From ea8280af9854a81cc9b42bf641a676fd2a574b92 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 17 Nov 2021 17:32:17 +0100 Subject: [PATCH 01/23] FIX : status filter on supplierOrder stats doesn't work --- htdocs/commande/stats/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index bd92dc084c7..e92cd076928 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -95,12 +95,12 @@ dol_mkdir($dir); $stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0)); if ($mode == 'customer') { if ($object_status != '' && $object_status >= -1) { - $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.implode(',',$object_status).')'; } } if ($mode == 'supplier') { if ($object_status != '' && $object_status >= 0) { - $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.implode(',',$object_status).')'; } } From c5f6c617c91dce34eced356c7605f5a4cd5ff2b9 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 19 Nov 2021 08:34:45 +0000 Subject: [PATCH 02/23] Fixing style errors. --- htdocs/commande/stats/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index e92cd076928..4753666b2bc 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -95,12 +95,12 @@ dol_mkdir($dir); $stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0)); if ($mode == 'customer') { if ($object_status != '' && $object_status >= -1) { - $stats->where .= ' AND c.fk_statut IN ('.implode(',',$object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.implode(',', $object_status).')'; } } if ($mode == 'supplier') { if ($object_status != '' && $object_status >= 0) { - $stats->where .= ' AND c.fk_statut IN ('.implode(',',$object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.implode(',', $object_status).')'; } } From dc23c7f6a3a69ae11367d696cde8a46a587d08a7 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Fri, 19 Nov 2021 10:29:27 +0100 Subject: [PATCH 03/23] FIX : Travis --- htdocs/commande/stats/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index 4753666b2bc..c93c8888aa9 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -95,12 +95,12 @@ dol_mkdir($dir); $stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0)); if ($mode == 'customer') { if ($object_status != '' && $object_status >= -1) { - $stats->where .= ' AND c.fk_statut IN ('.implode(',', $object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.$db->escape(implode(',', $object_status)).')'; } } if ($mode == 'supplier') { if ($object_status != '' && $object_status >= 0) { - $stats->where .= ' AND c.fk_statut IN ('.implode(',', $object_status).')'; + $stats->where .= ' AND c.fk_statut IN ('.$db->escape(implode(',', $object_status)).')'; } } From 4246cd80f9cde7c61601b6e7cd6e0bf571ac9749 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 24 Nov 2021 16:27:01 +0100 Subject: [PATCH 04/23] FIX : Travis + Update dev --- htdocs/commande/stats/index.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index c93c8888aa9..307588adb32 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -46,7 +46,9 @@ if ($mode == 'supplier' && !$user->rights->fournisseur->commande->lire) { accessforbidden(); } -$object_status = GETPOST('object_status', 'intcomma'); +$object_status = GETPOST('object_status', 'array'); +$object_status = implode(',', $object_status); + $typent_id = GETPOST('typent_id', 'int'); $categ_id = GETPOST('categ_id', 'categ_id'); @@ -95,12 +97,12 @@ dol_mkdir($dir); $stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0)); if ($mode == 'customer') { if ($object_status != '' && $object_status >= -1) { - $stats->where .= ' AND c.fk_statut IN ('.$db->escape(implode(',', $object_status)).')'; + $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')'; } } if ($mode == 'supplier') { if ($object_status != '' && $object_status >= 0) { - $stats->where .= ' AND c.fk_statut IN ('.$db->escape(implode(',', $object_status)).')'; + $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')'; } } From 400f6b244b5ef91b2752a4e158eec0a7da1b6c0c Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 11 Jan 2022 17:29:02 +0100 Subject: [PATCH 05/23] FIX user actions rights when mulit-company transverse mode is enabled --- htdocs/user/card.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 28fcda3871d..79a55f1604e 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1905,7 +1905,7 @@ else } } - if ($caneditfield && (empty($conf->multicompany->enabled) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + if ($caneditfield && (empty($conf->multicompany->enabled) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { if (!empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) { @@ -1917,7 +1917,7 @@ else } } elseif ($caneditpassword && !$object->ldap_sid && - (empty($conf->multicompany->enabled) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + (empty($conf->multicompany->enabled) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { print ''; } @@ -1930,7 +1930,7 @@ else print ''; } elseif (($user->id != $id && $caneditpassword) && $object->login && !$object->ldap_sid && - ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { print ''; } @@ -1940,7 +1940,7 @@ else print ''; } elseif (($user->id != $id && $caneditpassword) && $object->login && !$object->ldap_sid && - ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { if ($object->email) print ''; else print ''; @@ -1949,13 +1949,13 @@ else // Enable user if ($user->id <> $id && $candisableuser && $object->statut == 0 && - ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { print ''; } // Disable user if ($user->id <> $id && $candisableuser && $object->statut == 1 && - ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { print ''; } @@ -1968,7 +1968,7 @@ else } // Delete if ($user->id <> $id && $candisableuser && - ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $conf->entity == 1))) + ((empty($conf->multicompany->enabled) && $object->entity == $user->entity) || !$user->entity || ($object->entity == $conf->entity) || ($conf->global->MULTICOMPANY_TRANSVERSE_MODE && $object->entity == 1))) { if ($user->admin || !$object->admin) // If user edited is admin, delete is possible on for an admin { From 146b432acfed10fd9b57e835de5c48da6e1952af Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 24 Feb 2022 11:07:31 +0100 Subject: [PATCH 06/23] FIX: PR returns --- htdocs/commande/stats/index.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index 307588adb32..19092e49a3c 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -45,9 +45,13 @@ if ($mode == 'customer' && !$user->rights->commande->lire) { if ($mode == 'supplier' && !$user->rights->fournisseur->commande->lire) { accessforbidden(); } +if($mode == 'supplier'){ + $object_status = GETPOST('object_status', 'array:int'); + $object_status = implode(',', $object_status); +} else { + $object_status = GETPOST('object_status', 'intcomma'); +} -$object_status = GETPOST('object_status', 'array'); -$object_status = implode(',', $object_status); $typent_id = GETPOST('typent_id', 'int'); $categ_id = GETPOST('categ_id', 'categ_id'); From fa4e6bd93a068a52f6123fecb3e9062761f8f8a4 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 24 Feb 2022 10:10:41 +0000 Subject: [PATCH 07/23] Fixing style errors. --- htdocs/commande/stats/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index 19092e49a3c..7d0f9fb5a3a 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -45,7 +45,7 @@ if ($mode == 'customer' && !$user->rights->commande->lire) { if ($mode == 'supplier' && !$user->rights->fournisseur->commande->lire) { accessforbidden(); } -if($mode == 'supplier'){ +if ($mode == 'supplier') { $object_status = GETPOST('object_status', 'array:int'); $object_status = implode(',', $object_status); } else { From 6cac982507056f0c401b63bf8894cd6bf7679ba4 Mon Sep 17 00:00:00 2001 From: kamel Date: Mon, 4 Apr 2022 10:32:17 +0200 Subject: [PATCH 08/23] FIX - Fix the adding of lines in the create invoice functions --- htdocs/compta/facture/class/facture.class.php | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 58da30ad205..fab80677c25 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -800,6 +800,10 @@ class Facture extends CommonInvoice $fk_parent_line = 0; } + // Complete vat rate with code + $vatrate = $newinvoiceline->tva_tx; + if ($newinvoiceline->vat_src_code && ! preg_match('/\(.*\)/', $vatrate)) $vatrate.=' ('.$newinvoiceline->vat_src_code.')'; + $newinvoiceline->fk_parent_line = $fk_parent_line; if ($this->type === Facture::TYPE_REPLACEMENT && $newinvoiceline->fk_remise_except) { @@ -810,7 +814,37 @@ class Facture extends CommonInvoice $newinvoiceline->fk_remise_except = $discountId; } - $result = $newinvoiceline->insert(); + $result = $this->addline( + $newinvoiceline->desc, + $newinvoiceline->subprice, + $newinvoiceline->qty, + $vatrate, + $newinvoiceline->localtax1_tx, + $newinvoiceline->localtax2_tx, + $newinvoiceline->fk_product, + $newinvoiceline->remise_percent, + $newinvoiceline->date_start, + $newinvoiceline->date_end, + $newinvoiceline->fk_code_ventilation, + $newinvoiceline->info_bits, + $newinvoiceline->fk_remise_except, + 'HT', + 0, + $newinvoiceline->product_type, + $newinvoiceline->rang, + $newinvoiceline->special_code, + $newinvoiceline->element, + $newinvoiceline->id, + $fk_parent_line, + $newinvoiceline->fk_fournprice, + $newinvoiceline->pa_ht, + $newinvoiceline->label, + $newinvoiceline->array_options, + $newinvoiceline->situation_percent, + $newinvoiceline->fk_prev_id, + $newinvoiceline->fk_unit, + $newinvoiceline->pu_ht_devise + ); // Defined the new fk_parent_line if ($result > 0 && $newinvoiceline->product_type == 9) { From 1fec350ccc42daf13415ed366bc191f9d8626381 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 4 Apr 2022 22:51:30 +0200 Subject: [PATCH 09/23] fix: Bad dirthday displayed date (d-1) in the Bithday Widget --- htdocs/core/boxes/box_birthdays.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_birthdays.php b/htdocs/core/boxes/box_birthdays.php index 62cfaa590ab..be0abcdfdde 100644 --- a/htdocs/core/boxes/box_birthdays.php +++ b/htdocs/core/boxes/box_birthdays.php @@ -119,7 +119,7 @@ class box_birthdays extends ModeleBoxes $this->info_box_contents[$line][] = array( 'td' => 'class="center nowraponall"', - 'text' => dol_print_date($dateb, "day", 'gmt').' - '.$age.' '.$langs->trans('DurationYears') + 'text' => dol_print_date($dateb, "day").' - '.$age.' '.$langs->trans('DurationYears') ); /*$this->info_box_contents[$line][] = array( From c4f0c60a11804662916cb84fb5a075b27d87267c Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 6 Apr 2022 09:19:56 +0200 Subject: [PATCH 10/23] FIX: Filter on Object Referent page give CRSF page --- htdocs/product/stats/bom.php | 1 + htdocs/product/stats/commande_fournisseur.php | 1 + htdocs/product/stats/contrat.php | 2 +- htdocs/product/stats/facture.php | 1 + htdocs/product/stats/facture_fournisseur.php | 1 + htdocs/product/stats/mo.php | 1 + htdocs/product/stats/propal.php | 1 + htdocs/product/stats/supplier_proposal.php | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/product/stats/bom.php b/htdocs/product/stats/bom.php index 52eec409185..5ab7a8f40a8 100644 --- a/htdocs/product/stats/bom.php +++ b/htdocs/product/stats/bom.php @@ -247,6 +247,7 @@ if ($id > 0 || !empty($ref)) { } print '
'."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php index fd64a1c0572..c7283399a43 100644 --- a/htdocs/product/stats/commande_fournisseur.php +++ b/htdocs/product/stats/commande_fournisseur.php @@ -198,6 +198,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/contrat.php b/htdocs/product/stats/contrat.php index cb7c84fc863..4c958a20370 100644 --- a/htdocs/product/stats/contrat.php +++ b/htdocs/product/stats/contrat.php @@ -183,7 +183,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; - + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php index b3e5571ac5a..da81f915b45 100644 --- a/htdocs/product/stats/facture.php +++ b/htdocs/product/stats/facture.php @@ -214,6 +214,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php index 212674582f9..e85801c8642 100644 --- a/htdocs/product/stats/facture_fournisseur.php +++ b/htdocs/product/stats/facture_fournisseur.php @@ -197,6 +197,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/mo.php b/htdocs/product/stats/mo.php index 5a5c33312ca..adfe989289e 100644 --- a/htdocs/product/stats/mo.php +++ b/htdocs/product/stats/mo.php @@ -176,6 +176,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/propal.php b/htdocs/product/stats/propal.php index b83d0368b75..096848d6205 100644 --- a/htdocs/product/stats/propal.php +++ b/htdocs/product/stats/propal.php @@ -199,6 +199,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } diff --git a/htdocs/product/stats/supplier_proposal.php b/htdocs/product/stats/supplier_proposal.php index d583d58bff8..a60261af115 100644 --- a/htdocs/product/stats/supplier_proposal.php +++ b/htdocs/product/stats/supplier_proposal.php @@ -198,6 +198,7 @@ if ($id > 0 || !empty($ref)) { } print ''."\n"; + print ''; if (!empty($sortfield)) { print ''; } From 798c7a8a0bdb1bba11c802b24d08a964d14b3431 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 6 Apr 2022 14:09:44 +0200 Subject: [PATCH 11/23] try with tzserver --- htdocs/core/boxes/box_birthdays.php | 2 +- htdocs/user/card.php | 8 ++++---- htdocs/user/class/user.class.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/boxes/box_birthdays.php b/htdocs/core/boxes/box_birthdays.php index be0abcdfdde..02c39c2f625 100644 --- a/htdocs/core/boxes/box_birthdays.php +++ b/htdocs/core/boxes/box_birthdays.php @@ -119,7 +119,7 @@ class box_birthdays extends ModeleBoxes $this->info_box_contents[$line][] = array( 'td' => 'class="center nowraponall"', - 'text' => dol_print_date($dateb, "day").' - '.$age.' '.$langs->trans('DurationYears') + 'text' => dol_print_date($dateb, "day", 'tzserver').' - '.$age.' '.$langs->trans('DurationYears') ); /*$this->info_box_contents[$line][] = array( diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 23437a7564c..ebb001e6ca9 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1255,7 +1255,7 @@ if ($action == 'create' || $action == 'adduserldap') { // Date birth print ''.$langs->trans("DateOfBirth").''; print ''; - print $form->selectDate($dateofbirth, 'dateofbirth', 0, 0, 1, 'createuser', 1, 0); + print $form->selectDate($dateofbirth, 'dateofbirth', 0, 0, 1, 'createuser', 1, 0, 0, '', 0, '', '', 1, '', '', 'tzserver'); print ''; print "\n"; @@ -1565,7 +1565,7 @@ if ($action == 'create' || $action == 'adduserldap') { // Date of birth print ''.$langs->trans("DateOfBirth").''; print ''; - print dol_print_date($object->birth, 'day'); + print dol_print_date($object->birth, 'day', 'tzserver'); print ''; print "\n"; @@ -2712,9 +2712,9 @@ if ($action == 'create' || $action == 'adduserldap') { print ''.$langs->trans("DateOfBirth").''; print ''; if ($caneditfield) { - echo $form->selectDate($dateofbirth ? $dateofbirth : $object->birth, 'dateofbirth', 0, 0, 1, 'updateuser', 1, 0); + echo $form->selectDate($dateofbirth ? $dateofbirth : $object->birth, 'dateofbirth', 0, 0, 1, 'updateuser', 1, 0, 0, '', '', '', '', 1, '', '', 'tzserver'); } else { - print dol_print_date($object->birth, 'day'); + print dol_print_date($object->birth, 'day', 'tzserver'); } print ''; print "\n"; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 2b284f6878e..04eebd6b6c9 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1731,7 +1731,7 @@ class User extends CommonObject $sql .= ", login = '".$this->db->escape($this->login)."'"; $sql .= ", api_key = ".($this->api_key ? "'".$this->db->escape($this->api_key)."'" : "null"); $sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman' - $sql .= ", birth=".(strval($this->birth) != '' ? "'".$this->db->idate($this->birth)."'" : 'null'); + $sql .= ", birth=".(strval($this->birth) != '' ? "'".$this->db->idate($this->birth, 'tzserver')."'" : 'null'); if (!empty($user->admin)) { $sql .= ", admin = ".(int) $this->admin; // admin flag can be set/unset only by an admin user } From 9ffe82e25937983ca5f2c2ed14699b7c8857fd65 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Thu, 7 Apr 2022 10:32:23 +0200 Subject: [PATCH 12/23] FIX : originproductline array td identification --- htdocs/core/class/commonobject.class.php | 16 ++++++++-------- htdocs/core/tpl/originproductline.tpl.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1064d34561d..02421ea9157 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4805,18 +4805,18 @@ abstract class CommonObject global $langs, $hookmanager, $conf, $form; print ''; - print ''.$langs->trans('Ref').''; - print ''.$langs->trans('Description').''; - print ''.$langs->trans('VATRate').''; - print ''.$langs->trans('PriceUHT').''; + print ''.$langs->trans('Ref').''; + print ''.$langs->trans('Description').''; + print ''.$langs->trans('VATRate').''; + print ''.$langs->trans('PriceUHT').''; if (!empty($conf->multicurrency->enabled)) { - print ''.$langs->trans('PriceUHTCurrency').''; + print ''.$langs->trans('PriceUHTCurrency').''; } - print ''.$langs->trans('Qty').''; + print ''.$langs->trans('Qty').''; if (!empty($conf->global->PRODUCT_USE_UNITS)) { - print ''.$langs->trans('Unit').''; + print ''.$langs->trans('Unit').''; } - print ''.$langs->trans('ReductionShort').''; + print ''.$langs->trans('ReductionShort').''; print ''.$form->showCheckAddButtons('checkforselect', 1).''; print ''; $i = 0; diff --git a/htdocs/core/tpl/originproductline.tpl.php b/htdocs/core/tpl/originproductline.tpl.php index d4943ac454d..93c2bd3a8df 100644 --- a/htdocs/core/tpl/originproductline.tpl.php +++ b/htdocs/core/tpl/originproductline.tpl.php @@ -27,20 +27,20 @@ if (empty($conf) || !is_object($conf)) { tpl['strike']) ? '' : ' strikefordisabled').'">'; -print ''.$this->tpl['label'].''; -print ''.$this->tpl['description'].''; -print ''.$this->tpl['vat_rate'].''; -print ''.$this->tpl['price'].''; +print ''.$this->tpl['label'].''; +print ''.$this->tpl['description'].''; +print ''.$this->tpl['vat_rate'].''; +print ''.$this->tpl['price'].''; if (!empty($conf->multicurrency->enabled)) { - print ''.$this->tpl['multicurrency_price'].''; + print ''.$this->tpl['multicurrency_price'].''; } -print ''.$this->tpl['qty'].''; +print ''.$this->tpl['qty'].''; if (!empty($conf->global->PRODUCT_USE_UNITS)) { - print ''.$langs->trans($this->tpl['unit']).''; + print ''.$langs->trans($this->tpl['unit']).''; } -print ''.$this->tpl['remise_percent'].''; +print ''.$this->tpl['remise_percent'].''; $selected = 1; if (!empty($selectedLines) && !in_array($this->tpl['id'], $selectedLines)) { From f1771af53cab8827e849c6053369ef692d6c6132 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Thu, 7 Apr 2022 11:03:25 +0200 Subject: [PATCH 13/23] FIX : originproductline array td identification data-id --- htdocs/core/tpl/originproductline.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/tpl/originproductline.tpl.php b/htdocs/core/tpl/originproductline.tpl.php index 93c2bd3a8df..6929b23fcad 100644 --- a/htdocs/core/tpl/originproductline.tpl.php +++ b/htdocs/core/tpl/originproductline.tpl.php @@ -26,7 +26,7 @@ if (empty($conf) || !is_object($conf)) { tpl['strike']) ? '' : ' strikefordisabled').'">'; +print ''; print ''.$this->tpl['label'].''; print ''.$this->tpl['description'].''; print ''.$this->tpl['vat_rate'].''; From 41ee9739db45a74f3731b0e215db13ed9d50d16f Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 7 Apr 2022 17:16:02 +0200 Subject: [PATCH 14/23] FIX: Add 'recruitment' into check array --- htdocs/core/lib/security.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 3ea554a4a8f..c0c540754fc 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -616,7 +616,7 @@ function checkUserAccessToObject($user, array $featuresarray, $objectid = 0, $ta $feature = 'projet_task'; } - $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website'); // Test on entity only (Objects with no link to company) + $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment'); // Test on entity only (Objects with no link to company) $checksoc = array('societe'); // Test for societe object $checkother = array('contact', 'agenda'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...). $checkproject = array('projet', 'project'); // Test for project object From 6e0888ca0ec5118e7094b24e2364ec740ee6c32e Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 7 Apr 2022 17:17:20 +0200 Subject: [PATCH 15/23] FIX: action comm list: holiday last day not included + handle duration with halfdays --- htdocs/comm/action/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 722423c0cd9..51d0f99b6b8 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -979,8 +979,8 @@ if ($resql) { $event->type = 'holiday'; $event->type_picto = 'holiday'; - $event->datep = $db->jdate($obj->date_start); - $event->datef = $db->jdate($obj->date_end); + $event->datep = $db->jdate($obj->date_start) + (empty($halfday) || $halfday == 1 ? 0 : 12 * 60 * 60 - 1); + $event->datef = $db->jdate($obj->date_end) + (empty($halfday) || $halfday == -1 ? 24 : 12) * 60 * 60 - 1; $event->date_start_in_calendar = $event->datep; $event->date_end_in_calendar = $event->datef; From de737b6b23d94c34bc36fb654b9778e2a65042fd Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 7 Apr 2022 18:07:30 +0200 Subject: [PATCH 16/23] FIX: holiday/leave requests: write status change emails in HTML --- htdocs/holiday/card.php | 73 +++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 3ca389176e7..42b7a7313f0 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -449,10 +449,9 @@ if (empty($reshook)) $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysToValidate"); // Content - $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n"; - $message .= "\n"; + $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - $message .= $langs->transnoentities("HolidaysToValidateBody")."\n"; + $message .= "

".$langs->transnoentities("HolidaysToValidateBody")."

\n"; $delayForRequest = $object->getConfCP('delayForRequest'); //$delayForRequest = $delayForRequest * (60*60*24); @@ -464,8 +463,7 @@ if (empty($reshook)) { if ($object->date_debut < $nextMonth) { - $message .= "\n"; - $message .= $langs->transnoentities("HolidaysToValidateDelay", $object->getConfCP('delayForRequest'))."\n"; + $message .= "

".$langs->transnoentities("HolidaysToValidateDelay", $object->getConfCP('delayForRequest'))."

\n"; } } @@ -475,20 +473,21 @@ if (empty($reshook)) $nbopenedday = num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, $object->halfday); if ($nbopenedday > $object->getCPforUser($object->fk_user, $object->fk_type)) { - $message .= "\n"; - $message .= $langs->transnoentities("HolidaysToValidateAlertSolde")."\n"; + $message .= "

".$langs->transnoentities("HolidaysToValidateAlertSolde")."

\n"; } } - $message .= "\n"; - $message .= "- ".$langs->transnoentitiesnoconv("Name")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n"; - $message .= "- ".$langs->transnoentitiesnoconv("Period")." : ".dol_print_date($object->date_debut, 'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($object->date_fin, 'day')."\n"; - $message .= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/card.php?id=".$object->id."\n\n"; - $message .= "\n"; + $link = dol_buildpath("/holiday/card.php", 3) . '?id='.$object->id; + + $message .= "
    "; + $message .= "
  • ".$langs->transnoentitiesnoconv("Name")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Period")." : ".dol_print_date($object->date_debut, 'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($object->date_fin, 'day')."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; + $message .= "
\n"; $trackid = 'leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); // Envoi du mail $result = $mail->sendfile(); @@ -603,19 +602,20 @@ if (empty($reshook)) $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysValidated"); // Content - $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n"; - $message .= "\n"; + $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - $message .= $langs->transnoentities("HolidaysValidatedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."\n"; + $message .= "

".$langs->transnoentities("HolidaysValidatedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; - $message .= "- ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n"; + $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; - $message .= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/card.php?id=".$object->id."\n\n"; - $message .= "\n"; + $message .= "
    \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; + $message .= "
\n"; $trackid = 'leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); // Envoi du mail $result = $mail->sendfile(); @@ -689,20 +689,21 @@ if (empty($reshook)) $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysRefused"); // Content - $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n"; - $message .= "\n"; + $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - $message .= $langs->transnoentities("HolidaysRefusedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."\n"; - $message .= GETPOST('detail_refuse', 'alpha')."\n\n"; + $message .= "

