Passed
Branch develop (e2bf59)
by
unknown
29:11
created

Lettering::letteringThirdparty()   F

Complexity

Conditions 41
Paths 4864

Size

Total Lines 190
Code Lines 136

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 41
eloc 136
nc 4864
nop 1
dl 0
loc 190
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2004-2005  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2013       Olivier Geffroy         <[email protected]>
4
 * Copyright (C) 2013-2019  Alexandre Spangaro      <[email protected]>
5
 * Copyright (C) 2018       Frédéric France         <[email protected]>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
/**
22
 * \file      	htdocs/accountancy/class/lettering.class.php
23
 * \ingroup 	Accountancy (Double entries)
24
 * \brief 		File of class for lettering
25
 */
26
27
include_once DOL_DOCUMENT_ROOT."/accountancy/class/bookkeeping.class.php";
28
include_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
29
include_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
30
31
/**
32
 * Class Lettering
33
 */
34
class Lettering extends BookKeeping
35
{
36
	/**
37
	 * @var BookKeeping[] 	Bookkeeping cached
38
	 */
39
	public static $bookkeeping_cached = array();
40
41
42
	/**
43
	 * letteringThirdparty
44
	 *
45
	 * @param int $socid Thirdparty id
46
	 * @return int 1 OK, <0 error
47
	 */
48
	public function letteringThirdparty($socid)
49
	{
50
		global $conf;
51
52
		$error = 0;
53
54
		$object = new Societe($this->db);
55
		$object->id = $socid;
56
		$object->fetch($socid);
57
58
59
		if ($object->code_compta == '411CUSTCODE') {
60
			$object->code_compta = '';
61
		}
62
63
		if ($object->code_compta_fournisseur == '401SUPPCODE') {
64
			$object->code_compta_fournisseur = '';
65
		}
66
67
		/**
68
		 * Prise en charge des lettering complexe avec prelevment , virement
69
		 */
70
		$sql = "SELECT DISTINCT bk.rowid, bk.doc_date, bk.doc_type, bk.doc_ref, bk.subledger_account, ";
71
		$sql .= " bk.numero_compte , bk.label_compte, bk.debit , bk.credit, bk.montant ";
72
		$sql .= " , bk.sens , bk.code_journal , bk.piece_num, bk.date_lettering, bu.url_id , bu.type ";
73
		$sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as bk";
74
		$sql .= " LEFT JOIN  ".MAIN_DB_PREFIX."bank_url as bu ON(bk.fk_doc = bu.fk_bank AND bu.type IN ('payment', 'payment_supplier') ) ";
75
		$sql .= " WHERE ( ";
76
		if ($object->code_compta != "") {
77
			$sql .= " bk.subledger_account = '".$this->db->escape($object->code_compta)."'  ";
78
		}
79
		if ($object->code_compta != "" && $object->code_compta_fournisseur != "") {
80
			$sql .= " OR ";
81
		}
82
		if ($object->code_compta_fournisseur != "") {
83
			$sql .= " bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur)."' ";
84
		}
85
86
		$sql .= " ) AND (bk.date_lettering ='' OR bk.date_lettering IS NULL) ";
87
		$sql .= "  AND (bk.lettering_code != '' OR bk.lettering_code IS NULL) ";
88
		$sql .= ' AND bk.date_validated IS NULL ';
89
		$sql .= $this->db->order('bk.doc_date', 'DESC');
90
91
		// echo $sql;
92
		//
93
		$resql = $this->db->query($sql);
94
		if ($resql) {
95
			$num = $this->db->num_rows($resql);
96
97
			while ($obj = $this->db->fetch_object($resql)) {
98
				$ids = array();
99
				$ids_fact = array();
100
101
				if ($obj->type == 'payment_supplier') {
102
					$sql = 'SELECT DISTINCT bk.rowid, facf.ref, facf.ref_supplier, payf.fk_bank, facf.rowid as fact_id';
103
					$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn facf ";
104
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as payfacf ON  payfacf.fk_facturefourn=facf.rowid";
105
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."paiementfourn as payf ON  payfacf.fk_paiementfourn=payf.rowid";
106
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON (bk.fk_doc = payf.fk_bank AND bk.code_journal='".$this->db->escape($obj->code_journal)."')";
107
					$sql .= " WHERE payfacf.fk_paiementfourn = '".$this->db->escape($obj->url_id)."' ";
108
					$sql .= " AND facf.entity = ".$conf->entity;
109
					$sql .= " AND code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=4 AND entity=".$conf->entity.") ";
110
					$sql .= " AND ( ";
111
					if ($object->code_compta != "") {
112
						$sql .= "  bk.subledger_account = '".$this->db->escape($object->code_compta)."'  ";
113
					}
114
					if ($object->code_compta != "" && $object->code_compta_fournisseur != "") {
115
						$sql .= "  OR  ";
116
					}
117
					if ($object->code_compta_fournisseur != "") {
118
						$sql .= "   bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur)."' ";
119
					}
120
					$sql .= " )  ";
121
122
					$resql2 = $this->db->query($sql);
123
					if ($resql2) {
124
						while ($obj2 = $this->db->fetch_object($resql2)) {
125
							$ids[$obj2->rowid] = $obj2->rowid;
126
							$ids_fact[] = $obj2->fact_id;
127
						}
128
						$this->db->free($resql2);
129
					} else {
130
						$this->errors[] = $this->db->lasterror;
131
						return -1;
132
					}
133
					if (count($ids_fact)) {
134
						$sql = 'SELECT bk.rowid, facf.ref, facf.ref_supplier ';
135
						$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn facf ";
136
						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = facf.rowid AND facf.rowid IN (".$this->db->sanitize(implode(',', $ids_fact))."))";
137
						$sql .= " WHERE bk.code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=3 AND entity=".$conf->entity.") ";
138
						$sql .= " AND facf.entity = ".$conf->entity;
139
						$sql .= " AND ( ";
140
						if ($object->code_compta != "") {
141
							$sql .= " bk.subledger_account = '".$this->db->escape($object->code_compta)."'  ";
142
						}
143
						if ($object->code_compta != "" && $object->code_compta_fournisseur != "") {
144
							$sql .= " OR ";
145
						}
146
						if ($object->code_compta_fournisseur != "") {
147
							$sql .= " bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur)."' ";
148
						}
149
						$sql .= ") ";
150
151
						$resql2 = $this->db->query($sql);
152
						if ($resql2) {
153
							while ($obj2 = $this->db->fetch_object($resql2)) {
154
								$ids[$obj2->rowid] = $obj2->rowid;
155
							}
156
							$this->db->free($resql2);
157
						} else {
158
							$this->errors[] = $this->db->lasterror;
159
							return -1;
160
						}
161
					}
162
				} elseif ($obj->type == 'payment') {
163
					$sql = 'SELECT DISTINCT bk.rowid, fac.ref, fac.ref, pay.fk_bank, fac.rowid as fact_id';
164
					$sql .= " FROM ".MAIN_DB_PREFIX."facture fac ";
165
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."paiement_facture as payfac ON  payfac.fk_facture=fac.rowid";
166
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."paiement as pay ON  payfac.fk_paiement=pay.rowid";
167
					$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON (bk.fk_doc = pay.fk_bank AND bk.code_journal='".$this->db->escape($obj->code_journal)."')";
168
					$sql .= " WHERE payfac.fk_paiement = '".$this->db->escape($obj->url_id)."' ";
169
					$sql .= " AND bk.code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=4 AND entity=".$conf->entity.") ";
170
					$sql .= " AND fac.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy
171
					$sql .= " AND ( ";
172
					if ($object->code_compta != "") {
173
						$sql .= "  bk.subledger_account = '".$this->db->escape($object->code_compta)."'  ";
174
					}
175
					if ($object->code_compta != "" && $object->code_compta_fournisseur != "") {
176
						$sql .= "  OR  ";
177
					}
178
					if ($object->code_compta_fournisseur != "") {
179
						$sql .= "   bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur)."' ";
180
					}
181
					$sql .= " )";
182
183
					$resql2 = $this->db->query($sql);
184
					if ($resql2) {
185
						while ($obj2 = $this->db->fetch_object($resql2)) {
186
							$ids[$obj2->rowid] = $obj2->rowid;
187
							$ids_fact[] = $obj2->fact_id;
188
						}
189
					} else {
190
						$this->errors[] = $this->db->lasterror;
191
						return -1;
192
					}
193
					if (count($ids_fact)) {
194
						$sql = 'SELECT bk.rowid, fac.ref, fac.ref_supplier ';
195
						$sql .= " FROM ".MAIN_DB_PREFIX."facture fac ";
196
						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = fac.rowid AND fac.rowid IN (".$this->db->sanitize(implode(',', $ids_fact))."))";
197
						$sql .= " WHERE code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=2 AND entity=".$conf->entity.") ";
198
						$sql .= " AND fac.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy
199
						$sql .= " AND ( ";
200
						if ($object->code_compta != "") {
201
							$sql .= "  bk.subledger_account = '".$this->db->escape($object->code_compta)."'  ";
202
						}
203
						if ($object->code_compta != "" && $object->code_compta_fournisseur != "") {
204
							$sql .= "  OR  ";
205
						}
206
						if ($object->code_compta_fournisseur != "") {
207
							$sql .= "   bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur)."' ";
208
						}
209
						$sql .= " )  ";
210
211
						$resql2 = $this->db->query($sql);
212
						if ($resql2) {
213
							while ($obj2 = $this->db->fetch_object($resql2)) {
214
								$ids[$obj2->rowid] = $obj2->rowid;
215
							}
216
							$this->db->free($resql2);
217
						} else {
218
							$this->errors[] = $this->db->lasterror;
219
							return -1;
220
						}
221
					}
222
				}
223
224
				if (count($ids) > 1) {
225
					$result = $this->updateLettering($ids);
226
				}
227
			}
228
			$this->db->free($resql);
229
		}
