From eb52f5daa0767387fd48d99e29949e57c0bc456d Mon Sep 17 00:00:00 2001 From: Indelog Date: Thu, 22 Apr 2021 14:48:05 +0200 Subject: [PATCH] Add : register donation payment when public payment - When we paid a donation whit public link, create the associated payment and put its status to payed if all the promised amount is it. - Set the amount to pay on public page depending to the rest to pay for the don. --- htdocs/don/class/don.class.php | 30 +++++ htdocs/don/class/paymentdonation.class.php | 25 +++- .../install/mysql/migration/13.0.0-14.0.0.sql | 4 + .../mysql/tables/llx_payment_donation.sql | 10 +- htdocs/public/payment/newpayment.php | 3 +- htdocs/public/payment/paymentok.php | 113 ++++++++++++++++++ 6 files changed, 177 insertions(+), 8 deletions(-) diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index 1ec3ebe1cc5..799ad1376cf 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -7,6 +7,7 @@ * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2019 Thibault FOUCART * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2021 Maxime DEMAREST * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1098,4 +1099,33 @@ class Don extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Function to get reamain to pay for a donation + * + * @return int <0 if KO, > reamain to pay if OK + */ + public function getRemainToPay() + { + dol_syslog(__METHOD__, LOG_DEBUG); + + if (empty($this->id)) + { + $this->error = 'Missing object id'; + $this->errors[] = $this->error; + dol_syslog(__METHOD__.' : '.$this->error, LOG_ERR); + return -1; + } + + $sql = 'SELECT SUM(amount) as sum_amount FROM '.MAIN_DB_PREFIX.'payment_donation WHERE fk_donation = '.$this->id; + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + return -2; + } else { + $sum_amount = (float) $this->db->fetch_object($resql)->sum_amount; + return (float) $this->amount - $sum_amount; + } + + } } diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php index 7c8bd71ccd2..6a39850e2db 100644 --- a/htdocs/don/class/paymentdonation.class.php +++ b/htdocs/don/class/paymentdonation.class.php @@ -92,6 +92,15 @@ class PaymentDonation extends CommonObject public $type_code; public $type_label; + /** + * @var string Id of external payment mode + */ + public $ext_payment_id; + + /** + * @var string Name of external payment mode + */ + public $ext_payment_site; /** * Constructor @@ -126,6 +135,14 @@ class PaymentDonation extends CommonObject } // Clean parameters + if (isset($this->chid)) { + $this->chid = (int) $this->chid; + } + // NOTE : The property used in INSERT for fk_donation is not fk_donation but chid + // (keep priority to chid property) + elseif (isset($this->fk_donation)) { + $this->chid = (int) $this->fk_donation; + } if (isset($this->fk_donation)) { $this->fk_donation = (int) $this->fk_donation; } @@ -169,12 +186,14 @@ class PaymentDonation extends CommonObject if ($totalamount != 0) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_donation (fk_donation, datec, datep, amount,"; - $sql .= " fk_typepayment, num_payment, note, fk_user_creat, fk_bank)"; + $sql .= " fk_typepayment, num_payment, note, ext_payment_id, ext_payment_site,"; + $sql .= " fk_user_creat, fk_bank)"; $sql .= " VALUES ($this->chid, '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datepaid)."',"; $sql .= " ".$totalamount.","; - $sql .= " ".$this->paymenttype.", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_public)."', ".$user->id.","; - $sql .= " 0)"; + $sql .= " ".$this->paymenttype.", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_public)."', "; + $sql .= " ".($this->ext_payment_id ? "'".$this->db->escape($this->ext_payment_id)."'" : "null").", ".($this->ext_payment_site ? "'".$this->db->escape($this->ext_payment_site)."'" : "null").","; + $sql .= " ".$user->id.", 0)"; dol_syslog(get_class($this)."::create", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index e762ddd94e4..10a38ee44bf 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -431,6 +431,10 @@ ALTER TABLE llx_facture_fourn ADD COLUMN fk_user_closing integer DEFAULT NULL af ALTER TABLE llx_entrepot ADD COLUMN fk_project INTEGER DEFAULT NULL AFTER entity; -- project associated to warehouse if any +-- Add external payement suport for donation +ALTER TABLE llx_payment_donation ADD COLUMN ext_payment_site varchar(128) AFTER note; +ALTER TABLE llx_payment_donation ADD COLUMN ext_payment_id varchar(128) AFTER note; + -- Rebuild sequence for postgres only after query INSERT INTO llx_salary(rowid, ... -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); diff --git a/htdocs/install/mysql/tables/llx_payment_donation.sql b/htdocs/install/mysql/tables/llx_payment_donation.sql index 088138bf96f..a93a6c1a0e9 100644 --- a/htdocs/install/mysql/tables/llx_payment_donation.sql +++ b/htdocs/install/mysql/tables/llx_payment_donation.sql @@ -20,14 +20,16 @@ create table llx_payment_donation ( rowid integer AUTO_INCREMENT PRIMARY KEY, fk_donation integer, - datec datetime, -- date de creation + datec datetime, -- date de creation tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - datep datetime, -- payment date + datep datetime, -- payment date amount double(24,8) DEFAULT 0, fk_typepayment integer NOT NULL, num_payment varchar(50), note text, + ext_payment_id varchar(128), -- external id of payment (for example Stripe charge id) + ext_payment_site varchar(128), -- name of external paymentmode (for example 'stripe') fk_bank integer NOT NULL, - fk_user_creat integer, -- creation user - fk_user_modif integer -- last modification user + fk_user_creat integer, -- creation user + fk_user_modif integer -- last modification user )ENGINE=innodb; diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 40c742d562a..684c559dac3 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1587,9 +1587,10 @@ if ($source == 'donation') { $object = $don; if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment - $amount = $subscription->total_ttc; if (GETPOST("amount", 'alpha')) { $amount = GETPOST("amount", 'alpha'); + } else { + $amount = $don->getRemainToPay(); } $amount = price2num($amount); } diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 1942635001f..902bfa29321 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -3,6 +3,7 @@ * Copyright (C) 2006-2013 Laurent Destailleur * Copyright (C) 2012 Regis Houssin * Copyright (C) 2021 Waël Almoman + * Copyright (C) 2021 Maxime Demarest * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -776,6 +777,117 @@ if ($ispaymentok) { $postactionmessages[] = 'Invoice paid '.$tmptag['INV'].' was not found'; $ispostactionok = -1; } + + } elseif (array_key_exists('DON', $tmptag) && $tmptag['DON'] > 0) { + include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; + $don = new Don($db); + $result = $don->fetch($tmptag['DON']); + if ($result) { + $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; + + $paymentTypeId = 0; + if ($paymentmethod == 'paybox') { + $paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS; + } + if ($paymentmethod == 'paypal') { + $paymentTypeId = $conf->global->PAYPAL_PAYMENT_MODE_FOR_PAYMENTS; + } + if ($paymentmethod == 'stripe') { + $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; + } + if (empty($paymentTypeId)) { + $paymentType = $_SESSION["paymentType"]; + if (empty($paymentType)) { + $paymentType = 'CB'; + } + $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); + } + + $currencyCodeType = $_SESSION['currencyCodeType']; + + // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) + if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { + $db->begin(); + + // Creation of paiement line for donation + include_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php'; + $paiement = new PaymentDonation($db); + + if ($currencyCodeType == $conf->currency) { + $paiement->amounts = array($object->id => $FinalPaymentAmt); // Array with all payments dispatching with donation + + } else { + // PaymentDonation does not support multi currency + $postactionmessages[] = 'Payment donation can\'t be payed with diffent currency than '.$conf->currency; + $ispostactionok = -1; + $error++; // Not yet supported + } + + $paiement->fk_donation = $don->id; + $paiement->datepaid = $now; + $paiement->paymenttype = $paymentTypeId; + $paiement->num_payment = ''; + $paiement->note_public = 'Online payment '.dol_print_date($now, 'standard').' from '.$ipaddress; + $paiement->ext_payment_id = $TRANSACTIONID; + $paiement->ext_payment_site = $service; + + if (!$error) { + $paiement_id = $paiement->create($user, 1); + if ($paiement_id < 0) { + $postactionmessages[] = $paiement->error.' '.join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + } else { + $postactionmessages[] = 'Payment created'; + $ispostactionok = 1; + + if ($totalpayed >= $don->getRemainToPay()) $don->setPaid($don->id); + } + } + + if (!$error && !empty($conf->banque->enabled)) { + $bankaccountid = 0; + if ($paymentmethod == 'paybox') { + $bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS; + } elseif ($paymentmethod == 'paypal') { + $bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS; + } elseif ($paymentmethod == 'stripe') { + $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; + } + + if ($bankaccountid > 0) { + $result = $paiement->addPaymentToBank($user, 'payment_donation', '(DonationPayment)', $bankaccountid, '', ''); + if ($result < 0) { + $postactionmessages[] = $paiement->error.' '.join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + } else { + $postactionmessages[] = 'Bank transaction of payment created'; + $ispostactionok = 1; + } + } else { + $postactionmessages[] = 'Setup of bank account to use in module '.$paymentmethod.' was not set. No way to record the payment.'; + $ispostactionok = -1; + $error++; + } + } + + if (!$error) { + $db->commit(); + } else { + $db->rollback(); + } + } else { + $postactionmessages[] = 'Failed to get a valid value for "amount paid" ('.$FinalPaymentAmt.') or "payment type" ('.$paymentType.') to record the payment of donation '.$tmptag['DON'].'. May be payment was already recorded.'; + $ispostactionok = -1; + } + } else { + $postactionmessages[] = 'Donation paid '.$tmptag['DON'].' was not found'; + $ispostactionok = -1; + } + + // TODO send email with acknowledgment for the donation + // (need that the donation module can gen a pdf document for the cerfa with pre filled content) } else { // Nothing done } @@ -903,6 +1015,7 @@ if ($ispaymentok) { $content .= "ErrorSeverityCode = ".$ErrorSeverityCode."
\n"; } + $ishtml = dol_textishtml($content); // May contain urls require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';