dolibarr  16.0.5
lettering.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2013 Olivier Geffroy <jeff@jeffinfo.com>
4  * Copyright (C) 2013-2019 Alexandre Spangaro <aspangaro@open-dsi.fr>
5  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
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 
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 
34 class Lettering extends BookKeeping
35 {
39  public static $bookkeeping_cached = array();
40 
41 
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 
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 
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  $resqla = $this->db->query($sql);
270  if ($resqla) {
271  $obj = $this->db->fetch_object($resqla);
272  $lettre = (empty($obj->lettering_code) ? 'AAA' : $obj->lettering_code);
273  if (!empty($obj->lettering_code)) {
274  $lettre++;
275  }
276  $this->db->free($resqla);
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  $resqlb = $this->db->query($sql);
285  if ($resqlb) {
286  $obj = $this->db->fetch_object($resqlb);
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($resqlb);
292  } else {
293  $this->errors[] = 'Erreur sql'.$this->db->lasterror();
294  $error++;
295  }
296 
297  // Update request
298 
299  $now = dol_now();
300  $affected_rows = 0;
301 
302  if (!$error) {
303  $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
304  $sql .= " lettering_code='".$this->db->escape($lettre)."'";
305  $sql .= " , date_lettering = '".$this->db->idate($now)."'"; // todo correct date it's false
306  $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
307 
308  dol_syslog(get_class($this)."::update", LOG_DEBUG);
309  $resql = $this->db->query($sql);
310  if (!$resql) {
311  $error++;
312  $this->errors[] = "Error ".$this->db->lasterror();
313  } else {
314  $affected_rows = $this->db->affected_rows($resql);
315  }
316  }
317 
318  // Commit or rollback
319  if ($error) {
320  foreach ($this->errors as $errmsg) {
321  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
322  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
323  }
324  return -1 * $error;
325  } else {
326  return $affected_rows;
327  }
328  }
329 
336  public function deleteLettering($ids, $notrigger = false)
337  {
338  $error = 0;
339 
340  $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
341  $sql .= " lettering_code = NULL";
342  $sql .= " , date_lettering = NULL";
343  $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).")";
344  $sql .= " AND subledger_account != ''";
345 
346  dol_syslog(get_class($this)."::update", LOG_DEBUG);
347  $resql = $this->db->query($sql);
348  if (!$resql) {
349  $error++;
350  $this->errors[] = "Error ".$this->db->lasterror();
351  }
352 
353  // Commit or rollback
354  if ($error) {
355  foreach ($this->errors as $errmsg) {
356  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
357  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
358  }
359  return -1 * $error;
360  } else {
361  return $this->db->affected_rows($resql);
362  }
363  }
364 
372  public function bookkeepingLetteringAll($bookkeeping_ids, $unlettering = false)
373  {
374  dol_syslog(__METHOD__ . " - ", LOG_DEBUG);
375 
376  $error = 0;
377  $errors = array();
378  $nb_lettering = 0;
379 
380  $result = $this->bookkeepingLettering($bookkeeping_ids, 'customer_invoice', $unlettering);
381  if ($result < 0) {
382  $error++;
383  $errors = array_merge($errors, $this->errors);
384  $nb_lettering += abs($result) - 2;
385  } else {
386  $nb_lettering += $result;
387  }
388 
389  $result = $this->bookkeepingLettering($bookkeeping_ids, 'supplier_invoice', $unlettering);
390  if ($result < 0) {
391  $error++;
392  $errors = array_merge($errors, $this->errors);
393  $nb_lettering += abs($result) - 2;
394  } else {
395  $nb_lettering += $result;
396  }
397 
398  if ($error) {
399  $this->errors = $errors;
400  return -2 - $nb_lettering;
401  } else {
402  return $nb_lettering;
403  }
404  }
405 
414  public function bookkeepingLettering($bookkeeping_ids, $type = 'customer_invoice', $unlettering = false)
415  {
416  global $langs;
417 
418  $this->errors = array();
419 
420  // Clean parameters
421  $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
422  $type = trim($type);
423 
424  $error = 0;
425  $nb_lettering = 0;
426  $grouped_lines = $this->getLinkedLines($bookkeeping_ids, $type);
427  foreach ($grouped_lines as $lines) {
428  $group_error = 0;
429  $total = 0;
430  $do_it = !$unlettering;
431  $lettering_code = null;
432  $piece_num_lines = array();
433  $bookkeeping_lines = array();
434  foreach ($lines as $line_infos) {
435  $bookkeeping_lines[$line_infos['id']] = $line_infos['id'];
436  $piece_num_lines[$line_infos['piece_num']] = $line_infos['piece_num'];
437  $total += ($line_infos['credit'] > 0 ? $line_infos['credit'] : -$line_infos['debit']);
438 
439  // Check lettering code
440  if ($unlettering) {
441  if (isset($lettering_code) && $lettering_code != $line_infos['lettering_code']) {
442  $this->errors[] = $langs->trans('AccountancyErrorMismatchLetteringCode');
443  $group_error++;
444  break;
445  }
446  if (!isset($lettering_code)) $lettering_code = (string) $line_infos['lettering_code'];
447  if (!empty($line_infos['lettering_code'])) $do_it = true;
448  } elseif (!empty($line_infos['lettering_code'])) $do_it = false;
449  }
450 
451  // Check balance amount
452  if (!$group_error && !$unlettering && price2num($total) != 0) {
453  $this->errors[] = $langs->trans('AccountancyErrorMismatchBalanceAmount', $total);
454  $group_error++;
455  }
456 
457  // Lettering/Unlettering the group of bookkeeping lines
458  if (!$group_error && $do_it) {
459  if ($unlettering) $result = $this->deleteLettering($bookkeeping_lines);
460  else $result = $this->updateLettering($bookkeeping_lines);
461  if ($result < 0) {
462  $group_error++;
463  } elseif ($result > 0) {
464  $nb_lettering++;
465  }
466  }
467 
468  if ($group_error) {
469  $this->errors[] = $langs->trans('AccountancyErrorLetteringBookkeeping', implode(', ', $piece_num_lines));
470  $error++;
471  }
472  }
473 
474  if ($error) {
475  return -2 - $nb_lettering;
476  } else {
477  return $nb_lettering;
478  }
479  }
480 
488  public function getLinkedLines($bookkeeping_ids, $type = 'customer_invoice')
489  {
490  global $conf, $langs;
491  $this->errors = array();
492 
493  // Clean parameters
494  $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
495  $type = trim($type);
496 
497  if ($type == 'customer_invoice') {
498  $doc_type = 'customer_invoice';
499  $bank_url_type = 'payment';
500  $payment_element = 'paiement_facture';
501  $fk_payment_element = 'fk_paiement';
502  $fk_element = 'fk_facture';
503  $account_number = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
504  } elseif ($type == 'supplier_invoice') {
505  $doc_type = 'supplier_invoice';
506  $bank_url_type = 'payment_supplier';
507  $payment_element = 'paiementfourn_facturefourn';
508  $fk_payment_element = 'fk_paiementfourn';
509  $fk_element = 'fk_facturefourn';
510  $account_number = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
511  } else {
512  $langs->load('errors');
513  $this->errors[] = $langs->trans('ErrorBadParameters');
514  return -1;
515  }
516 
517  $payment_ids = array();
518 
519  // Get all payment id from bank lines
520  $sql = "SELECT DISTINCT bu.url_id AS payment_id";
521  $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
522  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc";
523  $sql .= " WHERE ab.doc_type = 'bank'";
524  // $sql .= " AND ab.subledger_account != ''";
525  // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
526  $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
527  if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
528 
529  dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
530  $resql = $this->db->query($sql);
531  if (!$resql) {
532  $this->errors[] = "Error " . $this->db->lasterror();
533  return -1;
534  }
535 
536  while ($obj = $this->db->fetch_object($resql)) {
537  $payment_ids[$obj->payment_id] = $obj->payment_id;
538  }
539  $this->db->free($resql);
540 
541  // Get all payment id from payment lines
542  $sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id";
543  $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
544  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc";
545  $sql .= " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'";
546  // $sql .= " AND ab.subledger_account != ''";
547  // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
548  $sql .= " AND pe.$fk_payment_element IS NOT NULL";
549  if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
550 
551  dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
552  $resql = $this->db->query($sql);
553  if (!$resql) {
554  $this->errors[] = "Error " . $this->db->lasterror();
555  return -1;
556  }
557 
558  while ($obj = $this->db->fetch_object($resql)) {
559  $payment_ids[$obj->payment_id] = $obj->payment_id;
560  }
561  $this->db->free($resql);
562 
563  if (empty($payment_ids)) {
564  return array();
565  }
566 
567  // Get all payments linked by group
568  $payment_by_group = $this->getLinkedPaymentByGroup($payment_ids, $type);
569 
570  $groups = array();
571  foreach ($payment_by_group as $payment_list) {
572  $lines = array();
573 
574  // Get bank lines
575  $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
576  $sql .= " FROM " . MAIN_DB_PREFIX . "bank_url AS bu";
577  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank";
578  $sql .= " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
579  $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
580  $sql .= " AND ab.doc_type = 'bank'";
581  $sql .= " AND ab.subledger_account != ''";
582  $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
583 
584  dol_syslog(__METHOD__ . " - Get bank lines", LOG_DEBUG);
585  $resql = $this->db->query($sql);
586  if (!$resql) {
587  $this->errors[] = "Error " . $this->db->lasterror();
588  return -1;
589  }
590 
591  while ($obj = $this->db->fetch_object($resql)) {
592  $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
593  }
594  $this->db->free($resql);
595 
596  // Get payment lines
597  $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
598  $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
599  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element";
600  $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
601  $sql .= " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'";
602  $sql .= " AND ab.subledger_account != ''";
603  $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
604 
605  dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
606  $resql = $this->db->query($sql);
607  if (!$resql) {
608  $this->errors[] = "Error " . $this->db->lasterror();
609  return -1;
610  }
611 
612  while ($obj = $this->db->fetch_object($resql)) {
613  $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
614  }
615  $this->db->free($resql);
616 
617  if (!empty($lines)) {
618  $groups[] = $lines;
619  }
620  }
621 
622  return $groups;
623  }
624 
632  public function getLinkedPaymentByGroup($payment_ids, $type)
633  {
634  global $langs;
635 
636  // Clean parameters
637  $payment_ids = is_array($payment_ids) ? $payment_ids : array();
638  $type = trim($type);
639 
640  if (empty($payment_ids)) {
641  return array();
642  }
643 
644  if ($type == 'customer_invoice') {
645  $payment_element = 'paiement_facture';
646  $fk_payment_element = 'fk_paiement';
647  $fk_element = 'fk_facture';
648  } elseif ($type == 'supplier_invoice') {
649  $payment_element = 'paiementfourn_facturefourn';
650  $fk_payment_element = 'fk_paiementfourn';
651  $fk_element = 'fk_facturefourn';
652  } else {
653  $langs->load('errors');
654  $this->errors[] = $langs->trans('ErrorBadParameters');
655  return -1;
656  }
657 
658  // Get payment lines
659  $sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element";
660  $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
661  $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element";
662  $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")";
663 
664  dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
665  $resql = $this->db->query($sql);
666  if (!$resql) {
667  $this->errors[] = "Error " . $this->db->lasterror();
668  return -1;
669  }
670 
671  $current_payment_ids = array();
672  $payment_by_element = array();
673  $element_by_payment = array();
674  while ($obj = $this->db->fetch_object($resql)) {
675  $current_payment_ids[$obj->$fk_payment_element] = $obj->$fk_payment_element;
676  $element_by_payment[$obj->$fk_payment_element][$obj->$fk_element] = $obj->$fk_element;
677  $payment_by_element[$obj->$fk_element][$obj->$fk_payment_element] = $obj->$fk_payment_element;
678  }
679  $this->db->free($resql);
680 
681  if (count(array_diff($payment_ids, $current_payment_ids))) {
682  return $this->getLinkedPaymentByGroup($current_payment_ids, $type);
683  }
684 
685  return $this->getGroupElements($payment_by_element, $element_by_payment);
686  }
687 
697  public function getGroupElements(&$payment_by_element, &$element_by_payment, $element_id = 0, &$current_group = array())
698  {
699  $grouped_payments = array();
700  if ($element_id > 0 && !isset($payment_by_element[$element_id])) {
701  // Return if specific element id not found
702  return $grouped_payments;
703  }
704 
705  $save_payment_by_element = null;
706  $save_element_by_payment = null;
707  if ($element_id == 0) {
708  // Save list when is the begin of recursive function
709  $save_payment_by_element = $payment_by_element;
710  $save_element_by_payment = $element_by_payment;
711  }
712 
713  do {
714  // Get current element id, get this payment id list and delete the entry
715  $current_element_id = $element_id > 0 ? $element_id : array_keys($payment_by_element)[0];
716  $payment_ids = $payment_by_element[$current_element_id];
717  unset($payment_by_element[$current_element_id]);
718 
719  foreach ($payment_ids as $payment_id) {
720  // Continue if payment id in not found
721  if (!isset($element_by_payment[$payment_id])) continue;
722 
723  // Set the payment in the current group
724  $current_group[$payment_id] = $payment_id;
725 
726  // Get current element ids, get this payment id list and delete the entry
727  $element_ids = $element_by_payment[$payment_id];
728  unset($element_by_payment[$payment_id]);
729 
730  // Set payment id on the current group for each element id of the payment
731  foreach ($element_ids as $id) {
732  $this->getGroupElements($payment_by_element, $element_by_payment, $id, $current_group);
733  }
734  }
735 
736  if ($element_id == 0) {
737  // Save current group and reset the current group when is the begin of recursive function
738  $grouped_payments[] = $current_group;
739  $current_group = array();
740  }
741  } while (!empty($payment_by_element) && $element_id == 0);
742 
743  if ($element_id == 0) {
744  // Restore list when is the begin of recursive function
745  $payment_by_element = $save_payment_by_element;
746  $element_by_payment = $save_element_by_payment;
747  }
748 
749  return $grouped_payments;
750  }
751 }
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:48
db
$conf db
API class for accounts.
Definition: inc.php:41
Lettering\letteringThirdparty
letteringThirdparty($socid)
letteringThirdparty
Definition: lettering.class.php:48
Lettering\updateLettering
updateLettering($ids=array(), $notrigger=false)
Definition: lettering.class.php:247
Lettering\bookkeepingLetteringAll
bookkeepingLetteringAll($bookkeeping_ids, $unlettering=false)
Lettering bookkeeping lines all types.
Definition: lettering.class.php:372
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
Lettering\deleteLettering
deleteLettering($ids, $notrigger=false)
Definition: lettering.class.php:336
Lettering\getLinkedPaymentByGroup
getLinkedPaymentByGroup($payment_ids, $type)
Linked payment by group.
Definition: lettering.class.php:632
BookKeeping
Class to manage Ledger (General Ledger and Subledger)
Definition: bookkeeping.class.php:33
Lettering
Class Lettering.
Definition: lettering.class.php:34
Lettering\getLinkedLines
getLinkedLines($bookkeeping_ids, $type='customer_invoice')
Lettering bookkeeping lines.
Definition: lettering.class.php:488
Lettering\bookkeepingLettering
bookkeepingLettering($bookkeeping_ids, $type='customer_invoice', $unlettering=false)
Lettering bookkeeping lines.
Definition: lettering.class.php:414
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2845
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
Lettering\getGroupElements
getGroupElements(&$payment_by_element, &$element_by_payment, $element_id=0, &$current_group=array())
Get payment ids grouped by payment id and element id in common.
Definition: lettering.class.php:697