230
		if ($error) {
231
			foreach ($this->errors as $errmsg) {
232
				dol_syslog(__METHOD__.' '.$errmsg, LOG_ERR);
233
				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
234
			}
235
			return -1 * $error;
236
		} else {
237
			return 1;
238
		}
239
	}
240
241
	/**
242
	 *
243
	 * @param	array		$ids			ids array
244
	 * @param	boolean		$notrigger		no trigger
245
	 * @return	int
246
	 */
247
	public function updateLettering($ids = array(), $notrigger = false)
248
	{
249
		$error = 0;
250
		$lettre = 'AAA';
251
252
		$sql = "SELECT DISTINCT ab2.lettering_code";
253
		$sql .=	" FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping As ab";
254
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc";
255
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu2 ON bu2.url_id = bu.url_id";
256
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab2 ON ab2.fk_doc = bu2.fk_bank";
257
		$sql .= " WHERE ab.rowid IN (" . $this->db->sanitize(implode(',', $ids)) . ")";
258
		$sql .= " AND ab.doc_type = 'bank'";
259
		$sql .= " AND ab2.doc_type = 'bank'";
260
		$sql .= " AND bu.type = 'company'";
261
		$sql .= " AND bu2.type = 'company'";
262
		$sql .= " AND ab.subledger_account != ''";
263
		$sql .= " AND ab2.subledger_account != ''";
264
		$sql .= " AND ab.lettering_code IS NULL";
265
		$sql .= " AND ab2.lettering_code != ''";
266
		$sql .= " ORDER BY ab2.lettering_code DESC";
267
		$sql .= " LIMIT 1 ";
268
269
		$result = $this->db->query($sql);
270
		if ($result) {
271
			$obj = $this->db->fetch_object($result);
272
			$lettre = (empty($obj->lettering_code) ? 'AAA' : $obj->lettering_code);
273
			if (!empty($obj->lettering_code)) {
274
				$lettre++;
275
			}
276
			$this->db->free($result);
277
		} else {
278
			$this->errors[] = 'Error'.$this->db->lasterror();
279
			$error++;
280
		}
281
282
		$sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE ";
283
		$sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
284
		$result = $this->db->query($sql);
285
		if ($result) {
286
			$obj = $this->db->fetch_object($result);
287
			if (!(round(abs($obj->deb), 2) === round(abs($obj->cred), 2))) {
288
				$this->errors[] = 'Total not exacts '.round(abs($obj->deb), 2).' vs '.round(abs($obj->cred), 2);
289
				$error++;
290
			}
291
			$this->db->free($result);
292
		} else {
293
			$this->errors[] = 'Erreur sql'.$this->db->lasterror();
294
			$error++;
295
		}
296
297
		// Update request
298
299
		$now = dol_now();
300
301
		if (!$error) {
302
			$sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
303
			$sql .= " lettering_code='".$this->db->escape($lettre)."'";
304
			$sql .= " , date_lettering = '".$this->db->idate($now)."'"; // todo correct date it's false
305
			$sql .= "  WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
306
307
			dol_syslog(get_class($this)."::update", LOG_DEBUG);
308
			$resql = $this->db->query($sql);
309
			if (!$resql) {
310
				$error++;
311
				$this->errors[] = "Error ".$this->db->lasterror();
312
			}
313
		}
314
315
		// Commit or rollback
316
		if ($error) {
317
			foreach ($this->errors as $errmsg) {
318
				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
319
				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
320
			}
321
			return -1 * $error;
322
		} else {
323
			return 1;
324
		}
325
	}