".$langs->transnoentities("HolidaysRefusedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; + $message .= "

".GETPOST('detail_refuse', 'alpha')."

"; - $message .= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n"; + $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; - $message .= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/card.php?id=".$object->id."\n\n"; - $message .= "\n"; + $message .= "
    \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; + $message .= "
"; $trackid = 'leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); // Envoi du mail $result = $mail->sendfile(); @@ -838,18 +839,20 @@ if (empty($reshook)) $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysCanceled"); // Content - $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n"; - $message .= "\n"; + $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - $message .= $langs->transnoentities("HolidaysCanceledBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."\n"; - $message .= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n"; + $message .= "

".$langs->transnoentities("HolidaysCanceledBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; - $message .= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/card.php?id=".$object->id."\n\n"; - $message .= "\n"; + $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; + + $message .= "
    \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; + $message .= "
\n"; $trackid = 'leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); // Envoi du mail $result = $mail->sendfile(); From 0cdc146f5b897438099524b63c3fceee872101af Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 00:55:40 +0200 Subject: [PATCH 17/23] FIX add tools to fix bad bank amount in accounting with multicurrency --- htdocs/accountancy/journal/bankjournal.php | 35 +++++++++++-------- .../install/mysql/migration/14.0.0-15.0.0.sql | 5 +++ htdocs/install/mysql/migration/repair.sql | 5 +++ htdocs/install/mysql/tables/llx_bank.sql | 3 +- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 2530454d056..4841b8bf171 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -117,7 +117,7 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false); } -$sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,"; +$sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.amount_main_currency, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,"; $sql .= " ba.courant, ba.ref as baref, ba.account_number, ba.fk_accountancy_journal,"; $sql .= " soc.rowid as socid, soc.nom as name, soc.email as email, bu1.type as typeop_company,"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { @@ -142,7 +142,7 @@ if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on bu2.url_id=u.rowid"; $sql .= " WHERE ba.fk_accountancy_journal=".((int) $id_journal); -$sql .= ' AND b.amount != 0 AND ba.entity IN ('.getEntity('bank_account', 0).')'; // We don't share object for accountancy +$sql .= ' AND b.amount <> 0 AND ba.entity IN ('.getEntity('bank_account', 0).')'; // We don't share object for accountancy if ($date_start && $date_end) { $sql .= " AND b.dateo >= '".$db->idate($date_start)."' AND b.dateo <= '".$db->idate($date_end)."'"; } @@ -282,6 +282,7 @@ if ($result) { $tabpay[$obj->rowid]["fk_bank"] = $obj->rowid; $tabpay[$obj->rowid]["bank_account_ref"] = $obj->baref; $tabpay[$obj->rowid]["fk_bank_account"] = $obj->fk_account; + $reg = array(); if (preg_match('/^\((.*)\)$/i', $obj->label, $reg)) { $tabpay[$obj->rowid]["lib"] = $langs->trans($reg[1]); } else { @@ -296,6 +297,12 @@ if ($result) { $tabtype[$obj->rowid] = 'unknown'; $tabmoreinfo[$obj->rowid] = array(); + $amounttouse = $obj->amount; + if (!empty($obj->amount_main_currency)) { + // If $obj->amount_main_currency is set, it means that $obj->amount is not in same currency, we must use $obj->amount_main_currency + $amounttouse = $obj->amount_main_currency; + } + // get_url may return -1 which is not traversable if (is_array($links) && count($links) > 0) { // Now loop on each link of record in bank (code similar to bankentries_list.php) @@ -334,7 +341,7 @@ if ($result) { $societestatic->email = $tabcompany[$obj->rowid]['email']; $tabpay[$obj->rowid]["soclib"] = $societestatic->getNomUrl(1, '', 30); if ($compta_soc) { - $tabtp[$obj->rowid][$compta_soc] += $obj->amount; + $tabtp[$obj->rowid][$compta_soc] += $amounttouse; } } elseif ($links[$key]['type'] == 'user') { $userstatic->id = $links[$key]['url_id']; @@ -350,7 +357,7 @@ if ($result) { $tabpay[$obj->rowid]["soclib"] = '???'; // Should not happen, but happens with old data when id of user was not saved on expense report payment. } if ($compta_user) { - $tabtp[$obj->rowid][$compta_user] += $obj->amount; + $tabtp[$obj->rowid][$compta_user] += $amounttouse; } } elseif ($links[$key]['type'] == 'sc') { $chargestatic->id = $links[$key]['url_id']; @@ -383,7 +390,7 @@ if ($result) { $resultmid = $db->query($sqlmid); if ($resultmid) { $objmid = $db->fetch_object($resultmid); - $tabtp[$obj->rowid][$objmid->accountancy_code] += $obj->amount; + $tabtp[$obj->rowid][$objmid->accountancy_code] += $amounttouse; } } elseif ($links[$key]['type'] == 'payment_donation') { $paymentdonstatic->id = $links[$key]['url_id']; @@ -391,7 +398,7 @@ if ($result) { $paymentdonstatic->fk_donation = $links[$key]['url_id']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentdonstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentdonationid"] = $paymentdonstatic->id; - $tabtp[$obj->rowid][$account_pay_donation] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_donation] += $amounttouse; } elseif ($links[$key]['type'] == 'member') { $paymentsubscriptionstatic->id = $links[$key]['url_id']; $paymentsubscriptionstatic->ref = $links[$key]['url_id']; @@ -399,14 +406,14 @@ if ($result) { $tabpay[$obj->rowid]["lib"] .= ' '.$paymentsubscriptionstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentsubscriptionid"] = $paymentsubscriptionstatic->id; $paymentsubscriptionstatic->fetch($paymentsubscriptionstatic->id); - $tabtp[$obj->rowid][$account_pay_subscription] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_subscription] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_vat') { // Payment VAT $paymentvatstatic->id = $links[$key]['url_id']; $paymentvatstatic->ref = $links[$key]['url_id']; $paymentvatstatic->label = $links[$key]['label']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentvatstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentvatid"] = $paymentvatstatic->id; - $tabtp[$obj->rowid][$account_pay_vat] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_vat] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_salary') { $paymentsalstatic->id = $links[$key]['url_id']; $paymentsalstatic->ref = $links[$key]['url_id']; @@ -438,7 +445,7 @@ if ($result) { if (empty($obj->typeop_user)) { // Add test to avoid to add amount twice if a link already exists also on user. $compta_user = $userstatic->accountancy_code; if ($compta_user) { - $tabtp[$obj->rowid][$compta_user] += $obj->amount; + $tabtp[$obj->rowid][$compta_user] += $amounttouse; $tabuser[$obj->rowid] = array( 'id' => $userstatic->id, 'name' => dolGetFirstLastname($userstatic->firstname, $userstatic->lastname), @@ -465,14 +472,14 @@ if ($result) { $account_various = (!empty($paymentvariousstatic->accountancy_code) ? $paymentvariousstatic->accountancy_code : 'NotDefined'); // NotDefined is a reserved word $account_subledger = (!empty($paymentvariousstatic->subledger_account) ? $paymentvariousstatic->subledger_account : ''); // NotDefined is a reserved word $tabpay[$obj->rowid]["account_various"] = $account_various; - $tabtp[$obj->rowid][$account_subledger] += $obj->amount; + $tabtp[$obj->rowid][$account_subledger] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_loan') { $paymentloanstatic->id = $links[$key]['url_id']; $paymentloanstatic->ref = $links[$key]['url_id']; $paymentloanstatic->fk_loan = $links[$key]['url_id']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentloanstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentloanid"] = $paymentloanstatic->id; - //$tabtp[$obj->rowid][$account_pay_loan] += $obj->amount; + //$tabtp[$obj->rowid][$account_pay_loan] += $amounttouse; $sqlmid = 'SELECT pl.amount_capital, pl.amount_insurance, pl.amount_interest, l.accountancy_account_capital, l.accountancy_account_insurance, l.accountancy_account_interest'; $sqlmid .= ' FROM '.MAIN_DB_PREFIX.'payment_loan as pl, '.MAIN_DB_PREFIX.'loan as l'; $sqlmid .= ' WHERE l.rowid = pl.fk_loan AND pl.fk_bank = '.((int) $obj->rowid); @@ -488,14 +495,14 @@ if ($result) { } elseif ($links[$key]['type'] == 'banktransfert') { $accountLinestatic->fetch($links[$key]['url_id']); $tabpay[$obj->rowid]["lib"] .= ' '.$langs->trans("BankTransfer").'- '.$accountLinestatic ->getNomUrl(1); - $tabtp[$obj->rowid][$account_transfer] += $obj->amount; + $tabtp[$obj->rowid][$account_transfer] += $amounttouse; $bankaccountstatic->fetch($tabpay[$obj->rowid]['fk_bank_account']); $tabpay[$obj->rowid]["soclib"] = $bankaccountstatic->getNomUrl(2); } } } - $tabbq[$obj->rowid][$compta_bank] += $obj->amount; + $tabbq[$obj->rowid][$compta_bank] += $amounttouse; // If no links were found to know the amount on thirdparty, we try to guess it. // This may happens on bank entries without the links lines to 'company'. @@ -542,7 +549,7 @@ if ($result) { } }*/ - // if($obj->socid)$tabtp[$obj->rowid][$compta_soc] += $obj->amount; + // if($obj->socid)$tabtp[$obj->rowid][$compta_soc] += $amounttouse; $i++; } diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql index ab037313dfb..30636a8bb98 100644 --- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql +++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql @@ -509,3 +509,8 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) value -- VMYSQL4.3 ALTER TABLE llx_user MODIFY COLUMN fk_soc integer NULL; -- VPGSQL8.2 ALTER TABLE llx_user ALTER COLUMN fk_soc DROP NOT NULL; + +-- Add column to help to fix a very critical bug when transferring into accounting bank record of a bank account into another currency. +-- Idea is to update this column manually in v15 with value in currency of company for bank that are not into the main currency and the transfer +-- into accounting will use it in priority if value is not null. +ALTER TABLE llx_bank ADD COLUMN amount_main_currency double(24,8) NULL; diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 4935577cbf8..070f3a2c5da 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -557,3 +557,8 @@ UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NUL DELETE FROM llx_rights_def WHERE module = 'hrm' AND perms = 'employee'; + +-- Sequence to fix the content of llx_bank.amount_main_currency +-- DROP TABLE tmp_bank; +-- CREATE TABLE tmp_bank SELECT b.rowid, b.amount, p.rowid as pid, p.amount as pamount, p.multicurrency_amount as pmulticurrencyamount FROM llx_bank as b INNER JOIN llx_bank_url as bu ON bu.fk_bank=b.rowid AND bu.type = 'payment' INNER JOIN llx_paiement as p ON bu.url_id = p.rowid WHERE p.multicurrency_amount <> 0 AND p.multicurrency_amount <> p.amount; +-- UPDATE llx_bank as b SET b.amount_main_currency = (SELECT tb.pamount FROM tmp_bank as tb WHERE tb.rowid = b.rowid) WHERE b.amount_main_currency IS NULL; diff --git a/htdocs/install/mysql/tables/llx_bank.sql b/htdocs/install/mysql/tables/llx_bank.sql index 0e1dbc403da..d0a8e34790b 100644 --- a/htdocs/install/mysql/tables/llx_bank.sql +++ b/htdocs/install/mysql/tables/llx_bank.sql @@ -24,7 +24,8 @@ create table llx_bank tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, datev date, -- date de valeur dateo date, -- date operation - amount double(24,8) NOT NULL default 0, + amount double(24,8) NOT NULL default 0, -- amount in the currency of the bank account + amount_main_currency double(24,8) NULL, -- amount in the main currency of the company label varchar(255), fk_account integer, fk_user_author integer, From d6860ca41b49b463fa08e1b9576d009dc842c1c5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 00:55:40 +0200 Subject: [PATCH 18/23] FIX bad bank amount in accounting with multicurrency --- htdocs/accountancy/journal/bankjournal.php | 35 +++-- htdocs/compta/bank/class/account.class.php | 11 +- htdocs/compta/paiement.php | 12 +- .../compta/paiement/class/paiement.class.php | 139 ++++++++++++------ htdocs/fourn/class/paiementfourn.class.php | 48 +++++- htdocs/fourn/facture/paiement.php | 12 +- .../install/mysql/migration/14.0.0-15.0.0.sql | 5 + htdocs/install/mysql/migration/repair.sql | 5 + htdocs/install/mysql/tables/llx_bank.sql | 3 +- 9 files changed, 196 insertions(+), 74 deletions(-) diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 2530454d056..4841b8bf171 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -117,7 +117,7 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false); } -$sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,"; +$sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.amount_main_currency, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,"; $sql .= " ba.courant, ba.ref as baref, ba.account_number, ba.fk_accountancy_journal,"; $sql .= " soc.rowid as socid, soc.nom as name, soc.email as email, bu1.type as typeop_company,"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { @@ -142,7 +142,7 @@ if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on bu2.url_id=u.rowid"; $sql .= " WHERE ba.fk_accountancy_journal=".((int) $id_journal); -$sql .= ' AND b.amount != 0 AND ba.entity IN ('.getEntity('bank_account', 0).')'; // We don't share object for accountancy +$sql .= ' AND b.amount <> 0 AND ba.entity IN ('.getEntity('bank_account', 0).')'; // We don't share object for accountancy if ($date_start && $date_end) { $sql .= " AND b.dateo >= '".$db->idate($date_start)."' AND b.dateo <= '".$db->idate($date_end)."'"; } @@ -282,6 +282,7 @@ if ($result) { $tabpay[$obj->rowid]["fk_bank"] = $obj->rowid; $tabpay[$obj->rowid]["bank_account_ref"] = $obj->baref; $tabpay[$obj->rowid]["fk_bank_account"] = $obj->fk_account; + $reg = array(); if (preg_match('/^\((.*)\)$/i', $obj->label, $reg)) { $tabpay[$obj->rowid]["lib"] = $langs->trans($reg[1]); } else { @@ -296,6 +297,12 @@ if ($result) { $tabtype[$obj->rowid] = 'unknown'; $tabmoreinfo[$obj->rowid] = array(); + $amounttouse = $obj->amount; + if (!empty($obj->amount_main_currency)) { + // If $obj->amount_main_currency is set, it means that $obj->amount is not in same currency, we must use $obj->amount_main_currency + $amounttouse = $obj->amount_main_currency; + } + // get_url may return -1 which is not traversable if (is_array($links) && count($links) > 0) { // Now loop on each link of record in bank (code similar to bankentries_list.php) @@ -334,7 +341,7 @@ if ($result) { $societestatic->email = $tabcompany[$obj->rowid]['email']; $tabpay[$obj->rowid]["soclib"] = $societestatic->getNomUrl(1, '', 30); if ($compta_soc) { - $tabtp[$obj->rowid][$compta_soc] += $obj->amount; + $tabtp[$obj->rowid][$compta_soc] += $amounttouse; } } elseif ($links[$key]['type'] == 'user') { $userstatic->id = $links[$key]['url_id']; @@ -350,7 +357,7 @@ if ($result) { $tabpay[$obj->rowid]["soclib"] = '???'; // Should not happen, but happens with old data when id of user was not saved on expense report payment. } if ($compta_user) { - $tabtp[$obj->rowid][$compta_user] += $obj->amount; + $tabtp[$obj->rowid][$compta_user] += $amounttouse; } } elseif ($links[$key]['type'] == 'sc') { $chargestatic->id = $links[$key]['url_id']; @@ -383,7 +390,7 @@ if ($result) { $resultmid = $db->query($sqlmid); if ($resultmid) { $objmid = $db->fetch_object($resultmid); - $tabtp[$obj->rowid][$objmid->accountancy_code] += $obj->amount; + $tabtp[$obj->rowid][$objmid->accountancy_code] += $amounttouse; } } elseif ($links[$key]['type'] == 'payment_donation') { $paymentdonstatic->id = $links[$key]['url_id']; @@ -391,7 +398,7 @@ if ($result) { $paymentdonstatic->fk_donation = $links[$key]['url_id']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentdonstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentdonationid"] = $paymentdonstatic->id; - $tabtp[$obj->rowid][$account_pay_donation] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_donation] += $amounttouse; } elseif ($links[$key]['type'] == 'member') { $paymentsubscriptionstatic->id = $links[$key]['url_id']; $paymentsubscriptionstatic->ref = $links[$key]['url_id']; @@ -399,14 +406,14 @@ if ($result) { $tabpay[$obj->rowid]["lib"] .= ' '.$paymentsubscriptionstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentsubscriptionid"] = $paymentsubscriptionstatic->id; $paymentsubscriptionstatic->fetch($paymentsubscriptionstatic->id); - $tabtp[$obj->rowid][$account_pay_subscription] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_subscription] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_vat') { // Payment VAT $paymentvatstatic->id = $links[$key]['url_id']; $paymentvatstatic->ref = $links[$key]['url_id']; $paymentvatstatic->label = $links[$key]['label']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentvatstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentvatid"] = $paymentvatstatic->id; - $tabtp[$obj->rowid][$account_pay_vat] += $obj->amount; + $tabtp[$obj->rowid][$account_pay_vat] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_salary') { $paymentsalstatic->id = $links[$key]['url_id']; $paymentsalstatic->ref = $links[$key]['url_id']; @@ -438,7 +445,7 @@ if ($result) { if (empty($obj->typeop_user)) { // Add test to avoid to add amount twice if a link already exists also on user. $compta_user = $userstatic->accountancy_code; if ($compta_user) { - $tabtp[$obj->rowid][$compta_user] += $obj->amount; + $tabtp[$obj->rowid][$compta_user] += $amounttouse; $tabuser[$obj->rowid] = array( 'id' => $userstatic->id, 'name' => dolGetFirstLastname($userstatic->firstname, $userstatic->lastname), @@ -465,14 +472,14 @@ if ($result) { $account_various = (!empty($paymentvariousstatic->accountancy_code) ? $paymentvariousstatic->accountancy_code : 'NotDefined'); // NotDefined is a reserved word $account_subledger = (!empty($paymentvariousstatic->subledger_account) ? $paymentvariousstatic->subledger_account : ''); // NotDefined is a reserved word $tabpay[$obj->rowid]["account_various"] = $account_various; - $tabtp[$obj->rowid][$account_subledger] += $obj->amount; + $tabtp[$obj->rowid][$account_subledger] += $amounttouse; } elseif ($links[$key]['type'] == 'payment_loan') { $paymentloanstatic->id = $links[$key]['url_id']; $paymentloanstatic->ref = $links[$key]['url_id']; $paymentloanstatic->fk_loan = $links[$key]['url_id']; $tabpay[$obj->rowid]["lib"] .= ' '.$paymentloanstatic->getNomUrl(2); $tabpay[$obj->rowid]["paymentloanid"] = $paymentloanstatic->id; - //$tabtp[$obj->rowid][$account_pay_loan] += $obj->amount; + //$tabtp[$obj->rowid][$account_pay_loan] += $amounttouse; $sqlmid = 'SELECT pl.amount_capital, pl.amount_insurance, pl.amount_interest, l.accountancy_account_capital, l.accountancy_account_insurance, l.accountancy_account_interest'; $sqlmid .= ' FROM '.MAIN_DB_PREFIX.'payment_loan as pl, '.MAIN_DB_PREFIX.'loan as l'; $sqlmid .= ' WHERE l.rowid = pl.fk_loan AND pl.fk_bank = '.((int) $obj->rowid); @@ -488,14 +495,14 @@ if ($result) { } elseif ($links[$key]['type'] == 'banktransfert') { $accountLinestatic->fetch($links[$key]['url_id']); $tabpay[$obj->rowid]["lib"] .= ' '.$langs->trans("BankTransfer").'- '.$accountLinestatic ->getNomUrl(1); - $tabtp[$obj->rowid][$account_transfer] += $obj->amount; + $tabtp[$obj->rowid][$account_transfer] += $amounttouse; $bankaccountstatic->fetch($tabpay[$obj->rowid]['fk_bank_account']); $tabpay[$obj->rowid]["soclib"] = $bankaccountstatic->getNomUrl(2); } } } - $tabbq[$obj->rowid][$compta_bank] += $obj->amount; + $tabbq[$obj->rowid][$compta_bank] += $amounttouse; // If no links were found to know the amount on thirdparty, we try to guess it. // This may happens on bank entries without the links lines to 'company'. @@ -542,7 +549,7 @@ if ($result) { } }*/ - // if($obj->socid)$tabtp[$obj->rowid][$compta_soc] += $obj->amount; + // if($obj->socid)$tabtp[$obj->rowid][$compta_soc] += $amounttouse; $i++; } diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 5a484e9e97c..45472008bf7 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -513,9 +513,10 @@ class Account extends CommonObject * @param string $accountancycode When we record a free bank entry, we must provide accounting account if accountancy module is on. * @param int $datev Date value * @param string $num_releve Label of bank receipt for reconciliation + * @param float $amount_main_currency Amount * @return int Rowid of added entry, <0 if KO */ - public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '') + public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '', $amount_main_currency = null) { // Deprecation warning if (is_numeric($oper)) { @@ -573,6 +574,7 @@ class Account extends CommonObject $accline->datev = $datev; $accline->label = $label; $accline->amount = $amount; + $accline->amount_main_currency = $amount_main_currency; $accline->fk_user_author = $user->id; $accline->fk_account = $this->id; $accline->fk_type = $oper; @@ -1789,7 +1791,8 @@ class AccountLine extends CommonObject */ public $datev; - public $amount; + public $amount; /* Amount of payment in the bank account currency */ + public $amount_main_currency; /* Amount in the currency of company if bank account use another currency */ /** * @var int ID @@ -1950,6 +1953,7 @@ class AccountLine extends CommonObject $sql .= ", datev"; $sql .= ", label"; $sql .= ", amount"; + $sql .= ", amount_main_currency"; $sql .= ", fk_user_author"; $sql .= ", num_chq"; $sql .= ", fk_account"; @@ -1964,7 +1968,8 @@ class AccountLine extends CommonObject $sql .= ", '".$this->db->idate($this->datev)."'"; $sql .= ", '".$this->db->escape($this->label)."'"; $sql .= ", ".price2num($this->amount); - $sql .= ", ".($this->fk_user_author > 0 ? $this->fk_user_author : "null"); + $sql .= ", ".(empty($this->amount_main_currency) ? "NULL" : price2num($this->amount_main_currency)); + $sql .= ", ".($this->fk_user_author > 0 ? ((int) $this->fk_user_author) : "null"); $sql .= ", ".($this->num_chq ? "'".$this->db->escape($this->num_chq)."'" : "null"); $sql .= ", '".$this->db->escape($this->fk_account)."'"; $sql .= ", '".$this->db->escape($this->fk_type)."'"; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index 96d482b33ae..30234ae92fc 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -133,7 +133,7 @@ if (empty($reshook)) { } } - $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => $_POST[$key]); + $formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOST($key)); } elseif (substr($key, 0, 21) == 'multicurrency_amount_') { $cursorfacid = substr($key, 21); $multicurrency_amounts[$cursorfacid] = price2num(GETPOST($key)); @@ -190,6 +190,7 @@ if (empty($reshook)) { // Check if payments in both currency if ($totalpayment > 0 && $multicurrency_totalpayment > 0) { + $langs->load("errors"); setEventMessages($langs->transnoentities('ErrorPaymentInBothCurrency'), null, 'errors'); $error++; } @@ -220,6 +221,8 @@ if (empty($reshook)) { $thirdparty->fetch($socid); } + $multicurrency_code = array(); + // Clean parameters amount if payment is for a credit note foreach ($amounts as $key => $value) { // How payment is dispatched $tmpinvoice = new Facture($db); @@ -228,6 +231,7 @@ if (empty($reshook)) { $newvalue = price2num($value, 'MT'); $amounts[$key] = - abs($newvalue); } + $multicurrency_code[$key] = $tmpinvoice->multicurrency_code; } foreach ($multicurrency_amounts as $key => $value) { // How payment is dispatched @@ -237,6 +241,7 @@ if (empty($reshook)) { $newvalue = price2num($value, 'MT'); $multicurrency_amounts[$key] = - abs($newvalue); } + $multicurrency_code[$key] = $tmpinvoice->multicurrency_code; } if (!empty($conf->banque->enabled)) { @@ -252,13 +257,16 @@ if (empty($reshook)) { $paiement->datepaye = $datepaye; $paiement->amounts = $amounts; // Array with all payments dispatching with invoice id $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching + $paiement->multicurrency_code = $multicurrency_code; // Array with all currency of payments dispatching $paiement->paiementid = dol_getIdFromCode($db, GETPOST('paiementcode'), 'c_paiement', 'code', 'id', 1); $paiement->num_payment = GETPOST('num_paiement', 'alpha'); $paiement->note_private = GETPOST('comment', 'alpha'); + $paiement->fk_account = GETPOST('accountid', 'int'); if (!$error) { // Create payment and update this->multicurrency_amounts if this->amounts filled or // this->amounts if this->multicurrency_amounts filled. + // This also set ->amount and ->multicurrency_amount $paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices') == 'on' ? 1 : 0), $thirdparty); // This include closing invoices and regenerating documents if ($paiement_id < 0) { setEventMessages($paiement->error, $paiement->errors, 'errors'); @@ -271,7 +279,7 @@ if (empty($reshook)) { if (GETPOST('type') == Facture::TYPE_CREDIT_NOTE) { $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note } - $result = $paiement->addPaymentToBank($user, 'payment', $label, GETPOST('accountid'), GETPOST('chqemetteur'), GETPOST('chqbank')); + $result = $paiement->addPaymentToBank($user, 'payment', $label, GETPOST('accountid', 'int'), GETPOST('chqemetteur'), GETPOST('chqbank')); if ($result < 0) { setEventMessages($paiement->error, $paiement->errors, 'errors'); $error++; diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 3abf38fb16e..edab2922efb 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -72,8 +72,9 @@ class Paiement extends CommonObject public $amount; // Total amount of payment (in the main currency) public $multicurrency_amount; // Total amount of payment (in the currency of the bank account) - public $amounts = array(); // array: invoice ID => amount for that invoice (in the main currency)> - public $multicurrency_amounts = array(); // array: invoice ID => amount for that invoice (in the invoice's currency)> + public $amounts = array(); // array: invoice ID => amount for that invoice (in the main currency) + public $multicurrency_amounts = array(); // array: invoice ID => amount for that invoice (in the invoice's currency) + public $multicurrency_code = array(); // array: invoice ID => currency code for that invoice public $pos_change = 0; // Excess received in TakePOS cash payment @@ -82,12 +83,12 @@ class Paiement extends CommonObject public $paiementcode; // Code of payment. /** - * @var string type libelle + * @var string Type of payment label */ public $type_label; /** - * @var string type code + * @var string Type of payment code (seems duplicate with $paiementcode); */ public $type_code; @@ -230,7 +231,7 @@ class Paiement extends CommonObject global $conf, $langs; $error = 0; - $way = $this->getWay(); + $way = $this->getWay(); // 'dolibarr' to use amount, 'customer' to use foreign multicurrency amount $now = dol_now(); @@ -239,16 +240,37 @@ class Paiement extends CommonObject $totalamount_converted = 0; $atleastonepaymentnotnull = 0; - if ($way == 'dolibarr') { + if ($way == 'dolibarr') { // Payments were entered into the column of main currency $amounts = &$this->amounts; $amounts_to_update = &$this->multicurrency_amounts; - } else { + } else { // Payments were entered into the column of foreign currency $amounts = &$this->multicurrency_amounts; $amounts_to_update = &$this->amounts; } + $currencyofpayment = ''; + foreach ($amounts as $key => $value) { // How payment is dispatch + if (empty($value)) { + continue; + } + // $key is id of invoice, $value is amount, $way is a 'dolibarr' if amount is in main currency, 'customer' if in foreign currency $value_converted = Multicurrency::getAmountConversionFromInvoiceRate($key, $value, $way); + // Add controls of input validity + if ($value_converted === false) { + // We failed to find the conversion for one invoice + $this->error = 'FailedToFoundTheConversionRateForInvoice'; + return -1; + } + if (empty($currencyofpayment)) { + $currencyofpayment = $this->multicurrency_code[$key]; + } + if ($currencyofpayment != $this->multicurrency_code[$key]) { + // If we have invoices with different currencies in the payment, we stop here + $this->error = 'ErrorYouTryToPayInvoicesWithDifferentCurrenciesInSamePayment'; + return -1; + } + $totalamount_converted += $value_converted; $amounts_to_update[$key] = price2num($value_converted, 'MT'); @@ -260,6 +282,19 @@ class Paiement extends CommonObject } } + if (!empty($currencyofpayment)) { + // We must check that the currency of invoices is the same than the currency of the bank + $bankaccount = new Account($this->db); + $bankaccount->fetch($this->fk_account); + $bankcurrencycode = empty($bankaccount->currency_code) ? $conf->currency : $bankaccount->currency_code; + if ($currencyofpayment != $bankcurrencycode && $currencyofpayment != $conf->currency && $bankcurrencycode != $conf->currency) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorYouTryToPayInvoicesInACurrencyFromBankWithAnotherCurrency', $currencyofpayment, $bankcurrencycode); + return -1; + } + } + + $totalamount = price2num($totalamount); $totalamount_converted = price2num($totalamount_converted); @@ -597,17 +632,22 @@ class Paiement extends CommonObject $result = $acc->fetch($this->fk_account); $totalamount = $this->amount; + $totalamount_main_currency = null; if (empty($totalamount)) { $totalamount = $this->total; // For backward compatibility } // if dolibarr currency != bank currency then we received an amount in customer currency (currently I don't manage the case : my currency is USD, the customer currency is EUR and he paid me in GBP. Seems no sense for me) if (!empty($conf->multicurrency->enabled) && $conf->currency != $acc->currency_code) { - $totalamount = $this->multicurrency_amount; + $totalamount = $this->multicurrency_amount; // We will insert into llx_bank.amount in foreign currency + $totalamount_main_currency = $this->amount; // We will also save the amount in main currency into column llx_bank.amount_main_currency } if ($mode == 'payment_supplier') { $totalamount = -$totalamount; + if (isset($totalamount_main_currency)) { + $totalamount_main_currency = -$totalamount_main_currency; + } } // Insert payment into llx_bank @@ -621,8 +661,11 @@ class Paiement extends CommonObject $user, $emetteur_nom, $emetteur_banque, - $accountancycode - ); + $accountancycode, + null, + '', + $totalamount_main_currency + ); // Mise a jour fk_bank dans llx_paiement // On connait ainsi le paiement qui a genere l'ecriture bancaire @@ -667,7 +710,7 @@ class Paiement extends CommonObject DOL_URL_ROOT.'/comm/card.php?socid=', $fac->thirdparty->name, 'company' - ); + ); if ($result <= 0) { dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror()); } @@ -685,7 +728,7 @@ class Paiement extends CommonObject DOL_URL_ROOT.'/fourn/card.php?socid=', $fac->thirdparty->name, 'company' - ); + ); if ($result <= 0) { dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror()); } @@ -703,7 +746,7 @@ class Paiement extends CommonObject DOL_URL_ROOT.'/compta/prelevement/card.php?id=', $this->num_payment, 'withdraw' - ); + ); } // Add link 'InvoiceRefused' in bank_url @@ -714,7 +757,7 @@ class Paiement extends CommonObject DOL_URL_ROOT.'/compta/prelevement/card.php?id=', $this->num_prelevement, 'withdraw' - ); + ); } if (!$error && !$notrigger) { @@ -1241,40 +1284,40 @@ class Paiement extends CommonObject $langs->load('compta'); /*if ($mode == 0) - { - if ($status == 0) return $langs->trans('ToValidate'); - if ($status == 1) return $langs->trans('Validated'); - } - if ($mode == 1) - { - if ($status == 0) return $langs->trans('ToValidate'); - if ($status == 1) return $langs->trans('Validated'); - } - if ($mode == 2) - { - if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate'); - if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated'); - } - if ($mode == 3) - { - if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1'); - if ($status == 1) return img_picto($langs->trans('Validated'),'statut4'); - } - if ($mode == 4) - { - if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate'); - if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated'); - } - if ($mode == 5) - { - if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1'); - if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4'); - } - if ($mode == 6) - { - if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1'); - if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4'); - }*/ + { + if ($status == 0) return $langs->trans('ToValidate'); + if ($status == 1) return $langs->trans('Validated'); + } + if ($mode == 1) + { + if ($status == 0) return $langs->trans('ToValidate'); + if ($status == 1) return $langs->trans('Validated'); + } + if ($mode == 2) + { + if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate'); + if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated'); + } + if ($mode == 3) + { + if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1'); + if ($status == 1) return img_picto($langs->trans('Validated'),'statut4'); + } + if ($mode == 4) + { + if ($status == 0) return img_picto($langs->trans('ToValidate'),'statut1').' '.$langs->trans('ToValidate'); + if ($status == 1) return img_picto($langs->trans('Validated'),'statut4').' '.$langs->trans('Validated'); + } + if ($mode == 5) + { + if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1'); + if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4'); + } + if ($mode == 6) + { + if ($status == 0) return $langs->trans('ToValidate').' '.img_picto($langs->trans('ToValidate'),'statut1'); + if ($status == 1) return $langs->trans('Validated').' '.img_picto($langs->trans('Validated'),'statut4'); + }*/ return ''; } diff --git a/htdocs/fourn/class/paiementfourn.class.php b/htdocs/fourn/class/paiementfourn.class.php index de9aa4eade9..db2a503673c 100644 --- a/htdocs/fourn/class/paiementfourn.class.php +++ b/htdocs/fourn/class/paiementfourn.class.php @@ -160,11 +160,12 @@ class PaiementFourn extends Paiement $error = 0; $way = $this->getWay(); + $now = dol_now(); + // Clean parameters $totalamount = 0; $totalamount_converted = 0; - - dol_syslog(get_class($this)."::create", LOG_DEBUG); + $atleastonepaymentnotnull = 0; if ($way == 'dolibarr') { $amounts = &$this->amounts; @@ -174,23 +175,62 @@ class PaiementFourn extends Paiement $amounts_to_update = &$this->amounts; } + $currencyofpayment = ''; + foreach ($amounts as $key => $value) { + if (empty($value)) { + continue; + } + // $key is id of invoice, $value is amount, $way is a 'dolibarr' if amount is in main currency, 'customer' if in foreign currency $value_converted = Multicurrency::getAmountConversionFromInvoiceRate($key, $value ? $value : 0, $way, 'facture_fourn'); + // Add controls of input validity + if ($value_converted === false) { + // We failed to find the conversion for one invoice + $this->error = 'FailedToFoundTheConversionRateForInvoice'; + return -1; + } + if (empty($currencyofpayment)) { + $currencyofpayment = $this->multicurrency_code[$key]; + } + if ($currencyofpayment != $this->multicurrency_code[$key]) { + // If we have invoices with different currencies in the payment, we stop here + $this->error = 'ErrorYouTryToPayInvoicesWithDifferentCurrenciesInSamePayment'; + return -1; + } + $totalamount_converted += $value_converted; $amounts_to_update[$key] = price2num($value_converted, 'MT'); $newvalue = price2num($value, 'MT'); $amounts[$key] = $newvalue; $totalamount += $newvalue; + if (!empty($newvalue)) { + $atleastonepaymentnotnull++; + } } + + if (!empty($currencyofpayment)) { + // We must check that the currency of invoices is the same than the currency of the bank + $bankaccount = new Account($this->db); + $bankaccount->fetch($this->fk_account); + $bankcurrencycode = empty($bankaccount->currency_code) ? $conf->currency : $bankaccount->currency_code; + if ($currencyofpayment != $bankcurrencycode && $currencyofpayment != $conf->currency && $bankcurrencycode != $conf->currency) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorYouTryToPayInvoicesInACurrencyFromBankWithAnotherCurrency', $currencyofpayment, $bankcurrencycode); + return -1; + } + } + + $totalamount = price2num($totalamount); $totalamount_converted = price2num($totalamount_converted); + dol_syslog(get_class($this)."::create", LOG_DEBUG); + $this->db->begin(); if ($totalamount <> 0) { // On accepte les montants negatifs $ref = $this->getNextNumRef(is_object($thirdparty) ? $thirdparty : ''); - $now = dol_now(); if ($way == 'dolibarr') { $total = $totalamount; @@ -346,7 +386,7 @@ class PaiementFourn extends Paiement $this->total = $total; $this->multicurrency_amount = $mtotal; $this->db->commit(); - dol_syslog('PaiementFourn::Create Ok Total = '.$this->total); + dol_syslog('PaiementFourn::Create Ok Total = '.$this->amount.', Total currency = '.$this->multicurrency_amount); return $this->id; } else { $this->db->rollback(); diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php index 33c07c58e99..cb9ca7437bb 100644 --- a/htdocs/fourn/facture/paiement.php +++ b/htdocs/fourn/facture/paiement.php @@ -252,6 +252,8 @@ if (empty($reshook)) { $datepaye = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + $multicurrency_code = array(); + // Clean parameters amount if payment is for a credit note foreach ($amounts as $key => $value) { // How payment is dispatched $tmpinvoice = new FactureFournisseur($db); @@ -260,6 +262,7 @@ if (empty($reshook)) { $newvalue = price2num($value, 'MT'); $amounts[$key] = - abs($newvalue); } + $multicurrency_code[$key] = $tmpinvoice->multicurrency_code; } foreach ($multicurrency_amounts as $key => $value) { // How payment is dispatched @@ -269,6 +272,7 @@ if (empty($reshook)) { $newvalue = price2num($value, 'MT'); $multicurrency_amounts[$key] = - abs($newvalue); } + $multicurrency_code[$key] = $tmpinvoice->multicurrency_code; } //var_dump($amounts); @@ -288,12 +292,16 @@ if (empty($reshook)) { $paiement->datepaye = $datepaye; $paiement->amounts = $amounts; // Array of amounts $paiement->multicurrency_amounts = $multicurrency_amounts; + $paiement->multicurrency_code = $multicurrency_code; // Array with all currency of payments dispatching $paiement->paiementid = GETPOST('paiementid', 'int'); - $paiement->num_payment = GETPOST('num_paiement', 'alphanohtml'); $paiement->note_private = GETPOST('comment', 'alpha'); + $paiement->fk_account = GETPOST('accountid', 'int'); if (!$error) { + // Create payment and update this->multicurrency_amounts if this->amounts filled or + // this->amounts if this->multicurrency_amounts filled. + // This also set ->amount and ->multicurrency_amount $paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices') == 'on' ? 1 : 0), $thirdparty); if ($paiement_id < 0) { setEventMessages($paiement->error, $paiement->errors, 'errors'); @@ -302,7 +310,7 @@ if (empty($reshook)) { } if (!$error) { - $result = $paiement->addPaymentToBank($user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, '', ''); + $result = $paiement->addPaymentToBank($user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, GETPOST('chqemetteur'), GETPOST('chqbank')); if ($result < 0) { setEventMessages($paiement->error, $paiement->errors, 'errors'); $error++; diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql index ab037313dfb..30636a8bb98 100644 --- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql +++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql @@ -509,3 +509,8 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) value -- VMYSQL4.3 ALTER TABLE llx_user MODIFY COLUMN fk_soc integer NULL; -- VPGSQL8.2 ALTER TABLE llx_user ALTER COLUMN fk_soc DROP NOT NULL; + +-- Add column to help to fix a very critical bug when transferring into accounting bank record of a bank account into another currency. +-- Idea is to update this column manually in v15 with value in currency of company for bank that are not into the main currency and the transfer +-- into accounting will use it in priority if value is not null. +ALTER TABLE llx_bank ADD COLUMN amount_main_currency double(24,8) NULL; diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 4935577cbf8..070f3a2c5da 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -557,3 +557,8 @@ UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NUL DELETE FROM llx_rights_def WHERE module = 'hrm' AND perms = 'employee'; + +-- Sequence to fix the content of llx_bank.amount_main_currency +-- DROP TABLE tmp_bank; +-- CREATE TABLE tmp_bank SELECT b.rowid, b.amount, p.rowid as pid, p.amount as pamount, p.multicurrency_amount as pmulticurrencyamount FROM llx_bank as b INNER JOIN llx_bank_url as bu ON bu.fk_bank=b.rowid AND bu.type = 'payment' INNER JOIN llx_paiement as p ON bu.url_id = p.rowid WHERE p.multicurrency_amount <> 0 AND p.multicurrency_amount <> p.amount; +-- UPDATE llx_bank as b SET b.amount_main_currency = (SELECT tb.pamount FROM tmp_bank as tb WHERE tb.rowid = b.rowid) WHERE b.amount_main_currency IS NULL; diff --git a/htdocs/install/mysql/tables/llx_bank.sql b/htdocs/install/mysql/tables/llx_bank.sql index 0e1dbc403da..d0a8e34790b 100644 --- a/htdocs/install/mysql/tables/llx_bank.sql +++ b/htdocs/install/mysql/tables/llx_bank.sql @@ -24,7 +24,8 @@ create table llx_bank tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, datev date, -- date de valeur dateo date, -- date operation - amount double(24,8) NOT NULL default 0, + amount double(24,8) NOT NULL default 0, -- amount in the currency of the bank account + amount_main_currency double(24,8) NULL, -- amount in the main currency of the company label varchar(255), fk_account integer, fk_user_author integer, From 68d11f2e892468037b6aa5e18a866de4d29845bc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 02:42:32 +0200 Subject: [PATCH 19/23] Fix phpunit regression --- htdocs/compta/facture/class/facture.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index fab80677c25..b1eb8656645 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -843,7 +843,7 @@ class Facture extends CommonInvoice $newinvoiceline->situation_percent, $newinvoiceline->fk_prev_id, $newinvoiceline->fk_unit, - $newinvoiceline->pu_ht_devise + $newinvoiceline->multicurrency_subprice ); // Defined the new fk_parent_line From 1aecff854bd9dc79d7b64f27d4d8c339a7bf61fa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 14:40:29 +0200 Subject: [PATCH 20/23] Fix missing limit in redirect --- htdocs/compta/bank/bankentries_list.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index 524d8c79d4a..421080951f2 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -276,6 +276,9 @@ if ((GETPOST('confirm_savestatement', 'alpha') || GETPOST('confirm_reconcile', ' if ($offset) { $param .= '&offset='.urlencode($offset); } + if ($limit) { + $param .= '&limit='.urlencode($limit); + } if ($search_conciliated != '' && $search_conciliated != '-1') { $param .= '&search_conciliated='.urlencode($search_conciliated); } From da0fcb556fee1104cbdce6398d861f76b61fc392 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 15:28:01 +0200 Subject: [PATCH 21/23] Fix css --- htdocs/fourn/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 3889ab026a0..5a9b1054773 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -3014,7 +3014,7 @@ if ($action == 'create') { } // Show link for "recalculate" if ($object->getVentilExportCompta() == 0) { - $s = $langs->trans("ReCalculate").' '; + $s = ''.$langs->trans("ReCalculate").' '; $s .= ''.$langs->trans("Mode1").''; $s .= ' / '; $s .= ''.$langs->trans("Mode2").''; From 71516ecd3e92961001a5b6fb27b84461f4403c71 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 9 Apr 2022 15:48:25 +0200 Subject: [PATCH 22/23] Clean package.json to avoid false alert of security (not used) Conflicts: package.json --- package.json => test/acceptance/package.json | 5 ----- 1 file changed, 5 deletions(-) rename package.json => test/acceptance/package.json (75%) diff --git a/package.json b/test/acceptance/package.json similarity index 75% rename from package.json rename to test/acceptance/package.json index 02c9b2abcb9..9bf55927540 100644 --- a/package.json +++ b/test/acceptance/package.json @@ -7,9 +7,4 @@ "scripts": { "test:e2e": "node_modules/cucumber/bin/cucumber-js --require test/acceptance/index.js --require test/acceptance/setup.js --require test/acceptance/stepDefinitions -f node_modules/cucumber-pretty" }, - "dependencies": { - "chart.js": "^2.9.4", - "cucumber-pretty": "^6.0.0", - "node-fetch": "^2.6.1" - } } From 18488cf1dde807699899ca6c95c2e87482a4d285 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 11 Apr 2022 13:53:35 +0200 Subject: [PATCH 23/23] FIX replenish and manage product stock by warhouse --- htdocs/product/stock/replenish.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 0f13770d3b3..a4ce5577361 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -904,10 +904,10 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Desired stock - print ''.($fk_entrepot > 0 ? $desiredstockwarehouse : $desiredstock).''; + print ''.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $desiredstockwarehouse : $desiredstock).''; // Limit stock for alert - print ''.($fk_entrepot > 0 ? $alertstockwarehouse : $alertstock).''; + print ''.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $alertstockwarehouse : $alertstock).''; // Current stock (all warehouses) print ''.$warning.$stock; @@ -923,7 +923,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''.$ordered.' '.$picto.''; // To order - print ''; + print ''; // Supplier print '';