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";
36 public static $doc_type_infos = array(
37 'customer_invoice' => array(
38 'payment_table' =>
'paiement',
39 'payment_table_fk_bank' =>
'fk_bank',
40 'doc_payment_table' =>
'paiement_facture',
41 'doc_payment_table_fk_payment' =>
'fk_paiement',
42 'doc_payment_table_fk_doc' =>
'fk_facture',
43 'linked_info' => array(
45 'table' =>
'paiement_facture',
46 'fk_doc' =>
'fk_facture',
47 'fk_link' =>
'fk_paiement',
51 'table' =>
'societe_remise_except',
52 'fk_doc' =>
'fk_facture_source',
53 'fk_link' =>
'fk_facture',
55 'is_fk_link_is_also_fk_doc' =>
true,
59 'supplier_invoice' => array(
60 'payment_table' =>
'paiementfourn',
61 'payment_table_fk_bank' =>
'fk_bank',
62 'doc_payment_table' =>
'paiementfourn_facturefourn',
63 'doc_payment_table_fk_payment' =>
'fk_paiementfourn',
64 'doc_payment_table_fk_doc' =>
'fk_facturefourn',
65 'linked_info' => array(
67 'table' =>
'paiementfourn_facturefourn',
68 'fk_doc' =>
'fk_facturefourn',
69 'fk_link' =>
'fk_paiementfourn',
73 'table' =>
'societe_remise_except',
74 'fk_doc' =>
'fk_invoice_supplier_source',
75 'fk_link' =>
'fk_invoice_supplier',
77 'is_fk_link_is_also_fk_doc' =>
true,
95 $object =
new Societe($this->db);
97 $object->fetch($socid);
100 if ($object->code_compta ==
'411CUSTCODE') {
101 $object->code_compta =
'';
104 if ($object->code_compta_fournisseur ==
'401SUPPCODE') {
105 $object->code_compta_fournisseur =
'';
111 $sql =
"SELECT DISTINCT bk.rowid, bk.doc_date, bk.doc_type, bk.doc_ref, bk.subledger_account, ";
112 $sql .=
" bk.numero_compte , bk.label_compte, bk.debit , bk.credit, bk.montant ";
113 $sql .=
" , bk.sens , bk.code_journal , bk.piece_num, bk.date_lettering, bu.url_id , bu.type ";
114 $sql .=
" FROM ".MAIN_DB_PREFIX.
"accounting_bookkeeping as bk";
115 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"bank_url as bu ON(bk.fk_doc = bu.fk_bank AND bu.type IN ('payment', 'payment_supplier') ) ";
117 if ($object->code_compta !=
"") {
118 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta).
"' ";
120 if ($object->code_compta !=
"" && $object->code_compta_fournisseur !=
"") {
123 if ($object->code_compta_fournisseur !=
"") {
124 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur).
"' ";
127 $sql .=
" ) AND (bk.date_lettering ='' OR bk.date_lettering IS NULL) ";
128 $sql .=
" AND (bk.lettering_code != '' OR bk.lettering_code IS NULL) ";
129 $sql .=
' AND bk.date_validated IS NULL ';
130 $sql .= $this->db->order(
'bk.doc_date',
'DESC');
134 $resql = $this->db->query(
$sql);
136 $num = $this->db->num_rows($resql);
138 while ($obj = $this->db->fetch_object($resql)) {
142 if ($obj->type ==
'payment_supplier') {
143 $sql =
'SELECT DISTINCT bk.rowid, facf.ref, facf.ref_supplier, payf.fk_bank, facf.rowid as fact_id';
144 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture_fourn facf ";
145 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"paiementfourn_facturefourn as payfacf ON payfacf.fk_facturefourn=facf.rowid";
146 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"paiementfourn as payf ON payfacf.fk_paiementfourn=payf.rowid";
147 $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).
"')";
148 $sql .=
" WHERE payfacf.fk_paiementfourn = '".$this->db->escape($obj->url_id).
"' ";
149 $sql .=
" AND facf.entity = ".$conf->entity;
150 $sql .=
" AND code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX.
"accounting_journal WHERE nature=4 AND entity=".$conf->entity.
") ";
152 if ($object->code_compta !=
"") {
153 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta).
"' ";
155 if ($object->code_compta !=
"" && $object->code_compta_fournisseur !=
"") {
158 if ($object->code_compta_fournisseur !=
"") {
159 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur).
"' ";
163 $resql2 = $this->db->query(
$sql);
165 while ($obj2 = $this->db->fetch_object($resql2)) {
166 $ids[$obj2->rowid] = $obj2->rowid;
167 $ids_fact[] = $obj2->fact_id;
169 $this->db->free($resql2);
171 $this->errors[] = $this->db->lasterror;
174 if (count($ids_fact)) {
175 $sql =
'SELECT bk.rowid, facf.ref, facf.ref_supplier ';
176 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture_fourn facf ";
177 $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)).
"))";
178 $sql .=
" WHERE bk.code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX.
"accounting_journal WHERE nature=3 AND entity=".$conf->entity.
") ";
179 $sql .=
" AND facf.entity = ".$conf->entity;
181 if ($object->code_compta !=
"") {
182 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta).
"' ";
184 if ($object->code_compta !=
"" && $object->code_compta_fournisseur !=
"") {
187 if ($object->code_compta_fournisseur !=
"") {
188 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur).
"' ";
192 $resql2 = $this->db->query(
$sql);
194 while ($obj2 = $this->db->fetch_object($resql2)) {
195 $ids[$obj2->rowid] = $obj2->rowid;
197 $this->db->free($resql2);
199 $this->errors[] = $this->db->lasterror;
203 } elseif ($obj->type ==
'payment') {
204 $sql =
'SELECT DISTINCT bk.rowid, fac.ref, fac.ref, pay.fk_bank, fac.rowid as fact_id';
205 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture fac ";
206 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"paiement_facture as payfac ON payfac.fk_facture=fac.rowid";
207 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"paiement as pay ON payfac.fk_paiement=pay.rowid";
208 $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).
"')";
209 $sql .=
" WHERE payfac.fk_paiement = '".$this->db->escape($obj->url_id).
"' ";
210 $sql .=
" AND bk.code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX.
"accounting_journal WHERE nature=4 AND entity=".$conf->entity.
") ";
211 $sql .=
" AND fac.entity IN (".getEntity(
'invoice', 0).
")";
213 if ($object->code_compta !=
"") {
214 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta).
"' ";
216 if ($object->code_compta !=
"" && $object->code_compta_fournisseur !=
"") {
219 if ($object->code_compta_fournisseur !=
"") {
220 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur).
"' ";
224 $resql2 = $this->db->query(
$sql);
226 while ($obj2 = $this->db->fetch_object($resql2)) {
227 $ids[$obj2->rowid] = $obj2->rowid;
228 $ids_fact[] = $obj2->fact_id;
231 $this->errors[] = $this->db->lasterror;
234 if (count($ids_fact)) {
235 $sql =
'SELECT bk.rowid, fac.ref, fac.ref_supplier ';
236 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture fac ";
237 $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)).
"))";
238 $sql .=
" WHERE code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX.
"accounting_journal WHERE nature=2 AND entity=".$conf->entity.
") ";
239 $sql .=
" AND fac.entity IN (".getEntity(
'invoice', 0).
")";
241 if ($object->code_compta !=
"") {
242 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta).
"' ";
244 if ($object->code_compta !=
"" && $object->code_compta_fournisseur !=
"") {
247 if ($object->code_compta_fournisseur !=
"") {
248 $sql .=
" bk.subledger_account = '".$this->db->escape($object->code_compta_fournisseur).
"' ";
252 $resql2 = $this->db->query(
$sql);
254 while ($obj2 = $this->db->fetch_object($resql2)) {
255 $ids[$obj2->rowid] = $obj2->rowid;
257 $this->db->free($resql2);
259 $this->errors[] = $this->db->lasterror;
265 if (count($ids) > 1) {
269 $this->db->free($resql);
272 foreach ($this->errors as $errmsg) {
274 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
293 $sql =
"SELECT DISTINCT ab2.lettering_code";
294 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS ab";
295 $sql .=
" LEFT JOIN " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS ab2 ON ab2.subledger_account = ab.subledger_account";
296 $sql .=
" WHERE ab.rowid IN (" . $this->db->sanitize(implode(
',', $ids)) .
")";
297 $sql .=
" AND ab2.lettering_code != ''";
298 $sql .=
" ORDER BY ab2.lettering_code DESC";
301 $resqla = $this->db->query(
$sql);
303 $obj = $this->db->fetch_object($resqla);
304 $lettre = (empty($obj->lettering_code) ? $lettre : $obj->lettering_code);
305 if (!empty($obj->lettering_code)) {
308 $this->db->free($resqla);
310 $this->errors[] =
'Error'.$this->db->lasterror();
314 $sql =
"SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX.
"accounting_bookkeeping WHERE ";
315 $sql .=
" rowid IN (".$this->db->sanitize(implode(
',', $ids)).
") AND lettering_code IS NULL AND subledger_account != ''";
316 $resqlb = $this->db->query(
$sql);
318 $obj = $this->db->fetch_object($resqlb);
319 if (!(round(abs($obj->deb), 2) === round(abs($obj->cred), 2))) {
320 $this->errors[] =
'Total not exacts '.round(abs($obj->deb), 2).
' vs '.round(abs($obj->cred), 2);
323 $this->db->free($resqlb);
325 $this->errors[] =
'Erreur sql'.$this->db->lasterror();
335 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"accounting_bookkeeping SET";
336 $sql .=
" lettering_code='".$this->db->escape($lettre).
"'";
337 $sql .=
", date_lettering = '".$this->db->idate($now).
"'";
338 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $ids)).
") AND lettering_code IS NULL AND subledger_account != ''";
340 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
341 $resql = $this->db->query(
$sql);
344 $this->errors[] =
"Error ".$this->db->lasterror();
346 $affected_rows = $this->db->affected_rows($resql);
352 foreach ($this->errors as $errmsg) {
353 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
354 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
358 return $affected_rows;
372 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"accounting_bookkeeping SET";
373 $sql .=
" lettering_code = NULL";
374 $sql .=
", date_lettering = NULL";
375 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $ids)).
")";
376 $sql .=
" AND subledger_account != ''";
378 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
379 $resql = $this->db->query(
$sql);
382 $this->errors[] =
"Error ".$this->db->lasterror();
387 foreach ($this->errors as $errmsg) {
388 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
389 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
393 return $this->db->affected_rows($resql);
415 $errors = array_merge($errors, $this->errors);
416 $nb_lettering += abs($result) - 2;
418 $nb_lettering += $result;
422 $this->errors = $errors;
423 return -2 - $nb_lettering;
425 return $nb_lettering;
440 $this->errors = array();
443 $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
448 if (!is_array($grouped_lines)) {
452 foreach ($grouped_lines as $lines) {
455 $do_it = !$unlettering;
456 $lettering_code =
null;
457 $piece_num_lines = array();
458 $bookkeeping_lines = array();
459 foreach ($lines as $line_infos) {
460 $bookkeeping_lines[$line_infos[
'id']] = $line_infos[
'id'];
461 $piece_num_lines[$line_infos[
'piece_num']] = $line_infos[
'piece_num'];
462 $total += ($line_infos[
'credit'] > 0 ? $line_infos[
'credit'] : -$line_infos[
'debit']);
466 if (isset($lettering_code) && $lettering_code != $line_infos[
'lettering_code']) {
467 $this->errors[] = $langs->trans(
'AccountancyErrorMismatchLetteringCode');
471 if (!isset($lettering_code)) $lettering_code = (
string) $line_infos[
'lettering_code'];
472 if (!empty($line_infos[
'lettering_code'])) $do_it =
true;
473 } elseif (!empty($line_infos[
'lettering_code'])) $do_it =
false;
477 if (!$group_error && !$unlettering &&
price2num($total) != 0) {
478 $this->errors[] = $langs->trans(
'AccountancyErrorMismatchBalanceAmount', $total);
483 if (!$group_error && $do_it) {
484 if ($unlettering) $result = $this->
deleteLettering($bookkeeping_lines);
488 } elseif ($result > 0) {
494 $this->errors[] = $langs->trans(
'AccountancyErrorLetteringBookkeeping', implode(
', ', $piece_num_lines));
500 return -2 - $nb_lettering;
502 return $nb_lettering;
513 public function getLinkedLines($bookkeeping_ids, $only_has_subledger_account =
true)
515 global $conf, $langs;
516 $this->errors = array();
519 $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
522 $sql =
"SELECT DISTINCT ab.doc_type, ab.fk_doc";
523 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS ab";
524 $sql .=
" WHERE ab.entity IN (" .
getEntity(
'accountancy') .
")";
525 $sql .=
" AND ab.fk_doc > 0";
526 if (!empty($bookkeeping_ids)) {
528 $sql .=
" AND EXISTS (";
529 $sql .=
" SELECT rowid";
530 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS pn";
531 $sql .=
" WHERE pn.entity IN (" .
getEntity(
'accountancy') .
")";
532 $sql .=
" AND pn.rowid IN (" . $this->db->sanitize(implode(
',', $bookkeeping_ids)) .
")";
533 $sql .=
" AND pn.piece_num = ab.piece_num";
536 if ($only_has_subledger_account)
$sql .=
" AND ab.subledger_account != ''";
538 dol_syslog(__METHOD__ .
" - Get all bookkeeping lines", LOG_DEBUG);
539 $resql = $this->db->query(
$sql);
541 $this->errors[] =
"Error " . $this->db->lasterror();
545 $bookkeeping_lines_by_type = array();
546 while ($obj = $this->db->fetch_object($resql)) {
547 $bookkeeping_lines_by_type[$obj->doc_type][$obj->fk_doc] = $obj->fk_doc;
549 $this->db->free($resql);
551 if (empty($bookkeeping_lines_by_type)) {
555 if (!empty($bookkeeping_lines_by_type[
'bank'])) {
557 if (!is_array($new_bookkeeping_lines_by_type)) {
560 foreach ($new_bookkeeping_lines_by_type as $doc_type => $fk_docs) {
561 foreach ($fk_docs as $fk_doc) {
562 $bookkeeping_lines_by_type[$doc_type][$fk_doc] = $fk_doc;
567 $grouped_lines = array();
568 foreach (self::$doc_type_infos as $doc_type => $doc_type_info) {
569 if (!is_array($bookkeeping_lines_by_type[$doc_type])) {
575 if (!is_array($doc_grouped)) {
580 foreach ($doc_grouped as $doc_ids) {
582 if (!is_array($bank_ids)) {
587 $sql =
"SELECT DISTINCT ab.rowid, ab.piece_num, ab.debit, ab.credit, ab.lettering_code";
588 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS ab";
589 $sql .=
" WHERE ab.entity IN (" .
getEntity(
'accountancy') .
")";
591 if (!empty($bank_ids)) {
593 $sql .=
" SELECT bpn.rowid";
594 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS bpn";
595 $sql .=
" WHERE bpn.entity IN (" .
getEntity(
'accountancy') .
")";
596 $sql .=
" AND bpn.doc_type = 'bank'";
597 $sql .=
" AND bpn.fk_doc IN (" . $this->db->sanitize(implode(
',', $bank_ids)) .
")";
598 $sql .=
" AND bpn.piece_num = ab.piece_num";
602 $sql .=
" SELECT dpn.rowid";
603 $sql .=
" FROM " . MAIN_DB_PREFIX .
"accounting_bookkeeping AS dpn";
604 $sql .=
" WHERE dpn.entity IN (" .
getEntity(
'accountancy') .
")";
605 $sql .=
" AND dpn.doc_type = '" . $this->db->escape($doc_type) .
"'";
606 $sql .=
" AND dpn.fk_doc IN (" . $this->db->sanitize(implode(
',', $doc_ids)) .
")";
607 $sql .=
" AND dpn.piece_num = ab.piece_num";
610 if ($only_has_subledger_account)
$sql .=
" AND ab.subledger_account != ''";
612 dol_syslog(__METHOD__ .
" - Get all bookkeeping lines linked", LOG_DEBUG);
613 $resql = $this->db->query(
$sql);
615 $this->errors[] =
"Error " . $this->db->lasterror();
620 while ($obj = $this->db->fetch_object($resql)) {
621 $group[$obj->rowid] = array(
623 'piece_num' => $obj->piece_num,
624 'debit' => $obj->debit,
625 'credit' => $obj->credit,
626 'lettering_code' => $obj->lettering_code,
629 $this->db->free($resql);
631 if (!empty($group)) $grouped_lines[] = $group;
635 return $grouped_lines;
646 dol_syslog(__METHOD__ .
" - bank_ids=".json_encode($bank_ids), LOG_DEBUG);
649 $bank_ids = is_array($bank_ids) ? $bank_ids : array();
651 if (empty($bank_ids)) {
655 $bookkeeping_lines_by_type = array();
656 foreach (self::$doc_type_infos as $doc_type => $doc_type_info) {
658 $sql =
"SELECT DISTINCT dp." . $doc_type_info[
'doc_payment_table_fk_doc'] .
" AS fk_doc";
659 $sql .=
" FROM " . MAIN_DB_PREFIX . $doc_type_info[
'payment_table'] .
" AS p";
660 $sql .=
" LEFT JOIN " . MAIN_DB_PREFIX . $doc_type_info[
'doc_payment_table'] .
" AS dp ON dp." . $doc_type_info[
'doc_payment_table_fk_payment'] .
" = p.rowid";
661 $sql .=
" WHERE p." . $doc_type_info[
'payment_table_fk_bank'] .
" IN (" . $this->db->sanitize(implode(
',', $bank_ids)) .
")";
662 $sql .=
" AND dp." . $doc_type_info[
'doc_payment_table_fk_doc'] .
" > 0";
664 dol_syslog(__METHOD__ .
" - Get all fk_doc by doc_type from list of bank ids for '" . $doc_type .
"'", LOG_DEBUG);
665 $resql = $this->db->query(
$sql);
667 $this->errors[] =
"Error " . $this->db->lasterror();
671 while ($obj = $this->db->fetch_object($resql)) {
672 $bookkeeping_lines_by_type[$doc_type][$obj->fk_doc] = $obj->fk_doc;
674 $this->db->free($resql);
677 return $bookkeeping_lines_by_type;
691 dol_syslog(__METHOD__ .
" - bank_ids=".json_encode($document_ids) .
", doc_type=$doc_type", LOG_DEBUG);
694 $document_ids = is_array($document_ids) ? $document_ids : array();
696 $document_ids = array_filter($document_ids);
698 $doc_type = trim($doc_type);
700 if (empty($document_ids)) {
703 if (!is_array(self::$doc_type_infos[$doc_type])) {
704 $langs->load(
'errors');
705 $this->errors[] = $langs->trans(
'ErrorBadParameters');
709 $doc_type_info = self::$doc_type_infos[$doc_type];
713 $sql =
"SELECT DISTINCT p." . $doc_type_info[
'payment_table_fk_bank'] .
" AS fk_doc";
714 $sql .=
" FROM " . MAIN_DB_PREFIX . $doc_type_info[
'payment_table'] .
" AS p";
715 $sql .=
" LEFT JOIN " . MAIN_DB_PREFIX . $doc_type_info[
'doc_payment_table'] .
" AS dp ON dp." . $doc_type_info[
'doc_payment_table_fk_payment'] .
" = p.rowid";
716 $sql .=
" WHERE dp." . $doc_type_info[
'doc_payment_table_fk_doc'] .
" IN (" . $this->db->sanitize(implode(
',', $document_ids)) .
")";
717 $sql .=
" AND p." . $doc_type_info[
'payment_table_fk_bank'] .
" > 0";
719 dol_syslog(__METHOD__ .
" - Get all bank ids from list of document ids of a type '" . $doc_type .
"'", LOG_DEBUG);
720 $resql = $this->db->query(
$sql);
722 $this->errors[] =
"Error " . $this->db->lasterror();
726 while ($obj = $this->db->fetch_object($resql)) {
727 $bank_ids[$obj->fk_doc] = $obj->fk_doc;
729 $this->db->free($resql);
746 $document_ids = is_array($document_ids) ? $document_ids : array();
747 $doc_type = trim($doc_type);
749 $document_ids = array_filter($document_ids);
751 if (empty($document_ids)) {
755 if (!is_array(self::$doc_type_infos[$doc_type])) {
756 $langs->load(
'errors');
757 $this->errors[] = $langs->trans(
'ErrorBadParameters');
761 $doc_type_info = self::$doc_type_infos[$doc_type];
764 $current_document_ids = array();
765 $link_by_element = array();
766 $element_by_link = array();
767 foreach ($doc_type_info[
'linked_info'] as $linked_info) {
768 $sql =
"SELECT DISTINCT tl2." . $linked_info[
'fk_link'] .
" AS fk_link, tl2." . $linked_info[
'fk_doc'] .
" AS fk_doc";
769 $sql .=
" FROM " . MAIN_DB_PREFIX . $linked_info[
'table'] .
" AS tl";
770 $sql .=
" LEFT JOIN " . MAIN_DB_PREFIX . $linked_info[
'table'] .
" AS tl2 ON tl2." . $linked_info[
'fk_link'] .
" = tl." . $linked_info[
'fk_link'];
771 $sql .=
" WHERE tl." . $linked_info[
'fk_doc'] .
" IN (" . $this->db->sanitize(implode(
',', $document_ids)) .
")";
773 dol_syslog(__METHOD__ .
" - Get document lines", LOG_DEBUG);
774 $resql = $this->db->query(
$sql);
776 $this->errors[] =
"Error " . $this->db->lasterror();
780 $is_fk_link_is_also_fk_doc = !empty($linked_info[
'is_fk_link_is_also_fk_doc']);
781 while ($obj = $this->db->fetch_object($resql)) {
782 $current_document_ids[$obj->fk_doc] = $obj->fk_doc;
784 $link_key = $linked_info[
'prefix'] . $obj->fk_link;
785 $element_by_link[$link_key][$obj->fk_doc] = $obj->fk_doc;
786 $link_by_element[$obj->fk_doc][$link_key] = $link_key;
787 if ($is_fk_link_is_also_fk_doc) {
788 $element_by_link[$link_key][$obj->fk_link] = $obj->fk_link;
789 $link_by_element[$obj->fk_link][$link_key] = $link_key;
792 $this->db->free($resql);
795 if (count(array_diff($document_ids, $current_document_ids))) {
811 public function getGroupElements(&$link_by_element, &$element_by_link, $link_key =
'', &$current_group = array())
813 $grouped_elements = array();
814 if (!empty($link_key) && !isset($element_by_link[$link_key])) {
816 return $grouped_elements;
819 if (empty($link_key)) {
821 $save_link_by_element = $link_by_element;
822 $save_element_by_link = $element_by_link;
827 $current_link_key = !empty($link_key) ? $link_key : array_keys($element_by_link)[0];
828 $element_ids = $element_by_link[$current_link_key];
829 unset($element_by_link[$current_link_key]);
831 foreach ($element_ids as $element_id) {
833 if (!isset($link_by_element[$element_id]))
continue;
836 $current_group[$element_id] = $element_id;
839 $link_keys = $link_by_element[$element_id];
840 unset($link_by_element[$element_id]);
843 foreach ($link_keys as $key) {
844 $this->
getGroupElements($link_by_element, $element_by_link, $key, $current_group);
848 if (empty($link_key)) {
850 $grouped_elements[] = $current_group;
851 $current_group = array();
853 }
while (!empty($element_by_link) && empty($link_key));
855 if (empty($link_key)) {
857 $link_by_element = $save_link_by_element;
858 $element_by_link = $save_element_by_link;
861 return $grouped_elements;