326
327
	/**
328
	 *
329
	 * @param	array		$ids			ids array
330
	 * @param	boolean		$notrigger		no trigger
331
	 * @return	int
332
	 */
333
	public function deleteLettering($ids, $notrigger = false)
334
	{
335
		$error = 0;
336
337
		$sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
338
		$sql .= " lettering_code = NULL";
339
		$sql .= " , date_lettering = NULL";
340
		$sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).")";
341
		$sql .= " AND subledger_account != ''";
342
343
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
344
		$resql = $this->db->query($sql);
345
		if (!$resql) {
346
			$error++;
347
			$this->errors[] = "Error ".$this->db->lasterror();
348
		}
349
350
		// Commit or rollback
351
		if ($error) {
352
			foreach ($this->errors as $errmsg) {
353
				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
354
				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
355
			}
356
			return -1 * $error;
357
		} else {
358
			return 1;
359
		}
360
	}
361
362
	/**
363
	 * Lettering bookkeeping lines all types
364
	 *
365
	 * @param	array		$bookkeeping_ids		Lettering specific list of bookkeeping id
366
	 * @param	bool		$unlettering			Do unlettering
367
	 * @return	int									<0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered)
368
	 */
369
	public function bookkeepingLetteringAll($bookkeeping_ids, $unlettering = false)
