dolibarr  16.0.1
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 
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 
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 
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 
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 
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 
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 
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  $save_payment_by_element = null;
703  $save_element_by_payment = null;
704  if ($element_id == 0) {
705  // Save list when is the begin of recursive function
706  $save_payment_by_element = $payment_by_element;
707  $save_element_by_payment = $element_by_payment;
708  }
709 
710  do {
711  // Get current element id, get this payment id list and delete the entry
712  $current_element_id = $element_id > 0 ? $element_id : array_keys($payment_by_element)[0];
713  $payment_ids = $payment_by_element[$current_element_id];
714  unset($payment_by_element[$current_element_id]);
715 
716  foreach ($payment_ids as $payment_id) {
717  // Continue if payment id in not found
718  if (!isset($element_by_payment[$payment_id])) continue;
719 
720  // Set the payment in the current group
721  $current_group[$payment_id] = $payment_id;
722 
723  // Get current element ids, get this payment id list and delete the entry
724  $element_ids = $element_by_payment[$payment_id];
725  unset($element_by_payment[$payment_id]);
726 
727  // Set payment id on the current group for each element id of the payment
728  foreach ($element_ids as $id) {
729  $this->getGroupElements($payment_by_element, $element_by_payment, $id, $current_group);
730  }
731  }
732 
733  if ($element_id == 0) {
734  // Save current group and reset the current group when is the begin of recursive function
735  $grouped_payments[] = $current_group;
736  $current_group = array();
737  }
738  } while (!empty($payment_by_element) && $element_id == 0);
739 
740  if ($element_id == 0) {
741  // Restore list when is the begin of recursive function
742  $payment_by_element = $save_payment_by_element;
743  $element_by_payment = $save_element_by_payment;
744  }
745 
746  return $grouped_payments;
747  }
748 }
Class Lettering.
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.
$conf db
API class for accounts.
Definition: inc.php:41
dol_now($mode= 'auto')
Return date for now.
letteringThirdparty($socid)
letteringThirdparty
Class to manage Ledger (General Ledger and Subledger)
Class to manage third parties objects (customers, suppliers, prospects...)
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
bookkeepingLetteringAll($bookkeeping_ids, $unlettering=false)
Lettering bookkeeping lines all types.
updateLettering($ids=array(), $notrigger=false)
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
getLinkedLines($bookkeeping_ids, $type= 'customer_invoice')
Lettering bookkeeping lines.
bookkeepingLettering($bookkeeping_ids, $type= 'customer_invoice', $unlettering=false)
Lettering bookkeeping lines.
deleteLettering($ids, $notrigger=false)
getLinkedPaymentByGroup($payment_ids, $type)
Linked payment by group.