1<?php
2/* Copyright (C) 2015       Alexandre Spangaro	  	<aspangaro@open-dsi.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18/**
19 *  \file       htdocs/don/class/paymentdonation.class.php
20 *  \ingroup    Donation
21 *  \brief      File of class to manage payment of donations
22 */
23
24require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
25
26
27/**
28 *	Class to manage payments of donations
29 */
30class PaymentDonation extends CommonObject
31{
32	/**
33	 * @var string ID to identify managed object
34	 */
35	public $element = 'payment_donation';
36
37	/**
38	 * @var string Name of table without prefix where object is stored
39	 */
40	public $table_element = 'payment_donation';
41
42	/**
43	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
44	 */
45	public $picto = 'payment';
46
47	/**
48	 * @var int ID
49	 */
50	public $rowid;
51
52	/**
53	 * @var int ID
54	 */
55	public $fk_donation;
56
57	public $datec = '';
58
59	public $tms = '';
60
61	public $datep = '';
62
63	public $amount; // Total amount of payment
64
65	public $amounts = array(); // Array of amounts
66
67	public $typepayment;
68
69	public $num_payment;
70
71	/**
72	 * @var int ID
73	 */
74	public $fk_bank;
75
76	/**
77	 * @var int ID
78	 */
79	public $fk_user_creat;
80
81	/**
82	 * @var int ID
83	 */
84	public $fk_user_modif;
85
86	/**
87	 * @deprecated
88	 * @see $amount, $amounts
89	 */
90	public $total;
91
92	public $type_code;
93	public $type_label;
94
95	/**
96	 * @var string Id of external payment mode
97	 */
98	public $ext_payment_id;
99
100	/**
101	 * @var string Name of external payment mode
102	 */
103	public $ext_payment_site;
104
105	/**
106	 *	Constructor
107	 *
108	 *  @param		DoliDB		$db      Database handler
109	 */
110	public function __construct($db)
111	{
112		$this->db = $db;
113	}
114
115	/**
116	 *  Create payment of donation into database.
117	 *  Use this->amounts to have list of lines for the payment
118	 *
119	 *  @param      User		$user			User making payment
120	 *  @param      bool 		$notrigger 		false=launch triggers after, true=disable triggers
121	 *  @return     int     					<0 if KO, id of payment if OK
122	 */
123	public function create($user, $notrigger = false)
124	{
125		global $conf, $langs;
126
127		$error = 0;
128
129		$now = dol_now();
130
131		// Validate parameters
132		if (!$this->datepaid) {
133			$this->error = 'ErrorBadValueForParameterCreatePaymentDonation';
134			return -1;
135		}
136
137		// Clean parameters
138		if (isset($this->chid)) {
139			$this->chid = (int) $this->chid;
140		} elseif (isset($this->fk_donation)) {
141			// NOTE : The property used in INSERT for fk_donation is not fk_donation but chid
142			//        (keep priority to chid property)
143			$this->chid = (int) $this->fk_donation;
144		}
145		if (isset($this->fk_donation)) {
146			$this->fk_donation = (int) $this->fk_donation;
147		}
148		if (isset($this->amount)) {
149			$this->amount = trim($this->amount);
150		}
151		if (isset($this->fk_typepayment)) {
152			$this->fk_typepayment = trim($this->fk_typepayment);
153		}
154		if (isset($this->num_payment)) {
155			$this->num_payment    = trim($this->num_payment);
156		}
157		if (isset($this->note_public)) {
158			$this->note_public = trim($this->note_public);
159		}
160		if (isset($this->fk_bank)) {
161			$this->fk_bank = (int) $this->fk_bank;
162		}
163		if (isset($this->fk_user_creat)) {
164			$this->fk_user_creat  = (int) $this->fk_user_creat;
165		}
166		if (isset($this->fk_user_modif)) {
167			$this->fk_user_modif  = (int) $this->fk_user_modif;
168		}
169
170		$totalamount = 0;
171		foreach ($this->amounts as $key => $value) {  // How payment is dispatch
172			$newvalue = price2num($value, 'MT');
173			$this->amounts[$key] = $newvalue;
174			$totalamount += $newvalue;
175		}
176		$totalamount = price2num($totalamount);
177
178		// Check parameters
179		if ($totalamount == 0) {
180			return -1; // On accepte les montants negatifs pour les rejets de prelevement mais pas null
181		}
182
183
184		$this->db->begin();
185
186		if ($totalamount != 0) {
187			$sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_donation (fk_donation, datec, datep, amount,";
188			$sql .= " fk_typepayment, num_payment, note, ext_payment_id, ext_payment_site,";
189			$sql .= " fk_user_creat, fk_bank)";
190			$sql .= " VALUES ($this->chid, '".$this->db->idate($now)."',";
191			$sql .= " '".$this->db->idate($this->datepaid)."',";
192			$sql .= " ".price2num($totalamount).",";
193			$sql .= " ".((int) $this->paymenttype).", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_public)."', ";
194			$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").",";
195			$sql .= " ".$user->id.", 0)";
196
197			dol_syslog(get_class($this)."::create", LOG_DEBUG);
198			$resql = $this->db->query($sql);
199			if ($resql) {
200				$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."payment_donation");
201				$this->ref = $this->id;
202			} else {
203				$error++;
204			}
205		}
206
207		if (!$error && !$notrigger) {
208			// Call triggers
209			$result = $this->call_trigger('DONATION_PAYMENT_CREATE', $user);
210			if ($result < 0) {
211				$error++;
212			}
213			// End call triggers
214		}
215
216		if ($totalamount != 0 && !$error) {
217			$this->amount = $totalamount;
218			$this->total = $totalamount; // deprecated
219			$this->db->commit();
220			return $this->id;
221		} else {
222			$this->error = $this->db->error();
223			$this->db->rollback();
224			return -1;
225		}
226	}
227
228	/**
229	 *  Load object in memory from database
230	 *
231	 *  @param	int		$id         Id object
232	 *  @return int         		<0 if KO, >0 if OK
233	 */
234	public function fetch($id)
235	{
236		global $langs;
237		$sql = "SELECT";
238		$sql .= " t.rowid,";
239		$sql .= " t.fk_donation,";
240		$sql .= " t.datec,";
241		$sql .= " t.tms,";
242		$sql .= " t.datep,";
243		$sql .= " t.amount,";
244		$sql .= " t.fk_typepayment,";
245		$sql .= " t.num_payment,";
246		$sql .= " t.note as note_public,";
247		$sql .= " t.fk_bank,";
248		$sql .= " t.fk_user_creat,";
249		$sql .= " t.fk_user_modif,";
250		$sql .= " pt.code as type_code, pt.libelle as type_label,";
251		$sql .= ' b.fk_account';
252		$sql .= " FROM ".MAIN_DB_PREFIX."payment_donation as t";
253		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as pt ON t.fk_typepayment = pt.id";
254		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON t.fk_bank = b.rowid';
255		$sql .= " WHERE t.rowid = ".((int) $id);
256
257		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
258		$resql = $this->db->query($sql);
259		if ($resql) {
260			if ($this->db->num_rows($resql)) {
261				$obj = $this->db->fetch_object($resql);
262
263				$this->id  = $obj->rowid;
264				$this->ref = $obj->rowid;
265
266				$this->fk_donation    = $obj->fk_donation;
267				$this->datec		  = $this->db->jdate($obj->datec);
268				$this->tms            = $this->db->jdate($obj->tms);
269				$this->datep		  = $this->db->jdate($obj->datep);
270				$this->amount         = $obj->amount;
271				$this->fk_typepayment = $obj->fk_typepayment;
272				$this->num_payment    = $obj->num_payment;
273				$this->note_public    = $obj->note_public;
274				$this->fk_bank        = $obj->fk_bank;
275				$this->fk_user_creat  = $obj->fk_user_creat;
276				$this->fk_user_modif  = $obj->fk_user_modif;
277
278				$this->type_code  = $obj->type_code;
279				$this->type_label = $obj->type_label;
280
281				$this->bank_account = $obj->fk_account;
282				$this->bank_line    = $obj->fk_bank;
283			}
284			$this->db->free($resql);
285
286			return 1;
287		} else {
288			$this->error = "Error ".$this->db->lasterror();
289			return -1;
290		}
291	}
292
293
294	/**
295	 *  Update database
296	 *
297	 *  @param	User	$user        	User that modify
298	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
299	 *  @return int         			<0 if KO, >0 if OK
300	 */
301	public function update($user, $notrigger = 0)
302	{
303		global $conf, $langs;
304		$error = 0;
305
306		// Clean parameters
307
308		if (isset($this->fk_donation)) {
309			$this->fk_donation = (int) $this->fk_donation;
310		}
311		if (isset($this->amount)) {
312			$this->amount = trim($this->amount);
313		}
314		if (isset($this->fk_typepayment)) {
315			$this->fk_typepayment = trim($this->fk_typepayment);
316		}
317		if (isset($this->num_payment)) {
318			$this->num_payment = trim($this->num_payment);
319		}
320		if (isset($this->note_public)) {
321			$this->note_public = trim($this->note_public);
322		}
323		if (isset($this->fk_bank)) {
324			$this->fk_bank = (int) $this->fk_bank;
325		}
326		if (isset($this->fk_user_creat)) {
327			$this->fk_user_creat = (int) $this->fk_user_creat;
328		}
329		if (isset($this->fk_user_modif)) {
330			$this->fk_user_modif = (int) $this->fk_user_modif;
331		}
332
333		// Check parameters
334		// Put here code to add control on parameters values
335
336		// Update request
337		$sql = "UPDATE ".MAIN_DB_PREFIX."payment_donation SET";
338		$sql .= " fk_donation=".(isset($this->fk_donation) ? $this->fk_donation : "null").",";
339		$sql .= " datec=".(dol_strlen($this->datec) != 0 ? "'".$this->db->idate($this->datec)."'" : 'null').",";
340		$sql .= " tms=".(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : 'null').",";
341		$sql .= " datep=".(dol_strlen($this->datep) != 0 ? "'".$this->db->idate($this->datep)."'" : 'null').",";
342		$sql .= " amount=".(isset($this->amount) ? $this->amount : "null").",";
343		$sql .= " fk_typepayment=".(isset($this->fk_typepayment) ? $this->fk_typepayment : "null").",";
344		$sql .= " num_payment=".(isset($this->num_payment) ? "'".$this->db->escape($this->num_payment)."'" : "null").",";
345		$sql .= " note=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").",";
346		$sql .= " fk_bank=".(isset($this->fk_bank) ? $this->fk_bank : "null").",";
347		$sql .= " fk_user_creat=".(isset($this->fk_user_creat) ? $this->fk_user_creat : "null").",";
348		$sql .= " fk_user_modif=".(isset($this->fk_user_modif) ? $this->fk_user_modif : "null")."";
349		$sql .= " WHERE rowid=".(int) $this->id;
350
351		$this->db->begin();
352
353		dol_syslog(get_class($this)."::update", LOG_DEBUG);
354		$resql = $this->db->query($sql);
355		if (!$resql) {
356			$error++;
357			$this->errors[] = "Error ".$this->db->lasterror();
358		}
359
360		if (!$error) {
361			if (!$notrigger) {
362				if (!$error && !$notrigger) {
363					// Call triggers
364					$result = $this->call_trigger('DONATION_PAYMENT_MODIFY', $user);
365					if ($result < 0) {
366						$error++;
367					}
368					// End call triggers
369				}
370			}
371		}
372
373		// Commit or rollback
374		if ($error) {
375			foreach ($this->errors as $errmsg) {
376				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
377				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
378			}
379			$this->db->rollback();
380			return -1 * $error;
381		} else {
382			$this->db->commit();
383			return 1;
384		}
385	}
386
387
388	/**
389	 *  Delete object in database
390	 *
391	 *  @param	User	$user        	User that delete
392	 *  @param  int		$notrigger		0=launch triggers after, 1=disable triggers
393	 *  @return int						<0 if KO, >0 if OK
394	 */
395	public function delete($user, $notrigger = 0)
396	{
397		global $conf, $langs;
398		$error = 0;
399
400		$this->db->begin();
401
402		if (!$error) {
403			$sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_url";
404			$sql .= " WHERE type='payment_donation' AND url_id=".(int) $this->id;
405
406			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
407			$resql = $this->db->query($sql);
408			if (!$resql) {
409				$error++; $this->errors[] = "Error ".$this->db->lasterror();
410			}
411		}
412
413		if (!$error) {
414			$sql = "DELETE FROM ".MAIN_DB_PREFIX."payment_donation";
415			$sql .= " WHERE rowid=".((int) $this->id);
416
417			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
418			$resql = $this->db->query($sql);
419			if (!$resql) {
420				$error++;
421				$this->errors[] = "Error ".$this->db->lasterror();
422			}
423		}
424
425		if (!$error) {
426			if (!$notrigger) {
427				if (!$error && !$notrigger) {
428					// Call triggers
429					$result = $this->call_trigger('DONATION_PAYMENT_DELETE', $user);
430					if ($result < 0) {
431						$error++;
432					}
433					// End call triggers
434				}
435			}
436		}
437
438		// Commit or rollback
439		if ($error) {
440			foreach ($this->errors as $errmsg) {
441				dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
442				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
443			}
444			$this->db->rollback();
445			return -1 * $error;
446		} else {
447			$this->db->commit();
448			return 1;
449		}
450	}
451
452
453
454	/**
455	 *	Load an object from its id and create a new one in database
456	 *
457	 *  @param	User	$user		    User making the clone
458	 *	@param	int		$fromid     	Id of object to clone
459	 * 	@return	int						New id of clone
460	 */
461	public function createFromClone(User $user, $fromid)
462	{
463		$error = 0;
464
465		$object = new PaymentDonation($this->db);
466
467		$this->db->begin();
468
469		// Load source object
470		$object->fetch($fromid);
471		$object->id = 0;
472		$object->statut = 0;
473
474		// Clear fields
475		// ...
476
477		// Create clone
478		$object->context['createfromclone'] = 'createfromclone';
479		$result = $object->create($user);
480
481		// Other options
482		if ($result < 0) {
483			$this->error = $object->error;
484			$error++;
485		}
486
487		if (!$error) {
488		}
489
490		unset($object->context['createfromclone']);
491
492		// End
493		if (!$error) {
494			$this->db->commit();
495			return $object->id;
496		} else {
497			$this->db->rollback();
498			return -1;
499		}
500	}
501
502
503	/**
504	 * 	Retourne le libelle du statut d'un don (brouillon, validee, abandonnee, payee)
505	 *
506	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long
507	 *  @return string        		Libelle
508	 */
509	public function getLibStatut($mode = 0)
510	{
511		return '';
512	}
513
514	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
515	/**
516	 *  Renvoi le libelle d'un statut donne
517	 *
518	 *  @param	int		$status        	Id status
519	 *  @param  int		$mode          	0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
520	 *  @return string 			       	Libelle du statut
521	 */
522	public function LibStatut($status, $mode = 0)
523	{
524		// phpcs:enable
525		global $langs;
526
527		return '';
528	}
529
530
531	/**
532	 *  Initialise an instance with random values.
533	 *  Used to build previews or test instances.
534	 *	id must be 0 if object instance is a specimen.
535	 *
536	 *  @return	void
537	 */
538	public function initAsSpecimen()
539	{
540		$this->id = 0;
541
542		$this->fk_donation = '';
543		$this->datec = '';
544		$this->tms = '';
545		$this->datep = '';
546		$this->amount = '';
547		$this->fk_typepayment = '';
548		$this->num_payment = '';
549		$this->note_public = '';
550		$this->fk_bank = '';
551		$this->fk_user_creat = '';
552		$this->fk_user_modif = '';
553	}
554
555
556	/**
557	 *      Add record into bank for payment with links between this bank record and invoices of payment.
558	 *      All payment properties must have been set first like after a call to create().
559	 *
560	 *      @param	User	$user               Object of user making payment
561	 *      @param  string	$mode               'payment_donation'
562	 *      @param  string	$label              Label to use in bank record
563	 *      @param  int		$accountid          Id of bank account to do link with
564	 *      @param  string	$emetteur_nom       Name of transmitter
565	 *      @param  string	$emetteur_banque    Name of bank
566	 *      @return int                 		<0 if KO, >0 if OK
567	 */
568	public function addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque)
569	{
570		global $conf;
571
572		$error = 0;
573
574		if (!empty($conf->banque->enabled)) {
575			require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
576
577			$acc = new Account($this->db);
578			$acc->fetch($accountid);
579
580			$total = $this->total;
581			if ($mode == 'payment_donation') {
582				$amount = $total;
583			}
584
585			// Insert payment into llx_bank
586			$bank_line_id = $acc->addline(
587				$this->datepaid,
588				$this->paymenttype, // Payment mode id or code ("CHQ or VIR for example")
589				$label,
590				$amount,
591				$this->num_payment,
592				'',
593				$user,
594				$emetteur_nom,
595				$emetteur_banque
596			);
597
598			// Update fk_bank in llx_paiement.
599			// On connait ainsi le paiement qui a genere l'ecriture bancaire
600			if ($bank_line_id > 0) {
601				$result = $this->update_fk_bank($bank_line_id);
602				if ($result <= 0) {
603					$error++;
604					dol_print_error($this->db);
605				}
606
607				// Add link 'payment', 'payment_supplier', 'payment_donation' in bank_url between payment and bank transaction
608				$url = '';
609				if ($mode == 'payment_donation') {
610					$url = DOL_URL_ROOT.'/don/payment/card.php?rowid=';
611				}
612				if ($url) {
613					$result = $acc->add_url_line($bank_line_id, $this->id, $url, '(paiement)', $mode);
614					if ($result <= 0) {
615						$error++;
616						dol_print_error($this->db);
617					}
618				}
619			} else {
620				$this->error = $acc->error;
621				$error++;
622			}
623		}
624
625		if (!$error) {
626			return 1;
627		} else {
628			return -1;
629		}
630	}
631
632
633	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
634	/**
635	 *  Update link between the donation payment and the generated line in llx_bank
636	 *
637	 *  @param	int		$id_bank         Id if bank
638	 *  @return	int			             >0 if OK, <=0 if KO
639	 */
640	public function update_fk_bank($id_bank)
641	{
642		// phpcs:enable
643		$sql = "UPDATE ".MAIN_DB_PREFIX."payment_donation SET fk_bank = ".(int) $id_bank." WHERE rowid = ".(int) $this->id;
644
645		dol_syslog(get_class($this)."::update_fk_bank", LOG_DEBUG);
646		$result = $this->db->query($sql);
647		if ($result) {
648			return 1;
649		} else {
650			$this->error = $this->db->error();
651			return 0;
652		}
653	}
654
655	/**
656	 *  Return clicable name (with picto eventually)
657	 *
658	 *	@param	int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
659	 * 	@param	int		$maxlen			Max length
660	 *	@return	string					String with URL
661	 */
662	public function getNomUrl($withpicto = 0, $maxlen = 0)
663	{
664		global $langs;
665
666		$result = '';
667
668		$label = '<u>'.$langs->trans("DonationPayment").'</u>';
669		$label .= '<br>';
670		$label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
671
672		if (!empty($this->id)) {
673			$link = '<a href="'.DOL_URL_ROOT.'/don/payment/card.php?id='.$this->id.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
674			$linkend = '</a>';
675
676			if ($withpicto) {
677				$result .= ($link.img_object($label, 'payment', 'class="classfortooltip"').$linkend.' ');
678			}
679			if ($withpicto && $withpicto != 2) {
680				$result .= ' ';
681			}
682			if ($withpicto != 2) {
683				$result .= $link.($maxlen ?dol_trunc($this->ref, $maxlen) : $this->ref).$linkend;
684			}
685		}
686
687		return $result;
688	}
689}
690