370
	{
371
		dol_syslog(__METHOD__ . " - ", LOG_DEBUG);
372
373
		$error = 0;
374
		$errors = array();
375
		$nb_lettering = 0;
376
377
		$result = $this->bookkeepingLettering($bookkeeping_ids, 'customer_invoice', $unlettering);
378
		if ($result < 0) {
379
			$error++;
380
			$errors = array_merge($errors, $this->errors);
381
			$nb_lettering += abs($result) - 2;
382
		} else {
383
			$nb_lettering += $result;
384
		}
385
386
		$result = $this->bookkeepingLettering($bookkeeping_ids, 'supplier_invoice', $unlettering);
387
		if ($result < 0) {
388
			$error++;
389
			$errors = array_merge($errors, $this->errors);
390
			$nb_lettering += abs($result) - 2;
391
		} else {
392
			$nb_lettering += $result;
393
		}
394
395
		if ($error) {
396
			$this->errors = $errors;
397
			return -2 - $nb_lettering;
398
		} else {
399
			return $nb_lettering;
400
		}
401
	}
402
403
	/**
404
	 * Lettering bookkeeping lines
405
	 *
406
	 * @param	array		$bookkeeping_ids		Lettering specific list of bookkeeping id
407
	 * @param	string		$type					Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
408
	 * @param	bool		$unlettering			Do unlettering
409
	 * @return	int									<0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered)
410
	 */
