26 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
27 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
107 public $totaldeposits;
108 public $totalcreditnotes;
111 public $sumpayed_multicurrency;
113 public $sumdeposit_multicurrency;
114 public $sumcreditnote;
115 public $sumcreditnote_multicurrency;
133 $remaintopay =
price2num($this->total_ttc - $alreadypaid,
'MT');
134 if ($this->statut == self::STATUS_CLOSED && $this->close_code ==
'discount_vat') {
149 $table =
'paiement_facture';
150 $field =
'fk_facture';
151 if ($this->element ==
'facture_fourn' || $this->element ==
'invoice_supplier') {
152 $table =
'paiementfourn_facturefourn';
153 $field =
'fk_facturefourn';
156 $sql =
"SELECT sum(amount) as amount, sum(multicurrency_amount) as multicurrency_amount";
157 $sql .=
" FROM ".$this->db->prefix().$table;
158 $sql .=
" WHERE ".$field.
" = ".((int) $this->
id);
160 dol_syslog(get_class($this).
"::getSommePaiement", LOG_DEBUG);
162 $resql = $this->db->query(
$sql);
164 $obj = $this->db->fetch_object($resql);
166 $this->db->free($resql);
169 if ($multicurrency < 0) {
170 $this->sumpayed = $obj->amount;
171 $this->sumpayed_multicurrency = $obj->multicurrency_amount;
172 return array(
'alreadypaid'=>(
float) $obj->amount,
'alreadypaid_multicurrency'=>(
float) $obj->multicurrency_amount);
173 } elseif ($multicurrency) {
174 $this->sumpayed_multicurrency = $obj->multicurrency_amount;
175 return (
float) $obj->multicurrency_amount;
177 $this->sumpayed = $obj->amount;
178 return (
float) $obj->amount;
184 $this->error = $this->db->lasterror();
204 require_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
207 $result = $discountstatic->getSumDepositsUsed($this, $multicurrency);
210 if ($multicurrency) {
211 $this->sumdeposit_multicurrency = $result;
213 $this->sumdeposit = $result;
218 $this->error = $discountstatic->error;
231 require_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
234 $result = $discountstatic->getSumCreditNotesUsed($this, $multicurrency);
236 if ($multicurrency) {
237 $this->sumcreditnote_multicurrency = $result;
239 $this->sumcreditnote = $result;
244 $this->error = $discountstatic->error;
257 require_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
260 $result = $discountstatic->getSumFromThisCreditNotesNotUsed($this, $multicurrency);
264 $this->error = $discountstatic->error;
278 $sql =
"SELECT rowid";
279 $sql .=
" FROM ".$this->db->prefix().$this->table_element;
280 $sql .=
" WHERE fk_facture_source = ".((int) $this->
id);
281 $sql .=
" AND type = 2";
282 $resql = $this->db->query(
$sql);
284 $num = $this->db->num_rows($resql);
287 $row = $this->db->fetch_row($resql);
288 $idarray[] = $row[0];
305 $sql =
"SELECT rowid";
306 $sql .=
" FROM ".$this->db->prefix().$this->table_element;
307 $sql .=
" WHERE fk_facture_source = ".((int) $this->
id);
308 $sql .=
" AND type < 2";
309 if ($option ==
'validated') {
310 $sql .=
' AND fk_statut = 1';
317 $sql .=
" ORDER BY fk_statut DESC";
319 $resql = $this->db->query(
$sql);
321 $obj = $this->db->fetch_object($resql);
344 $table =
'paiement_facture';
345 $table2 =
'paiement';
346 $field =
'fk_facture';
347 $field2 =
'fk_paiement';
348 $field3 =
', p.ref_ext';
349 $field4 =
', p.fk_bank';
350 $sharedentity =
'facture';
351 if ($this->element ==
'facture_fourn' || $this->element ==
'invoice_supplier') {
352 $table =
'paiementfourn_facturefourn';
353 $table2 =
'paiementfourn';
354 $field =
'fk_facturefourn';
355 $field2 =
'fk_paiementfourn';
357 $sharedentity =
'facture_fourn';
360 $sql =
"SELECT p.ref, pf.amount, pf.multicurrency_amount, p.fk_paiement, p.datep, p.num_paiement as num, t.code".$field3 . $field4;
361 $sql .=
" FROM ".$this->db->prefix().$table.
" as pf, ".$this->db->prefix().$table2.
" as p, ".$this->db->prefix().
"c_paiement as t";
362 $sql .=
" WHERE pf.".$field.
" = ".((int) $this->
id);
363 $sql .=
" AND pf.".$field2.
" = p.rowid";
364 $sql .=
' AND p.fk_paiement = t.id';
365 $sql .=
' AND p.entity IN ('.getEntity($sharedentity).
')';
367 $sql .=
" AND t.code='PRE'";
370 dol_syslog(get_class($this).
"::getListOfPayments", LOG_DEBUG);
371 $resql = $this->db->query(
$sql);
373 $num = $this->db->num_rows($resql);
376 $obj = $this->db->fetch_object($resql);
377 $tmp = array(
'amount'=>$obj->amount,
'type'=>$obj->code,
'date'=>$obj->datep,
'num'=>$obj->num,
'ref'=>$obj->ref);
378 if (!empty($field3)) {
379 $tmp[
'ref_ext'] = $obj->ref_ext;
381 if (!empty($field4)) {
382 $tmp[
'fk_bank_line'] = $obj->fk_bank;
387 $this->db->free($resql);
391 if ($this->element ==
'facture' || $this->element ==
'invoice') {
392 $sql =
"SELECT rc.amount_ttc as amount, rc.multicurrency_amount_ttc as multicurrency_amount, rc.datec as date, f.ref as ref, rc.description as type";
393 $sql .=
' FROM '.$this->db->prefix().
'societe_remise_except as rc, '.$this->db->prefix().
'facture as f';
394 $sql .=
' WHERE rc.fk_facture_source=f.rowid AND rc.fk_facture = '.((int) $this->
id);
395 $sql .=
' AND (f.type = 2 OR f.type = 0 OR f.type = 3)';
396 } elseif ($this->element ==
'facture_fourn' || $this->element ==
'invoice_supplier') {
397 $sql =
"SELECT rc.amount_ttc as amount, rc.multicurrency_amount_ttc as multicurrency_amount, rc.datec as date, f.ref as ref, rc.description as type";
398 $sql .=
' FROM '.$this->db->prefix().
'societe_remise_except as rc, '.$this->db->prefix().
'facture_fourn as f';
399 $sql .=
' WHERE rc.fk_invoice_supplier_source=f.rowid AND rc.fk_invoice_supplier = '.((int) $this->
id);
400 $sql .=
' AND (f.type = 2 OR f.type = 0 OR f.type = 3)';
404 $resql = $this->db->query(
$sql);
406 $num = $this->db->num_rows($resql);
409 $obj = $this->db->fetch_object($resql);
410 if ($multicurrency) {
411 $retarray[] = array(
'amount'=>$obj->multicurrency_amount,
'type'=>$obj->type,
'date'=>$obj->date,
'num'=>
'0',
'ref'=>$obj->ref);
413 $retarray[] = array(
'amount'=>$obj->amount,
'type'=>$obj->type,
'date'=>$obj->date,
'num'=>
'',
'ref'=>$obj->ref);
418 $this->error = $this->db->lasterror();
422 $this->db->free($resql);
427 $this->error = $this->db->lasterror();
454 $tmppart = substr($this->
ref, 1, 4);
456 if ($this->statut == self::STATUS_DRAFT && $tmppart ===
'PROV') {
460 if (!empty($conf->global->INVOICE_CAN_NEVER_BE_REMOVED)) {
465 if ($tmppart !==
'PROV') {
467 if ($ventilExportCompta != 0) {
472 if ($this->element !=
'invoice_supplier') {
473 if (empty($this->thirdparty)) {
476 $maxref = $this->getNextNumRef($this->thirdparty,
'last');
480 if (empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED) && $maxref !=
'' && $maxref != $this->ref) {
487 if ($this->situation_cycle_ref && method_exists($this,
'is_last_in_cycle')) {
488 $last = $this->is_last_in_cycle();
497 if (empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED) && $this->getSommePaiement() > 0) {
511 $alreadydispatched = 0;
513 $type =
'customer_invoice';
514 if ($this->element ==
'invoice_supplier') {
515 $type =
'supplier_invoice';
518 $sql =
" SELECT COUNT(ab.rowid) as nb FROM ".$this->db->prefix().
"accounting_bookkeeping as ab WHERE ab.doc_type='".$this->db->escape($type).
"' AND ab.fk_doc = ".((int) $this->
id);
519 $resql = $this->db->query(
$sql);
521 $obj = $this->db->fetch_object($resql);
523 $alreadydispatched = $obj->nb;
526 $this->error = $this->db->lasterror();
530 if ($alreadydispatched) {
547 $labellong =
"Unknown";
549 $labellong =
"InvoiceStandard";
550 $labelshort =
"InvoiceStandardShort";
552 $labellong =
"InvoiceReplacement";
553 $labelshort =
"InvoiceReplacementShort";
555 $labellong =
"InvoiceAvoir";
556 $labelshort =
"CreditNote";
558 $labellong =
"InvoiceDeposit";
559 $labelshort =
"Deposit";
561 $labellong =
"InvoiceProForma";
562 $labelshort =
"ProForma";
564 $labellong =
"InvoiceSituation";
565 $labelshort =
"Situation";
570 $out .=
'<span class="badgeneutral" title="'.dol_escape_htmltag($langs->trans($labellong)).
'">';
572 $out .= $langs->trans($withbadge == 2 ? $labelshort : $labellong);
588 return $this->
LibStatut($this->paye, $this->statut, $mode, $alreadypaid, $this->
type);
602 public function LibStatut($paye, $status, $mode = 0, $alreadypaid = -1, $type = -1)
605 global $langs, $hookmanager;
606 $langs->load(
'bills');
612 $statusType =
'status0';
616 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusDraft');
617 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusDraft');
618 } elseif (($status == 3 || $status == 2) && $alreadypaid <= 0) {
620 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusCanceled');
621 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusCanceled');
623 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusClosedUnpaid');
624 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusClosedUnpaid');
626 $statusType =
'status5';
627 } elseif (($status == 3 || $status == 2) && $alreadypaid > 0) {
628 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusClosedPaidPartially');
629 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusClosedPaidPartially');
630 $statusType =
'status9';
631 } elseif ($alreadypaid == 0) {
632 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusNotPaid');
633 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusNotPaid');
634 $statusType =
'status1';
636 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusStarted');
637 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusStarted');
638 $statusType =
'status3';
641 $statusType =
'status6';
643 if ($type == self::TYPE_CREDIT_NOTE) {
644 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusPaidBackOrConverted');
645 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusPaidBackOrConverted');
646 } elseif ($type == self::TYPE_DEPOSIT) {
647 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusConverted');
648 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusConverted');
650 $labelStatus = $langs->transnoentitiesnoconv(
'BillStatusPaid');
651 $labelStatusShort = $langs->transnoentitiesnoconv(
'Bill'.$prefix.
'StatusPaid');
659 'alreadypaid' => $alreadypaid,
663 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
666 return $hookmanager->resPrint;
671 return dolGetStatus($labelStatus, $labelStatusShort,
'', $statusType, $mode);
685 if (!$cond_reglement) {
686 $cond_reglement = $this->cond_reglement_code;
688 if (!$cond_reglement) {
689 $cond_reglement = $this->cond_reglement_id;
691 if (!$cond_reglement) {
699 $sqltemp =
"SELECT c.type_cdr, c.nbjour, c.decalage";
700 $sqltemp .=
" FROM ".$this->db->prefix().
"c_payment_term as c";
701 if (is_numeric($cond_reglement)) {
702 $sqltemp .=
" WHERE c.rowid=".((int) $cond_reglement);
704 $sqltemp .=
" WHERE c.entity IN (".getEntity(
'c_payment_term').
")";
705 $sqltemp .=
" AND c.code = '".$this->db->escape($cond_reglement).
"'";
708 dol_syslog(get_class($this).
'::calculate_date_lim_reglement', LOG_DEBUG);
709 $resqltemp = $this->db->query($sqltemp);
711 if ($this->db->num_rows($resqltemp)) {
712 $obj = $this->db->fetch_object($resqltemp);
713 $cdr_nbjour = $obj->nbjour;
714 $cdr_type = $obj->type_cdr;
715 $cdr_decalage = $obj->decalage;
718 $this->error = $this->db->error();
721 $this->db->free($resqltemp);
726 if ($cdr_type == 0) {
727 $datelim = $this->date + ($cdr_nbjour * 3600 * 24);
729 $datelim += ($cdr_decalage * 3600 * 24);
730 } elseif ($cdr_type == 1) {
732 $datelim = $this->date + ($cdr_nbjour * 3600 * 24);
734 $mois = date(
'm', $datelim);
735 $annee = date(
'Y', $datelim);
743 $datelim =
dol_mktime(12, 0, 0, $mois, 1, $annee);
744 $datelim -= (3600 * 24);
746 $datelim += ($cdr_decalage * 3600 * 24);
747 } elseif ($cdr_type == 2 && !empty($cdr_decalage)) {
749 include_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
750 $datelim = $this->date + ($cdr_nbjour * 3600 * 24);
752 $date_piece =
dol_mktime(0, 0, 0, date(
'm', $datelim), date(
'd', $datelim), date(
'Y', $datelim));
753 $date_lim_current =
dol_mktime(0, 0, 0, date(
'm', $datelim), $cdr_decalage, date(
'Y', $datelim));
756 $diff = $date_piece - $date_lim_current;
759 $datelim = $date_lim_current;
761 $datelim = $date_lim_next;
764 return 'Bad value for type_cdr in database for record cond_reglement = '.$cond_reglement;
782 public function demande_prelevement($fuser, $amount = 0, $type =
'direct-debit', $sourcetype =
'facture', $checkduplicateamongall = 0)
789 dol_syslog(get_class($this).
"::demande_prelevement", LOG_DEBUG);
791 if ($this->statut > self::STATUS_DRAFT && $this->paye == 0) {
792 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companybankaccount.class.php';
794 $bac->fetch(0, $this->socid);
796 $sql =
"SELECT count(rowid) as nb";
797 $sql .=
" FROM ".$this->db->prefix().
"prelevement_demande";
798 if ($type ==
'bank-transfer') {
799 $sql .=
" WHERE fk_facture_fourn = ".((int) $this->
id);
801 $sql .=
" WHERE fk_facture = ".((int) $this->
id);
803 $sql .=
" AND type = 'ban'";
804 if (empty($checkduplicateamongall)) {
805 $sql .=
" AND traite = 0";
808 dol_syslog(get_class($this).
"::demande_prelevement", LOG_DEBUG);
810 $resql = $this->db->query(
$sql);
812 $obj = $this->db->fetch_object($resql);
813 if ($obj && $obj->nb == 0) {
825 if (empty($amount)) {
826 $amount =
price2num($this->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits,
'MT');
829 if (is_numeric($amount) && $amount != 0) {
830 $sql =
'INSERT INTO '.$this->db->prefix().
'prelevement_demande(';
831 if ($type ==
'bank-transfer') {
832 $sql .=
'fk_facture_fourn, ';
834 $sql .=
'fk_facture, ';
836 $sql .=
' amount, date_demande, fk_user_demande, code_banque, code_guichet, number, cle_rib, sourcetype, type, entity)';
837 $sql .=
" VALUES (".((int) $this->
id);
839 $sql .=
", '".$this->db->idate($now).
"'";
840 $sql .=
", ".((int) $fuser->id);
841 $sql .=
", '".$this->db->escape($bac->code_banque).
"'";
842 $sql .=
", '".$this->db->escape($bac->code_guichet).
"'";
843 $sql .=
", '".$this->db->escape($bac->number).
"'";
844 $sql .=
", '".$this->db->escape($bac->cle_rib).
"'";
845 $sql .=
", '".$this->db->escape($sourcetype).
"'";
847 $sql .=
", ".((int) $conf->entity);
850 dol_syslog(get_class($this).
"::demande_prelevement", LOG_DEBUG);
851 $resql = $this->db->query(
$sql);
853 $this->error = $this->db->lasterror();
854 dol_syslog(get_class($this).
'::demandeprelevement Erreur');
858 $this->error =
'WithdrawRequestErrorNilAmount';
859 dol_syslog(get_class($this).
'::demandeprelevement WithdrawRequestErrorNilAmount');
865 $payment_mode_id =
dol_getIdFromCode($this->db, ($type ==
'bank-transfer' ?
'VIR' :
'PRE'),
'c_paiement',
'code',
'id', 1);
866 if ($payment_mode_id > 0) {
876 $this->error =
"A request already exists";
877 dol_syslog(get_class($this).
'::demandeprelevement Impossible de creer une demande, demande deja en cours');
881 $this->error = $this->db->error();
882 dol_syslog(get_class($this).
'::demandeprelevement Erreur -2');
886 $this->error =
"Status of invoice does not allow this";
887 dol_syslog(get_class($this).
"::demandeprelevement ".$this->error.
" $this->statut, $this->paye, $this->mode_reglement_id");
904 global $conf, $mysoc, $user, $langs;
906 if ($type !=
'bank-transfer' && $type !=
'credit-transfer' && empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) {
909 if ($type !=
'direct-debit' && empty($conf->global->STRIPE_SEPA_CREDIT_TRANSFER)) {
915 dol_syslog(get_class($this).
"::makeStripeSepaRequest start", LOG_DEBUG);
917 if ($this->statut > self::STATUS_DRAFT && $this->paye == 0) {
919 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companybankaccount.class.php';
921 $result = $bac->fetch(0, $this->socid, 1,
'ban');
922 if ($result <= 0 || empty($bac->id)) {
923 $this->error = $langs->trans(
"ThirdpartyHasNoDefaultBanAccount");
924 $this->errors[] = $this->error;
925 dol_syslog(get_class($this).
"::makeStripeSepaRequest ".$this->error);
930 $sql =
"SELECT rowid, date_demande, amount, fk_facture, fk_facture_fourn, fk_prelevement_bons";
931 $sql .=
" FROM ".$this->db->prefix().
"prelevement_demande";
932 $sql .=
" WHERE rowid = ".((int) $did);
933 if ($type !=
'bank-transfer' && $type !=
'credit-transfer') {
934 $sql .=
" AND fk_facture = ".((int) $this->
id);
936 if ($type !=
'direct-debit') {
937 $sql .=
" AND fk_facture_fourn = ".((int) $this->
id);
939 $sql .=
" AND traite = 0";
941 dol_syslog(get_class($this).
"::makeStripeSepaRequest load requests to process", LOG_DEBUG);
942 $resql = $this->db->query(
$sql);
944 $obj = $this->db->fetch_object($resql);
951 $amount = $obj->amount;
953 if (is_numeric($amount) && $amount != 0) {
954 require_once DOL_DOCUMENT_ROOT.
'/societe/class/companypaymentmode.class.php';
956 $companypaymentmode->fetch($bac->id);
960 $service =
'StripeTest';
962 if (!empty($conf->global->STRIPE_LIVE) && !
GETPOST(
'forcesandbox',
'alpha')) {
963 $service =
'StripeLive';
967 dol_syslog(
"makeStripeSepaRequest amount = ".$amount.
" service=" . $service .
" servicestatus=" . $servicestatus .
" thirdparty_id=" . $this->socid.
" did=".$did);
969 $this->stripechargedone = 0;
970 $this->stripechargeerror = 0;
974 $currency = $conf->currency;
976 global $stripearrayofkeysbyenv;
978 $errorforinvoice = 0;
982 dol_syslog(
"--- Process payment request thirdparty_id=" . $this->thirdparty->id .
", thirdparty_name=" . $this->thirdparty->name .
" ban id=" . $bac->id, LOG_DEBUG);
987 $amounttopay = $amount;
991 $arrayzerounitcurrency = [
'BIF',
'CLP',
'DJF',
'GNF',
'JPY',
'KMF',
'KRW',
'MGA',
'PYG',
'RWF',
'VND',
'VUV',
'XAF',
'XOF',
'XPF'];
992 $amountstripe = $amounttopay;
993 if (!in_array($currency, $arrayzerounitcurrency)) {
994 $amountstripe = $amountstripe * 100;
997 $fk_bank_account =
getDolGlobalInt(
'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS');
998 if (!($fk_bank_account > 0)) {
1001 dol_syslog(
"Error no bank account defined for Stripe payments", LOG_ERR);
1002 $this->errors[] =
"Error bank account for Stripe payments not defined into Stripe module";
1008 require_once DOL_DOCUMENT_ROOT.
'/compta/prelevement/class/bonprelevement.class.php';
1011 if (empty($obj->fk_prelevement_bons)) {
1013 $nbinvoices = $bon->create(0, 0,
'real',
'ALL',
'', 0, $type, $did, $fk_bank_account);
1014 if ($nbinvoices <= 0) {
1017 dol_syslog(
"Error on BonPrelevement creation", LOG_ERR);
1018 $this->errors[] =
"Error on BonPrelevement creation";
1037 dol_syslog(
"Error Line already part of a bank payment order", LOG_ERR);
1038 $this->errors[] =
"The line is already included into a bank payment order. Delete the bank payment order first.";
1043 if ($amountstripe > 0) {
1046 dol_syslog(
"We will try to pay with companypaymentmodeid=" . $companypaymentmode->id .
" stripe_card_ref=" . $companypaymentmode->stripe_card_ref .
" mode=" . $companypaymentmode->status, LOG_DEBUG);
1048 $thirdparty =
new Societe($this->db);
1049 $resultthirdparty = $thirdparty->fetch($this->socid);
1051 include_once DOL_DOCUMENT_ROOT .
'/stripe/class/stripe.class.php';
1053 $stripe =
new Stripe($this->db);
1055 dol_syslog(
"makeStripeSepaRequest Current Stripe environment is " . $stripearrayofkeysbyenv[$servicestatus][
'publishable_key']);
1057 $stripearrayofkeys = $stripearrayofkeysbyenv[$servicestatus];
1058 \Stripe\Stripe::setApiKey($stripearrayofkeys[
'secret_key']);
1061 dol_syslog(
"makeStripeSepaRequest get stripe connet account", LOG_DEBUG);
1062 $stripeacc = $stripe->getStripeAccount($service, $this->socid);
1063 dol_syslog(
"makeStripeSepaRequest get stripe connect account return " . json_encode($stripeacc), LOG_DEBUG);
1065 $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 0);
1066 if (empty($customer) && !empty($stripe->error)) {
1067 $this->errors[] = $stripe->error;
1072 $postactionmessages = [];
1074 if ($resultthirdparty > 0 && !empty($customer)) {
1077 if ($companypaymentmode->type ==
'ban') {
1081 $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0);
1084 $this->error =
'The payment mode type is not "ban"';
1088 $FULLTAG =
'DID='.$did.
'-INV=' . $this->
id .
'-CUS=' . $thirdparty->id;
1089 $description =
'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG .
' did='.$did.
' ref=' . $this->ref;
1091 $stripefailurecode =
'';
1092 $stripefailuremessage =
'';
1093 $stripefailuredeclinecode =
'';
1096 dol_syslog(
"* Create payment on SEPA " . $stripecard->id .
", amounttopay=" . $amounttopay .
", amountstripe=" . $amountstripe .
", FULLTAG=" . $FULLTAG, LOG_DEBUG);
1099 $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $this, $customer->id, $stripeacc, $servicestatus, 0,
'automatic',
true, $stripecard->id, 1, 1, $did);
1101 $charge =
new stdClass();
1103 if ($paymentintent->status ===
'succeeded' || $paymentintent->status ===
'processing') {
1104 $charge->status =
'ok';
1105 $charge->id = $paymentintent->id;
1106 $charge->customer = $customer->id;
1107 } elseif ($paymentintent->status ===
'requires_action') {
1109 dol_syslog(var_export($paymentintent,
true), LOG_DEBUG);
1111 $charge->status =
'failed';
1112 $charge->customer = $customer->id;
1113 $charge->failure_code = $stripe->code;
1114 $charge->failure_message = $stripe->error;
1115 $charge->failure_declinecode = $stripe->declinecode;
1116 $stripefailurecode = $stripe->code;
1117 $stripefailuremessage =
'Action required. Contact the support at ';
1118 $stripefailuredeclinecode = $stripe->declinecode;
1120 dol_syslog(var_export($paymentintent,
true), LOG_DEBUG);
1122 $charge->status =
'failed';
1123 $charge->customer = $customer->id;
1124 $charge->failure_code = $stripe->code;
1125 $charge->failure_message = $stripe->error;
1126 $charge->failure_declinecode = $stripe->declinecode;
1127 $stripefailurecode = $stripe->code;
1128 $stripefailuremessage = $stripe->error;
1129 $stripefailuredeclinecode = $stripe->declinecode;
1137 if (empty($charge) || $charge->status ==
'failed') {
1138 dol_syslog(
'Failed to charge payment mode ' . $stripecard->id .
' stripefailurecode=' . $stripefailurecode .
' stripefailuremessage=' . $stripefailuremessage .
' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING);
1141 $this->stripechargeerror++;
1145 $errmsg = $langs->trans(
"FailedToChargeCard");
1146 if (!empty($charge)) {
1147 if ($stripefailuredeclinecode ==
'authentication_required') {
1148 $errauthenticationmessage = $langs->trans(
"ErrSCAAuthentication");
1149 $errmsg = $errauthenticationmessage;
1150 } elseif (in_array($stripefailuredeclinecode, [
'insufficient_funds',
'generic_decline'])) {
1151 $errmsg .=
': ' . $charge->failure_code;
1152 $errmsg .= ($charge->failure_message ?
' - ' :
'') .
' ' . $charge->failure_message;
1153 if (empty($stripefailurecode)) {
1154 $stripefailurecode = $charge->failure_code;
1156 if (empty($stripefailuremessage)) {
1157 $stripefailuremessage = $charge->failure_message;
1160 $errmsg .=
': failure_code=' . $charge->failure_code;
1161 $errmsg .= ($charge->failure_message ?
' - ' :
'') .
' failure_message=' . $charge->failure_message;
1162 if (empty($stripefailurecode)) {
1163 $stripefailurecode = $charge->failure_code;
1165 if (empty($stripefailuremessage)) {
1166 $stripefailuremessage = $charge->failure_message;
1170 $errmsg .=
': ' . $stripefailurecode .
' - ' . $stripefailuremessage;
1171 $errmsg .= ($stripefailuredeclinecode ?
' - ' . $stripefailuredeclinecode :
'');
1174 $description =
'Stripe payment ERROR from makeStripeSepaRequest: ' . $FULLTAG;
1175 $postactionmessages[] = $errmsg .
' (' . $stripearrayofkeys[
'publishable_key'] .
')';
1176 $this->errors[] = $errmsg;
1178 dol_syslog(
'Successfuly request '.$type.
' '.$stripecard->id);
1180 $postactionmessages[] =
'Success to request '.$type.
' (' . $charge->id .
' with ' . $stripearrayofkeys[
'publishable_key'] .
')';
1184 $this->stripechargedone++;
1187 $description =
'Stripe payment request OK (' . $charge->id .
') from makeStripeSepaRequest: ' . $FULLTAG;
1193 if (empty($charge) || $charge->status ==
'failed') {
1194 $actioncode =
'PAYMENT_STRIPE_KO';
1195 $extraparams = $stripefailurecode;
1196 $extraparams .= (($extraparams && $stripefailuremessage) ?
' - ' :
'') . $stripefailuremessage;
1197 $extraparams .= (($extraparams && $stripefailuredeclinecode) ?
' - ' :
'') . $stripefailuredeclinecode;
1199 $actioncode =
'PAYMENT_STRIPE_OK';
1205 dol_syslog(
"No ban payment method found for this stripe customer " . $customer->id, LOG_WARNING);
1206 $this->errors[] =
'Failed to get direct debit payment method for stripe customer = ' . $customer->id;
1208 $description =
'Failed to find or use the payment mode - no ban defined for the thirdparty account';
1209 $stripefailurecode =
'BADPAYMENTMODE';
1210 $stripefailuremessage =
'Failed to find or use the payment mode - no ban defined for the thirdparty account';
1211 $postactionmessages[] = $description .
' (' . $stripearrayofkeys[
'publishable_key'] .
')';
1215 $actioncode =
'PAYMENT_STRIPE_KO';
1221 $stripefailurecode =
'';
1222 $stripefailuremessage =
'';
1230 if ($resultthirdparty <= 0) {
1231 dol_syslog(
'SellYourSaasUtils Failed to load customer for thirdparty_id = ' . $thirdparty->id, LOG_WARNING);
1232 $this->errors[] =
'Failed to load Stripe account for thirdparty_id = ' . $thirdparty->id;
1234 dol_syslog(
'SellYourSaasUtils Failed to get Stripe customer id for thirdparty_id = ' . $thirdparty->id .
" in mode " . $servicestatus .
" in Stripe env " . $stripearrayofkeysbyenv[$servicestatus][
'publishable_key'], LOG_WARNING);
1235 $this->errors[] =
'Failed to get Stripe account id for thirdparty_id = ' . $thirdparty->id .
" in mode " . $servicestatus .
" in Stripe env " . $stripearrayofkeysbyenv[$servicestatus][
'publishable_key'];
1240 $description =
'Failed to find or use your payment mode (no payment mode for this customer id)';
1241 $stripefailurecode =
'BADPAYMENTMODE';
1242 $stripefailuremessage =
'Failed to find or use your payment mode (no payment mode for this customer id)';
1243 $postactionmessages = [];
1247 $actioncode =
'PAYMENT_STRIPE_KO';
1252 dol_syslog(
"* Record event for credit transfer or direct debit request result - " . $description);
1253 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
1258 $actioncomm->type_code =
'AC_OTH_AUTO';
1259 $actioncomm->code =
'AC_' . $actioncode;
1260 $actioncomm->label = $description;
1261 $actioncomm->note_private = join(
",\n", $postactionmessages);
1262 $actioncomm->fk_project = $this->fk_project;
1263 $actioncomm->datep = $now;
1264 $actioncomm->datef = $now;
1265 $actioncomm->percentage = -1;
1266 $actioncomm->socid = $thirdparty->id;
1267 $actioncomm->contactid = 0;
1268 $actioncomm->authorid = $user->id;
1269 $actioncomm->userownerid = $user->id;
1279 $actioncomm->fk_element = $this->id;
1280 $actioncomm->elementtype = $this->element;
1281 $actioncomm->extraparams =
dol_trunc($extraparams, 250);
1283 $actioncomm->create($user);
1287 $this->postactionmessages = $postactionmessages;
1291 dol_syslog(
'Error ' . $e->getMessage(), LOG_ERR);
1292 $this->errors[] =
'Error ' . $e->getMessage();
1297 dol_syslog(
"Remain to pay is null for the invoice " . $this->
id .
" " . $this->
ref .
". Why is the invoice not classified 'Paid' ?", LOG_WARNING);
1298 $this->errors[] =
"Remain to pay is null for the invoice " . $this->
id .
" " . $this->ref .
". Why is the invoice not classified 'Paid' ?";
1303 if (!$error && !$errorforinvoice) {
1304 $result = $bon->set_infotrans($user, $now, 3);
1308 dol_syslog(
"Error on BonPrelevement creation", LOG_ERR);
1309 $this->errors[] =
"Error on BonPrelevement creation";
1313 if (!$error && !$errorforinvoice) {
1315 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"prelevement_demande SET";
1316 $sql .=
" ext_payment_id = '".$this->db->escape($paymentintent->id).
"',";
1317 $sql .=
" ext_payment_site = '".$this->db->escape($service).
"'";
1318 $sql .=
" WHERE rowid = ".((int) $did);
1320 dol_syslog(get_class($this).
"::makeStripeSepaRequest update to save stripe paymentintent ids", LOG_DEBUG);
1321 $resql = $this->db->query(
$sql);
1323 $this->error = $this->db->lasterror();
1324 dol_syslog(get_class($this).
'::makeStripeSepaRequest Erreur');
1329 if (!$error && !$errorforinvoice) {
1330 $this->db->commit();
1332 $this->db->rollback();
1335 $this->error =
'WithdrawRequestErrorNilAmount';
1336 dol_syslog(get_class($this).
'::makeStripeSepaRequest WithdrawRequestErrorNilAmount');
1354 $this->error = $this->db->error();
1355 dol_syslog(get_class($this).
'::makeStripeSepaRequest Erreur -2');
1359 $this->error =
"Status of invoice does not allow this";
1360 dol_syslog(get_class($this).
"::makeStripeSepaRequest ".$this->error.
" $this->statut, $this->paye, $this->mode_reglement_id");
1376 $sql =
'DELETE FROM '.$this->db->prefix().
'prelevement_demande';
1377 $sql .=
' WHERE rowid = '.((int) $did);
1378 $sql .=
' AND traite = 0';
1379 if ($this->db->query(
$sql)) {
1382 $this->error = $this->db->lasterror();
1383 dol_syslog(get_class($this).
'::demande_prelevement_delete Error '.$this->error);
1396 global $conf, $mysoc;
1399 $tmplang->setDefaultLang(
'en_US');
1400 $tmplang->load(
"main");
1405 $pricewithtaxstring =
price2num($this->total_ttc, 2, 1);
1406 $pricetaxstring =
price2num($this->total_tva, 2, 1);
1433 $s = pack(
'C1', 1).pack(
'C1', strlen($mysoc->name)).$mysoc->name;
1434 $s .= pack(
'C1', 2).pack(
'C1', strlen($mysoc->tva_intra)).$mysoc->tva_intra;
1435 $s .= pack(
'C1', 3).pack(
'C1', strlen($datestring)).$datestring;
1436 $s .= pack(
'C1', 4).pack(
'C1', strlen($pricewithtaxstring)).$pricewithtaxstring;
1437 $s .= pack(
'C1', 5).pack(
'C1', strlen($pricetaxstring)).$pricetaxstring;
1443 $s = base64_encode($s);
1456 global $conf, $mysoc;
1459 $tmplang->setDefaultLang(
'en_US');
1460 $tmplang->load(
"main");
1462 $pricewithtaxstring =
price2num($this->total_ttc, 2, 1);
1463 $pricetaxstring =
price2num($this->total_tva, 2, 1);
1465 $complementaryinfo =
'';
1479 $complementaryinfo =
'//S1/10/'.str_replace(
'/',
'', $this->
ref).
'/11/'.$datestring;
1480 if ($this->ref_client) {
1481 $complementaryinfo .=
'/20/'.$this->ref_client;
1483 if ($this->thirdparty->tva_intra) {
1484 $complementaryinfo .=
'/30/'.$this->thirdparty->tva_intra;
1487 include_once DOL_DOCUMENT_ROOT.
'/compta/bank/class/account.class.php';
1488 $bankaccount =
new Account($this->db);
1496 if ($this->fk_account > 0) {
1498 $bankaccount->fetch($this->fk_account);
1499 $s .= $bankaccount->iban.
"\n";
1503 if ($bankaccount->id > 0 &&
getDolGlobalString(
'PDF_SWISS_QRCODE_USE_OWNER_OF_ACCOUNT_AS_CREDITOR')) {
1507 $s .=
dol_trunc($bankaccount->proprio, 70,
'right',
'UTF-8', 1).
"\n";
1508 $addresslinearray = explode(
"\n", $bankaccount->owner_address);
1509 $s .=
dol_trunc(empty($addresslinearray[1]) ?
'' : $addresslinearray[1], 70,
'right',
'UTF-8', 1).
"\n";
1510 $s .=
dol_trunc(empty($addresslinearray[2]) ?
'' : $addresslinearray[2], 70,
'right',
'UTF-8', 1).
"\n";
1516 $s .=
dol_trunc($mysoc->name, 70,
'right',
'UTF-8', 1).
"\n";
1517 $addresslinearray = explode(
"\n", $mysoc->address);
1518 $s .=
dol_trunc(empty($addresslinearray[1]) ?
'' : $addresslinearray[1], 70,
'right',
'UTF-8', 1).
"\n";
1519 $s .=
dol_trunc(empty($addresslinearray[2]) ?
'' : $addresslinearray[2], 70,
'right',
'UTF-8', 1).
"\n";
1520 $s .=
dol_trunc($mysoc->zip, 16,
'right',
'UTF-8', 1).
"\n";
1521 $s .=
dol_trunc($mysoc->town, 35,
'right',
'UTF-8', 1).
"\n";
1522 $s .=
dol_trunc($mysoc->country_code, 2,
'right',
'UTF-8', 1).
"\n";
1533 $s .=
price($pricewithtaxstring, 0,
'none', 0, 0, 2).
"\n";
1534 $s .= ($this->multicurrency_code ? $this->multicurrency_code : $conf->currency).
"\n";
1537 $s .=
dol_trunc($this->thirdparty->name, 70,
'right',
'UTF-8', 1).
"\n";
1538 $addresslinearray = explode(
"\n", $this->thirdparty->address);
1539 $s .=
dol_trunc(empty($addresslinearray[1]) ?
'' : $addresslinearray[1], 70,
'right',
'UTF-8', 1).
"\n";
1540 $s .=
dol_trunc(empty($addresslinearray[2]) ?
'' : $addresslinearray[2], 70,
'right',
'UTF-8', 1).
"\n";
1541 $s .=
dol_trunc($this->thirdparty->zip, 16,
'right',
'UTF-8', 1).
"\n";
1542 $s .=
dol_trunc($this->thirdparty->town, 35,
'right',
'UTF-8', 1).
"\n";
1543 $s .=
dol_trunc($this->thirdparty->country_code, 2,
'right',
'UTF-8', 1).
"\n";
1548 if ($complementaryinfo) {
1549 $s .= $complementaryinfo.
"\n";
1555 if ($complementaryinfo) {
1556 $s .= $complementaryinfo.
"\n";
1566 require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobjectline.class.php';
1594 public $product_type = 0;
1600 public $product_ref;
1606 public $product_label;
1612 public $product_desc;
1643 public $vat_src_code;
1655 public $localtax1_tx;
1661 public $localtax2_tx;
1667 public $localtax1_type;
1673 public $localtax2_type;
1679 public $remise_percent;
1704 public $total_localtax1;
1710 public $total_localtax2;
1718 public $date_start_fill;
1719 public $date_end_fill;
1721 public $buy_price_ht;
1734 public $info_bits = 0;
1736 public $special_code = 0;
1738 public $fk_multicurrency;
1739 public $multicurrency_code;
1740 public $multicurrency_subprice;
1741 public $multicurrency_total_ht;
1742 public $multicurrency_total_tva;
1743 public $multicurrency_total_ttc;
1745 public $fk_user_author;
1746 public $fk_user_modif;
1748 public $fk_accounting_account;
Class to manage bank accounts.
Class to manage agenda events (actions)
Class to manage withdrawal receipts.
Superclass for invoices classes.
const TYPE_CREDIT_NOTE
Credit note invoice.
const STATUS_CLOSED
Classified paid.
getSumCreditNotesUsed($multicurrency=0)
Return amount (with tax) of all credit notes invoices + excess received used by invoice.
getRemainToPay($multicurrency=0)
Return remain amount to pay.
makeStripeSepaRequest($fuser, $did=0, $type='direct-debit', $sourcetype='facture')
Create a payment order into prelevement_demande then send the payment order to Stripe (for a direct d...
buildZATCAQRString()
Build string for ZATCA QR Code (Arabi Saudia)
const TYPE_STANDARD
Standard invoice.
demande_prelevement($fuser, $amount=0, $type='direct-debit', $sourcetype='facture', $checkduplicateamongall=0)
Create a withdrawal request for a direct debit order or a credit transfer order.
demande_prelevement_delete($fuser, $did)
Remove a direct debit request or a credit transfer request.
getVentilExportCompta()
Return if an invoice was dispatched into bookkeeping.
const TYPE_PROFORMA
Proforma invoice.
buildSwitzerlandQRString()
Build string for QR-Bill (Switzerland)
const STATUS_VALIDATED
Validated (need to be paid)
const TYPE_SITUATION
Situation invoice.
getSumDepositsUsed($multicurrency=0)
Return amount (with tax) of all deposits invoices used by invoice.
getSommePaiement($multicurrency=0)
Return amount of payments already done.
const TYPE_DEPOSIT
Deposit invoice.
LibStatut($paye, $status, $mode=0, $alreadypaid=-1, $type=-1)
Return label of a status.
const STATUS_ABANDONED
Classified abandoned and no payment done.
calculate_date_lim_reglement($cond_reglement=0)
Returns an invoice payment deadline based on the invoice settlement conditions and billing date.
const TYPE_REPLACEMENT
Replacement invoice.
getSumFromThisCreditNotesNotUsed($multicurrency=0)
Return amount (with tax) of all converted amount for this credit note.
getListIdAvoirFromInvoice()
Returns array of credit note ids from the invoice.
const STATUS_DRAFT
Draft status.
getIdReplacingInvoice($option='')
Returns the id of the invoice that replaces it.
getLibType($withbadge=0)
Return label of type of invoice.
is_erasable()
Return if an invoice can be deleted Rule is: If invoice is draft and has a temporary ref -> yes (1) I...
getListOfPayments($filtertype='')
Return list of payments.
getLibStatut($mode=0, $alreadypaid=-1)
Return label of object status.
Parent class of all other business classes for details of elements (invoices, contracts,...
$label
Custom label of line.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
setPaymentMethods($id)
Change the payments methods.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage bank accounts description of third parties.
Class for CompanyPaymentMode.
Class to manage absolute discounts.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
trait CommonIncoterm
Superclass for incoterm classes.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
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...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type