411
	public function bookkeepingLettering($bookkeeping_ids, $type = 'customer_invoice', $unlettering = false)
412
	{
413
		global $langs;
414
415
		$this->errors = array();
416
417
		// Clean parameters
418
		$bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
419
		$type = trim($type);
420
421
		$error = 0;
422
		$nb_lettering = 0;
423
		$grouped_lines = $this->getLinkedLines($bookkeeping_ids, $type);
424
		foreach ($grouped_lines as $lines) {
425
			$group_error = 0;
426
			$total = 0;
427
			$do_it = !$unlettering;
428
			$lettering_code = null;
429
			$piece_num_lines = array();
430
			$bookkeeping_lines = array();
431
			foreach ($lines as $line_infos) {
432
				$bookkeeping_lines[$line_infos['id']] = $line_infos['id'];
433
				$piece_num_lines[$line_infos['piece_num']] = $line_infos['piece_num'];
434
				$total += ($line_infos['credit'] > 0 ? $line_infos['credit'] : -$line_infos['debit']);
435
436
				// Check lettering code
437
				if ($unlettering) {
438
					if (isset($lettering_code) && $lettering_code != $line_infos['lettering_code']) {
439
						$this->errors[] = $langs->trans('AccountancyErrorMismatchLetteringCode');
440
						$group_error++;
441
						break;
442
					}
443
					if (!isset($lettering_code)) $lettering_code = (string) $line_infos['lettering_code'];
444
					if (!empty($line_infos['lettering_code'])) $do_it = true;
445
				} elseif (!empty($line_infos['lettering_code'])) $do_it = false;
446
			}
447
448
			// Check balance amount
449
			if (!$group_error && !$unlettering && price2num($total) != 0) {
450
				$this->errors[] = $langs->trans('AccountancyErrorMismatchBalanceAmount', $total);
451
				$group_error++;
452
			}
453
454
			// Lettering/Unlettering the group of bookkeeping lines
455
			if (!$group_error && $do_it) {
456
				if ($unlettering) $result = $this->deleteLettering($bookkeeping_lines);
457
				else $result = $this->updateLettering($bookkeeping_lines);
458
				if ($result < 0) {
459
					$group_error++;
460
				} else {
461
					$nb_lettering++;
462
				}
463
			}
464
465
			if ($group_error) {
466
				$this->errors[] = $langs->trans('AccountancyErrorLetteringBookkeeping', implode(', ', $piece_num_lines));
467
				$error++;
468
			}
469
		}
470
471
		if ($error) {
472
			return -2 - $nb_lettering;
473
		} else {
474
			return $nb_lettering;
475
		}
476
	}
477
478
	/**
479
	 * Lettering bookkeeping lines
480
	 *
481
	 * @param	array			$bookkeeping_ids		Lettering specific list of bookkeeping id
482
	 * @param	string			$type					Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
483
	 * @return	array|int								<0 if error otherwise all linked lines by block
484
	 */
485
	public function getLinkedLines($bookkeeping_ids, $type = 'customer_invoice')
486
	{
487
		global $conf, $langs;
488
		$this->errors = array();
489
490
		// Clean parameters
491
		$bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
492
		$type = trim($type);
493
494
		if ($type == 'customer_invoice') {
495
			$doc_type = 'customer_invoice';
496
			$bank_url_type = 'payment';
497
			$payment_element = 'paiement_facture';
498
			$fk_payment_element = 'fk_paiement';
499
			$fk_element = 'fk_facture';
500
			$account_number = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
501
		} elseif ($type == 'supplier_invoice') {
502
			$doc_type = 'supplier_invoice';
503
			$bank_url_type = 'payment_supplier';
504
			$payment_element = 'paiementfourn_facturefourn';
505
			$fk_payment_element = 'fk_paiementfourn';
506
			$fk_element = 'fk_facturefourn';
507
			$account_number = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
508
		} else {
509
			$langs->load('errors');
510
			$this->errors[] = $langs->trans('ErrorBadParameters');
511
			return -1;
512
		}
513
514
		$payment_ids = array();
515
516
		// Get all payment id from bank lines
517
		$sql = "SELECT DISTINCT bu.url_id AS payment_id";
518
		$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
519
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc";
520
		$sql .= " WHERE ab.doc_type = 'bank'";
521
		//	$sql .= " AND ab.subledger_account != ''";
522
		//	$sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
523
		$sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
524
		if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
525
526
		dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
527
		$resql = $this->db->query($sql);
528
		if (!$resql) {
529
			$this->errors[] = "Error " . $this->db->lasterror();
530
			return -1;
531
		}
532
533
		while ($obj = $this->db->fetch_object($resql)) {
534
			$payment_ids[$obj->payment_id] = $obj->payment_id;
535
		}
536
		$this->db->free($resql);
537
538
		// Get all payment id from payment lines
539
		$sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id";
540
		$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
541
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc";
542
		$sql .= " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'";
543
		//	$sql .= " AND ab.subledger_account != ''";
544
		//	$sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
545
		$sql .= " AND pe.$fk_payment_element IS NOT NULL";
546
		if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
547
548
		dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
549
		$resql = $this->db->query($sql);
550
		if (!$resql) {
551
			$this->errors[] = "Error " . $this->db->lasterror();
552
			return -1;
553
		}
554
555
		while ($obj = $this->db->fetch_object($resql)) {
556
			$payment_ids[$obj->payment_id] = $obj->payment_id;
557
		}
558
		$this->db->free($resql);
559
560
		if (empty($payment_ids)) {
561
			return array();
562
		}
563
564
		// Get all payments linked by group
565
		$payment_by_group = $this->getLinkedPaymentByGroup($payment_ids, $type);
566
567
		$groups = array();
568
		foreach ($payment_by_group as $payment_list) {
569
			$lines = array();
570
571
			// Get bank lines
572
			$sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
573
			$sql .=	" FROM " . MAIN_DB_PREFIX . "bank_url AS bu";
574
			$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank";
575
			$sql .= " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
576
			$sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
577
			$sql .= " AND ab.doc_type = 'bank'";
578
			$sql .= " AND ab.subledger_account != ''";
579
			$sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
580
581
			dol_syslog(__METHOD__ . " - Get bank lines", LOG_DEBUG);
582
			$resql = $this->db->query($sql);
583
			if (!$resql) {
584
				$this->errors[] = "Error " . $this->db->lasterror();
585
				return -1;
586
			}
587
588
			while ($obj = $this->db->fetch_object($resql)) {
589
				$lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
590
			}
591
			$this->db->free($resql);
592
593
			// Get payment lines
594
			$sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
595
			$sql .=	" FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
596
			$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element";
597
			$sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
598
			$sql .= " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'";
599
			$sql .= " AND ab.subledger_account != ''";
600
			$sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
601
602
			dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
603
			$resql = $this->db->query($sql);
604
			if (!$resql) {
605
				$this->errors[] = "Error " . $this->db->lasterror();
606
				return -1;
607
			}
608
609
			while ($obj = $this->db->fetch_object($resql)) {
610
				$lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
611
			}
612
			$this->db->free($resql);
613
614
			if (!empty($lines)) {
615
				$groups[] = $lines;
616
			}
617
		}
618
619
		return $groups;
620
	}
621
622
	/**
623
	 * Linked payment by group
624
	 *
625
	 * @param	array			$payment_ids			list of payment id
626
	 * @param	string			$type					Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
627
	 * @return	array|int								<0 if error otherwise all linked lines by block
628
	 */
629
	public function getLinkedPaymentByGroup($payment_ids, $type)
630
	{
631
		global $langs;
632
633
		// Clean parameters
634
		$payment_ids = is_array($payment_ids) ? $payment_ids : array();
635
		$type = trim($type);
636
637
		if (empty($payment_ids)) {
638
			return array();
639
		}
640
641
		if ($type == 'customer_invoice') {
642
			$payment_element = 'paiement_facture';
643
			$fk_payment_element = 'fk_paiement';
644
			$fk_element = 'fk_facture';
645
		} elseif ($type == 'supplier_invoice') {
646
			$payment_element = 'paiementfourn_facturefourn';
647
			$fk_payment_element = 'fk_paiementfourn';
648
			$fk_element = 'fk_facturefourn';
649
		} else {
650
			$langs->load('errors');
651
			$this->errors[] = $langs->trans('ErrorBadParameters');
652
			return -1;
653
		}
654
655
		// Get payment lines
656
		$sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element";
657
		$sql .=	" FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
658
		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element";
659
		$sql .=	" WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")";
660
661
		dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
662
		$resql = $this->db->query($sql);
663
		if (!$resql) {
664
			$this->errors[] = "Error " . $this->db->lasterror();
665
			return -1;
666
		}
667
668
		$current_payment_ids = array();
669
		$payment_by_element = array();
670
		$element_by_payment = array();
671
		while ($obj = $this->db->fetch_object($resql)) {
672
			$current_payment_ids[$obj->$fk_payment_element] = $obj->$fk_payment_element;
673
			$element_by_payment[$obj->$fk_payment_element][$obj->$fk_element] = $obj->$fk_element;
674
			$payment_by_element[$obj->$fk_element][$obj->$fk_payment_element] = $obj->$fk_payment_element;
675
		}
676
		$this->db->free($resql);
677
678
		if (count(array_diff($payment_ids, $current_payment_ids))) {
679
			return $this->getLinkedPaymentByGroup($current_payment_ids, $type);
680
		}
681
682
		return $this->getGroupElements($payment_by_element, $element_by_payment);
683
	}
684
685
	/**
686
	 * Get payment ids grouped by payment id and element id in common
687
	 *
688
	 * @param	array	$payment_by_element		List of payment ids by element id
689
	 * @param	array	$element_by_payment		List of element ids by payment id
690
	 * @param	int		$element_id				Element Id (used for recursive function)
691
	 * @param	array	$current_group			Current group (used for recursive function)
692
	 * @return	array							List of payment ids grouped by payment id and element id in common
693
	 */
694
	public function getGroupElements(&$payment_by_element, &$element_by_payment, $element_id = 0, &$current_group = array())
695
	{
696
		$grouped_payments = array();
697
		if ($element_id > 0 && !isset($payment_by_element[$element_id])) {
698
			// Return if specific element id not found
699
			return $grouped_payments;
700
		}
701
702
		if ($element_id == 0) {
703
			// Save list when is the begin of recursive function
704
			$save_payment_by_element = $payment_by_element;
705
			$save_element_by_payment = $element_by_payment;
706
		}
707
708
		do {
709
			// Get current element id, get this payment id list and delete the entry
710
			$current_element_id = $element_id > 0 ? $element_id : array_keys($payment_by_element)[0];
711
			$payment_ids = $payment_by_element[$current_element_id];
712
			unset($payment_by_element[$current_element_id]);
713
714
			foreach ($payment_ids as $payment_id) {
715
				// Continue if payment id in not found
716
				if (!isset($element_by_payment[$payment_id])) continue;
717
718
				// Set the payment in the current group
719
				$current_group[$payment_id] = $payment_id;
720
721
				// Get current element ids, get this payment id list and delete the entry
722
				$element_ids = $element_by_payment[$payment_id];
723
				unset($element_by_payment[$payment_id]);
724
725
				// Set payment id on the current group for each element id of the payment
726
				foreach ($element_ids as $id) {
727
					$this->getGroupElements($payment_by_element, $element_by_payment, $id, $current_group);
728
				}
729
			}
730
731
			if ($element_id == 0) {
732
				// Save current group and reset the current group when is the begin of recursive function
733
				$grouped_payments[] = $current_group;
734
				$current_group = array();
735
			}
736
		} while (!empty($payment_by_element) && $element_id == 0);
737
738
		if ($element_id == 0) {
739
			// Restore list when is the begin of recursive function
740
			$payment_by_element = $save_payment_by_element;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $save_payment_by_element does not seem to be defined for all execution paths leading up to this point.
Loading history...
741
			$element_by_payment = $save_element_by_payment;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $save_element_by_payment does not seem to be defined for all execution paths leading up to this point.
Loading history...
742
		}
743
744
		return $grouped_payments;
745
	}
746
}
747