From 63a47112ae3280e9f921f1e7ad1395cb0f7266f5 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 16 Jul 2021 11:14:30 +0200 Subject: [PATCH 001/473] new: #18162 --- htdocs/core/modules/modProjet.class.php | 6 ++++++ htdocs/langs/en_US/admin.lang | 5 +++-- htdocs/langs/fr_FR/admin.lang | 3 ++- htdocs/projet/tasks/time.php | 12 ++++++------ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index 25448f239e6..7502fbffa81 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -202,6 +202,12 @@ class modProjet extends DolibarrModules $this->rights[$r][4] = 'all'; $this->rights[$r][5] = 'supprimer'; + $r++; + $this->rights[$r][0] = 145; // id de la permission + $this->rights[$r][1] = "Can enter time consumed on assigned tasks (timesheet)"; // libelle de la permission + $this->rights[$r][2] = 'w'; // type de la permission (deprecie a ce jour) + $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut + $this->rights[$r][4] = 'time'; // Menus //------- diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index a05c9e7ea97..13dbef8bff3 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -707,7 +707,8 @@ Permission34=Delete products Permission36=See/manage hidden products Permission38=Export products Permission39=Ignore minimum price -Permission41=Read projects and tasks (shared project and projects I'm contact for). Can also enter time consumed, for me or my hierarchy, on assigned tasks (Timesheet) +Permission41=Read projects and tasks (shared project and projects I'm contact for). +Permission145=Can enter time consumed, for me or my hierarchy, on assigned tasks (Timesheet) Permission42=Create/modify projects (shared project and projects I'm contact for). Can also create tasks and assign users to project and tasks Permission44=Delete projects (shared project and projects I'm contact for) Permission45=Export projects @@ -2145,4 +2146,4 @@ RandomlySelectedIfSeveral=Randomly selected if several pictures are available DatabasePasswordObfuscated=Database password is obfuscated in conf file DatabasePasswordNotObfuscated=Database password is NOT obfuscated in conf file APIsAreNotEnabled=APIs modules are not enabled -YouShouldSetThisToOff=You should set this to 0 or off \ No newline at end of file +YouShouldSetThisToOff=You should set this to 0 or off diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 57a50388a4f..0d0dadf3327 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -707,7 +707,8 @@ Permission34=Supprimer les produits Permission36=Voir/gérer les produits cachés Permission38=Exporter les produits Permission39=Ignorer le prix minimum -Permission41=Lire les projets et tâches (partagés ou dont vous n'êtes pas contact). Permet la saisie de temps passé, pour vous-même et votre hiérarchie (vos subordonnés), sur les tâches assignées (Feuilles de temps). +Permission41=Lire les projets et tâches (partagés ou dont vous n'êtes pas contact). +Permission145=Permet la saisie de temps passé, pour vous-même et votre hiérarchie (vos subordonnés), sur les tâches assignées (Feuilles de temps). Permission42=Créer/modifier les projets (projets partagés et projets pour lesquels je suis contact). Permet aussi de créer des tâches et d'assigner des utilisateurs aux projets et tâches. Permission44=Supprimer les projets et tâches (partagés ou dont je suis contact) Permission45=Exporter les projets diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index a9316bcedcd..4cac12ad801 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -149,7 +149,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $action = ''; } -if ($action == 'addtimespent' && $user->rights->projet->lire) { +if ($action == 'addtimespent' && $user->rights->projet->time) { $error = 0; $timespent_durationhour = GETPOST('timespent_durationhour', 'int'); @@ -281,7 +281,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } } -if ($action == 'confirm_delete' && $confirm == "yes" && $user->rights->projet->lire) { +if ($action == 'confirm_delete' && $confirm == "yes" && $user->rights->projet->supprimer) { $object->fetchTimeSpent(GETPOST('lineid', 'int')); // TODO Check that ($task_time->fk_user == $user->id || in_array($task_time->fk_user, $childids)) $result = $object->delTimeSpent($user); @@ -722,7 +722,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { $linktocreatetimeBtnStatus = 0; $linktocreatetimeUrl = ''; $linktocreatetimeHelpText = ''; - if ($user->rights->projet->all->lire || $user->rights->projet->lire) { // To enter time, read permission is enough + if ($user->rights->projet->all->lire || $user->rights->projet->time) { if ($projectstatic->public || $userRead > 0) { $linktocreatetimeBtnStatus = 1; @@ -940,7 +940,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { print ''; } elseif ($action == 'splitline') { print ''; - } elseif ($action == 'createtime' && $user->rights->projet->lire) { + } elseif ($action == 'createtime' && $user->rights->projet->time) { print ''; } elseif ($massaction == 'generateinvoice' && $user->rights->facture->lire) { print ''; @@ -1122,7 +1122,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { /* * Form to add a new line of time spent */ - if ($action == 'createtime' && $user->rights->projet->lire) { + if ($action == 'createtime' && $user->rights->projet->time) { print ''."\n"; if (!empty($id)) { print ''; @@ -1537,7 +1537,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { print ''; print '
'; print ''; - } elseif ($user->rights->projet->lire || $user->rights->projet->all->creer) { // Read project and enter time consumed on assigned tasks + } elseif ($user->rights->projet->time || $user->rights->projet->all->creer) { // Read project and enter time consumed on assigned tasks if ($task_time->fk_user == $user->id || in_array($task_time->fk_user, $childids) || $user->rights->projet->all->creer) { if ($conf->MAIN_FEATURES_LEVEL >= 2) { print ' '; From ab48351d15ce4fa150618fd2f189039fd8a84379 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 11:10:58 +0200 Subject: [PATCH 002/473] NEW: deposit payment terms: database fields --- htdocs/install/mysql/migration/14.0.0-15.0.0.sql | 5 +++++ htdocs/install/mysql/tables/llx_c_payment_term.sql | 1 + htdocs/install/mysql/tables/llx_commande.sql | 1 + htdocs/install/mysql/tables/llx_propal.sql | 1 + htdocs/install/mysql/tables/llx_societe.sql | 1 + 5 files changed, 9 insertions(+) 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 03bb7631dda..3e5d86b5dd6 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 @@ -149,3 +149,8 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (20, '2010', ' INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (20, '2011', 'Ideell förening'); INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (20, '2012', 'Stiftelse'); +-- Deposit generation helper with specific payment terms +ALTER TABLE llx_c_payment_term ADD COLUMN deposit_percent real DEFAULT NULL AFTER decalage; +ALTER TABLE llx_societe ADD COLUMN deposit_percent real DEFAULT NULL AFTER cond_reglement; +ALTER TABLE llx_propal ADD COLUMN deposit_percent real DEFAULT NULL AFTER fk_cond_reglement; +ALTER TABLE llx_commande ADD COLUMN deposit_percent real DEFAULT NULL AFTER fk_cond_reglement; diff --git a/htdocs/install/mysql/tables/llx_c_payment_term.sql b/htdocs/install/mysql/tables/llx_c_payment_term.sql index 087ab63c184..6ed1c580e4f 100644 --- a/htdocs/install/mysql/tables/llx_c_payment_term.sql +++ b/htdocs/install/mysql/tables/llx_c_payment_term.sql @@ -30,6 +30,7 @@ create table llx_c_payment_term type_cdr tinyint, -- Type of change date reckoning. 1=Payment at end of current month, 2=the Nth of next month nbjour smallint, decalage smallint, + deposit_percent real DEFAULT NULL, module varchar(32) NULL, position integer NOT NULL DEFAULT 0 )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_commande.sql b/htdocs/install/mysql/tables/llx_commande.sql index e3a075933c2..096bd8305a2 100644 --- a/htdocs/install/mysql/tables/llx_commande.sql +++ b/htdocs/install/mysql/tables/llx_commande.sql @@ -63,6 +63,7 @@ create table llx_commande fk_account integer, -- bank account fk_currency varchar(3), -- currency code fk_cond_reglement integer, -- condition de reglement + deposit_percent real DEFAULT NULL, -- default deposit % if payment term needs it fk_mode_reglement integer, -- mode de reglement date_livraison datetime default NULL, diff --git a/htdocs/install/mysql/tables/llx_propal.sql b/htdocs/install/mysql/tables/llx_propal.sql index 7c94086b3b9..e795d63ff8b 100644 --- a/htdocs/install/mysql/tables/llx_propal.sql +++ b/htdocs/install/mysql/tables/llx_propal.sql @@ -58,6 +58,7 @@ create table llx_propal fk_account integer, -- bank account fk_currency varchar(3), -- currency code fk_cond_reglement integer, -- condition de reglement (30 jours, fin de mois ...) + deposit_percent real DEFAULT NULL, -- default deposit % if payment term needs it fk_mode_reglement integer, -- mode de reglement (Virement, Prelevement) note_private text, diff --git a/htdocs/install/mysql/tables/llx_societe.sql b/htdocs/install/mysql/tables/llx_societe.sql index 7112b6e93ea..eb2ac1cd136 100644 --- a/htdocs/install/mysql/tables/llx_societe.sql +++ b/htdocs/install/mysql/tables/llx_societe.sql @@ -92,6 +92,7 @@ create table llx_societe remise_supplier real DEFAULT 0, -- discount by default granted by this supplier mode_reglement tinyint, -- payment mode customer cond_reglement tinyint, -- payment term customer + deposit_percent real DEFAULT NULL, -- default deposit % if payment term needs it transport_mode tinyint, -- transport mode customer (Intracomm report) mode_reglement_supplier tinyint, -- payment mode supplier cond_reglement_supplier tinyint, -- payment term supplier From ef624ec5bc5cbb1daab90d2fe6fdf5e8026bfcfb Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 11:34:30 +0200 Subject: [PATCH 003/473] NEW: deposit payment terms: add field into dictionary admin page --- htdocs/admin/dict.php | 23 +++++++++++++++++------ htdocs/langs/en_US/bills.lang | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 9073c9e238c..02a3cb07ffa 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -207,7 +207,7 @@ $tabsql[8] = "SELECT t.id as rowid, t.code as code, t.libelle, t.fk_country as $tabsql[9] = "SELECT c.code_iso as code, c.label, c.unicode, c.active FROM ".MAIN_DB_PREFIX."c_currencies AS c"; $tabsql[10] = "SELECT t.rowid, t.code, t.taux, t.localtax1_type, t.localtax1, t.localtax2_type, t.localtax2, c.label as country, c.code as country_code, t.fk_pays as country_id, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid"; $tabsql[11] = "SELECT t.rowid as rowid, t.element, t.source, t.code, t.libelle, t.position, t.active FROM ".MAIN_DB_PREFIX."c_type_contact AS t"; -$tabsql[12] = "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = ".getEntity($tabname[12]); +$tabsql[12] = "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.deposit_percent, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = ".getEntity($tabname[12]); $tabsql[13] = "SELECT c.id as rowid, c.code, c.libelle, c.type, c.active, c.entity FROM ".MAIN_DB_PREFIX."c_paiement AS c WHERE c.entity = ".getEntity($tabname[13]); $tabsql[14] = "SELECT e.rowid as rowid, e.code as code, e.label, e.price, e.organization, e.fk_pays as country_id, c.code as country_code, c.label as country, e.active FROM ".MAIN_DB_PREFIX."c_ecotaxe AS e, ".MAIN_DB_PREFIX."c_country as c WHERE e.fk_pays=c.rowid and c.active=1"; $tabsql[15] = "SELECT rowid as rowid, code, label as libelle, width, height, unit, active FROM ".MAIN_DB_PREFIX."c_paper_format"; @@ -299,7 +299,7 @@ $tabfield[8] = "code,libelle,country_id,country".(!empty($conf->global->SOCIETE_ $tabfield[9] = "code,label,unicode"; $tabfield[10] = "country_id,country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfield[11] = "element,source,code,libelle,position"; -$tabfield[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity"; +$tabfield[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity"; $tabfield[13] = "code,libelle,type,entity"; $tabfield[14] = "code,label,price,organization,country"; $tabfield[15] = "code,libelle,width,height,unit"; @@ -345,7 +345,7 @@ $tabfieldvalue[8] = "code,libelle,country".(!empty($conf->global->SOCIETE_SORT_O $tabfieldvalue[9] = "code,label,unicode"; $tabfieldvalue[10] = "country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldvalue[11] = "element,source,code,libelle,position"; -$tabfieldvalue[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder"; +$tabfieldvalue[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder"; $tabfieldvalue[13] = "code,libelle,type"; $tabfieldvalue[14] = "code,label,price,organization,country"; $tabfieldvalue[15] = "code,libelle,width,height,unit"; @@ -391,7 +391,7 @@ $tabfieldinsert[8] = "code,libelle,fk_country".(!empty($conf->global->SOCIETE_SO $tabfieldinsert[9] = "code_iso,label,unicode"; $tabfieldinsert[10] = "fk_pays,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldinsert[11] = "element,source,code,libelle,position"; -$tabfieldinsert[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity"; +$tabfieldinsert[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity"; $tabfieldinsert[13] = "code,libelle,type,entity"; $tabfieldinsert[14] = "code,label,price,organization,fk_pays"; $tabfieldinsert[15] = "code,label,width,height,unit"; @@ -738,6 +738,9 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($fieldnamekey == 'libelle_facture') { $fieldnamekey = 'LabelOnDocuments'; } + if ($fieldnamekey == 'deposit_percent') { + $fieldnamekey = 'DepositPercent'; + } if ($fieldnamekey == 'nbjour') { $fieldnamekey = 'NbOfDays'; } @@ -1284,6 +1287,10 @@ if ($id) { if ($value == 'libelle_facture') { $valuetoshow = $form->textwithtooltip($langs->trans("LabelOnDocuments"), $langs->trans("LabelUsedByDefault"), 2, 1, img_help(1, '')); } + if ($value == 'deposit_percent') { + $valuetoshow = $langs->trans('DepositPercent'); + $class = 'right'; + } if ($value == 'country') { if (in_array('region_id', $fieldlist)) { print ' '; continue; @@ -1635,6 +1642,10 @@ if ($id) { if ($value == 'libelle_facture') { $valuetoshow = $langs->trans("LabelOnDocuments"); } + if ($value == 'deposit_percent') { + $valuetoshow = $langs->trans('DepositPercent'); + $cssprefix = 'right '; + } if ($value == 'country') { $valuetoshow = $langs->trans("Country"); } @@ -1995,7 +2006,7 @@ if ($id) { if ($value == 'tracking') { $class .= ' tdoverflowauto'; } - if (in_array($value, array('pos', 'position'))) { + if (in_array($value, array('pos', 'position', 'deposit_percent'))) { $class .= ' right'; } if (in_array($value, array('localtax1_type', 'localtax2_type'))) { @@ -2380,7 +2391,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') if ($fieldlist[$field] == 'code') { $class = 'maxwidth100'; } - if (in_array($fieldlist[$field], array('pos', 'position'))) { + if (in_array($fieldlist[$field], array('pos', 'position', 'deposit_percent'))) { $classtd = 'right'; $class = 'maxwidth50 right'; } if (in_array($fieldlist[$field], array('dayrule', 'day', 'month', 'year', 'use_default', 'affect', 'delay', 'public', 'sortorder', 'sens', 'category_type', 'fk_parent'))) { diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index e475a815ac9..86344105168 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -424,6 +424,7 @@ FixAmount=Fixed amount - 1 line with label '%s' VarAmount=Variable amount (%% tot.) VarAmountOneLine=Variable amount (%% tot.) - 1 line with label '%s' VarAmountAllLines=Variable amount (%% tot.) - all lines from origin +DepositPercent=Deposit %% # PaymentType PaymentTypeVIR=Bank transfer PaymentTypeShortVIR=Bank transfer From 004b52f590ebed7ee7acfccf99bac8184dbcc947 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 12:05:38 +0200 Subject: [PATCH 004/473] NEW: deposit payment terms: add field into CRUD methods --- htdocs/comm/propal/class/propal.class.php | 9 ++++++++- htdocs/commande/class/commande.class.php | 15 +++++++++++++-- htdocs/societe/class/societe.class.php | 8 +++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index a7b5c465226..f2132799007 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -203,6 +203,7 @@ class Propal extends CommonObject public $total; public $cond_reglement_code; + public $deposit_percent; public $mode_reglement_code; public $remise = 0; public $remise_percent = 0; @@ -309,6 +310,7 @@ class Propal extends CommonObject 'fk_account' =>array('type'=>'integer', 'label'=>'BankAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>150), 'fk_currency' =>array('type'=>'varchar(3)', 'label'=>'Currency', 'enabled'=>1, 'visible'=>-1, 'position'=>155), 'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'PaymentTerm', 'enabled'=>1, 'visible'=>-1, 'position'=>160), + 'deposit_percent' =>array('type'=>'double', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>161), 'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'PaymentMode', 'enabled'=>1, 'visible'=>-1, 'position'=>165), 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>170), 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>175), @@ -1080,6 +1082,7 @@ class Propal extends CommonObject $sql .= ", model_pdf"; $sql .= ", fin_validite"; $sql .= ", fk_cond_reglement"; + $sql .= ", deposit_percent"; $sql .= ", fk_mode_reglement"; $sql .= ", fk_account"; $sql .= ", ref_client"; @@ -1113,6 +1116,7 @@ class Propal extends CommonObject $sql .= ", '".$this->db->escape($this->model_pdf)."'"; $sql .= ", ".($this->fin_validite != '' ? "'".$this->db->idate($this->fin_validite)."'" : "NULL"); $sql .= ", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) : 'NULL'); + $sql .= ", ".(! empty($this->deposit_percent) ? floatval($this->deposit_percent) : 'NULL'); $sql .= ", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) : 'NULL'); $sql .= ", ".($this->fk_account > 0 ? ((int) $this->fk_account) : 'NULL'); $sql .= ", '".$this->db->escape($this->ref_client)."'"; @@ -1336,6 +1340,7 @@ class Propal extends CommonObject if ($objsoc->fetch($socid) > 0) { $object->socid = $objsoc->id; $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0); + $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent : null); $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0); $object->fk_delivery_address = ''; @@ -1463,7 +1468,7 @@ class Propal extends CommonObject $sql .= ", c.label as statut_label"; $sql .= ", ca.code as availability_code, ca.label as availability"; $sql .= ", dr.code as demand_reason_code, dr.label as demand_reason"; - $sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc"; + $sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent"; $sql .= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement"; $sql .= " FROM ".MAIN_DB_PREFIX."propal as p"; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_propalst as c ON p.fk_statut = c.id'; @@ -1546,6 +1551,7 @@ class Propal extends CommonObject $this->cond_reglement_code = $obj->cond_reglement_code; $this->cond_reglement = $obj->cond_reglement; $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc; + $this->deposit_percent = $obj->deposit_percent; $this->extraparams = (array) json_decode($obj->extraparams, true); @@ -1655,6 +1661,7 @@ class Propal extends CommonObject $sql .= " fk_user_valid=".(isset($this->user_valid) ? $this->user_valid : "null").","; $sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").","; $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").","; + $sql .= " deposit_percent=".(! empty($this->deposit_percent) ? floatval($this->deposit_percent) : "null"); $sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->mode_reglement_id : "null").","; $sql .= " fk_input_reason=".(isset($this->demand_reason_id) ? $this->demand_reason_id : "null").","; $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").","; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index e3675129198..90566bd2051 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -133,6 +133,11 @@ class Commande extends CommonOrder */ public $cond_reglement_code; + /** + * @var double Deposit % for payment terms + */ + public $deposit_percent; + /** * @var int bank account ID */ @@ -321,6 +326,7 @@ class Commande extends CommonOrder 'fk_account' =>array('type'=>'integer', 'label'=>'BankAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>170), 'fk_currency' =>array('type'=>'varchar(3)', 'label'=>'MulticurrencyID', 'enabled'=>1, 'visible'=>-1, 'position'=>175), 'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'PaymentTerm', 'enabled'=>1, 'visible'=>-1, 'position'=>180), + 'deposit_percent' =>array('type'=>'double', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>181), 'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'PaymentMode', 'enabled'=>1, 'visible'=>-1, 'position'=>185), 'date_livraison' =>array('type'=>'date', 'label'=>'DateDeliveryPlanned', 'enabled'=>1, 'visible'=>-1, 'position'=>190), 'fk_shipping_method' =>array('type'=>'integer', 'label'=>'ShippingMethod', 'enabled'=>1, 'visible'=>-1, 'position'=>195), @@ -924,7 +930,7 @@ class Commande extends CommonOrder $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande ("; $sql .= " ref, fk_soc, date_creation, fk_user_author, fk_projet, date_commande, source, note_private, note_public, ref_ext, ref_client, ref_int"; - $sql .= ", model_pdf, fk_cond_reglement, fk_mode_reglement, fk_account, fk_availability, fk_input_reason, date_livraison, fk_delivery_address"; + $sql .= ", model_pdf, fk_cond_reglement, deposit_percent, fk_mode_reglement, fk_account, fk_availability, fk_input_reason, date_livraison, fk_delivery_address"; $sql .= ", fk_shipping_method"; $sql .= ", fk_warehouse"; $sql .= ", remise_absolue, remise_percent"; @@ -945,6 +951,7 @@ class Commande extends CommonOrder $sql .= ", ".($this->ref_int ? "'".$this->db->escape($this->ref_int)."'" : "null"); $sql .= ", '".$this->db->escape($this->model_pdf)."'"; $sql .= ", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) : "null"); + $sql .= ", ".(! empty($this->deposit_percent) ? floatval($this->deposit_percent) : "null"); $sql .= ", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) : "null"); $sql .= ", ".($this->fk_account > 0 ? ((int) $this->fk_account) : 'NULL'); $sql .= ", ".($this->availability_id > 0 ? ((int) $this->availability_id) : "null"); @@ -1193,6 +1200,7 @@ class Commande extends CommonOrder if ($objsoc->fetch($socid) > 0) { $this->socid = $objsoc->id; $this->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0); + $this->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent : null); $this->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0); $this->fk_project = 0; $this->fk_delivery_address = 0; @@ -1335,6 +1343,7 @@ class Commande extends CommonOrder $this->socid = $object->socid; $this->fk_project = $object->fk_project; $this->cond_reglement_id = $object->cond_reglement_id; + $this->deposit_percent = $object->deposit_percent; $this->mode_reglement_id = $object->mode_reglement_id; $this->fk_account = $object->fk_account; $this->availability_id = $object->availability_id; @@ -1783,7 +1792,7 @@ class Commande extends CommonOrder } $sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_statut'; - $sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason'; + $sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.deposit_percent, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason'; $sql .= ', c.fk_account'; $sql .= ', c.date_commande, c.date_valid, c.tms'; $sql .= ', c.date_livraison as delivery_date'; @@ -1875,6 +1884,7 @@ class Commande extends CommonOrder $this->cond_reglement_code = $obj->cond_reglement_code; $this->cond_reglement = $obj->cond_reglement_libelle; $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc; + $this->deposit_percent = $obj->deposit_percent; $this->fk_account = $obj->fk_account; $this->availability_id = $obj->fk_availability; $this->availability_code = $obj->availability_code; @@ -3309,6 +3319,7 @@ class Commande extends CommonOrder $sql .= " fk_user_valid=".(isset($this->user_valid) ? $this->user_valid : "null").","; $sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").","; $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").","; + $sql .= " deposit_percent=".(! empty($this->deposit_percent) ? floatval($this->deposit_percent) : "null"); $sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->mode_reglement_id : "null").","; $sql .= " date_livraison=".(strval($this->delivery_date) != '' ? "'".$this->db->idate($this->delivery_date)."'" : 'null').","; $sql .= " fk_shipping_method=".(isset($this->shipping_method_id) ? $this->shipping_method_id : "null").","; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 8f0e2c84805..16bcfdfb52f 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -208,6 +208,7 @@ class Societe extends CommonObject //'remise_supplier' =>array('type'=>'double', 'label'=>'SupplierDiscount', 'enabled'=>1, 'visible'=>-1, 'position'=>290, 'isameasure'=>1), 'mode_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Mode reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>295), 'cond_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Cond reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>300), + 'deposit_percent' =>array('type'=>'double', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>301), 'mode_reglement_supplier' =>array('type'=>'integer', 'label'=>'Mode reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>305), 'outstanding_limit' =>array('type'=>'double(24,8)', 'label'=>'OutstandingBill', 'enabled'=>1, 'visible'=>-1, 'position'=>310, 'isameasure'=>1), 'order_min_amount' =>array('type'=>'double(24,8)', 'label'=>'Order min amount', 'enabled'=>'!empty($conf->commande->enabled) && !empty($conf->global->ORDER_MANAGE_MIN_AMOUNT)', 'visible'=>-1, 'position'=>315, 'isameasure'=>1), @@ -481,6 +482,9 @@ class Societe extends CommonObject public $remise_percent; public $remise_supplier_percent; + public $mode_reglement_id; + public $cond_reglement_id; + public $deposit_percent; public $mode_reglement_supplier_id; public $cond_reglement_supplier_id; public $transport_mode_supplier_id; @@ -1432,6 +1436,7 @@ class Societe extends CommonObject $sql .= ",mode_reglement = ".(!empty($this->mode_reglement_id) ? "'".$this->db->escape($this->mode_reglement_id)."'" : "null"); $sql .= ",cond_reglement = ".(!empty($this->cond_reglement_id) ? "'".$this->db->escape($this->cond_reglement_id)."'" : "null"); + $sql .= ",deposit_percent = ".(!empty($this->deposit_percent) ? floatval($this->deposit_percent) : "null"); $sql .= ",transport_mode = ".(!empty($this->transport_mode_id) ? "'".$this->db->escape($this->transport_mode_id)."'" : "null"); $sql .= ",mode_reglement_supplier = ".(!empty($this->mode_reglement_supplier_id) ? "'".$this->db->escape($this->mode_reglement_supplier_id)."'" : "null"); $sql .= ",cond_reglement_supplier = ".(!empty($this->cond_reglement_supplier_id) ? "'".$this->db->escape($this->cond_reglement_supplier_id)."'" : "null"); @@ -1651,7 +1656,7 @@ class Societe extends CommonObject $sql .= ', spe.accountancy_code_buy, spe.accountancy_code_sell'; } $sql .= ', s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur, s.parent, s.barcode'; - $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.transport_mode'; + $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.deposit_percent, s.transport_mode'; $sql .= ', s.fk_account, s.tva_assuj'; $sql .= ', s.mode_reglement_supplier, s.cond_reglement_supplier, s.transport_mode_supplier'; $sql .= ', s.localtax1_assuj, s.localtax1_value, s.localtax2_assuj, s.localtax2_value, s.fk_prospectlevel, s.default_lang, s.logo, s.logo_squarred'; @@ -1828,6 +1833,7 @@ class Societe extends CommonObject $this->mode_reglement_id = $obj->mode_reglement; $this->cond_reglement_id = $obj->cond_reglement; + $this->deposit_percent = $obj->deposit_percent; $this->transport_mode_id = $obj->transport_mode; $this->mode_reglement_supplier_id = $obj->mode_reglement_supplier; $this->cond_reglement_supplier_id = $obj->cond_reglement_supplier; From 4b3fc4d7f33f3b2489a2e763c0e9e551202b0343 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 13:02:32 +0200 Subject: [PATCH 005/473] NEW: deposit payment terms: add input in payment conditions form --- htdocs/core/class/html.form.class.php | 67 +++++++++++++++++++++------ 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 8deda2ecd09..61b00812efd 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3609,7 +3609,7 @@ class Form dol_syslog(__METHOD__, LOG_DEBUG); - $sql = "SELECT rowid, code, libelle as label"; + $sql = "SELECT rowid, code, libelle as label, deposit_percent"; $sql .= " FROM ".MAIN_DB_PREFIX.'c_payment_term'; $sql .= " WHERE entity IN (".getEntity('c_payment_term').")"; $sql .= " AND active > 0"; @@ -3621,11 +3621,11 @@ class Form $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); - // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($langs->trans("PaymentConditionShort".$obj->code) != ("PaymentConditionShort".$obj->code) ? $langs->trans("PaymentConditionShort".$obj->code) : ($obj->label != '-' ? $obj->label : '')); $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code; $this->cache_conditions_paiements[$obj->rowid]['label'] = $label; + $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent; $i++; } @@ -3881,9 +3881,10 @@ class Form * @param int $addempty Add an empty entry * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info * @param string $morecss Add more CSS on select tag + * @param float $deposit_percent % of deposit if needed by payment conditions * @return void */ - public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '') + public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = null) { // phpcs:enable global $langs, $user, $conf; @@ -3901,13 +3902,24 @@ class Form if ($addempty) { print ''; } + + $selectedDepositPercent = null; foreach ($this->cache_conditions_paiements as $id => $arrayconditions) { if ($selected == $id) { - print ''; } print ''; @@ -3915,6 +3927,28 @@ class Form print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } print ajax_combobox($htmlname); + print ' '; + print ' + '; } @@ -5099,13 +5133,14 @@ class Form /** * Show a form to select payment conditions * - * @param int $page Page - * @param string $selected Id condition pre-selectionne - * @param string $htmlname Name of select html field - * @param int $addempty Add empty entry + * @param int $page Page + * @param string $selected Id condition pre-selectionne + * @param string $htmlname Name of select html field + * @param int $addempty Add empty entry + * @param float $deposit_percent % of deposit if needed by payment conditions * @return void */ - public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0) + public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $deposit_percent = null) { // phpcs:enable global $langs; @@ -5113,14 +5148,20 @@ class Form print '
'; print ''; print ''; - $this->select_conditions_paiements($selected, $htmlname, -1, $addempty); + $this->select_conditions_paiements($selected, $htmlname, -1, $addempty, 0, '', $deposit_percent); print ''; print '
'; } else { if ($selected) { $this->load_cache_conditions_paiements(); if (isset($this->cache_conditions_paiements[$selected])) { - print $this->cache_conditions_paiements[$selected]['label']; + $label = $this->cache_conditions_paiements[$selected]['label']; + + if (! empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) { + $label = sprintf($label, ! empty($deposit_percent) ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent']); + } + + print $label; } else { $langs->load('errors'); print $langs->trans('ErrorNotInDictionaryPaymentConditions'); From 4d6c1d892b120c314283be4c66a210964d6b4590 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:03:35 +0200 Subject: [PATCH 006/473] NEW: deposit payment terms: set deposit percentage in company card --- htdocs/comm/card.php | 6 +++--- htdocs/core/class/commonobject.class.php | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index c9f422d78c8..b511d932f52 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -169,7 +169,7 @@ if (empty($reshook)) { // terms of the settlement if ($action == 'setconditions' && $user->rights->societe->creer) { $object->fetch($id); - $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int')); + $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'int')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } @@ -411,9 +411,9 @@ if ($object->id > 0) { print ''; print ''; if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, $object->deposit_percent); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'none', 0, $object->deposit_percent); } print ""; print ''; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 7adf7a89079..01f42a73417 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2548,10 +2548,11 @@ abstract class CommonObject /** * Change the payments terms * - * @param int $id Id of new payment terms - * @return int >0 if OK, <0 if KO + * @param int $id Id of new payment terms + * @param float $deposit_percent % of deposit if needed by payment terms + * @return int >0 if OK, <0 if KO */ - public function setPaymentTerms($id) + public function setPaymentTerms($id, $deposit_percent = null) { dol_syslog(get_class($this).'::setPaymentTerms('.$id.')'); if ($this->statut >= 0 || $this->element == 'societe') { @@ -2564,8 +2565,17 @@ abstract class CommonObject $fieldname = 'cond_reglement_supplier'; } + if (empty($deposit_percent) || $deposit_percent < 0) { + $deposit_percent = null; + } + + if ($deposit_percent > 100) { + $deposit_percent = 100; + } + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql .= " SET ".$fieldname." = ".(($id > 0 || $id == '0') ? ((int) $id) : 'NULL'); + $sql .= " , deposit_percent = " . (! empty($deposit_percent) ? floatval($deposit_percent) : 'NULL'); $sql .= ' WHERE rowid='.((int) $this->id); if ($this->db->query($sql)) { @@ -2575,6 +2585,7 @@ abstract class CommonObject $this->cond_reglement_supplier_id = $id; } $this->cond_reglement = $id; // for compatibility + $this->deposit_percent = $deposit_percent; return 1; } else { dol_syslog(get_class($this).'::setPaymentTerms Error '.$sql.' - '.$this->db->error()); From b0aa502ed425aac4b091c8248b8c24d8a1efdd46 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:51:30 +0200 Subject: [PATCH 007/473] NEW: deposit payment terms: set deposit percentage in proposals/orders + get from origin document or company --- htdocs/comm/propal/card.php | 10 ++++++---- htdocs/commande/card.php | 20 +++++++++++++++----- htdocs/core/class/commonobject.class.php | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index cff5c5d0e35..12b7138ce51 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -397,6 +397,7 @@ if (empty($reshook)) { $object->warehouse_id = GETPOST('warehouse_id', 'int'); $object->duree_validite = $duration; $object->cond_reglement_id = GETPOST('cond_reglement_id'); + $object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'int'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); $object->remise_percent = price2num(GETPOST('remise_percent'), '', 2); @@ -429,6 +430,7 @@ if (empty($reshook)) { $object->warehouse_id = GETPOST('warehouse_id', 'int'); $object->duree_validite = price2num(GETPOST('duree_validite', 'alpha')); $object->cond_reglement_id = GETPOST('cond_reglement_id', 'int'); + $object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'int'); $object->mode_reglement_id = GETPOST('mode_reglement_id', 'int'); $object->fk_account = GETPOST('fk_account', 'int'); $object->contact_id = GETPOST('contactid', 'int'); @@ -1358,7 +1360,7 @@ if (empty($reshook)) { $result = $object->set_demand_reason($user, GETPOST('demand_reason_id', 'int')); } elseif ($action == 'setconditions' && $usercancreate) { // Terms of payment - $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int')); + $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'int')); } elseif ($action == 'setremisepercent' && $usercancreate) { $result = $object->set_remise_percent($user, price2num(GETPOST('remise_percent'), '', 2)); } elseif ($action == 'setremiseabsolue' && $usercancreate) { @@ -1647,7 +1649,7 @@ if ($action == 'create') { // Terms of payment print ''.$langs->trans('PaymentConditionsShort').''; print img_picto('', 'paiment'); - $form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id), 'cond_reglement_id', -1, 1); + $form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id), 'cond_reglement_id', -1, 1, 0, '', (GETPOSTISSET('cond_reglement_id_deposit_percent') ? GETPOST('cond_reglement_id_deposit_percent', 'int') : $soc->deposit_percent)); print ''; // Mode of payment @@ -2155,9 +2157,9 @@ if ($action == 'create') { print ''; print ''; if ($object->statut == Propal::STATUS_DRAFT && $action == 'editconditions' && $usercancreate) { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 0, $object->deposit_percent); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 0, $object->deposit_percent); } print ''; print ''; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index decabedc2e8..e933231822a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -268,6 +268,7 @@ if (empty($reshook)) { $object->ref_client = GETPOST('ref_client', 'alpha'); $object->model_pdf = GETPOST('model'); $object->cond_reglement_id = GETPOST('cond_reglement_id'); + $object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'int'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); $object->availability_id = GETPOST('availability_id'); @@ -548,7 +549,7 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setmode' && $usercancreate) { - $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int')); + $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'), GETPOST('mode_reglement_id_deposit_percent', 'int')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } @@ -569,7 +570,7 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setconditions' && $usercancreate) { - $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int')); + $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'int')); if ($result < 0) { dol_print_error($db, $object->error); } else { @@ -1437,6 +1438,10 @@ if ($action == 'create' && $usercancreate) { $currency_code = $conf->currency; + $cond_reglement_id = GETPOST('cond_reglement_id', 'int'); + $deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'int'); + $mode_reglement_id = GETPOST('mode_reglement_id', 'int'); + if (!empty($origin) && !empty($originid)) { // Parse element/subelement (ex: project_task) $element = $subelement = $origin; @@ -1452,6 +1457,9 @@ if ($action == 'create' && $usercancreate) { if (!$cond_reglement_id) { $cond_reglement_id = $soc->cond_reglement_id; } + if (!$deposit_percent) { + $deposit_percent = $soc->deposit_percent; + } if (!$mode_reglement_id) { $mode_reglement_id = $soc->mode_reglement_id; } @@ -1492,6 +1500,7 @@ if ($action == 'create' && $usercancreate) { $soc = $objectsrc->thirdparty; $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0)); // TODO maybe add default value option + $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null)); $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0)); $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0)); $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : (!empty($soc->availability_id) ? $soc->availability_id : 0)); @@ -1524,6 +1533,7 @@ if ($action == 'create' && $usercancreate) { } } else { $cond_reglement_id = $soc->cond_reglement_id; + $deposit_percent = $soc->deposit_percent; $mode_reglement_id = $soc->mode_reglement_id; $fk_account = $soc->fk_account; $availability_id = $soc->availability_id; @@ -1649,7 +1659,7 @@ if ($action == 'create' && $usercancreate) { // Terms of the settlement print ''.$langs->trans('PaymentConditionsShort').''; print img_picto('', 'paiment'); - $form->select_conditions_paiements($cond_reglement_id, 'cond_reglement_id', - 1, 1); + $form->select_conditions_paiements($cond_reglement_id, 'cond_reglement_id', - 1, 1, 0, '', $deposit_percent); print ''; // Mode de reglement @@ -2215,9 +2225,9 @@ if ($action == 'create' && $usercancreate) { print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable); print ''; if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, $object->deposit_percent); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1, $object->deposit_percent); } print ''; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 01f42a73417..2a7c0c87353 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2554,7 +2554,7 @@ abstract class CommonObject */ public function setPaymentTerms($id, $deposit_percent = null) { - dol_syslog(get_class($this).'::setPaymentTerms('.$id.')'); + dol_syslog(get_class($this).'::setPaymentTerms('.$id.', '.var_export($deposit_percent, true).')'); if ($this->statut >= 0 || $this->element == 'societe') { // TODO uniformize field name $fieldname = 'fk_cond_reglement'; From 8cb6cdf1bc1c8a8074fdd5183db913297cdcc0df Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 30 Sep 2021 11:48:32 +0200 Subject: [PATCH 008/473] NEW: deposit payment terms: prefill deposit parameters if coming from an origin with the corresponding payment conditions --- htdocs/compta/facture/card.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 764af7a232a..b2cb45e5b1a 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3256,10 +3256,21 @@ if ($action == 'create') { 'variable' => $langs->transnoentitiesnoconv('VarAmountOneLine', $langs->transnoentitiesnoconv('Deposit')), 'variablealllines' => $langs->transnoentitiesnoconv('VarAmountAllLines') ); - print $form->selectarray('typedeposit', $arraylist, GETPOST('typedeposit', 'aZ09'), 0, 0, 0, '', 1); + $typedeposit = GETPOST('typedeposit', 'aZ09'); + $valuedeposit = GETPOST('valuedeposit', 'int'); + if (empty($typedeposit) && ! empty($objectsrc->deposit_percent)) { + $origin_payment_conditions_deposit_percent = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $objectsrc->cond_reglement_id); + if (! empty($origin_payment_conditions_deposit_percent)) { + $typedeposit = 'variable'; + } + } + if (empty($valuedeposit) && $typedeposit == 'variable' && ! empty($objectsrc->deposit_percent)) { + $valuedeposit = $objectsrc->deposit_percent; + } + print $form->selectarray('typedeposit', $arraylist, $typedeposit, 0, 0, 0, '', 1); print ''; print ''; - print ''.$langs->trans("AmountOrPercent").''; + print ''.$langs->trans("AmountOrPercent").''; print ''; } print ''; From 81ddc6c0f6367c15305bd2223347ca9974ad60ed Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 30 Sep 2021 12:41:07 +0200 Subject: [PATCH 009/473] NEW: deposit payment terms: generate deposit from proposal --- htdocs/comm/propal/card.php | 100 +++++++ htdocs/compta/facture/class/facture.class.php | 260 ++++++++++++++++++ htdocs/langs/en_US/bills.lang | 6 + 3 files changed, 366 insertions(+) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 12b7138ce51..fc16dcdbe16 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -684,11 +684,46 @@ if (empty($reshook)) { $error++; } + $deposit = null; + $locationTarget = $_SERVER['PHP_SELF'] . '?id=' . $object->id; + + if (!$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'int') > 0) { + $deposit = Facture::createDepositFromOrigin($object, $user, 0, GETPOST('validate_generated_deposit', 'int') > 0); + + if ($deposit) { + setEventMessage('DepositGenerated'); + $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id; + } else { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } + } + if (!$error) { $db->commit(); + + if ($deposit && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + $ret = $deposit->fetch($deposit->id); // Reload to get new records + $outputlangs = $langs; + + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang($deposit->thirdparty->default_lang); + $outputlangs->load('products'); + } + + $result = $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + + if ($result < 0) { + setEventMessages($deposit->error, $deposit->errors, 'errors'); + } + } } else { $db->rollback(); } + + header('Location: ' . $locationTarget); + exit; } } } elseif ($action == 'confirm_reopen' && $usercanclose && !GETPOST('cancel', 'alpha')) { @@ -1934,6 +1969,71 @@ if ($action == 'create') { array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => '') // Field to complete private note (not replace) ); + $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + + if (! empty($deposit_percent_from_payment_terms)) { + $object->fetchObjectLinked(); + + $eligibleForDepositGeneration = true; + + if (array_key_exists('facture', $object->linkedObjects)) { + foreach ($object->linkedObjectsIds['facture'] as $invoice) { + if ($invoice->type == Facture::TYPE_DEPOSIT) { + $eligibleForDepositGeneration = false; + break; + } + } + } + + if ($eligibleForDepositGeneration && array_key_exists('commande', $object->linkedObjects)) { + foreach ($object->linkedObjects['commande'] as $order) { + $order->fetchObjectLinked(); + + if (array_key_exists('facture', $order->linkedObjects)) { + foreach ($order->linkedObjects['facture'] as $invoice) { + if ($invoice->type == Facture::TYPE_DEPOSIT) { + $eligibleForDepositGeneration = false; + break 2; + } + } + } + } + } + + if ($eligibleForDepositGeneration) { + $formquestion[] = array( + 'type' => 'onecolumn', + 'name' => 'generate_deposit,validate_generated_deposit', + 'value' => ' + + + ' + ); + } + } + if (!empty($conf->notification->enabled)) { require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; $notify = new Notify($db); diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 22cd946275c..d8265aeef01 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1406,6 +1406,266 @@ class Facture extends CommonInvoice } } + /** + * @param Propal|Commande $origin + * @param User $user + * @param type $notrigger + * @param bool $autoValidate + * @return Facture + */ + static public function createDepositFromOrigin(CommonObject $origin, User $user, $notrigger = 0, $autoValidateDeposit = false, $forceInvoiceDate = null) + { + global $conf, $langs, $hookmanager, $action; + + if (! in_array($origin->element, array('propal', 'commande'))) { + $origin->error = 'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder'; // TRAD + return null; + } + + require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; + + $invoiceDate = ! empty($forceInvoiceDate) ? $forceInvoiceDate : dol_now(); + + if ($invoiceDate > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $origin->error = 'ErrorDateIsInFuture'; + return null; + } + + if ($origin->cond_reglement_id <= 0) { + $origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('PaymentConditionsShort')); + return null; + } + + $payment_conditions_deposit_percent = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $origin->cond_reglement_id); + + if (empty($payment_conditions_deposit_percent)) { + $origin->error = 'ErrorPaymentConditionsNotEligibleToDepositCreation'; + return null; + } + + if (empty($origin->deposit_percent)) { + $origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('DepositPercent')); + return null; + } + + $deposit = new self($origin->db); + $deposit->socid = $origin->socid; + $deposit->type = self::TYPE_DEPOSIT; + $deposit->fk_project = $origin->fk_project; + $deposit->ref_client = $origin->ref_client; + $deposit->date = $invoiceDate; + $deposit->mode_reglement_id = $origin->mode_reglement_id; // CHECK + // TODO Deposit is always due upon reception ? + $deposit->availability_id = $origin->availability_id; + $deposit->demand_reason_id = $origin->demand_reason_id; + $deposit->fk_account = $origin->fk_account; + $deposit->fk_incoterms = $origin->fk_incoterms; + $deposit->location_incoterms = $origin->location_incoterms; + $deposit->fk_multicurrency = $origin->fk_multicurrency; + $deposit->multicurrency_code = $origin->multicurrency_code; + $deposit->multicurrency_tx = $origin->multicurrency_tx; + $deposit->module_source = $origin->module_source; + $deposit->pos_source = $origin->pos_source; + $deposit->model_pdf = 'crabe'; + + $modelByTypeConfName = 'FACTURE_ADDON_PDF_' . $deposit->type; + + if (!empty($conf->global->$modelByTypeConfName)) { + $deposit->model_pdf = $conf->global->$modelByTypeConfName; + } elseif (!empty($conf->global->FACTURE_ADDON_PDF)) { + $deposit->model_pdf = $conf->global->FACTURE_ADDON_PDF; + } + + if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) { + $deposit->note_private = $origin->note_private; + $deposit->note_public = $origin->note_public; + } + + $deposit->origin = $origin->element; + $deposit->origin_id = $origin->id; + + $origin->fetch_optionals(); + + foreach ($origin->array_options as $extrakey => $value) { + $deposit->array_options[$extrakey] = $value; + } + + $deposit->linked_objects[$deposit->origin] = $deposit->origin_id; + + $deposit->context['createdepositfromorigin'] = 'createdepositfromorigin'; + + $origin->db->begin(); + + // Facture::create() also imports contact from origin + $createReturn = $deposit->create($user, $notrigger); + + if ($createReturn <= 0) { + $origin->db->rollback(); + $origin->error = $deposit->error; + $origin->errors = $deposit->errors; + return null; + } + + $amount_ttc_diff = 0; + $amountdeposit = array(); + + if (! empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)) { + $amount = $origin->total_ttc * ($origin->deposit_percent / 100); + + $TTotalByTva = array(); + foreach ($origin->lines as &$line) { + if (!empty($line->special_code)) { + continue; + } + $TTotalByTva[$line->tva_tx] += $line->total_ttc; + } + + foreach ($TTotalByTva as $tva => &$total) { + $coef = $total / $origin->total_ttc; // Calc coef + $am = $amount * $coef; + $amount_ttc_diff += $am; + $amountdeposit[$tva] += $am / (1 + $tva / 100); // Convert into HT for the addline + } + } else { + $totalamount = 0; + $lines = $origin->lines; + $numlines = count($lines); + for ($i = 0; $i < $numlines; $i++) { + if (empty($lines[$i]->qty)) { + continue; // We discard qty=0, it is an option + } + if (!empty($lines[$i]->special_code)) { + continue; // We discard special_code (frais port, ecotaxe, option, ...) + } + + $totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ? + $tva_tx = $lines[$i]->tva_tx; + $amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100; + } + + if ($totalamount == 0) { + $amountdeposit[0] = 0; + } + + $amount_ttc_diff = $amountdeposit[0]; + } + + foreach ($amountdeposit as $tva => $amount) { + if (empty($amount)) { + continue; + } + + $descline = '(DEPOSIT) ('. $origin->deposit_percent .'%) - '.$origin->ref; + + $addlineResult = $deposit->addline( + $descline, + $amount, // subprice + 1, // quantity + $tva, // vat rate + 0, // localtax1_tx + 0, // localtax2_tx + (empty($conf->global->INVOICE_PRODUCTID_DEPOSIT) ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT), // fk_product + 0, // remise_percent + 0, // date_start + 0, // date_end + 0, + $lines[$i]->info_bits, // info_bits + 0, + 'HT', + 0, + 0, // product_type + 1, + $lines[$i]->special_code, + $deposit->origin, + 0, + 0, + 0, + 0 + //,$langs->trans('Deposit') //Deprecated + ); + + if ($addlineResult < 0) { + $origin->db->rollback(); + $origin->error = $deposit->error; + $origin->errors = $deposit->errors; + return null; + } + } + + $diff = $deposit->total_ttc - $amount_ttc_diff; + + if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0) { + $deposit->fetch_lines(); + $subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100); + + $updatelineResult = $deposit->updateline( + $deposit->lines[0]->id, + $deposit->lines[0]->desc, + $subprice_diff, + $deposit->lines[0]->qty, + $deposit->lines[0]->remise_percent, + $deposit->lines[0]->date_start, + $deposit->lines[0]->date_end, + $deposit->lines[0]->tva_tx, + 0, + 0, + 'HT', + $deposit->lines[0]->info_bits, + $deposit->lines[0]->product_type, + 0, + 0, + 0, + $deposit->lines[0]->pa_ht, + $deposit->lines[0]->label, + 0, + array(), + 100 + ); + + if ($updatelineResult < 0) { + $origin->db->rollback(); + $origin->error = $deposit->error; + $origin->errors = $deposit->errors; + return null; + } + } + + + if (! is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($origin->db); + } + + $hookmanager->initHooks(array('invoicedao')); + + $parameters = array('objFrom' => $origin); + $reshook = $hookmanager->executeHooks('createFrom', $parameters, $deposit, $action); // Note that $action and $object may have been + // modified by hook + if ($reshook < 0) { + $origin->db->rollback(); + $origin->error = $hookmanager->error; + $origin->errors = $hookmanager->errors; + return null; + } + + if (! empty($autoValidateDeposit)) { + $validateReturn = $deposit->validate($user, '', 0, $notrigger); + + if ($validateReturn < 0) { + $origin->db->rollback(); + $origin->error = $deposit->error; + $origin->errors = $deposit->errors; + return null; + } + } + + unset($object->context['createdepositfromorigin']); + + $origin->db->commit(); + + return $deposit; + } + /** * Return clicable link of object (with eventually picto) * diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 86344105168..88f653473d5 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -425,6 +425,12 @@ VarAmount=Variable amount (%% tot.) VarAmountOneLine=Variable amount (%% tot.) - 1 line with label '%s' VarAmountAllLines=Variable amount (%% tot.) - all lines from origin DepositPercent=Deposit %% +PaymentConditionPermitsDepositGenerationSelected=You can generate a deposit invoice with the payment conditions you selected +GenerateDeposit=Generate a %s%% deposit invoice +ValidateGeneratedDeposit=Validate the generated deposit +DepositGenerated=Deposit generated +ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder=You can only automatically generate a deposit from a proposal or an order +ErrorPaymentConditionsNotEligibleToDepositCreation=The chose payment conditions are not eligible for automatic deposit generation # PaymentType PaymentTypeVIR=Bank transfer PaymentTypeShortVIR=Bank transfer From e1c5d01361c92dc818ec0cdddce4cc9630929555 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 30 Sep 2021 10:43:40 +0000 Subject: [PATCH 010/473] Fixing style errors. --- htdocs/comm/propal/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index fc16dcdbe16..6cdcb94e169 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1969,9 +1969,9 @@ if ($action == 'create') { array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => '') // Field to complete private note (not replace) ); - $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); - if (! empty($deposit_percent_from_payment_terms)) { + if (! empty($deposit_percent_from_payment_terms)) { $object->fetchObjectLinked(); $eligibleForDepositGeneration = true; @@ -2032,7 +2032,7 @@ if ($action == 'create') { ' ); } - } + } if (!empty($conf->notification->enabled)) { require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; From d74776622d87b8361923bb4e166c2621a77259b8 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 30 Sep 2021 12:57:00 +0200 Subject: [PATCH 011/473] NEW: deposit payment terms: check invoice module activation + rights --- htdocs/comm/propal/card.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 6cdcb94e169..039b8fc25ec 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -687,7 +687,12 @@ if (empty($reshook)) { $deposit = null; $locationTarget = $_SERVER['PHP_SELF'] . '?id=' . $object->id; - if (!$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'int') > 0) { + $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + + if ( + !$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'int') > 0 + && ! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer) + ) { $deposit = Facture::createDepositFromOrigin($object, $user, 0, GETPOST('validate_generated_deposit', 'int') > 0); if ($deposit) { @@ -1971,7 +1976,7 @@ if ($action == 'create') { $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); - if (! empty($deposit_percent_from_payment_terms)) { + if (! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)) { $object->fetchObjectLinked(); $eligibleForDepositGeneration = true; @@ -2032,7 +2037,7 @@ if ($action == 'create') { ' ); } - } + } if (!empty($conf->notification->enabled)) { require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; From f6b9336a82649d0eb4ad44a6ea8657faf026e633 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 30 Sep 2021 10:59:29 +0000 Subject: [PATCH 012/473] Fixing style errors. --- htdocs/comm/propal/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 039b8fc25ec..8002c199efc 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2037,7 +2037,7 @@ if ($action == 'create') { ' ); } - } + } if (!empty($conf->notification->enabled)) { require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; From 087157890e77c650244b6c913aef329dd481ab01 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 4 Oct 2021 15:06:52 +0200 Subject: [PATCH 013/473] FIX: deposit payment terms: unused variable --- htdocs/comm/propal/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 8002c199efc..83e905461c6 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -711,7 +711,7 @@ if (empty($reshook)) { $ret = $deposit->fetch($deposit->id); // Reload to get new records $outputlangs = $langs; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if ($conf->global->MAIN_MULTILANGS) { $outputlangs = new Translate('', $conf); $outputlangs->setDefaultLang($deposit->thirdparty->default_lang); $outputlangs->load('products'); From 6580c2e30837e04a3bee75d6e16c3c37c68759db Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 4 Oct 2021 15:07:27 +0200 Subject: [PATCH 014/473] FIX: deposit payment terms: correctly untag deposit as created from an origin --- 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 d8265aeef01..e209994c9ae 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1659,7 +1659,7 @@ class Facture extends CommonInvoice } } - unset($object->context['createdepositfromorigin']); + unset($deposit->context['createdepositfromorigin']); $origin->db->commit(); From 1b2494855d60dd0a4e1be8b66de5b4d867202736 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 4 Oct 2021 18:09:24 +0200 Subject: [PATCH 015/473] NEW: deposit payment terms: set required invoice fields + filter payment terms with deposits in select + UI --- htdocs/comm/propal/card.php | 95 +++++++++++++++---- htdocs/compta/facture/class/facture.class.php | 24 +++-- htdocs/core/class/html.form.class.php | 7 +- 3 files changed, 100 insertions(+), 26 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 83e905461c6..8dffa7ee5c3 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -690,10 +690,17 @@ if (empty($reshook)) { $deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); if ( - !$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'int') > 0 + !$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'alpha') == 'on' && ! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer) ) { - $deposit = Facture::createDepositFromOrigin($object, $user, 0, GETPOST('validate_generated_deposit', 'int') > 0); + $date = dol_mktime(0, 0, 0, GETPOST('datefmonth', 'int'), GETPOST('datefday', 'int'), GETPOST('datefyear', 'int')); + $forceFields = array(); + + if (GETPOSTISSET('date_pointoftax')) { + $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int')); + } + + $deposit = Facture::createDepositFromOrigin($object, $date, GETPOST('cond_reglement_id', 'int'), $user, 0, GETPOST('validate_generated_deposit', 'alpha') == 'on', $forceFields); if ($deposit) { setEventMessage('DepositGenerated'); @@ -2005,33 +2012,89 @@ if ($action == 'create') { } } + if ($eligibleForDepositGeneration) { + $formquestion[] = array( + 'type' => 'checkbox', + 'tdclass' => 'showonlyifsigned', + 'name' => 'generate_deposit', + 'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('PaymentConditionPermitsDepositGenerationSelected')) + ); + + $formquestion[] = array( + 'type' => 'date', + 'tdclass' => 'fieldrequired showonlyifgeneratedeposit', + 'name' => 'datef', + 'label' => $langs->trans('DateInvoice'), + 'value' => dol_now(), + 'datenow' => true + ); + + if (! empty($conf->global->INVOICE_POINTOFTAX_DATE)) { + $formquestion[] = array( + 'type' => 'date', + 'tdclass' => 'fieldrequired showonlyifgeneratedeposit', + 'name' => 'date_pointoftax', + 'label' => $langs->trans('DatePointOfTax'), + 'value' => dol_now(), + 'datenow' => true + ); + } + + ob_start(); + $form->select_conditions_paiements(0, 'cond_reglement_id', 1, 0, 0, 'minwidth200'); // TODO param 3 + $paymentTermsSelect = ob_get_clean(); + + $formquestion[] = array( + 'type' => 'other', + 'tdclass' => 'fieldrequired showonlyifgeneratedeposit', + 'name' => 'cond_reglement_id', + 'label' => $langs->trans('PaymentTerm'), + 'value' => $paymentTermsSelect + ); + + $formquestion[] = array( + 'type' => 'checkbox', + 'tdclass' => 'showonlyifgeneratedeposit', + 'name' => 'validate_generated_deposit', + 'label' => $langs->trans('ValidateGeneratedDeposit') + ); + $formquestion[] = array( 'type' => 'onecolumn', - 'name' => 'generate_deposit,validate_generated_deposit', 'value' => ' - ' diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index e209994c9ae..bf4271ef7d0 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1411,9 +1411,10 @@ class Facture extends CommonInvoice * @param User $user * @param type $notrigger * @param bool $autoValidate + * @param array $overrideFields * @return Facture */ - static public function createDepositFromOrigin(CommonObject $origin, User $user, $notrigger = 0, $autoValidateDeposit = false, $forceInvoiceDate = null) + static public function createDepositFromOrigin(CommonObject $origin, $date, $cond_reglement_id, User $user, $notrigger = 0, $autoValidateDeposit = false, $overrideFields = array()) { global $conf, $langs, $hookmanager, $action; @@ -1422,16 +1423,19 @@ class Facture extends CommonInvoice return null; } + if (empty($date)) { + $origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('DateInvoice')); + return null; + } + require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; - $invoiceDate = ! empty($forceInvoiceDate) ? $forceInvoiceDate : dol_now(); - - if ($invoiceDate > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + if ($date > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { $origin->error = 'ErrorDateIsInFuture'; return null; } - if ($origin->cond_reglement_id <= 0) { + if ($cond_reglement_id <= 0) { $origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('PaymentConditionsShort')); return null; } @@ -1453,9 +1457,9 @@ class Facture extends CommonInvoice $deposit->type = self::TYPE_DEPOSIT; $deposit->fk_project = $origin->fk_project; $deposit->ref_client = $origin->ref_client; - $deposit->date = $invoiceDate; - $deposit->mode_reglement_id = $origin->mode_reglement_id; // CHECK - // TODO Deposit is always due upon reception ? + $deposit->date = $date; + $deposit->mode_reglement_id = $origin->mode_reglement_id; + $deposit->cond_reglement_id = $cond_reglement_id; $deposit->availability_id = $origin->availability_id; $deposit->demand_reason_id = $origin->demand_reason_id; $deposit->fk_account = $origin->fk_account; @@ -1492,6 +1496,10 @@ class Facture extends CommonInvoice $deposit->linked_objects[$deposit->origin] = $deposit->origin_id; + foreach ($overrideFields as $key => $value) { + $deposit->$key = $value; + } + $deposit->context['createdepositfromorigin'] = 'createdepositfromorigin'; $origin->db->begin(); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 61b00812efd..98ea68e5542 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3877,7 +3877,7 @@ class Form * * @param int $selected Id of payment term to preselect by default * @param string $htmlname Nom de la zone select - * @param int $filtertype Not used + * @param int $filtertype If > 0, don't include payment terms with deposit percentage (for invoices) * @param int $addempty Add an empty entry * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info * @param string $morecss Add more CSS on select tag @@ -3905,6 +3905,10 @@ class Form $selectedDepositPercent = null; foreach ($this->cache_conditions_paiements as $id => $arrayconditions) { + if ($filtertype > 0 && ! empty($arrayconditions['deposit_percent'])) { + continue; + } + if ($selected == $id) { $selectedDepositPercent = ! empty($deposit_percent) ? $deposit_percent : $arrayconditions['deposit_percent']; print ''; } $out.= ''; if ($user->admin && empty($noinfoadmin)) { $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } $out.= ajax_combobox($htmlname); + if ($deposit_percent >= 0) { - print ' '; - print ' + $out .= ' '; + $out .= ' '; } + return $out; } 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 2fc7107e07e..f744abffde4 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 @@ -188,13 +188,6 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (20, '2012', ' ALTER TABLE llx_c_holiday_types ADD COLUMN block_if_negative integer NOT NULL DEFAULT 0 AFTER fk_country; --- Deposit generation helper with specific payment terms -ALTER TABLE llx_c_payment_term ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER decalage; -ALTER TABLE llx_societe ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER cond_reglement; -ALTER TABLE llx_propal ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement; -ALTER TABLE llx_commande ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement; -INSERT INTO llx_c_payment_term(code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values ('DEP30PCTDEL', 13, 0, '__DEPOSIT_PERCENT__% deposit', '__DEPOSIT_PERCENT__% deposit, remainder on delivery', 0, 1, '30'); - -- START GRH/HRM MODULE diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 5d838fc8bb1..db1617e8bdd 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -272,4 +272,12 @@ ALTER TABLE llx_reception MODIFY COLUMN ref_supplier varchar(128); ALTER TABLE llx_bank_account ADD COLUMN pti_in_ctti smallint DEFAULT 0 AFTER domiciliation; -- Set default ticket type to OTHER if no default exists -UPDATE llx_c_ticket_type SET use_default=1 WHERE code='OTHER' AND NOT EXISTS(SELECT * FROM (SELECT * FROM llx_c_ticket_type) AS t WHERE use_default=1); \ No newline at end of file +UPDATE llx_c_ticket_type SET use_default=1 WHERE code='OTHER' AND NOT EXISTS(SELECT * FROM (SELECT * FROM llx_c_ticket_type) AS t WHERE use_default=1); + + +-- Deposit generation helper with specific payment terms +ALTER TABLE llx_c_payment_term ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER decalage; +ALTER TABLE llx_societe ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER cond_reglement; +ALTER TABLE llx_propal ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement; +ALTER TABLE llx_commande ADD COLUMN deposit_percent VARCHAR(63) DEFAULT NULL AFTER fk_cond_reglement; +INSERT INTO llx_c_payment_term(code, sortorder, active, libelle, libelle_facture, type_cdr, nbjour, deposit_percent) values ('DEP30PCTDEL', 13, 0, '__DEPOSIT_PERCENT__% deposit', '__DEPOSIT_PERCENT__% deposit, remainder on delivery', 0, 1, '30'); From 6462fd83067f07f9a7a667fcd3f7b55668be0c4a Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Mon, 28 Mar 2022 16:02:18 +0200 Subject: [PATCH 076/473] update pmp real even if it's not edit --- htdocs/product/inventory/inventory.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 536aaf7d354..895ff8105cd 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -268,6 +268,8 @@ if (empty($reshook)) { $result = $inventoryline->fetch($lineid); if ($result > 0) { $inventoryline->qty_view = null; // The new value we want + $inventoryline->pmp_real = price2num(GETPOST('realpmp_'.$lineid, 'alpha'), 'MS'); + $inventoryline->pmp_expected = price2num(GETPOST('expectedpmp_'.$lineid, 'alpha'), 'MS'); $resultupdate = $inventoryline->update($user); } } From ca7ecfbb579e6115b78698ef16ddde56d5bc5076 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 29 Mar 2022 11:06:18 +0200 Subject: [PATCH 077/473] FIX avoid warning for missing cookie samesite params (and more secure) --- htdocs/main.inc.php | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index fe0986e8d13..c13f7cbe2c9 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -265,10 +265,22 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) { $cookiearrayvalue[$tmpkey] = $_POST[$postkey]; } } - $cookiename = $tmpautoset[0]; + $cookiename = (empty($dolibarr_main_force_https) ? $tmpautoset[0] : '__Secure-'.$tmpautoset[0]); // __Secure- || __Host- $cookievalue = json_encode($cookiearrayvalue); //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue); - setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // keep cookie 1 year and add tag httponly + if (PHP_VERSION_ID < 70300) { + setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // keep cookie 1 year and add tag httponly + } else { + $cookieparams = array( + 'expires' => empty($cookievalue) ? 0 : (time() + (86400 * 354)), + 'path' => '/', + //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains + 'secure' => (empty($dolibarr_main_force_https) ? false : true), + 'httponly' => true, + 'samesite' => 'Lax' // None || Lax || Strict + ); + setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, $cookieparams); + } if (empty($cookievalue)) { unset($_COOKIE[$cookiename]); } @@ -284,7 +296,7 @@ if (!empty($php_session_save_handler) && $php_session_save_handler == 'db') { // Must be done after the include of filefunc.inc.php so global variables of conf file are defined (like $dolibarr_main_instance_unique_id or $dolibarr_main_force_https). // Note: the function dol_getprefix() is defined into functions.lib.php but may have been defined to return a different key to manage another area to protect. $prefix = dol_getprefix(''); -$sessionname = 'DOLSESSID_'.$prefix; +$sessionname = (empty($dolibarr_main_force_https) ? 'DOLSESSID_'.$prefix : '__Secure-DOLSESSID_'.$prefix); // __Secure- || __Host- $sessiontimeout = 'DOLSESSTIMEOUT_'.$prefix; if (!empty($_COOKIE[$sessiontimeout])) { ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]); @@ -293,7 +305,19 @@ if (!empty($_COOKIE[$sessiontimeout])) { // This create lock, released by session_write_close() or end of page. // We need this lock as long as we read/write $_SESSION ['vars']. We can remove lock when finished. if (!defined('NOSESSION')) { - session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. + if (PHP_VERSION_ID < 70300) { + session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. + } else { + $sessioncookieparams = array( + 'lifetime' => 0, + 'path' => '/', + //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains + 'secure' => (empty($dolibarr_main_force_https) ? false : true), + 'httponly' => true, + 'samesite' => 'Lax' // None || Lax || Strict + ); + session_set_cookie_params($sessioncookieparams); + } session_name($sessionname); session_start(); // This call the open and read of session handler //exit; // this exist generates a call to write and close From b7d6436e339a9e2653344620abd3e5567afc341a Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 29 Mar 2022 11:10:41 +0200 Subject: [PATCH 078/473] FIX add doc --- htdocs/main.inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index c13f7cbe2c9..eba557ffe17 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -271,6 +271,7 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) { if (PHP_VERSION_ID < 70300) { setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // keep cookie 1 year and add tag httponly } else { + // Only available for php >= 7.3 $cookieparams = array( 'expires' => empty($cookievalue) ? 0 : (time() + (86400 * 354)), 'path' => '/', @@ -308,6 +309,7 @@ if (!defined('NOSESSION')) { if (PHP_VERSION_ID < 70300) { session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. } else { + // Only available for php >= 7.3 $sessioncookieparams = array( 'lifetime' => 0, 'path' => '/', From 29a4e7c725612b08c898eb3830f23d2010ff83e3 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 29 Mar 2022 12:03:18 +0200 Subject: [PATCH 079/473] FIX check if https or not --- htdocs/main.inc.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index eba557ffe17..e66c9e9d313 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -265,18 +265,18 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) { $cookiearrayvalue[$tmpkey] = $_POST[$postkey]; } } - $cookiename = (empty($dolibarr_main_force_https) ? $tmpautoset[0] : '__Secure-'.$tmpautoset[0]); // __Secure- || __Host- + $cookiename = ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? $tmpautoset[0] : '__Secure-'.$tmpautoset[0]); // __Secure- || __Host- $cookievalue = json_encode($cookiearrayvalue); //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue); if (PHP_VERSION_ID < 70300) { - setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // keep cookie 1 year and add tag httponly + setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), true); // keep cookie 1 year and add tag httponly } else { // Only available for php >= 7.3 $cookieparams = array( 'expires' => empty($cookievalue) ? 0 : (time() + (86400 * 354)), 'path' => '/', //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains - 'secure' => (empty($dolibarr_main_force_https) ? false : true), + 'secure' => ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), 'httponly' => true, 'samesite' => 'Lax' // None || Lax || Strict ); @@ -297,7 +297,7 @@ if (!empty($php_session_save_handler) && $php_session_save_handler == 'db') { // Must be done after the include of filefunc.inc.php so global variables of conf file are defined (like $dolibarr_main_instance_unique_id or $dolibarr_main_force_https). // Note: the function dol_getprefix() is defined into functions.lib.php but may have been defined to return a different key to manage another area to protect. $prefix = dol_getprefix(''); -$sessionname = (empty($dolibarr_main_force_https) ? 'DOLSESSID_'.$prefix : '__Secure-DOLSESSID_'.$prefix); // __Secure- || __Host- +$sessionname = ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? 'DOLSESSID_'.$prefix : '__Secure-DOLSESSID_'.$prefix); // __Secure- || __Host- $sessiontimeout = 'DOLSESSTIMEOUT_'.$prefix; if (!empty($_COOKIE[$sessiontimeout])) { ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]); @@ -307,14 +307,14 @@ if (!empty($_COOKIE[$sessiontimeout])) { // We need this lock as long as we read/write $_SESSION ['vars']. We can remove lock when finished. if (!defined('NOSESSION')) { if (PHP_VERSION_ID < 70300) { - session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. + session_set_cookie_params(0, '/', null, ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. } else { // Only available for php >= 7.3 $sessioncookieparams = array( 'lifetime' => 0, 'path' => '/', //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains - 'secure' => (empty($dolibarr_main_force_https) ? false : true), + 'secure' => ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), 'httponly' => true, 'samesite' => 'Lax' // None || Lax || Strict ); From 67e7c91c3ed34b1c8a0f94c0e5032e4ee7ce8edb Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Mon, 11 Apr 2022 15:47:38 +0200 Subject: [PATCH 080/473] pmp inventory conf MAIN_PRODUCT_PERENTITY_SHARED --- htdocs/product/inventory/inventory.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 2b21de99079..77cdc965164 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -194,6 +194,15 @@ if (empty($reshook)) { setEventMessages($db->lasterror(), null, 'errors'); break; } + if(!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product_perentity SET pmp = '.((float) $line->pmp_real).' WHERE fk_product = '.((int) $line->fk_product).' AND entity='.$conf->entity; + $resqlpmp = $db->query($sqlpmp); + if (! $resqlpmp) { + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + break; + } + } } // Update line with id of stock movement (and the start quantity if it has changed this last recording) From ddb50264aeb5c132ec89aa39c09c074f0b65e234 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 11 Apr 2022 13:58:59 +0000 Subject: [PATCH 081/473] Fixing style errors. --- htdocs/product/inventory/inventory.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 77cdc965164..9cef5671041 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -194,15 +194,15 @@ if (empty($reshook)) { setEventMessages($db->lasterror(), null, 'errors'); break; } - if(!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product_perentity SET pmp = '.((float) $line->pmp_real).' WHERE fk_product = '.((int) $line->fk_product).' AND entity='.$conf->entity; - $resqlpmp = $db->query($sqlpmp); - if (! $resqlpmp) { - $error++; - setEventMessages($db->lasterror(), null, 'errors'); - break; - } - } + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product_perentity SET pmp = '.((float) $line->pmp_real).' WHERE fk_product = '.((int) $line->fk_product).' AND entity='.$conf->entity; + $resqlpmp = $db->query($sqlpmp); + if (! $resqlpmp) { + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + break; + } + } } // Update line with id of stock movement (and the start quantity if it has changed this last recording) From 89b7c8298b4f7f27b4d3b08079014826437677a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Mon, 11 Apr 2022 17:25:45 +0200 Subject: [PATCH 082/473] Module builder: Translate permissions label --- htdocs/modulebuilder/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index f3922aa6342..f8abd703bf0 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -3008,7 +3008,7 @@ if ($module == 'initmodule') print ''; print ''; - print $perm[1]; + print $langs->trans($perm[1]); print ''; print ''; From 9547b9e7febb4312bd491d6d3e089d0eb7c521e3 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Mon, 11 Apr 2022 18:01:25 +0200 Subject: [PATCH 083/473] Fix: Online signature of proposals does not work well with multicompany --- htdocs/core/ajax/onlineSign.php | 4 ++++ htdocs/public/onlinesign/newonlinesign.php | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/core/ajax/onlineSign.php b/htdocs/core/ajax/onlineSign.php index 5110918541f..ce9ae57864d 100644 --- a/htdocs/core/ajax/onlineSign.php +++ b/htdocs/core/ajax/onlineSign.php @@ -48,6 +48,10 @@ if (!defined('NOIPCHECK')) { if (!defined('NOBROWSERNOTIF')) { define('NOBROWSERNOTIF', '1'); } +$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1)); +if (is_numeric($entity)) { + define("DOLENTITY", $entity); +} include '../../main.inc.php'; $action = GETPOST('action', 'aZ09'); diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index 8bd95d23c8d..2a9ed568fe8 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -431,11 +431,12 @@ if ($action == "dosign" && empty($cancel)) { "ref" : \''.dol_escape_js($REF).'\', "securekey" : \''.dol_escape_js($SECUREKEY).'\', "mode" : \''.dol_escape_htmltag($source).'\', + "entity" : \''.dol_escape_htmltag($entity).'\', }, success: function(response) { if(response == "success"){ console.log("Success on saving signature"); - window.location.replace("'.$_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&message=signed&securekey='.urlencode($SECUREKEY).'"); + window.location.replace("'.$_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&message=signed&securekey='.urlencode($SECUREKEY).($conf->multicompany->enabled?'&entity='.$entity:'').'"); }else{ console.error(response); } From 62b74962535ed38c424e569d9dbd79b25653ab16 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Mon, 11 Apr 2022 18:26:49 +0200 Subject: [PATCH 084/473] Fix: Direct download don't work with multicompany --- htdocs/document.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/htdocs/document.php b/htdocs/document.php index 060722e8d5b..fc894091615 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -5,6 +5,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2010 Pierre Morin * Copyright (C) 2010 Juanjo Menent + * Copyright (C) 2022 Ferran Marcet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -140,6 +141,11 @@ if (!empty($hashp)) $modulepart = $moduleparttocheck; $original_file = (($tmp[1] ? $tmp[1].'/' : '').$ecmfile->filename); // this is relative to module dir } + $entity = $ecmfile->entity; + if ($entity != $conf->entity) { + $conf->entity = $entity; + $conf->setValues($db); + } } else { $langs->load("errors"); accessforbidden($langs->trans("ErrorFileNotFoundWithSharedLink"), 0, 0, 1); From b8bccd62efa45ce1617eaa3d4a0278c3d3305adc Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Mon, 11 Apr 2022 18:41:36 +0200 Subject: [PATCH 085/473] Update newonlinesign.php --- htdocs/public/onlinesign/newonlinesign.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index 2a9ed568fe8..d1020dc2c1d 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -193,7 +193,7 @@ $replacemainarea = (empty($conf->dol_hide_leftmenu) ? '
' : '').'
'; llxHeader($head, $langs->trans("OnlineSignature"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1); if ($action == 'refusepropal') { - print $form->formconfirm($_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&securekey='.urlencode($SECUREKEY), $langs->trans('RefusePropal'), $langs->trans('ConfirmRefusePropal', $object->ref), 'confirm_refusepropal', '', '', 1); + print $form->formconfirm($_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&securekey='.urlencode($SECUREKEY).($conf->multicompany->enabled?'&entity='.$entity:''), $langs->trans('RefusePropal'), $langs->trans('ConfirmRefusePropal', $object->ref), 'confirm_refusepropal', '', '', 1); } // Check link validity for param 'source' to avoid use of the examples as value From f679392d26ad3f902c9f42d0e38f6a5c897e29d1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 02:26:37 +0200 Subject: [PATCH 086/473] FIX missing picto in combo of mass actions of thirdparties. --- htdocs/societe/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index da056ec33da..bdc0fae08e0 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -870,10 +870,10 @@ if ($user->rights->societe->creer) { $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } if ($user->rights->societe->creer) { - $arrayofmassactions['preenable'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("SetToEnabled"); + $arrayofmassactions['preenable'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SetToEnabled"); } if ($user->rights->societe->creer) { - $arrayofmassactions['predisable'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("SetToDisabled"); + $arrayofmassactions['predisable'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SetToDisabled"); } if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag', 'preenable', 'preclose'))) { $arrayofmassactions = array(); From cfe554b04cbec7987f1f4b8951ba75a9d87a3831 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 03:08:31 +0200 Subject: [PATCH 087/473] Fix var not defined --- htdocs/modulebuilder/index.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 872a88b28aa..39f70d30d2d 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -46,6 +46,9 @@ $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); +$sortfield = ''; +$sortorder = ''; + $module = GETPOST('module', 'alpha'); $tab = GETPOST('tab', 'aZ09'); $tabobj = GETPOST('tabobj', 'alpha'); From c4747735b99509d948361dd3ba28a0187811d125 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 12 Apr 2022 07:55:09 +0200 Subject: [PATCH 088/473] FIX missing signature library when ODT model is used --- .../modules/propale/doc/doc_generic_proposal_odt.modules.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 636bf4c4f7f..bd86d27b0a3 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -31,6 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; +include_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php'; /** From 2d56aed912d37f220b446ecaaea9a2623aa9c6de Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 12 Apr 2022 08:31:51 +0200 Subject: [PATCH 089/473] FIX uniformize code --- .../modules/propale/doc/doc_generic_proposal_odt.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index bd86d27b0a3..66e2f3c8312 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; -include_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php'; /** From f4023b4e44160e0861eb09a0d0d407e5420575e3 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 12 Apr 2022 11:08:50 +0200 Subject: [PATCH 090/473] Add missing entity on salary's payment --- htdocs/salaries/class/paymentsalary.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 76236bb88aa..506e9b73ea5 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -164,9 +164,9 @@ class PaymentSalary extends CommonObject $this->db->begin(); if ($totalamount != 0) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_salary (fk_salary, datec, datep, amount,"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_salary (entity, fk_salary, datec, datep, amount,"; $sql .= " fk_typepayment, num_payment, note, fk_user_author, fk_bank)"; - $sql .= " VALUES ($this->chid, '".$this->db->idate($now)."',"; + $sql .= " VALUES (".$conf->entity.", ".$this->chid.", '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datepaye)."',"; $sql .= " ".price2num($totalamount).","; $sql .= " ".((int) $this->paiementtype).", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note)."', ".((int) $user->id).","; From a6407257dd2752b6f2931f43b0c4bcdf9b1ffe05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Tue, 12 Apr 2022 11:11:26 +0200 Subject: [PATCH 091/473] Allow to view tabs in module builder --- htdocs/langs/en_US/modulebuilder.lang | 5 +- htdocs/modulebuilder/index.php | 127 ++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 7ba539d3bd4..6376024ea0b 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -143,4 +143,7 @@ AsciiToHtmlConverter=Ascii to HTML converter AsciiToPdfConverter=Ascii to PDF converter TableNotEmptyDropCanceled=Table not empty. Drop has been canceled. ModuleBuilderNotAllowed=The module builder is available but not allowed to your user. -ImportExportProfiles=Import and export profiles \ No newline at end of file +ImportExportProfiles=Import and export profiles +ListOfTabsEntries=List of tab entries +TabsDefDesc= Define here the tabs provided by your module +TabsDefDescTooltip=The tabs provided by your module/application are defined into the array $this->tabs into the module descriptor file. You can edit manually this file or use the embedded editor. diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 82567e05fac..16671ddf137 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1931,6 +1931,11 @@ if ($module == 'initmodule') { $head2[$h][2] = 'permissions'; $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : ''); + $head2[$h][1] = $langs->trans("Tabs"); + $head2[$h][2] = 'tabs'; + $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("Menus"); $head2[$h][2] = 'menus'; @@ -3902,6 +3907,128 @@ if ($module == 'initmodule') { print ''; } + if ($tab == 'tabs') { + $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; + + $tabs = $moduleobj->tabs; + + if ($action != 'editfile' || empty($file)) { + print ''; + $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}'); + $htmlhelp = str_replace('{s1}', ''.$langs->trans('Setup').' - '.$langs->trans('Tabs').'', $htmlhelp); + print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; + print '
'; + + print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + + print '
'; + print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', ''); + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + print ''; + + print ''; + print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); + print "\n"; + + if (count($tabs)) { + foreach ($tabs as $tab) { + $parts = explode(':', $tab['data']); + + $objectType = $parts[0]; + $tabName = $parts[1]; + $tabTitle = isset($parts[2]) ? $parts[2] : ''; + $langFile = isset($parts[3]) ? $parts[3] : ''; + $condition = isset($parts[4]) ? $parts[4] : ''; + $path = isset($parts[5]) ? $parts[5] : ''; + + // If we want to remove the tab, then the format is 'tabname:optionalcondition' + // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab + if ($tabName[0] === '-') { + $tabTitle = ''; + $condition = isset($parts[2]) ? $parts[2] : ''; + } + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + } + } else { + print ''; + } + + print '
'; + print dol_escape_htmltag($parts[0]); + print ''; + if ($tabName[0] === "+") + print '' . dol_escape_htmltag($tabName) . ''; + else + print '' . dol_escape_htmltag($tabName) . ''; + print ''; + print dol_escape_htmltag($tabTitle); + print ''; + print dol_escape_htmltag($langFile); + print ''; + print dol_escape_htmltag($condition); + print ''; + print dol_escape_htmltag($path); + print '
'.$langs->trans("None").'
'; + print '
'; + + print '
'; + } else { + $fullpathoffile = dol_buildpath($file, 0); + + $content = file_get_contents($fullpathoffile); + + // New module + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + + $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%'); + print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html')); + print '
'; + print '
'; + print ''; + print '   '; + print ''; + print '
'; + + print '
'; + } + } + if ($tab != 'description') { print dol_get_fiche_end(); } From 25a851ac70f70df00e5408e344b26b3b5a979c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Tue, 12 Apr 2022 11:12:43 +0200 Subject: [PATCH 092/473] Fix translation --- htdocs/langs/en_US/modulebuilder.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 6376024ea0b..5544c2b932a 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -145,5 +145,5 @@ TableNotEmptyDropCanceled=Table not empty. Drop has been canceled. ModuleBuilderNotAllowed=The module builder is available but not allowed to your user. ImportExportProfiles=Import and export profiles ListOfTabsEntries=List of tab entries -TabsDefDesc= Define here the tabs provided by your module +TabsDefDesc=Define here the tabs provided by your module TabsDefDescTooltip=The tabs provided by your module/application are defined into the array $this->tabs into the module descriptor file. You can edit manually this file or use the embedded editor. From a747f574b3dc5144e9e695f1ec42d19935ca1ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Tue, 12 Apr 2022 11:15:40 +0200 Subject: [PATCH 093/473] Improve comment --- htdocs/modulebuilder/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 16671ddf137..14385864b6b 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -3957,7 +3957,7 @@ if ($module == 'initmodule') { $condition = isset($parts[4]) ? $parts[4] : ''; $path = isset($parts[5]) ? $parts[5] : ''; - // If we want to remove the tab, then the format is 'tabname:optionalcondition' + // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition' // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab if ($tabName[0] === '-') { $tabTitle = ''; From 752cc6f4a7adbc4fd791ef6229ce28feb5c8569d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Tue, 12 Apr 2022 11:17:24 +0200 Subject: [PATCH 094/473] Lint source code --- htdocs/modulebuilder/index.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 14385864b6b..937ef6d83fb 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -3971,10 +3971,11 @@ if ($module == 'initmodule') { print ''; print ''; - if ($tabName[0] === "+") + if ($tabName[0] === "+") { print '' . dol_escape_htmltag($tabName) . ''; - else + } else { print '' . dol_escape_htmltag($tabName) . ''; + } print ''; print ''; From a006eaecdeac66bf6f1c67112a9dde9e77e8029e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 13:02:33 +0200 Subject: [PATCH 095/473] Fix trans --- htdocs/adherents/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 996f2d16c8d..441ce85ec86 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -482,7 +482,7 @@ if (GETPOSTISSET("search_status")) { $titre = $langs->trans("MembersListToValid"); } if ($search_status == Adherent::STATUS_VALIDATED && $filter == '') { - $titre = $langs->trans("MembersValidated"); + $titre = $langs->trans("MenuMembersValidated"); } if ($search_status == Adherent::STATUS_VALIDATED && $filter == 'withoutsubscription') { $titre = $langs->trans("MembersWithSubscriptionToReceive"); From d41676cf8bd71789a90eeb08ed66f72cdf0f1de9 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 12 Apr 2022 13:57:00 +0200 Subject: [PATCH 096/473] Close #20609 : new massaction asign sale representative --- htdocs/core/actions_massactions.inc.php | 38 +++++++++++++++++++++++++ htdocs/core/tpl/massactions_pre.tpl.php | 10 ++++++- htdocs/langs/en_US/main.lang | 4 +++ htdocs/societe/list.php | 3 ++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index c5ff1d8f82a..5ec011f5017 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1602,6 +1602,44 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == } } +if (!$error && ($massaction == 'affectcommercial' || ($action == 'affectcommercial' && $confirm == 'yes')) && $permissiontoadd) { + $db->begin(); + + $objecttmp = new $objectclass($db); + $nbok = 0; + + foreach ($toselect as $toselectid) { + $result = $objecttmp->fetch($toselectid); + if ($result>0) { + if (in_array($objecttmp->element, array('societe'))) { + $result = $objecttmp->setSalesRep(GETPOST("commercial", "alpha")); + } + if ($result <= 0) { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } else { + $nbok++; + } + } else { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + if ($nbok > 1) { + setEventMessages($langs->trans("CommercialsAffected", $nbok), null, 'mesgs'); + } else { + setEventMessages($langs->trans("CommercialAffected"), null, 'mesgs'); + } + $db->commit(); + } else { + $db->rollback(); + } +} + // Approve for leave only if (!$error && ($massaction == 'approveleave' || ($action == 'approveleave' && $confirm == 'yes')) && $permissiontoapprove) { $db->begin(); diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index de034f652d3..4e138b0f1dc 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -217,7 +217,15 @@ if ($massaction == 'preenable') { if ($massaction == 'predisable') { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDisabling"), $langs->trans("ConfirmMassDisablingQuestion", count($toselect)), "disable", null, '', 0, 200, 500, 1); } - +if ($massaction == 'presetcommercial') { + $formquestion = array(); + $userlist = $form->select_dolusers('', '', 0, null, 0, '', '', 0, 0, 0, 'AND u.statut = 1', 0, '', '', 0, 1); + $formquestion[] = array('type' => 'other', + 'name' => 'affectedcommercial', + 'label' => $form->editfieldkey('AllocateCommercial', 'commercial_id', '', $object, 0), + 'value' => $form->multiselectarray('commercial', $userlist, null, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0, '', '', '', 1)); + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmAllocateCommercial"), $langs->trans("ConfirmAllocateCommercialQuestion", count($toselect)), "affectcommercial", $formquestion, 1, 0, 200, 500, 1); +} if ($massaction == 'preapproveleave') { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassLeaveApproval"), $langs->trans("ConfirmMassLeaveApprovalQuestion", count($toselect)), "approveleave", null, 'yes', 0, 200, 500, 1); } diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index c66895e58a4..b39124c7c53 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1169,3 +1169,7 @@ CanceledShown=Canceled shown Terminate=Terminate Terminated=Terminated AddLineOnPosition=Add line on position (at the end if empty) +ConfirmAllocateCommercial=Assign sales representative confirmation +ConfirmAllocateCommercialQuestion=Are you sure you want to assign the %s selected record(s)? +CommercialsAffected=Sales representatives affected +CommercialAffected=Sales representative affected \ No newline at end of file diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 3544611ac45..26e955e7ab4 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -875,6 +875,9 @@ if ($user->rights->societe->creer) { if ($user->rights->societe->creer) { $arrayofmassactions['predisable'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("SetToDisabled"); } +if ($user->rights->societe->creer) { + $arrayofmassactions['presetcommercial'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("AllocateCommercial"); +} if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag', 'preenable', 'preclose'))) { $arrayofmassactions = array(); } From c51aff99af711f0a7a04fcd2de99ab243ad2175c Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 12 Apr 2022 14:38:17 +0200 Subject: [PATCH 097/473] Add missing entity on adding new VAT --- htdocs/compta/tva/class/tva.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index 45d3d2e74b4..ce5ff657eca 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -125,6 +125,7 @@ class Tva extends CommonObject // Insert request $sql = "INSERT INTO ".MAIN_DB_PREFIX."tva("; + $sql .= "entity,"; $sql .= "datec,"; $sql .= "datep,"; $sql .= "datev,"; @@ -136,6 +137,7 @@ class Tva extends CommonObject $sql .= "fk_user_creat,"; $sql .= "fk_user_modif"; $sql .= ") VALUES ("; + $sql .= " '".$conf->entity."',"; $sql .= " '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datep)."',"; $sql .= " '".$this->db->idate($this->datev)."',"; From adda436dab9acc806ff33c5ea25e9f21df41f90d Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 12 Apr 2022 12:45:05 +0000 Subject: [PATCH 098/473] Fixing style errors. --- htdocs/compta/tva/class/tva.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index ce5ff657eca..c9fcf18d587 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -125,7 +125,7 @@ class Tva extends CommonObject // Insert request $sql = "INSERT INTO ".MAIN_DB_PREFIX."tva("; - $sql .= "entity,"; + $sql .= "entity,"; $sql .= "datec,"; $sql .= "datep,"; $sql .= "datev,"; @@ -137,7 +137,7 @@ class Tva extends CommonObject $sql .= "fk_user_creat,"; $sql .= "fk_user_modif"; $sql .= ") VALUES ("; - $sql .= " '".$conf->entity."',"; + $sql .= " '".$conf->entity."',"; $sql .= " '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datep)."',"; $sql .= " '".$this->db->idate($this->datev)."',"; From 1bfd9c695fda90db19047a04305877bf809580e3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 16:29:25 +0200 Subject: [PATCH 099/473] Update tva.class.php --- htdocs/compta/tva/class/tva.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index c9fcf18d587..a6828587763 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -137,7 +137,7 @@ class Tva extends CommonObject $sql .= "fk_user_creat,"; $sql .= "fk_user_modif"; $sql .= ") VALUES ("; - $sql .= " '".$conf->entity."',"; + $sql .= " ".((int) $conf->entity.", "; $sql .= " '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datep)."',"; $sql .= " '".$this->db->idate($this->datev)."',"; @@ -146,8 +146,8 @@ class Tva extends CommonObject $sql .= " '".$this->db->escape($this->note)."',"; $sql .= " '".$this->db->escape($this->fk_account)."',"; $sql .= " '".$this->db->escape($this->type_payment)."',"; - $sql .= " '".($this->fk_user_creat > 0 ? (int) $this->fk_user_creat : (int) $user->id)."',"; - $sql .= " '".$this->db->escape($this->fk_user_modif)."'"; + $sql .= " ".($this->fk_user_creat > 0 ? (int) $this->fk_user_creat : (int) $user->id).","; + $sql .= " ".($this->fk_user_modif > 0 ? (int) $this->fk_user_modif : (int) $user->id); $sql .= ")"; dol_syslog(get_class($this)."::create", LOG_DEBUG); From 6cbcc54bd964eab272fd3e7f6ea63efc65dec6b5 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Tue, 12 Apr 2022 19:19:41 +0200 Subject: [PATCH 100/473] Fix: The resource dropdown does not show the values --- htdocs/resource/class/html.formresource.class.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index 99916b8ed70..fa775bf5d58 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -1,6 +1,7 @@ * Copyright (C) 2019 Frédéric France + * Copyright (C) 2022 Ferran Marcet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -224,9 +225,10 @@ class FormResource $value = ($maxlength ?dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']); } elseif ($format == 3) { $value = $arraytypes['code']; - } elseif (empty($value)) { - print ' '; + } else { + $value = ' '; } + print $value; print ''; } } From ed172421f0bf1b425fb86227686dbcc633558d54 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Tue, 12 Apr 2022 19:20:45 +0200 Subject: [PATCH 101/473] Fix: The resource dropdown does not show the values --- htdocs/resource/class/html.formresource.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index fa775bf5d58..a541dfab700 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -225,7 +225,8 @@ class FormResource $value = ($maxlength ?dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']); } elseif ($format == 3) { $value = $arraytypes['code']; - } else { + } + if (empty($value)) { $value = ' '; } print $value; From 5e76c1a45d627ab077413ceab556694549558c0f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 21:59:34 +0200 Subject: [PATCH 102/473] Fix doc --- htdocs/install/mysql/migration/14.0.0-15.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 30636a8bb98..6f35a9f1c44 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 @@ -512,5 +512,5 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) value -- 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. +-- into accounting will use it in priority if value is not null. The script repair.sql contains the sequence to fix datas in llx_bank. ALTER TABLE llx_bank ADD COLUMN amount_main_currency double(24,8) NULL; From 6a7212a48df1a03baeed55960379992303141ad6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 12 Apr 2022 22:02:46 +0200 Subject: [PATCH 103/473] Fix sql error --- htdocs/compta/tva/class/tva.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index a6828587763..1b71cb261e1 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -137,7 +137,7 @@ class Tva extends CommonObject $sql .= "fk_user_creat,"; $sql .= "fk_user_modif"; $sql .= ") VALUES ("; - $sql .= " ".((int) $conf->entity.", "; + $sql .= " ".((int) $conf->entity).", "; $sql .= " '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datep)."',"; $sql .= " '".$this->db->idate($this->datev)."',"; From e9e10e84b2adb333e276f8dd5fce713b34ed87bb Mon Sep 17 00:00:00 2001 From: Norbert Penel Date: Wed, 13 Apr 2022 10:47:33 +0200 Subject: [PATCH 104/473] ensure priority in this usage ensure priority in this usage --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bd3cf69c86a..6fd09ed9723 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1690,7 +1690,7 @@ class Product extends CommonObject $testExit = array('multiprices','multiprices_ttc','multiprices_base_type','multiprices_min','multiprices_min_ttc','multiprices_tva_tx','multiprices_recuperableonly'); foreach ($testExit as $field) { - if (!isset($this->$field[$level])) { + if (!isset($this->{$field}[$level])) { return array(); } } From 29242a23c36be39dfe7f76a21ae02aecce75165b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 13 Apr 2022 12:11:35 +0200 Subject: [PATCH 105/473] Update product.class.php --- htdocs/product/class/product.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 6fd09ed9723..8ff89d8d086 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1690,7 +1690,11 @@ class Product extends CommonObject $testExit = array('multiprices','multiprices_ttc','multiprices_base_type','multiprices_min','multiprices_min_ttc','multiprices_tva_tx','multiprices_recuperableonly'); foreach ($testExit as $field) { - if (!isset($this->{$field}[$level])) { + if (!isset($this->$field)) { + return array(); + } + $tmparray = $this->$field; + if (!isset($tmparray[$level])) { return array(); } } From d154696c32b3ccdeb02b161fd3e04d27db2a3c02 Mon Sep 17 00:00:00 2001 From: BB2A Anthony Berton Date: Wed, 13 Apr 2022 16:15:07 +0200 Subject: [PATCH 106/473] morecss select_compagny --- htdocs/comm/propal/card.php | 2 +- htdocs/commande/card.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 0153f554169..f6989d90d59 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1921,7 +1921,7 @@ if ($action == 'create') { $formquestion = array( // 'text' => $langs->trans("ConfirmClone"), // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), - array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)')), + array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', '', 0, 0, null, 0, 'maxwidth300')), array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans('PuttingPricesUpToDate'), 'value' => (!empty($conf->global->PROPOSAL_CLONE_UPDATE_PRICES) ? 1 : 0)), ); if (!empty($conf->global->PROPAL_CLONE_DATE_DELIVERY) && !empty($object->delivery_date)) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 3a903e233de..53b6d40d6b0 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2043,7 +2043,7 @@ if ($action == 'create' && $usercancreate) { if ($action == 'clone') { // Create an array for form $formquestion = array( - array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client = 2 OR s.client=3)')) + array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client = 2 OR s.client=3)', '', 0, 0, null, 0, 'maxwidth300')) ); $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } From 5f7f9a751508dc5840151b0f674a671a2a88281a Mon Sep 17 00:00:00 2001 From: lvessiller Date: Thu, 14 Apr 2022 09:48:06 +0200 Subject: [PATCH 107/473] FIX include tpl path in product stock --- htdocs/product/stock/tpl/stockcorrection.tpl.php | 2 +- htdocs/product/stock/tpl/stocktransfer.tpl.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index eb84df7d14e..6afea0abe54 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -180,7 +180,7 @@ print ''; print ''; // Extrafield template -include 'extrafields_add.tpl.php'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; print ''; diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index ccedf993221..f1c08b7673e 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -137,7 +137,7 @@ print ''; print ''; // Extrafield template -include 'extrafields_add.tpl.php'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; print ''; From c90d758b0ff06021b5eafd72b69c0276fa88e4eb Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Thu, 14 Apr 2022 11:06:54 +0200 Subject: [PATCH 108/473] New : add of unique(entity,label) --- htdocs/install/mysql/migration/15.0.0-16.0.0.sql | 2 ++ .../tables/llx_takepos_floor_tables.key.sql | 16 ++++++++++++++++ htdocs/takepos/floors.php | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 htdocs/install/mysql/tables/llx_takepos_floor_tables.key.sql diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 5f8b1d886c3..745955c7bcd 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -324,3 +324,5 @@ ALTER TABLE llx_actioncomm MODIFY COLUMN note mediumtext; DELETE FROM llx_boxes WHERE box_id IN (select rowid FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php')); DELETE FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php'); + +ALTER TABLE llx_takepos_floor_tables ADD UNIQUE(entity,label); \ No newline at end of file diff --git a/htdocs/install/mysql/tables/llx_takepos_floor_tables.key.sql b/htdocs/install/mysql/tables/llx_takepos_floor_tables.key.sql new file mode 100644 index 00000000000..e90cd67e889 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_takepos_floor_tables.key.sql @@ -0,0 +1,16 @@ +-- Copyright (C) 2018 SuperAdmin +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_takepos_floor_tables ADD UNIQUE(entity,label); \ No newline at end of file diff --git a/htdocs/takepos/floors.php b/htdocs/takepos/floors.php index 64040a24466..73e84109116 100644 --- a/htdocs/takepos/floors.php +++ b/htdocs/takepos/floors.php @@ -104,7 +104,7 @@ if ($action == "updatename") { if (strlen($newname) > 3) { $newname = substr($newname, 0, 3); // Only 3 chars } - $db->query("UPDATE ".MAIN_DB_PREFIX."takepos_floor_tables set label='".$db->escape($newname)."' WHERE rowid = ".((int) $place)); + $resql = $db->query("UPDATE ".MAIN_DB_PREFIX."takepos_floor_tables set label='".$db->escape($newname)."' WHERE rowid = ".((int) $place)); } if ($action == "add") { From 0fcfb7c5fd3988fb362ee550dd7edc6beb185c97 Mon Sep 17 00:00:00 2001 From: atm-arnaud Date: Thu, 14 Apr 2022 12:08:06 +0200 Subject: [PATCH 109/473] FIX intervention entity missing --- htdocs/fichinter/class/fichinter.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 371853dc70c..92b628b9aab 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -426,7 +426,7 @@ class Fichinter extends CommonObject $sql .= " f.datec, f.dateo, f.datee, f.datet, f.fk_user_author,"; $sql .= " f.date_valid as datev,"; $sql .= " f.tms as datem,"; - $sql .= " f.duree, f.fk_projet as fk_project, f.note_public, f.note_private, f.model_pdf, f.extraparams, fk_contrat"; + $sql .= " f.duree, f.fk_projet as fk_project, f.note_public, f.note_private, f.model_pdf, f.extraparams, fk_contrat, f.entity as entity"; $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as f"; if ($ref) { $sql .= " WHERE f.entity IN (".getEntity('intervention').")"; @@ -459,6 +459,7 @@ class Fichinter extends CommonObject $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; // deprecated $this->fk_contrat = $obj->fk_contrat; + $this->entity = $obj->entity; $this->user_creation = $obj->fk_user_author; From f15438dd039dc3f6ecb7c4c3642d83f8e57e7927 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Thu, 14 Apr 2022 12:28:51 +0200 Subject: [PATCH 110/473] NEW: data sign on propal list --- htdocs/comm/propal/list.php | 71 ++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 73b4c479b2e..561682ba02f 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -123,6 +123,15 @@ $search_fk_input_reason = GETPOST("search_fk_input_reason", 'int'); $search_fk_mode_reglement = GETPOST("search_fk_mode_reglement", 'int'); $search_btn = GETPOST('button_search', 'alpha'); $search_remove_btn = GETPOST('button_removefilter', 'alpha'); +$search_date_signature_startday = GETPOST('search_date_signature_startday', 'int'); +$search_date_signature_startmonth = GETPOST('search_date_signature_startmonth', 'int'); +$search_date_signature_startyear = GETPOST('search_date_signature_startyear', 'int'); +$search_date_signature_endday = GETPOST('search_date_signature_endday', 'int'); +$search_date_signature_endmonth = GETPOST('search_date_signature_endmonth', 'int'); +$search_date_signature_endyear = GETPOST('search_date_signature_endyear', 'int'); +$search_date_signature_start = dol_mktime(0, 0, 0, $search_date_signature_startmonth, $search_date_signature_startday, $search_date_signature_startyear); +$search_date_signature_end = dol_mktime(23, 59, 59, $search_date_signature_endmonth, $search_date_signature_endday, $search_date_signature_endyear); + $search_status = GETPOST('search_status', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); @@ -207,6 +216,7 @@ $arrayfields = array( 'p.date'=>array('label'=>"DatePropal", 'checked'=>1), 'p.fin_validite'=>array('label'=>"DateEnd", 'checked'=>1), 'p.date_livraison'=>array('label'=>"DeliveryDate", 'checked'=>0), + 'p.date_signature'=>array('label'=>"DateSigning", 'checked'=>0), 'ava.rowid'=>array('label'=>"AvailabilityPeriod", 'checked'=>0), 'p.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>0, 'enabled'=>!empty($conf->expedition->enabled)), 'p.fk_input_reason'=>array('label'=>"Origin", 'checked'=>0, 'enabled'=>1), @@ -337,6 +347,14 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_fk_shipping_method = ''; $search_fk_input_reason = ''; $search_fk_mode_reglement = ''; + $search_date_signature_startday = ''; + $search_date_signature_startmonth = ''; + $search_date_signature_startyear = ''; + $search_date_signature_endday = ''; + $search_date_signature_endmonth = ''; + $search_date_signature_endyear = ''; + $search_date_signature_start = ''; + $search_date_signature_end = ''; } if ($object_statut != '') { $search_status = $object_statut; @@ -517,6 +535,7 @@ $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= ' p.rowid, p.entity as propal_entity, p.note_private, p.total_ht, p.total_tva, p.total_ttc, p.localtax1, p.localtax2, p.ref, p.ref_client, p.fk_statut as status, p.fk_user_author, p.datep as dp, p.fin_validite as dfv,p.date_livraison as ddelivery,'; $sql .= ' p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc,'; $sql .= ' p.datec as date_creation, p.tms as date_update, p.date_cloture as date_cloture,'; +$sql .= ' p.date_signature as dsignature,'; $sql .= ' p.note_public, p.note_private,'; $sql .= ' p.fk_cond_reglement,p.fk_mode_reglement,p.fk_shipping_method,p.fk_input_reason,'; $sql .= " pr.rowid as project_id, pr.ref as project_ref, pr.title as project_label,"; @@ -701,6 +720,12 @@ if ($search_sale > 0) { if ($search_user > 0) { $sql .= " AND c.fk_c_type_contact = tc.rowid AND tc.element='propal' AND tc.source='internal' AND c.element_id = p.rowid AND c.fk_socpeople = ".((int) $search_user); } +if ($search_date_signature_start) { + $sql .= " AND p.date_signature >= '".$db->idate($search_date_signature_start)."'"; +} +if ($search_date_signature_end) { + $sql .= " AND p.date_signature <= '".$db->idate($search_date_signature_end)."'"; +} // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -917,6 +942,24 @@ if ($resql) { if ($search_country) { $param .= '&search_country='.urlencode($search_country); } + if ($search_date_signature_startday) { + $param .= '&search_date_signature_startday='.urlencode($search_date_signature_startday); + } + if ($search_date_signature_startmonth) { + $param .= '&search_date_signature_startmonth='.urlencode($search_date_signature_startmonth); + } + if ($search_date_signature_startyear) { + $param .= '&search_date_signature_startyear='.urlencode($search_date_signature_startyear); + } + if ($search_date_signature_endday) { + $param .= '&search_date_signature_endday='.urlencode($search_date_signature_endday); + } + if ($search_date_signature_endmonth) { + $param .= '&search_date_signature_endmonth='.urlencode($search_date_signature_endmonth); + } + if ($search_date_signature_endyear) { + $param .= '&search_date_signature_endyear='.urlencode($search_date_signature_endyear); + } // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -1148,6 +1191,17 @@ if ($resql) { print '
'; print ''; } + // Date Signature + if (!empty($arrayfields['p.date_signature']['checked'])) { + print ''; + print '
'; + print $form->selectDate($search_date_signature_start ? $search_date_signature_start : -1, 'search_date_signature_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_signature_end ? $search_date_signature_end : -1, 'search_date_signature_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print ''; + } // Availability if (!empty($arrayfields['ava.rowid']['checked'])) { print ''; @@ -1361,7 +1415,10 @@ if ($resql) { print_liste_field_titre($arrayfields['p.fin_validite']['label'], $_SERVER["PHP_SELF"], 'dfv', '', $param, 'align="center"', $sortfield, $sortorder); } if (!empty($arrayfields['p.date_livraison']['checked'])) { - print_liste_field_titre($arrayfields['p.date_livraison']['label'], $_SERVER["PHP_SELF"], 'ddelivery', '', $param, 'align="center"', $sortfield, $sortorder); + print_liste_field_titre($arrayfields['p.date_livraison']['label'], $_SERVER["PHP_SELF"], 'p.date_livraison', '', $param, 'align="center"', $sortfield, $sortorder); + } + if (!empty($arrayfields['p.date_signature']['checked'])) { + print_liste_field_titre($arrayfields['p.date_signature']['label'], $_SERVER["PHP_SELF"], 'p.date_signature', '', $param, 'align="center"', $sortfield, $sortorder); } if (!empty($arrayfields['ava.rowid']['checked'])) { print_liste_field_titre($arrayfields['ava.rowid']['label'], $_SERVER["PHP_SELF"], 'availability', '', $param, '', $sortfield, $sortorder); @@ -1720,6 +1777,18 @@ if ($resql) { $totalarray['nbfield']++; } } + // Date Signature + if (!empty($arrayfields['p.date_signature']['checked'])) { + if ($obj->dsignature) { + print ''.dol_print_date($db->jdate($obj->dsignature), 'day'); + print ''; + } else { + print ' '; + } + if (!$i) { + $totalarray['nbfield']++; + } + } // Availability if (!empty($arrayfields['ava.rowid']['checked'])) { print ''; From 3d21023110a27ab96d6ff0fafb8ae6eb3117709a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Apr 2022 14:11:40 +0200 Subject: [PATCH 111/473] Label of option --- htdocs/admin/pdf.php | 6 +++--- htdocs/langs/en_US/companies.lang | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index fd8377b0a27..1e015d69f9c 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -309,7 +309,7 @@ print ''.$langs->trans("Par // Show sender name -/* Set option as hidden because no need of this for 99.99% of users. +/* Set option as hidden because no need of this for 99.99% of users. Having it as hidden feature is enough. print ''.$langs->trans("MAIN_PDF_HIDE_SENDER_NAME").''; if ($conf->use_javascript_ajax) { print ajax_constantonoff('MAIN_PDF_HIDE_SENDER_NAME'); @@ -321,7 +321,7 @@ print ''; // Hide VAT Intra on address -print ''.$langs->trans("ShowVATIntaInAddress").''; +print ''.$langs->trans("ShowVATIntaInAddress").' - '.$langs->trans("ThirdPartyAddress").''; if ($conf->use_javascript_ajax) { print ajax_constantonoff('MAIN_TVAINTRA_NOT_IN_ADDRESS'); } else { @@ -340,7 +340,7 @@ for ($i = 1; $i <= 6; $i++) { $pid = img_warning().' '.$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CompanyCountry")).''; } if ($pid) { - print ''.$langs->trans("ShowProfIdInAddress").' - '.$pid.''; + print ''.$langs->trans("ShowProfIdInAddress").' - '.$pid.' - '.$langs->trans("ThirdPartyAddress").''; $keyforconstant = 'MAIN_PROFID'.$i.'_IN_ADDRESS'; if ($conf->use_javascript_ajax) { print ajax_constantonoff($keyforconstant); diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 093fb47189d..b1438691cd9 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -19,6 +19,7 @@ ProspectionArea=Prospection area IdThirdParty=Id third party IdCompany=Company Id IdContact=Contact Id +ThirdPartyAddress=Third-party address ThirdPartyContacts=Third-party contacts ThirdPartyContact=Third-party contact/address Company=Company From 8a9be6705d4c674013dfa2ab74184b2370d73df4 Mon Sep 17 00:00:00 2001 From: kamel Date: Thu, 14 Apr 2022 14:14:07 +0200 Subject: [PATCH 112/473] FIX: Call of printOriginObjectLine hook --- htdocs/core/class/commonobject.class.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 02421ea9157..7828e61b166 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4824,11 +4824,9 @@ abstract class CommonObject if (!empty($this->lines)) { foreach ($this->lines as $line) { if (is_object($hookmanager) && (($line->product_type == 9 && !empty($line->special_code)) || !empty($line->fk_parent_line))) { - if (empty($line->fk_parent_line)) { - $parameters = array('line'=>$line, 'i'=>$i); - $action = ''; - $hookmanager->executeHooks('printOriginObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks - } + $parameters = array('line' => $line, 'i' => $i); + $action = ''; + $hookmanager->executeHooks('printOriginObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks } else { $this->printOriginLine($line, '', $restrictlist, '/core/tpl', $selectedLines); } From e0d208214731df7f404c33b1488f543e4ad0d109 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Thu, 14 Apr 2022 16:49:08 +0200 Subject: [PATCH 113/473] Update barcode_EAN13.txt start formatting & english translation --- dev/resources/iso-normes/barcode_EAN13.txt | 64 +++++++++++----------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dev/resources/iso-normes/barcode_EAN13.txt b/dev/resources/iso-normes/barcode_EAN13.txt index f4496327ee4..f6b3c5f5ebb 100644 --- a/dev/resources/iso-normes/barcode_EAN13.txt +++ b/dev/resources/iso-normes/barcode_EAN13.txt @@ -16,57 +16,57 @@ Voici la liste des codes pays ou systeme : EN == -Meaning of the numbers. +Meaning of the numbers: -- 2 digits for the country code or system code +- first 2-3 digits for the country code or system code - 5 digits for the company identifier - 5 digits for item identifier - 1 digit for checksum This rule has been twisted many times to improve the use of the available numbers. -Here is the list of country codes or system: +Here is the list of country codes or system: List ==== -00 � 13 UCC (Etats-Unis et Canada) -20 � 29 Codification interne en magasin -30 � 37 GENCOD-EAN France -380 BCCI (Bulgarie) -383 SANA (Slovenie) -385 CRO-EAN (Croatie) -387 EAN-BIH (Bosnie-Herzegovine) -400 � 440 CCG (Allemagne) -45 + 49 Distribution Code Center � DCC (Japon) -460 � 469 UNISCAN - EAN Russie (Federation de Russie) -471 CAN (Taiwan) -474 EAN Estonie -475 EAN Lettonie -476 EAN Azerba� djan -477 EAN Lituanie -478 EAN Ouzbekistan -479 EAN Sri Lanka -480 PANC (Philippines) -481 EAN Bielorussie -482 EAN Ukraine -484 EAN Moldavie -485 EAN Armenie -486 EAN Georgie -487 EAN Kazakhstan -489 HKANA (Hong Kong) -50 E Centre UK +00 - 13 UCC (U.S.A / États-Unis & Canada) +20 - 29 Flag for internal numbering / Codification interne en magasin +30 - 37 GENCOD-EAN France +380 BCCI (Bulgaria) +383 SANA (Slovenia) +385 CRO-EAN (Croatia) +387 EAN-BIH (Bosnia-Herzegovina) +400-440 CCG (Allemagne/Germany) +45 + 49 Distribution Code Center - DCC (Japan) +460-469 UNISCAN - EAN Russia (Federation de Russie) +471 CAN Taiwan +474 EAN Estonia +475 EAN Latvia +476 EAN Azerbaijan +477 EAN Lithuania +478 EAN Uzbekistan +479 EAN Sri Lanka +480 PANC Philippines +481 EAN Belarus +482 EAN Ukraine +484 EAN Moldova +485 EAN Armenia +486 EAN Georgia +487 EAN Kazakhstan +489 HKANA Hong Kong +50 E Centre UK - United Kingdom 520 HELLCAN-EAN HELLAS (Grece) 528 EAN Liban 529 EAN Chypre -531 EAN-MAC (FYR Mac�donie) +531 EAN-MAC (FYR Macedonie) 535 EAN Malte 539 EAN Irlande -54 ICODIF/EAN Belgique. Luxembourg +54 ICODIF/EAN Belgique. Luxembourg 560 CODIPOR (Portugal) 569 EAN Islande -57 EAN Danemark +57 EAN Danemark 590 EAN Pologne 594 EAN Roumanie 599 H.A.P.M.H. (Hongrie) From 02a3cfbb5f16672f2fff6c65f0fe6a0a3386d56b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Apr 2022 21:43:55 +0200 Subject: [PATCH 114/473] Update paymentsalary.class.php --- htdocs/salaries/class/paymentsalary.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 506e9b73ea5..08e850c259a 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -166,7 +166,7 @@ class PaymentSalary extends CommonObject if ($totalamount != 0) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_salary (entity, fk_salary, datec, datep, amount,"; $sql .= " fk_typepayment, num_payment, note, fk_user_author, fk_bank)"; - $sql .= " VALUES (".$conf->entity.", ".$this->chid.", '".$this->db->idate($now)."',"; + $sql .= " VALUES (".((int) $conf->entity).", ".((int) $this->chid).", '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datepaye)."',"; $sql .= " ".price2num($totalamount).","; $sql .= " ".((int) $this->paiementtype).", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note)."', ".((int) $user->id).","; From d62d24a337778890f042a58aaa17d3ab459160aa Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Thu, 14 Apr 2022 21:47:35 +0200 Subject: [PATCH 115/473] add code to get documents list by knowledgemanagement with api --- htdocs/api/class/api_documents.class.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index da49e4cbba7..d4e35e848ac 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -458,6 +458,20 @@ class Documents extends DolibarrApi } $upload_dir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($object->ref); + } elseif ($modulepart == 'knowledgemanagement') { + require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php'; + + if (!DolibarrApiAccess::$user->rights->knowledgemanagement->knowledgerecord->read && !DolibarrApiAccess::$user->rights->knowledgemanagement->knowledgerecord->read) { + throw new RestException(401); + } + + $object = new KnowledgeRecord($this->db); + $result = $object->fetch($id, $ref); + if (!$result) { + throw new RestException(404, 'Expense report not found'); + } + + $upload_dir = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.dol_sanitizeFileName($object->ref); } elseif ($modulepart == 'categorie' || $modulepart == 'category') { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; From 0023850c9a6f37c31db33d95a018ea3ee8d55fb5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Apr 2022 22:16:17 +0200 Subject: [PATCH 116/473] Update api_documents.class.php --- htdocs/api/class/api_documents.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index d4e35e848ac..9bf7dd7c117 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -468,7 +468,7 @@ class Documents extends DolibarrApi $object = new KnowledgeRecord($this->db); $result = $object->fetch($id, $ref); if (!$result) { - throw new RestException(404, 'Expense report not found'); + throw new RestException(404, 'KM article not found'); } $upload_dir = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.dol_sanitizeFileName($object->ref); From 06f112d3ce5454cd428d7862bea2fdd7402d426e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Apr 2022 22:43:43 +0200 Subject: [PATCH 117/473] Update main.inc.php --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index e66c9e9d313..dd8010dfa92 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -265,7 +265,7 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) { $cookiearrayvalue[$tmpkey] = $_POST[$postkey]; } } - $cookiename = ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? $tmpautoset[0] : '__Secure-'.$tmpautoset[0]); // __Secure- || __Host- + $cookiename = $tmpautoset[0]; $cookievalue = json_encode($cookiearrayvalue); //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue); if (PHP_VERSION_ID < 70300) { From 75d3b3527c148aa2e444f0ac70da2b2aaac7eb4c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Apr 2022 22:45:56 +0200 Subject: [PATCH 118/473] Update main.inc.php --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index dd8010dfa92..3b5793a2cf1 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -297,7 +297,7 @@ if (!empty($php_session_save_handler) && $php_session_save_handler == 'db') { // Must be done after the include of filefunc.inc.php so global variables of conf file are defined (like $dolibarr_main_instance_unique_id or $dolibarr_main_force_https). // Note: the function dol_getprefix() is defined into functions.lib.php but may have been defined to return a different key to manage another area to protect. $prefix = dol_getprefix(''); -$sessionname = ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? 'DOLSESSID_'.$prefix : '__Secure-DOLSESSID_'.$prefix); // __Secure- || __Host- +$sessionname = 'DOLSESSID_'.$prefix; $sessiontimeout = 'DOLSESSTIMEOUT_'.$prefix; if (!empty($_COOKIE[$sessiontimeout])) { ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]); From b4fb6cf527e9499e5763075572d420014734cc8a Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 15 Apr 2022 09:13:41 +0200 Subject: [PATCH 119/473] fix: HTML on PRODUCT_LOT_ENABLE_QUALITY_CONTROL --- htdocs/product/card.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 420203eedae..98f264bb09e 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1396,8 +1396,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Quality control if (!empty($conf->global->PRODUCT_LOT_ENABLE_QUALITY_CONTROL)) { - print ''.$langs->trans("LifeTime").''; - print ''.$langs->trans("QCFrequency").''; + print ''.$langs->trans("LifeTime").''; + print ''.$langs->trans("QCFrequency").''; } // Other attributes @@ -2443,19 +2443,19 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Custom code if (!$object->isService() && empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO)) { - print ''.$langs->trans("CustomCode").''.$object->customcode.''; + print ''.$langs->trans("CustomCode").''.$object->customcode.''; // Origin country code print ''.$langs->trans("Origin").''.getCountry($object->country_id, 0, $db); if (!empty($object->state_id)) { print ' - '.getState($object->state_id, 0, $db); } - print ''; + print ''; } // Quality Control if (!empty($conf->global->PRODUCT_LOT_ENABLE_QUALITY_CONTROL)) { - print ''.$langs->trans("LifeTime").''.$object->lifetime.''; + print ''.$langs->trans("LifeTime").''.$object->lifetime.''; print ''.$langs->trans("QCFrequency").''.$object->qc_frequency.''; } From 24bb6c6f8345b80fc49ef097d3a7f1dbd0103a3f Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 15 Apr 2022 10:20:52 +0200 Subject: [PATCH 120/473] fix: clean mess up around element_tag table --- htdocs/install/mysql/migration/14.0.0-15.0.0.sql | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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..c0d7a328e59 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,16 @@ 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; + +DROP TABLE IF EXISTS llx_element_tag; -- in migration 3.2.0 to 3.3.0 there is a element_tag table creation that is notin create table +CREATE TABLE llx_element_tag +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + fk_categorie integer NOT NULL, + fk_element integer NOT NULL, + import_key varchar(14) +)ENGINE=innodb; + +ALTER TABLE llx_element_tag ADD UNIQUE INDEX idx_element_tag_uk (fk_categorie, fk_element); + +ALTER TABLE llx_element_tag ADD CONSTRAINT fk_element_tag_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); From b8f602008892678d52094345fec22b43daf6995b Mon Sep 17 00:00:00 2001 From: BB2A Anthony Berton Date: Fri, 15 Apr 2022 10:35:36 +0200 Subject: [PATCH 121/473] Move checkbox column as first column on Thirdparty list --- htdocs/core/class/html.form.class.php | 17 ++++++++---- htdocs/societe/list.php | 38 ++++++++++++++------------- htdocs/theme/eldy/global.inc.php | 3 +++ 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b9812d8eec3..679d3b388c6 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8213,10 +8213,11 @@ class Form * @param string $htmlname Name of HTML field * @param array $array Array with array of fields we could show. This array may be modified according to setup of user. * @param string $varpage Id of context for page. Can be set by caller with $varpage=(empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage); + * @param string $pos position colon on liste value left or right * @return string HTML multiselect string * @see selectarray() */ - public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage) + public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '') { global $conf, $langs, $user, $extrafields; @@ -8283,7 +8284,7 @@ class Form
'."\n"; +$formcategory = new FormCategory($db); + +print load_fiche_titre($langs->trans("Other"), '', ''); +print ''; + +print ''; +print ''; +print ''; +print ''; +print "\n"; + +// Hide e-mail headers from collected messages +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("Parameter").'
'.$langs->trans("EmailCollectorHideMailHeaders").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $formcategory->selectarray("MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND); +} +print ''; +print $formcategory->textwithpicto('', $langs->trans("EmailCollectorHideMailHeadersHelp"), 1, 'help'); +print '

'; print ''."\n"; if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) { diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index a3473139638..fe555e7b699 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2070,6 +2070,8 @@ ConfirmCloneEmailCollector=Are you sure you want to clone the Email collector %s DateLastCollectResult=Date of latest collect try DateLastcollectResultOk=Date of latest collect success LastResult=Latest result +EmailCollectorHideMailHeaders=Hide headers of collected e-mails +EmailCollectorHideMailHeadersHelp=When enabled, e-mail headers are ignored during the collection EmailCollectorConfirmCollectTitle=Email collect confirmation EmailCollectorConfirmCollect=Do you want to run this collector now? EmailCollectorExampleToCollectTicketRequestsDesc=Collect emails that match some rules and create automatically a ticket (Module Ticket must be enabled) with the email informations. You can use this collector if you provide some support by email, so your ticket request will be automatically generated. Activate also Collect_Responses to collect answers of your client directly on the ticket view (you must reply from Dolibarr). From aa36e396a3338451090dee16338699dcc91f6fc5 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 18 Apr 2022 22:23:44 +0000 Subject: [PATCH 152/473] Fixing style errors. --- htdocs/admin/ticket.php | 2 +- htdocs/core/modules/modTicket.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index 43f19047bf8..f257b040636 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -106,7 +106,7 @@ if ($action == 'updateMask') { $notification_email_description = "Sender of ticket replies sent from Dolibarr"; if (!empty($notification_email)) { $res = dolibarr_set_const($db, 'TICKET_NOTIFICATION_EMAIL_FROM', $notification_email, 'chaine', 0, $notification_email_description, $conf->entity); - } else { // If an empty e-mail address is providen, use the global "FROM" since an empty field will cause other issues + } else { // If an empty e-mail address is providen, use the global "FROM" since an empty field will cause other issues $res = dolibarr_set_const($db, 'TICKET_NOTIFICATION_EMAIL_FROM', $conf->global->MAIN_MAIL_EMAIL_FROM, 'chaine', 0, $notification_email_description, $conf->entity); } if (!($res > 0)) { diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 483c5ff27cc..8fa132d4843 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -104,7 +104,7 @@ class modTicket extends DolibarrModules // List of particular constants to add when module is enabled // (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) // Example: - $default_signature = $langs->trans('TicketMessageMailSignatureText', $conf->global->MAIN_INFO_SOCIETE_NOM); + $default_signature = $langs->trans('TicketMessageMailSignatureText', $conf->global->MAIN_INFO_SOCIETE_NOM); $this->const = array( 1 => array('TICKET_ENABLE_PUBLIC_INTERFACE', 'chaine', '0', 'Enable ticket public interface', 0), 2 => array('TICKET_ADDON', 'chaine', 'mod_ticket_simple', 'Ticket ref module', 0), From 68cfe61fb8fa8a72c8b5c10a4fb54fab2d8af1fd Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 19 Apr 2022 17:59:59 +0200 Subject: [PATCH 153/473] FIX get TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCE const in TakePos --- htdocs/takepos/admin/setup.php | 2 +- htdocs/takepos/ajax/ajax.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index e631776490a..849c5c56481 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -392,7 +392,7 @@ if (!empty($conf->barcode->enabled)) { print ''; print $form->textwithpicto($langs->trans("TakeposBarcodeRuleToInsertProduct"), $langs->trans("TakeposBarcodeRuleToInsertProductDesc")); print ''; - print ''; + print ''; print "\n"; } diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index a3bcc04b5c8..491a9754748 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -111,8 +111,8 @@ if ($action == 'getProducts') { } } - if (!empty($conf->barcode->enabled) && !empty($conf->global->TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT)) { - $barcode_rules = $conf->global->TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT; + $barcode_rules = getDolGlobalString('TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT'); + if (!empty($conf->barcode->enabled) && !empty($barcode_rules)) { $barcode_rules_list = array(); // get barcode rules From aa86b2c71fc7b82f80d5173e7b6b31f2b12dd39e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Apr 2022 22:26:27 +0200 Subject: [PATCH 154/473] Fix root passfield not editable on install Fix user photo when gravatar not reachable --- htdocs/admin/system/dolibarr.php | 3 ++- htdocs/core/class/html.form.class.php | 6 +++--- htdocs/install/fileconf.php | 3 ++- htdocs/langs/en_US/admin.lang | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index d10e789f39c..e58cf45dd7e 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -435,7 +435,8 @@ foreach ($configfileparameters as $key => $value) { if (empty($valuetoshow)) { print img_warning("EditConfigFileToAddEntry", 'dolibarr_main_instance_unique_id'); } - print '   ('.$langs->trans("HashForPing").'='.md5('dolibarr'.$valuetoshow).')'; + print ''; + print '  => '.$langs->trans("HashForPing").''.md5('dolibarr'.$valuetoshow).''."\n"; } elseif ($newkey == 'dolibarr_main_prod') { print ${$newkey}; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d3e14b09c85..d656fbde897 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -9101,12 +9101,12 @@ class Form if (!empty($conf->gravatar->enabled) && $email && empty($noexternsourceoverwrite)) { // see https://gravatar.com/site/implement/images/php/ $ret .= ''; - $ret .= 'Gravatar avatar'; // gravatar need md5 hash + $ret .= ''; // gravatar need md5 hash } else { if ($nophoto == 'company') { - $ret .= '
'.img_picto('', 'company').'
'; + $ret .= '
'.img_picto('', 'company').'
'; } else { - $ret .= 'No photo'; + $ret .= ''; } } } diff --git a/htdocs/install/fileconf.php b/htdocs/install/fileconf.php index 42ea5e423af..03c5984d780 100644 --- a/htdocs/install/fileconf.php +++ b/htdocs/install/fileconf.php @@ -613,12 +613,13 @@ jQuery(document).ready(function() { function init_needroot() { + console.log("init_needroot force_install_noedit="); /*alert(jQuery("#db_create_database").prop("checked")); */ if (jQuery("#db_create_database").is(":checked") || jQuery("#db_create_user").is(":checked")) { jQuery(".hideroot").show(); + if (empty($force_install_noedit)) { ?> jQuery(".needroot").removeAttr('disabled'); } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 5af3fe19592..84df64fe655 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2219,4 +2219,5 @@ EachTerminalHasItsOwnCounter=Each terminal use its own counter. FillAndSaveAccountIdAndSecret=Fill and save account ID and secret first PreviousHash=Previous hash LateWarningAfter="Late" warning after -TemplateforBusinessCards=Template for a business card in different size \ No newline at end of file +TemplateforBusinessCards=Template for a business card in different size +HashForPing=Hash used for ping From 1e96cd636f81935b452cc5e40a7814e93bdc5d40 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 19 Apr 2022 22:38:42 +0200 Subject: [PATCH 155/473] FIX Accountancy - Missing language key --- htdocs/langs/en_US/accountancy.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index fd5ff8461fe..c66e0295bfa 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -302,6 +302,7 @@ NotYetAccounted=Not yet transferred to accounting ShowTutorial=Show Tutorial NotReconciled=Not reconciled WarningRecordWithoutSubledgerAreExcluded=Warning, all lines without subledger account defined are filtered and excluded from this view +AccountRemovedFromCurrentChartOfAccount=Accounting account that does not exist in the current chart of accounts ## Admin BindingOptions=Binding options From 307476786cc33f94447e78db3c58882f47523185 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Apr 2022 23:24:08 +0200 Subject: [PATCH 156/473] Fix label of remain to pay on vendor invoices FIX tool to fix bank account not in main currency for vendor invoice --- htdocs/compta/bank/card.php | 8 +++--- htdocs/fourn/facture/card.php | 30 ++++++++++------------- htdocs/install/mysql/migration/repair.sql | 3 +++ htdocs/langs/en_US/withdrawals.lang | 4 ++- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 283258a08a0..9211fa71b9e 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -769,13 +769,13 @@ if ($action == 'create') { print ''; if ($conf->prelevement->enabled) { - print ''.$langs->trans("ICS").' ('.$langs->trans("StandingOrder").')'; + print ''.$form->textwithpicto($langs->trans("ICS"), $langs->trans("ICS").' ('.$langs->trans("UsedFor", $langs->transnoentitiesnoconv("StandingOrder")).')').''; print ''.$object->ics.''; print ''; } if ($conf->paymentbybanktransfer->enabled) { - print ''.$langs->trans("ICS").' ('.$langs->trans("BankTransfer").')'; + print ''.$form->textwithpicto($langs->trans("IDS"), $langs->trans("IDS").' ('.$langs->trans("UsedFor", $langs->transnoentitiesnoconv("BankTransfer")).')').''; print ''.$object->ics_transfer.''; print ''; } @@ -1068,12 +1068,12 @@ if ($action == 'create') { print ''; if ($conf->prelevement->enabled) { - print ''.$langs->trans("ICS").' ('.$langs->trans("StandingOrder").')'; + print ''.$form->textwithpicto($langs->trans("ICS"), $langs->trans("ICS").' ('.$langs->trans("UsedFor", $langs->transnoentitiesnoconv("StandingOrder")).')').''; print ''; } if ($conf->paymentbybanktransfer->enabled) { - print ''.$langs->trans("ICS").' ('.$langs->trans("BankTransfer").')'; + print ''.$form->textwithpicto($langs->trans("IDS"), $langs->trans("IDS").' ('.$langs->trans("UsedFor", $langs->transnoentitiesnoconv("BankTransfer")).')').''; print ''; } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 5a9b1054773..71c7a4beaf5 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1846,7 +1846,7 @@ if ($action == 'create') { $currency_code = $conf->currency; $societe = ''; - if (GETPOST('socid') > 0) { + if (GETPOST('socid', 'int') > 0) { $societe = new Societe($db); $societe->fetch(GETPOST('socid', 'int')); if (!empty($conf->multicurrency->enabled) && !empty($societe->multicurrency_code)) { @@ -3285,10 +3285,9 @@ if ($action == 'create') { // Remainder to pay print ''; print ''; - if ($resteapayeraffiche >= 0) { - print $langs->trans('RemainderToPay'); - } else { - print $langs->trans('ExcessPaid'); + print $langs->trans('RemainderToPay'); + if ($resteapayeraffiche < 0) { + print ' ('.$langs->trans('NegativeIfExcessPaid').')'; } print ''; print ''; @@ -3298,10 +3297,9 @@ if ($action == 'create') { if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) { print ''; print ''; - if ($resteapayeraffiche <= 0) { - print $langs->trans('RemainderToPayBackMulticurrency'); - } else { - print $langs->trans('ExcessPaidMulticurrency'); + print $langs->trans('RemainderToPayMulticurrency'); + if ($resteapayeraffiche < 0) { + print ' ('.$langs->trans('NegativeIfExcessPaid').')'; } print ''; print ''; @@ -3322,10 +3320,9 @@ if ($action == 'create') { // Remainder to pay back print ''; print ''; - if ($resteapayeraffiche <= 0) { - print $langs->trans('RemainderToPayBack'); - } else { - print $langs->trans('ExcessPaid'); + print $langs->trans('RemainderToPayBack'); + if ($resteapayeraffiche > 0) { + print ' ('.$langs->trans('NegativeIfExcessRefunded').')'; } print ''; print ''; @@ -3335,10 +3332,9 @@ if ($action == 'create') { if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) { print ''; print ''; - if ($resteapayeraffiche <= 0) { - print $langs->trans('RemainderToPayBackMulticurrency'); - } else { - print $langs->trans('ExcessPaidMulticurrency'); + print $langs->trans('RemainderToPayBackMulticurrency'); + if ($resteapayeraffiche> 0) { + print ' ('.$langs->trans('NegativeIfExcessRefunded').')'; } print ''; print ''; diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 070f3a2c5da..2e7f42a2727 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -562,3 +562,6 @@ DELETE FROM llx_rights_def WHERE module = 'hrm' AND perms = 'employee'; -- 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; +-- DROP TABLE tmp_bank2; +-- CREATE TABLE tmp_bank2 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_supplier' INNER JOIN llx_paiementfourn 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_bank2 as tb WHERE tb.rowid = b.rowid) WHERE b.amount_main_currency IS NULL; diff --git a/htdocs/langs/en_US/withdrawals.lang b/htdocs/langs/en_US/withdrawals.lang index 9d145ef354d..75cee952bcd 100644 --- a/htdocs/langs/en_US/withdrawals.lang +++ b/htdocs/langs/en_US/withdrawals.lang @@ -137,6 +137,7 @@ SEPAFRST=SEPA FRST ExecutionDate=Execution date CreateForSepa=Create direct debit file ICS=Creditor Identifier - ICS +IDS=Debitor Identifier END_TO_END="EndToEndId" SEPA XML tag - Unique id assigned per transaction USTRD="Unstructured" SEPA XML tag ADDDAYS=Add days to Execution Date @@ -154,4 +155,5 @@ ErrorCompanyHasDuplicateDefaultBAN=Company with id %s has more than one default ErrorICSmissing=Missing ICS in Bank account %s TotalAmountOfdirectDebitOrderDiffersFromSumOfLines=Total amount of direct debit order differs from sum of lines WarningSomeDirectDebitOrdersAlreadyExists=Warning: There is already some pending Direct Debit orders (%s) requested for an amount of %s -WarningSomeCreditTransferAlreadyExists=Warning: There is already some pending Credit Transfer (%s) requested for an amount of %s \ No newline at end of file +WarningSomeCreditTransferAlreadyExists=Warning: There is already some pending Credit Transfer (%s) requested for an amount of %s +UsedFor=Used for %s \ No newline at end of file From ad7fcd264b15b467c75719add855bbd51934fc32 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Apr 2022 23:39:09 +0200 Subject: [PATCH 157/473] FIX Tabulation must be allowed for HTML content --- htdocs/main.inc.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 9d96eb63a27..1d09b9f9887 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -108,10 +108,11 @@ function testSqlAndScriptInject($val, $type) // We check string because some hacks try to obfuscate evil strings by inserting non printable chars. Example: 'java(ascci09)scr(ascii00)ipt' is processed like 'javascript' (whatever is place of evil ascii char) // We should use dol_string_nounprintableascii but function is not yet loaded/available // Example of valid UTF8 chars: - // utf8=utf8mb3: '\x0A', '\x0D', '\x7E' + // utf8=utf8mb3: '\x09', '\x0A', '\x0D', '\x7E' // utf8=utf8mb3: '\xE0\xA0\x80' // utf8mb4: '\xF0\x9D\x84\x9E' (but this may be refused by the database insert if pagecode is utf8=utf8mb3) - $newval = preg_replace('/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F]/u', '', $val); // /u operator makes UTF8 valid characters being ignored so are not included into the replace + $newval = preg_replace('/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/u', '', $val); // /u operator makes UTF8 valid characters being ignored so are not included into the replace + // Note that $newval may also be completely empty '' when non valid UTF8 are found. if ($newval != $val) { // If $val has changed after removing non valid UTF8 chars, it means we have an evil string. From 0faec59f56c5c72e54146fe3c773610be16717fe Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 20 Apr 2022 08:13:01 +0200 Subject: [PATCH 158/473] FIX conflict and integrate Lionel fix --- htdocs/takepos/ajax/ajax.php | 133 ++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 8 deletions(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index ab4c9af2904..3ec334bd703 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -53,6 +53,8 @@ if (empty($user->rights->takepos->run)) { accessforbidden(); } +// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks +$hookmanager->initHooks(array('takeposproductsearch')); /* * View @@ -70,9 +72,10 @@ if ($action == 'getProducts') { $res = array(); if (is_array($prods) && count($prods) > 0) { foreach ($prods as $prod) { - if ($conf->global->TAKEPOS_PRODUCT_IN_STOCK == 1) { + if (getDolGlobalInt('TAKEPOS_PRODUCT_IN_STOCK') == 1) { + // remove products without stock $prod->load_stock('nobatch,novirtual'); - if ($prod->stock_warehouse[$conf->global->{'CASHDESK_ID_WAREHOUSE'.$_SESSION['takeposterminal']}]->real <= 0) { + if ($prod->stock_warehouse[getDolGlobalString('CASHDESK_ID_WAREHOUSE'.$_SESSION['takeposterminal'])]->real <= 0) { continue; } } @@ -117,25 +120,138 @@ if ($action == 'getProducts') { } } - $sql = 'SELECT p.rowid, p.ref, p.label, p.tosell, p.tobuy, p.barcode, p.price '; - if ($conf->global->TAKEPOS_PRODUCT_IN_STOCK == 1) { + $barcode_rules = getDolGlobalString('TAKEPOS_BARCODE_RULE_TO_INSERT_PRODUCT'); + if (!empty($conf->barcode->enabled) && !empty($barcode_rules)) { + $barcode_rules_list = array(); + + // get barcode rules + $barcode_char_nb = 0; + $barcode_rules_arr = explode('+', $barcode_rules); + foreach ($barcode_rules_arr as $barcode_rules_values) { + $barcode_rules_values_arr = explode(':', $barcode_rules_values); + if (count($barcode_rules_values_arr) == 2) { + $char_nb = intval($barcode_rules_values_arr[1]); + $barcode_rules_list[] = array('code' => $barcode_rules_values_arr[0], 'char_nb' => $char_nb); + $barcode_char_nb += $char_nb; + } + } + + $barcode_value_list = array(); + $barcode_offset = 0; + $barcode_length = dol_strlen($term); + if ($barcode_length == $barcode_char_nb) { + $rows = array(); + + // split term with barcode rules + foreach ($barcode_rules_list as $barcode_rule_arr) { + $code = $barcode_rule_arr['code']; + $char_nb = $barcode_rule_arr['char_nb']; + $barcode_value_list[$code] = substr($term, $barcode_offset, $char_nb); + $barcode_offset += $char_nb; + } + + if (isset($barcode_value_list['ref'])) { + // search product from reference + $sql = "SELECT rowid, ref, label, tosell, tobuy, barcode, price"; + $sql .= " FROM " . $db->prefix() . "product as p"; + $sql .= " WHERE entity IN (" . getEntity('product') . ")"; + $sql .= " AND ref = '" . $db->escape($barcode_value_list['ref']) . "'"; + if ($filteroncategids) { + $sql .= " AND EXISTS (SELECT cp.fk_product FROM " . $db->prefix() . "categorie_product as cp WHERE cp.fk_product = p.rowid AND cp.fk_categorie IN (".$db->sanitize($filteroncategids)."))"; + } + $sql .= " AND tosell = 1"; + $sql .= " AND (barcode IS NULL OR barcode != '" . $db->escape($term) . "')"; + + $resql = $db->query($sql); + if ($resql && $db->num_rows($resql) == 1) { + if ($obj = $db->fetch_object($resql)) { + $qty = 1; + if (isset($barcode_value_list['qu'])) { + $qty_str = $barcode_value_list['qu']; + if (isset($barcode_value_list['qd'])) { + $qty_str .= '.' . $barcode_value_list['qd']; + } + $qty = floatval($qty_str); + } + + $ig = '../public/theme/common/nophoto.png'; + if (empty($conf->global->TAKEPOS_HIDE_PRODUCT_IMAGES)) { + $objProd = new Product($db); + $objProd->fetch($obj->rowid); + $image = $objProd->show_photos('product', $conf->product->multidir_output[$objProd->entity], 'small', 1); + + $match = array(); + preg_match('@src="([^"]+)"@', $image, $match); + $file = array_pop($match); + + if ($file != '') { + if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) { + $ig = $file.'&cache=1'; + } else { + $ig = $file.'&cache=1&publictakepos=1&modulepart=product'; + } + } + } + + $rows[] = array( + 'rowid' => $obj->rowid, + 'ref' => $obj->ref, + 'label' => $obj->label, + 'tosell' => $obj->tosell, + 'tobuy' => $obj->tobuy, + 'barcode' => $obj->barcode, + 'price' => $obj->price, + 'object' => 'product', + 'img' => $ig, + 'qty' => $qty, + ); + } + $db->free($resql); + } + } + + if (count($rows) == 1) { + echo json_encode($rows); + exit(); + } + } + } + + $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price' ; + if (getDolGlobalInt('TAKEPOS_PRODUCT_IN_STOCK') == 1) { $sql .= ', ps.reel'; } + // Add fields from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; - if ($conf->global->TAKEPOS_PRODUCT_IN_STOCK == 1) { + if (getDolGlobalInt('TAKEPOS_PRODUCT_IN_STOCK') == 1) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps'; $sql .= ' ON (p.rowid = ps.fk_product'; $sql .= " AND ps.fk_entrepot = ".((int) getDolGlobalInt("CASHDESK_ID_WAREHOUSE".$_SESSION['takeposterminal'])); } + + // Add tables from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $sql .= ' WHERE entity IN ('.getEntity('product').')'; if ($filteroncategids) { $sql .= ' AND EXISTS (SELECT cp.fk_product FROM '.MAIN_DB_PREFIX.'categorie_product as cp WHERE cp.fk_product = p.rowid AND cp.fk_categorie IN ('.$db->sanitize($filteroncategids).'))'; } - $sql .= ' AND p.tosell = 1'; - if ($conf->global->TAKEPOS_PRODUCT_IN_STOCK == 1) { + $sql .= ' AND tosell = 1'; + if (getDolGlobalInt('TAKEPOS_PRODUCT_IN_STOCK') == 1) { $sql .= ' AND ps.reel > 0'; } - $sql .= natural_search(array('p.ref', 'p.label', 'p.barcode'), $term); + $sql .= natural_search(array('ref', 'label', 'barcode'), $term); + // Add where from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $resql = $db->query($sql); if ($resql) { $rows = array(); @@ -168,6 +284,7 @@ if ($action == 'getProducts') { 'price' => $obj->price, 'object' => 'product', 'img' => $ig, + 'qty' => 1, //'price_formated' => price(price2num($obj->price, 'MU'), 1, $langs, 1, -1, -1, $conf->currency) ); } From 6788cd179c82725397922347c40f9347e0a1e931 Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 20 Apr 2022 12:01:17 +0200 Subject: [PATCH 159/473] Add hooks completeAjaxReturnArray --- htdocs/takepos/ajax/ajax.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index a3bcc04b5c8..5f30b8599b3 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -267,6 +267,11 @@ if ($action == 'getProducts') { 'qty' => 1, //'price_formated' => price(price2num($obj->price, 'MU'), 1, $langs, 1, -1, -1, $conf->currency) ); + // Add entries to row from hooks + $parameters=array(); + $parameters['row'] = end($rows); + $parameters['obj'] = $obj; + $reshook=$hookmanager->executeHooks('completeAjaxReturnArray', $parameters); } echo json_encode($rows); } else { From c23ed7c47b016d386f8df3c456371d4baebaa2a7 Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 20 Apr 2022 14:47:36 +0200 Subject: [PATCH 160/473] Add hooks completeJSProductDisplay --- htdocs/takepos/index.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index b23907b64f1..d64c497d05f 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -360,7 +360,13 @@ function LoadProducts(position, issubcat) { $("#prodiv"+ishow).data("iscat", 0); $("#prodiv"+ishow).attr("class","wrapper2"); $("#prowatermark"+ishow).hide(); - ishow++; //Next product to show after print data product + executeHooks('completeJSProductDisplay', $parameters); + print $hookmanager->resPrint; + ?> } //console.log("Hide the prowatermark for ishow="+ishow); idata++; //Next data everytime @@ -615,6 +621,13 @@ function Search2(keyCodeForEnter) { } $("#prodiv" + i).data("rowid", data[i]['rowid']); $("#prodiv" + i).data("iscat", 0); + executeHooks('completeJSProductDisplay', $parameters); + print $hookmanager->resPrint; + ?> } }).always(function (data) { // If there is only 1 answer From db3edba5784180e1472557d27930e798e4f80412 Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 20 Apr 2022 14:51:55 +0200 Subject: [PATCH 161/473] Delete comments --- htdocs/takepos/ajax/ajax.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 5f30b8599b3..9afde9ba341 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -211,14 +211,14 @@ if ($action == 'getProducts') { $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price' ; // Add fields from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook + $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); $sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; // Add tables from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); // Note that $action and $object may have been modified by hook + $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); $sql .= $hookmanager->resPrint; $sql .= ' WHERE entity IN ('.getEntity('product').')'; @@ -229,7 +229,7 @@ if ($action == 'getProducts') { $sql .= natural_search(array('ref', 'label', 'barcode'), $term); // Add where from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook + $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); $sql .= $hookmanager->resPrint; $resql = $db->query($sql); From 6e8ba543ded0790237a09a85ca5fcdf16c2c0156 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 20 Apr 2022 13:33:22 +0000 Subject: [PATCH 162/473] Fixing style errors. --- htdocs/takepos/ajax/ajax.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 9afde9ba341..f794ac0584a 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -218,7 +218,7 @@ if ($action == 'getProducts') { // Add tables from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); + $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); $sql .= $hookmanager->resPrint; $sql .= ' WHERE entity IN ('.getEntity('product').')'; @@ -229,7 +229,7 @@ if ($action == 'getProducts') { $sql .= natural_search(array('ref', 'label', 'barcode'), $term); // Add where from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); + $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); $sql .= $hookmanager->resPrint; $resql = $db->query($sql); From 5cb114df610024dc3de0b95452535e51bc6537cb Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 20 Apr 2022 17:46:16 +0200 Subject: [PATCH 163/473] fix empty search --- htdocs/takepos/index.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index b23907b64f1..0bfdbc84b29 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -557,6 +557,18 @@ function New() { * return {void} */ function Search2(keyCodeForEnter) { + if ($('#search').val() == '') { + $("[id^=prowatermark]").html(""); + $("[id^=prodesc]").text(""); + $("[id^=probutton]").text(""); + $("[id^=probutton]").hide(); + $("[id^=proprice]").attr("class", "hidden"); + $("[id^=proprice]").html(""); + $("[id^=proimg]").attr("src", "genimg/empty.png"); + $("[id^=prodiv]").data("rowid", ""); + return; + } + console.log("Search2 Call ajax search to replace products keyCodeForEnter="+keyCodeForEnter); var search = false; @@ -579,6 +591,7 @@ function Search2(keyCodeForEnter) { $.getJSON('/takepos/ajax/ajax.php?action=search&term=' + $('#search').val(), function (data) { for (i = 0; i < ; i++) { if (typeof (data[i]) == "undefined") { + $("#prowatermark" + i).html(""); $("#prodesc" + i).text(""); $("#probutton" + i).text(""); $("#probutton" + i).hide(); From d9521d40e4b3dd26dcb866f8fc76dc4d679cf5ff Mon Sep 17 00:00:00 2001 From: fred1201 Date: Thu, 21 Apr 2022 07:39:51 +0200 Subject: [PATCH 164/473] Update index.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace call function text( ) by html() to fix display in take post when spécial caracter are store in database: éèà become éàè --- htdocs/takepos/index.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index b23907b64f1..c0045fc67d8 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -232,7 +232,7 @@ function PrintCategories(first) { continue; } $("#catdivdesc"+i).show(); - $("#catdesc"+i).text(categories[parseInt(i)+parseInt(first)]['label']); + $("#catdesc"+i).html(categories[parseInt(i)+parseInt(first)]['label']); $("#catimg"+i).attr("src","genimg/index.php?query=cat&id="+categories[parseInt(i)+parseInt(first)]['rowid']); $("#catdiv"+i).data("rowid",categories[parseInt(i)+parseInt(first)]['rowid']); $("#catdiv"+i).attr('class', 'wrapper'); @@ -266,7 +266,7 @@ function MoreCategories(moreorless) { continue; } $("#catdivdesc"+i).show(); - $("#catdesc"+i).text(categories[i+( * pagecategories)]['label']); + $("#catdesc"+i).html(categories[i+( * pagecategories)]['label']); $("#catimg"+i).attr("src","genimg/index.php?query=cat&id="+categories[i+( * pagecategories)]['rowid']); $("#catdiv"+i).data("rowid",categories[i+( * pagecategories)]['rowid']); $("#catwatermark"+i).show(); @@ -295,8 +295,8 @@ function LoadProducts(position, issubcat) { jQuery.each(subcategories, function(i, val) { if (currentcat==val.fk_parent) { $("#prodivdesc"+ishow).show(); - $("#prodesc"+ishow).text(val.label); - $("#probutton"+ishow).text(val.label); + $("#prodesc"+ishow).html(val.label); + $("#probutton"+ishow).html(val.label); $("#probutton"+ishow).show(); $("#proprice"+ishow).attr("class", "hidden"); $("#proprice"+ishow).html(""); @@ -343,13 +343,13 @@ function LoadProducts(position, issubcat) { if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'ref\'].bold() + \' - \' + data[parseInt(idata)][\'label\']);'; } else { - echo '$("#prodesc"+ishow).text(data[parseInt(idata)][\'label\']);'; + echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'label\']);'; } echo '$("#proimg"+ishow).attr("title", titlestring);'; echo '$("#proimg"+ishow).attr("src", "genimg/index.php?query=pro&id="+data[idata][\'id\']);'; } else { echo '$("#probutton"+ishow).show();'; - echo '$("#probutton"+ishow).text(data[parseInt(idata)][\'label\']);'; + echo '$("#probutton"+ishow).html(data[parseInt(idata)][\'label\']);'; } ?> if (data[parseInt(idata)]['price_formated']) { @@ -414,9 +414,9 @@ function MoreProducts(moreorless) { if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?> $("#prodesc"+ishow).html(data[parseInt(idata)]['ref'].bold() + ' - ' + data[parseInt(idata)]['label']); - $("#prodesc"+ishow).text(data[parseInt(idata)]['label']); + $("#prodesc"+ishow).html(data[parseInt(idata)]['label']); - $("#probutton"+ishow).text(data[parseInt(idata)]['label']); + $("#probutton"+ishow).html(data[parseInt(idata)]['label']); $("#probutton"+ishow).show(); if (data[parseInt(idata)]['price_formated']) { $("#proprice"+ishow).attr("class", "productprice"); @@ -597,10 +597,10 @@ function Search2(keyCodeForEnter) { if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?> $("#prodesc" + i).html(data[i]['ref'].bold() + ' - ' + data[i]['label']); - $("#prodesc" + i).text(data[i]['label']); + $("#prodesc" + i).html(data[i]['label']); $("#prodivdesc" + i).show(); - $("#probutton" + i).text(data[i]['label']); + $("#probutton" + i).html(data[i]['label']); $("#probutton" + i).show(); if (data[i]['price_formated']) { $("#proprice" + i).attr("class", "productprice"); From 731d85130c702fc9414490a1784e65d9eda3ba7e Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 21 Apr 2022 09:49:00 +0200 Subject: [PATCH 165/473] FIX missing hook parameter --- htdocs/core/class/html.form.class.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d656fbde897..6a7bd9a688f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8404,7 +8404,7 @@ class Form public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array()) { global $conf, $langs, $hookmanager; - global $bc, $action; + global $action; $linktoelem = ''; $linktoelemlist = ''; @@ -8450,11 +8450,10 @@ class Form ); } - // Can complete the possiblelink array - $hookmanager->initHooks(array('commonobject')); - $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan); - if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to + // Can complete the possiblelink array + $hookmanager->initHooks(array('commonobject')); + $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks); $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook } From 8878eb6d76445653bac28817006877d5d163f237 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 21 Apr 2022 14:52:06 +0200 Subject: [PATCH 166/473] FIX compatibility with multicompany sharings --- htdocs/core/modules/project/mod_project_simple.php | 6 +++--- htdocs/core/modules/project/mod_project_universal.php | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/core/modules/project/mod_project_simple.php b/htdocs/core/modules/project/mod_project_simple.php index b1dbe4bae48..921b68f492b 100644 --- a/htdocs/core/modules/project/mod_project_simple.php +++ b/htdocs/core/modules/project/mod_project_simple.php @@ -125,14 +125,14 @@ class mod_project_simple extends ModeleNumRefProjects */ public function getNextValue($objsoc, $project) { - global $db, $conf; + global $db; // First, we get the max value $posindice = strlen($this->prefix) + 6; $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql .= " FROM ".MAIN_DB_PREFIX."projet"; $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - $sql .= " AND entity = ".$conf->entity; + $sql .= " AND entity IN (".getEntity('projectnumber', 1, $project).")"; $resql = $db->query($sql); if ($resql) { @@ -147,7 +147,7 @@ class mod_project_simple extends ModeleNumRefProjects return -1; } - $date = empty($project->date_c) ?dol_now() : $project->date_c; + $date = (empty($project->date_c) ? dol_now() : $project->date_c); //$yymm = strftime("%y%m",time()); $yymm = strftime("%y%m", $date); diff --git a/htdocs/core/modules/project/mod_project_universal.php b/htdocs/core/modules/project/mod_project_universal.php index 550d72c4f68..47fd83842ed 100644 --- a/htdocs/core/modules/project/mod_project_universal.php +++ b/htdocs/core/modules/project/mod_project_universal.php @@ -136,8 +136,11 @@ class mod_project_universal extends ModeleNumRefProjects return 0; } - $date = empty($project->date_c) ?dol_now() : $project->date_c; - $numFinal = get_next_value($db, $mask, 'projet', 'ref', '', (is_object($objsoc) ? $objsoc->code_client : ''), $date); + // Get entities + $entity = getEntity('projectnumber', 1, $project); + + $date = (empty($project->date_c) ? dol_now() : $project->date_c); + $numFinal = get_next_value($db, $mask, 'projet', 'ref', '', (is_object($objsoc) ? $objsoc : ''), $date, 'next', false, null, $entity); return $numFinal; } From 2a5c54d4e4deb51439531e8561e5b151e84789e0 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 21 Apr 2022 16:02:41 +0200 Subject: [PATCH 167/473] FIX compatibility for ticket number sharing --- htdocs/core/modules/ticket/mod_ticket_simple.php | 2 +- htdocs/core/modules/ticket/mod_ticket_universal.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/ticket/mod_ticket_simple.php b/htdocs/core/modules/ticket/mod_ticket_simple.php index 523da47191d..76d8e4f8d79 100644 --- a/htdocs/core/modules/ticket/mod_ticket_simple.php +++ b/htdocs/core/modules/ticket/mod_ticket_simple.php @@ -129,7 +129,7 @@ class mod_ticket_simple extends ModeleNumRefTicket $sql .= " FROM ".MAIN_DB_PREFIX."ticket"; $search = $this->prefix."____-%"; $sql .= " WHERE ref LIKE '".$db->escape($search)."'"; - $sql .= " AND entity = ".$conf->entity; + $sql .= " AND entity IN (".getEntity('ticketnumber', 1, $ticket).")"; $resql = $db->query($sql); if ($resql) { diff --git a/htdocs/core/modules/ticket/mod_ticket_universal.php b/htdocs/core/modules/ticket/mod_ticket_universal.php index 176af782dc7..2c46376eea1 100644 --- a/htdocs/core/modules/ticket/mod_ticket_universal.php +++ b/htdocs/core/modules/ticket/mod_ticket_universal.php @@ -134,8 +134,11 @@ class mod_ticket_universal extends ModeleNumRefTicket return 0; } + // Get entities + $entity = getEntity('ticketnumber', 1, $ticket); + $date = empty($ticket->datec) ? dol_now() : $ticket->datec; - $numFinal = get_next_value($db, $mask, 'ticket', 'ref', '', $objsoc->code_client, $date); + $numFinal = get_next_value($db, $mask, 'ticket', 'ref', '', $objsoc->code_client, $date, 'next', false, null, $entity); return $numFinal; } From 2992b3e84580c400b9afb401a1c9bb3f4f9253de Mon Sep 17 00:00:00 2001 From: lvessiller Date: Fri, 22 Apr 2022 09:24:23 +0200 Subject: [PATCH 168/473] NEW send last document in mass mailing action --- htdocs/core/actions_massactions.inc.php | 46 ++++++++++++++++++------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5ec011f5017..171383d7008 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -306,29 +306,51 @@ if (!$error && $massaction == 'confirm_presend') { // TODO Set subdir to be compatible with multi levels dir trees // $subdir = get_exdir($objectobj->id, 2, 0, 0, $objectobj, $objectobj->element) $filedir = $uploaddir.'/'.$subdir.dol_sanitizeFileName($objectobj->ref); - $file = $filedir.'/'.$filename; + $filepath = $filedir.'/'.$filename; // For supplier invoices, we use the file provided by supplier, not the one we generate if ($objectobj->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($uploaddir.'/'.get_exdir($objectobj->id, 2, 0, 0, $objectobj, $objectobj->element).$objectobj->ref, preg_quote($objectobj->ref, '/').'([^\-])+'); - $file = $fileparams['fullname']; + $filepath = $fileparams['fullname']; } - $mime = dol_mimetype($file); + // try to find other files generated for this object (last_main_doc) + $filename_found = ''; + $filepath_found = ''; + $file_check_list = array(); + $file_check_list[] = array( + 'name' => $filename, + 'path' => $filepath, + ); + if (!empty($objectobj->last_main_doc)) { + $file_check_list[] = array( + 'name' => basename($objectobj->last_main_doc), + 'path' => DOL_DATA_ROOT . '/' . $objectobj->last_main_doc, + ); + } + foreach ($file_check_list as $file_check_arr) { + if (dol_is_file($file_check_arr['path'])) { + $filename_found = $file_check_arr['name']; + $filepath_found = $file_check_arr['path']; + break; + } + } - if (dol_is_file($file)) { + if ($filepath_found) { // Create form object $attachedfilesThirdpartyObj[$thirdpartyid][$objectid] = array( - 'paths'=>array($file), - 'names'=>array($filename), - 'mimes'=>array($mime) + 'paths'=>array($filepath_found), + 'names'=>array($filename_found), + 'mimes'=>array(dol_mimetype($filepath_found)) ); } else { - $nbignored++; - $langs->load("errors"); - $resaction .= '
'.$langs->trans('ErrorCantReadFile', $file).'

'; - dol_syslog('Failed to read file: '.$file, LOG_WARNING); - continue; + $nbignored++; + $langs->load("errors"); + foreach ($file_check_list as $file_check_arr) { + $resaction .= '
'.$langs->trans('ErrorCantReadFile', $file_check_arr['path']).'

'; + dol_syslog('Failed to read file: '.$file_check_arr['path'], LOG_WARNING); + } + continue; } } From ca0f98d09f65f7aa107ca30bab815388d2ebb410 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Fri, 22 Apr 2022 13:50:39 +0200 Subject: [PATCH 169/473] FIX : label tax cat trad --- htdocs/expensereport/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 50ee78b4097..31cf21c34ae 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -2068,7 +2068,8 @@ if ($action == 'create') { // IK if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) { print ''; - print dol_getIdFromCode($db, $line->fk_c_exp_tax_cat, 'c_exp_tax_cat', 'rowid', 'label'); + $exp_tax_cat_label = dol_getIdFromCode($db, $line->fk_c_exp_tax_cat, 'c_exp_tax_cat', 'rowid', 'label'); + print $langs->trans($exp_tax_cat_label); print ''; } From 609ef9bfa79c47cc91b322b1276c956eccaa8400 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Fri, 22 Apr 2022 14:26:16 +0200 Subject: [PATCH 170/473] FIX : var name --- htdocs/expensereport/payment/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/expensereport/payment/list.php b/htdocs/expensereport/payment/list.php index 8308ea3fc4c..fa8ba9bcdcf 100644 --- a/htdocs/expensereport/payment/list.php +++ b/htdocs/expensereport/payment/list.php @@ -523,7 +523,7 @@ while ($i < min($num, $limit)) { // Cheque number (fund transfer) if (!empty($arrayfields['pndf.num_payment']['checked'])) { - print ''.$objp->num_paiement.''; + print ''.$objp->num_payment.''; if (!$i) { $totalarray['nbfield']++; } From 6f9f78af33db723907284b7d3f814518a971165d Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Fri, 22 Apr 2022 14:28:43 +0200 Subject: [PATCH 171/473] FIX : var name --- htdocs/expensereport/payment/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/expensereport/payment/list.php b/htdocs/expensereport/payment/list.php index fa8ba9bcdcf..f5196181cf2 100644 --- a/htdocs/expensereport/payment/list.php +++ b/htdocs/expensereport/payment/list.php @@ -515,7 +515,7 @@ while ($i < min($num, $limit)) { // Pyament type if (!empty($arrayfields['c.libelle']['checked'])) { $payment_type = $langs->trans("PaymentType".$objp->paiement_type) != ("PaymentType".$objp->paiement_type) ? $langs->trans("PaymentType".$objp->paiement_type) : $objp->paiement_libelle; - print ''.$payment_type.' '.dol_trunc($objp->num_paiement, 32).''; + print ''.$payment_type.' '.dol_trunc($objp->num_payment, 32).''; if (!$i) { $totalarray['nbfield']++; } From d2ec1efb42acd6454628a1ef9ddc8d9f8cc28d2e Mon Sep 17 00:00:00 2001 From: Eric Seigne Date: Fri, 22 Apr 2022 14:49:22 +0200 Subject: [PATCH 172/473] fix #20690: add lang filter for people --- htdocs/core/modules/mailings/contacts1.modules.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/mailings/contacts1.modules.php b/htdocs/core/modules/mailings/contacts1.modules.php index bd4300ea71d..1450fe75b8c 100644 --- a/htdocs/core/modules/mailings/contacts1.modules.php +++ b/htdocs/core/modules/mailings/contacts1.modules.php @@ -311,6 +311,13 @@ class mailing_contacts1 extends MailingTargets else dol_print_error($this->db); $s .= ''; + + //Choose language + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($this->db); + $s .= $langs->trans("DefaultLang").': '; + $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); + return $s; } @@ -344,6 +351,7 @@ class mailing_contacts1 extends MailingTargets $filter_category = GETPOST('filter_category', 'alpha'); $filter_category_customer = GETPOST('filter_category_customer', 'alpha'); $filter_category_supplier = GETPOST('filter_category_supplier', 'alpha'); + $filter_lang = GETPOST('filter_lang', 'alpha'); $cibles = array(); @@ -391,6 +399,7 @@ class mailing_contacts1 extends MailingTargets if ($filter_category_customer <> 'all') $sql .= " AND c2.label = '".$this->db->escape($filter_category_customer)."'"; if ($filter_category_supplier <> 'all') $sql .= " AND c3s.fk_categorie = c3.rowid AND c3s.fk_soc = sp.fk_soc"; if ($filter_category_supplier <> 'all') $sql .= " AND c3.label = '".$this->db->escape($filter_category_supplier)."'"; + if ($filter_lang <> '') $sql .= " AND sp.default_lang = '".$this->db->escape($filter_lang)."'"; // Filter on nature $key = $filter; { @@ -404,7 +413,7 @@ class mailing_contacts1 extends MailingTargets $key = $filter_jobposition; if (!empty($key) && $key != 'all') $sql .= " AND sp.poste ='".$this->db->escape($key)."'"; $sql .= " ORDER BY sp.email"; - //print "wwwwwwx".$sql; + // print "wwwwwwx".$sql; // Stocke destinataires dans cibles $result = $this->db->query($sql); From 72ac1fdfd2e4eb69a7b53c5a8a2060e687e9f871 Mon Sep 17 00:00:00 2001 From: Eric Seigne Date: Fri, 22 Apr 2022 15:05:38 +0200 Subject: [PATCH 173/473] fix #20690: add lang filter for companies --- .../modules/mailings/thirdparties.modules.php | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/mailings/thirdparties.modules.php b/htdocs/core/modules/mailings/thirdparties.modules.php index 05e9f4f12c4..9dc9e716cf3 100644 --- a/htdocs/core/modules/mailings/thirdparties.modules.php +++ b/htdocs/core/modules/mailings/thirdparties.modules.php @@ -79,6 +79,11 @@ class mailing_thirdparties extends MailingTargets $sql .= " WHERE s.email <> ''"; $sql .= " AND s.entity IN (".getEntity('societe').")"; $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + + if (GETPOST('default_lang','alpha')) + { + $sql .= " AND s.default_lang LIKE '".GETPOST('default_lang','alpha')."%'"; + } } else { @@ -126,6 +131,13 @@ class mailing_thirdparties extends MailingTargets $addDescription .= $langs->trans("Disabled"); } } + if (GETPOST('default_lang','alpha')) + { + $addFilter .= " AND s.default_lang LIKE '".GETPOST('default_lang','alpha')."%'"; + $addDescription = $langs->trans('DefaultLang')."="; + } + + $sql = "SELECT s.rowid as id, s.email as email, s.nom as name, null as fk_contact, null as firstname, c.label as label"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."categorie_societe as cs, ".MAIN_DB_PREFIX."categorie as c"; $sql .= " WHERE s.email <> ''"; @@ -147,7 +159,6 @@ class mailing_thirdparties extends MailingTargets $sql .= $addFilter; } $sql .= " ORDER BY email"; - // Stock recipients emails into targets table $result = $this->db->query($sql); if ($result) @@ -314,6 +325,14 @@ class mailing_thirdparties extends MailingTargets $s .= ''; $s .= ''; $s .= ''; + + + //Choose language + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($this->db); + $s .= $langs->trans("DefaultLang").': '; + $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); + return $s; } From 9fd3a4b2c9c99c56f46b8e9559372f142c33ad09 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 22 Apr 2022 13:30:43 +0000 Subject: [PATCH 174/473] Fixing style errors. --- htdocs/core/modules/mailings/thirdparties.modules.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/mailings/thirdparties.modules.php b/htdocs/core/modules/mailings/thirdparties.modules.php index 9dc9e716cf3..07b08e60d60 100644 --- a/htdocs/core/modules/mailings/thirdparties.modules.php +++ b/htdocs/core/modules/mailings/thirdparties.modules.php @@ -80,9 +80,9 @@ class mailing_thirdparties extends MailingTargets $sql .= " AND s.entity IN (".getEntity('societe').")"; $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; - if (GETPOST('default_lang','alpha')) + if (GETPOST('default_lang', 'alpha')) { - $sql .= " AND s.default_lang LIKE '".GETPOST('default_lang','alpha')."%'"; + $sql .= " AND s.default_lang LIKE '".GETPOST('default_lang', 'alpha')."%'"; } } else @@ -131,9 +131,9 @@ class mailing_thirdparties extends MailingTargets $addDescription .= $langs->trans("Disabled"); } } - if (GETPOST('default_lang','alpha')) + if (GETPOST('default_lang', 'alpha')) { - $addFilter .= " AND s.default_lang LIKE '".GETPOST('default_lang','alpha')."%'"; + $addFilter .= " AND s.default_lang LIKE '".GETPOST('default_lang', 'alpha')."%'"; $addDescription = $langs->trans('DefaultLang')."="; } From 5eb74772d619d895250f690506ce77dc7cece1d6 Mon Sep 17 00:00:00 2001 From: Nicolas SILOBRE <45969285+ns-info90@users.noreply.github.com> Date: Sat, 23 Apr 2022 03:41:17 +0200 Subject: [PATCH 175/473] Update pdf_rouget.modules.php Correction of units in the total weight --- htdocs/core/modules/expedition/doc/pdf_rouget.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php index 211231b9812..94e048382dc 100644 --- a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php @@ -212,7 +212,7 @@ class pdf_rouget extends ModelePdfExpedition } // Load traductions files required by page - $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies", "propal", "deliveries", "sendings", "productbatch")); + $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies", "propal", "deliveries", "sendings", "productbatch", "other")); $nblines = count($object->lines); From 16c607f4d8c0d826c4a7436599f028428e890393 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Apr 2022 18:39:26 +0200 Subject: [PATCH 176/473] Fix responsive --- htdocs/compta/localtax/card.php | 22 ++++++++++++++-------- htdocs/compta/localtax/list.php | 5 ++++- htdocs/compta/paiement_vat.php | 19 +++++++++++-------- htdocs/compta/tva/card.php | 11 ++++++----- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/htdocs/compta/localtax/card.php b/htdocs/compta/localtax/card.php index 35c6aa399fe..45cb1f03bb8 100644 --- a/htdocs/compta/localtax/card.php +++ b/htdocs/compta/localtax/card.php @@ -32,8 +32,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/vat.lib.php'; $langs->loadLangs(array('compta', 'banks', 'bills')); $id = GETPOST("id", 'int'); -$action = GETPOST("action", "alpha"); -$cancel = GETPOST('cancel'); +$action = GETPOST("action", "aZ09"); +$cancel = GETPOST('cancel', 'aZ09'); $refund = GETPOST("refund", "int"); if (empty($refund)) { @@ -143,7 +143,7 @@ $form = new Form($db); $title = $langs->trans("LT".$object->ltt)." - ".$langs->trans("Card"); $help_url = ''; -llxHeader("", $title, $helpurl); +llxHeader('', $title, $helpurl); if ($action == 'create') { print load_fiche_titre($langs->transcountry($lttype == 2 ? "newLT2Payment" : "newLT1Payment", $mysoc->country_code)); @@ -157,11 +157,13 @@ if ($action == 'create') { print ''; + // Date of payment print ""; print ''; + // End date of period print ''; @@ -173,20 +175,24 @@ if ($action == 'create') { print ''; if (!empty($conf->banque->enabled)) { - print ''; - + // Type payment print '\n"; print ""; + + // Bank account + print ''; // Number print ''."\n"; } + // Other attributes $parameters = array(); $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook diff --git a/htdocs/compta/localtax/list.php b/htdocs/compta/localtax/list.php index 6590e250832..6f6fc303262 100644 --- a/htdocs/compta/localtax/list.php +++ b/htdocs/compta/localtax/list.php @@ -63,6 +63,7 @@ if ($result) { $i = 0; $total = 0; + print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table print '
'.$langs->trans("DatePayment").''; print $form->selectDate($datep, "datep", '', '', '', 'add', 1, 1); print '
'.$form->textwithpicto($langs->trans("PeriodEndDate"), $langs->trans("LastDayTaxIsRelatedTo")).''; print $form->selectDate($datev, "datev", '', '', '', 'add', 1, 1); print '
'.$langs->trans("Amount").'
'.$langs->trans("Account").''; - $form->select_comptes(GETPOST("accountid", "int"), "accountid", 0, "courant=1", 2); // Affiche liste des comptes courant - print '
'.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype"); + $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); print "
'.$langs->trans("Account").''; + print img_picto('', 'bank_account', 'pictofixedwidth'); + $form->select_comptes(GETPOST("accountid", "int"), "accountid", 0, "courant=1", 2, '', 0, 'maxwidth500 widthcentpercentminusx'); // Affiche liste des comptes courant + print '
'.$langs->trans('Numero'); print ' ('.$langs->trans("ChequeOrTransferNumber").')'; print '
'; print ''; print ''; @@ -85,7 +86,7 @@ if ($result) { print '\n"; $total = $total + $obj->amount; - print ""; + print ''; print "\n"; $i++; @@ -94,6 +95,8 @@ if ($result) { print ''; print "
'.$langs->trans("Ref").''.dol_print_date($db->jdate($obj->datep), 'day')."".price($obj->amount)."'.price($obj->amount).'
'.price($total).'
"; + print ''; + $db->free($result); } else { dol_print_error($db); diff --git a/htdocs/compta/paiement_vat.php b/htdocs/compta/paiement_vat.php index ce224735927..2f7b775096d 100644 --- a/htdocs/compta/paiement_vat.php +++ b/htdocs/compta/paiement_vat.php @@ -207,14 +207,15 @@ if ($action == 'create') { print ''; print ''.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOSTISSET("paiementtype") ? GETPOST("paiementtype", "int") : $tva->paiementtype, "paiementtype"); + $form->select_types_paiements(GETPOSTISSET("paiementtype") ? GETPOST("paiementtype", "int") : $tva->paiementtype, "paiementtype", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); print "\n"; print ''; print ''; print ''.$langs->trans('AccountToDebit').''; print ''; - $form->select_comptes(GETPOST("accountid") ? GETPOST("accountid", "int") : $tva->accountid, "accountid", 0, '', 1); // Show opend bank account list + print img_picto('', 'bank_account', 'pictofixedwidth'); + $form->select_comptes(GETPOST("accountid", "int") ? GETPOST("accountid", "int") : $tva->accountid, "accountid", 0, '', 1, '', 0, 'maxwidth500 widthcentpercentminusx'); // Show opend bank account list print ''; // Number @@ -225,7 +226,7 @@ if ($action == 'create') { print ''; print ''.$langs->trans("Comments").''; - print ''; + print ''; print ''; print ''; @@ -238,6 +239,7 @@ if ($action == 'create') { $num = 1; $i = 0; + print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table print ''; print ''; //print ''; @@ -259,14 +261,14 @@ if ($action == 'create') { if ($objp->datev > 0) { print ''."\n"; } else { - print "\n"; + print ''."\n"; } - print '"; + print '"; - print '"; + print '"; - print '"; + print '"; print '
'.$langs->trans("SocialContribution").''.dol_print_date($objp->datev, 'day').'!!!!!!'.price($objp->amount)."'.price($objp->amount)."'.price($sumpaid)."'.price($sumpaid)."'.price($objp->amount - $sumpaid)."'.price($objp->amount - $sumpaid)."'; @@ -279,7 +281,7 @@ if ($action == 'create') { } */ $remaintopay = $objp->amount - $sumpaid; print ''; - print ''; + print ''; } else { print '-'; } @@ -303,6 +305,7 @@ if ($action == 'create') { } print "
"; + print '
'; // Bouton Save payment print '
'.$langs->trans("ClosePaidVATAutomatically"); diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index 317838009c7..3ffb405f8ad 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -460,7 +460,7 @@ if ($action == 'create') { print '
'; print ''; - //print "
\n"; + print "\n"; // Label if ($refund == 1) { @@ -468,7 +468,7 @@ if ($action == 'create') { } else { $label = $langs->trans("VATPayment"); } - print ''.$langs->trans("Label").''; + print ''.$langs->trans("Label").''; print ''.$form->textwithpicto($langs->trans("PeriodEndDate"), $langs->trans("LastDayTaxIsRelatedTo")).''; print $form->selectDate((GETPOST("datevmonth", 'int') ? $datev : -1), "datev", '', '', '', 'add', 1, 1); @@ -490,14 +490,15 @@ if ($action == 'create') { // Type payment print ''.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOST("type_payment"), "type_payment"); + $form->select_types_paiements(GETPOST("type_payment", 'int'), "type_payment", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); print "\n"; print ""; if (!empty($conf->banque->enabled)) { + // Bank account print ''.$langs->trans("BankAccount").''; print img_picto('', 'bank_account', 'pictofixedwidth'); - $form->select_comptes(GETPOST("accountid", 'int'), "accountid", 0, "courant=1", 1); // List of bank account available + $form->select_comptes(GETPOST("accountid", 'int'), "accountid", 0, "courant=1", 1, '', 0, 'maxwidth500 widthcentpercentminusx'); // List of bank account available print ''; } @@ -509,7 +510,7 @@ if ($action == 'create') { // Comments print ''; print ''.$langs->trans("Comments").''; - print ''; + print ''; print ''; // Other attributes From 97328f732e1ee3841b28c9d02a8745926f6393e3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Apr 2022 23:02:53 +0200 Subject: [PATCH 177/473] Fix error managemnt when getting RSS. --- htdocs/core/class/rssparser.class.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/rssparser.class.php b/htdocs/core/class/rssparser.class.php index c3c434d1aed..2048a80bae6 100644 --- a/htdocs/core/class/rssparser.class.php +++ b/htdocs/core/class/rssparser.class.php @@ -227,11 +227,16 @@ class RssParser } else { try { $result = getURLContent($this->_urlRSS, 'GET', '', 1, array(), array('http', 'https'), 0); + if (!empty($result['content'])) { $str = $result['content']; + } elseif (!empty($result['curl_error_msg'])){ + $this->error = 'Error retrieving URL '.$this->_urlRSS.' - '.$result['curl_error_msg']; + return -1; } } catch (Exception $e) { - print 'Error retrieving URL '.$this->_urlRSS.' - '.$e->getMessage(); + $this->error = 'Error retrieving URL '.$this->_urlRSS.' - '.$e->getMessage(); + return -2; } } @@ -248,7 +253,8 @@ class RssParser } $xmlparser = xml_parser_create(''); - if (!is_resource($xmlparser)) { + + if (!is_resource($xmlparser) && !is_object($xmlparser)) { $this->error = "ErrorFailedToCreateParser"; return -1; } @@ -256,10 +262,11 @@ class RssParser xml_set_object($xmlparser, $this); xml_set_element_handler($xmlparser, 'feed_start_element', 'feed_end_element'); xml_set_character_data_handler($xmlparser, 'feed_cdata'); + $status = xml_parse($xmlparser, $str); xml_parser_free($xmlparser); $rss = $this; - //var_dump($rss->_format);exit; + //var_dump($status.' '.$rss->_format);exit; } } From 8bb9cc83ebbdddc10ab9e898be9462bb3a748f8a Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 09:30:05 +0200 Subject: [PATCH 178/473] Fix migration warning. --- htdocs/core/extrafieldsinimport.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/extrafieldsinimport.inc.php b/htdocs/core/extrafieldsinimport.inc.php index 4845d9a6d44..395b67520d1 100644 --- a/htdocs/core/extrafieldsinimport.inc.php +++ b/htdocs/core/extrafieldsinimport.inc.php @@ -11,7 +11,7 @@ if (empty($keyforselect) || empty($keyforelement) || empty($keyforaliasextra)) { } // Add extra fields -$sql = "SELECT name, label, type, param, fieldcomputed, fielddefault FROM ".MAIN_DB_PREFIX."extrafields"; +$sql = "SELECT name, label, type, param, fieldcomputed, fielddefault, fieldrequired FROM ".MAIN_DB_PREFIX."extrafields"; $sql .= " WHERE elementtype = '".$this->db->escape($keyforselect)."' AND type <> 'separate' AND entity IN (0, ".((int) $conf->entity).') ORDER BY pos ASC'; //print $sql; $resql = $this->db->query($sql); From 8a2cc52b5c5ca3cd7d5aed43fe77eed4182ef27c Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 25 Apr 2022 10:14:30 +0200 Subject: [PATCH 179/473] FIX wrong website data root with multicompany --- htdocs/admin/website.php | 6 +++--- htdocs/core/class/html.formwebsite.class.php | 2 +- htdocs/core/filemanagerdol/connectors/php/config.php | 2 +- htdocs/core/lib/website.lib.php | 4 ++-- htdocs/public/website/index.php | 4 ++-- htdocs/public/website/styles.css.php | 2 +- htdocs/website/class/website.class.php | 8 +++++--- htdocs/website/class/websitepage.class.php | 2 +- htdocs/website/index.php | 10 +++++----- 9 files changed, 21 insertions(+), 19 deletions(-) diff --git a/htdocs/admin/website.php b/htdocs/admin/website.php index d1a24ff072c..17858b9991c 100644 --- a/htdocs/admin/website.php +++ b/htdocs/admin/website.php @@ -113,7 +113,7 @@ $tabcond[1] = (!empty($conf->website->enabled)); // List of help for fields $tabhelp = array(); -$tabhelp[1] = array('ref'=>$langs->trans("EnterAnyCode"), 'virtualhost'=>$langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.'/website/websiteref')); +$tabhelp[1] = array('ref'=>$langs->trans("EnterAnyCode"), 'virtualhost'=>$langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/websiteref')); // List of check for fields (NOT USED YET) $tabfieldcheck = array(); @@ -271,8 +271,8 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($resql) { $newname = dol_sanitizeFileName(GETPOST('ref', 'aZ09')); if ($newname != $website->ref) { - $srcfile = DOL_DATA_ROOT.'/website/'.$website->ref; - $destfile = DOL_DATA_ROOT.'/website/'.$newname; + $srcfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$website->ref; + $destfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$newname; if (dol_is_dir($destfile)) { $error++; diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php index a4db07f95c0..5d553887777 100644 --- a/htdocs/core/class/html.formwebsite.class.php +++ b/htdocs/core/class/html.formwebsite.class.php @@ -173,7 +173,7 @@ class FormWebsite $langs->load("admin"); - $listofsamples = dol_dir_list(DOL_DOCUMENT_ROOT.'/website/samples', 'files', 0, '^page-sample-.*\.html$'); + $listofsamples = dol_dir_list(DOL_DOCUMENT_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/samples', 'files', 0, '^page-sample-.*\.html$'); $arrayofsamples = array(); $arrayofsamples['empty'] = 'EmptyPage'; // Always this one first diff --git a/htdocs/core/filemanagerdol/connectors/php/config.php b/htdocs/core/filemanagerdol/connectors/php/config.php index 73c222841cc..c2d7478e36e 100644 --- a/htdocs/core/filemanagerdol/connectors/php/config.php +++ b/htdocs/core/filemanagerdol/connectors/php/config.php @@ -50,7 +50,7 @@ $Config['Enabled'] = true; $extEntity = (empty($entity) ? 1 : $entity); // For multicompany with external access $Config['UserFilesPath'] = DOL_URL_ROOT.'/viewimage.php?modulepart=medias'.(empty($website) ? '' : '_'.$website).'&entity='.$extEntity.'&file='; -$Config['UserFilesAbsolutePathRelative'] = (empty($website) ? ((!empty($entity) ? '/'.$entity : '').'/medias/') : ('/website/'.$website)); +$Config['UserFilesAbsolutePathRelative'] = (!empty($entity) ? '/'.$entity : '').(empty($website) ? '/medias/' : ('/website/'.$website)); // Fill the following value it you prefer to specify the absolute path for the diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index ca907ae6f1c..eeb68458252 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -495,7 +495,7 @@ function includeContainer($containerref) $containerref .= '.php'; } - $fullpathfile = DOL_DATA_ROOT.'/website/'.$websitekey.'/'.$containerref; + $fullpathfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity.'/' : '').'/website/'.$websitekey.'/'.$containerref; if (empty($includehtmlcontentopened)) { $includehtmlcontentopened = 0; @@ -984,7 +984,7 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so if (!$error && (empty($max) || ($found < $max)) && (preg_match('/sitefiles/', $algo))) { global $dolibarr_main_data_root; - $pathofwebsite = $dolibarr_main_data_root.'/website/'.$website->ref; + $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity.'/' : '').'/website/'.$website->ref; $filehtmlheader = $pathofwebsite.'/htmlheader.html'; $filecss = $pathofwebsite.'/styles.css.php'; $filejs = $pathofwebsite.'/javascript.js.php'; diff --git a/htdocs/public/website/index.php b/htdocs/public/website/index.php index d72fedefa7e..4b0342693d8 100644 --- a/htdocs/public/website/index.php +++ b/htdocs/public/website/index.php @@ -169,9 +169,9 @@ if ($pageid == 'css') { // No more used ? //if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate'); //else header('Cache-Control: no-cache'); - $original_file = $dolibarr_main_data_root.'/website/'.$websitekey.'/styles.css.php'; + $original_file = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey.'/styles.css.php'; } else { - $original_file = $dolibarr_main_data_root.'/website/'.$websitekey.'/page'.$pageid.'.tpl.php'; + $original_file = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey.'/page'.$pageid.'.tpl.php'; } // Find the subdirectory name as the reference diff --git a/htdocs/public/website/styles.css.php b/htdocs/public/website/styles.css.php index a0002b5380b..73cbed73dbd 100644 --- a/htdocs/public/website/styles.css.php +++ b/htdocs/public/website/styles.css.php @@ -122,7 +122,7 @@ if (empty($pageid)) // Security: Delete string ../ into $original_file global $dolibarr_main_data_root; -$original_file = $dolibarr_main_data_root.'/website/'.$website.'/styles.css.php'; +$original_file = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$website.'/styles.css.php'; // Find the subdirectory name as the reference $refname = basename(dirname($original_file)."/"); diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 80a48048151..8dfaf284ea5 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -587,6 +587,8 @@ class Website extends CommonObject */ public function delete(User $user, $notrigger = false) { + global $conf; + dol_syslog(__METHOD__, LOG_DEBUG); $error = 0; @@ -618,7 +620,7 @@ class Website extends CommonObject } if (!$error && !empty($this->ref)) { - $pathofwebsite = DOL_DATA_ROOT.'/website/'.$this->ref; + $pathofwebsite = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$this->ref; dol_delete_dir_recursive($pathofwebsite); } @@ -678,8 +680,8 @@ class Website extends CommonObject $oldidforhome = $object->fk_default_home; $oldref = $object->ref; - $pathofwebsiteold = $dolibarr_main_data_root.'/website/'.dol_sanitizeFileName($oldref); - $pathofwebsitenew = $dolibarr_main_data_root.'/website/'.dol_sanitizeFileName($newref); + $pathofwebsiteold = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.dol_sanitizeFileName($oldref); + $pathofwebsitenew = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.dol_sanitizeFileName($newref); dol_delete_dir_recursive($pathofwebsitenew); $fileindex = $pathofwebsitenew.'/index.php'; diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 0126f8a4dc4..6b65df983ca 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -642,7 +642,7 @@ class WebsitePage extends CommonObject if ($result > 0) { global $dolibarr_main_data_root; - $pathofwebsite = $dolibarr_main_data_root.'/website/'.$websiteobj->ref; + $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websiteobj->ref; $filealias = $pathofwebsite.'/'.$this->pageurl.'.php'; $filetpl = $pathofwebsite.'/page'.$this->id.'.tpl.php'; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 8ac4d612264..346a6715647 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -226,7 +226,7 @@ if (empty($pageid) && empty($pageref) && $object->id > 0 && $action != 'createco global $dolibarr_main_data_root; -$pathofwebsite = $dolibarr_main_data_root.'/website/'.$websitekey; +$pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey; $filehtmlheader = $pathofwebsite.'/htmlheader.html'; $filecss = $pathofwebsite.'/styles.css.php'; $filejs = $pathofwebsite.'/javascript.js.php'; @@ -1924,7 +1924,7 @@ if ($usercanedit && (($action == 'updatesource' || $action == 'updatecontent' || $tmpwebsite = new Website($db); if ($newwebsiteid > 0 && $newwebsiteid != $object->id) { $tmpwebsite->fetch($newwebsiteid); - $pathofwebsitenew = $dolibarr_main_data_root.'/website/'.$tmpwebsite->ref; + $pathofwebsitenew = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$tmpwebsite->ref; } else { $tmpwebsite = $object; } @@ -2573,7 +2573,7 @@ if (!GETPOST('hide_websitemenu')) { if ($websitekey) { $virtualurl = ''; - $dataroot = DOL_DATA_ROOT.'/website/'.$websitekey; + $dataroot = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey; if (!empty($object->virtualhost)) { $virtualurl = $object->virtualhost; } @@ -3342,7 +3342,7 @@ if ($action == 'editcss') { // VirtualHost print ''; - $htmltext = $langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.'/website/{s1}'.$websitekey.'{s2}'); + $htmltext = $langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/{s1}'.$websitekey.'{s2}'); $htmltext = str_replace(array('{s1}', '{s2}'), array('', ''), $htmltext); $htmltext .= '
'; $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT); @@ -3528,7 +3528,7 @@ if ($action == 'createsite') { print ''; $htmltext = $langs->trans("SetHereVirtualHost", '{s1}'); - $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website/websiteref', $htmltext); + $htmltext = str_replace('{s1}', DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/websiteref', $htmltext); $htmltext .= '
'; $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT); $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}'); From 7e7ae863c7c9afa4512bcb4c760bee7351b4a021 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 25 Apr 2022 10:19:52 +0200 Subject: [PATCH 180/473] FIX syntax error --- htdocs/core/class/html.formwebsite.class.php | 2 +- htdocs/core/lib/website.lib.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php index 5d553887777..a4db07f95c0 100644 --- a/htdocs/core/class/html.formwebsite.class.php +++ b/htdocs/core/class/html.formwebsite.class.php @@ -173,7 +173,7 @@ class FormWebsite $langs->load("admin"); - $listofsamples = dol_dir_list(DOL_DOCUMENT_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/samples', 'files', 0, '^page-sample-.*\.html$'); + $listofsamples = dol_dir_list(DOL_DOCUMENT_ROOT.'/website/samples', 'files', 0, '^page-sample-.*\.html$'); $arrayofsamples = array(); $arrayofsamples['empty'] = 'EmptyPage'; // Always this one first diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index eeb68458252..87608d81118 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -495,7 +495,7 @@ function includeContainer($containerref) $containerref .= '.php'; } - $fullpathfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity.'/' : '').'/website/'.$websitekey.'/'.$containerref; + $fullpathfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey.'/'.$containerref; if (empty($includehtmlcontentopened)) { $includehtmlcontentopened = 0; @@ -984,7 +984,7 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so if (!$error && (empty($max) || ($found < $max)) && (preg_match('/sitefiles/', $algo))) { global $dolibarr_main_data_root; - $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity.'/' : '').'/website/'.$website->ref; + $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$website->ref; $filehtmlheader = $pathofwebsite.'/htmlheader.html'; $filecss = $pathofwebsite.'/styles.css.php'; $filejs = $pathofwebsite.'/javascript.js.php'; From e6ce81bf8be6adbde09c4c8e67e8ecea453cd117 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 11:20:00 +0200 Subject: [PATCH 181/473] Move confirm_createbills mass action to order list --- htdocs/commande/list.php | 342 +++++++++++++++++++++++ htdocs/core/actions_massactions.inc.php | 343 ------------------------ 2 files changed, 342 insertions(+), 343 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 52071b672fe..4859412f692 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -302,6 +302,348 @@ if (empty($reshook)) { $uploaddir = $conf->commande->multidir_output[$conf->entity]; $triggersendname = 'ORDER_SENTBYMAIL'; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if ($massaction == 'confirm_createbills') { // Create bills from orders. + $orders = GETPOST('toselect', 'array'); + $createbills_onebythird = GETPOST('createbills_onebythird', 'int'); + $validate_invoices = GETPOST('validate_invoices', 'int'); + + $errors = array(); + + $TFact = array(); + $TFactThird = array(); + $TFactThirdNbLines = array(); + + $nb_bills_created = 0; + $lastid= 0; + $lastref = ''; + + $db->begin(); + + foreach ($orders as $id_order) { + $cmd = new Commande($db); + if ($cmd->fetch($id_order) <= 0) { + continue; + } + $cmd->fetch_thirdparty(); + + $objecttmp = new Facture($db); + if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) { + // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it. + $objecttmp = $TFactThird[$cmd->socid]; + } else { + // If we want one invoice per order or if there is no first invoice yet for this thirdparty. + $objecttmp->socid = $cmd->socid; + $objecttmp->thirdparty = $cmd->thirdparty; + + $objecttmp->type = $objecttmp::TYPE_STANDARD; + $objecttmp->cond_reglement_id = !empty($cmd->cond_reglement_id) ? $cmd->cond_reglement_id : $cmd->thirdparty->cond_reglement_id; + $objecttmp->mode_reglement_id = !empty($cmd->mode_reglement_id) ? $cmd->mode_reglement_id : $cmd->thirdparty->mode_reglement_id; + + $objecttmp->fk_project = $cmd->fk_project; + $objecttmp->multicurrency_code = $cmd->multicurrency_code; + if (empty($createbills_onebythird)) { + $objecttmp->ref_client = $cmd->ref_client; + } + + $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + if (empty($datefacture)) { + $datefacture = dol_now(); + } + + $objecttmp->date = $datefacture; + $objecttmp->origin = 'commande'; + $objecttmp->origin_id = $id_order; + + $objecttmp->array_options = $cmd->array_options; // Copy extrafields + + $res = $objecttmp->create($user); + + if ($res > 0) { + $nb_bills_created++; + $lastref = $objecttmp->ref; + $lastid = $objecttmp->id; + + $TFactThird[$cmd->socid] = $objecttmp; + $TFactThirdNbLines[$cmd->socid] = 0; //init nblines to have lines ordered by expedition and rang + } else { + $langs->load("errors"); + $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->error); + $error++; + } + } + + if ($objecttmp->id > 0) { + $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order); + + if ($res == 0) { + $errors[] = $objecttmp->error; + $error++; + } + + if (!$error) { + $lines = $cmd->lines; + if (empty($lines) && method_exists($cmd, 'fetch_lines')) { + $cmd->fetch_lines(); + $lines = $cmd->lines; + } + + $fk_parent_line = 0; + $num = count($lines); + + for ($i = 0; $i < $num; $i++) { + $desc = ($lines[$i]->desc ? $lines[$i]->desc : ''); + // If we build one invoice for several orders, we must put the ref of order on the invoice line + if (!empty($createbills_onebythird)) { + $desc = dol_concatdesc($desc, $langs->trans("Order").' '.$cmd->ref.' - '.dol_print_date($cmd->date, 'day')); + } + + if ($lines[$i]->subprice < 0) { + // Negative line, we create a discount line + $discount = new DiscountAbsolute($db); + $discount->fk_soc = $objecttmp->socid; + $discount->amount_ht = abs($lines[$i]->total_ht); + $discount->amount_tva = abs($lines[$i]->total_tva); + $discount->amount_ttc = abs($lines[$i]->total_ttc); + $discount->tva_tx = $lines[$i]->tva_tx; + $discount->fk_user = $user->id; + $discount->description = $desc; + $discountid = $discount->create($user); + if ($discountid > 0) { + $result = $objecttmp->insert_discount($discountid); + //$result=$discount->link_to_invoice($lineid,$id); + } else { + setEventMessages($discount->error, $discount->errors, 'errors'); + $error++; + break; + } + } else { + // Positive line + $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); + // Date start + $date_start = false; + if ($lines[$i]->date_debut_prevue) { + $date_start = $lines[$i]->date_debut_prevue; + } + if ($lines[$i]->date_debut_reel) { + $date_start = $lines[$i]->date_debut_reel; + } + if ($lines[$i]->date_start) { + $date_start = $lines[$i]->date_start; + } + //Date end + $date_end = false; + if ($lines[$i]->date_fin_prevue) { + $date_end = $lines[$i]->date_fin_prevue; + } + if ($lines[$i]->date_fin_reel) { + $date_end = $lines[$i]->date_fin_reel; + } + if ($lines[$i]->date_end) { + $date_end = $lines[$i]->date_end; + } + // Reset fk_parent_line for no child products and special product + if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { + $fk_parent_line = 0; + } + + // Extrafields + if (method_exists($lines[$i], 'fetch_optionals')) { + $lines[$i]->fetch_optionals(); + $array_options = $lines[$i]->array_options; + } + + $objecttmp->context['createfromclone']; + + $rang = $lines[$i]->rang; + //there may already be rows from previous orders + if (!empty($createbills_onebythird)) + $rang = $TFactThirdNbLines[$cmd->socid]; + + $result = $objecttmp->addline( + $desc, + $lines[$i]->subprice, + $lines[$i]->qty, + $lines[$i]->tva_tx, + $lines[$i]->localtax1_tx, + $lines[$i]->localtax2_tx, + $lines[$i]->fk_product, + $lines[$i]->remise_percent, + $date_start, + $date_end, + 0, + $lines[$i]->info_bits, + $lines[$i]->fk_remise_except, + 'HT', + 0, + $product_type, + $rang, + $lines[$i]->special_code, + $objecttmp->origin, + $lines[$i]->rowid, + $fk_parent_line, + $lines[$i]->fk_fournprice, + $lines[$i]->pa_ht, + $lines[$i]->label, + $array_options, + 100, + 0, + $lines[$i]->fk_unit + ); + if ($result > 0) { + $lineid = $result; + if (!empty($createbills_onebythird)) //increment rang to keep order + $TFactThirdNbLines[$rcp->socid]++; + } else { + $lineid = 0; + $error++; + break; + } + // Defined the new fk_parent_line + if ($result > 0 && $lines[$i]->product_type == 9) { + $fk_parent_line = $result; + } + } + } + } + } + + //$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module. + + if (!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) { + $TFactThird[$cmd->socid] = $objecttmp; + } else { + $TFact[$objecttmp->id] = $objecttmp; + } + } + + // Build doc with all invoices + $TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird; + $toselect = array(); + + if (!$error && $validate_invoices) { + $massaction = $action = 'builddoc'; + + foreach ($TAllFact as &$objecttmp) { + $result = $objecttmp->validate($user); + if ($result <= 0) { + $error++; + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + break; + } + + $id = $objecttmp->id; // For builddoc action + + // Builddoc + $donotredirect = 1; + $upload_dir = $conf->facture->dir_output; + $permissiontoadd = $user->rights->facture->creer; + + // Call action to build doc + $savobject = $object; + $object = $objecttmp; + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + $object = $savobject; + } + + $massaction = $action = 'confirm_createbills'; + } + + if (!$error) { + $db->commit(); + + if ($nb_bills_created == 1) { + $texttoshow = $langs->trans('BillXCreated', '{s1}'); + $texttoshow = str_replace('{s1}', ''.$lastref.'', $texttoshow); + setEventMessages($texttoshow, null, 'mesgs'); + } else { + setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs'); + } + + // Make a redirect to avoid to bill twice if we make a refresh or back + $param = ''; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); + } + if ($sall) { + $param .= '&sall='.urlencode($sall); + } + if ($socid > 0) { + $param .= '&socid='.urlencode($socid); + } + if ($search_status != '') { + $param .= '&search_status='.urlencode($search_status); + } + if ($search_orderday) { + $param .= '&search_orderday='.urlencode($search_orderday); + } + if ($search_ordermonth) { + $param .= '&search_ordermonth='.urlencode($search_ordermonth); + } + if ($search_orderyear) { + $param .= '&search_orderyear='.urlencode($search_orderyear); + } + if ($search_deliveryday) { + $param .= '&search_deliveryday='.urlencode($search_deliveryday); + } + if ($search_deliverymonth) { + $param .= '&search_deliverymonth='.urlencode($search_deliverymonth); + } + if ($search_deliveryyear) { + $param .= '&search_deliveryyear='.urlencode($search_deliveryyear); + } + if ($search_ref) { + $param .= '&search_ref='.urlencode($search_ref); + } + if ($search_company) { + $param .= '&search_company='.urlencode($search_company); + } + if ($search_ref_customer) { + $param .= '&search_ref_customer='.urlencode($search_ref_customer); + } + if ($search_user > 0) { + $param .= '&search_user='.urlencode($search_user); + } + if ($search_sale > 0) { + $param .= '&search_sale='.urlencode($search_sale); + } + if ($search_total_ht != '') { + $param .= '&search_total_ht='.urlencode($search_total_ht); + } + if ($search_total_vat != '') { + $param .= '&search_total_vat='.urlencode($search_total_vat); + } + if ($search_total_ttc != '') { + $param .= '&search_total_ttc='.urlencode($search_total_ttc); + } + if ($search_project_ref >= 0) { + $param .= "&search_project_ref=".urlencode($search_project_ref); + } + if ($show_files) { + $param .= '&show_files='.urlencode($show_files); + } + if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); + } + if ($billed != '') { + $param .= '&billed='.urlencode($billed); + } + + header("Location: ".$_SERVER['PHP_SELF'].'?'.$param); + exit; + } else { + $db->rollback(); + + $action = 'create'; + $_GET["origin"] = $_POST["origin"]; + $_GET["originid"] = $_POST["originid"]; + setEventMessages("Error", null, 'errors'); + $error++; + } + } } if ($action == 'validate' && $permissiontoadd) { if (GETPOST('confirm') == 'yes') { diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5ec011f5017..c0a35947b9d 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -625,349 +625,6 @@ if (!$error && $massaction == 'confirm_presend') { } } -// TODO Move this action into commande/list.php if called only by this page. -if ($massaction == 'confirm_createbills') { // Create bills from orders. - $orders = GETPOST('toselect', 'array'); - $createbills_onebythird = GETPOST('createbills_onebythird', 'int'); - $validate_invoices = GETPOST('validate_invoices', 'int'); - - $errors = array(); - - $TFact = array(); - $TFactThird = array(); - $TFactThirdNbLines = array(); - - $nb_bills_created = 0; - $lastid= 0; - $lastref = ''; - - $db->begin(); - - foreach ($orders as $id_order) { - $cmd = new Commande($db); - if ($cmd->fetch($id_order) <= 0) { - continue; - } - $cmd->fetch_thirdparty(); - - $objecttmp = new Facture($db); - if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) { - // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it. - $objecttmp = $TFactThird[$cmd->socid]; - } else { - // If we want one invoice per order or if there is no first invoice yet for this thirdparty. - $objecttmp->socid = $cmd->socid; - $objecttmp->thirdparty = $cmd->thirdparty; - - $objecttmp->type = $objecttmp::TYPE_STANDARD; - $objecttmp->cond_reglement_id = !empty($cmd->cond_reglement_id) ? $cmd->cond_reglement_id : $cmd->thirdparty->cond_reglement_id; - $objecttmp->mode_reglement_id = !empty($cmd->mode_reglement_id) ? $cmd->mode_reglement_id : $cmd->thirdparty->mode_reglement_id; - - $objecttmp->fk_project = $cmd->fk_project; - $objecttmp->multicurrency_code = $cmd->multicurrency_code; - if (empty($createbills_onebythird)) { - $objecttmp->ref_client = $cmd->ref_client; - } - - $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($datefacture)) { - $datefacture = dol_now(); - } - - $objecttmp->date = $datefacture; - $objecttmp->origin = 'commande'; - $objecttmp->origin_id = $id_order; - - $objecttmp->array_options = $cmd->array_options; // Copy extrafields - - $res = $objecttmp->create($user); - - if ($res > 0) { - $nb_bills_created++; - $lastref = $objecttmp->ref; - $lastid = $objecttmp->id; - - $TFactThird[$cmd->socid] = $objecttmp; - $TFactThirdNbLines[$cmd->socid] = 0; //init nblines to have lines ordered by expedition and rang - } else { - $langs->load("errors"); - $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->error); - $error++; - } - } - - if ($objecttmp->id > 0) { - $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order); - - if ($res == 0) { - $errors[] = $objecttmp->error; - $error++; - } - - if (!$error) { - $lines = $cmd->lines; - if (empty($lines) && method_exists($cmd, 'fetch_lines')) { - $cmd->fetch_lines(); - $lines = $cmd->lines; - } - - $fk_parent_line = 0; - $num = count($lines); - - for ($i = 0; $i < $num; $i++) { - $desc = ($lines[$i]->desc ? $lines[$i]->desc : ''); - // If we build one invoice for several orders, we must put the ref of order on the invoice line - if (!empty($createbills_onebythird)) { - $desc = dol_concatdesc($desc, $langs->trans("Order").' '.$cmd->ref.' - '.dol_print_date($cmd->date, 'day')); - } - - if ($lines[$i]->subprice < 0) { - // Negative line, we create a discount line - $discount = new DiscountAbsolute($db); - $discount->fk_soc = $objecttmp->socid; - $discount->amount_ht = abs($lines[$i]->total_ht); - $discount->amount_tva = abs($lines[$i]->total_tva); - $discount->amount_ttc = abs($lines[$i]->total_ttc); - $discount->tva_tx = $lines[$i]->tva_tx; - $discount->fk_user = $user->id; - $discount->description = $desc; - $discountid = $discount->create($user); - if ($discountid > 0) { - $result = $objecttmp->insert_discount($discountid); - //$result=$discount->link_to_invoice($lineid,$id); - } else { - setEventMessages($discount->error, $discount->errors, 'errors'); - $error++; - break; - } - } else { - // Positive line - $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); - // Date start - $date_start = false; - if ($lines[$i]->date_debut_prevue) { - $date_start = $lines[$i]->date_debut_prevue; - } - if ($lines[$i]->date_debut_reel) { - $date_start = $lines[$i]->date_debut_reel; - } - if ($lines[$i]->date_start) { - $date_start = $lines[$i]->date_start; - } - //Date end - $date_end = false; - if ($lines[$i]->date_fin_prevue) { - $date_end = $lines[$i]->date_fin_prevue; - } - if ($lines[$i]->date_fin_reel) { - $date_end = $lines[$i]->date_fin_reel; - } - if ($lines[$i]->date_end) { - $date_end = $lines[$i]->date_end; - } - // Reset fk_parent_line for no child products and special product - if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { - $fk_parent_line = 0; - } - - // Extrafields - if (method_exists($lines[$i], 'fetch_optionals')) { - $lines[$i]->fetch_optionals(); - $array_options = $lines[$i]->array_options; - } - - $objecttmp->context['createfromclone']; - - $rang = $lines[$i]->rang; - //there may already be rows from previous orders - if (!empty($createbills_onebythird)) - $rang = $TFactThirdNbLines[$cmd->socid]; - - $result = $objecttmp->addline( - $desc, - $lines[$i]->subprice, - $lines[$i]->qty, - $lines[$i]->tva_tx, - $lines[$i]->localtax1_tx, - $lines[$i]->localtax2_tx, - $lines[$i]->fk_product, - $lines[$i]->remise_percent, - $date_start, - $date_end, - 0, - $lines[$i]->info_bits, - $lines[$i]->fk_remise_except, - 'HT', - 0, - $product_type, - $rang, - $lines[$i]->special_code, - $objecttmp->origin, - $lines[$i]->rowid, - $fk_parent_line, - $lines[$i]->fk_fournprice, - $lines[$i]->pa_ht, - $lines[$i]->label, - $array_options, - 100, - 0, - $lines[$i]->fk_unit - ); - if ($result > 0) { - $lineid = $result; - if (!empty($createbills_onebythird)) //increment rang to keep order - $TFactThirdNbLines[$rcp->socid]++; - } else { - $lineid = 0; - $error++; - break; - } - // Defined the new fk_parent_line - if ($result > 0 && $lines[$i]->product_type == 9) { - $fk_parent_line = $result; - } - } - } - } - } - - //$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module. - - if (!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) { - $TFactThird[$cmd->socid] = $objecttmp; - } else { - $TFact[$objecttmp->id] = $objecttmp; - } - } - - // Build doc with all invoices - $TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird; - $toselect = array(); - - if (!$error && $validate_invoices) { - $massaction = $action = 'builddoc'; - - foreach ($TAllFact as &$objecttmp) { - $result = $objecttmp->validate($user); - if ($result <= 0) { - $error++; - setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); - break; - } - - $id = $objecttmp->id; // For builddoc action - - // Builddoc - $donotredirect = 1; - $upload_dir = $conf->facture->dir_output; - $permissiontoadd = $user->rights->facture->creer; - - // Call action to build doc - $savobject = $object; - $object = $objecttmp; - include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; - $object = $savobject; - } - - $massaction = $action = 'confirm_createbills'; - } - - if (!$error) { - $db->commit(); - - if ($nb_bills_created == 1) { - $texttoshow = $langs->trans('BillXCreated', '{s1}'); - $texttoshow = str_replace('{s1}', ''.$lastref.'', $texttoshow); - setEventMessages($texttoshow, null, 'mesgs'); - } else { - setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs'); - } - - // Make a redirect to avoid to bill twice if we make a refresh or back - $param = ''; - if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { - $param .= '&contextpage='.urlencode($contextpage); - } - if ($limit > 0 && $limit != $conf->liste_limit) { - $param .= '&limit='.urlencode($limit); - } - if ($sall) { - $param .= '&sall='.urlencode($sall); - } - if ($socid > 0) { - $param .= '&socid='.urlencode($socid); - } - if ($search_status != '') { - $param .= '&search_status='.urlencode($search_status); - } - if ($search_orderday) { - $param .= '&search_orderday='.urlencode($search_orderday); - } - if ($search_ordermonth) { - $param .= '&search_ordermonth='.urlencode($search_ordermonth); - } - if ($search_orderyear) { - $param .= '&search_orderyear='.urlencode($search_orderyear); - } - if ($search_deliveryday) { - $param .= '&search_deliveryday='.urlencode($search_deliveryday); - } - if ($search_deliverymonth) { - $param .= '&search_deliverymonth='.urlencode($search_deliverymonth); - } - if ($search_deliveryyear) { - $param .= '&search_deliveryyear='.urlencode($search_deliveryyear); - } - if ($search_ref) { - $param .= '&search_ref='.urlencode($search_ref); - } - if ($search_company) { - $param .= '&search_company='.urlencode($search_company); - } - if ($search_ref_customer) { - $param .= '&search_ref_customer='.urlencode($search_ref_customer); - } - if ($search_user > 0) { - $param .= '&search_user='.urlencode($search_user); - } - if ($search_sale > 0) { - $param .= '&search_sale='.urlencode($search_sale); - } - if ($search_total_ht != '') { - $param .= '&search_total_ht='.urlencode($search_total_ht); - } - if ($search_total_vat != '') { - $param .= '&search_total_vat='.urlencode($search_total_vat); - } - if ($search_total_ttc != '') { - $param .= '&search_total_ttc='.urlencode($search_total_ttc); - } - if ($search_project_ref >= 0) { - $param .= "&search_project_ref=".urlencode($search_project_ref); - } - if ($show_files) { - $param .= '&show_files='.urlencode($show_files); - } - if ($optioncss != '') { - $param .= '&optioncss='.urlencode($optioncss); - } - if ($billed != '') { - $param .= '&billed='.urlencode($billed); - } - - header("Location: ".$_SERVER['PHP_SELF'].'?'.$param); - exit; - } else { - $db->rollback(); - - $action = 'create'; - $_GET["origin"] = $_POST["origin"]; - $_GET["originid"] = $_POST["originid"]; - setEventMessages("Error", null, 'errors'); - $error++; - } -} - if (!$error && $massaction == 'cancelorders') { $db->begin(); From e9cfb9b69c17678e9eca50ddb19da5d10cce0fcb Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 11:24:09 +0200 Subject: [PATCH 182/473] Improve error handling confirm_billcreate --- htdocs/commande/list.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 4859412f692..38d79aa9698 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -368,7 +368,7 @@ if (empty($reshook)) { $TFactThirdNbLines[$cmd->socid] = 0; //init nblines to have lines ordered by expedition and rang } else { $langs->load("errors"); - $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->error); + $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); $error++; } } @@ -377,7 +377,7 @@ if (empty($reshook)) { $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order); if ($res == 0) { - $errors[] = $objecttmp->error; + $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); $error++; } @@ -640,7 +640,11 @@ if (empty($reshook)) { $action = 'create'; $_GET["origin"] = $_POST["origin"]; $_GET["originid"] = $_POST["originid"]; - setEventMessages("Error", null, 'errors'); + if (!empty($errors)) { + setEventMessages(null, $errors, 'errors'); + } else { + setEventMessages("Error", null, 'errors'); + } $error++; } } From 40da13922506d9a108d731e51c8eb42dd0fe51ec Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 13:58:33 +0200 Subject: [PATCH 183/473] Add hook massaction to reception list. --- htdocs/reception/list.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 8575c84c026..b3b039c2f68 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -166,6 +166,15 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' } if (empty($reshook)) { + // Mass actions + $objectclass = 'Reception'; + $objectlabel = 'Receptions'; + $permissiontoread = $user->rights->reception->lire; + $permissiontoadd = $user->rights->reception->creer; + $permissiontodelete = $user->rights->reception->supprimer; + $uploaddir = $conf->reception->multidir_output[$conf->entity]; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + if ($massaction == 'confirm_createbills') { $receptions = GETPOST('toselect', 'array'); $createbills_onebythird = GETPOST('createbills_onebythird', 'int'); From 752aaeb275a7cf028cb0cf1b2624bb09271745dc Mon Sep 17 00:00:00 2001 From: BENKE Charlene <1179011+defrance@users.noreply.github.com> Date: Mon, 25 Apr 2022 14:07:48 +0200 Subject: [PATCH 184/473] fix : allow cut&paste as real numeric value to excel --- htdocs/compta/resultat/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/resultat/index.php b/htdocs/compta/resultat/index.php index ff770acf554..68068dec866 100644 --- a/htdocs/compta/resultat/index.php +++ b/htdocs/compta/resultat/index.php @@ -1042,7 +1042,7 @@ for ($mois = 1 + $nb_mois_decalage; $mois <= 12 + $nb_mois_decalage; $mois++) { } $case = strftime("%Y-%m", dol_mktime(12, 0, 0, $mois_modulo, 1, $annee_decalage)); - print ' '; + print ''; if ($modecompta == 'CREANCES-DETTES' || $modecompta == 'BOOKKEEPING') { if (isset($decaiss[$case]) && $decaiss[$case] != 0) { print ''.price(price2num($decaiss[$case], 'MT')).''; @@ -1062,7 +1062,7 @@ for ($mois = 1 + $nb_mois_decalage; $mois <= 12 + $nb_mois_decalage; $mois++) { } print ""; - print ' '; + print ''; if ($modecompta == 'CREANCES-DETTES' || $modecompta == 'BOOKKEEPING') { if (isset($encaiss[$case])) { print ''.price(price2num($encaiss[$case], 'MT')).''; From 7e44227df24cc4df1441d2a231ca43c8b72aaaa9 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 14:28:57 +0200 Subject: [PATCH 185/473] Cleanup 'confirm_createbills' --- htdocs/adherents/list.php | 2 +- htdocs/adherents/subscription/list.php | 2 +- htdocs/contrat/services_list.php | 2 +- htdocs/fichinter/list.php | 2 +- htdocs/fourn/facture/list.php | 45 ++------------------------ htdocs/projet/list.php | 2 +- htdocs/projet/tasks/list.php | 2 +- htdocs/projet/tasks/time.php | 2 -- htdocs/user/group/list.php | 2 +- htdocs/user/list.php | 2 +- 10 files changed, 11 insertions(+), 52 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 1936d855a7e..8dacc74722e 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -172,7 +172,7 @@ $result = restrictedArea($user, 'adherent'); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 0b83881e502..aed531d86b4 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -111,7 +111,7 @@ $result = restrictedArea($user, 'adherent', '', '', 'cotisation'); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index adf7a4b6ed7..f12d48df44a 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -163,7 +163,7 @@ $arrayfields = dol_sort_array($arrayfields, 'position'); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/fichinter/list.php b/htdocs/fichinter/list.php index 46a9f2eee3f..04d98031e36 100644 --- a/htdocs/fichinter/list.php +++ b/htdocs/fichinter/list.php @@ -149,7 +149,7 @@ $arrayfields = dol_sort_array($arrayfields, 'position'); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 0e682351992..f110ab78e82 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -228,7 +228,7 @@ if ((empty($user->rights->fournisseur->facture->lire) && empty($conf->global->MA if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } @@ -829,7 +829,7 @@ if ($resql) { //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); - //if($user->rights->fournisseur->facture->creer) $arrayofmassactions['createbills']=$langs->trans("CreateInvoiceForThisCustomer"); + if (!empty($conf->paymentbybanktransfer->enabled) && !empty($user->rights->paymentbybanktransfer->create)) { $langs->load('withdrawals'); $arrayofmassactions['banktransfertrequest'] = img_picto('', 'payment', 'class="pictofixedwidth"').$langs->trans("MakeBankTransferOrder"); @@ -837,7 +837,7 @@ if ($resql) { if ($user->rights->fournisseur->facture->supprimer) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } - if (in_array($massaction, array('presend', 'predelete', 'createbills'))) { + if (in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); @@ -868,45 +868,6 @@ if ($resql) { $trackid = 'sinv'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; - if ($massaction == 'createbills') { - //var_dump($_REQUEST); - print ''; - - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print '
'; - print $langs->trans('DateInvoice'); - print ''; - print $form->selectDate('', '', '', '', '', '', 1, 1); - print '
'; - print $langs->trans('CreateOneBillByThird'); - print ''; - print $form->selectyesno('createbills_onebythird', '', 1); - print '
'; - print $langs->trans('ValidateInvoices'); - print ''; - print $form->selectyesno('validate_invoices', 1, 1); - print '
'; - - print '
'; - print '
'; - print ' '; - print ''; - print '
'; - print '
'; - } - if ($search_all) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index b254ac2b26f..93c92231bfd 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -226,7 +226,7 @@ $arrayfields = dol_sort_array($arrayfields, 'position'); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index d71cd9bca56..6d9e44c3799 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -185,7 +185,7 @@ if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 1b8e116092f..4374ffb2d37 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1149,8 +1149,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Form to convert time spent into invoice if ($massaction == 'generateinvoice') { - print ''; - if ($projectstatic->thirdparty->id > 0) { print ''; print ''; diff --git a/htdocs/user/group/list.php b/htdocs/user/group/list.php index 04fa0035418..bf8bd407093 100644 --- a/htdocs/user/group/list.php +++ b/htdocs/user/group/list.php @@ -92,7 +92,7 @@ if (!$user->rights->user->user->lire && !$user->admin) { if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } diff --git a/htdocs/user/list.php b/htdocs/user/list.php index cd87e286225..4ae920e6dc7 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -203,7 +203,7 @@ $childids = $user->getAllChildIds(1); if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } From 22b56bde9eab474052e3b4c54ffd8d877c677819 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 25 Apr 2022 14:30:55 +0200 Subject: [PATCH 186/473] Update changelog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 31bfa1c1cff..428829038f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,7 +34,7 @@ Following changes may create regressions for some external modules, but were nec * The deprecated method thirdparty_doc_create() has been removed. You can use the generateDocument() instead. * All triggers with a name XXX_UPDATE have been rename with name XXX_MODIFY for code consistency purpose. * Rename build_path_from_id_categ() into buildPathFromId() and set method to private - +* Move massaction 'confirm_createbills' from actions_massactions.inc.php to commande/list.php ***** ChangeLog for 15.0.1 compared to 15.0.0 ***** FIX: #19777 #20281 From 7f1d5fa86731b66d68b95d13a6750a365e471486 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 25 Apr 2022 12:43:58 +0000 Subject: [PATCH 187/473] Fixing style errors. --- htdocs/fourn/facture/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index f110ab78e82..b8ad5e68415 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -829,7 +829,7 @@ if ($resql) { //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); - + if (!empty($conf->paymentbybanktransfer->enabled) && !empty($user->rights->paymentbybanktransfer->create)) { $langs->load('withdrawals'); $arrayofmassactions['banktransfertrequest'] = img_picto('', 'payment', 'class="pictofixedwidth"').$langs->trans("MakeBankTransferOrder"); From 694bcda3bbdbac9b79a74cf6b51df477be5660a7 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Mon, 25 Apr 2022 22:26:25 +0200 Subject: [PATCH 188/473] Fix #20712 - No more empty wrong line added in bookkeeping confirme_create mode --- htdocs/accountancy/bookkeeping/card.php | 63 ++++++++++++++----------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index c156a388735..0aa57dde3c6 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -260,7 +260,7 @@ if ($action == "confirm_update") { if ($mode != '_tmp') { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); } - $action = 'update'; + $action = ''; $id = $object->id; $piece_num = $object->piece_num; } @@ -642,6 +642,12 @@ if ($action == 'create') { } print "\n"; + + // Empty line is the first line of $object->linesmvt + // So we must get the first line (the empty one) and pu it at the end of the array + // in order to display it correctly to the user + $empty_line = array_shift($object->linesmvt); + $object->linesmvt[]= $empty_line; foreach ($object->linesmvt as $line) { print ''; @@ -673,7 +679,33 @@ if ($action == 'create') { print ''."\n"; print ''; print ''; + } elseif (empty($line->numero_compte) || (empty($line->debit) &&empty($line->creit))) { + if ($action == "" || $action == 'add') { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } } else { + print ''; $accountingaccount->fetch(null, $line->numero_compte, true); print ''; print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - } - print '
'; + print $formaccounting->select_account('', 'accountingaccount_number', 1, array(), 1, 1, ''); + print ''; + // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because: + // It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases. + // Also, it is not possible to use a value that is not in the list. + // Also, the label is not automatically filled when a value is selected. + if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { + print $formaccounting->select_auxaccount('', 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); + } else { + print ''; + } + print '
'; + print '
'; + print ''; + print ''.$accountingaccount->getNomUrl(0, 1, 1, '', 0).''.length_accounta($line->subledger_account); @@ -715,33 +747,8 @@ if ($action == 'create') { setEventMessages(null, array($langs->trans('MvtNotCorrectlyBalanced', $total_debit, $total_credit)), 'warnings'); } - if (empty($object->date_export) && empty($object->date_validation)) { - if ($action == "" || $action == 'add') { - print '
'; - print $formaccounting->select_account('', 'accountingaccount_number', 1, array(), 1, 1, ''); - print ''; - // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because: - // It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases. - // Also, it is not possible to use a value that is not in the list. - // Also, the label is not automatically filled when a value is selected. - if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $formaccounting->select_auxaccount('', 'subledger_account', 1); - } else { - print ''; - } - print '
'; - print '
'; - } + print ''; + print ''; if ($mode == '_tmp' && $action == '') { print '
'; From 6a1d4c2255a0ac9fa77a97960f7315511dd893ce Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 25 Apr 2022 20:36:34 +0000 Subject: [PATCH 189/473] Fixing style errors. --- htdocs/accountancy/bookkeeping/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 0aa57dde3c6..0eff932fd19 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -642,7 +642,7 @@ if ($action == 'create') { } print "\n"; - + // Empty line is the first line of $object->linesmvt // So we must get the first line (the empty one) and pu it at the end of the array // in order to display it correctly to the user @@ -703,7 +703,7 @@ if ($action == 'create') { print ''; print ''; print ''; - } + } } else { print ''; $accountingaccount->fetch(null, $line->numero_compte, true); From fb1c770568e139c4e4cf19a1db51e820f768d110 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Apr 2022 23:37:34 +0200 Subject: [PATCH 190/473] Doc --- htdocs/install/mysql/migration/repair.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 2e7f42a2727..4add688b880 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -559,6 +559,10 @@ DELETE FROM llx_rights_def WHERE module = 'hrm' AND perms = 'employee'; -- Sequence to fix the content of llx_bank.amount_main_currency +-- Note: amount is amount in currency of bank account +-- Note: pamount is always amount into the main currency +-- Note: pmulticurrencyamount is in currency of invoice +-- Note: amount_main_currency must be amount in 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; From 8de9d63f7df725cdc5d4e59c37b0961e6f59c570 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Apr 2022 00:35:20 +0200 Subject: [PATCH 191/473] FIX Numbering of sepa files --- htdocs/compta/prelevement/class/bonprelevement.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 27c96bd47db..afd6b5e075c 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -920,7 +920,7 @@ class BonPrelevement extends CommonObject $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX" $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons"; - $sql .= " WHERE ref LIKE '%".$this->db->escape($ref)."%'"; + $sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'"; $sql .= " AND entity = ".((int) $conf->entity); $sql .= " ORDER BY ref DESC LIMIT 1"; @@ -931,7 +931,7 @@ class BonPrelevement extends CommonObject $row = $this->db->fetch_row($resql); // Build the new ref - $ref = "T".$ref.str_pad(dol_substr("00".(intval($row[0]) + 1), 0, 2), 2, "0", STR_PAD_LEFT); + $ref = "T".$ref.sprintf("%02d", (intval($row[0]) + 1)); // $conf->abc->dir_output may be: // /home/ldestailleur/git/dolibarr_15.0/documents/abc/ From 134113db646f49d3a97314282e0dea679fdc5843 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Apr 2022 01:00:10 +0200 Subject: [PATCH 192/473] Fix upload of doc for purchase orders --- htdocs/api/class/api_documents.class.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index da49e4cbba7..44c3b1fcb52 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -597,6 +597,16 @@ class Documents extends DolibarrApi require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $object = new FactureFournisseur($this->db); + } elseif ($modulepart == 'commande' || $modulepart == 'order') { + $modulepart = 'commande'; + + require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; + $object = new Commande($this->db); + } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') { + $modulepart = 'supplier_order'; + + require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; + $object = new CommandeFournisseur($this->db); } elseif ($modulepart == 'project') { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $object = new Project($this->db); @@ -655,7 +665,7 @@ class Documents extends DolibarrApi } // Special cases that need to use get_exdir to get real dir of object - // If future, all object should use this to define path of documents. + // In future, all object should use this to define path of documents. if ($modulepart == 'supplier_invoice') { $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier'); } From 8980b2e6c09a3d55808ae10b23ecc36a8715d952 Mon Sep 17 00:00:00 2001 From: matll42 Date: Tue, 26 Apr 2022 01:44:53 +0200 Subject: [PATCH 193/473] FIX #20476 migration postgresql 14.0.x to 15.0.x packaging type --- htdocs/install/mysql/migration/14.0.0-15.0.0.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 4b34d3a72ac..58f29acfe60 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 @@ -36,7 +36,8 @@ -- VPGSQL8.2 ALTER TABLE llx_partnership ALTER COLUMN date_partnership_end DROP NOT NULL; ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging real DEFAULT NULL; -ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; +-- VMYSQL4.3 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; +-- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL USING packaging::real; ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_export datetime DEFAULT NULL; From 8d3c2e34f42b8d237c75c022090052da46839cf0 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 26 Apr 2022 11:46:00 +0200 Subject: [PATCH 194/473] FIX Check field accountancy code customer is mandatory in mass action --- htdocs/compta/facture/class/facture.class.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 7ad0a8ed4bc..2134570ee2e 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2724,7 +2724,7 @@ class Facture extends CommonInvoice // Check for mandatory fields in thirdparty (defined into setup) if (!empty($this->thirdparty) && is_object($this->thirdparty)) { - $array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL'); + $array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL', 'ACCOUNTANCY_CODE_CUSTOMER'); foreach ($array_to_check as $key) { $keymin = strtolower($key); if (!property_exists($this->thirdparty, $keymin)) { @@ -2756,6 +2756,15 @@ class Facture extends CommonInvoice return -1; } } + if ($key == 'ACCOUNTANCY_CODE_CUSTOMER') { + // Check for mandatory + if (!empty($conf->global->SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY) && empty($this->thirdparty->code_compta)) { + $langs->load("errors"); + $this->error = $langs->trans("ErrorAccountancyCodeCustomerIsMandatory", $this->thirdparty->name).' ('.$langs->trans("ForbiddenBySetupRules").')'; + dol_syslog(__METHOD__.' '.$this->error, LOG_ERR); + return -1; + } + } } } } From c00a56bee3ce475fa268ea3cb707465702f6b4eb Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 26 Apr 2022 16:39:06 +0200 Subject: [PATCH 195/473] fix: truncate too long Ref Customer in PDF Header --- htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php | 2 +- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 2 +- htdocs/core/modules/propale/doc/pdf_cyan.modules.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index 6486306d9ed..96966606e1c 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1504,7 +1504,7 @@ class pdf_eratosthene extends ModelePDFCommandes $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 3134bbc63f5..1bbbb2c9f3f 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1961,7 +1961,7 @@ class pdf_sponge extends ModelePDFFactures $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 5fb9949acd3..cb2df1a5ed9 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -1595,7 +1595,7 @@ class pdf_cyan extends ModelePDFPropales $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { From 399addfb033e07924ec988a65b87329d925b8a7e Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 26 Apr 2022 16:40:27 +0200 Subject: [PATCH 196/473] mor docs --- .../core/modules/supplier_proposal/doc/pdf_aurore.modules.php | 2 +- .../doc/pdf_standard_recruitmentjobposition.modules.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index 7e1b1105452..f2d2a473145 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -1336,7 +1336,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } /* PHFAVRE $posy+=4; diff --git a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php index 50e978aceab..cc215a855ff 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php @@ -919,7 +919,7 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { From 3d4bd1e1553a76c87bcf172d3f8640f86de09cf2 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 26 Apr 2022 16:53:40 +0200 Subject: [PATCH 197/473] FIX: truncate Customer Reference too long on PDF header (PR #20718) --- .../core/modules/supplier_proposal/doc/pdf_aurore.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index f2d2a473145..aba01f51742 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -1336,7 +1336,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R'); } /* PHFAVRE $posy+=4; From 5387a8e9530b19d4bdc32127196478c8673cba47 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Tue, 26 Apr 2022 19:07:31 +0200 Subject: [PATCH 198/473] FiX miss spelling --- htdocs/accountancy/bookkeeping/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 0eff932fd19..f9ec739e63d 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -679,7 +679,7 @@ if ($action == 'create') { print ''."\n"; print ''; print ''; - } elseif (empty($line->numero_compte) || (empty($line->debit) &&empty($line->creit))) { + } elseif (empty($line->numero_compte) || (empty($line->debit) && empty($line->credit))) { if ($action == "" || $action == 'add') { print ''; print ''; From 3f832c1c5d405866b704e9cd9a1beb5aa4d7e423 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 27 Apr 2022 04:46:09 +0200 Subject: [PATCH 199/473] FIX Accountancy - Export format FEC - Prevent tab in label with the formats for which it is the separator --- htdocs/accountancy/class/accountancyexport.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 3c30200c130..128b14fa800 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -980,6 +980,8 @@ class AccountancyExport print dol_string_unaccent($date_creation) . $separator; // FEC:EcritureLib + // Clean label operation to prevent problem on export with tab separator & other character + $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation); print dol_string_unaccent($line->label_operation) . $separator; // FEC:Debit @@ -1007,6 +1009,8 @@ class AccountancyExport print $date_limit_payment . $separator; // FEC_suppl:NumFacture + // Clean ref invoice to prevent problem on export with tab separator & other character + $refInvoice = str_replace(array("\t", "\n", "\r"), " ", $refInvoice); print dol_trunc(self::toAnsi($refInvoice), 17, 'right', 'UTF-8', 1); print $end_line; @@ -1107,6 +1111,8 @@ class AccountancyExport print $date_document . $separator; // FEC:EcritureLib + // Clean label operation to prevent problem on export with tab separator & other character + $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation); print dol_string_unaccent($line->label_operation) . $separator; // FEC:Debit @@ -1134,6 +1140,8 @@ class AccountancyExport print $date_limit_payment . $separator; // FEC_suppl:NumFacture + // Clean ref invoice to prevent problem on export with tab separator & other character + $refInvoice = str_replace(array("\t", "\n", "\r"), " ", $refInvoice); print dol_trunc(self::toAnsi($refInvoice), 17, 'right', 'UTF-8', 1); @@ -1712,6 +1720,8 @@ class AccountancyExport print self::trunc($line->label_compte, 60).$separator; //Account label print self::trunc($line->doc_ref, 20).$separator; //Piece + // Clean label operation to prevent problem on export with tab separator & other character + $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation); print self::trunc($line->label_operation, 60).$separator; //Operation label print price(abs($line->debit - $line->credit)).$separator; //Amount print $line->sens.$separator; //Direction From dd85c22927a8e17afa59058615ffe32ecfd24dd6 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 27 Apr 2022 08:50:58 +0200 Subject: [PATCH 200/473] remove combox search box --- htdocs/compta/facture/list.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 1c4ce0cdecf..c026b3a5db1 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -136,7 +136,7 @@ $search_datelimit_endyear = GETPOST('search_datelimit_endyear', 'int'); $search_datelimit_start = dol_mktime(0, 0, 0, $search_datelimit_startmonth, $search_datelimit_startday, $search_datelimit_startyear); $search_datelimit_end = dol_mktime(23, 59, 59, $search_datelimit_endmonth, $search_datelimit_endday, $search_datelimit_endyear); $search_categ_cus = GETPOST("search_categ_cus", 'int'); -$search_fac_rec_source = GETPOST("search_fac_rec_source", 'int'); +$search_fac_rec_source_title = GETPOST("search_fac_rec_source_title", 'alpha'); $search_btn = GETPOST('button_search', 'alpha'); $search_remove_btn = GETPOST('button_removefilter', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); @@ -363,7 +363,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', $search_datelimit_endyear = ''; $search_datelimit_start = ''; $search_datelimit_end = ''; - $search_fac_rec_source = ''; + $search_fac_rec_source_title = ''; $option = ''; $filter = ''; $toselect = ''; @@ -622,6 +622,10 @@ if ($sall || $search_product_category > 0) { if ($search_product_category > 0) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product'; } + +if (!empty($search_fac_rec_source_title)) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facture_rec as facrec ON f.fk_fac_rec_source=facrec.rowid'; +} $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = f.fk_projet"; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user AS u ON f.fk_user_author = u.rowid'; // We'll need this table joined to the select in order to filter by sale @@ -806,9 +810,8 @@ if ($search_sale > 0) { if ($search_user > 0) { $sql .= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='facture' AND tc.source='internal' AND ec.element_id = f.rowid AND ec.fk_socpeople = ".((int) $search_user); } - -if ($search_fac_rec_source > 0) { - $sql .= " AND f.fk_fac_rec_source = ".((int) $search_fac_rec_source); +if (!empty($search_fac_rec_source_title)) { + $sql .= natural_search('facrec.titre', $search_fac_rec_source_title); } // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -1088,8 +1091,8 @@ if ($resql) { if ($search_categ_cus > 0) { $param .= '&search_categ_cus='.urlencode($search_categ_cus); } - if ($search_fac_rec_source > 0) { - $param .= '&search_fac_rec_source='.urlencode($search_fac_rec_source); + if (!empty($search_fac_rec_source_title)) { + $param .= '&$search_fac_rec_source_title='.urlencode($search_fac_rec_source_title); } // Add $param from extra fields @@ -1515,7 +1518,7 @@ if ($resql) { if (!empty($arrayfields['f.fk_fac_rec_source']['checked'])) { // Template Invoice print ''; - $form->selectInvoiceRec($search_fac_rec_source, 'search_fac_rec_source'); + print ''; print ''; } // Status @@ -1678,7 +1681,7 @@ if ($resql) { print_liste_field_titre($arrayfields['f.note_private']['label'], $_SERVER["PHP_SELF"], "f.note_private", "", $param, '', $sortfield, $sortorder, 'center nowrap '); } if (!empty($arrayfields['f.fk_fac_rec_source']['checked'])) { - print_liste_field_titre($arrayfields['f.fk_fac_rec_source']['label'], $_SERVER["PHP_SELF"], "f.fk_fac_rec_source", "", $param, '', $sortfield, $sortorder); + print_liste_field_titre($arrayfields['f.fk_fac_rec_source']['label'], $_SERVER["PHP_SELF"], "facrec.titre", "", $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['f.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['f.fk_statut']['label'], $_SERVER["PHP_SELF"], "f.fk_statut,f.paye,f.type", "", $param, 'class="right"', $sortfield, $sortorder); From 543e6f186cdf03113f07b2d7b3ffbebadbda3afa Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Wed, 27 Apr 2022 09:03:51 +0200 Subject: [PATCH 201/473] add hook to getSellPrice function --- htdocs/product/class/product.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 84cc2454c21..cf9a0c3fa87 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1804,6 +1804,16 @@ class Product extends CommonObject { global $conf, $db; + // call hook if any + $hookmanager->initHooks(array('productdao')); + $parameters = array('thirdparty_seller'=>$thirdparty_seller, 'thirdparty_buyer' => $thirdparty_buyer, 'pqp' => $pqp); + // Note that $action and $object may have been modified by some hooks + global $action; + $reshook = $hookmanager->executeHooks('getSellPrice', $parameters, $this, $action); + if ( ! empty($reshook)) { + return $hookmanager->resArray; + } + // Update if prices fields are defined $tva_tx = get_default_tva($thirdparty_seller, $thirdparty_buyer, $this->id); $tva_npr = get_default_npr($thirdparty_seller, $thirdparty_buyer, $this->id); From 4939da560f7becf2bf51f5a776ec6c4b1c90ad74 Mon Sep 17 00:00:00 2001 From: dolibarr95 <24292300+dolibarr95@users.noreply.github.com> Date: Wed, 27 Apr 2022 09:25:38 +0200 Subject: [PATCH 202/473] New: Add option to foce delivery receipt to yes Add a constant to force delivery receipt for supplier order. --- htdocs/core/class/html.formmail.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 0c9a1b2531a..818c3b19c7b 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1202,6 +1202,9 @@ class FormMail extends Form if (!empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_INVOICE) && !empty($this->param['models']) && $this->param['models'] == 'facture_send') { $defaultvaluefordeliveryreceipt = 1; } + if (!empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_ORDER) && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') { + $defaultvaluefordeliveryreceipt = 1; + } $out .= $form->selectyesno('deliveryreceipt', (GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt), 1); } $out .= "\n"; From 25078b292d6996065fd265c678780584d86d8065 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Wed, 27 Apr 2022 09:40:09 +0200 Subject: [PATCH 203/473] fix hookmanager --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index cf9a0c3fa87..bb411d530c7 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1802,7 +1802,7 @@ class Product extends CommonObject */ public function getSellPrice($thirdparty_seller, $thirdparty_buyer, $pqp = 0) { - global $conf, $db; + global $conf, $db, $hookmanager; // call hook if any $hookmanager->initHooks(array('productdao')); From c969cef731c9f772f8c86af73d5ce7d71ef1fd84 Mon Sep 17 00:00:00 2001 From: dolibarr95 <24292300+dolibarr95@users.noreply.github.com> Date: Wed, 27 Apr 2022 10:09:22 +0200 Subject: [PATCH 204/473] NEW : Send email to the supplier order contact Select the recipient defined in object contact (Vendor contact following-up order / Contact fournisseur suivi commande) in order to send email to the specific contact and not to generic company email (as for invoice/bill) --- htdocs/core/actions_massactions.inc.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5ec011f5017..3b45cffd772 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -128,6 +128,14 @@ if (!$error && $massaction == 'confirm_presend') { $listofobjectcontacts[$toselectid][$data_email['id']] = $data_email['email']; } } + } elseif ($objectclass == 'CommandeFournisseur') { + $tmparraycontact = array(); + $tmparraycontact = $objecttmp->liste_contact(-1, 'external', 0, 'CUSTOMER'); + if (is_array($tmparraycontact) && count($tmparraycontact) > 0) { + foreach ($tmparraycontact as $data_email) { + $listofobjectcontacts[$toselectid][$data_email['id']] = $data_email['email']; + } + } } $listofobjectthirdparties[$thirdpartyid] = $thirdpartyid; @@ -277,6 +285,19 @@ if (!$error && $massaction == 'confirm_presend') { if (count($emails_to_sends) > 0) { $sendto = implode(',', $emails_to_sends); } + } elseif ($objectobj->element == 'order_supplier' && !empty($listofobjectcontacts[$objectid])) { + $emails_to_sends = array(); + $objectobj->fetch_thirdparty(); + $contactidtosend = array(); + foreach ($listofobjectcontacts[$objectid] as $contactemailid => $contactemailemail) { + $emails_to_sends[] = $objectobj->thirdparty->contact_get_property($contactemailid, 'email'); + if (!in_array($contactemailid, $contactidtosend)) { + $contactidtosend[] = $contactemailid; + } + } + if (count($emails_to_sends) > 0) { + $sendto = implode(',', $emails_to_sends); + } } else { $objectobj->fetch_thirdparty(); $sendto = $objectobj->thirdparty->email; From fb7f0545e4a08dd5c835e2d1fe816c3003f839d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Wed, 27 Apr 2022 17:56:31 +0200 Subject: [PATCH 205/473] Fix error reporting in getLinesArray() --- htdocs/modulebuilder/template/class/myobject.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index e7da913f39c..51992ada8ee 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -937,8 +937,8 @@ class MyObject extends CommonObject if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; From 5dce613118c367d1957eee36c5ab2a1cfe848a11 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 28 Apr 2022 05:34:02 +0200 Subject: [PATCH 206/473] NEW Accountancy - Product admin - Add product categories --- htdocs/accountancy/admin/productaccount.php | 108 ++++++++++++++++++-- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 847891c949b..8a8ca0ecf46 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -1,10 +1,10 @@ - * Copyright (C) 2013-2021 Alexandre Spangaro - * Copyright (C) 2014 Florian Henry - * Copyright (C) 2014 Juanjo Menent - * Copyright (C) 2015 Ari Elbaz (elarifr) - * Copyright (C) 2021 Gauthier VERDOL + * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2015 Ari Elbaz (elarifr) + * Copyright (C) 2021 Gauthier VERDOL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,6 +34,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} // Load translation files required by the page $langs->loadLangs(array("companies", "compta", "accountancy", "products")); @@ -59,6 +62,8 @@ $account_number_sell = GETPOST('account_number_sell'); $changeaccount = GETPOST('changeaccount', 'array'); $changeaccount_buy = GETPOST('changeaccount_buy', 'array'); $changeaccount_sell = GETPOST('changeaccount_sell', 'array'); +$searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0); +$searchCategoryProductList = GETPOST('search_category_product_list', 'array'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); $search_desc = GETPOST('search_desc', 'alpha'); @@ -144,6 +149,8 @@ if ($reshook < 0) { // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers + $searchCategoryProductOperator = 0; + $searchCategoryProductList = array(); $search_ref = ''; $search_label = ''; $search_desc = ''; @@ -283,7 +290,16 @@ $aacompta_prodsell = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUN $aacompta_prodsell_intra = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT', $langs->trans("CodeNotDef")); $aacompta_prodsell_export = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT', $langs->trans("CodeNotDef")); -llxHeader('', $langs->trans("ProductsBinding")); + +$title = $langs->trans("ProductsBinding"); +$helpurl = ''; + +$paramsCat = ''; +foreach ($searchCategoryProductList as $searchCategoryProduct) { + $paramsCat .= "&search_category_product_list[]=".urlencode($searchCategoryProduct); +} + +llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, ''); $pcgverid = getDolGlobalString('CHARTOFACCOUNTS'); $pcgvercode = dol_getIdFromCode($db, $pcgverid, 'accounting_system', 'rowid', 'pcg_version'); @@ -308,6 +324,9 @@ if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { } else { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; } +if (!empty($searchCategoryProductList)) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ +} $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; if (strlen(trim($search_current_account))) { $sql .= natural_search((empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "ppe.") . $accountancy_field_name, $search_current_account); @@ -318,6 +337,30 @@ if ($search_current_account_valid == 'withoutvalidaccount') { if ($search_current_account_valid == 'withvalidaccount') { $sql .= " AND aa.account_number IS NOT NULL"; } +$searchCategoryProductSqlList = array(); +if ($searchCategoryProductOperator == 1) { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL"; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "cp.fk_categorie = ".$db->escape($searchCategoryProduct); + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")"; + } +} else { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL"; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "p.rowid IN (SELECT fk_product FROM ".MAIN_DB_PREFIX."categorie_product WHERE fk_categorie = ".((int) $searchCategoryProduct).")"; + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")"; + } +} // Add search filter like if (strlen(trim($search_ref))) { $sql .= natural_search("p.ref", $search_ref); @@ -338,6 +381,15 @@ if ($search_onpurchase != '' && $search_onpurchase != '-1') { $sql .= natural_search('p.tobuy', $search_onpurchase, 1); } +$sql .= " GROUP BY p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.tva_tx,"; +$sql .= " p.fk_product_type,"; +$sql .= ' p.tms,'; +if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export"; +} else { + $sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export, ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export"; +} + $sql .= $db->order($sortfield, $sortorder); $nbtotalofrecords = ''; @@ -365,11 +417,17 @@ if ($result) { if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } + if ($searchCategoryProductOperator == 1) { + $param .= "&search_category_product_operator=".urlencode($searchCategoryProductOperator); + } + foreach ($searchCategoryProductList as $searchCategoryProduct) { + $param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct); + } if ($search_ref > 0) { - $param .= "&search_desc=".urlencode($search_ref); + $param .= "&search_ref=".urlencode($search_ref); } if ($search_label > 0) { - $param .= "&search_desc=".urlencode($search_label); + $param .= "&search_label=".urlencode($search_label); } if ($search_desc > 0) { $param .= "&search_desc=".urlencode($search_desc); @@ -461,6 +519,40 @@ if ($result) { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmPreselectAccount"), $langs->trans("ConfirmPreselectAccountQuestion", count($chk_prod)), "confirm_set_default_account", $formquestion, 1, 0, 200, 500, 1); } + // Filter on categories + $moreforfilter = ''; + if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); + $categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1); + $categoriesProductArr[-2] = '- '.$langs->trans('NotCategorized').' -'; + $moreforfilter .= Form::multiselectarray('search_category_product_list', $categoriesProductArr, $searchCategoryProductList, 0, 0, 'minwidth300'); + $moreforfilter .= ' '.$langs->trans('UseOrOperatorForCategories').''; + $moreforfilter .= '
'; + } + + //Show/hide child products. Hidden by default + if (!empty($conf->variants->enabled) && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { + $moreforfilter .= '
'; + $moreforfilter .= ''; + $moreforfilter .= ' '; + $moreforfilter .= '
'; + } + + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; + } else { + $moreforfilter = $hookmanager->resPrint; + } + + if ($moreforfilter) { + print '
'; + print $moreforfilter; + print '
'; + } + print '
'; print ''; From 1efa44a0220efb7168ba9aa1decd5befc7f8673f Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 28 Apr 2022 06:50:37 +0200 Subject: [PATCH 207/473] NEW Accountancy - Add reconcile functionality --- htdocs/accountancy/bookkeeping/list.php | 369 ++++--- .../accountancy/bookkeeping/listbyaccount.php | 449 +++++--- .../bookkeeping/listbysubaccount.php | 979 ------------------ .../accountancy/class/bookkeeping.class.php | 4 +- htdocs/accountancy/class/lettering.class.php | 456 +++++++- htdocs/accountancy/journal/bankjournal.php | 10 + .../accountancy/journal/purchasesjournal.php | 6 + htdocs/accountancy/journal/sellsjournal.php | 6 + htdocs/langs/en_US/accountancy.lang | 18 + 9 files changed, 1052 insertions(+), 1245 deletions(-) delete mode 100644 htdocs/accountancy/bookkeeping/listbysubaccount.php diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index a760a550bef..bc7ea7c7072 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -28,6 +28,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; @@ -42,6 +43,10 @@ $langs->loadLangs(array("accountancy", "compta")); $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepinglist'; $search_mvt_num = GETPOST('search_mvt_num', 'int'); $search_doc_type = GETPOST("search_doc_type", 'alpha'); $search_doc_ref = GETPOST("search_doc_ref", 'alpha'); @@ -86,6 +91,7 @@ $search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', ' $search_date_validation_endday = GETPOST('search_date_validation_endday', 'int'); $search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear); $search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); +$search_import_key = GETPOST("search_import_key", 'alpha'); //var_dump($search_date_start);exit; if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) { @@ -191,6 +197,7 @@ $arrayfields = array( 't.tms'=>array('label'=>$langs->trans("DateModification"), 'checked'=>0), 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1), + 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), ); if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { @@ -220,10 +227,12 @@ if (empty($user->rights->accounting->mouvements->lire)) { * Actions */ +$param = ''; + if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'preunlettering' && $massaction != 'predeletebookkeepingwriting') { $massaction = ''; } @@ -294,10 +303,11 @@ if (empty($reshook)) { $search_credit = ''; $search_lettering_code = ''; $search_not_reconciled = ''; + $search_import_key = ''; + $toselect = ''; } // Must be after the remove filter action, before the export. - $param = ''; $filter = array(); if (!empty($search_date_start)) { $filter['t.doc_date>='] = $search_date_start; @@ -416,77 +426,143 @@ if (empty($reshook)) { $filter['t.reconciled_option'] = $search_not_reconciled; $param .= '&search_not_reconciled='.urlencode($search_not_reconciled); } -} + if (!empty($search_import_key)) { + $filter['t.import_key'] = $search_import_key; + $param .= '&search_import_key='.urlencode($search_import_key); + } -if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) { - $import_key = GETPOST('importkey', 'alpha'); - - if (!empty($import_key)) { - $result = $object->deleteByImportkey($import_key); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + //if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) { + // $delmonth = GETPOST('delmonth', 'int'); + // $delyear = GETPOST('delyear', 'int'); + // if ($delyear == -1) { + // $delyear = 0; + // } + // $deljournal = GETPOST('deljournal', 'alpha'); + // if ($deljournal == -1) { + // $deljournal = 0; + // } + // + // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { + // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); + // if ($result < 0) { + // setEventMessages($object->error, $object->errors, 'errors'); + // } else { + // setEventMessages("RecordDeleted", null, 'mesgs'); + // } + // + // // Make a redirect to avoid to launch the delete later after a back button + // header("Location: list.php".($param ? '?'.$param : '')); + // exit; + // } else { + // setEventMessages("NoRecordDeleted", null, 'warnings'); + // } + //} + if ($action == 'setreexport') { + $setreexport = GETPOST('value', 'int'); + if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) { + $error++; } - // Make a redirect to avoid to launch the delete later after a back button - header("Location: list.php".($param ? '?'.$param : '')); - exit; - } -} -if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) { - $delmonth = GETPOST('delmonth', 'int'); - $delyear = GETPOST('delyear', 'int'); - if ($delyear == -1) { - $delyear = 0; - } - $deljournal = GETPOST('deljournal', 'alpha'); - if ($deljournal == -1) { - $deljournal = 0; - } - - if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { - $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + if (!$error) { + if ($conf->global->ACCOUNTING_REEXPORT == 1) { + setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs'); + } } else { - setEventMessages("RecordDeleted", null, 'mesgs'); + setEventMessages($langs->trans("Error"), null, 'errors'); } - - // Make a redirect to avoid to launch the delete later after a back button - header("Location: list.php".($param ? '?'.$param : '')); - exit; - } else { - setEventMessages("NoRecordDeleted", null, 'warnings'); - } -} -if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) { - $mvt_num = GETPOST('mvt_num', 'int'); - - if (!empty($mvt_num)) { - $result = $object->deleteMvtNum($mvt_num); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); - } - - header("Location: list.php?noreset=1".($param ? '&'.$param : '')); - exit; - } -} -if ($action == 'setreexport') { - $setreexport = GETPOST('value', 'int'); - if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) { - $error++; } - if (!$error) { - if ($conf->global->ACCOUNTING_REEXPORT == 1) { - setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs'); - } else { - setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs'); + // Mass actions + $objectclass = 'Bookkeeping'; + $objectlabel = 'Bookkeeping'; + $permissiontoread = $user->rights->societe->lire; + $permissiontodelete = $user->rights->societe->supprimer; + $permissiontoadd = $user->rights->societe->creer; + $uploaddir = $conf->societe->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if (!$error && $action == 'deletebookkeepingwriting' && $confirm == "yes" && $user->rights->accounting->mouvements->supprimer) { + $nbok = 0; + foreach ($toselect as $toselectid) { + $result = $object->fetch($toselectid); + if ($result > 0 && (!isset($object->date_validation) || $object->date_validation === '')) { + $result = $object->deleteMvtNum($object->piece_num); + if ($result > 0) { + $nbok++; + } else { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } elseif ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } + + // Message for elements well deleted + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs'); + } elseif ($nbok > 0) { + setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs'); + } elseif (!$error) { + setEventMessages($langs->trans("NoRecordDeleted"), null, 'mesgs'); + } + + if (!$error) { + header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : '')); + exit; + } + } + + // others mass actions + if (!$error && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) { + if ($massaction == 'lettering') { + $lettering = new Lettering($db); + $nb_lettering = $lettering->bookkeepingLetteringAll($toselect); + if ($nb_lettering < 0) { + setEventMessages('', $lettering->errors, 'errors'); + $error++; + $nb_lettering = max(0, abs($nb_lettering) - 2); + } elseif ($nb_lettering == 0) { + $nb_lettering = 0; + setEventMessages($langs->trans('AccountancyNoLetteringModified'), array(), 'mesgs'); + } + if ($nb_lettering == 1) { + setEventMessages($langs->trans('AccountancyOneLetteringModifiedSuccessfully'), array(), 'mesgs'); + } elseif ($nb_lettering > 1) { + setEventMessages($langs->trans('AccountancyLetteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs'); + } + + if (!$error) { + header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param); + exit(); + } + } elseif ($action == 'unlettering' && $confirm == "yes") { + $lettering = new Lettering($db); + $nb_lettering = $lettering->bookkeepingLetteringAll($toselect, true); + if ($nb_lettering < 0) { + setEventMessages('', $lettering->errors, 'errors'); + $error++; + $nb_lettering = max(0, abs($nb_lettering) - 2); + } elseif ($nb_lettering == 0) { + $nb_lettering = 0; + setEventMessages($langs->trans('AccountancyNoUnletteringModified'), array(), 'mesgs'); + } + if ($nb_lettering == 1) { + setEventMessages($langs->trans('AccountancyOneUnletteringModifiedSuccessfully'), array(), 'mesgs'); + } elseif ($nb_lettering > 1) { + setEventMessages($langs->trans('AccountancyUnletteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs'); + } + + if (!$error) { + header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param); + exit(); + } } - } else { - setEventMessages($langs->trans("Error"), null, 'errors'); } } @@ -520,7 +596,8 @@ $sql .= " t.piece_num,"; $sql .= " t.date_creation,"; $sql .= " t.tms as date_modification,"; $sql .= " t.date_export,"; -$sql .= " t.date_validated as date_validation"; +$sql .= " t.date_validated as date_validation,"; +$sql .= " t.import_key"; $sql .= ' FROM '.MAIN_DB_PREFIX.$object->table_element.' as t'; // Manage filter $sqlwhere = array(); @@ -667,6 +744,7 @@ if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) { $num = $db->num_rows($resql); } +$arrayofselected = is_array($toselect) ? $toselect : array(); // Output page // -------------------------------------------------------------------- @@ -684,7 +762,7 @@ if ($action == 'export_file') { 'name' => 'notifiedexportdate', 'type' => 'checkbox', 'label' => $langs->trans('NotifiedExportDate'), - 'value' => $checked, + 'value' => (!empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) ? 'false' : 'true'), ); $form_question['separator'] = array('name'=>'separator', 'type'=>'separator'); @@ -703,50 +781,46 @@ if ($action == 'export_file') { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 300, 600); } -if ($action == 'delmouv') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.urlencode(GETPOST('mvt_num')).$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1); -} - -if ($action == 'delbookkeepingyear') { - $form_question = array(); - $delyear = GETPOST('delyear', 'int'); - $deljournal = GETPOST('deljournal', 'alpha'); - - if (empty($delyear)) { - $delyear = dol_print_date(dol_now(), '%Y'); - } - $month_array = array(); - for ($i = 1; $i <= 12; $i++) { - $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); - } - $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); - $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); - - $form_question['delmonth'] = array( - 'name' => 'delmonth', - 'type' => 'select', - 'label' => $langs->trans('DelMonth'), - 'values' => $month_array, - 'morecss' => 'minwidth150', - 'default' => '' - ); - $form_question['delyear'] = array( - 'name' => 'delyear', - 'type' => 'select', - 'label' => $langs->trans('DelYear'), - 'values' => $year_array, - 'default' => $delyear - ); - $form_question['deljournal'] = array( - 'name' => 'deljournal', - 'type' => 'other', // We don't use select here, the journal_array is already a select html component - 'label' => $langs->trans('DelJournal'), - 'value' => $journal_array, - 'default' => $deljournal - ); - - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 320); -} +//if ($action == 'delbookkeepingyear') { +// $form_question = array(); +// $delyear = GETPOST('delyear', 'int'); +// $deljournal = GETPOST('deljournal', 'alpha'); +// +// if (empty($delyear)) { +// $delyear = dol_print_date(dol_now(), '%Y'); +// } +// $month_array = array(); +// for ($i = 1; $i <= 12; $i++) { +// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); +// } +// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); +// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); +// +// $form_question['delmonth'] = array( +// 'name' => 'delmonth', +// 'type' => 'select', +// 'label' => $langs->trans('DelMonth'), +// 'values' => $month_array, +// 'morecss' => 'minwidth150', +// 'default' => '' +// ); +// $form_question['delyear'] = array( +// 'name' => 'delyear', +// 'type' => 'select', +// 'label' => $langs->trans('DelYear'), +// 'values' => $year_array, +// 'default' => $delyear +// ); +// $form_question['deljournal'] = array( +// 'name' => 'deljournal', +// 'type' => 'other', // We don't use select here, the journal_array is already a select html component +// 'label' => $langs->trans('DelJournal'), +// 'value' => $journal_array, +// 'default' => $deljournal +// ); +// +// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 320); +//} // Print form confirm print $formconfirm; @@ -759,6 +833,22 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } +// List of mass actions available +$arrayofmassactions = array(); +/* +if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) { + $arrayofmassactions['lettering'] = img_picto('', 'check', 'class="pictofixedwidth"') . $langs->trans('Lettering'); + $arrayofmassactions['preunlettering'] = img_picto('', 'uncheck', 'class="pictofixedwidth"') . $langs->trans('Unlettering'); +} +*/ +if ($user->rights->accounting->mouvements->supprimer) { + $arrayofmassactions['predeletebookkeepingwriting'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('preunlettering', 'predeletebookkeepingwriting'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions); + print '
'; print ''; print ''; @@ -768,8 +858,7 @@ if ($optioncss != '') { print ''; print ''; print ''; - -$massactionbutton = ''; +print ''; if (count($filter)) { $buttonLabel = $langs->trans("ExportFilteredList"); @@ -794,7 +883,7 @@ if (empty($reshook)) { $newcardbutton .= dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?type=sub'.$param, '', 1, array('morecss' => 'marginleftonly')); $url = './card.php?action=create'; if (!empty($socid)) { @@ -805,9 +894,21 @@ if (empty($reshook)) { print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); +if ($massaction == 'preunlettering') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassUnlettering"), $langs->trans("ConfirmMassUnletteringQuestion", count($toselect)), "unlettering", null, '', 0, 200, 500, 1); +} elseif ($massaction == 'predeletebookkeepingwriting') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDeleteBookkeepingWriting"), $langs->trans("ConfirmMassDeleteBookkeepingWritingQuestion", count($toselect)), "deletebookkeepingwriting", null, '', 0, 200, 500, 1); +} + +//$topicmail = "Information"; +//$modelmail = "accountingbookkeeping"; +//$objecttmp = new BookKeeping($db); +//$trackid = 'bk'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -if ($massactionbutton) { +if ($massactionbutton && $contextpage != 'poslist') { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -954,6 +1055,11 @@ if (!empty($arrayfields['t.date_validated']['checked'])) { print ''; print ''; } +if (!empty($arrayfields['t.import_key']['checked'])) { + print '
'; +} // Action column print '\n"; @@ -1252,17 +1361,21 @@ while ($i < min($num, $limit)) { } } - // Action column - print '\n"; + if (!$i) { + $totalarray['nbfield']++; } } - if (empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->supprimer) { - print ''.img_delete().''; + + // Action column + print ''; @@ -1283,11 +1396,11 @@ print "
'; + print ''; + print ''; $searchpicto = $form->showFilterButtons(); @@ -1008,6 +1114,9 @@ if (!empty($arrayfields['t.date_export']['checked'])) { if (!empty($arrayfields['t.date_validated']['checked'])) { print_liste_field_titre($arrayfields['t.date_validated']['label'], $_SERVER['PHP_SELF'], "t.date_validated", "", $param, '', $sortfield, $sortorder, 'center '); } +if (!empty($arrayfields['t.import_key']['checked'])) { + print_liste_field_titre($arrayfields['t.import_key']['label'], $_SERVER["PHP_SELF"], "t.import_key", "", $param, '', $sortfield, $sortorder, 'center '); +} print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); print "
'; - if (empty($line->date_export) && empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->creer) { - print '' . img_edit() . ''; + if (!empty($arrayfields['t.import_key']['checked'])) { + print ''.$obj->import_key."'; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($line->id, $arrayofselected)) { + $selected = 1; } + print ''; } print '
"; print '
'; // TODO Replace this with mass delete action -if ($user->rights->accounting->mouvements->supprimer_tous) { - print '
'."\n"; - print ''.$langs->trans("DeleteMvt").''; - print '
'; -} +//if ($user->rights->accounting->mouvements->supprimer_tous) { +// print '
'."\n"; +// print ''.$langs->trans("DeleteMvt").''; +// print '
'; +//} print ''; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 837a372a32d..5650cce8767 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -28,6 +28,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; @@ -39,6 +40,16 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $langs->loadLangs(array("accountancy", "compta")); $action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$type = GETPOST('type', 'alpha'); +if ($type == 'sub') { + $context_default = 'bookkeepingbysubaccountlist'; +} else { + $context_default = 'bookkeepingbyaccountlist'; +} +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : $context_default; $search_date_startyear = GETPOST('search_date_startyear', 'int'); $search_date_startmonth = GETPOST('search_date_startmonth', 'int'); $search_date_startday = GETPOST('search_date_startday', 'int'); @@ -64,6 +75,7 @@ $search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', ' $search_date_validation_endday = GETPOST('search_date_validation_endday', 'int'); $search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear); $search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); +$search_import_key = GETPOST("search_import_key", 'alpha'); $search_accountancy_code = GETPOST("search_accountancy_code"); $search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); @@ -109,7 +121,7 @@ if ($sortfield == "") { // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new BookKeeping($db); $formfile = new FormFile($db); -$hookmanager->initHooks(array('bookkeepingbyaccountlist')); +$hookmanager->initHooks(array($context_default)); $formaccounting = new FormAccounting($db); $form = new Form($db); @@ -153,6 +165,7 @@ $arrayfields = array( 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1), 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), 't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1), + 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), ); if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { @@ -187,10 +200,13 @@ if (empty($user->rights->accounting->mouvements->lire)) { * Action */ +$param = ''; + if (GETPOST('cancel', 'alpha')) { - $action = 'list'; $massaction = ''; + $action = 'list'; + $massaction = ''; } -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'preunlettering' && $massaction != 'predeletebookkeepingwriting') { $massaction = ''; } @@ -242,10 +258,11 @@ if (empty($reshook)) { $search_credit = ''; $search_lettering_code = ''; $search_not_reconciled = ''; + $search_import_key = ''; + $toselect = ''; } // Must be after the remove filter action, before the export. - $param = ''; $filter = array(); if (!empty($search_date_start)) { @@ -261,12 +278,20 @@ if (empty($reshook)) { $param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int'); } if (!empty($search_accountancy_code_start)) { - $filter['t.numero_compte>='] = $search_accountancy_code_start; - $param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start); + if ($type == 'sub') { + $filter['t.subledger_account>='] = $search_accountancy_code_start; + } else { + $filter['t.numero_compte>='] = $search_accountancy_code_start; + } + $param .= '&search_accountancy_code_start=' . urlencode($search_accountancy_code_start); } if (!empty($search_accountancy_code_end)) { - $filter['t.numero_compte<='] = $search_accountancy_code_end; - $param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end); + if ($type == 'sub') { + $filter['t.subledger_account<='] = $search_accountancy_code_end; + } else { + $filter['t.numero_compte<='] = $search_accountancy_code_end; + } + $param .= '&search_accountancy_code_end=' . urlencode($search_accountancy_code_end); } if (!empty($search_label_account)) { $filter['t.label_compte'] = $search_label_account; @@ -326,61 +351,133 @@ if (empty($reshook)) { $filter['t.date_validated<='] = $search_date_validation_end; $param .= '&search_date_validation_endmonth='.$search_date_validation_endmonth.'&search_date_validation_endday='.$search_date_validation_endday.'&search_date_validation_endyear='.$search_date_validation_endyear; } -} + if (!empty($search_import_key)) { + $filter['t.import_key'] = $search_import_key; + $param .= '&search_import_key='.urlencode($search_import_key); + } -if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) { - $import_key = GETPOST('importkey', 'alpha'); + // param with type of list + $url_param = substr($param, 1); // remove first "&" + if (!empty($type)) { + $param = '&type='.$type.$param; + } - if (!empty($import_key)) { - $result = $object->deleteByImportkey($import_key); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + //if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) { + // $delmonth = GETPOST('delmonth', 'int'); + // $delyear = GETPOST('delyear', 'int'); + // if ($delyear == -1) { + // $delyear = 0; + // } + // $deljournal = GETPOST('deljournal', 'alpha'); + // if ($deljournal == -1) { + // $deljournal = 0; + // } + // + // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { + // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); + // if ($result < 0) { + // setEventMessages($object->error, $object->errors, 'errors'); + // } else { + // setEventMessages("RecordDeleted", null, 'mesgs'); + // } + // + // // Make a redirect to avoid to launch the delete later after a back button + // header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); + // exit; + // } else { + // setEventMessages("NoRecordDeleted", null, 'warnings'); + // } + //} + + // Mass actions + $objectclass = 'Bookkeeping'; + $objectlabel = 'Bookkeeping'; + $permissiontoread = $user->rights->societe->lire; + $permissiontodelete = $user->rights->societe->supprimer; + $permissiontoadd = $user->rights->societe->creer; + $uploaddir = $conf->societe->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if (!$error && $action == 'deletebookkeepingwriting' && $confirm == "yes" && $user->rights->accounting->mouvements->supprimer) { + $nbok = 0; + foreach ($toselect as $toselectid) { + $result = $object->fetch($toselectid); + if ($result > 0 && (!isset($object->date_validation) || $object->date_validation === '')) { + $result = $object->deleteMvtNum($object->piece_num); + if ($result > 0) { + $nbok++; + } else { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } elseif ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } } - // Make a redirect to avoid to launch the delete later after a back button - header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); - exit; - } -} -if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) { - $delmonth = GETPOST('delmonth', 'int'); - $delyear = GETPOST('delyear', 'int'); - if ($delyear == -1) { - $delyear = 0; - } - $deljournal = GETPOST('deljournal', 'alpha'); - if ($deljournal == -1) { - $deljournal = 0; - } - - if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { - $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages("RecordDeleted", null, 'mesgs'); + // Message for elements well deleted + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs'); + } elseif ($nbok > 0) { + setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs'); + } elseif (!$error) { + setEventMessages($langs->trans("NoRecordDeleted"), null, 'mesgs'); } - // Make a redirect to avoid to launch the delete later after a back button - header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); - exit; - } else { - setEventMessages("NoRecordDeleted", null, 'warnings'); - } -} -if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) { - $mvt_num = GETPOST('mvt_num', 'int'); - - if (!empty($mvt_num)) { - $result = $object->deleteMvtNum($mvt_num); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); + if (!$error) { + header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : '')); + exit; } + } - header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : '')); - exit; + // others mass actions + if (!$error && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) { + if ($massaction == 'lettering') { + $lettering = new Lettering($db); + $nb_lettering = $lettering->bookkeepingLetteringAll($toselect); + if ($nb_lettering < 0) { + setEventMessages('', $lettering->errors, 'errors'); + $error++; + $nb_lettering = max(0, abs($nb_lettering) - 2); + } elseif ($nb_lettering == 0) { + $nb_lettering = 0; + setEventMessages($langs->trans('AccountancyNoLetteringModified'), array(), 'mesgs'); + } + if ($nb_lettering == 1) { + setEventMessages($langs->trans('AccountancyOneLetteringModifiedSuccessfully'), array(), 'mesgs'); + } elseif ($nb_lettering > 1) { + setEventMessages($langs->trans('AccountancyLetteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs'); + } + + if (!$error) { + header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param); + exit(); + } + } elseif ($action == 'unlettering' && $confirm == "yes") { + $lettering = new Lettering($db); + $nb_lettering = $lettering->bookkeepingLetteringAll($toselect, true); + if ($nb_lettering < 0) { + setEventMessages('', $lettering->errors, 'errors'); + $error++; + $nb_lettering = max(0, abs($nb_lettering) - 2); + } elseif ($nb_lettering == 0) { + $nb_lettering = 0; + setEventMessages($langs->trans('AccountancyNoUnletteringModified'), array(), 'mesgs'); + } + if ($nb_lettering == 1) { + setEventMessages($langs->trans('AccountancyOneUnletteringModifiedSuccessfully'), array(), 'mesgs'); + } elseif ($nb_lettering > 1) { + setEventMessages($langs->trans('AccountancyUnletteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs'); + } + + if (!$error) { + header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param); + exit(); + } + } } } @@ -394,73 +491,101 @@ $formfile = new FormFile($db); $formother = new FormOther($db); $form = new Form($db); -$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('.$langs->trans("Bookkeeping").')'; +$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('; +if ($type == 'sub') { + $title_page .= $langs->trans("BookkeepingSubAccount"); +} else { + $title_page .= $langs->trans("Bookkeeping"); +} +$title_page .= ')'; llxHeader('', $title_page); // List $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter); + if ($type == 'sub') { + $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1); + } else { + $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter); + } + if ($nbtotalofrecords < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } -$result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter); +if ($type == 'sub') { + $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1); +} else { + $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter); +} if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } +$arrayofselected = is_array($toselect) ? $toselect : array(); + $num = count($object->lines); -if ($action == 'delmouv') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1); - print $formconfirm; +///if ($action == 'delbookkeepingyear') { +// $form_question = array(); +// $delyear = GETPOST('delyear', 'int'); +// $deljournal = GETPOST('deljournal', 'alpha'); +// +// if (empty($delyear)) { +// $delyear = dol_print_date(dol_now(), '%Y'); +// } +// $month_array = array(); +// for ($i = 1; $i <= 12; $i++) { +// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); +// } +// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); +// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); +// +// $form_question['delmonth'] = array( +// 'name' => 'delmonth', +// 'type' => 'select', +// 'label' => $langs->trans('DelMonth'), +// 'values' => $month_array, +// 'default' => '' +// ); +// $form_question['delyear'] = array( +// 'name' => 'delyear', +// 'type' => 'select', +// 'label' => $langs->trans('DelYear'), +// 'values' => $year_array, +// 'default' => $delyear +// ); +// $form_question['deljournal'] = array( +// 'name' => 'deljournal', +// 'type' => 'other', // We don't use select here, the journal_array is already a select html component +// 'label' => $langs->trans('DelJournal'), +// 'value' => $journal_array, +// 'default' => $deljournal +// ); +// +// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300); +//} + +// Print form confirm +print $formconfirm; + +// List of mass actions available +$arrayofmassactions = array(); +if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) { + $arrayofmassactions['lettering'] = img_picto('', 'check', 'class="pictofixedwidth"') . $langs->trans('Lettering'); + $arrayofmassactions['preunlettering'] = img_picto('', 'uncheck', 'class="pictofixedwidth"') . $langs->trans('Unlettering'); } -if ($action == 'delbookkeepingyear') { - $form_question = array(); - $delyear = GETPOST('delyear', 'int'); - $deljournal = GETPOST('deljournal', 'alpha'); - - if (empty($delyear)) { - $delyear = dol_print_date(dol_now(), '%Y'); - } - $month_array = array(); - for ($i = 1; $i <= 12; $i++) { - $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); - } - $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); - $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); - - $form_question['delmonth'] = array( - 'name' => 'delmonth', - 'type' => 'select', - 'label' => $langs->trans('DelMonth'), - 'values' => $month_array, - 'default' => '' - ); - $form_question['delyear'] = array( - 'name' => 'delyear', - 'type' => 'select', - 'label' => $langs->trans('DelYear'), - 'values' => $year_array, - 'default' => $delyear - ); - $form_question['deljournal'] = array( - 'name' => 'deljournal', - 'type' => 'other', // We don't use select here, the journal_array is already a select html component - 'label' => $langs->trans('DelJournal'), - 'value' => $journal_array, - 'default' => $deljournal - ); - - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300); - print $formconfirm; +if ($user->rights->accounting->mouvements->supprimer) { + $arrayofmassactions['predeletebookkeepingwriting'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } - +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('preunlettering', 'predeletebookkeepingwriting'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions); print '
'; print ''; @@ -469,15 +594,22 @@ if ($optioncss != '') { print ''; } print ''; +print ''; print ''; print ''; +print ''; $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); + if ($type == 'sub') { + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + } else { + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + } $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'); } @@ -488,11 +620,29 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } -print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); +print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); + +if ($massaction == 'preunlettering') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassUnlettering"), $langs->trans("ConfirmMassUnletteringQuestion", count($toselect)), "unlettering", null, '', 0, 200, 500, 1); +} elseif ($massaction == 'predeletebookkeepingwriting') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDeleteBookkeepingWriting"), $langs->trans("ConfirmMassDeleteBookkeepingWritingQuestion", count($toselect)), "deletebookkeepingwriting", null, '', 0, 200, 500, 1); +} +//DeleteMvt=Supprimer des lignes d'opérations de la comptabilité +//DelMonth=Mois à effacer +//DelYear=Année à supprimer +//DelJournal=Journal à supprimer +//ConfirmDeleteMvt=Cette action supprime les lignes des opérations pour l'année/mois et/ou pour le journal sélectionné (au moins un critère est requis). Vous devrez utiliser de nouveau la fonctionnalité '%s' pour retrouver vos écritures dans la comptabilité. +//ConfirmDeleteMvtPartial=Cette action supprime l'écriture de la comptabilité (toutes les lignes opérations liées à une même écriture seront effacées). + +//$topicmail = "Information"; +//$modelmail = "accountingbookkeeping"; +//$objecttmp = new BookKeeping($db); +//$trackid = 'bk'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -if ($massactionbutton) { +if ($massactionbutton && $contextpage != 'poslist') { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -509,9 +659,17 @@ $moreforfilter = ''; $moreforfilter .= '
'; $moreforfilter .= $langs->trans('AccountAccounting').': '; $moreforfilter .= '
'; -$moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200'); +if ($type == 'sub') { + $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200'); +} else { + $moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200'); +} $moreforfilter .= ' '; -$moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200'); +if ($type == 'sub') { + $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200'); +} else { + $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200'); +} $moreforfilter .= '
'; $moreforfilter .= '
'; @@ -599,6 +757,11 @@ if (!empty($arrayfields['t.date_validated']['checked'])) { print ''; print ''; } +if (!empty($arrayfields['t.import_key']['checked'])) { + print ''; + print ''; + print ''; +} // Fields from hook $parameters = array('arrayfields'=>$arrayfields); @@ -643,6 +806,9 @@ if (!empty($arrayfields['t.date_export']['checked'])) { if (!empty($arrayfields['t.date_validated']['checked'])) { print_liste_field_titre($arrayfields['t.date_validated']['label'], $_SERVER['PHP_SELF'], "t.date_validated", "", $param, '', $sortfield, $sortorder, 'center '); } +if (!empty($arrayfields['t.import_key']['checked'])) { + print_liste_field_titre($arrayfields['t.import_key']['label'], $_SERVER["PHP_SELF"], "t.import_key", "", $param, '', $sortfield, $sortorder, 'center '); +} // Hook fields $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook @@ -667,7 +833,11 @@ while ($i < min($num, $limit)) { $total_debit += $line->debit; $total_credit += $line->credit; - $accountg = length_accountg($line->numero_compte); + if ($type == 'sub') { + $accountg = length_accounta($line->subledger_account); + } else { + $accountg = length_accountg($line->numero_compte); + } //if (empty($accountg)) $accountg = '-'; $colspan = 0; // colspan before field 'label of operation' @@ -686,7 +856,11 @@ while ($i < min($num, $limit)) { // Show a subtotal by accounting account if (isset($displayed_account_number)) { print ''; - print ''.$langs->trans("TotalForAccount").' '.length_accountg($displayed_account_number).':'; + if ($type == 'sub') { + print '' . $langs->trans("TotalForAccount") . ' ' . length_accounta($displayed_account_number) . ':'; + } else { + print '' . $langs->trans("TotalForAccount") . ' ' . length_accountg($displayed_account_number) . ':'; + } print ''.price($sous_total_debit).''; print ''.price($sous_total_credit).''; print ''; @@ -712,11 +886,28 @@ while ($i < min($num, $limit)) { // Show the break account print ''; - print ''; - if ($line->numero_compte != "" && $line->numero_compte != '-1') { - print length_accountg($line->numero_compte).' : '.$object->get_compte_desc($line->numero_compte); + print ''; + if ($type == 'sub') { + if ($line->subledger_account != "" && $line->subledger_account != '-1') { + print $line->subledger_label . ' : ' . length_accounta($line->subledger_account); + } else { + // Should not happen: subledger account must be null or a non empty value + print '' . $langs->trans("Unknown"); + if ($line->subledger_label) { + print ' (' . $line->subledger_label . ')'; + $htmltext = 'EmptyStringForSubledgerAccountButSubledgerLabelDefined'; + } else { + $htmltext = 'EmptyStringForSubledgerAccountAndSubledgerLabel'; + } + print $form->textwithpicto('', $htmltext); + print ''; + } } else { - print ''.$langs->trans("Unknown").''; + if ($line->numero_compte != "" && $line->numero_compte != '-1') { + print length_accountg($line->numero_compte) . ' : ' . $object->get_compte_desc($line->numero_compte); + } else { + print '' . $langs->trans("Unknown") . ''; + } } print ''; print ''; @@ -890,22 +1081,26 @@ while ($i < min($num, $limit)) { } } + if (!empty($arrayfields['t.import_key']['checked'])) { + print ''.$line->import_key."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj); + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$line); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column print ''; - if (empty($line->date_export) && empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->creer) { - print '' . img_edit() . ''; - } - } - if (empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->supprimer) { - print ''.img_delete().''; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($line->id, $arrayofselected)) { + $selected = 1; } + print ''; } print ''; if (!$i) { @@ -955,11 +1150,11 @@ print ""; print ''; // TODO Replace this with mass delete action -if ($user->rights->accounting->mouvements->supprimer_tous) { - print '
'."\n"; - print ''.$langs->trans("DeleteMvt").''; - print '
'; -} +//if ($user->rights->accounting->mouvements->supprimer_tous) { +// print '
'."\n"; +// print ''.$langs->trans("DeleteMvt").''; +// print '
'; +//} print '
'; diff --git a/htdocs/accountancy/bookkeeping/listbysubaccount.php b/htdocs/accountancy/bookkeeping/listbysubaccount.php deleted file mode 100644 index c6fb95d5ab7..00000000000 --- a/htdocs/accountancy/bookkeeping/listbysubaccount.php +++ /dev/null @@ -1,979 +0,0 @@ - - * Copyright (C) 2013-2016 Olivier Geffroy - * Copyright (C) 2013-2020 Florian Henry - * Copyright (C) 2013-2021 Alexandre Spangaro - * Copyright (C) 2018-2020 Frédéric France - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file htdocs/accountancy/bookkeeping/listbysubaccount.php - * \ingroup Accountancy (Double entries) - * \brief List operation of ledger ordered by subaccount number - */ - -require '../../main.inc.php'; - -require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; -require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; - -// Load translation files required by the page -$langs->loadLangs(array("accountancy", "compta")); - -$action = GETPOST('action', 'aZ09'); -$search_date_startyear = GETPOST('search_date_startyear', 'int'); -$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); -$search_date_startday = GETPOST('search_date_startday', 'int'); -$search_date_endyear = GETPOST('search_date_endyear', 'int'); -$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); -$search_date_endday = GETPOST('search_date_endday', 'int'); -$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); -$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); -$search_doc_date = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int')); -$search_date_export_startyear = GETPOST('search_date_export_startyear', 'int'); -$search_date_export_startmonth = GETPOST('search_date_export_startmonth', 'int'); -$search_date_export_startday = GETPOST('search_date_export_startday', 'int'); -$search_date_export_endyear = GETPOST('search_date_export_endyear', 'int'); -$search_date_export_endmonth = GETPOST('search_date_export_endmonth', 'int'); -$search_date_export_endday = GETPOST('search_date_export_endday', 'int'); -$search_date_export_start = dol_mktime(0, 0, 0, $search_date_export_startmonth, $search_date_export_startday, $search_date_export_startyear); -$search_date_export_end = dol_mktime(23, 59, 59, $search_date_export_endmonth, $search_date_export_endday, $search_date_export_endyear); -$search_date_validation_startyear = GETPOST('search_date_validation_startyear', 'int'); -$search_date_validation_startmonth = GETPOST('search_date_validation_startmonth', 'int'); -$search_date_validation_startday = GETPOST('search_date_validation_startday', 'int'); -$search_date_validation_endyear = GETPOST('search_date_validation_endyear', 'int'); -$search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', 'int'); -$search_date_validation_endday = GETPOST('search_date_validation_endday', 'int'); -$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear); -$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); - -$search_accountancy_code = GETPOST("search_accountancy_code"); -$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); -if ($search_accountancy_code_start == - 1) { - $search_accountancy_code_start = ''; -} -$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha'); -if ($search_accountancy_code_end == - 1) { - $search_accountancy_code_end = ''; -} -$search_doc_ref = GETPOST('search_doc_ref', 'alpha'); -$search_label_operation = GETPOST('search_label_operation', 'alpha'); -$search_mvt_num = GETPOST('search_mvt_num', 'int'); -$search_direction = GETPOST('search_direction', 'alpha'); -$search_ledger_code = GETPOST('search_ledger_code', 'array'); -$search_debit = GETPOST('search_debit', 'alpha'); -$search_credit = GETPOST('search_credit', 'alpha'); -$search_lettering_code = GETPOST('search_lettering_code', 'alpha'); -$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha'); - -if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) { - $action = 'delbookkeepingyear'; -} - -// Load variable for pagination -$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST('sortorder', 'aZ09comma'); -$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -if (empty($page) || $page < 0) { - $page = 0; -} -$offset = $limit * $page; -$pageprev = $page - 1; -$pagenext = $page + 1; -if ($sortorder == "") { - $sortorder = "ASC"; -} -if ($sortfield == "") { - $sortfield = "t.doc_date,t.rowid"; -} - -// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context -$object = new BookKeeping($db); -$formfile = new FormFile($db); -$hookmanager->initHooks(array('bookkeepingbysubaccountlist')); - -$formaccounting = new FormAccounting($db); -$form = new Form($db); - -if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('search_date_startday') && !GETPOSTISSET('search_date_startmonth') && !GETPOSTISSET('search_date_starthour')) { - $sql = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear "; - $sql .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."'"; - $sql .= $db->plimit(1); - $res = $db->query($sql); - - if ($res->num_rows > 0) { - $fiscalYear = $db->fetch_object($res); - $search_date_start = strtotime($fiscalYear->date_start); - $search_date_end = strtotime($fiscalYear->date_end); - } else { - $month_start = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1); - $year_start = dol_print_date(dol_now(), '%Y'); - if (dol_print_date(dol_now(), '%m') < $month_start) { - $year_start--; // If current month is lower that starting fiscal month, we start last year - } - $year_end = $year_start + 1; - $month_end = $month_start - 1; - if ($month_end < 1) { - $month_end = 12; - $year_end--; - } - $search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start); - $search_date_end = dol_get_last_day($year_end, $month_end); - } -} - -$arrayfields = array( - // 't.subledger_account'=>array('label'=>$langs->trans("SubledgerAccount"), 'checked'=>1), - 't.piece_num'=>array('label'=>$langs->trans("TransactionNumShort"), 'checked'=>1), - 't.code_journal'=>array('label'=>$langs->trans("Codejournal"), 'checked'=>1), - 't.doc_date'=>array('label'=>$langs->trans("Docdate"), 'checked'=>1), - 't.doc_ref'=>array('label'=>$langs->trans("Piece"), 'checked'=>1), - 't.label_operation'=>array('label'=>$langs->trans("Label"), 'checked'=>1), - 't.debit'=>array('label'=>$langs->trans("Debit"), 'checked'=>1), - 't.credit'=>array('label'=>$langs->trans("Credit"), 'checked'=>1), - 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1), - 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), - 't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1), -); - -if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { - unset($arrayfields['t.lettering_code']); -} - -if ($search_date_start && empty($search_date_startyear)) { - $tmparray = dol_getdate($search_date_start); - $search_date_startyear = $tmparray['year']; - $search_date_startmonth = $tmparray['mon']; - $search_date_startday = $tmparray['mday']; -} -if ($search_date_end && empty($search_date_endyear)) { - $tmparray = dol_getdate($search_date_end); - $search_date_endyear = $tmparray['year']; - $search_date_endmonth = $tmparray['mon']; - $search_date_endday = $tmparray['mday']; -} - -if (empty($conf->accounting->enabled)) { - accessforbidden(); -} -if ($user->socid > 0) { - accessforbidden(); -} -if (empty($user->rights->accounting->mouvements->lire)) { - accessforbidden(); -} - - -/* - * Action - */ - -if (GETPOST('cancel', 'alpha')) { - $action = 'list'; $massaction = ''; -} -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { - $massaction = ''; -} - -$parameters = array('socid'=>$socid); -$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks -if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -} - -if (empty($reshook)) { - include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; - - if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers - $search_doc_date = ''; - $search_accountancy_code = ''; - $search_accountancy_code_start = ''; - $search_accountancy_code_end = ''; - $search_label_account = ''; - $search_doc_ref = ''; - $search_label_operation = ''; - $search_mvt_num = ''; - $search_direction = ''; - $search_ledger_code = array(); - $search_date_start = ''; - $search_date_end = ''; - $search_date_startyear = ''; - $search_date_startmonth = ''; - $search_date_startday = ''; - $search_date_endyear = ''; - $search_date_endmonth = ''; - $search_date_endday = ''; - $search_date_export_start = ''; - $search_date_export_end = ''; - $search_date_export_startyear = ''; - $search_date_export_startmonth = ''; - $search_date_export_startday = ''; - $search_date_export_endyear = ''; - $search_date_export_endmonth = ''; - $search_date_export_endday = ''; - $search_date_validation_start = ''; - $search_date_validation_end = ''; - $search_date_validation_startyear = ''; - $search_date_validation_startmonth = ''; - $search_date_validation_startday = ''; - $search_date_validation_endyear = ''; - $search_date_validation_endmonth = ''; - $search_date_validation_endday = ''; - $search_debit = ''; - $search_credit = ''; - $search_lettering_code = ''; - $search_not_reconciled = ''; - } - - // Must be after the remove filter action, before the export. - $param = ''; - $filter = array(); - - if (!empty($search_date_start)) { - $filter['t.doc_date>='] = $search_date_start; - $param .= '&search_date_startmonth='.$search_date_startmonth.'&search_date_startday='.$search_date_startday.'&search_date_startyear='.$search_date_startyear; - } - if (!empty($search_date_end)) { - $filter['t.doc_date<='] = $search_date_end; - $param .= '&search_date_endmonth='.$search_date_endmonth.'&search_date_endday='.$search_date_endday.'&search_date_endyear='.$search_date_endyear; - } - if (!empty($search_doc_date)) { - $filter['t.doc_date'] = $search_doc_date; - $param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int'); - } - if (!empty($search_accountancy_code_start)) { - $filter['t.subledger_account>='] = $search_accountancy_code_start; - $param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start); - } - if (!empty($search_accountancy_code_end)) { - $filter['t.subledger_account<='] = $search_accountancy_code_end; - $param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end); - } - if (!empty($search_label_account)) { - $filter['t.label_compte'] = $search_label_account; - $param .= '&search_label_compte='.urlencode($search_label_account); - } - if (!empty($search_mvt_num)) { - $filter['t.piece_num'] = $search_mvt_num; - $param .= '&search_mvt_num='.urlencode($search_mvt_num); - } - if (!empty($search_doc_ref)) { - $filter['t.doc_ref'] = $search_doc_ref; - $param .= '&search_doc_ref='.urlencode($search_doc_ref); - } - if (!empty($search_label_operation)) { - $filter['t.label_operation'] = $search_label_operation; - $param .= '&search_label_operation='.urlencode($search_label_operation); - } - if (!empty($search_direction)) { - $filter['t.sens'] = $search_direction; - $param .= '&search_direction='.urlencode($search_direction); - } - if (!empty($search_ledger_code)) { - $filter['t.code_journal'] = $search_ledger_code; - foreach ($search_ledger_code as $code) { - $param .= '&search_ledger_code[]='.urlencode($code); - } - } - if (!empty($search_debit)) { - $filter['t.debit'] = $search_debit; - $param .= '&search_debit='.urlencode($search_debit); - } - if (!empty($search_credit)) { - $filter['t.credit'] = $search_credit; - $param .= '&search_credit='.urlencode($search_credit); - } - if (!empty($search_lettering_code)) { - $filter['t.lettering_code'] = $search_lettering_code; - $param .= '&search_lettering_code='.urlencode($search_lettering_code); - } - if (!empty($search_not_reconciled)) { - $filter['t.reconciled_option'] = $search_not_reconciled; - $param .= '&search_not_reconciled='.urlencode($search_not_reconciled); - } - if (!empty($search_date_export_start)) { - $filter['t.date_export>='] = $search_date_export_start; - $param .= '&search_date_export_startmonth='.$search_date_export_startmonth.'&search_date_export_startday='.$search_date_export_startday.'&search_date_export_startyear='.$search_date_export_startyear; - } - if (!empty($search_date_export_end)) { - $filter['t.date_export<='] = $search_date_export_end; - $param .= '&search_date_export_endmonth='.$search_date_export_endmonth.'&search_date_export_endday='.$search_date_export_endday.'&search_date_export_endyear='.$search_date_export_endyear; - } - if (!empty($search_date_validation_start)) { - $filter['t.date_validated>='] = $search_date_validation_start; - $param .= '&search_date_validation_startmonth='.$search_date_validation_startmonth.'&search_date_validation_startday='.$search_date_validation_startday.'&search_date_validation_startyear='.$search_date_validation_startyear; - } - if (!empty($search_date_validation_end)) { - $filter['t.date_validated<='] = $search_date_validation_end; - $param .= '&search_date_validation_endmonth='.$search_date_validation_endmonth.'&search_date_validation_endday='.$search_date_validation_endday.'&search_date_validation_endyear='.$search_date_validation_endyear; - } -} - -if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) { - $import_key = GETPOST('importkey', 'alpha'); - - if (!empty($import_key)) { - $result = $object->deleteByImportkey($import_key); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } - - // Make a redirect to avoid to launch the delete later after a back button - header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); - exit; - } -} -if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) { - $delmonth = GETPOST('delmonth', 'int'); - $delyear = GETPOST('delyear', 'int'); - if ($delyear == -1) { - $delyear = 0; - } - $deljournal = GETPOST('deljournal', 'alpha'); - if ($deljournal == -1) { - $deljournal = 0; - } - - if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { - $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages("RecordDeleted", null, 'mesgs'); - } - - // Make a redirect to avoid to launch the delete later after a back button - header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); - exit; - } else { - setEventMessages("NoRecordDeleted", null, 'warnings'); - } -} -if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) { - $mvt_num = GETPOST('mvt_num', 'int'); - - if (!empty($mvt_num)) { - $result = $object->deleteMvtNum($mvt_num); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); - } - - header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : '')); - exit; - } -} - - -/* - * View - */ - -$formaccounting = new FormAccounting($db); -$formfile = new FormFile($db); -$formother = new FormOther($db); -$form = new Form($db); - -$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('.$langs->trans("BookkeepingSubAccount").')'; - -llxHeader('', $title_page); - -// List -$nbtotalofrecords = ''; -if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1); - if ($nbtotalofrecords < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } -} - -$result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1); - -if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); -} - -$num = count($object->lines); - - -if ($action == 'delmouv') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1); - print $formconfirm; -} -if ($action == 'delbookkeepingyear') { - $form_question = array(); - $delyear = GETPOST('delyear', 'int'); - $deljournal = GETPOST('deljournal', 'alpha'); - - if (empty($delyear)) { - $delyear = dol_print_date(dol_now(), '%Y'); - } - $month_array = array(); - for ($i = 1; $i <= 12; $i++) { - $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); - } - $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); - $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); - - $form_question['delmonth'] = array( - 'name' => 'delmonth', - 'type' => 'select', - 'label' => $langs->trans('DelMonth'), - 'values' => $month_array, - 'default' => '' - ); - $form_question['delyear'] = array( - 'name' => 'delyear', - 'type' => 'select', - 'label' => $langs->trans('DelYear'), - 'values' => $year_array, - 'default' => $delyear - ); - $form_question['deljournal'] = array( - 'name' => 'deljournal', - 'type' => 'other', // We don't use select here, the journal_array is already a select html component - 'label' => $langs->trans('DelJournal'), - 'value' => $journal_array, - 'default' => $deljournal - ); - - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300); - print $formconfirm; -} - - -print '
'; -print ''; -print ''; -if ($optioncss != '') { - print ''; -} -print ''; -print ''; -print ''; - -$parameters = array(); -$reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook -if (empty($reshook)) { - $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); - $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'); -} - -if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { - $param .= '&contextpage='.urlencode($contextpage); -} -if ($limit > 0 && $limit != $conf->liste_limit) { - $param .= '&limit='.urlencode($limit); -} - -print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); - -print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded")); - -$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -if ($massactionbutton) { - $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); -} - -// Reverse sort order -if (preg_match('/^asc/i', $sortorder)) { - $sortorder = "asc"; -} else { - $sortorder = "desc"; -} - -$moreforfilter = ''; - -// Accountancy account -$moreforfilter .= '
'; -$moreforfilter .= $langs->trans('AccountAccounting').': '; -$moreforfilter .= '
'; -$moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200'); -$moreforfilter .= ' '; -$moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200'); -$moreforfilter .= '
'; -$moreforfilter .= '
'; - -$parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook -if (empty($reshook)) { - $moreforfilter .= $hookmanager->resPrint; -} else { - $moreforfilter = $hookmanager->resPrint; -} - -print '
'; -print $moreforfilter; -print '
'; - -print '
'; -print ''; - -// Filters lines -print ''; - -// Movement number -if (!empty($arrayfields['t.piece_num']['checked'])) { - print ''; -} -// Code journal -if (!empty($arrayfields['t.code_journal']['checked'])) { - print ''; -} -// Date document -if (!empty($arrayfields['t.doc_date']['checked'])) { - print ''; -} -// Ref document -if (!empty($arrayfields['t.doc_ref']['checked'])) { - print ''; -} -// Label operation -if (!empty($arrayfields['t.label_operation']['checked'])) { - print ''; -} -// Debit -if (!empty($arrayfields['t.debit']['checked'])) { - print ''; -} -// Credit -if (!empty($arrayfields['t.credit']['checked'])) { - print ''; -} -// Lettering code -if (!empty($arrayfields['t.lettering_code']['checked'])) { - print ''; -} -// Date export -if (!empty($arrayfields['t.date_export']['checked'])) { - print ''; -} -// Date validation -if (!empty($arrayfields['t.date_validated']['checked'])) { - print ''; -} - -// Fields from hook -$parameters = array('arrayfields'=>$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook -print $hookmanager->resPrint; - -// Action column -print ''; -print "\n"; - -print ''; -if (!empty($arrayfields['t.piece_num']['checked'])) { - print_liste_field_titre($arrayfields['t.piece_num']['label'], $_SERVER['PHP_SELF'], "t.piece_num", "", $param, '', $sortfield, $sortorder); -} -if (!empty($arrayfields['t.code_journal']['checked'])) { - print_liste_field_titre($arrayfields['t.code_journal']['label'], $_SERVER['PHP_SELF'], "t.code_journal", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['t.doc_date']['checked'])) { - print_liste_field_titre($arrayfields['t.doc_date']['label'], $_SERVER['PHP_SELF'], "t.doc_date", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['t.doc_ref']['checked'])) { - print_liste_field_titre($arrayfields['t.doc_ref']['label'], $_SERVER['PHP_SELF'], "t.doc_ref", "", $param, "", $sortfield, $sortorder); -} -if (!empty($arrayfields['t.label_operation']['checked'])) { - print_liste_field_titre($arrayfields['t.label_operation']['label'], $_SERVER['PHP_SELF'], "t.label_operation", "", $param, "", $sortfield, $sortorder); -} -if (!empty($arrayfields['t.debit']['checked'])) { - print_liste_field_titre($arrayfields['t.debit']['label'], $_SERVER['PHP_SELF'], "t.debit", "", $param, '', $sortfield, $sortorder, 'right '); -} -if (!empty($arrayfields['t.credit']['checked'])) { - print_liste_field_titre($arrayfields['t.credit']['label'], $_SERVER['PHP_SELF'], "t.credit", "", $param, '', $sortfield, $sortorder, 'right '); -} -if (!empty($arrayfields['t.lettering_code']['checked'])) { - print_liste_field_titre($arrayfields['t.lettering_code']['label'], $_SERVER['PHP_SELF'], "t.lettering_code", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['t.date_export']['checked'])) { - print_liste_field_titre($arrayfields['t.date_export']['label'], $_SERVER['PHP_SELF'], "t.date_export", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['t.date_validated']['checked'])) { - print_liste_field_titre($arrayfields['t.date_validated']['label'], $_SERVER['PHP_SELF'], "t.date_validated", "", $param, '', $sortfield, $sortorder, 'center '); -} -// Hook fields -$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); -$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook -print $hookmanager->resPrint; -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); -print "\n"; - - -$total_debit = 0; -$total_credit = 0; -$sous_total_debit = 0; -$sous_total_credit = 0; -$displayed_account_number = null; // Start with undefined to be able to distinguish with empty - -// Loop on record -// -------------------------------------------------------------------- -$i = 0; -$totalarray = array(); -while ($i < min($num, $limit)) { - $line = $object->lines[$i]; - - $total_debit += $line->debit; - $total_credit += $line->credit; - - $accountg = length_accounta($line->subledger_account); - //if (empty($accountg)) $accountg = '-'; - - $colspan = 0; // colspan before field 'label of operation' - $colspanend = 3; // colspan after debit/credit - if (!empty($arrayfields['t.piece_num']['checked'])) { $colspan++; } - if (!empty($arrayfields['t.code_journal']['checked'])) { $colspan++; } - if (!empty($arrayfields['t.doc_date']['checked'])) { $colspan++; } - if (!empty($arrayfields['t.doc_ref']['checked'])) { $colspan++; } - if (!empty($arrayfields['t.label_operation']['checked'])) { $colspan++; } - if (!empty($arrayfields['t.date_export']['checked'])) { $colspanend++; } - if (!empty($arrayfields['t.date_validating']['checked'])) { $colspanend++; } - if (!empty($arrayfields['t.lettering_code']['checked'])) { $colspanend++; } - - // Is it a break ? - if ($accountg != $displayed_account_number || !isset($displayed_account_number)) { - // Show a subtotal by accounting account - if (isset($displayed_account_number)) { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - // Show balance of last shown account - $balance = $sous_total_debit - $sous_total_credit; - print ''; - print ''; - if ($balance > 0) { - print ''; - print ''; - } else { - print ''; - print ''; - } - print ''; - print ''; - } - - // Show the break account - print ''; - print ''; - print ''; - - $displayed_account_number = $accountg; - //if (empty($displayed_account_number)) $displayed_account_number='-'; - $sous_total_debit = 0; - $sous_total_credit = 0; - - $colspan = 0; - } - - print ''; - - // Piece number - if (!empty($arrayfields['t.piece_num']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Journal code - if (!empty($arrayfields['t.code_journal']['checked'])) { - $accountingjournal = new AccountingJournal($db); - $result = $accountingjournal->fetch('', $line->code_journal); - $journaltoshow = (($result > 0) ? $accountingjournal->getNomUrl(0, 0, 0, '', 0) : $line->code_journal); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Document date - if (!empty($arrayfields['t.doc_date']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Document ref - if (!empty($arrayfields['t.doc_ref']['checked'])) { - if ($line->doc_type == 'customer_invoice') { - $langs->loadLangs(array('bills')); - - require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; - $objectstatic = new Facture($db); - $objectstatic->fetch($line->fk_doc); - //$modulepart = 'facture'; - - $filename = dol_sanitizeFileName($line->doc_ref); - $filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id; - $documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); - } elseif ($line->doc_type == 'supplier_invoice') { - $langs->loadLangs(array('bills')); - - require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; - $objectstatic = new FactureFournisseur($db); - $objectstatic->fetch($line->fk_doc); - //$modulepart = 'invoice_supplier'; - - $filename = dol_sanitizeFileName($line->doc_ref); - $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($line->fk_doc, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); - $subdir = get_exdir($objectstatic->id, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); - $documentlink = $formfile->getDocumentsLink($objectstatic->element, $subdir, $filedir); - } elseif ($line->doc_type == 'expense_report') { - $langs->loadLangs(array('trips')); - - require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; - $objectstatic = new ExpenseReport($db); - $objectstatic->fetch($line->fk_doc); - //$modulepart = 'expensereport'; - - $filename = dol_sanitizeFileName($line->doc_ref); - $filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id; - $documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); - } elseif ($line->doc_type == 'bank') { - require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; - $objectstatic = new AccountLine($db); - $objectstatic->fetch($line->fk_doc); - } else { - // Other type - } - - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label operation - if (!empty($arrayfields['t.label_operation']['checked'])) { - // Affiche un lien vers la facture client/fournisseur - $doc_ref = preg_replace('/\(.*\)/', '', $line->doc_ref); - print strlen(length_accounta($line->subledger_account)) == 0 ? '' : ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Amount debit - if (!empty($arrayfields['t.debit']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totaldebit'; - } - $totalarray['val']['totaldebit'] += $line->debit; - } - - // Amount credit - if (!empty($arrayfields['t.credit']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalcredit'; - } - $totalarray['val']['totalcredit'] += $line->credit; - } - - // Lettering code - if (!empty($arrayfields['t.lettering_code']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Exported operation date - if (!empty($arrayfields['t.date_export']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Validated operation date - if (!empty($arrayfields['t.date_validated']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - - // Action column - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - // Comptabilise le sous-total - $sous_total_debit += $line->debit; - $sous_total_credit += $line->credit; - - print "\n"; - - $i++; -} - -if ($num > 0 && $colspan > 0) { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - // Show balance of last shown account - $balance = $sous_total_debit - $sous_total_credit; - print ''; - print ''; - if ($balance > 0) { - print ''; - print ''; - } else { - print ''; - print ''; - } - print ''; - print ''; -} - -// Show total line -include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; - - -print "
'; - print $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1); - print ''; - print '
'; - print $form->selectDate($search_date_start, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); - print '
'; - print '
'; - print $form->selectDate($search_date_end, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); - print '
'; - print '
'; - print ''; - print '
'.$langs->trans("NotReconciled").''; - print '
'; - print '
'; - print $form->selectDate($search_date_export_start, 'search_date_export_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); - print '
'; - print '
'; - print $form->selectDate($search_date_export_end, 'search_date_export_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); - print '
'; - print '
'; - print '
'; - print $form->selectDate($search_date_validation_start, 'search_date_validation_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); - print '
'; - print '
'; - print $form->selectDate($search_date_validation_end, 'search_date_validation_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); - print '
'; - print '
'; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print '
'.$langs->trans("TotalForAccount").' '.length_accounta($displayed_account_number).':'.price($sous_total_debit).''.price($sous_total_credit).'
'.$langs->trans("Balance").':'; - print price($sous_total_debit - $sous_total_credit); - print ''; - print price($sous_total_credit - $sous_total_debit); - print '
'; - if ($line->subledger_account != "" && $line->subledger_account != '-1') { - print $line->subledger_label.' : '.length_accounta($line->subledger_account); - } else { - // Should not happen: subledger account must be null or a non empty value - print ''.$langs->trans("Unknown"); - if ($line->subledger_label) { - print ' ('.$line->subledger_label.')'; - $htmltext = 'EmptyStringForSubledgerAccountButSubledgerLabelDefined'; - } else { - $htmltext = 'EmptyStringForSubledgerAccountAndSubledgerLabel'; - } - print $form->textwithpicto('', $htmltext); - print ''; - } - print '
'; - $object->id = $line->id; - $object->piece_num = $line->piece_num; - print $object->getNomUrl(1, '', 0, '', 1); - print ''.$journaltoshow.''.dol_print_date($line->doc_date, 'day').''; - - print ''; - // Picto + Ref - print '
'; - - if ($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice' || $line->doc_type == 'expense_report') { - print $objectstatic->getNomUrl(1, '', 0, 0, '', 0, -1, 1); - print $documentlink; - } elseif ($line->doc_type == 'bank') { - print $objectstatic->getNomUrl(1); - $bank_ref = strstr($line->doc_ref, '-'); - print " " . $bank_ref; - } else { - print $line->doc_ref; - } - print '
'; - - print "
'.$line->label_operation.''.$line->label_operation.'
('.length_accounta($line->subledger_account).')
'.($line->debit ? price($line->debit) : '').''.($line->credit ? price($line->credit) : '').''.$line->lettering_code.''.dol_print_date($line->date_export, 'dayhour').''.dol_print_date($line->date_validation, 'dayhour').''; - if (empty($line->date_export) && empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->creer) { - print '' . img_edit() . ''; - } - } - if (empty($line->date_validation)) { - if ($user->rights->accounting->mouvements->supprimer) { - print ''.img_delete().''; - } - } - print '
'.$langs->trans("TotalForAccount").' '.$accountg.':'.price($sous_total_debit).''.price($sous_total_credit).'
'.$langs->trans("Balance").':'; - print price($sous_total_debit - $sous_total_credit); - print ''; - print price($sous_total_credit - $sous_total_debit); - print '
"; -print '
'; - -// TODO Replace this with mass delete action -if ($user->rights->accounting->mouvements->supprimer_tous) { - print '
'."\n"; - print ''.$langs->trans("DeleteMvt").''; - print '
'; -} - -print '
'; - -// End of page -llxFooter(); -$db->close(); diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index a83a311010d..21b723b003b 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -852,7 +852,8 @@ class BookKeeping extends CommonObject $sql .= " t.piece_num,"; $sql .= " t.date_creation,"; $sql .= " t.date_export,"; - $sql .= " t.date_validated as date_validation"; + $sql .= " t.date_validated as date_validation,"; + $sql .= " t.import_key"; // Manage filter $sqlwhere = array(); if (count($filter) > 0) { @@ -947,6 +948,7 @@ class BookKeeping extends CommonObject $line->date_creation = $this->db->jdate($obj->date_creation); $line->date_export = $this->db->jdate($obj->date_export); $line->date_validation = $this->db->jdate($obj->date_validation); + $line->import_key = $obj->import_key; $this->lines[] = $line; diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index f722a716b79..a31a4675851 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -33,6 +33,12 @@ include_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php"; */ class Lettering extends BookKeeping { + /** + * @var BookKeeping[] Bookkeeping cached + */ + public static $bookkeeping_cached = array(); + + /** * letteringThirdparty * @@ -119,6 +125,7 @@ class Lettering extends BookKeeping $ids[$obj2->rowid] = $obj2->rowid; $ids_fact[] = $obj2->fact_id; } + $this->db->free($resql2); } else { $this->errors[] = $this->db->lasterror; return -1; @@ -146,6 +153,7 @@ class Lettering extends BookKeeping while ($obj2 = $this->db->fetch_object($resql2)) { $ids[$obj2->rowid] = $obj2->rowid; } + $this->db->free($resql2); } else { $this->errors[] = $this->db->lasterror; return -1; @@ -205,6 +213,7 @@ class Lettering extends BookKeeping while ($obj2 = $this->db->fetch_object($resql2)) { $ids[$obj2->rowid] = $obj2->rowid; } + $this->db->free($resql2); } else { $this->errors[] = $this->db->lasterror; return -1; @@ -216,6 +225,7 @@ class Lettering extends BookKeeping $result = $this->updateLettering($ids); } } + $this->db->free($resql); } if ($error) { foreach ($this->errors as $errmsg) { @@ -230,17 +240,31 @@ class Lettering extends BookKeeping /** * - * @param array $ids ids array - * @param boolean $notrigger no trigger - * @return number + * @param array $ids ids array + * @param boolean $notrigger no trigger + * @return int */ public function updateLettering($ids = array(), $notrigger = false) { $error = 0; $lettre = 'AAA'; - $sql = "SELECT DISTINCT lettering_code FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE "; - $sql .= " lettering_code != '' ORDER BY lettering_code DESC limit 1"; + $sql = "SELECT DISTINCT ab2.lettering_code" . + " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping As ab" . + " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc" . + " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu2 ON bu2.url_id = bu.url_id" . + " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab2 ON ab2.fk_doc = bu2.fk_bank" . + " WHERE ab.rowid IN (" . $this->db->sanitize(implode(',', $ids)) . ")" . + " AND ab.doc_type = 'bank'" . + " AND ab2.doc_type = 'bank'" . + " AND bu.type = 'company'" . + " AND bu2.type = 'company'" . + " AND ab.subledger_account != ''" . + " AND ab2.subledger_account != ''" . + " AND ab.lettering_code IS NULL" . + " AND ab2.lettering_code != ''" . + " ORDER BY ab2.lettering_code DESC" . + " LIMIT 1 "; $result = $this->db->query($sql); if ($result) { @@ -249,13 +273,14 @@ class Lettering extends BookKeeping if (!empty($obj->lettering_code)) { $lettre++; } + $this->db->free($result); } else { $this->errors[] = 'Error'.$this->db->lasterror(); $error++; } $sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE "; - $sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL"; + $sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''"; $result = $this->db->query($sql); if ($result) { $obj = $this->db->fetch_object($result); @@ -263,6 +288,7 @@ class Lettering extends BookKeeping $this->errors[] = 'Total not exacts '.round(abs($obj->deb), 2).' vs '.round(abs($obj->cred), 2); $error++; } + $this->db->free($result); } else { $this->errors[] = 'Erreur sql'.$this->db->lasterror(); $error++; @@ -276,8 +302,7 @@ class Lettering extends BookKeeping $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET"; $sql .= " lettering_code='".$this->db->escape($lettre)."'"; $sql .= " , date_lettering = '".$this->db->idate($now)."'"; // todo correct date it's false - $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL "; - $this->db->begin(); + $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''"; dol_syslog(get_class($this)."::update", LOG_DEBUG); $resql = $this->db->query($sql); @@ -293,11 +318,422 @@ class Lettering extends BookKeeping dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR); $this->error .= ($this->error ? ', '.$errmsg : $errmsg); } - $this->db->rollback(); return -1 * $error; } else { - $this->db->commit(); return 1; } } + + /** + * + * @param array $ids ids array + * @param boolean $notrigger no trigger + * @return int + */ + public function deleteLettering($ids, $notrigger = false) + { + $error = 0; + + $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET"; + $sql .= " lettering_code = NULL"; + $sql .= " , date_lettering = NULL"; + $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).")"; + $sql .= " AND subledger_account != ''"; + + dol_syslog(get_class($this)."::update", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = "Error ".$this->db->lasterror(); + } + + // Commit or rollback + if ($error) { + foreach ($this->errors as $errmsg) { + dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR); + $this->error .= ($this->error ? ', '.$errmsg : $errmsg); + } + return -1 * $error; + } else { + return 1; + } + } + + /** + * Lettering bookkeeping lines all types + * + * @param array $bookkeeping_ids Lettering specific list of bookkeeping id + * @param bool $unlettering Do unlettering + * @return int <0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered) + */ + public function bookkeepingLetteringAll($bookkeeping_ids, $unlettering = false) + { + dol_syslog(__METHOD__ . " - ", LOG_DEBUG); + + $error = 0; + $errors = array(); + $nb_lettering = 0; + + $result = $this->bookkeepingLettering($bookkeeping_ids, 'customer_invoice', $unlettering); + if ($result < 0) { + $error++; + $errors = array_merge($errors, $this->errors); + $nb_lettering += abs($result) - 2; + } else { + $nb_lettering += $result; + } + + $result = $this->bookkeepingLettering($bookkeeping_ids, 'supplier_invoice', $unlettering); + if ($result < 0) { + $error++; + $errors = array_merge($errors, $this->errors); + $nb_lettering += abs($result) - 2; + } else { + $nb_lettering += $result; + } + + if ($error) { + $this->errors = $errors; + return -2 - $nb_lettering; + } else { + return $nb_lettering; + } + } + + /** + * Lettering bookkeeping lines + * + * @param array $bookkeeping_ids Lettering specific list of bookkeeping id + * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice') + * @param bool $unlettering Do unlettering + * @return int <0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered) + */ + public function bookkeepingLettering($bookkeeping_ids, $type = 'customer_invoice', $unlettering = false) + { + global $langs; + + $this->errors = array(); + + // Clean parameters + $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array(); + $type = trim($type); + + $error = 0; + $nb_lettering = 0; + $grouped_lines = $this->getLinkedLines($bookkeeping_ids, $type); + foreach ($grouped_lines as $lines) { + $group_error = 0; + $total = 0; + $do_it = !$unlettering; + $lettering_code = null; + $piece_num_lines = array(); + $bookkeeping_lines = array(); + foreach ($lines as $line_infos) { + $bookkeeping_lines[$line_infos['id']] = $line_infos['id']; + $piece_num_lines[$line_infos['piece_num']] = $line_infos['piece_num']; + $total += ($line_infos['credit'] > 0 ? $line_infos['credit'] : -$line_infos['debit']); + + // Check lettering code + if ($unlettering) { + if (isset($lettering_code) && $lettering_code != $line_infos['lettering_code']) { + $this->errors[] = $langs->trans('AccountancyErrorMismatchLetteringCode'); + $group_error++; + break; + } + if (!isset($lettering_code)) $lettering_code = (string)$line_infos['lettering_code']; + if (!empty($line_infos['lettering_code'])) $do_it = true; + } elseif (!empty($line_infos['lettering_code'])) $do_it = false; + } + + // Check balance amount + if (!$group_error && !$unlettering && price2num($total) != 0) { + $this->errors[] = $langs->trans('AccountancyErrorMismatchBalanceAmount', $total); + $group_error++; + } + + // Lettering/Unlettering the group of bookkeeping lines + if (!$group_error && $do_it) { + if ($unlettering) $result = $this->deleteLettering($bookkeeping_lines); + else $result = $this->updateLettering($bookkeeping_lines); + if ($result < 0) { + $group_error++; + } else { + $nb_lettering++; + } + } + + if ($group_error) { + $this->errors[] = $langs->trans('AccountancyErrorLetteringBookkeeping', implode(', ', $piece_num_lines)); + $error++; + } + } + + if ($error) { + return -2 - $nb_lettering; + } else { + return $nb_lettering; + } + } + + /** + * Lettering bookkeeping lines + * + * @param array $bookkeeping_ids Lettering specific list of bookkeeping id + * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice') + * @return array|int <0 if error otherwise all linked lines by block + */ + public function getLinkedLines($bookkeeping_ids, $type = 'customer_invoice') + { + global $conf, $langs; + $this->errors = array(); + + // Clean parameters + $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array(); + $type = trim($type); + + if ($type == 'customer_invoice') { + $doc_type = 'customer_invoice'; + $bank_url_type = 'payment'; + $payment_element = 'paiement_facture'; + $fk_payment_element = 'fk_paiement'; + $fk_element = 'fk_facture'; + $account_number = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER; + } elseif ($type == 'supplier_invoice') { + $doc_type = 'supplier_invoice'; + $bank_url_type = 'payment_supplier'; + $payment_element = 'paiementfourn_facturefourn'; + $fk_payment_element = 'fk_paiementfourn'; + $fk_element = 'fk_facturefourn'; + $account_number = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER; + } else { + $langs->load('errors'); + $this->errors[] = $langs->trans('ErrorBadParameters'); + return -1; + } + + $payment_ids = array(); + + // Get all payment id from bank lines + $sql = "SELECT DISTINCT bu.url_id AS payment_id" . + " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . + " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc" . + " WHERE ab.doc_type = 'bank'" . + // " AND ab.subledger_account != ''" . + // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . + " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; + if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; + + dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = "Error " . $this->db->lasterror(); + return -1; + } + + while ($obj = $this->db->fetch_object($resql)) { + $payment_ids[$obj->payment_id] = $obj->payment_id; + } + $this->db->free($resql); + + // Get all payment id from payment lines + $sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id" . + " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . + " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc" . + " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'" . + // " AND ab.subledger_account != ''" . + // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . + " AND pe.$fk_payment_element IS NOT NULL"; + if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; + + dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = "Error " . $this->db->lasterror(); + return -1; + } + + while ($obj = $this->db->fetch_object($resql)) { + $payment_ids[$obj->payment_id] = $obj->payment_id; + } + $this->db->free($resql); + + if (empty($payment_ids)) { + return array(); + } + + // Get all payments linked by group + $payment_by_group = $this->getLinkedPaymentByGroup($payment_ids, $type); + + $groups = array(); + foreach ($payment_by_group as $payment_list) { + $lines = array(); + + // Get bank lines + $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit" . + " FROM " . MAIN_DB_PREFIX . "bank_url AS bu" . + " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank" . + " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")" . + " AND bu.type = '" . $this->db->escape($bank_url_type) . "'" . + " AND ab.doc_type = 'bank'" . + " AND ab.subledger_account != ''" . + " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + + dol_syslog(__METHOD__ . " - Get bank lines", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = "Error " . $this->db->lasterror(); + return -1; + } + + while ($obj = $this->db->fetch_object($resql)) { + $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit); + } + $this->db->free($resql); + + // Get payment lines + $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit" . + " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe" . + " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element" . + " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")" . + " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'" . + " AND ab.subledger_account != ''" . + " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + + dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = "Error " . $this->db->lasterror(); + return -1; + } + + while ($obj = $this->db->fetch_object($resql)) { + $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit); + } + $this->db->free($resql); + + if (!empty($lines)) { + $groups[] = $lines; + } + } + + return $groups; + } + + public function getLinkedPaymentByGroup($payment_ids, $type) + { + global $langs; + + // Clean parameters + $payment_ids = is_array($payment_ids) ? $payment_ids : array(); + $type = trim($type); + + if (empty($payment_ids)) { + return array(); + } + + if ($type == 'customer_invoice') { + $payment_element = 'paiement_facture'; + $fk_payment_element = 'fk_paiement'; + $fk_element = 'fk_facture'; + } elseif ($type == 'supplier_invoice') { + $payment_element = 'paiementfourn_facturefourn'; + $fk_payment_element = 'fk_paiementfourn'; + $fk_element = 'fk_facturefourn'; + } else { + $langs->load('errors'); + $this->errors[] = $langs->trans('ErrorBadParameters'); + return -1; + } + + // Get payment lines + $sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element" . + " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe" . + " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element" . + " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")"; + + dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = "Error " . $this->db->lasterror(); + return -1; + } + + $current_payment_ids = array(); + $payment_by_element = array(); + $element_by_payment = array(); + while ($obj = $this->db->fetch_object($resql)) { + $current_payment_ids[$obj->$fk_payment_element] = $obj->$fk_payment_element; + $element_by_payment[$obj->$fk_payment_element][$obj->$fk_element] = $obj->$fk_element; + $payment_by_element[$obj->$fk_element][$obj->$fk_payment_element] = $obj->$fk_payment_element; + } + $this->db->free($resql); + + if (count(array_diff($payment_ids, $current_payment_ids))) { + return $this->getLinkedPaymentByGroup($current_payment_ids, $type); + } + + return $this->getGroupElements($payment_by_element, $element_by_payment); + } + + /** + * Get payment ids grouped by payment id and element id in common + * + * @param array &$payment_by_element List of payment ids by element id + * @param array &$element_by_payment List of element ids by payment id + * @param int $element_id Element Id (used for recursive function) + * @param array &$current_group Current group (used for recursive function) + * @return array List of payment ids grouped by payment id and element id in common + */ + public function getGroupElements(&$payment_by_element, &$element_by_payment, $element_id = 0, &$current_group = array()) + { + $grouped_payments = array(); + if ($element_id > 0 && !isset($payment_by_element[$element_id])) { + // Return if specific element id not found + return $grouped_payments; + } + + if ($element_id == 0) { + // Save list when is the begin of recursive function + $save_payment_by_element = $payment_by_element; + $save_element_by_payment = $element_by_payment; + } + + do { + // Get current element id, get this payment id list and delete the entry + $current_element_id = $element_id > 0 ? $element_id : array_keys($payment_by_element)[0]; + $payment_ids = $payment_by_element[$current_element_id]; + unset($payment_by_element[$current_element_id]); + + foreach ($payment_ids as $payment_id) { + // Continue if payment id in not found + if (!isset($element_by_payment[$payment_id])) continue; + + // Set the payment in the current group + $current_group[$payment_id] = $payment_id; + + // Get current element ids, get this payment id list and delete the entry + $element_ids = $element_by_payment[$payment_id]; + unset($element_by_payment[$payment_id]); + + // Set payment id on the current group for each element id of the payment + foreach ($element_ids as $id) { + $this->getGroupElements($payment_by_element, $element_by_payment, $id, $current_group); + } + } + + if ($element_id == 0) { + // Save current group and reset the current group when is the begin of recursive function + $grouped_payments[] = $current_group; + $current_group = array(); + } + } while(!empty($payment_by_element) && $element_id == 0); + + if ($element_id == 0) { + // Restore list when is the begin of recursive function + $payment_by_element = $save_payment_by_element; + $element_by_payment = $save_element_by_payment; + } + + return $grouped_payments; + } } diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 4841b8bf171..8a02ac3849a 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -665,6 +665,8 @@ if (!$error && $action == 'writebookkeeping') { // Line into thirdparty account foreach ($tabtp[$key] as $k => $mt) { if ($mt) { + $lettering = false; + $reflabel = ''; if (!empty($val['lib'])) { $reflabel .= dol_string_nohtmltag($val['lib']).($val['soclib'] ? " - " : ""); @@ -693,11 +695,13 @@ if (!$error && $action == 'writebookkeeping') { $bookkeeping->date_creation = $now; if ($tabtype[$key] == 'payment') { // If payment is payment of customer invoice, we get ref of invoice + $lettering = true; $bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp $bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER; $bookkeeping->label_compte = $accountingaccountcustomer->label; } elseif ($tabtype[$key] == 'payment_supplier') { // If payment is payment of supplier invoice, we get ref of invoice + $lettering = true; $bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp $bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER; @@ -780,6 +784,12 @@ if (!$error && $action == 'writebookkeeping') { $errorforline++; setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } + } else { + if ($lettering && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; + $lettering_static = new Lettering($db); + $nb_lettering = $lettering_static->bookkeepingLetteringAll(array($bookkeeping->id)); + } } } } diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index 8b1ac0d3de3..7c0a8b90f7d 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -377,6 +377,12 @@ if ($action == 'writebookkeeping') { $errorforinvoice[$key] = 'other'; setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } + } else { + if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; + $lettering_static = new Lettering($db); + $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id), 'supplier_invoice'); + } } } } diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 7a5ccd79b21..7cc7f0effbc 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -390,6 +390,12 @@ if ($action == 'writebookkeeping') { $errorforinvoice[$key] = 'other'; setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } + } else { + if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; + $lettering_static = new Lettering($db); + $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id), 'customer_invoice'); + } } } } diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index fd5ff8461fe..b3088e4427e 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -395,6 +395,21 @@ Range=Range of accounting account Calculated=Calculated Formula=Formula +## Reconcile +Unlettering=Unreconcile +AccountancyNoLetteringModified=No reconcile modified +AccountancyOneLetteringModifiedSuccessfully=One reconcile successfully modified +AccountancyLetteringModifiedSuccessfully=%s reconcile successfully modified +AccountancyNoUnletteringModified=No unreconcile modified +AccountancyOneUnletteringModifiedSuccessfully=One unreconcile successfully modified +AccountancyUnletteringModifiedSuccessfully=%s unreconcile successfully modified + +## Confirm box +ConfirmMassUnlettering=Bulk Unreconcile confirmation +ConfirmMassUnletteringQuestion=Are you sure you want to Unreconcile the %s selected record(s)? +ConfirmMassDeleteBookkeepingWriting=Bulk Delete confirmation +ConfirmMassDeleteBookkeepingWritingQuestion=This will delete the transaction from the accounting (all lines related to the same transaction will be deleted) Are you sure you want to delete the %s selected record(s)? + ## Error SomeMandatoryStepsOfSetupWereNotDone=Some mandatory steps of setup was not done, please complete them ErrorNoAccountingCategoryForThisCountry=No accounting account group available for country %s (See Home - Setup - Dictionaries) @@ -407,6 +422,9 @@ Binded=Lines bound ToBind=Lines to bind UseMenuToSetBindindManualy=Lines not yet bound, use menu %s to make the binding manually SorryThisModuleIsNotCompatibleWithTheExperimentalFeatureOfSituationInvoices=Sorry this module is not compatible with the experimental feature of situation invoices +AccountancyErrorMismatchLetterCode=Mismatch in reconcile code +AccountancyErrorMismatchBalanceAmount=The balance (%s) is not equal to 0 +AccountancyErrorLetteringBookkeeping=Errors have occurred concerning the transactions: %s ## Import ImportAccountingEntries=Accounting entries From 0c8a6bd6f017bfe2ab899fa74f71659df437392d Mon Sep 17 00:00:00 2001 From: melina Date: Thu, 28 Apr 2022 08:39:02 +0200 Subject: [PATCH 208/473] fix commit --- htdocs/takepos/ajax/ajax.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 9afde9ba341..0de7cb857a6 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -218,7 +218,7 @@ if ($action == 'getProducts') { // Add tables from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); + $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); $sql .= $hookmanager->resPrint; $sql .= ' WHERE entity IN ('.getEntity('product').')'; @@ -229,7 +229,7 @@ if ($action == 'getProducts') { $sql .= natural_search(array('ref', 'label', 'barcode'), $term); // Add where from hooks $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); + $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); $sql .= $hookmanager->resPrint; $resql = $db->query($sql); @@ -269,9 +269,11 @@ if ($action == 'getProducts') { ); // Add entries to row from hooks $parameters=array(); - $parameters['row'] = end($rows); + $parameters['row'] = $row; $parameters['obj'] = $obj; - $reshook=$hookmanager->executeHooks('completeAjaxReturnArray', $parameters); + $hookmanager->executeHooks('completeAjaxReturnArray', $parameters); + if (!empty($hookmanager->resArray)) $row = $hookmanager->resArray; + $rows[] = $row; } echo json_encode($rows); } else { From f634d7e50384faa0a1df4bd4f2eacb0fb97f7814 Mon Sep 17 00:00:00 2001 From: melina Date: Thu, 28 Apr 2022 08:42:44 +0200 Subject: [PATCH 209/473] fix commit --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 0de7cb857a6..13956794f18 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -254,7 +254,7 @@ if ($action == 'getProducts') { } } - $rows[] = array( + $row = array( 'rowid' => $obj->rowid, 'ref' => $obj->ref, 'label' => $obj->label, From be2502c29f2d69db2dea3972c58e1ae4a889afdd Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Thu, 28 Apr 2022 10:50:55 +0200 Subject: [PATCH 210/473] New : module webhook database structure --- .../mysql/tables/llx_webhook_target.key.sql | 27 ++++++++++++++ .../mysql/tables/llx_webhook_target.sql | 36 +++++++++++++++++++ .../llx_webhook_target_extrafields.key.sql | 19 ++++++++++ .../tables/llx_webhook_target_extrafields.sql | 23 ++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 htdocs/install/mysql/tables/llx_webhook_target.key.sql create mode 100644 htdocs/install/mysql/tables/llx_webhook_target.sql create mode 100644 htdocs/install/mysql/tables/llx_webhook_target_extrafields.key.sql create mode 100644 htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql diff --git a/htdocs/install/mysql/tables/llx_webhook_target.key.sql b/htdocs/install/mysql/tables/llx_webhook_target.key.sql new file mode 100644 index 00000000000..04a0dbb306a --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target.key.sql @@ -0,0 +1,27 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_rowid (rowid); +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_ref (ref); +ALTER TABLE llx_webhook_target ADD CONSTRAINT llx_webhook_target_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_status (status); +-- END MODULEBUILDER INDEXES + +--ALTER TABLE llx_webhook_target ADD UNIQUE INDEX uk_webhook_target_fieldxy(fieldx, fieldy); + +--ALTER TABLE llx_webhook_target ADD CONSTRAINT llx_webhook_target_fk_field FOREIGN KEY (fk_field) REFERENCES llx_webhook_myotherobject(rowid); + diff --git a/htdocs/install/mysql/tables/llx_webhook_target.sql b/htdocs/install/mysql/tables/llx_webhook_target.sql new file mode 100644 index 00000000000..f9a6b61d489 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target.sql @@ -0,0 +1,36 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +CREATE TABLE llx_webhook_target( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + label varchar(255), + description text, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + last_main_doc varchar(255), + import_key varchar(14), + model_pdf varchar(255), + status integer NOT NULL, + url varchar(255) NOT NULL, + trigger_codes text NOT NULL + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_webhook_target_extrafields.key.sql b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.key.sql new file mode 100644 index 00000000000..c8ebcf12bdc --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.key.sql @@ -0,0 +1,19 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_webhook_target_extrafields ADD INDEX idx_target_fk_object(fk_object); +-- END MODULEBUILDER INDEXES diff --git a/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql new file mode 100644 index 00000000000..0af3a1fadda --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql @@ -0,0 +1,23 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +create table llx_webhook_target_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + From 729d1f57aaa1757470b0a855fec3eebbc4949619 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 28 Apr 2022 10:53:16 +0200 Subject: [PATCH 211/473] fix select fields --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index a3bcc04b5c8..ff2cbd65d51 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -208,7 +208,7 @@ if ($action == 'getProducts') { } } - $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price' ; + $sql = 'SELECT p.rowid, p.ref, p.label, p.tosell, p.tobuy, p.barcode, p.price' ; // Add fields from hooks $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook From d376d285888cec7ade770db59a9a032d0aefa831 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 11:12:21 +0200 Subject: [PATCH 212/473] Missing trans --- htdocs/langs/en_US/users.lang | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 888c9f52161..5bfbec87294 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -123,4 +123,8 @@ ForceUserHolidayValidator=Force leave request validator ValidatorIsSupervisorByDefault=By default, the validator is the supervisor of the user. Keep empty to keep this behaviour. UserPersonalEmail=Personal email UserPersonalMobile=Personal mobile phone -WarningNotLangOfInterface=Warning, this is the main language the user speak, not the language of the interface he choosed to see. To change the interface language visible by this user, go on tab %s \ No newline at end of file +WarningNotLangOfInterface=Warning, this is the main language the user speak, not the language of the interface he choosed to see. To change the interface language visible by this user, go on tab %s +DateLastLogin=Date last login +DatePreviousLogin=Date previous login +IPLastLogin=IP last login +IPPreviousLogin=IP previous login From fc6228a48ca487560c112c0d754f5c7b461b8fa2 Mon Sep 17 00:00:00 2001 From: IC-faycal Date: Thu, 28 Apr 2022 11:27:15 +0200 Subject: [PATCH 213/473] NEW Events on Proposal to Return to Draft --- .../triggers/interface_50_modAgenda_ActionsAuto.class.php | 8 ++++++++ htdocs/langs/en_US/agenda.lang | 1 + 2 files changed, 9 insertions(+) diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index cf6a8220c29..187e3f5a156 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -186,6 +186,14 @@ class InterfaceActionsAuto extends DolibarrTriggers } $object->actionmsg = $langs->transnoentities("PropalValidatedInDolibarr", ($object->newref ? $object->newref : $object->ref)); + $object->sendtoid = 0; + } elseif ($action == 'PROPAL_MODIFY') { + // Load translation files required by the page + $langs->loadLangs(array("agenda", "other", "propal")); + + if (empty($object->actionmsg2)) $object->actionmsg2 = $langs->transnoentities("PropalBackToDraftInDolibarr", ($object->newref ? $object->newref : $object->ref)); + $object->actionmsg = $langs->transnoentities("PropalBackToDraftInDolibarr", ($object->newref ? $object->newref : $object->ref)); + $object->sendtoid = 0; } elseif ($action == 'PROPAL_SENTBYMAIL') { // Load translation files required by the page diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index bc9c7dab537..73bb8d92346 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -45,6 +45,7 @@ CONTRACT_DELETEInDolibarr=Contract %s deleted PropalClosedSignedInDolibarr=Proposal %s signed PropalClosedRefusedInDolibarr=Proposal %s refused PropalValidatedInDolibarr=Proposal %s validated +PropalBackToDraftInDolibarr=Proposal %s go back to draft status PropalClassifiedBilledInDolibarr=Proposal %s classified billed InvoiceValidatedInDolibarr=Invoice %s validated InvoiceValidatedInDolibarrFromPos=Invoice %s validated from POS From ed4610b36bde8878574d0ab4922627f37f443717 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 28 Apr 2022 11:45:55 +0200 Subject: [PATCH 214/473] FIX : Move column "Real Qty" just before "Real PMP" column --- htdocs/product/inventory/inventory.php | 48 +++++++++++++++++--------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 204c6539c29..f7691193e24 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -910,15 +910,17 @@ if ($object->id > 0) { print ''; } print ''.$langs->trans("ExpectedQty").''; - print ''; - print $form->textwithpicto($langs->trans("RealQty"), $langs->trans("InventoryRealQtyHelp")); - print ''; if (!empty($conf->global->INVENTORY_MANAGE_REAL_PMP)) { print ''.$langs->trans('PMPExpected').''; print ''.$langs->trans('ExpectedValuation').''; + print ''.$form->textwithpicto($langs->trans("RealQty"), $langs->trans("InventoryRealQtyHelp")).''; print ''.$langs->trans('PMPReal').''; print ''.$langs->trans('RealValuation').''; - } + } else { + print ''; + print $form->textwithpicto($langs->trans("RealQty"), $langs->trans("InventoryRealQtyHelp")); + print ''; + } if ($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) { // Actions or link to stock movement print ''; @@ -1041,7 +1043,6 @@ if ($object->id > 0) { // Real quantity if ($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) { - print ''; $qty_view = GETPOST("id_".$obj->rowid) && price2num(GETPOST("id_".$obj->rowid), 'MS') >= 0 ? GETPOST("id_".$obj->rowid) : $obj->qty_view; //if (!$hasinput && $qty_view !== null && $obj->qty_stock != $qty_view) { @@ -1049,11 +1050,6 @@ if ($object->id > 0) { $hasinput = true; } - print ''; - print img_picto('', 'eraser', 'class="opacitymedium"'); - print ''; - print ''; - print ''; if (! empty($conf->global->INVENTORY_MANAGE_REAL_PMP)) { //PMP Expected if (! empty($obj->pmp_expected)) $pmp_expected = $obj->pmp_expected; @@ -1066,6 +1062,14 @@ if ($object->id > 0) { print ''; print price($pmp_valuation); print ''; + + print ''; + print ''; + print img_picto('', 'eraser', 'class="opacitymedium"'); + print ''; + print ''; + print ''; + //PMP Real print ''; @@ -1081,18 +1085,22 @@ if ($object->id > 0) { $totalExpectedValuation += $pmp_valuation; $totalRealValuation += $pmp_valuation_real; - } + } else { + print ''; + print ''; + print img_picto('', 'eraser', 'class="opacitymedium"'); + print ''; + print ''; + print ''; + } // Picto delete line print ''; print ''.img_delete().''; $qty_tmp = price2num(GETPOST("id_".$obj->rowid."_input_tmp", 'MS')) >= 0 ? GETPOST("id_".$obj->rowid."_input_tmp") : $qty_view; - print ''; + print ''; print ''; } else { - print ''; - print $obj->qty_view; // qty found - print ''; if (!empty($conf->global->INVENTORY_MANAGE_REAL_PMP)) { //PMP Expected if (! empty($obj->pmp_expected)) $pmp_expected = $obj->pmp_expected; @@ -1105,6 +1113,10 @@ if ($object->id > 0) { print price($pmp_valuation); print ''; + print ''; + print $obj->qty_view; // qty found + print ''; + //PMP Real print ''; if (! empty($obj->pmp_real)) $pmp_real = $obj->pmp_real; @@ -1119,7 +1131,11 @@ if ($object->id > 0) { $totalExpectedValuation += $pmp_valuation; $totalRealValuation += $pmp_valuation_real; - } + } else { + print ''; + print $obj->qty_view; // qty found + print ''; + } if ($obj->fk_movement > 0) { $stockmovment = new MouvementStock($db); $stockmovment->fetch($obj->fk_movement); From 701960bd70654bf643d07d5c53f829cb175e6d85 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Thu, 28 Apr 2022 11:47:13 +0200 Subject: [PATCH 215/473] try to fix build fail --- htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql index 0af3a1fadda..a01ac0e1d1c 100644 --- a/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql +++ b/htdocs/install/mysql/tables/llx_webhook_target_extrafields.sql @@ -16,7 +16,7 @@ create table llx_webhook_target_extrafields ( rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_object integer NOT NULL, import_key varchar(14) -- import key ) ENGINE=innodb; From 75f540c30cde44d9dc1eef300f44c319e29e7205 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 28 Apr 2022 11:49:15 +0200 Subject: [PATCH 216/473] fix for reshook when several module use the hook but only on is concerned --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bb411d530c7..1bacf75c7d2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1810,7 +1810,7 @@ class Product extends CommonObject // Note that $action and $object may have been modified by some hooks global $action; $reshook = $hookmanager->executeHooks('getSellPrice', $parameters, $this, $action); - if ( ! empty($reshook)) { + if ( ! empty($hookmanager->resArray)) { return $hookmanager->resArray; } From f0e65e8bdd259ba8aedc4cbc0d9a74e4a95833fd Mon Sep 17 00:00:00 2001 From: lainwir3d Date: Thu, 14 Apr 2022 00:37:26 +0400 Subject: [PATCH 217/473] FIX #20733 Inventory: Do not use batch qty even if present if batch module is disabled. --- htdocs/product/inventory/class/inventory.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index bb55bc1b143..c506204d3f0 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -306,9 +306,14 @@ class Inventory extends CommonObject $inventoryline->fk_warehouse = $obj->fk_warehouse; $inventoryline->fk_product = $obj->fk_product; $inventoryline->batch = $obj->batch; - $inventoryline->qty_stock = ($obj->batch ? $obj->qty : $obj->reel); // If there is batch detail, we take qty for batch, else global qty $inventoryline->datec = dol_now(); + if ($conf->productbatch->enabled) { + $inventoryline->qty_stock = ($obj->batch ? $obj->qty : $obj->reel); // If there is batch detail, we take qty for batch, else global qty + }else{ + $inventoryline->qty_stock = $obj->reel; + } + $resultline = $inventoryline->create($user); if ($resultline <= 0) { $this->error = $inventoryline->error; From 6ab88d0169572afbee05f63e8c41979260a62691 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 28 Apr 2022 10:09:02 +0000 Subject: [PATCH 218/473] Fixing style errors. --- htdocs/product/inventory/class/inventory.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index c506204d3f0..f49b262bc13 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -310,7 +310,7 @@ class Inventory extends CommonObject if ($conf->productbatch->enabled) { $inventoryline->qty_stock = ($obj->batch ? $obj->qty : $obj->reel); // If there is batch detail, we take qty for batch, else global qty - }else{ + } else { $inventoryline->qty_stock = $obj->reel; } From 900caf5a443910fa4d3f98ff329b30115909c853 Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Thu, 28 Apr 2022 12:12:20 +0200 Subject: [PATCH 219/473] Fix missing budget export --- htdocs/core/modules/modProjet.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index 791442dab1c..b97aad1b149 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -222,7 +222,7 @@ class modProjet extends DolibarrModules 's.phone'=>'Text', 's.email'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 's.code_compta'=>'Text', 's.code_compta_fournisseur'=>'Text', 'p.rowid'=>"List:projet:ref::project", 'p.ref'=>"Text", 'p.title'=>"Text", 'p.usage_opportunity'=>'Boolean', 'p.usage_task'=>'Boolean', 'p.usage_bill_time'=>'Boolean', - 'p.datec'=>"Date", 'p.dateo'=>"Date", 'p.datee'=>"Date", 'p.fk_statut'=>'Status', 'cls.code'=>"Text", 'p.opp_percent'=>'Numeric', 'p.opp_amount'=>'Numeric', 'p.description'=>"Text", 'p.entity'=>'Numeric', + 'p.datec'=>"Date", 'p.dateo'=>"Date", 'p.datee'=>"Date", 'p.fk_statut'=>'Status', 'cls.code'=>"Text", 'p.opp_percent'=>'Numeric', 'p.opp_amount'=>'Numeric', 'p.description'=>"Text", 'p.entity'=>'Numeric', 'p.budget_amount'=>'Numeric', 'pt.rowid'=>'Numeric', 'pt.ref'=>'Text', 'pt.label'=>'Text', 'pt.dateo'=>"Date", 'pt.datee'=>"Date", 'pt.duration_effective'=>"Duree", 'pt.planned_workload'=>"Numeric", 'pt.progress'=>"Numeric", 'pt.description'=>"Text", 'ptt.rowid'=>'Numeric', 'ptt.task_date'=>'Date', 'ptt.task_duration'=>"Duree", 'ptt.fk_user'=>"List:user:CONCAT(lastname,' ',firstname)", 'ptt.note'=>"Text" ); @@ -235,7 +235,7 @@ class modProjet extends DolibarrModules 's.phone'=>'Phone', 's.email'=>'Email', 's.siren'=>'ProfId1', 's.siret'=>'ProfId2', 's.ape'=>'ProfId3', 's.idprof4'=>'ProfId4', 's.code_compta'=>'CustomerAccountancyCode', 's.code_compta_fournisseur'=>'SupplierAccountancyCode', 'p.rowid'=>"ProjectId", 'p.ref'=>"RefProject", 'p.title'=>'ProjectLabel', 'p.usage_opportunity'=>'ProjectFollowOpportunity', 'p.usage_task'=>'ProjectFollowTasks', 'p.usage_bill_time'=>'BillTime', - 'p.datec'=>"DateCreation", 'p.dateo'=>"DateStart", 'p.datee'=>"DateEnd", 'p.fk_statut'=>'ProjectStatus', 'cls.code'=>'OpportunityStatus', 'p.opp_percent'=>'OpportunityProbability', 'p.opp_amount'=>'OpportunityAmount', 'p.description'=>"Description" + 'p.datec'=>"DateCreation", 'p.dateo'=>"DateStart", 'p.datee'=>"DateEnd", 'p.fk_statut'=>'ProjectStatus', 'cls.code'=>'OpportunityStatus', 'p.opp_percent'=>'OpportunityProbability', 'p.opp_amount'=>'OpportunityAmount', 'p.budget_amount'=>'Budget', 'p.description'=>"Description" ); // Add multicompany field if (!empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) From b35b40649f575f1d4f90c56c63b7c55125443037 Mon Sep 17 00:00:00 2001 From: lainwir3d Date: Thu, 28 Apr 2022 15:42:49 +0400 Subject: [PATCH 220/473] CLOSE #20736 Allow extrafields SQL filters on REST API product lookup --- htdocs/product/class/api_products.class.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index e44aef221f6..c1a387167ec 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -173,9 +173,10 @@ class Products extends DolibarrApi * @param int $variant_filter Use this param to filter list (0 = all, 1=products without variants, 2=parent of variants, 3=variants only) * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0 * @param int $includestockdata Load also information about stock (slower) + * @param bool $allow_extrafields_sqlfilters Allow sqlfilters to contain extrafields filter (slower). * @return array Array of product objects */ - public function index($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $ids_only = false, $variant_filter = 0, $pagination_data = false, $includestockdata = 0) + public function index($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $ids_only = false, $variant_filter = 0, $pagination_data = false, $includestockdata = 0, $allow_extrafields_sqlfilters = false) { global $db, $conf; @@ -192,6 +193,11 @@ class Products extends DolibarrApi if ($category > 0) { $sql .= ", ".$this->db->prefix()."categorie_product as c"; } + + if ($allow_extrafields_sqlfilters) { + $sql .= " LEFT JOIN llx_product_extrafields AS ef ON ef.fk_object = t.rowid"; + } + $sql .= ' WHERE t.entity IN ('.getEntity('product').')'; if ($variant_filter == 1) { From 88bd28323cfe03bccccfdda7b7b6a4e35d6e5548 Mon Sep 17 00:00:00 2001 From: lainwir3d Date: Thu, 28 Apr 2022 16:46:42 +0400 Subject: [PATCH 221/473] FIX #20738 Inventory: Add missing for movement number / card. --- htdocs/product/inventory/inventory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 204c6539c29..dde5248a528 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -1120,6 +1120,7 @@ if ($object->id > 0) { $totalExpectedValuation += $pmp_valuation; $totalRealValuation += $pmp_valuation_real; } + print ''; if ($obj->fk_movement > 0) { $stockmovment = new MouvementStock($db); $stockmovment->fetch($obj->fk_movement); From 68864840b64e25131fe513201dc8e509e03b5410 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 28 Apr 2022 13:25:50 +0000 Subject: [PATCH 222/473] Fixing style errors. --- htdocs/accountancy/class/lettering.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index a31a4675851..39c56d5e3d8 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -440,7 +440,7 @@ class Lettering extends BookKeeping $group_error++; break; } - if (!isset($lettering_code)) $lettering_code = (string)$line_infos['lettering_code']; + if (!isset($lettering_code)) $lettering_code = (string) $line_infos['lettering_code']; if (!empty($line_infos['lettering_code'])) $do_it = true; } elseif (!empty($line_infos['lettering_code'])) $do_it = false; } @@ -518,8 +518,8 @@ class Lettering extends BookKeeping " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc" . " WHERE ab.doc_type = 'bank'" . - // " AND ab.subledger_account != ''" . - // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . + // " AND ab.subledger_account != ''" . + // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; @@ -540,8 +540,8 @@ class Lettering extends BookKeeping " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc" . " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'" . - // " AND ab.subledger_account != ''" . - // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . + // " AND ab.subledger_account != ''" . + // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . " AND pe.$fk_payment_element IS NOT NULL"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; @@ -726,7 +726,7 @@ class Lettering extends BookKeeping $grouped_payments[] = $current_group; $current_group = array(); } - } while(!empty($payment_by_element) && $element_id == 0); + } while (!empty($payment_by_element) && $element_id == 0); if ($element_id == 0) { // Restore list when is the begin of recursive function From 5379db7c6bbfeb25259c5d173183da5de0354348 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 28 Apr 2022 15:49:08 +0200 Subject: [PATCH 223/473] Fix stickler-ci --- htdocs/accountancy/class/lettering.class.php | 98 ++++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index a31a4675851..1532768826d 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -249,22 +249,22 @@ class Lettering extends BookKeeping $error = 0; $lettre = 'AAA'; - $sql = "SELECT DISTINCT ab2.lettering_code" . - " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping As ab" . - " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc" . - " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu2 ON bu2.url_id = bu.url_id" . - " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab2 ON ab2.fk_doc = bu2.fk_bank" . - " WHERE ab.rowid IN (" . $this->db->sanitize(implode(',', $ids)) . ")" . - " AND ab.doc_type = 'bank'" . - " AND ab2.doc_type = 'bank'" . - " AND bu.type = 'company'" . - " AND bu2.type = 'company'" . - " AND ab.subledger_account != ''" . - " AND ab2.subledger_account != ''" . - " AND ab.lettering_code IS NULL" . - " AND ab2.lettering_code != ''" . - " ORDER BY ab2.lettering_code DESC" . - " LIMIT 1 "; + $sql = "SELECT DISTINCT ab2.lettering_code"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping As ab"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu2 ON bu2.url_id = bu.url_id"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab2 ON ab2.fk_doc = bu2.fk_bank"; + $sql .= " WHERE ab.rowid IN (" . $this->db->sanitize(implode(',', $ids)) . ")"; + $sql .= " AND ab.doc_type = 'bank'"; + $sql .= " AND ab2.doc_type = 'bank'"; + $sql .= " AND bu.type = 'company'"; + $sql .= " AND bu2.type = 'company'"; + $sql .= " AND ab.subledger_account != ''"; + $sql .= " AND ab2.subledger_account != ''"; + $sql .= " AND ab.lettering_code IS NULL"; + $sql .= " AND ab2.lettering_code != ''"; + $sql .= " ORDER BY ab2.lettering_code DESC"; + $sql .= " LIMIT 1 "; $result = $this->db->query($sql); if ($result) { @@ -514,13 +514,13 @@ class Lettering extends BookKeeping $payment_ids = array(); // Get all payment id from bank lines - $sql = "SELECT DISTINCT bu.url_id AS payment_id" . - " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . - " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc" . - " WHERE ab.doc_type = 'bank'" . - // " AND ab.subledger_account != ''" . - // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . - " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; + $sql = "SELECT DISTINCT bu.url_id AS payment_id"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc"; + $sql .= " WHERE ab.doc_type = 'bank'"; + // $sql .= " AND ab.subledger_account != ''"; + // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG); @@ -536,13 +536,13 @@ class Lettering extends BookKeeping $this->db->free($resql); // Get all payment id from payment lines - $sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id" . - " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab" . - " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc" . - " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'" . - // " AND ab.subledger_account != ''" . - // " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'" . - " AND pe.$fk_payment_element IS NOT NULL"; + $sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc"; + $sql .= " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'"; + // $sql .= " AND ab.subledger_account != ''"; + // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + $sql .= " AND pe.$fk_payment_element IS NOT NULL"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG); @@ -569,14 +569,14 @@ class Lettering extends BookKeeping $lines = array(); // Get bank lines - $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit" . - " FROM " . MAIN_DB_PREFIX . "bank_url AS bu" . - " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank" . - " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")" . - " AND bu.type = '" . $this->db->escape($bank_url_type) . "'" . - " AND ab.doc_type = 'bank'" . - " AND ab.subledger_account != ''" . - " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit"; + $sql .= " FROM " . MAIN_DB_PREFIX . "bank_url AS bu"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank"; + $sql .= " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")"; + $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; + $sql .= " AND ab.doc_type = 'bank'"; + $sql .= " AND ab.subledger_account != ''"; + $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; dol_syslog(__METHOD__ . " - Get bank lines", LOG_DEBUG); $resql = $this->db->query($sql); @@ -591,13 +591,13 @@ class Lettering extends BookKeeping $this->db->free($resql); // Get payment lines - $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit" . - " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe" . - " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element" . - " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")" . - " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'" . - " AND ab.subledger_account != ''" . - " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit"; + $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element"; + $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")"; + $sql .= " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'"; + $sql .= " AND ab.subledger_account != ''"; + $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG); $resql = $this->db->query($sql); @@ -646,10 +646,10 @@ class Lettering extends BookKeeping } // Get payment lines - $sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element" . - " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe" . - " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element" . - " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")"; + $sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element"; + $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element"; + $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")"; dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG); $resql = $this->db->query($sql); From 5fe448e86cb455bbe629a72e15b63c0a00d9a63a Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 28 Apr 2022 15:49:31 +0200 Subject: [PATCH 224/473] FIX : [inventory] Update PMP when qty stay the same --- htdocs/product/inventory/inventory.php | 39 +++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index f7691193e24..48f9c83513f 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -186,25 +186,6 @@ if (empty($reshook)) { break; } - if (!empty($line->pmp_real) && !empty($conf->global->INVENTORY_MANAGE_REAL_PMP)) { - $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product SET pmp = '.((float) $line->pmp_real).' WHERE rowid = '.((int) $line->fk_product); - $resqlpmp = $db->query($sqlpmp); - if (! $resqlpmp) { - $error++; - setEventMessages($db->lasterror(), null, 'errors'); - break; - } - if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product_perentity SET pmp = '.((float) $line->pmp_real).' WHERE fk_product = '.((int) $line->fk_product).' AND entity='.$conf->entity; - $resqlpmp = $db->query($sqlpmp); - if (! $resqlpmp) { - $error++; - setEventMessages($db->lasterror(), null, 'errors'); - break; - } - } - } - // Update line with id of stock movement (and the start quantity if it has changed this last recording) $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."inventorydet"; $sqlupdate .= " SET fk_movement = ".((int) $idstockmove); @@ -219,6 +200,26 @@ if (empty($reshook)) { break; } } + + if (!empty($line->pmp_real) && !empty($conf->global->INVENTORY_MANAGE_REAL_PMP)) { + $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product SET pmp = '.((float) $line->pmp_real).' WHERE rowid = '.((int) $line->fk_product); + $resqlpmp = $db->query($sqlpmp); + if (! $resqlpmp) { + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + break; + } + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sqlpmp = 'UPDATE '.MAIN_DB_PREFIX.'product_perentity SET pmp = '.((float) $line->pmp_real).' WHERE fk_product = '.((int) $line->fk_product).' AND entity='.$conf->entity; + $resqlpmp = $db->query($sqlpmp); + if (! $resqlpmp) { + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + break; + } + } + } + } $i++; } From 96e247bf8935caa8e4b841bccb40ac1bad3f53be Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 28 Apr 2022 13:55:54 +0000 Subject: [PATCH 225/473] Fixing style errors. --- htdocs/accountancy/class/lettering.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index 2c2c07e7944..a32df04e79a 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -518,8 +518,8 @@ class Lettering extends BookKeeping $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc"; $sql .= " WHERE ab.doc_type = 'bank'"; - // $sql .= " AND ab.subledger_account != ''"; - // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + // $sql .= " AND ab.subledger_account != ''"; + // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; @@ -540,8 +540,8 @@ class Lettering extends BookKeeping $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc"; $sql .= " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'"; - // $sql .= " AND ab.subledger_account != ''"; - // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; + // $sql .= " AND ab.subledger_account != ''"; + // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'"; $sql .= " AND pe.$fk_payment_element IS NOT NULL"; if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")"; From f2d81f97b9687796b342c295cc4a38a2add6662a Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 28 Apr 2022 17:10:30 +0200 Subject: [PATCH 226/473] Comment function --- htdocs/accountancy/class/lettering.class.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index a32df04e79a..58443cfec8d 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -619,6 +619,13 @@ class Lettering extends BookKeeping return $groups; } + /** + * Linked payment by group + * + * @param array $payment_ids list of payment id + * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice') + * @return array|int <0 if error otherwise all linked lines by block + */ public function getLinkedPaymentByGroup($payment_ids, $type) { global $langs; From 7752c5f1221316575b691a529ff049512aa5cb1c Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 28 Apr 2022 17:24:10 +0200 Subject: [PATCH 227/473] Comment function --- htdocs/accountancy/class/lettering.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index 58443cfec8d..a2718973185 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -685,10 +685,10 @@ class Lettering extends BookKeeping /** * Get payment ids grouped by payment id and element id in common * - * @param array &$payment_by_element List of payment ids by element id - * @param array &$element_by_payment List of element ids by payment id + * @param array $payment_by_element List of payment ids by element id + * @param array $element_by_payment List of element ids by payment id * @param int $element_id Element Id (used for recursive function) - * @param array &$current_group Current group (used for recursive function) + * @param array $current_group Current group (used for recursive function) * @return array List of payment ids grouped by payment id and element id in common */ public function getGroupElements(&$payment_by_element, &$element_by_payment, $element_id = 0, &$current_group = array()) From ebe68350d1d2770b0500560fdeda5fe00639745f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 17:34:04 +0200 Subject: [PATCH 228/473] IP for last and previous login is now saved inuser table --- htdocs/user/class/user.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index f01820f93e9..8c61af9ccbb 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -275,6 +275,8 @@ class User extends CommonObject public $datelastlogin; public $datepreviouslogin; + public $iplastlogin; + public $ippreviouslogin; public $datestartvalidity; public $dateendvalidity; @@ -2111,9 +2113,13 @@ class User extends CommonObject // phpcs:enable $now = dol_now(); + $userremoteip = getUserRemoteIP(); + $sql = "UPDATE ".$this->db->prefix()."user SET"; $sql .= " datepreviouslogin = datelastlogin,"; + $sql .= " ippreviouslogin = iplastlogin,"; $sql .= " datelastlogin = '".$this->db->idate($now)."',"; + $sql .= " iplastlogin = '".$this->db->escape($userremoteip)."',"; $sql .= " tms = tms"; // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion $sql .= " WHERE rowid = ".((int) $this->id); @@ -2122,6 +2128,8 @@ class User extends CommonObject if ($resql) { $this->datepreviouslogin = $this->datelastlogin; $this->datelastlogin = $now; + $this->ippreviouslogin = $this->iplastlogin; + $this->iplastlogin = $userremoteip; return 1; } else { $this->error = $this->db->lasterror().' sql='.$sql; @@ -3116,7 +3124,9 @@ class User extends CommonObject $this->datem = $now; $this->datelastlogin = $now; + $this->iplastlogin = '127.0.0.1'; $this->datepreviouslogin = $now; + $this->ippreviouslogin = '127.0.0.1'; $this->statut = 1; $this->entity = 1; From 93815404a27d5d474c578c97e496efdcfc8eb863 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 18:46:52 +0200 Subject: [PATCH 229/473] Fix phpcs --- htdocs/compta/localtax/card.php | 4 ++-- htdocs/compta/paiement_vat.php | 2 +- htdocs/compta/tva/card.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/compta/localtax/card.php b/htdocs/compta/localtax/card.php index 45cb1f03bb8..9bd37eafa36 100644 --- a/htdocs/compta/localtax/card.php +++ b/htdocs/compta/localtax/card.php @@ -177,10 +177,10 @@ if ($action == 'create') { if (!empty($conf->banque->enabled)) { // Type payment print ''.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); + $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype", '', 0, 1, 0, 0, 1, 'maxwidth500 widthcentpercentminusx'); print "\n"; print ""; - + // Bank account print ''.$langs->trans("Account").''; print img_picto('', 'bank_account', 'pictofixedwidth'); diff --git a/htdocs/compta/paiement_vat.php b/htdocs/compta/paiement_vat.php index 2f7b775096d..28bc838c296 100644 --- a/htdocs/compta/paiement_vat.php +++ b/htdocs/compta/paiement_vat.php @@ -207,7 +207,7 @@ if ($action == 'create') { print ''; print ''.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOSTISSET("paiementtype") ? GETPOST("paiementtype", "int") : $tva->paiementtype, "paiementtype", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); + $form->select_types_paiements(GETPOSTISSET("paiementtype") ? GETPOST("paiementtype", "int") : $tva->paiementtype, "paiementtype", '', 0, 1, 0, 0, 1, 'maxwidth500 widthcentpercentminusx'); print "\n"; print ''; diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index 3ffb405f8ad..3a34d71c11d 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -490,7 +490,7 @@ if ($action == 'create') { // Type payment print ''.$langs->trans("PaymentMode").''; - $form->select_types_paiements(GETPOST("type_payment", 'int'), "type_payment", '', 0, 1, 0, 0, 1,'maxwidth500 widthcentpercentminusx'); + $form->select_types_paiements(GETPOST("type_payment", 'int'), "type_payment", '', 0, 1, 0, 0, 1, 'maxwidth500 widthcentpercentminusx'); print "\n"; print ""; From 559694dd4fa70a874f9851c8ef7b79fa517ad6ce Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 19:05:23 +0200 Subject: [PATCH 230/473] API doc --- htdocs/compta/facture/class/api_invoices.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 551edb05731..3623a36cbb9 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -1724,8 +1724,8 @@ class Invoices extends DolibarrApi * * Return an array with invoice informations * - * @param int $id ID of template invoice - * @param int $contact_list 0:Return array contains all properties, 1:Return array contains just id, 1: Return array contains just id, -1: Do not return contacts/adddesses + * @param int $id ID of template invoice + * @param int $contact_list 0:Return array contains all properties, 1:Return array contains just id, -1: Do not return contacts/adddesses * @return array|mixed data without useless information * * @url GET templates/{id} From 3b98f74a56bfbb829050284e5c1e93b0ab0ed21b Mon Sep 17 00:00:00 2001 From: lainwir3d Date: Thu, 28 Apr 2022 22:56:44 +0400 Subject: [PATCH 231/473] Fix typo and switch to old join style. --- htdocs/product/class/api_products.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index c1a387167ec..262d83a0afc 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -195,7 +195,7 @@ class Products extends DolibarrApi } if ($allow_extrafields_sqlfilters) { - $sql .= " LEFT JOIN llx_product_extrafields AS ef ON ef.fk_object = t.rowid"; + $sql .= ", ".MAIN_DB_PREFIX."product_extrafields AS ef"; } $sql .= ' WHERE t.entity IN ('.getEntity('product').')'; @@ -223,6 +223,11 @@ class Products extends DolibarrApi // Show only services $sql .= " AND t.fk_product_type = 1"; } + + if ($allow_extrafields_sqlfilters) { + $sql .= " AND ef.fk_object = t.rowid"; + } + // Add sql filters if ($sqlfilters) { $errormessage = ''; From a129b6d13260cc0c8ac77fa0fc4d9ce2e5183a57 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 22:29:48 +0200 Subject: [PATCH 232/473] FIX phpcs --- htdocs/core/class/rssparser.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/rssparser.class.php b/htdocs/core/class/rssparser.class.php index 2048a80bae6..93224b9f04d 100644 --- a/htdocs/core/class/rssparser.class.php +++ b/htdocs/core/class/rssparser.class.php @@ -230,7 +230,7 @@ class RssParser if (!empty($result['content'])) { $str = $result['content']; - } elseif (!empty($result['curl_error_msg'])){ + } elseif (!empty($result['curl_error_msg'])) { $this->error = 'Error retrieving URL '.$this->_urlRSS.' - '.$result['curl_error_msg']; return -1; } From 822a0a37f3aaf7e649233ef20249311174c5a1f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Apr 2022 22:28:32 +0200 Subject: [PATCH 233/473] Fix phpunit --- htdocs/langs/en_US/admin.lang | 2 +- htdocs/user/class/user.class.php | 4 ++++ test/phpunit/UserTest.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 0009cd00bcf..970426eb488 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2143,7 +2143,7 @@ DeleteEmailCollector=Delete email collector ConfirmDeleteEmailCollector=Are you sure you want to delete this email collector? RecipientEmailsWillBeReplacedWithThisValue=Recipient emails will be always replaced with this value AtLeastOneDefaultBankAccountMandatory=At least 1 default bank account must be defined -RESTRICT_ON_IP=Allow access to some host IP only (wildcard not allowed, use space between values). Empty means every hosts can access. +RESTRICT_ON_IP=Allow API access to only certain client IPs (wildcard not allowed, use space between values). Empty means every clients can access. IPListExample=127.0.0.1 192.168.0.2 [::1] BaseOnSabeDavVersion=Based on the library SabreDAV version NotAPublicIp=Not a public IP diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 8c61af9ccbb..6f10ada3267 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -437,6 +437,8 @@ class User extends CommonObject $sql .= " u.tms as datem,"; $sql .= " u.datelastlogin as datel,"; $sql .= " u.datepreviouslogin as datep,"; + $sql .= " u.iplastlogin,"; + $sql .= " u.ippreviouslogin,"; $sql .= " u.datelastpassvalidation,"; $sql .= " u.datestartvalidity,"; $sql .= " u.dateendvalidity,"; @@ -564,6 +566,8 @@ class User extends CommonObject $this->datem = $this->db->jdate($obj->datem); $this->datelastlogin = $this->db->jdate($obj->datel); $this->datepreviouslogin = $this->db->jdate($obj->datep); + $this->iplastlogin = $obj->iplastlogin; + $this->ippreviouslogin = $obj->ippreviouslogin; $this->datestartvalidity = $this->db->jdate($obj->datestartvalidity); $this->dateendvalidity = $this->db->jdate($obj->dateendvalidity); diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index 699e9fd89f0..c6ccc3b01a0 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -204,7 +204,7 @@ class UserTest extends PHPUnit\Framework\TestCase $newlocalobject=new User($this->savdb); $newlocalobject->initAsSpecimen(); $this->changeProperties($newlocalobject); - $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','trackid')), array()); // Actual, Expected + $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected return $localobject; } From accb900d4f54fbf4f4b9fa2be89bfae4ee94be7d Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 09:45:36 +0200 Subject: [PATCH 234/473] ajax load only one page of search results --- htdocs/takepos/ajax/ajax.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index a3bcc04b5c8..5e0b329676a 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -48,6 +48,8 @@ $category = GETPOST('category', 'alphanohtml'); // Can be id of category or 'sup $action = GETPOST('action', 'aZ09'); $term = GETPOST('term', 'alpha'); $id = GETPOST('id', 'int'); +$search_start = GETPOST('search_start', 'int'); +$search_limit = GETPOST('search_limit', 'int'); if (empty($user->rights->takepos->run)) { accessforbidden(); @@ -232,6 +234,9 @@ if ($action == 'getProducts') { $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; + // load only one page of products + $sql.= ' LIMIT '. $search_start . ',' . $search_limit; + $resql = $db->query($sql); if ($resql) { $rows = array(); From 78f46bb98b13978e27e24811007158eb4ae0ee0e Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 09:49:10 +0200 Subject: [PATCH 235/473] search next or previous page of products if asked --- htdocs/takepos/index.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index b23907b64f1..eab5b12c3c1 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -372,6 +372,9 @@ function LoadProducts(position, issubcat) { function MoreProducts(moreorless) { console.log("MoreProducts"); + + if ($('#search_pagination').val() != '') return Search2('', moreorless); + var maxproduct = ; if (moreorless=="more"){ From fb076a92828e33bc3ec084650bf8157837061f92 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 10:00:25 +0200 Subject: [PATCH 236/473] FIX pagination on search results --- htdocs/takepos/index.php | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index eab5b12c3c1..d934765b846 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -559,12 +559,20 @@ function New() { * @param {int} keyCodeForEnter Key code for "enter" * return {void} */ -function Search2(keyCodeForEnter) { +function Search2(keyCodeForEnter, moreorless) { console.log("Search2 Call ajax search to replace products keyCodeForEnter="+keyCodeForEnter); + var search_term = $('#search').val(); + var search_start = 0; + var search_limit = ; + if (moreorless != null) { + search_term = $('#search_pagination').val(); + search_start = $('#search_start_'+moreorless).val(); + } + var search = false; var eventKeyCode = window.event.keyCode; - if (typeof keyCodeForEnter === 'undefined' || eventKeyCode == keyCodeForEnter) { + if (keyCodeForEnter == '' || eventKeyCode == keyCodeForEnter) { search = true; } @@ -579,7 +587,8 @@ function Search2(keyCodeForEnter) { pageproducts = 0; jQuery(".wrapper2 .catwatermark").hide(); - $.getJSON('/takepos/ajax/ajax.php?action=search&term=' + $('#search').val(), function (data) { + var nbsearchresults = 0; + $.getJSON('/takepos/ajax/ajax.php?action=search&term=' + search_term + '&search_start=' + search_start + '&search_limit=' + search_limit, function (data) { for (i = 0; i < ; i++) { if (typeof (data[i]) == "undefined") { $("#prodesc" + i).text(""); @@ -618,6 +627,7 @@ function Search2(keyCodeForEnter) { } $("#prodiv" + i).data("rowid", data[i]['rowid']); $("#prodiv" + i).data("iscat", 0); + nbsearchresults++; } }).always(function (data) { // If there is only 1 answer @@ -642,6 +652,24 @@ function Search2(keyCodeForEnter) { } else ClearSearch(); } + // memorize search_term and start for pagination + $("#search_pagination").val($("#search").val()); + if (search_start == 0) { + $("#prodiv span").hide(); + } + else { + $("#prodiv span").show(); + var search_start_less = Math.max(0, parseInt(search_start) - parseInt()); + $("#search_start_less").val(search_start_less); + } + if (nbsearchresults != ) { + $("#prodiv span").hide(); + } + else { + $("#prodiv span").show(); + var search_start_more = parseInt(search_start) + parseInt(); + $("#search_start_more").val(search_start_more); + } }); }, 500); // 500ms delay } @@ -918,7 +946,7 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) {
From a11b5b43998501dec9f1da1332bdba6f209590a5 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 10:12:53 +0200 Subject: [PATCH 237/473] escape sql string for my Travais friend --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 5e0b329676a..e15963efb9a 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -235,7 +235,7 @@ if ($action == 'getProducts') { $sql .= $hookmanager->resPrint; // load only one page of products - $sql.= ' LIMIT '. $search_start . ',' . $search_limit; + $sql.= ' LIMIT '. $db->escape($search_start) . ',' . $db->escape($search_limit); $resql = $db->query($sql); if ($resql) { From 6d79d03cb2a275d4b41845752030e6be261ec9d0 Mon Sep 17 00:00:00 2001 From: melina Date: Fri, 29 Apr 2022 10:43:35 +0200 Subject: [PATCH 238/473] add comment to fix stickler --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 3ec334bd703..3af186813e2 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -54,7 +54,7 @@ if (empty($user->rights->takepos->run)) { } // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks -$hookmanager->initHooks(array('takeposproductsearch')); +$hookmanager->initHooks(array('takeposproductsearch')); // new context for product search hooks /* * View From 726b899d30e4defe41113f79d765287254e19554 Mon Sep 17 00:00:00 2001 From: Quentin-Seekness <72733832+Quentin-Seekness@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:45:08 +0200 Subject: [PATCH 239/473] FIX: Delete an extrafield where type is double Found the bug on a propal's extrafield, it was impossible to delete a decimal extrafield. In updateExtraField() the $value stayed "" where it needed to be null. The same issue can be found in insertExtraFields(). --- htdocs/core/class/commonobject.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 272d66e4855..aa88aeb825a 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5999,7 +5999,7 @@ abstract class CommonObject $this->errors[] = $langs->trans("ExtraFieldHasWrongValue", $attributeLabel); return -1; } elseif ($value == '') { - $new_array_options[$key] = null; + $value = null; } //dol_syslog("double value"." sur ".$attributeLabel."(".$value." is '".$attributeType."')", LOG_DEBUG); $new_array_options[$key] = $value; @@ -6365,7 +6365,7 @@ abstract class CommonObject $this->errors[] = $langs->trans("ExtraFieldHasWrongValue", $attributeLabel); return -1; } elseif ($value === '') { - $this->array_options["options_".$key] = null; + $value = null; } //dol_syslog("double value"." sur ".$attributeLabel."(".$value." is '".$attributeType."')", LOG_DEBUG); $this->array_options["options_".$key] = $value; From 812b9adee735c64225f7e48e0110ad81b3d123ef Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 10:58:04 +0200 Subject: [PATCH 240/473] still trying to please Travis... losing my time --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index e15963efb9a..380e205d53f 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -235,7 +235,7 @@ if ($action == 'getProducts') { $sql .= $hookmanager->resPrint; // load only one page of products - $sql.= ' LIMIT '. $db->escape($search_start) . ',' . $db->escape($search_limit); + $sql .= ' LIMIT '. $db->escape($search_start) . ',' . $db->escape($search_limit); $resql = $db->query($sql); if ($resql) { From d682cb3103f3feefb1394e810e8b8cc788eb0bdb Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 29 Apr 2022 11:09:32 +0200 Subject: [PATCH 241/473] please Travis --- htdocs/takepos/ajax/ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 380e205d53f..20fb282b1cd 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -235,7 +235,7 @@ if ($action == 'getProducts') { $sql .= $hookmanager->resPrint; // load only one page of products - $sql .= ' LIMIT '. $db->escape($search_start) . ',' . $db->escape($search_limit); + $sql.= $db->plimit($search_limit, $search_start); $resql = $db->query($sql); if ($resql) { From d496ad65e618650b34cd2e82d33f8f79acfb5525 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 11:16:15 +0200 Subject: [PATCH 242/473] Enhance the feature of keyword detection for partnership --- htdocs/core/modules/modPartnership.class.php | 18 ++++++++++-------- .../install/mysql/migration/15.0.0-16.0.0.sql | 6 +++++- ...llx_c_partnership_type-partnership.key.sql} | 0 ... => llx_c_partnership_type-partnership.sql} | 1 + .../tables/llx_partnership-partnership.sql | 5 +++-- htdocs/langs/en_US/partnership.lang | 4 +++- .../core/modules/modMyModule.class.php | 2 ++ htdocs/partnership/class/partnership.class.php | 7 ++++--- 8 files changed, 28 insertions(+), 15 deletions(-) rename htdocs/install/mysql/tables/{llx_c_partnership_type.key.sql => llx_c_partnership_type-partnership.key.sql} (100%) rename htdocs/install/mysql/tables/{llx_c_partnership_type.sql => llx_c_partnership_type-partnership.sql} (92%) diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php index 3bec23d0d37..c08cf66db06 100644 --- a/htdocs/core/modules/modPartnership.class.php +++ b/htdocs/core/modules/modPartnership.class.php @@ -219,19 +219,21 @@ class modPartnership extends DolibarrModules // Label of tables 'tablib'=>array("PartnershipType"), // Request to select fields - 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'c_partnership_type as f WHERE f.entity = '.$conf->entity), + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.keyword, f.active FROM '.MAIN_DB_PREFIX.'c_partnership_type as f WHERE f.entity = '.((int) $conf->entity)), // Sort order 'tabsqlsort'=>array("label ASC"), // List of fields (result of select to show dictionary) - 'tabfield'=>array("code,label"), + 'tabfield'=>array("code,label,keyword"), // List of fields (list of fields to edit a record) - 'tabfieldvalue'=>array("code,label"), + 'tabfieldvalue'=>array("code,label,keyword"), // List of fields (list of fields for insert) - 'tabfieldinsert'=>array("code,label"), + 'tabfieldinsert'=>array("code,label,keyword"), // Name of columns with primary key (try to always name it 'rowid') 'tabrowid'=>array("rowid"), // Condition to show each dictionary - 'tabcond'=>array($conf->partnership->enabled) + 'tabcond'=>array($conf->partnership->enabled), + // Help tooltip for each fields of the dictionary + 'tabhelp'=>array(array('keyword'=>$langs->trans('KeywordToCheckInWebsite'))) ); // Boxes/Widgets @@ -428,7 +430,7 @@ class modPartnership extends DolibarrModules $sql = array(); // Document templates - $moduledir = 'partnership'; + $moduledir = dol_sanitizeFileName('partnership'); $myTmpObjects = array(); $myTmpObjects['Partnership'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); @@ -437,8 +439,8 @@ class modPartnership extends DolibarrModules continue; } if ($myTmpObjectArray['includerefgeneration']) { - $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/partnership/template_partnerships.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/partnership'; + $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_partnerships.odt'; + $dirodt = DOL_DATA_ROOT.'/doctemplates/'.$moduledir; $dest = $dirodt.'/template_partnerships.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 39560240475..7170ebb62f4 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -334,4 +334,8 @@ ALTER TABLE llx_actioncomm MODIFY COLUMN note mediumtext; DELETE FROM llx_boxes WHERE box_id IN (select rowid FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php')); DELETE FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php'); -ALTER TABLE llx_takepos_floor_tables ADD UNIQUE(entity,label); \ No newline at end of file +ALTER TABLE llx_takepos_floor_tables ADD UNIQUE(entity,label); + +ALTER TABLE llx_partnership ADD COLUMN url_to_check varchar(255); +ALTER TABLE llx_c_partnership_type ADD COLUMN keyword varchar(128); + diff --git a/htdocs/install/mysql/tables/llx_c_partnership_type.key.sql b/htdocs/install/mysql/tables/llx_c_partnership_type-partnership.key.sql similarity index 100% rename from htdocs/install/mysql/tables/llx_c_partnership_type.key.sql rename to htdocs/install/mysql/tables/llx_c_partnership_type-partnership.key.sql diff --git a/htdocs/install/mysql/tables/llx_c_partnership_type.sql b/htdocs/install/mysql/tables/llx_c_partnership_type-partnership.sql similarity index 92% rename from htdocs/install/mysql/tables/llx_c_partnership_type.sql rename to htdocs/install/mysql/tables/llx_c_partnership_type-partnership.sql index 99841f967cb..fe4dd904662 100644 --- a/htdocs/install/mysql/tables/llx_c_partnership_type.sql +++ b/htdocs/install/mysql/tables/llx_c_partnership_type-partnership.sql @@ -31,6 +31,7 @@ create table llx_c_partnership_type entity integer DEFAULT 1 NOT NULL, code varchar(32) NOT NULL, label varchar(128) NOT NULL, + keyword varchar(128), -- a keyword to check into url of partner website or a dedicated url defined into partneship record active tinyint DEFAULT 1 NOT NULL )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_partnership-partnership.sql b/htdocs/install/mysql/tables/llx_partnership-partnership.sql index e3a5cb37e05..8f83e2e82e5 100644 --- a/htdocs/install/mysql/tables/llx_partnership-partnership.sql +++ b/htdocs/install/mysql/tables/llx_partnership-partnership.sql @@ -34,8 +34,9 @@ CREATE TABLE llx_partnership( note_private text, note_public text, last_main_doc varchar(255), - count_last_url_check_error integer DEFAULT '0', - last_check_backlink datetime NULL, + url_to_check varchar(255), -- url to check to find a specific keyword (defined into llx_c_partnership) to keep status of partnership valid + count_last_url_check_error integer DEFAULT '0', -- last result of check of keyword into url + last_check_backlink datetime NULL, -- date of last check of keyword into url import_key varchar(14), model_pdf varchar(255) ) ENGINE=innodb; \ No newline at end of file diff --git a/htdocs/langs/en_US/partnership.lang b/htdocs/langs/en_US/partnership.lang index f542bfab670..9c11e1cda2e 100644 --- a/htdocs/langs/en_US/partnership.lang +++ b/htdocs/langs/en_US/partnership.lang @@ -59,6 +59,7 @@ BacklinkNotFoundOnPartnerWebsite=Backlink not found on partner website ConfirmClosePartnershipAsk=Are you sure you want to cancel this partnership? PartnershipType=Partnership type PartnershipRefApproved=Partnership %s approved +KeywordToCheckInWebsite=If you want to check that a given keyword is present into the website of each partner, define this keyword here # # Template Mail @@ -89,4 +90,5 @@ PartnershipDraft=Draft PartnershipAccepted=Accepted PartnershipRefused=Refused PartnershipCanceled=Canceled -PartnershipManagedFor=Partners are \ No newline at end of file +PartnershipManagedFor=Partners are + diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index b1caea730f9..d843687157a 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -222,6 +222,8 @@ class modMyModule extends DolibarrModules 'tabrowid'=>array("rowid", "rowid", "rowid"), // Condition to show each dictionary 'tabcond'=>array($conf->mymodule->enabled, $conf->mymodule->enabled, $conf->mymodule->enabled) + // Help tooltip for each fields of the dictionary + 'tabhelp'=>array(array('code'=>$langs->trans('CodeTooltipHelp'))) ); */ diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index b673856d124..7d7d6a65d14 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -119,9 +119,10 @@ class Partnership extends CommonObject 'date_partnership_start' => array('type'=>'date', 'label'=>'DatePartnershipStart', 'enabled'=>'1', 'position'=>52, 'notnull'=>1, 'visible'=>1,), 'date_partnership_end' => array('type'=>'date', 'label'=>'DatePartnershipEnd', 'enabled'=>'1', 'position'=>53, 'notnull'=>0, 'visible'=>1,), 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'','0'=>'Draft', '1'=>'Accepted', '2'=>'Refused', '9'=>'Terminated'),), - 'count_last_url_check_error' => array('type'=>'integer', 'label'=>'CountLastUrlCheckError', 'enabled'=>'1', 'position'=>63, 'notnull'=>0, 'visible'=>-2, 'default'=>'0',), - 'last_check_backlink' => array('type'=>'datetime', 'label'=>'LastCheckBacklink', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>-2,), - 'reason_decline_or_cancel' => array('type'=>'text', 'label'=>'ReasonDeclineOrCancel', 'enabled'=>'1', 'position'=>64, 'notnull'=>0, 'visible'=>-2,), + 'url_to_check' => array('type'=>'varchar(255)', 'label'=>'UrlToCheck', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1), + 'count_last_url_check_error' => array('type'=>'integer', 'label'=>'CountLastUrlCheckError', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>-2, 'default'=>'0',), + 'last_check_backlink' => array('type'=>'datetime', 'label'=>'LastCheckBacklink', 'enabled'=>'1', 'position'=>72, 'notnull'=>0, 'visible'=>-2,), + 'reason_decline_or_cancel' => array('type'=>'text', 'label'=>'ReasonDeclineOrCancel', 'enabled'=>'1', 'position'=>73, 'notnull'=>0, 'visible'=>-2,), // fk_member and fk_soc are added into constructor ); From 3e4cd251eabf9f7559c8f8dd933474b611685f6f Mon Sep 17 00:00:00 2001 From: GregM Date: Fri, 29 Apr 2022 11:45:50 +0200 Subject: [PATCH 243/473] add edit extrafields Massaction products --- htdocs/core/actions_massactions.inc.php | 70 +++++++++++++++++++++++++ htdocs/core/tpl/massactions_pre.tpl.php | 25 +++++++++ htdocs/langs/en_US/main.lang | 4 ++ htdocs/product/list.php | 1 + 4 files changed, 100 insertions(+) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index c5ff1d8f82a..5f5703fc872 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1602,6 +1602,76 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == } } +if (!$error && $action == 'confirm_edit_value_extrafields' && $confirm == 'yes' && $permissiontoadd){ + $db->begin(); + + /** @var CommonObject $objecttmp */ + $objecttmp = new $objectclass($db); + + $nbok = 0; + $e = new ExtraFields($db); + $e->fetch_name_optionals_label($objecttmp->table_element); + + foreach ($toselect as $toselectid) { + $result = $objecttmp->fetch($toselectid); + + if ($result>0) { + + if (isset($e->attributes[$objecttmp->table_element]['type']) && is_array($e->attributes[$objecttmp->table_element]['type'])) { + foreach ($e->attributes[$objecttmp->table_element]['type'] as $key => $type){ + + //Permet de gérer les types d'extrafields + if (in_array($type, array('price', 'double'))) { + $value_arr = GETPOST("options_".$key, 'alpha'); + if(empty($value_arr)){ + continue; + } + $value_key = price2num($value_arr); + //var_dump($value_key);exit; + }else if (in_array($type, array('date'))) { + // Clean parameters + $value_key = dol_mktime(12, 0, 0, GETPOST("options_" . $key . "month", 'int'), GETPOST("options_" . $key . "day", 'int'), GETPOST("options_" . $key . "year", 'int')); + //var_dump($value_key);exit; + if(empty($value_key)){ + continue; + } + }else if (in_array($type, array('datetime'))) { + // Clean parameters + $value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'tzuserrel'); + if(empty($value_key)){ + continue; + } + } else { + $value_key = GETPOST("options_".$key); + if ((in_array($type, array('link')) && $key == '-1') || empty($value_key)) { + continue; + } + } + $objecttmp->array_options["options_".$key] = $value_key; + } + } + $objecttmp->insertExtraFields(); + + } else { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsDisabled", $nbok), null, 'mesgs'); + } else { + setEventMessages($langs->trans("save"), null, 'mesgs'); + } + $db->commit(); + } else { + $db->rollback(); + } + +} + // Approve for leave only if (!$error && ($massaction == 'approveleave' || ($action == 'approveleave' && $confirm == 'yes')) && $permissiontoapprove) { $db->begin(); diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index de034f652d3..40394cb99ff 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -211,6 +211,31 @@ if ($massaction == 'presend') { print dol_get_fiche_end(); } +if ($massaction == 'edit_extrafields') { + + require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + $elementtype = 'product'; + /** @var CommonObject $objecttmp */ + $extrafields = new ExtraFields($db); + + $extrafields->fetch_name_optionals_label($elementtype); + $extrafields_list = $extrafields->attributes[$elementtype]['label']; + + $formquestion = array(); + if (!empty($extrafields_list)) { + $myParamExtra = $object->showOptionals($extrafields, 'create'); + + $formquestion[] = array( + 'type' => 'other', + 'value' => $object->showOptionals($extrafields, 'create') + ); + + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmEditExtrafield"), $langs->trans("ConfirmEditExtrafieldQuestion", count($toselect)), "confirm_edit_value_extrafields", $formquestion, 1, 0, 200, 500, 1); + } else { + setEventMessage($langs->trans("noExtrafields")); + } +} + if ($massaction == 'preenable') { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassEnabling"), $langs->trans("ConfirmMassEnablingQuestion", count($toselect)), "enable", null, 'yes', 0, 200, 500, 1); } diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index c66895e58a4..c543fcf31e0 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1169,3 +1169,7 @@ CanceledShown=Canceled shown Terminate=Terminate Terminated=Terminated AddLineOnPosition=Add line on position (at the end if empty) +ConfirmEditExtrafield = Modifier les champs supplémentaires en masse +ChangeValueExtrafield = Modifier la valeur du champ supplémentaire +ConfirmEditExtrafieldQuestion = Etes vous sur de modifier cet extrafield ? +ConfirmEditValueExtrafieldQuestion = Etes vous sur de modifier la valeur de cet extrafield ? diff --git a/htdocs/product/list.php b/htdocs/product/list.php index de5e4f278b7..7cd0a91c923 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -727,6 +727,7 @@ if ($resql) { // List of mass actions available $arrayofmassactions = array( 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + 'edit_extrafields'=>img_picto('', 'edit', 'class="pictofixedwidth"').$langs->trans("Extrafields"), //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); From bdd9b2acf4557c9b86e2988afb4ca468dfe09e5d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 11:50:55 +0200 Subject: [PATCH 244/473] Clean css --- htdocs/core/lib/usergroups.lib.php | 7 ++++-- htdocs/langs/en_US/admin.lang | 2 +- htdocs/takepos/css/pos.css.php | 2 +- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 4 ++-- htdocs/theme/md/info-box.inc.php | 2 +- htdocs/theme/md/style.css.php | 38 +++++++++++++++--------------- 7 files changed, 30 insertions(+), 27 deletions(-) diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index c963c74c8b6..9bc0a59cf86 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -367,6 +367,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) $url = 'https://www.dolistore.com/9-skins'; print ''; print $langs->trans('DownloadMoreSkins'); + print img_picto('', 'globe', 'class="paddingleft"'); print ''; print ''; } @@ -435,7 +436,9 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) $colorbacktitle1 = ''; $colortexttitle = ''; $colorbacklineimpair1 = ''; + $colorbacklineimpair2 = ''; $colorbacklinepair1 = ''; + $colorbacklinepair2 = ''; $colortextlink = ''; $colorbacklinepairhover = ''; $colorbacklinepairhover = ''; @@ -746,7 +749,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) print ''.$langs->trans("BackgroundTableLineOddColor").''; print ''; if ($edit) { - print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->THEME_ELDY_LINEIMPAIR1) ? $conf->global->THEME_ELDY_LINEIMPAIR1 : ''), array()), ''), 'THEME_ELDY_LINEIMPAIR1', '', 1, '', '', 'colorbacklinepair2').' '; + print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->THEME_ELDY_LINEIMPAIR1) ? $conf->global->THEME_ELDY_LINEIMPAIR1 : ''), array()), ''), 'THEME_ELDY_LINEIMPAIR1', '', 1, '', '', 'colorbacklineimpair2').' '; } else { $color = colorArrayToHex(colorStringToArray($conf->global->THEME_ELDY_LINEIMPAIR1, array()), ''); if ($color) { @@ -770,7 +773,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) print ''.$langs->trans("BackgroundTableLineEvenColor").''; print ''; if ($edit) { - print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->THEME_ELDY_LINEPAIR1) ? $conf->global->THEME_ELDY_LINEPAIR1 : ''), array()), ''), 'THEME_ELDY_LINEPAIR1', '', 1, '', '', 'colorbacklineimpair2').' '; + print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->THEME_ELDY_LINEPAIR1) ? $conf->global->THEME_ELDY_LINEPAIR1 : ''), array()), ''), 'THEME_ELDY_LINEPAIR1', '', 1, '', '', 'colorbacklinepair2').' '; } else { $color = colorArrayToHex(colorStringToArray($conf->global->THEME_ELDY_LINEPAIR1, array()), ''); if ($color) { diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 970426eb488..bbb46d83900 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1925,7 +1925,7 @@ ConfFileMustContainCustom=Installing or building an external module from applica HighlightLinesOnMouseHover=Highlight table lines when mouse move passes over HighlightLinesColor=Highlight color of the line when the mouse passes over (use 'ffffff' for no highlight) HighlightLinesChecked=Highlight color of the line when it is checked (use 'ffffff' for no highlight) -UseBorderOnTable=Active border on tables +UseBorderOnTable=Show left-right borders on tables BtnActionColor=Color of the action button TextBtnActionColor=Text color of the action button TextTitleColor=Text color of Page title diff --git a/htdocs/takepos/css/pos.css.php b/htdocs/takepos/css/pos.css.php index ba85c111bcd..45130981876 100644 --- a/htdocs/takepos/css/pos.css.php +++ b/htdocs/takepos/css/pos.css.php @@ -311,7 +311,7 @@ table.postablelines tr td { .posinvoiceline td { height: 40px !important; - background-color: var(--colorbacklineimpair1); + background-color: var(--colorbacklineimpair2); } .postablelines td.linecolht { diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 356c8f45d63..c2c4d12012b 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -13,7 +13,7 @@ --colorbacktitle1: rgb(); --colorbacktabcard1: rgb(); --colorbacktabactive: rgb(); - --colorbacklinepair1: rgb(); + --colorbacklineimpair1: rgb(); --colorbacklineimpair2: rgb(); --colorbacklinepair1: rgb(); --colorbacklinepair2: rgb(); diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 8e4df027809..2d33a716692 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -21,7 +21,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) { display: block; position: relative; min-height: 90px; - /* background: #fff; */ + background: var(--colorbacklineimpair2); width: 100%; box-shadow: 1px 1px 15px rgba(192, 192, 192, 0.2); border-radius: 2px; @@ -88,7 +88,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) { text-align: center; font-size: 2.8em; line-height: 90px; - background: rgba(0, 0, 0, 0.08) !important; + background: var(--colorbacktitle1) !important; } .info-box-module .info-box-icon { diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index 1ea21ac44d1..8ffd6fc3f93 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -133,7 +133,7 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { display: block; position: relative; min-height: 90px; - background: #fff; + background: var(--colorbacklineimpair2); width: 100%; /* box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); */ border-radius: 2px; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index f1a07efbb0c..5317d6085fa 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -359,7 +359,7 @@ body { color: rgb(); font-size: ; - line-height: 1.3; + line-height: 1.4; font-family: ; margin-top: 0; margin-bottom: 0; @@ -3968,10 +3968,10 @@ table.hidepaginationnext .paginationnext { /* Prepare to remove class pair - impair .noborder > tbody > tr:nth-child(even) td { - background: linear-gradient(to bottom, var(--colorbacklineimpair1) 85%, var(--colorbacklineimpair2) 100%); - background: -o-linear-gradient(bottom, var(--colorbacklineimpair1) 85%, var(--colorbacklineimpair2) 100%); - background: -moz-linear-gradient(bottom, var(--colorbacklineimpair1) 85%, var(--colorbacklineimpair2) 100%); - background: -webkit-linear-gradient(bottom, var(--colorbacklineimpair1) 85%, var(--colorbacklineimpair2) 100%); + background: linear-gradient(to bottom, var(--colorbacklineimpai2) 85%, var(--colorbacklineimpair2) 100%); + background: -o-linear-gradient(bottom, var(--colorbacklineimpair2) 85%, var(--colorbacklineimpair2) 100%); + background: -moz-linear-gradient(bottom, var(--colorbacklineimpair2) 85%, var(--colorbacklineimpair2) 100%); + background: -webkit-linear-gradient(bottom, var(--colorbacklineimpair2) 85%, var(--colorbacklineimpair2) 100%); font-family: ; border: 0px; margin-bottom: 1px; @@ -3980,10 +3980,10 @@ table.hidepaginationnext .paginationnext { } .noborder > tbody > tr:nth-child(odd) td { - background: linear-gradient(to bottom, var(--colorbacklinepair1) 85%, var(--colorbacklinepair2) 100%); - background: -o-linear-gradient(bottom, var(--colorbacklinepair1) 85%, var(--colorbacklinepair2) 100%); - background: -moz-linear-gradient(bottom, var(--colorbacklinepair1) 85%, var(--colorbacklinepair2) 100%); - background: -webkit-linear-gradient(bottom, var(--colorbacklinepair1) 85%, var(--colorbacklinepair2) 100%); + background: linear-gradient(to bottom, var(--colorbacklinepair2) 85%, var(--colorbacklinepair2) 100%); + background: -o-linear-gradient(bottom, var(--colorbacklinepair2) 85%, var(--colorbacklinepair2) 100%); + background: -moz-linear-gradient(bottom, var(--colorbacklinepair2) 85%, var(--colorbacklinepair2) 100%); + background: -webkit-linear-gradient(bottom, var(--colorbacklinepair2) 85%, var(--colorbacklinepair2) 100%); font-family: ; border: 0px; margin-bottom: 1px; @@ -4038,10 +4038,10 @@ ul.noborder li:nth-child(odd):not(.liste_titre) { } .impair, .nohover .impair:hover, tr.impair td.nohover { - background: var(--colorbacklineimpair1); + background: var(--colorbacklineimpair2); } #GanttChartDIV { - background-color: var(--colorbacklineimpair1); + background-color: var(--colorbacklineimpair2); } .oddeven, .evenodd, .pair, .nohover .pair:hover, tr.pair td.nohover, .tagtr.oddeven { @@ -4059,12 +4059,12 @@ table.dataTable tr.oddeven { /* For no hover style */ td.oddeven, table.nohover tr.impair, table.nohover tr.pair, table.nohover tr.impair td, table.nohover tr.pair td, tr.nohover td, form.nohover, form.nohover:hover { - background-color: var(--colorbacklineimpair1) !important; - background: var(--colorbacklineimpair1) !important; + background-color: var(--colorbacklineimpair2) !important; + background: var(--colorbacklineimpair2) !important; } td.evenodd, tr.nohoverpair td, #trlinefordates td { - background-color: var(--colorbacklinepair1) !important; - background: var(--colorbacklinepair1) !important; + background-color: var(--colorbacklinepair2) !important; + background: var(--colorbacklinepair2) !important; } .trforbreak td { font-weight: bold; @@ -4277,10 +4277,10 @@ div .tdtop { div:not(.fichecenter):not(.fichehalfleft):not(.fichehalfright) > .border > tbody > tr:nth-of-type(even):not(.liste_titre), .liste > tbody > tr:nth-of-type(even):not(.liste_titre), div:not(.fichecenter):not(.fichehalfleft):not(.fichehalfright) .oddeven.tagtr:nth-of-type(even):not(.liste_titre) { - background: linear-gradient(to bottom, var(--colorbacklineimpair1) 0%, var(--colorbacklineimpair2) 100%); - background: -o-linear-gradient(bottom, var(--colorbacklineimpair1) 0%, var(--colorbacklineimpair2) 100%); - background: -moz-linear-gradient(bottom, var(--colorbacklineimpair1) 0%, var(--colorbacklineimpair2) 100%); - background: -webkit-linear-gradient(bottom, var(--colorbacklineimpair1) 0%, var(--colorbacklineimpair2) 100%); + background: linear-gradient(to bottom, var(--colorbacklineimpair2) 0%, var(--colorbacklineimpair2) 100%); + background: -o-linear-gradient(bottom, var(--colorbacklineimpair2) 0%, var(--colorbacklineimpair2) 100%); + background: -moz-linear-gradient(bottom, var(--colorbacklineimpair2) 0%, var(--colorbacklineimpair2) 100%); + background: -webkit-linear-gradient(bottom, var(--colorbacklineimpair2) 0%, var(--colorbacklineimpair2) 100%); } .noborder > tbody > tr:nth-child(even):not(:last-of-type) td:not(.liste_titre), .liste > tbody > tr:nth-child(even):not(:last-of-type) td:not(.liste_titre), .noborder .tagtr:nth-child(even):not(:last-of-type) .oddeven.tagtd:not(.liste_titre) From 708d3610a5a6c48e98e8682d674c13fae9d99536 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 13:04:29 +0200 Subject: [PATCH 245/473] Look and feel v16 --- htdocs/comm/propal/card.php | 6 +-- htdocs/commande/card.php | 6 +-- htdocs/core/class/html.form.class.php | 16 ++++--- htdocs/core/class/html.formprojet.class.php | 50 +++++++++++---------- htdocs/core/lib/functions.lib.php | 4 +- htdocs/projet/admin/project.php | 7 +-- 6 files changed, 48 insertions(+), 41 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index f6989d90d59..c36c3e86663 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1650,13 +1650,13 @@ if ($action == 'create') { // Terms of payment print ''.$langs->trans('PaymentConditionsShort').''; - print img_picto('', 'paiment'); + print img_picto('', 'payment', 'class="pictofixedwidth"'); $form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') && GETPOST('cond_reglement_id') != 0) ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id, 'cond_reglement_id', -1, 1); print ''; // Mode of payment print ''.$langs->trans('PaymentMode').''; - print img_picto('', 'bank').' '; + print img_picto('', 'bank', 'class="pictofixedwidth').' '; $form->select_types_paiements((GETPOSTISSET('mode_reglement_id') ? GETPOST('mode_reglement_id', 'int') : $soc->mode_reglement_id), 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx'); print ''; @@ -1752,7 +1752,7 @@ if ($action == 'create') { print ''; print ''.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).''; print ''; - print $form->selectMultiCurrency($currency_code, 'multicurrency_code', 0); + print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency($currency_code, 'multicurrency_code', 0); print ''; } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 53b6d40d6b0..d33ea387947 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1670,7 +1670,7 @@ if ($action == 'create' && $usercancreate) { // Terms of the settlement print ''.$langs->trans('PaymentConditionsShort').''; - print img_picto('', 'paiment'); + print img_picto('', 'payment', 'class="pictofixedwidth"'); $form->select_conditions_paiements($cond_reglement_id, 'cond_reglement_id', - 1, 1); print ''; @@ -1759,10 +1759,10 @@ if ($action == 'create' && $usercancreate) { // Template to use by default print ''.$langs->trans('DefaultModel').''; print ''; - print img_picto('', 'pdf', 'class="pictofixedwidth"'); include_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php'; $liste = ModelePDFCommandes::liste_modeles($db); $preselected = $conf->global->COMMANDE_ADDON_PDF; + print img_picto('', 'pdf', 'class="pictofixedwidth"'); print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1); print ""; @@ -1771,7 +1771,7 @@ if ($action == 'create' && $usercancreate) { print ''; print ''.$form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0).''; print ''; - print $form->selectMultiCurrency($currency_code, 'multicurrency_code'); + print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency($currency_code, 'multicurrency_code'); print ''; } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f86fcd88030..749b4dddb13 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5872,6 +5872,7 @@ class Form } $out .= ''; + // Make select dynamic include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); @@ -7753,13 +7754,6 @@ class Form } } - // Add code for jquery to use multiselect - if ($addjscombo && $jsbeautify) { - // Enhance with select2 - include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; - $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', $show_empty < 0 ? (string) $show_empty : '-1'); - } - $out .= ''; + $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array( // 'update' => array( // 'projectid' => 'id' // ) )); - - $out .= ''; } else { $out .= $this->select_projects_list($socid, $selected, $htmlname, $maxlength, $option_only, $show_empty, abs($discard_closed), $forcefocus, $disabled, 0, $filterkey, 1, $forceaddid, $htmlid, $morecss); } if ($discard_closed > 0) { - if (class_exists('Form')) { - if (!is_object($form)) { - $form = new Form($this->db); - } + if (!empty($form)) { $out .= $form->textwithpicto('', $langs->trans("ClosedProjectsAreHidden")); } } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 24557d1e90e..de31b0d632f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3730,7 +3730,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'briefcase-medical', 'bug', 'building', 'card', 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', 'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'conversation', 'cron', 'cubes', - 'multicurrency', + 'currency', 'multicurrency', 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'dynamicprice', 'edit', 'ellipsis-h', 'email', 'entity', 'eraser', 'establishment', 'expensereport', 'external-link-alt', 'external-link-square-alt', 'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'autofill', 'folder', 'folder-open', 'folder-plus', @@ -3789,7 +3789,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', 'switch_on_red'=>'toggle-on', 'check'=>'check', 'bookmark'=>'star', 'bank'=>'university', 'close_title'=>'times', 'delete'=>'trash', 'filter'=>'filter', 'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarmonth'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table', - 'intervention'=>'ambulance', 'invoice'=>'file-invoice-dollar', 'multicurrency'=>'dollar-sign', 'order'=>'file-invoice', + 'intervention'=>'ambulance', 'invoice'=>'file-invoice-dollar', 'currency'=>'dollar-sign', 'multicurrency'=>'dollar-sign', 'order'=>'file-invoice', 'error'=>'exclamation-triangle', 'warning'=>'exclamation-triangle', 'other'=>'square', 'playdisabled'=>'play', 'pdf'=>'file-pdf', 'poll'=>'check-double', 'pos'=>'cash-register', 'preview'=>'binoculars', 'project'=>'project-diagram', 'projectpub'=>'project-diagram', 'projecttask'=>'tasks', 'propal'=>'file-signature', diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php index adef0826992..37a2bb246ce 100644 --- a/htdocs/projet/admin/project.php +++ b/htdocs/projet/admin/project.php @@ -766,6 +766,7 @@ $form = new Form($db); print '
'; print ''; print ''; +print ''; print ''; print ''; @@ -788,7 +789,7 @@ if (!$conf->use_javascript_ajax) { ); print $form->selectarray("activate_PROJECT_USE_SEARCH_TO_SELECT", $arrval, $conf->global->PROJECT_USE_SEARCH_TO_SELECT); print '"; } print ''; @@ -799,7 +800,7 @@ print ''; print ''; print ''; @@ -818,7 +819,7 @@ print ''; print ''; print ''; print '
'; - print ''; + print ''; print "
'.$langs->trans("AllowToSelectProjectFromOtherCompany").''; print ' '; print $form->textwithpicto('', $langs->trans('AllowToLinkFromOtherCompany')); -print ''; +print ''; print '
'.$langs->trans("TimesheetPreventAfterFollowingMonths").''; print ' '; -print ''; +print ''; print '
'; From 147e61472c382549f4e2889b4390a25719be3534 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 13:10:28 +0200 Subject: [PATCH 246/473] Clean code: Remove all   entities. --- htdocs/adherents/list.php | 2 +- htdocs/comm/propal/card.php | 8 ++++---- htdocs/supplier_proposal/list.php | 4 ++-- htdocs/user/list.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 1936d855a7e..b99d763b7b0 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -587,7 +587,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; // List of mass actions available $arrayofmassactions = array( - //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').' '.$langs->trans("SendByMail"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), ); if ($user->rights->adherent->creer) { diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index c36c3e86663..07e041a8fd1 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1646,7 +1646,7 @@ if ($action == 'create') { print ''; // Validaty duration - print ''.$langs->trans("ValidityDuration").''.img_picto('', 'clock').'  '.$langs->trans("days").''; + print ''.$langs->trans("ValidityDuration").''.img_picto('', 'clock', 'class="paddingright"').' '.$langs->trans("days").''; // Terms of payment print ''.$langs->trans('PaymentConditionsShort').''; @@ -1656,7 +1656,7 @@ if ($action == 'create') { // Mode of payment print ''.$langs->trans('PaymentMode').''; - print img_picto('', 'bank', 'class="pictofixedwidth').' '; + print img_picto('', 'bank', 'class="pictofixedwidth"'); $form->select_types_paiements((GETPOSTISSET('mode_reglement_id') ? GETPOST('mode_reglement_id', 'int') : $soc->mode_reglement_id), 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx'); print ''; @@ -1679,7 +1679,7 @@ if ($action == 'create') { print ' ('.$langs->trans('AfterOrder').')'; } print ''; - print img_picto('', 'clock').' '; + print img_picto('', 'clock', 'class="pictofixedwidth"'); $form->selectAvailabilityDelay('', 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx'); print ''; @@ -1741,7 +1741,7 @@ if ($action == 'create') { print ''; print ''.$langs->trans("DefaultModel").''; print ''; - print img_picto('', 'pdf').' '; + print img_picto('', 'pdf', 'class="pictofixedwidth"'); $liste = ModelePDFPropales::liste_modeles($db); $preselected = (!empty($conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT) ? $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT : getDolGlobalString("PROPALE_ADDON_PDF")); print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1); diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index ad35c8f9914..c6411f9c169 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -573,10 +573,10 @@ if ($resql) { $arrayofmassactions = array( 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), - //'presend'=>img_picto('', 'email',, 'class="pictofixedwidth"').' '.$langs->trans("SendByMail"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); if ($user->rights->supplier_proposal->supprimer) { - $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').' '.$langs->trans("Delete"); + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } if (in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); diff --git a/htdocs/user/list.php b/htdocs/user/list.php index cd87e286225..9cc1fa88953 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -551,7 +551,7 @@ if ($permissiontoadd) { if ($permissiontoadd) { $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } -//if ($permissiontodelete) $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').' '.$langs->trans("Delete"); +//if ($permissiontodelete) $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag'))) { $arrayofmassactions = array(); From 3780e83615294c888f897b5daf826d7f28a48a11 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 13:20:14 +0200 Subject: [PATCH 247/473] Trans --- htdocs/langs/en_US/members.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index 8646c40b98f..faa2e0d0fcd 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -15,7 +15,7 @@ ErrorMemberIsAlreadyLinkedToThisThirdParty=Another member (name: %s, logi ErrorUserPermissionAllowsToLinksToItselfOnly=For security reasons, you must be granted permissions to edit all users to be able to link a member to a user that is not yours. SetLinkToUser=Link to a Dolibarr user SetLinkToThirdParty=Link to a Dolibarr third party -MembersCards=Business cards for members +MembersCards=Generation of cards for members MembersList=List of members MembersListToValid=List of draft members (to be validated) MembersListValid=List of valid members @@ -163,7 +163,7 @@ MoreActionsOnSubscription=Complementary action suggested by default when recordi MoreActionBankDirect=Create a direct entry on bank account MoreActionBankViaInvoice=Create an invoice, and a payment on bank account MoreActionInvoiceOnly=Create an invoice with no payment -LinkToGeneratedPages=Generate visit cards +LinkToGeneratedPages=Generation of business cards or address sheets LinkToGeneratedPagesDesc=This screen allows you to generate PDF files with business cards for all your members or a particular member. DocForAllMembersCards=Generate business cards for all members DocForOneMemberCards=Generate business cards for a particular member From fed14db94a5cd9df24b12c5013d44cf47f79e6a5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 13:22:46 +0200 Subject: [PATCH 248/473] css --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index de31b0d632f..51741179753 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3866,7 +3866,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'ecm'=>'infobox-action', 'eventorganization'=>'infobox-project', 'hrm'=>'infobox-adherent', 'group'=>'infobox-adherent', 'intervention'=>'infobox-contrat', 'incoterm'=>'infobox-supplier_proposal', - 'multicurrency'=>'infobox-bank_account', + 'currency'=>'infobox-bank_account', 'multicurrency'=>'infobox-bank_account', 'members'=>'infobox-adherent', 'member'=>'infobox-adherent', 'money-bill-alt'=>'infobox-bank_account', 'order'=>'infobox-commande', 'user'=>'infobox-adherent', 'users'=>'infobox-adherent', From 8ad57b3d7ab4c5193afa1d3bf4db84e125e6fcf9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 13:43:51 +0200 Subject: [PATCH 249/473] Fix td --- htdocs/admin/ihm.php | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index 2c997d746d9..fdfd8bb8fae 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -485,18 +485,17 @@ if ($mode == 'other') { print ''; print ''; + print $langs->trans("Miscellaneous"); + print ''; + print ''; + print ''; // Max size of lists print ''; - print ''; print ''; // Max size of short lists on customer card print ''; - print ''; print ''; // show input border @@ -504,7 +503,6 @@ if ($mode == 'other') { print ''; - print ''; print ''; */ @@ -512,21 +510,18 @@ if ($mode == 'other') { print ''; - print ''; print ''; // DefaultWorkingDays print ''; - print ''; print ''; // DefaultWorkingHours print ''; - print ''; print ''; // Firstname/Name @@ -534,7 +529,6 @@ if ($mode == 'other') { $array = array(0 => $langs->trans("Firstname") . ' ' . $langs->trans("Lastname"), 1 => $langs->trans("Lastname") . ' ' . $langs->trans("Firstname")); print $form->selectarray('MAIN_FIRSTNAME_NAME_POSITION', $array, (isset($conf->global->MAIN_FIRSTNAME_NAME_POSITION) ? $conf->global->MAIN_FIRSTNAME_NAME_POSITION : 0)); print ''; - print ''; print ''; // Hide unauthorized menus @@ -542,7 +536,6 @@ if ($mode == 'other') { //print $form->selectyesno('MAIN_MENU_HIDE_UNAUTHORIZED', isset($conf->global->MAIN_MENU_HIDE_UNAUTHORIZED) ? $conf->global->MAIN_MENU_HIDE_UNAUTHORIZED : 0, 1); print ajax_constantonoff("MAIN_MENU_HIDE_UNAUTHORIZED", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '', 'other'); print ''; - print ''; print ''; // Hide unauthorized button @@ -550,7 +543,6 @@ if ($mode == 'other') { //print $form->selectyesno('MAIN_BUTTON_HIDE_UNAUTHORIZED', isset($conf->global->MAIN_BUTTON_HIDE_UNAUTHORIZED) ? $conf->global->MAIN_BUTTON_HIDE_UNAUTHORIZED : 0, 1); print ajax_constantonoff("MAIN_BUTTON_HIDE_UNAUTHORIZED", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '', 'other'); print ''; - print ''; print ''; // Hide version link @@ -559,7 +551,6 @@ if ($mode == 'other') { print ''; - print ''; print ''; */ @@ -569,7 +560,6 @@ if ($mode == 'other') { print ''; - print ''; print ''; // Hide wiki link on login page @@ -578,7 +568,6 @@ if ($mode == 'other') { print ajax_constantonoff("MAIN_HELP_DISABLELINK", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '', 'other'); //print $form->selectyesno('MAIN_HELP_DISABLELINK', isset($conf->global->MAIN_HELP_DISABLELINK) ? $conf->global->MAIN_HELP_DISABLELINK : 0, 1); print ''; - print ''; print ''; // Disable javascript and ajax @@ -586,8 +575,6 @@ if ($mode == 'other') { print ajax_constantonoff("MAIN_DISABLE_JAVASCRIPT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '', 'other'); print ' ' . $langs->trans("DisableJavascriptNote") . ''; print ''; - print ''; print ''; print '
'; - print $langs->trans("Miscelaneous"); - print ''; - print '
' . $langs->trans("DefaultMaxSizeList") . ' 
' . $langs->trans("DefaultMaxSizeShortList") . ' 
'.$langs->trans("showInputBorder").''; print $form->selectyesno('main_showInputBorder',isset($conf->global->THEME_ELDY_SHOW_BORDER_INPUT)?$conf->global->THEME_ELDY_SHOW_BORDER_INPUT:0,1); print ' 
' . $langs->trans("WeekStartOnDay") . ''; print $formother->select_dayofweek((isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : '1'), 'MAIN_START_WEEK', 0); print ' 
' . $langs->trans("DefaultWorkingDays") . ''; print ''; print ' 
' . $langs->trans("DefaultWorkingHours") . ''; print ''; print ' 
 
 
 
'.$langs->trans("HideVersionLink").''; print $form->selectyesno('MAIN_HIDE_VERSION',$conf->global->MAIN_HIDE_VERSION,1); print ' 
'; print ''; print ' 
 
'; - print '
' . "\n"; From 921aabfc54eb4610f26fc9c8dacc19cbabc54474 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 14:11:38 +0200 Subject: [PATCH 250/473] Look and feel v16 --- htdocs/core/class/html.formfile.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 1d3faca93cb..acb7d5b5f2a 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -246,10 +246,10 @@ class FormFile $out .= ''.$options.''; } $out .= ''; - $out .= ' '; - $out .= ''; + $out .= ' '; + $out .= ''; + $out .= ''; $out .= ''; $out .= ''; } From 223db9bb76f66af8e2ce341699bde4c58910180a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 14:32:47 +0200 Subject: [PATCH 251/473] Fix: Not SetEventMessages inside a CRUD class. --- htdocs/compta/paiement/class/paiement.class.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index c5f40896a18..ae4064462e2 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -419,7 +419,8 @@ class Paiement extends CommonObject } if ($error) { - setEventMessages($discount->error, $discount->errors, 'errors'); + $this->error = $discount->error; + $this->errors = $discount->errors; $error++; } } @@ -460,7 +461,8 @@ class Paiement extends CommonObject $result = $invoice->generateDocument($invoice->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref); if ($result < 0) { - setEventMessages($invoice->error, $invoice->errors, 'errors'); + $this->error = $invoice->error; + $this->errors = $invoice->errors; $error++; } } From 8b248c75f29eff7a9ab61846bdc7f23ee5bf8c05 Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Fri, 29 Apr 2022 15:10:15 +0200 Subject: [PATCH 252/473] Factor save --- htdocs/core/actions_massactions.inc.php | 58 +++++++------------------ 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5f5703fc872..ccf2fbec73e 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1602,56 +1602,29 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == } } -if (!$error && $action == 'confirm_edit_value_extrafields' && $confirm == 'yes' && $permissiontoadd){ +if (!$error && $action == 'confirm_edit_value_extrafields' && $confirm == 'yes' && $permissiontoadd) { $db->begin(); - /** @var CommonObject $objecttmp */ - $objecttmp = new $objectclass($db); - $nbok = 0; - $e = new ExtraFields($db); - $e->fetch_name_optionals_label($objecttmp->table_element); + $extrafieldKeyToUpdate = GETPOST('extrafield-key-yo-update'); // TODO A FAIRE coté formulaire : ajouter le select de l'extrafield a utiliser + $extrafieldKeyToUpdate = 'code_tva_achat'; // TODO A FAIRE coté formulaire : ajouter le select de l'extrafield a utiliser + + // TODO vérifier que $extrafieldKeyToUpdate correspond bien a un extrafield foreach ($toselect as $toselectid) { + /** @var CommonObject $objecttmp */ + $objecttmp = new $objectclass($db); $result = $objecttmp->fetch($toselectid); - if ($result>0) { - - if (isset($e->attributes[$objecttmp->table_element]['type']) && is_array($e->attributes[$objecttmp->table_element]['type'])) { - foreach ($e->attributes[$objecttmp->table_element]['type'] as $key => $type){ - - //Permet de gérer les types d'extrafields - if (in_array($type, array('price', 'double'))) { - $value_arr = GETPOST("options_".$key, 'alpha'); - if(empty($value_arr)){ - continue; - } - $value_key = price2num($value_arr); - //var_dump($value_key);exit; - }else if (in_array($type, array('date'))) { - // Clean parameters - $value_key = dol_mktime(12, 0, 0, GETPOST("options_" . $key . "month", 'int'), GETPOST("options_" . $key . "day", 'int'), GETPOST("options_" . $key . "year", 'int')); - //var_dump($value_key);exit; - if(empty($value_key)){ - continue; - } - }else if (in_array($type, array('datetime'))) { - // Clean parameters - $value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'tzuserrel'); - if(empty($value_key)){ - continue; - } - } else { - $value_key = GETPOST("options_".$key); - if ((in_array($type, array('link')) && $key == '-1') || empty($value_key)) { - continue; - } - } - $objecttmp->array_options["options_".$key] = $value_key; - } + // Fill array 'array_options' with data from add form + $e = new ExtraFields($db); + $ret = $e->setOptionalsFromPost(null, $objecttmp, $extrafieldKeyToUpdate); + if ($ret > 0) { + $objecttmp->insertExtraFields(); // TODO gérer l'erreur + } else { + $error++; + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); } - $objecttmp->insertExtraFields(); - } else { setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); $error++; @@ -1669,7 +1642,6 @@ if (!$error && $action == 'confirm_edit_value_extrafields' && $confirm == 'yes' } else { $db->rollback(); } - } // Approve for leave only From 02cf3fa36102ecebd890d5d9d12652d01d1aad0d Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Fri, 29 Apr 2022 15:38:12 +0200 Subject: [PATCH 253/473] end factoring --- htdocs/core/actions_massactions.inc.php | 12 +++++++----- htdocs/core/tpl/massactions_pre.tpl.php | 6 +++++- htdocs/product/list.php | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index ccf2fbec73e..6308c33d268 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1605,20 +1605,22 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == if (!$error && $action == 'confirm_edit_value_extrafields' && $confirm == 'yes' && $permissiontoadd) { $db->begin(); - $nbok = 0; + $objecttmp = new $objectclass($db); + $e = new ExtraFields($db);// fetch optionals attributes and labels + $e->fetch_name_optionals_label($objecttmp->table_element); - $extrafieldKeyToUpdate = GETPOST('extrafield-key-yo-update'); // TODO A FAIRE coté formulaire : ajouter le select de l'extrafield a utiliser - $extrafieldKeyToUpdate = 'code_tva_achat'; // TODO A FAIRE coté formulaire : ajouter le select de l'extrafield a utiliser + $nbok = 0; + $extrafieldKeyToUpdate = GETPOST('extrafield-key-to-update'); // TODO A FAIRE coté formulaire : ajouter le select de l'extrafield a utiliser // TODO vérifier que $extrafieldKeyToUpdate correspond bien a un extrafield foreach ($toselect as $toselectid) { /** @var CommonObject $objecttmp */ - $objecttmp = new $objectclass($db); + $objecttmp = new $objectclass($db); // to avoid ghost data $result = $objecttmp->fetch($toselectid); if ($result>0) { // Fill array 'array_options' with data from add form - $e = new ExtraFields($db); $ret = $e->setOptionalsFromPost(null, $objecttmp, $extrafieldKeyToUpdate); + if ($ret > 0) { $objecttmp->insertExtraFields(); // TODO gérer l'erreur } else { diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index 40394cb99ff..8e364cd24e1 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -212,7 +212,6 @@ if ($massaction == 'presend') { } if ($massaction == 'edit_extrafields') { - require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $elementtype = 'product'; /** @var CommonObject $objecttmp */ @@ -225,6 +224,11 @@ if ($massaction == 'edit_extrafields') { if (!empty($extrafields_list)) { $myParamExtra = $object->showOptionals($extrafields, 'create'); + $formquestion[] = array( + 'type' => 'other', + 'value' => $form->selectarray('extrafield-key-to-update', $extrafields_list, GETPOST('extrafield-key-to-update')) + ); + $formquestion[] = array( 'type' => 'other', 'value' => $object->showOptionals($extrafields, 'create') diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 7cd0a91c923..4824015c299 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -740,7 +740,7 @@ if ($resql) { $arrayofmassactions['switchonpurchasestatus'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SwitchOnPurchaseStatus"); $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } - if (in_array($massaction, array('presend', 'predelete','preaffecttag'))) { + if (in_array($massaction, array('presend', 'predelete','preaffecttag', 'edit_extrafields'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); From 3dd90ecf416d7e62e94b20110f66d9ef84228568 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Apr 2022 16:02:05 +0200 Subject: [PATCH 254/473] js escape --- htdocs/takepos/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index d934765b846..1b1608d53e7 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -946,7 +946,7 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) {
'; - - print '
'; - - print '
'; - print ''; - - print ''; - - print ''; - print ''; - - if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { - // Block meteo - print ''; - print ''; - - // Block agenda - print ''; - print ''; - - // Block agenda - print ''; - print ''; - - // Block customer - print ''; - print ''; - - // Block supplier - print ''; - print ''; - - // Block contract - print ''; - print ''; - - // Block ticket - print ''; - print ''; - - // Block bank - print ''; - print ''; - - // Block adherent - print ''; - print ''; - - // Block expense report - print ''; - print ''; - - // Block holiday - print ''; - print ''; - } - - print '
'; - print $langs->trans("DashboardDisableBlocks"); - print ''; - print '
' . $langs->trans('DashboardDisableGlobal') . ''; - print ajax_constantonoff("MAIN_DISABLE_GLOBAL_WORKBOARD", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('MAIN_DISABLE_METEO') . ''; - print ajax_constantonoff("MAIN_DISABLE_METEO", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockAgenda') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_AGENDA", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockProject') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_PROJECT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockCustomer') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_CUSTOMER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockSupplier') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_SUPPLIER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockContract') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_CONTRACT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockTicket') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_TICKET", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockBank') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_BANK", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockAdherent') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_ADHERENT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockExpenseReport') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_EXPENSEREPORT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . $langs->trans('DashboardDisableBlockHoliday') . ''; - print ajax_constantonoff("MAIN_DISABLE_BLOCK_HOLIDAY", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); - print '
' . "\n"; - print '
'; -} - if ($mode == 'other') { print '
'; print ''; @@ -587,6 +463,133 @@ if ($mode == 'other') { print ''; } + +if ($mode == 'template') { + // Themes and themes options + showSkins(null, 1); +} + + +if ($mode == 'dashboard') { + print '
'; + print '
'; + + // Message of the day on home page + $substitutionarray = getCommonSubstitutionArray($langs, 0, array('object', 'objectamount')); + complete_substitutions_array($substitutionarray, $langs); + + print '' . "\n"; + + /* no more need for this option. It is now a widget already controlled by end user + print ''; + print ''; + */ + + print '
'; + $texthelp = $langs->trans("FollowingConstantsWillBeSubstituted") . '
'; + foreach ($substitutionarray as $key => $val) { + $texthelp .= $key . '
'; + } + print $form->textwithpicto($langs->trans("MessageOfDay"), $texthelp, 1, 'help', '', 0, 2, 'tooltipmessageofday'); + + print '
'; + + $doleditor = new DolEditor('main_motd', (isset($conf->global->MAIN_MOTD) ? $conf->global->MAIN_MOTD : ''), '', 142, 'dolibarr_notes', 'In', false, true, true, ROWS_4, '90%'); + $doleditor->Create(); + + print '
' . $langs->trans('BoxstatsDisableGlobal') . ''; + print ajax_constantonoff("MAIN_DISABLE_GLOBAL_BOXSTATS", array(), $conf->entity, 0, 0, 1, 0); + print '
'; + print '
'; + + print '
'; + + print '
'; + print ''; + + print ''; + + print ''; + print ''; + + if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { + // Block meteo + print ''; + print ''; + + // Block agenda + print ''; + print ''; + + // Block agenda + print ''; + print ''; + + // Block customer + print ''; + print ''; + + // Block supplier + print ''; + print ''; + + // Block contract + print ''; + print ''; + + // Block ticket + print ''; + print ''; + + // Block bank + print ''; + print ''; + + // Block adherent + print ''; + print ''; + + // Block expense report + print ''; + print ''; + + // Block holiday + print ''; + print ''; + } + + print '
'; + print $langs->trans("DashboardDisableBlocks"); + print ''; + print '
' . $langs->trans('DashboardDisableGlobal') . ''; + print ajax_constantonoff("MAIN_DISABLE_GLOBAL_WORKBOARD", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('MAIN_DISABLE_METEO') . ''; + print ajax_constantonoff("MAIN_DISABLE_METEO", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockAgenda') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_AGENDA", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockProject') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_PROJECT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockCustomer') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_CUSTOMER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockSupplier') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_SUPPLIER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockContract') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_CONTRACT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockTicket') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_TICKET", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockBank') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_BANK", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockAdherent') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_ADHERENT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockExpenseReport') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_EXPENSEREPORT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . $langs->trans('DashboardDisableBlockHoliday') . ''; + print ajax_constantonoff("MAIN_DISABLE_BLOCK_HOLIDAY", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard'); + print '
' . "\n"; + print '
'; +} + + if ($mode == 'login') { // Other print '
'; diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index ac3de08af10..8c4d958abac 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -637,6 +637,18 @@ function setConstant(url, code, input, entity, strict, forcereload, userid, toke url = url + "?dol_resetcache=1"; } } + var page_y = $(document).scrollTop(); + url = url.replace(/page_y=\d+/g, ''); + if (page_y > 0) { + if (url.indexOf('?') > -1) { + url = url + "&page_y="+page_y; + } else { + url = url + "?page_y="+page_y; + } + } + url = url.replace(/&&+/, '&'); + console.log("url ro redirect = "+url); + window.location.href = url; //location.reload(); return false; @@ -718,6 +730,18 @@ function delConstant(url, code, input, entity, strict, forcereload, userid, toke url = url + "?dol_resetcache=1"; } } + var page_y = $(document).scrollTop(); + url = url.replace(/page_y=\d+/g, ''); + if (page_y > 0) { + if (url.indexOf('?') > -1) { + url = url + "&page_y="+page_y; + } else { + url = url + "?page_y="+page_y; + } + } + url = url.replace(/&&+/, '&'); + console.log("url ro redirect = "+url); + window.location.href = url; //location.reload(); return false; From e9d7e216e29525b93c97dc6fa91232602995291b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 12:13:31 +0200 Subject: [PATCH 406/473] Debug v16 --- htdocs/admin/system/phpinfo.php | 16 ++++++++++ htdocs/admin/tools/update.php | 11 +++++-- htdocs/install/check.php | 54 ++++++++++++++++++++++++--------- htdocs/langs/en_US/install.lang | 7 ----- 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/htdocs/admin/system/phpinfo.php b/htdocs/admin/system/phpinfo.php index ac51ce33dc3..c9324565e5b 100644 --- a/htdocs/admin/system/phpinfo.php +++ b/htdocs/admin/system/phpinfo.php @@ -183,6 +183,22 @@ print "".$name.""; print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions); print ""; +$functions = ["easter_date"]; +$name = "Calendar"; + +print ""; +print "".$name.""; +print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions); +print ""; + +$functions = ["simplexml_load_string"]; +$name = "Xml"; + +print ""; +print "".$name.""; +print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions); +print ""; + if (empty($_SERVER["SERVER_ADMIN"]) || $_SERVER["SERVER_ADMIN"] != 'doliwamp@localhost') { $functions = ["locale_get_primary_language", "locale_get_region"]; $name = "Intl"; diff --git a/htdocs/admin/tools/update.php b/htdocs/admin/tools/update.php index ea9ca86e994..902e68b381e 100644 --- a/htdocs/admin/tools/update.php +++ b/htdocs/admin/tools/update.php @@ -61,7 +61,11 @@ $version = '0.0'; if ($action == 'getlastversion') { $result = getURLContent('https://sourceforge.net/projects/dolibarr/rss'); //var_dump($result['content']); - $sfurl = simplexml_load_string($result['content'], 'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET); + if (function_exists('simplexml_load_string')) { + $sfurl = simplexml_load_string($result['content'], 'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET); + } else { + $sfurl = 'xml_not_available'; + } } @@ -82,7 +86,10 @@ if (function_exists('curl_init')) { $conf->global->MAIN_USE_RESPONSE_TIMEOUT = 10; if ($action == 'getlastversion') { - if ($sfurl) { + if ($sfurl == 'xml_not_available') { + $langs->load("errors"); + print $langs->trans("LastStableVersion").' : '.$langs->trans("ErrorFunctionNotAvailableInPHP", 'simplexml_load_string').'
'; + } elseif ($sfurl) { $i = 0; while (!empty($sfurl->channel[0]->item[$i]->title) && $i < 10000) { $title = $sfurl->channel[0]->item[$i]->title; diff --git a/htdocs/install/check.php b/htdocs/install/check.php index f260be4f9fb..e9023b6389c 100644 --- a/htdocs/install/check.php +++ b/htdocs/install/check.php @@ -118,10 +118,28 @@ if (!function_exists("session_id")) { } +// Check for mbstring extension +if (!extension_loaded("mbstring")) { + $langs->load("errors"); + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "MBString")."
\n"; + // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) +} else { + print 'Ok '.$langs->trans("PHPSupport", "MBString")."
\n"; +} + +// Check for json extension +if (!extension_loaded("json")) { + $langs->load("errors"); + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "JSON")."
\n"; + // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) +} else { + print 'Ok '.$langs->trans("PHPSupport", "JSON")."
\n"; +} + // Check if GD is supported (we need GD for image conversion) if (!function_exists("imagecreate")) { $langs->load("errors"); - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportGD")."
\n"; + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "GD")."
\n"; // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) } else { print 'Ok '.$langs->trans("PHPSupport", "GD")."
\n"; @@ -131,7 +149,7 @@ if (!function_exists("imagecreate")) { // Check if Curl is supported if (!function_exists("curl_init")) { $langs->load("errors"); - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportCurl")."
\n"; + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "Curl")."
\n"; // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) } else { print 'Ok '.$langs->trans("PHPSupport", "Curl")."
\n"; @@ -139,41 +157,49 @@ if (!function_exists("curl_init")) { // Check if PHP calendar extension is available if (!function_exists("easter_date")) { - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportCalendar")."
\n"; + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "Calendar")."
\n"; } else { print 'Ok '.$langs->trans("PHPSupport", "Calendar")."
\n"; } +// Check if Curl is supported +if (!function_exists("simplexml_load_string")) { + $langs->load("errors"); + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "Xml")."
\n"; + // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) +} else { + print 'Ok '.$langs->trans("PHPSupport", "Xml")."
\n"; +} // Check if UTF8 is supported if (!function_exists("utf8_encode")) { $langs->load("errors"); - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportUTF8")."
\n"; + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "UTF8")."
\n"; // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) } else { print 'Ok '.$langs->trans("PHPSupport", "UTF8")."
\n"; } -// Check for mbstring extension -if (!extension_loaded("mbstring")) { - $langs->load("errors"); - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportMbstring")."
\n"; - // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) -} else { - print 'Ok '.$langs->trans("PHPSupport", "mbstring")."
\n"; -} - // Check if intl methods are supported if (empty($_SERVER["SERVER_ADMIN"]) || $_SERVER["SERVER_ADMIN"] != 'doliwamp@localhost') { if (!function_exists("locale_get_primary_language") || !function_exists("locale_get_region")) { $langs->load("errors"); - print 'Error '.$langs->trans("ErrorPHPDoesNotSupportIntl")."
\n"; + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "Intl")."
\n"; // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) } else { print 'Ok '.$langs->trans("PHPSupport", "Intl")."
\n"; } } +// Check if Curl is supported +if (!function_exists("imap_open")) { + $langs->load("errors"); + print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "IMAP")."
\n"; + // $checksok = 0; // If ko, just warning. So check must still be 1 (otherwise no way to install) +} else { + print 'Ok '.$langs->trans("PHPSupport", "IMAP")."
\n"; +} + if (!class_exists('ZipArchive')) { $langs->load("errors"); print 'Error '.$langs->trans("ErrorPHPDoesNotSupport", "ZIP")."
\n"; diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 18a2eee941c..9d76ad15d43 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -17,13 +17,6 @@ PHPMemoryOK=Your PHP max session memory is set to %s. This should be enou PHPMemoryTooLow=Your PHP max session memory is set to %s bytes. This is too low. Change your php.ini to set memory_limit parameter to at least %s bytes. Recheck=Click here for a more detailed test ErrorPHPDoesNotSupportSessions=Your PHP installation does not support sessions. This feature is required to allow Dolibarr to work. Check your PHP setup and permissions of the sessions directory. -ErrorPHPDoesNotSupportGD=Your PHP installation does not support GD graphical functions. No graphs will be available. -ErrorPHPDoesNotSupportCurl=Your PHP installation does not support Curl. -ErrorPHPDoesNotSupportCalendar=Your PHP installation does not support php calendar extensions. -ErrorPHPDoesNotSupportUTF8=Your PHP installation does not support UTF8 functions. Dolibarr cannot work correctly. Resolve this before installing Dolibarr. -ErrorPHPDoesNotSupportIntl=Your PHP installation does not support Intl functions. -ErrorPHPDoesNotSupportMbstring=Your PHP installation does not support mbstring functions. -ErrorPHPDoesNotSupportxDebug=Your PHP installation does not support extend debug functions. ErrorPHPDoesNotSupport=Your PHP installation does not support %s functions. ErrorDirDoesNotExists=Directory %s does not exist. ErrorGoBackAndCorrectParameters=Go back and check/correct the parameters. From 333b22b961507a60156802a2ccbf9b8de9bfc383 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 9 May 2022 14:32:47 +0200 Subject: [PATCH 407/473] fix: limit filename lenght to show glasses --- htdocs/core/class/html.formfile.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index c01ff5af541..a9f79095242 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -892,7 +892,7 @@ class FormFile } $out .= '>'; $out .= img_mime($file["name"], $langs->trans("File").': '.$file["name"]); - $out .= dol_trunc($file["name"], 150); + $out .= dol_trunc($file["name"], 40); $out .= ''."\n"; $out .= $this->showPreview($file, $modulepart, $relativepath, 0, $param); $out .= ''; From 86a8ae8c3dc25a845be8efbec1c3e89774f5f07e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 15:24:46 +0200 Subject: [PATCH 408/473] NEW Suggest a way to run upgrade per entities. --- ChangeLog | 2 +- htdocs/install/upgrade2.php | 776 +++++++++++++++++++----------------- 2 files changed, 417 insertions(+), 361 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a0a95aab9e..a458f7eea74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,7 +39,7 @@ Following changes may create regressions for some external modules, but were nec * Move massaction 'confirm_createbills' from actions_massactions.inc.php to commande/list.php * Method fetch_all_resources(), fetch_all_used(), fetch_all_available() of DolResource has been removed (they were not used by core code). * Method fetch_all of DolResource has been renamed into fetchAll() to match naming conventions. - +* The hook 'upgrade' and 'doUpgrade2" has been renamed 'doUpgradeBefore' and 'doUpgradeAfterDB'. A new trigger 'doUpgradeAfterFiles' has been introduced. ***** ChangeLog for 15.0.1 compared to 15.0.0 ***** FIX: #19777 #20281 diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 924d251702c..cda8fc0bc13 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -167,20 +167,17 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ } $conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey; - // Chargement config - if (!$error) { - $conf->setValues($db); - // Reset forced setup after the setValues - if (defined('SYSLOG_FILE')) { - $conf->global->SYSLOG_FILE = constant('SYSLOG_FILE'); - } - $conf->global->MAIN_ENABLE_LOG_TO_HTML = 1; - } + + $listofentities = array(1); // Create the global $hookmanager object include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager = new HookManager($db); - $hookmanager->initHooks(array('upgrade')); + $reshook = $hookmanager->initHooks(array('doUpgradeBefore')); + if ($reshook >= 0 && is_array($hookmanager->resArray)) { + // Example: $hookmanager->resArray = array(2, 3, 10); + $listofentities = array_unique(array_merge($listofentities, $hookmanager->resArray)); + } /*************************************************************************************** @@ -188,385 +185,399 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ * Migration of data * ***************************************************************************************/ + + // Force to execute this at begin to avoid the new core code into Dolibarr to be broken. + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN birth date'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN dateemployment date'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN dateemploymentend date'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN default_range integer'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN default_c_exp_tax_cat integer'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN langs varchar(24)'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN fieldcomputed text'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN fielddefault varchar(255)'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX."extrafields ADD COLUMN enabled varchar(255) DEFAULT '1'"; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN help text'; + $db->query($sql, 1); + $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user_rights ADD COLUMN entity integer DEFAULT 1 NOT NULL'; + $db->query($sql, 1); + + $db->begin(); - if (!$error) { - // Current version is $conf->global->MAIN_VERSION_LAST_UPGRADE - // Version to install is DOL_VERSION - $dolibarrlastupgradeversionarray = preg_split('/[\.-]/', isset($conf->global->MAIN_VERSION_LAST_UPGRADE) ? $conf->global->MAIN_VERSION_LAST_UPGRADE : (isset($conf->global->MAIN_VERSION_LAST_INSTALL) ? $conf->global->MAIN_VERSION_LAST_INSTALL : '')); - - // Chaque action de migration doit renvoyer une ligne sur 4 colonnes avec - // dans la 1ere colonne, la description de l'action a faire - // dans la 4eme colonne, le texte 'OK' si fait ou 'AlreadyDone' si rien n'est fait ou 'Error' - - $versiontoarray = explode('.', $versionto); - $versionranarray = explode('.', DOL_VERSION); - - - // Force to execute this at begin to avoid the new core code into Dolibarr to be broken. - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN birth date'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN dateemployment date'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN dateemploymentend date'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN default_range integer'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user ADD COLUMN default_c_exp_tax_cat integer'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN langs varchar(24)'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN fieldcomputed text'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN fielddefault varchar(255)'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX."extrafields ADD COLUMN enabled varchar(255) DEFAULT '1'"; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'extrafields ADD COLUMN help text'; - $db->query($sql, 1); - $sql = 'ALTER TABLE '.MAIN_DB_PREFIX.'user_rights ADD COLUMN entity integer DEFAULT 1 NOT NULL'; - $db->query($sql, 1); - - - $afterversionarray = explode('.', '2.0.0'); - $beforeversionarray = explode('.', '2.7.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - // Script pour V2 -> V2.1 - migrate_paiements($db, $langs, $conf); - - migrate_contracts_det($db, $langs, $conf); - - migrate_contracts_date1($db, $langs, $conf); - - migrate_contracts_date2($db, $langs, $conf); - - migrate_contracts_date3($db, $langs, $conf); - - migrate_contracts_open($db, $langs, $conf); - - migrate_modeles($db, $langs, $conf); - - migrate_price_propal($db, $langs, $conf); - - migrate_price_commande($db, $langs, $conf); - - migrate_price_commande_fournisseur($db, $langs, $conf); - - migrate_price_contrat($db, $langs, $conf); - - migrate_paiementfourn_facturefourn($db, $langs, $conf); - - - // Script pour V2.1 -> V2.2 - migrate_paiements_orphelins_1($db, $langs, $conf); - - migrate_paiements_orphelins_2($db, $langs, $conf); - - migrate_links_transfert($db, $langs, $conf); - - - // Script pour V2.2 -> V2.4 - migrate_commande_expedition($db, $langs, $conf); - - migrate_commande_livraison($db, $langs, $conf); - - migrate_detail_livraison($db, $langs, $conf); - - - // Script pour V2.5 -> V2.6 - migrate_stocks($db, $langs, $conf); - - - // Script pour V2.6 -> V2.7 - migrate_menus($db, $langs, $conf); - - migrate_commande_deliveryaddress($db, $langs, $conf); - - migrate_restore_missing_links($db, $langs, $conf); - - migrate_rename_directories($db, $langs, $conf, '/compta', '/banque'); - - migrate_rename_directories($db, $langs, $conf, '/societe', '/mycompany'); + foreach ($listofentities as $entity) { + // Set $conf context for entity + $conf->setEntityValues($db, $entity); + // Reset forced setup after the setValues + if (defined('SYSLOG_FILE')) { + $conf->global->SYSLOG_FILE = constant('SYSLOG_FILE'); } + $conf->global->MAIN_ENABLE_LOG_TO_HTML = 1; - // Script for 2.8 - $afterversionarray = explode('.', '2.7.9'); - $beforeversionarray = explode('.', '2.8.9'); - //print $versionto.' '.versioncompare($versiontoarray,$afterversionarray).' '.versioncompare($versiontoarray,$beforeversionarray); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_price_facture($db, $langs, $conf); // Code of this function works for 2.8+ because need a field tva_tx + if (!$error) { + if (count($listofentities) > 1) { + print '*** '.$langs->trans("Entity").' '.$entity.''."\n"; + } - migrate_relationship_tables($db, $langs, $conf, 'co_exp', 'fk_commande', 'commande', 'fk_expedition', 'shipping'); + // Current version is $conf->global->MAIN_VERSION_LAST_UPGRADE + // Version to install is DOL_VERSION + $dolibarrlastupgradeversionarray = preg_split('/[\.-]/', isset($conf->global->MAIN_VERSION_LAST_UPGRADE) ? $conf->global->MAIN_VERSION_LAST_UPGRADE : (isset($conf->global->MAIN_VERSION_LAST_INSTALL) ? $conf->global->MAIN_VERSION_LAST_INSTALL : '')); - migrate_relationship_tables($db, $langs, $conf, 'pr_exp', 'fk_propal', 'propal', 'fk_expedition', 'shipping'); + // Chaque action de migration doit renvoyer une ligne sur 4 colonnes avec + // dans la 1ere colonne, la description de l'action a faire + // dans la 4eme colonne, le texte 'OK' si fait ou 'AlreadyDone' si rien n'est fait ou 'Error' - migrate_relationship_tables($db, $langs, $conf, 'pr_liv', 'fk_propal', 'propal', 'fk_livraison', 'delivery'); + $versiontoarray = explode('.', $versionto); + $versionranarray = explode('.', DOL_VERSION); - migrate_relationship_tables($db, $langs, $conf, 'co_liv', 'fk_commande', 'commande', 'fk_livraison', 'delivery'); - migrate_relationship_tables($db, $langs, $conf, 'co_pr', 'fk_propale', 'propal', 'fk_commande', 'commande'); + $afterversionarray = explode('.', '2.0.0'); + $beforeversionarray = explode('.', '2.7.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + // Script pour V2 -> V2.1 + migrate_paiements($db, $langs, $conf); - migrate_relationship_tables($db, $langs, $conf, 'fa_pr', 'fk_propal', 'propal', 'fk_facture', 'facture'); + migrate_contracts_det($db, $langs, $conf); - migrate_relationship_tables($db, $langs, $conf, 'co_fa', 'fk_commande', 'commande', 'fk_facture', 'facture'); + migrate_contracts_date1($db, $langs, $conf); - migrate_project_user_resp($db, $langs, $conf); + migrate_contracts_date2($db, $langs, $conf); - migrate_project_task_actors($db, $langs, $conf); - } + migrate_contracts_date3($db, $langs, $conf); - // Script for 2.9 - $afterversionarray = explode('.', '2.8.9'); - $beforeversionarray = explode('.', '2.9.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_project_task_time($db, $langs, $conf); + migrate_contracts_open($db, $langs, $conf); - migrate_customerorder_shipping($db, $langs, $conf); + migrate_modeles($db, $langs, $conf); - migrate_shipping_delivery($db, $langs, $conf); + migrate_price_propal($db, $langs, $conf); - migrate_shipping_delivery2($db, $langs, $conf); - } + migrate_price_commande($db, $langs, $conf); - // Script for 3.0 - $afterversionarray = explode('.', '2.9.9'); - $beforeversionarray = explode('.', '3.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - // No particular code - } + migrate_price_commande_fournisseur($db, $langs, $conf); - // Script for 3.1 - $afterversionarray = explode('.', '3.0.9'); - $beforeversionarray = explode('.', '3.1.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_rename_directories($db, $langs, $conf, '/rss', '/externalrss'); + migrate_price_contrat($db, $langs, $conf); - migrate_actioncomm_element($db, $langs, $conf); - } + migrate_paiementfourn_facturefourn($db, $langs, $conf); - // Script for 3.2 - $afterversionarray = explode('.', '3.1.9'); - $beforeversionarray = explode('.', '3.2.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_price_contrat($db, $langs, $conf); - migrate_mode_reglement($db, $langs, $conf); + // Script pour V2.1 -> V2.2 + migrate_paiements_orphelins_1($db, $langs, $conf); - migrate_clean_association($db, $langs, $conf); - } + migrate_paiements_orphelins_2($db, $langs, $conf); - // Script for 3.3 - $afterversionarray = explode('.', '3.2.9'); - $beforeversionarray = explode('.', '3.3.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_categorie_association($db, $langs, $conf); - } + migrate_links_transfert($db, $langs, $conf); - // Script for 3.4 - // No specific scripts - // Tasks to do always and only into last targeted version - $afterversionarray = explode('.', '3.6.9'); // target is after this - $beforeversionarray = explode('.', '3.7.9'); // target is before this - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_event_assignement($db, $langs, $conf); - } + // Script pour V2.2 -> V2.4 + migrate_commande_expedition($db, $langs, $conf); - // Scripts for 3.9 - $afterversionarray = explode('.', '3.7.9'); - $beforeversionarray = explode('.', '3.8.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - // No particular code - } + migrate_commande_livraison($db, $langs, $conf); - // Scripts for 4.0 - $afterversionarray = explode('.', '3.9.9'); - $beforeversionarray = explode('.', '4.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_rename_directories($db, $langs, $conf, '/fckeditor', '/medias'); - } + migrate_detail_livraison($db, $langs, $conf); - // Scripts for 5.0 - $afterversionarray = explode('.', '4.0.9'); - $beforeversionarray = explode('.', '5.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - // Migrate to add entity value into llx_societe_remise - migrate_remise_entity($db, $langs, $conf); - // Migrate to add entity value into llx_societe_remise_except - migrate_remise_except_entity($db, $langs, $conf); - } + // Script pour V2.5 -> V2.6 + migrate_stocks($db, $langs, $conf); - // Scripts for 6.0 - $afterversionarray = explode('.', '5.0.9'); - $beforeversionarray = explode('.', '6.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - if (!empty($conf->multicompany->enabled)) { - global $multicompany_transverse_mode; - // Only if the transverse mode is not used - if (empty($multicompany_transverse_mode)) { - // Migrate to add entity value into llx_user_rights - migrate_user_rights_entity($db, $langs, $conf); + // Script pour V2.6 -> V2.7 + migrate_menus($db, $langs, $conf); - // Migrate to add entity value into llx_usergroup_rights - migrate_usergroup_rights_entity($db, $langs, $conf); + migrate_commande_deliveryaddress($db, $langs, $conf); + + migrate_restore_missing_links($db, $langs, $conf); + + migrate_rename_directories($db, $langs, $conf, '/compta', '/banque'); + + migrate_rename_directories($db, $langs, $conf, '/societe', '/mycompany'); + } + + // Script for 2.8 + $afterversionarray = explode('.', '2.7.9'); + $beforeversionarray = explode('.', '2.8.9'); + //print $versionto.' '.versioncompare($versiontoarray,$afterversionarray).' '.versioncompare($versiontoarray,$beforeversionarray); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_price_facture($db, $langs, $conf); // Code of this function works for 2.8+ because need a field tva_tx + + migrate_relationship_tables($db, $langs, $conf, 'co_exp', 'fk_commande', 'commande', 'fk_expedition', 'shipping'); + + migrate_relationship_tables($db, $langs, $conf, 'pr_exp', 'fk_propal', 'propal', 'fk_expedition', 'shipping'); + + migrate_relationship_tables($db, $langs, $conf, 'pr_liv', 'fk_propal', 'propal', 'fk_livraison', 'delivery'); + + migrate_relationship_tables($db, $langs, $conf, 'co_liv', 'fk_commande', 'commande', 'fk_livraison', 'delivery'); + + migrate_relationship_tables($db, $langs, $conf, 'co_pr', 'fk_propale', 'propal', 'fk_commande', 'commande'); + + migrate_relationship_tables($db, $langs, $conf, 'fa_pr', 'fk_propal', 'propal', 'fk_facture', 'facture'); + + migrate_relationship_tables($db, $langs, $conf, 'co_fa', 'fk_commande', 'commande', 'fk_facture', 'facture'); + + migrate_project_user_resp($db, $langs, $conf); + + migrate_project_task_actors($db, $langs, $conf); + } + + // Script for 2.9 + $afterversionarray = explode('.', '2.8.9'); + $beforeversionarray = explode('.', '2.9.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_project_task_time($db, $langs, $conf); + + migrate_customerorder_shipping($db, $langs, $conf); + + migrate_shipping_delivery($db, $langs, $conf); + + migrate_shipping_delivery2($db, $langs, $conf); + } + + // Script for 3.0 + $afterversionarray = explode('.', '2.9.9'); + $beforeversionarray = explode('.', '3.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + // No particular code + } + + // Script for 3.1 + $afterversionarray = explode('.', '3.0.9'); + $beforeversionarray = explode('.', '3.1.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_rename_directories($db, $langs, $conf, '/rss', '/externalrss'); + + migrate_actioncomm_element($db, $langs, $conf); + } + + // Script for 3.2 + $afterversionarray = explode('.', '3.1.9'); + $beforeversionarray = explode('.', '3.2.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_price_contrat($db, $langs, $conf); + + migrate_mode_reglement($db, $langs, $conf); + + migrate_clean_association($db, $langs, $conf); + } + + // Script for 3.3 + $afterversionarray = explode('.', '3.2.9'); + $beforeversionarray = explode('.', '3.3.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_categorie_association($db, $langs, $conf); + } + + // Script for 3.4 + // No specific scripts + + // Tasks to do always and only into last targeted version + $afterversionarray = explode('.', '3.6.9'); // target is after this + $beforeversionarray = explode('.', '3.7.9'); // target is before this + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_event_assignement($db, $langs, $conf); + } + + // Scripts for 3.9 + $afterversionarray = explode('.', '3.7.9'); + $beforeversionarray = explode('.', '3.8.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + // No particular code + } + + // Scripts for 4.0 + $afterversionarray = explode('.', '3.9.9'); + $beforeversionarray = explode('.', '4.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_rename_directories($db, $langs, $conf, '/fckeditor', '/medias'); + } + + // Scripts for 5.0 + $afterversionarray = explode('.', '4.0.9'); + $beforeversionarray = explode('.', '5.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + // Migrate to add entity value into llx_societe_remise + migrate_remise_entity($db, $langs, $conf); + + // Migrate to add entity value into llx_societe_remise_except + migrate_remise_except_entity($db, $langs, $conf); + } + + // Scripts for 6.0 + $afterversionarray = explode('.', '5.0.9'); + $beforeversionarray = explode('.', '6.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + if (!empty($conf->multicompany->enabled)) { + global $multicompany_transverse_mode; + + // Only if the transverse mode is not used + if (empty($multicompany_transverse_mode)) { + // Migrate to add entity value into llx_user_rights + migrate_user_rights_entity($db, $langs, $conf); + + // Migrate to add entity value into llx_usergroup_rights + migrate_usergroup_rights_entity($db, $langs, $conf); + } } } - } - // Scripts for 7.0 - $afterversionarray = explode('.', '6.0.9'); - $beforeversionarray = explode('.', '7.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - // Migrate contact association - migrate_event_assignement_contact($db, $langs, $conf); + // Scripts for 7.0 + $afterversionarray = explode('.', '6.0.9'); + $beforeversionarray = explode('.', '7.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + // Migrate contact association + migrate_event_assignement_contact($db, $langs, $conf); - migrate_reset_blocked_log($db, $langs, $conf); - } - - // Scripts for 8.0 - $afterversionarray = explode('.', '7.0.9'); - $beforeversionarray = explode('.', '8.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_rename_directories($db, $langs, $conf, '/contracts', '/contract'); - } - - // Scripts for 9.0 - $afterversionarray = explode('.', '8.0.9'); - $beforeversionarray = explode('.', '9.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_user_photospath(); - } - - // Scripts for 11.0 - $afterversionarray = explode('.', '10.0.9'); - $beforeversionarray = explode('.', '11.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_users_socialnetworks(); - migrate_members_socialnetworks(); - migrate_contacts_socialnetworks(); - migrate_thirdparties_socialnetworks(); - } - - // Scripts for 14.0 - $afterversionarray = explode('.', '13.0.9'); - $beforeversionarray = explode('.', '14.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_export_import_profiles('export'); - migrate_export_import_profiles('import'); - } - - // Scripts for 16.0 - $afterversionarray = explode('.', '15.0.9'); - $beforeversionarray = explode('.', '16.0.9'); - if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { - migrate_user_photospath2(); - } - } - - - // Code executed only if migration is LAST ONE. Must always be done. - if (versioncompare($versiontoarray, $versionranarray) >= 0 || versioncompare($versiontoarray, $versionranarray) <= -3) { - // Reload modules (this must be always done and only into last targeted version, because code to reload module may need table structure of last version) - $listofmodule = array( - 'MAIN_MODULE_ACCOUNTING'=>'newboxdefonly', - 'MAIN_MODULE_AGENDA'=>'newboxdefonly', - 'MAIN_MODULE_BOM'=>'menuonly', - 'MAIN_MODULE_BANQUE'=>'menuonly', - 'MAIN_MODULE_BARCODE'=>'newboxdefonly', - 'MAIN_MODULE_CRON'=>'newboxdefonly', - 'MAIN_MODULE_COMMANDE'=>'newboxdefonly', - 'MAIN_MODULE_BLOCKEDLOG'=>'noboxes', - 'MAIN_MODULE_DEPLACEMENT'=>'newboxdefonly', - 'MAIN_MODULE_DON'=>'newboxdefonly', - 'MAIN_MODULE_ECM'=>'newboxdefonly', - 'MAIN_MODULE_EXTERNALSITE'=>'newboxdefonly', - 'MAIN_MODULE_EXPENSEREPORT'=>'newboxdefonly', - 'MAIN_MODULE_FACTURE'=>'newboxdefonly', - 'MAIN_MODULE_FOURNISSEUR'=>'newboxdefonly', - 'MAIN_MODULE_HOLIDAY'=>'newboxdefonly', - 'MAIN_MODULE_MARGIN'=>'menuonly', - 'MAIN_MODULE_MRP'=>'menuonly', - 'MAIN_MODULE_OPENSURVEY'=>'newboxdefonly', - 'MAIN_MODULE_PAYBOX'=>'newboxdefonly', - 'MAIN_MODULE_PRINTING'=>'newboxdefonly', - 'MAIN_MODULE_PRODUIT'=>'newboxdefonly', - 'MAIN_MODULE_RECRUITMENT'=>'menuonly', - 'MAIN_MODULE_RESOURCE'=>'noboxes', - 'MAIN_MODULE_SALARIES'=>'newboxdefonly', - 'MAIN_MODULE_SERVICE'=>'newboxdefonly', - 'MAIN_MODULE_SYSLOG'=>'newboxdefonly', - 'MAIN_MODULE_SOCIETE'=>'newboxdefonly', - 'MAIN_MODULE_STRIPE'=>'menuonly', - 'MAIN_MODULE_TICKET'=>'newboxdefonly', - 'MAIN_MODULE_TAKEPOS'=>'newboxdefonly', - 'MAIN_MODULE_USER'=>'newboxdefonly', //This one must be always done and only into last targeted version) - 'MAIN_MODULE_VARIANTS'=>'newboxdefonly', - 'MAIN_MODULE_WEBSITE'=>'newboxdefonly', - ); - - $result = migrate_reload_modules($db, $langs, $conf, $listofmodule); - if ($result < 0) { - $error++; - } - // Reload menus (this must be always and only into last targeted version) - $result = migrate_reload_menu($db, $langs, $conf); - if ($result < 0) { - $error++; - } - } - - // Can force activation of some module during migration with parameter 'enablemodules=MAIN_MODULE_XXX,MAIN_MODULE_YYY,...' - // In most cases (online install or upgrade) $enablemodules is empty. Can be forced when ran from command line. - if (!$error && $enablemodules) { - // Reload modules (this must be always done and only into last targeted version) - $listofmodules = array(); - $enablemodules = preg_replace('/enablemodules=/', '', $enablemodules); - $tmplistofmodules = explode(',', $enablemodules); - foreach ($tmplistofmodules as $value) { - $listofmodules[$value] = 'forceactivate'; - } - - $resultreloadmodules = migrate_reload_modules($db, $langs, $conf, $listofmodules, 1); - if ($resultreloadmodules < 0) { - $error++; - } - } - - - // Can call a dedicated external upgrade process - if (!$error) { - $parameters = array('versionfrom' => $versionfrom, 'versionto' => $versionto); - $object = new stdClass(); - $action = "upgrade"; - $reshook = $hookmanager->executeHooks('doUpgrade2', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks - if ($hookmanager->resNbOfHooks > 0) { - if ($reshook < 0) { - print ''; - print ''.$langs->trans('UpgradeExternalModule').': '; - print $hookmanager->error; - print ""; - print ''; - } else { - print ''; - print ''.$langs->trans('UpgradeExternalModule').': OK'; - print ""; - print ''; + migrate_reset_blocked_log($db, $langs, $conf); } - } else { - //if (! empty($conf->modules)) - if (!empty($conf->modules_parts['hooks'])) { // If there is at least one module with one hook, we show message to say nothing was done - print ''; - print ''.$langs->trans('UpgradeExternalModule').': '.$langs->trans("None"); - print ''; + + // Scripts for 8.0 + $afterversionarray = explode('.', '7.0.9'); + $beforeversionarray = explode('.', '8.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_rename_directories($db, $langs, $conf, '/contracts', '/contract'); + } + + // Scripts for 9.0 + $afterversionarray = explode('.', '8.0.9'); + $beforeversionarray = explode('.', '9.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_user_photospath(); + } + + // Scripts for 11.0 + $afterversionarray = explode('.', '10.0.9'); + $beforeversionarray = explode('.', '11.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_users_socialnetworks(); + migrate_members_socialnetworks(); + migrate_contacts_socialnetworks(); + migrate_thirdparties_socialnetworks(); + } + + // Scripts for 14.0 + $afterversionarray = explode('.', '13.0.9'); + $beforeversionarray = explode('.', '14.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_export_import_profiles('export'); + migrate_export_import_profiles('import'); + } + + // Scripts for 16.0 + $afterversionarray = explode('.', '15.0.9'); + $beforeversionarray = explode('.', '16.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_user_photospath2(); + } + } + + + // Code executed only if migration is LAST ONE. Must always be done. + if (versioncompare($versiontoarray, $versionranarray) >= 0 || versioncompare($versiontoarray, $versionranarray) <= -3) { + // Reload modules (this must be always done and only into last targeted version, because code to reload module may need table structure of last version) + $listofmodule = array( + 'MAIN_MODULE_ACCOUNTING'=>'newboxdefonly', + 'MAIN_MODULE_AGENDA'=>'newboxdefonly', + 'MAIN_MODULE_BOM'=>'menuonly', + 'MAIN_MODULE_BANQUE'=>'menuonly', + 'MAIN_MODULE_BARCODE'=>'newboxdefonly', + 'MAIN_MODULE_CRON'=>'newboxdefonly', + 'MAIN_MODULE_COMMANDE'=>'newboxdefonly', + 'MAIN_MODULE_BLOCKEDLOG'=>'noboxes', + 'MAIN_MODULE_DEPLACEMENT'=>'newboxdefonly', + 'MAIN_MODULE_DON'=>'newboxdefonly', + 'MAIN_MODULE_ECM'=>'newboxdefonly', + 'MAIN_MODULE_EXTERNALSITE'=>'newboxdefonly', + 'MAIN_MODULE_EXPENSEREPORT'=>'newboxdefonly', + 'MAIN_MODULE_FACTURE'=>'newboxdefonly', + 'MAIN_MODULE_FOURNISSEUR'=>'newboxdefonly', + 'MAIN_MODULE_HOLIDAY'=>'newboxdefonly', + 'MAIN_MODULE_MARGIN'=>'menuonly', + 'MAIN_MODULE_MRP'=>'menuonly', + 'MAIN_MODULE_OPENSURVEY'=>'newboxdefonly', + 'MAIN_MODULE_PAYBOX'=>'newboxdefonly', + 'MAIN_MODULE_PRINTING'=>'newboxdefonly', + 'MAIN_MODULE_PRODUIT'=>'newboxdefonly', + 'MAIN_MODULE_RECRUITMENT'=>'menuonly', + 'MAIN_MODULE_RESOURCE'=>'noboxes', + 'MAIN_MODULE_SALARIES'=>'newboxdefonly', + 'MAIN_MODULE_SERVICE'=>'newboxdefonly', + 'MAIN_MODULE_SYSLOG'=>'newboxdefonly', + 'MAIN_MODULE_SOCIETE'=>'newboxdefonly', + 'MAIN_MODULE_STRIPE'=>'menuonly', + 'MAIN_MODULE_TICKET'=>'newboxdefonly', + 'MAIN_MODULE_TAKEPOS'=>'newboxdefonly', + 'MAIN_MODULE_USER'=>'newboxdefonly', //This one must be always done and only into last targeted version) + 'MAIN_MODULE_VARIANTS'=>'newboxdefonly', + 'MAIN_MODULE_WEBSITE'=>'newboxdefonly', + ); + + $result = migrate_reload_modules($db, $langs, $conf, $listofmodule); + if ($result < 0) { + $error++; + } + // Reload menus (this must be always and only into last targeted version) + $result = migrate_reload_menu($db, $langs, $conf); + if ($result < 0) { + $error++; + } + } + + // Can force activation of some module during migration with parameter 'enablemodules=MAIN_MODULE_XXX,MAIN_MODULE_YYY,...' + // In most cases (online install or upgrade) $enablemodules is empty. Can be forced when ran from command line. + if (!$error && $enablemodules) { + // Reload modules (this must be always done and only into last targeted version) + $listofmodules = array(); + $enablemodules = preg_replace('/enablemodules=/', '', $enablemodules); + $tmplistofmodules = explode(',', $enablemodules); + foreach ($tmplistofmodules as $value) { + $listofmodules[$value] = 'forceactivate'; + } + + $resultreloadmodules = migrate_reload_modules($db, $langs, $conf, $listofmodules, 1); + if ($resultreloadmodules < 0) { + $error++; + } + } + + + // Can call a dedicated external upgrade process with hook doUpgradeAfterDB() + if (!$error) { + $parameters = array('versionfrom' => $versionfrom, 'versionto' => $versionto, 'conf'=>$conf); + $object = new stdClass(); + $action = "upgrade"; + $reshook = $hookmanager->executeHooks('doUpgradeAfterDB', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($hookmanager->resNbOfHooks > 0) { + if ($reshook < 0) { + print ''; + print ''.$langs->trans('UpgradeExternalModule').': '; + print $hookmanager->error; + print ""; + print ''; + } else { + print ''; + print ''.$langs->trans('UpgradeExternalModule').' (DB): OK'; + print ""; + print ''; + } + } else { + //if (! empty($conf->modules)) + if (!empty($conf->modules_parts['hooks'])) { // If there is at least one module with one hook, we show message to say nothing was done + print ''; + print ''.$langs->trans('UpgradeExternalModule').': '.$langs->trans("NodoUpgradeAfterDB"); + print ''; + } } } } print ''; - if (!$error) { // Set constant to ask to remake a new ping to inform about upgrade (if first ping was done and OK) $sql = 'UPDATE '.MAIN_DB_PREFIX."const SET VALUE = 'torefresh' WHERE name = 'MAIN_FIRST_PING_OK_ID'"; @@ -576,23 +587,68 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ // We always commit. // Process is designed so we can run it several times whatever is situation. $db->commit(); + + + /*************************************************************************************** + * + * Migration of files + * + ***************************************************************************************/ + + foreach ($listofentities as $entity) { + // Set $conf context for entity + $conf->setEntityValues($db, $entity); + // Reset forced setup after the setValues + if (defined('SYSLOG_FILE')) { + $conf->global->SYSLOG_FILE = constant('SYSLOG_FILE'); + } + $conf->global->MAIN_ENABLE_LOG_TO_HTML = 1; + + + // Copy directory medias + $srcroot = DOL_DOCUMENT_ROOT.'/install/medias'; + $destroot = DOL_DATA_ROOT.'/medias'; + dolCopyDir($srcroot, $destroot, 0, 0); + + + // Actions for all versions (no database change but delete some files and directories) + migrate_delete_old_files($db, $langs, $conf); + migrate_delete_old_dir($db, $langs, $conf); + // Actions for all versions (no database change but create some directories) + dol_mkdir(DOL_DATA_ROOT.'/bank'); + // Actions for all versions (no database change but rename some directories) + migrate_rename_directories($db, $langs, $conf, '/banque/bordereau', '/bank/checkdeposits'); + + + $parameters = array('versionfrom' => $versionfrom, 'versionto' => $versionto, 'conf'=>$conf); + $object = new stdClass(); + $action = "upgrade"; + $reshook = $hookmanager->executeHooks('doUpgradeAfterFiles', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($hookmanager->resNbOfHooks > 0) { + if ($reshook < 0) { + print ''; + print ''.$langs->trans('UpgradeExternalModule').': '; + print $hookmanager->error; + print ""; + print ''; + } else { + print ''; + print ''.$langs->trans('UpgradeExternalModule').' (Files): OK'; + print ""; + print ''; + } + } else { + //if (! empty($conf->modules)) + if (!empty($conf->modules_parts['hooks'])) { // If there is at least one module with one hook, we show message to say nothing was done + print ''; + print ''.$langs->trans('UpgradeExternalModule').': '.$langs->trans("NodoUpgradeAfterFiles"); + print ''; + } + } + } + $db->close(); - - // Copy directory medias - $srcroot = DOL_DOCUMENT_ROOT.'/install/medias'; - $destroot = DOL_DATA_ROOT.'/medias'; - dolCopyDir($srcroot, $destroot, 0, 0); - - - // Actions for all versions (no database change but delete some files and directories) - migrate_delete_old_files($db, $langs, $conf); - migrate_delete_old_dir($db, $langs, $conf); - // Actions for all versions (no database change but create some directories) - dol_mkdir(DOL_DATA_ROOT.'/bank'); - // Actions for all versions (no database change but rename some directories) - migrate_rename_directories($db, $langs, $conf, '/banque/bordereau', '/bank/checkdeposits'); - $silent = 0; if (!$silent) { print ''; From 720a09dacb744c07311f253450a32810e6a618ea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 15:57:10 +0200 Subject: [PATCH 409/473] Fix regression --- htdocs/admin/expensereport_rules.php | 4 ++-- htdocs/comm/propal/card.php | 4 ++-- htdocs/commande/card.php | 4 ++-- htdocs/compta/facture/card.php | 2 +- htdocs/compta/facture/class/facture.class.php | 2 +- htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/lib/functions.lib.php | 4 +++- htdocs/holiday/class/holiday.class.php | 6 +++--- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/htdocs/admin/expensereport_rules.php b/htdocs/admin/expensereport_rules.php index 1146232dca3..62fb097841b 100644 --- a/htdocs/admin/expensereport_rules.php +++ b/htdocs/admin/expensereport_rules.php @@ -266,11 +266,11 @@ foreach ($rules as $rule) { if ($rule->fk_c_type_fees == -1) { echo $langs->trans('AllExpenseReport'); } else { - $key = getDictionaryValue(MAIN_DB_PREFIX . 'c_type_fees', 'code', $rule->fk_c_type_fees, false, 'id'); + $key = getDictionaryValue('c_type_fees', 'code', $rule->fk_c_type_fees, false, 'id'); if ($key && $key != $langs->trans($key)) { echo $langs->trans($key); } else { - $value = getDictionaryValue(MAIN_DB_PREFIX . 'c_type_fees', 'label', $rule->fk_c_type_fees, false, 'id'); + $value = getDictionaryValue('c_type_fees', 'label', $rule->fk_c_type_fees, false, 'id'); echo $langs->trans($value ? $value : 'Undefined'); // TODO check to return trans of 'code' } } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 229919d7e5d..22a816acc1d 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -692,7 +692,7 @@ if (empty($reshook)) { $deposit = null; $locationTarget = ''; - $deposit_percent_from_payment_terms = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id); if ( !$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'alpha') == 'on' @@ -1999,7 +1999,7 @@ if ($action == 'create') { array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => '') // Field to complete private note (not replace) ); - $deposit_percent_from_payment_terms = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id); if (! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)) { require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 6ba7b9086c3..b1d0cdb9223 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1184,7 +1184,7 @@ if (empty($reshook)) { $error = 0; $deposit = null; - $deposit_percent_from_payment_terms = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id); if ( GETPOST('generate_deposit', 'alpha') == 'on' && ! empty($deposit_percent_from_payment_terms) @@ -2025,7 +2025,7 @@ if ($action == 'create' && $usercancreate) { if ($nbMandated > 0 ) $text .= '
'.$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'
'; - $deposit_percent_from_payment_terms = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id); + $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id); if (! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)) { require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index e3fac863c77..7de827ff1d2 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3290,7 +3290,7 @@ if ($action == 'create') { $typedeposit = GETPOST('typedeposit', 'aZ09'); $valuedeposit = GETPOST('valuedeposit', 'int'); if (empty($typedeposit) && ! empty($objectsrc->deposit_percent)) { - $origin_payment_conditions_deposit_percent = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $objectsrc->cond_reglement_id); + $origin_payment_conditions_deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $objectsrc->cond_reglement_id); if (! empty($origin_payment_conditions_deposit_percent)) { $typedeposit = 'variable'; } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 0804f55b1ee..e29ecc251ff 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1501,7 +1501,7 @@ class Facture extends CommonInvoice return null; } - $payment_conditions_deposit_percent = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $origin->cond_reglement_id); + $payment_conditions_deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $origin->cond_reglement_id); if (empty($payment_conditions_deposit_percent)) { $origin->error = 'ErrorPaymentConditionsNotEligibleToDepositCreation'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index cabb50520fb..0758c696e29 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2606,7 +2606,7 @@ abstract class CommonObject } if (empty($deposit_percent) || $deposit_percent < 0) { - $deposit_percent = getDictionaryValue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $id); + $deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $id); } if ($deposit_percent > 100) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5025347dcb2..04713acbc8f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9862,7 +9862,7 @@ function dol_mimetype($file, $default = 'application/octet-stream', $mode = 0) * Return the value of a filed into a dictionary for the record $id. * This also set all the values into a cache for a next search. * - * @param string $tablename Name of dictionary + * @param string $tablename Name of table dictionary (without the MAIN_DB_PREFIX, example: 'c_holiday_types') * @param string $field The name of field where to find the value to return * @param int $id Id of line record * @param bool $checkentity Add filter on entity @@ -9873,6 +9873,8 @@ function getDictionaryValue($tablename, $field, $id, $checkentity = false, $rowi { global $conf, $db; + $tablename = preg_replace('/^'.preg_quote(MAIN_DB_PREFIX, '/').'/', '', $tablename); // Clean name of table for backward compatibility. + $dictvalues = (isset($conf->cache['dictvalues_'.$tablename]) ? $conf->cache['dictvalues_'.$tablename] : null); if (is_null($dictvalues)) { diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index d0bed943429..1e11e81f543 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -704,7 +704,7 @@ class Holiday extends CommonObject require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $error = 0; - $checkBalance = getDictionaryValue(MAIN_DB_PREFIX.'c_holiday_types', 'block_if_negative', $this->fk_type); + $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type); if ($checkBalance > 0) { $balance = $this->getCPforUser($this->fk_user, $this->fk_type); @@ -817,7 +817,7 @@ class Holiday extends CommonObject global $conf, $langs; $error = 0; - $checkBalance = getDictionaryValue(MAIN_DB_PREFIX.'c_holiday_types', 'block_if_negative', $this->fk_type); + $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type); if ($checkBalance > 0) { $balance = $this->getCPforUser($this->fk_user, $this->fk_type); @@ -936,7 +936,7 @@ class Holiday extends CommonObject global $conf, $langs; $error = 0; - $checkBalance = getDictionaryValue(MAIN_DB_PREFIX.'c_holiday_types', 'block_if_negative', $this->fk_type); + $checkBalance = getDictionaryValue('c_holiday_types', 'block_if_negative', $this->fk_type); if ($checkBalance > 0 && $this->statut != self::STATUS_DRAFT) { $balance = $this->getCPforUser($this->fk_user, $this->fk_type); From 43e1486dbb033710382d73a8fa8698239a1e9f77 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 16:42:08 +0200 Subject: [PATCH 410/473] FIX No empty line inserted into accounting_bookkeeping --- htdocs/accountancy/bookkeeping/card.php | 4 +- .../accountancy/class/bookkeeping.class.php | 45 ++++++++++++------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index d43d35f84c7..0fd0b719cd7 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -431,12 +431,12 @@ if ($action == 'create') { // Account movement print '
'; print ''; - print ''; + print ''; print ''; // Date print ''; + } - $db->free($result); + $db->free($resql); + + $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); + $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + print '
'.$langs->trans("NumMvts").''.$object->piece_num.''.($mode == '_tmp' ? ''.$langs->trans("Draft").'' : $object->piece_num).'
'; - print ''; // Ref print '\n"; // Creation date @@ -405,7 +404,7 @@ if ($result) { print ""; print '"; print "\n"; From d21f5eca830a341bb780a39c96f5390421ab0f2d Mon Sep 17 00:00:00 2001 From: amarchal Date: Mon, 9 May 2022 20:13:06 +0200 Subject: [PATCH 415/473] add hidden option SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN --- htdocs/fourn/class/fournisseur.commande.class.php | 7 ++++++- htdocs/fourn/commande/dispatch.php | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 128c2ab3356..1d26fb5cfab 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2084,7 +2084,12 @@ class CommandeFournisseur extends CommonOrder // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on) $mouv->origin = &$this; $mouv->setOrigin($this->element, $this->id); - $result = $mouv->reception($user, $product, $entrepot, $qty, $price, $comment, $eatby, $sellby, $batch); + // Method change if qty < 0 + if (!empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN) && $qty < 0) { + $result = $mouv->livraison($user, $product, $entrepot, $qty*(-1), $price, $comment, $now, $eatby, $sellby, $batch); + } else { + $result = $mouv->reception($user, $product, $entrepot, $qty, $price, $comment, $eatby, $sellby, $batch); + } if ($result < 0) { $this->error = $mouv->error; $this->errors = $mouv->errors; diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 166da07ab03..362741e1641 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -802,7 +802,7 @@ if ($id > 0 || !empty($ref)) { $nbfreeproduct++; } else { $remaintodispatch = price2num($objp->qty - ((float) $products_dispatched[$objp->rowid]), 5); // Calculation of dispatched - if ($remaintodispatch < 0) { + if ($remaintodispatch < 0 && empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN)) { $remaintodispatch = 0; } From ef184567248af5dbeea8cbd63be5cd2d965ad756 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 21:56:21 +0200 Subject: [PATCH 416/473] Fix regression in dol_eval --- htdocs/core/lib/functions.lib.php | 8 ++-- test/phpunit/SecurityTest.php | 62 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 22ff541f7d5..43a549655b9 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8200,7 +8200,7 @@ function verifCond($strToEvaluate) * @param string $s String to evaluate * @param int $returnvalue 0=No return (used to execute eval($a=something)). 1=Value of eval is returned (used to eval($something)). * @param int $hideerrors 1=Hide errors - * @param string $onlysimplestring 0=Accept all chars, 1=Accept only simple string with char 'a-z0-9\s$_->&|=';, 2=Accept also '!?():"\';,/' + * @param string $onlysimplestring 0=Accept all chars, 1=Accept only simple string with char 'a-z0-9\s^$_+-.*\/>&|=!?():"\',/';, 2=Accept also ';[]' * @return mixed Nothing or return result of eval */ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1') @@ -8218,7 +8218,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' // Test dangerous char (used for RCE), we allow only PHP variable testing. if ($onlysimplestring == '1') { //print preg_quote('$_->&|', '/'); - if (preg_match('/[^a-z0-9\s'.preg_quote('$_+-*/>&|=!?():"', '/').']/i', $s)) { + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*/>&|=!?():"\',/', '/').']/i', $s)) { if ($returnvalue) { return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; } else { @@ -8228,7 +8228,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' } } elseif ($onlysimplestring == '2') { //print preg_quote('$_->&|', '/'); - if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-*/>&|=!?():"\';,/', '/').']/i', $s)) { + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*/>&|=!?():"\',/;[]', '/').']/i', $s)) { if ($returnvalue) { return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; } else { @@ -8245,7 +8245,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' return ''; } } - if (strpos($s, '.') !== false) { + if (preg_match('/[^0-9]+\.[^0-9]+/', $s)) { // We refuse . if not between 2 numbers if ($returnvalue) { return 'Bad string syntax to evaluate (dot char is forbidden): '.$s; } else { diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index fe5cbd01462..b33ec06504a 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -584,34 +584,6 @@ class SecurityTest extends PHPUnit\Framework\TestCase return $result; } - /** - * testCheckLoginPassEntity - * - * @return void - */ - public function testCheckLoginPassEntity() - { - $login=checkLoginPassEntity('loginbidon', 'passwordbidon', 1, array('dolibarr')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, ''); - - $login=checkLoginPassEntity('admin', 'passwordbidon', 1, array('dolibarr')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, ''); - - $login=checkLoginPassEntity('admin', 'admin', 1, array('dolibarr')); // Should works because admin/admin exists - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, 'admin', 'The test to check if pass of user "admin" is "admin" has failed'); - - $login=checkLoginPassEntity('admin', 'admin', 1, array('http','dolibarr')); // Should work because of second authentication method - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, 'admin'); - - $login=checkLoginPassEntity('admin', 'admin', 1, array('forceuser')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, ''); // Expected '' because should failed because login 'auto' does not exists - } - /** * testEncodeDecode * @@ -919,6 +891,11 @@ class SecurityTest extends PHPUnit\Framework\TestCase print "result = ".$result."\n"; $this->assertContains('Bad string syntax to evaluate', $result); + $result=dol_eval("90402.38+267678+0", 1, 1, 1); + print "result = ".$result."\n"; + $this->assertEquals('358080.38', $result); + + global $leftmenu; $leftmenu = 'admintools'; $result=dol_eval('$conf->currency && preg_match(\'/^(admintools|all)/\',$leftmenu)', 1, 0, '2'); @@ -936,4 +913,33 @@ class SecurityTest extends PHPUnit\Framework\TestCase print "result = ".$result."\n"; $this->assertContains('Bad string syntax to evaluate', $result); } + + + /** + * testCheckLoginPassEntity + * + * @return void + */ + public function testCheckLoginPassEntity() + { + $login=checkLoginPassEntity('loginbidon', 'passwordbidon', 1, array('dolibarr')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, ''); + + $login=checkLoginPassEntity('admin', 'passwordbidon', 1, array('dolibarr')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, ''); + + $login=checkLoginPassEntity('admin', 'admin', 1, array('dolibarr')); // Should works because admin/admin exists + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, 'admin', 'The test to check if pass of user "admin" is "admin" has failed'); + + $login=checkLoginPassEntity('admin', 'admin', 1, array('http','dolibarr')); // Should work because of second authentication method + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, 'admin'); + + $login=checkLoginPassEntity('admin', 'admin', 1, array('forceuser')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, ''); // Expected '' because should failed because login 'auto' does not exists + } } From 80ed7af114a92258a7d42ceea428de88e106c4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alo=C3=AFs=20Micard?= Date: Tue, 10 May 2022 10:18:53 +0200 Subject: [PATCH 417/473] formConfirm: pass action even when not confirming --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 2817a8222d1..46beb66f7d4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4382,7 +4382,7 @@ class Form $dialogconfirm .= '-'.$button; } $pageyes = $page.(preg_match('/\?/', $page) ? '&' : '?').'action='.$action.'&confirm=yes'; - $pageno = ($useajax == 2 ? $page.(preg_match('/\?/', $page) ? '&' : '?').'confirm=no' : ''); + $pageno = ($useajax == 2 ? $page.(preg_match('/\?/', $page) ? '&' : '?').'action='.$action.'&confirm=no' : ''); // Add input fields into list of fields to read during submit (inputok and inputko) if (is_array($formquestion)) { From 2e6f4862f9bf42d279bbbfa8f0c14ee31dc8c7ce Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 10:57:51 +0200 Subject: [PATCH 418/473] Fix creation of thirdparty when module supplier not enabled NEw can use the clicktoclipboard feature when clicking on value --- htdocs/core/js/lib_foot.js.php | 2 +- htdocs/societe/card.php | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index 997132ca132..9167e08e599 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -230,7 +230,7 @@ print ' } ); - jQuery(\'.clipboardCPButton, .clipboardCPValueToPrint\').click(function() { + jQuery(\'.clipboardCPValue, .clipboardCPButton, .clipboardCPValueToPrint\').click(function() { /* console.log(this.parentNode); */ console.log("We click on a clipboardCPButton or clipboardCPValueToPrint class and we want to copy content of clipboardCPValue class"); diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 7d28edb1dc9..a620bd02d39 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -84,6 +84,7 @@ $error = 0; $errors = array(); $action = (GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'); $cancel = GETPOST('cancel', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $socid = GETPOST('socid', 'int') ?GETPOST('socid', 'int') : GETPOST('id', 'int'); @@ -135,16 +136,6 @@ $upload_dir = $conf->societe->multidir_output[isset($object->entity) ? $object-> // Security check $result = restrictedArea($user, 'societe', $socid, '&societe', '', 'fk_soc', 'rowid', 0); -/* -if ($object->id > 0) { - if ($object->client == 0 && $object->fournisseur > 0) { - if (!empty($user->rights->fournisseur->lire)) { - accessforbidden(); - } - } -} -*/ - /* @@ -413,11 +404,11 @@ if (empty($reshook)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdPartyName")), null, 'errors'); $error++; } - if (GETPOST('client') < 0) { + if (GETPOST('client', 'int') && GETPOST('client', 'int') < 0) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProspectCustomer")), null, 'errors'); $error++; } - if (GETPOST('fournisseur') < 0) { + if (GETPOSTISSET('fournisseur') && GETPOST('fournisseur', 'int') < 0) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Supplier")), null, 'errors'); $error++; } From 7c0c56bf7b1e3690fb06ec8341597a2e3b902457 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 11:07:29 +0200 Subject: [PATCH 419/473] css --- htdocs/theme/eldy/global.inc.php | 3 +++ htdocs/theme/md/style.css.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index ecb98d59734..55b716b0e0c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -4720,6 +4720,9 @@ div.titre { padding-bottom: 5px; font-weight: 400; } +div.titre.small { + font-size: 1em; +} div.fiche > table.table-fiche-title:first-of-type div { color: var(--colortexttitlenotab); font-size: 1.1em; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 60d7bae21cd..4532fa1d226 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4591,6 +4591,9 @@ div.titre { text-transform: uppercase; /* text-shadow: 1px 1px 2px #FFFFFF; */ } +div.titre.small { + font-size: 1em; +} div.titre { color: var(--colortexttitlenotab); } From fc718e68ee47aa19a39ac1342b63bb1c83c5b3fc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 11:38:56 +0200 Subject: [PATCH 420/473] css --- htdocs/comm/propal/list.php | 13 ++++- htdocs/compta/bank/various_payment/list.php | 48 +++++++++++++------ htdocs/compta/facture/list.php | 19 ++++++-- htdocs/compta/sociales/list.php | 27 +++++++++-- htdocs/compta/tva/list.php | 36 ++++++++++---- htdocs/contact/consumption.php | 2 +- htdocs/contact/list.php | 24 +++++++--- .../modulebuilder/template/myobject_list.php | 2 +- htdocs/societe/list.php | 6 +-- 9 files changed, 133 insertions(+), 44 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index eb5b310edd1..c989cd34d39 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -2133,7 +2133,7 @@ if ($resql) { $totalarray['nbfield']++; } - print "\n"; + print ''."\n"; $i++; } @@ -2141,6 +2141,17 @@ if ($resql) { // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + // If no record found + if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; + } + $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); diff --git a/htdocs/compta/bank/various_payment/list.php b/htdocs/compta/bank/various_payment/list.php index bbec4f23fc6..92d38d95274 100644 --- a/htdocs/compta/bank/various_payment/list.php +++ b/htdocs/compta/bank/various_payment/list.php @@ -40,7 +40,6 @@ $socid = GETPOST("socid", "int"); if ($user->socid) { $socid = $user->socid; } -$result = restrictedArea($user, 'banque', '', '', ''); $optioncss = GETPOST('optioncss', 'alpha'); @@ -173,6 +172,11 @@ $arrayfields = array( $arrayfields = dol_sort_array($arrayfields, 'position'); +$object = new PaymentVarious($db); + +$result = restrictedArea($user, 'banque', '', '', ''); + + /* * Actions */ @@ -271,19 +275,19 @@ if ($search_all) { $sql .= $db->order($sortfield, $sortorder); $totalnboflines = 0; -$result = $db->query($sql); -if ($result) { - $totalnboflines = $db->num_rows($result); +$resql = $db->query($sql); +if ($resql) { + $totalnboflines = $db->num_rows($resql); } $sql .= $db->plimit($limit + 1, $offset); -$result = $db->query($sql); -if ($result) { - $num = $db->num_rows($result); +$resql = $db->query($sql); +if ($resql) { + $num = $db->num_rows($resql); // Direct jump if only one record found if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); $id = $obj->rowid; header("Location: ".DOL_URL_ROOT.'/compta/bank/various_payment/card.php?id='.$id); exit; @@ -541,7 +545,7 @@ if ($result) { $totalarray = array(); while ($i < min($num, $limit)) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); $variousstatic->id = $obj->rowid; $variousstatic->ref = $obj->rowid; @@ -704,7 +708,7 @@ if ($result) { $totalarray['nbfield']++; } - print ""; + print ''."\n"; $i++; } @@ -712,11 +716,27 @@ if ($result) { // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; - print "
'; + print ''; if ($action != 'editdate') { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 507292d777a..3ed498bcc78 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1851,27 +1851,42 @@ class BookKeeping extends CommonObject if ($next_piecenum < 0) { $error++; } - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)'; - $sql .= ' SELECT doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'"; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + + // Delete if there is an empty line + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0"; $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = 'Error '.$this->db->lasterror(); dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); } - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + if (!$error) { + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)'; + $sql .= ' SELECT doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'"; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } + } + + if (!$error) { + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } } elseif ($direction == 1) { $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); From b3bfe22f58abfe6216da53ba748da067eb6e7fe4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 16:45:57 +0200 Subject: [PATCH 411/473] FIX Error management --- .../accountancy/class/bookkeeping.class.php | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 3ed498bcc78..94c0b717aef 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1852,13 +1852,15 @@ class BookKeeping extends CommonObject $error++; } - // Delete if there is an empty line - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0"; - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + if (!$error) { + // Delete if there is an empty line + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0"; + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } if (!$error) { @@ -1889,34 +1891,42 @@ class BookKeeping extends CommonObject } } } elseif ($direction == 1) { - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + if (!$error) { + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)'; - $sql .= ' SELECT doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num'; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + if (!$error) { + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)'; + $sql .= ' SELECT doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num'; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + if (!$error) { + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } } if (!$error) { From 0cac14c82fafb90f3b27f2803c09c9bfbc8e479d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 16:51:31 +0200 Subject: [PATCH 412/473] Fix trans --- .../accountancy/class/bookkeeping.class.php | 49 ++++++++++++------- htdocs/langs/en_US/accountancy.lang | 2 +- htdocs/langs/fr_FR/accountancy.lang | 2 +- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 21b723b003b..ad2720f4675 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1843,8 +1843,8 @@ class BookKeeping extends CommonObject /** * Transform transaction * - * @param number $direction If 0 tmp => real, if 1 real => tmp - * @param string $piece_num Piece num + * @param number $direction If 0: tmp => real, if 1: real => tmp + * @param string $piece_num Piece num = Transaction ref * @return int int <0 if KO, >0 if OK */ public function transformTransaction($direction = 0, $piece_num = '') @@ -1862,27 +1862,42 @@ class BookKeeping extends CommonObject if ($next_piecenum < 0) { $error++; } - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)'; - $sql .= ' SELECT doc_date, doc_type,'; - $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; - $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; - $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'"; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + + // Delete if there is an empty line + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0"; $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = 'Error '.$this->db->lasterror(); dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); } - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + if (!$error) { + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)'; + $sql .= ' SELECT doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'"; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } + } + + if (!$error) { + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + } } } elseif ($direction == 1) { $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity); diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 8283da55f41..eddc43c9f38 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -289,7 +289,7 @@ ValidateHistory=Bind Automatically AutomaticBindingDone=Automatic bindings done (%s) - Automatic binding not possible for some record (%s) ErrorAccountancyCodeIsAlreadyUse=Error, you cannot delete this accounting account because it is used -MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s | Credit = %s +MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s & Credit = %s Balancing=Balancing FicheVentilation=Binding card GeneralLedgerIsWritten=Transactions are written in the Ledger diff --git a/htdocs/langs/fr_FR/accountancy.lang b/htdocs/langs/fr_FR/accountancy.lang index fa9e2203eea..4c3ee5f939f 100644 --- a/htdocs/langs/fr_FR/accountancy.lang +++ b/htdocs/langs/fr_FR/accountancy.lang @@ -289,7 +289,7 @@ ValidateHistory=Lier automatiquement AutomaticBindingDone=Liaisons automatiques effectuées (%s) - Liaison automatique impossible pour certains enregistrements (%s) ErrorAccountancyCodeIsAlreadyUse=Erreur, vous ne pouvez pas détruire de compte comptable car il est utilisé -MvtNotCorrectlyBalanced=Mouvement non équilibré. Débit = %s| Crédit = %s +MvtNotCorrectlyBalanced=Mouvement non équilibré. Débit = %s & Crédit = %s Balancing=Équilibrage FicheVentilation=Fiche lien GeneralLedgerIsWritten=Les transactions sont enregistrées dans le grand livre From 32a1c201546925ba55c1014eb43df4f00ba21642 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 17:33:45 +0200 Subject: [PATCH 413/473] Fix phpcs --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index c803c83e97a..28c3c975a51 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4030,7 +4030,7 @@ class Form * > 0 : force deposit percentage (for example, from company object) * @return string */ - public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $deposit_percent = -1) + public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1) { global $langs, $user, $conf; From d0c95d87afe960e3074d611aa39d2f68433351b1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 9 May 2022 18:46:23 +0200 Subject: [PATCH 414/473] Debug v16 --- htdocs/admin/ticket.php | 176 +++++++----------- .../boxes/box_graph_nb_ticket_last_x_days.php | 27 ++- .../core/boxes/box_graph_nb_tickets_type.php | 4 +- .../boxes/box_graph_ticket_by_severity.php | 10 +- .../core/boxes/box_last_modified_ticket.php | 6 +- htdocs/core/boxes/box_last_ticket.php | 20 +- htdocs/core/class/html.formcategory.class.php | 5 +- htdocs/core/modules/modTicket.class.php | 4 +- htdocs/ticket/index.php | 39 ++-- 9 files changed, 129 insertions(+), 162 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index f257b040636..f902c3fb39b 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -99,6 +99,50 @@ if ($action == 'updateMask') { // par appel methode canBeActivated dolibarr_set_const($db, "TICKET_ADDON", $value, 'chaine', 0, '', $conf->entity); +} elseif ($action == 'setvarworkflow') { + $param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_limit_view = GETPOST('TICKET_LIMIT_VIEW_ASSIGNED_ONLY', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_LIMIT_VIEW_ASSIGNED_ONLY', $param_limit_view, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + if (GETPOSTISSET('product_category_id')) { + $param_ticket_product_category = GETPOST('product_category_id', 'int'); + $res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + } + + $param_delay_first_response = GETPOST('delay_first_response', 'int'); + $res = dolibarr_set_const($db, 'TICKET_DELAY_BEFORE_FIRST_RESPONSE', $param_delay_first_response, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_delay_between_responses = GETPOST('delay_between_responses', 'int'); + $res = dolibarr_set_const($db, 'TICKET_DELAY_SINCE_LAST_RESPONSE', $param_delay_between_responses, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_auto_notify_close = GETPOST('TICKET_NOTIFY_AT_CLOSING', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_NOTIFY_AT_CLOSING', $param_auto_notify_close, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } } elseif ($action == 'setvar') { include_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php"; @@ -146,50 +190,6 @@ if ($action == 'updateMask') { if (!($res > 0)) { $error++; } -} - -if ($action == 'setvarworkflow') { - $param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } -} - -if ($action == 'setvarworkflowother' || $action == 'setvarworkflow') { - $param_ticket_product_category = GETPOST('product_category_id', 'int'); - $res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } -} - -if ($action == 'setvarother') { - $param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - $param_disable_email = GETPOST('TICKET_DISABLE_NOTIFICATION_MAILS', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_DISABLE_NOTIFICATION_MAILS', $param_disable_email, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - $param_show_module_logo = GETPOST('TICKET_SHOW_MODULE_LOGO', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_SHOW_MODULE_LOGO', $param_show_module_logo, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - } if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { $param_notification_also_main_addressemail = GETPOST('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS', 'alpha'); @@ -198,34 +198,9 @@ if ($action == 'setvarother') { $error++; } } - - $param_limit_view = GETPOST('TICKET_LIMIT_VIEW_ASSIGNED_ONLY', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_LIMIT_VIEW_ASSIGNED_ONLY', $param_limit_view, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - $param_delay_first_response = GETPOST('delay_first_response', 'int'); - $res = dolibarr_set_const($db, 'TICKET_DELAY_BEFORE_FIRST_RESPONSE', $param_delay_first_response, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - $param_delay_between_responses = GETPOST('delay_between_responses', 'int'); - $res = dolibarr_set_const($db, 'TICKET_DELAY_SINCE_LAST_RESPONSE', $param_delay_between_responses, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - $param_auto_notify_close = GETPOST('TICKET_NOTIFY_AT_CLOSING', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_NOTIFY_AT_CLOSING', $param_auto_notify_close, 'chaine', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } } - /* * View */ @@ -384,8 +359,8 @@ if ($resql) { print '
'; -print "
'; print $langs->trans('Docdate'); print '
\n"; -print "\n"; +print '
'."\n"; +print ''."\n"; print ''; print ''; print '\n"; @@ -502,13 +477,14 @@ foreach ($dirmodels as $reldir) { print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."
'; print '
'; -if (empty($conf->use_javascript_ajax)) { - print '
'; - print ''; - print ''; -} + +print ''; +print ''; +print ''; +print ''; print load_fiche_titre($langs->trans("Other"), '', ''); +print '
'; print ''; print ''; @@ -563,34 +539,24 @@ print $formcategory->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp print ''; print ''; -// Choose which product category is used for tickets -if ($conf->use_javascript_ajax) { - print ''; - print ''; - print ''; +if (! empty($conf->product->enabled)) { + print ''; + print ''; + print ''; + print ''; } -print ''; -print ''; -print ''; -print ''; - -// Define wanted maximum time elapsed before answers to tickets -print ''; -print ''; - print ''; print '"; print ''; print ''; print ''; print '"; print ''; print ''; print '
'.$langs->trans("TicketChooseProductCategory").''; + $formcategory->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); + if ($conf->use_javascript_ajax) { + print ajax_combobox('select_'.$htmlname); + } + print ''; + print $formcategory->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); + print '
'.$langs->trans("TicketChooseProductCategory").''; -$formcategory->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); -if ($conf->use_javascript_ajax) { - print ajax_combobox('select_'.$htmlname); -} -print ''; -print $formcategory->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); -print '
'.$langs->trans("TicketsDelayBeforeFirstAnswer")." - - + '; print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBeforeFirstAnswerHelp"), 1, 'help'); @@ -600,8 +566,7 @@ print '
'.$langs->trans("TicketsDelayBetweenAnswers")." - - + '; print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), 1, 'help'); @@ -610,9 +575,7 @@ print '

'; -print '
'; -print ''; -print '
'; +print $formcategory->buttonsSaveCancel("Save", '', array(), 0, 'reposition'); print ''; @@ -622,9 +585,10 @@ print load_fiche_titre($langs->trans("Notification"), '', ''); print ''; -print ''; +print ''; print ''; print ''; +print ''; print ''; print ''; @@ -699,7 +663,7 @@ print ''; print '
'.$langs->trans("Email").'
'; -print $formcategory->buttonsSaveCancel("Save", ''); +print $formcategory->buttonsSaveCancel("Save", '', array(), 0, 'reposition'); print ''; diff --git a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php index 5c8bd2c8555..b75d0752334 100644 --- a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php +++ b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php"; class box_graph_nb_ticket_last_x_days extends ModeleBoxes { - public $boxcode = "box_nb_ticket_last_x_days"; + public $boxcode = "box_graph_nb_ticket_last_x_days"; public $boximg = "ticket"; public $boxlabel; public $depends = array("ticket"); @@ -102,18 +102,17 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes 'text' => $text, 'limit' => dol_strlen($text) ); - $today = date_time_set(date_create(), 0, 0); - $todayformat = date('Y-m-d', date_timestamp_get($today)); - $intervaltosub = new DateInterval('P'.dol_escape_htmltag($days - 1).'D'); - $intervaltoadd = new DateInterval('P1D'); - $minimumdatec = date_sub($today, $intervaltosub); - $minimumdatecformated = date('Y-m-d', date_timestamp_get($minimumdatec)); + $today = dol_now(); + $intervaltoadd = 1; + $minimumdatec = dol_time_plus_duree($today, -1 * ($days - 1), 'd'); + $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); if ($user->rights->ticket->read) { $sql = "SELECT CAST(t.datec AS DATE) as datec, COUNT(t.datec) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t"; - $sql .= " WHERE CAST(t.datec AS DATE) > DATE_SUB(CURRENT_DATE, INTERVAL ".$days." DAY)"; + $sql .= " WHERE CAST(t.datec AS DATE) > '".$this->db->idate($minimumdatec)."'"; $sql .= " GROUP BY CAST(t.datec AS DATE)"; + $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -122,18 +121,18 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes $objp = $this->db->fetch_object($resql); while ($minimumdatecformated < $objp->datec) { $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); - $minimumdatec = date_add($minimumdatec, $intervaltoadd); - $minimumdatecformated = date('Y-m-d', date_timestamp_get($minimumdatec)); + $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); + $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); } $dataseries[] = array('label' => dol_print_date($objp->datec, 'day'), 'data' => $objp->nb); - $minimumdatec = date_add($minimumdatec, $intervaltoadd); - $minimumdatecformated = date('Y-m-d', date_timestamp_get($minimumdatec)); + $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); + $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); $i++; } while (count($dataseries) < $days) { $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); - $minimumdatec = date_add($minimumdatec, $intervaltoadd); - $minimumdatecformated = date('Y-m-d', date_timestamp_get($minimumdatec)); + $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); + $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); $i++; } } else { diff --git a/htdocs/core/boxes/box_graph_nb_tickets_type.php b/htdocs/core/boxes/box_graph_nb_tickets_type.php index 2da54d84e7a..88d930e9e27 100644 --- a/htdocs/core/boxes/box_graph_nb_tickets_type.php +++ b/htdocs/core/boxes/box_graph_nb_tickets_type.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php"; class box_graph_nb_tickets_type extends ModeleBoxes { - public $boxcode = "box_nb_tickets_type"; + public $boxcode = "box_graph_nb_tickets_type"; public $boximg = "ticket"; public $boxlabel; public $depends = array("ticket"); @@ -171,7 +171,7 @@ class box_graph_nb_tickets_type extends ModeleBoxes } $stringtoprint .= '
'; $this->info_box_contents[][]=array( - 'td' => 'center', + 'td' => 'class="center"', 'text' => $stringtoprint ); } else { diff --git a/htdocs/core/boxes/box_graph_ticket_by_severity.php b/htdocs/core/boxes/box_graph_ticket_by_severity.php index 5e69a49e88e..3c8756cf544 100644 --- a/htdocs/core/boxes/box_graph_ticket_by_severity.php +++ b/htdocs/core/boxes/box_graph_ticket_by_severity.php @@ -191,19 +191,19 @@ class box_graph_ticket_by_severity extends ModeleBoxes } $stringtoprint .= ''; $this->info_box_contents[][]=array( - 'td' => 'center', + 'td' => 'class="center"', 'text' => $stringtoprint ); } else { $this->info_box_contents[0][0] = array( - 'td' => 'class="center opacitymedium"', - 'text' => $langs->trans("BoxNoTicketSeverity") + 'td' => '', + 'text' => ''.$langs->trans("BoxNoTicketSeverity").'' ); } } else { $this->info_box_contents[0][0] = array( - 'td' => 'class="left"', - 'text' => $langs->trans("ReadPermissionNotAllowed"), + 'td' => '', + 'text' => ''.$langs->trans("ReadPermissionNotAllowed").'', ); } } diff --git a/htdocs/core/boxes/box_last_modified_ticket.php b/htdocs/core/boxes/box_last_modified_ticket.php index 300a13803c5..fd8ecd95eaf 100644 --- a/htdocs/core/boxes/box_last_modified_ticket.php +++ b/htdocs/core/boxes/box_last_modified_ticket.php @@ -177,15 +177,15 @@ class box_last_modified_ticket extends ModeleBoxes } if ($num == 0) { - $this->info_box_contents[$i][0] = array('td' => 'class="center"', 'text'=>$langs->trans("BoxLastModifiedTicketNoRecordedTickets")); + $this->info_box_contents[$i][0] = array('td' => '', 'text'=>''.$langs->trans("BoxLastModifiedTicketNoRecordedTickets").''); } } else { dol_print_error($this->db); } } else { $this->info_box_contents[0][0] = array( - 'td' => 'class="left"', - 'text' => $langs->trans("ReadPermissionNotAllowed"), + 'td' => '', + 'text' => ''.$langs->trans("ReadPermissionNotAllowed").'', ); } } diff --git a/htdocs/core/boxes/box_last_ticket.php b/htdocs/core/boxes/box_last_ticket.php index 25cb353b268..41ac39c1239 100644 --- a/htdocs/core/boxes/box_last_ticket.php +++ b/htdocs/core/boxes/box_last_ticket.php @@ -85,9 +85,9 @@ class box_last_ticket extends ModeleBoxes ); if ($user->rights->ticket->read) { - $sql = "SELECT t.rowid as id, t.ref, t.track_id, t.fk_soc, t.fk_user_create, t.fk_user_assign, t.subject, t.message, t.fk_statut, t.type_code, t.category_code, t.severity_code, t.datec, t.date_read, t.date_close, t.origin_email "; - $sql .= ", type.label as type_label, category.label as category_label, severity.label as severity_label"; - $sql .= ", s.nom as company_name, s.email as socemail, s.client, s.fournisseur"; + $sql = "SELECT t.rowid as id, t.ref, t.track_id, t.fk_soc, t.fk_user_create, t.fk_user_assign, t.subject, t.message, t.fk_statut as status, t.type_code, t.category_code, t.severity_code, t.datec, t.date_read, t.date_close, t.origin_email,"; + $sql .= " type.label as type_label, category.label as category_label, severity.label as severity_label,"; + $sql .= " s.nom as company_name, s.email as socemail, s.client, s.fournisseur"; $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code"; @@ -113,6 +113,7 @@ class box_last_ticket extends ModeleBoxes while ($i < $num) { $objp = $this->db->fetch_object($resql); + $datec = $this->db->jdate($objp->datec); //$dateterm = $this->db->jdate($objp->fin_validite); //$dateclose = $this->db->jdate($objp->date_close); @@ -122,7 +123,8 @@ class box_last_ticket extends ModeleBoxes $ticket->id = $objp->id; $ticket->track_id = $objp->track_id; $ticket->ref = $objp->ref; - $ticket->fk_statut = $objp->fk_statut; + $ticket->fk_statut = $objp->status; + $ticket->status = $objp->status; $ticket->subject = $objp->subject; if ($objp->fk_soc > 0) { $thirdparty = new Societe($this->db); @@ -149,8 +151,8 @@ class box_last_ticket extends ModeleBoxes // Subject $this->info_box_contents[$i][$r] = array( 'td' => 'class="tdoverflowmax200"', - 'text' => ''.$objp->subject.'', // Some event have no ref - 'url' => DOL_URL_ROOT."/ticket/card.php?track_id=".$objp->track_id, + 'text' => ''.dol_escape_htmltag($objp->subject).'', // Some event have no ref + 'url' => DOL_URL_ROOT."/ticket/card.php?track_id=".urlencode($objp->track_id), ); $r++; @@ -180,14 +182,14 @@ class box_last_ticket extends ModeleBoxes } if ($num == 0) { - $this->info_box_contents[$i][0] = array('td' => 'class="center"', 'text' => $langs->trans("BoxLastTicketNoRecordedTickets")); + $this->info_box_contents[$i][0] = array('td' => '', 'text' => ''.$langs->trans("BoxLastTicketNoRecordedTickets").''); } } else { dol_print_error($this->db); } } else { - $this->info_box_contents[0][0] = array('td' => 'class="left"', - 'text' => $langs->trans("ReadPermissionNotAllowed")); + $this->info_box_contents[0][0] = array('td' => '', + 'text' => ''.$langs->trans("ReadPermissionNotAllowed").''); } } diff --git a/htdocs/core/class/html.formcategory.class.php b/htdocs/core/class/html.formcategory.class.php index 707b5d5d0ac..c0e07b6bb7a 100644 --- a/htdocs/core/class/html.formcategory.class.php +++ b/htdocs/core/class/html.formcategory.class.php @@ -72,7 +72,10 @@ class FormCategory extends Form { global $conf; - $sql = "SELECT cp.fk_categorie as cat_index, cat.label FROM `llx_categorie_product` as cp INNER JOIN llx_categorie as cat ON cat.rowid = cp.fk_categorie GROUP BY cp.fk_categorie;"; + $sql = "SELECT cp.fk_categorie as cat_index, cat.label"; + $sql .= " FROM ".MAIN_DB_PREFIX."categorie_product as cp"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."categorie as cat ON cat.rowid = cp.fk_categorie"; + $sql .= " GROUP BY cp.fk_categorie, cat.label"; dol_syslog(get_class($this)."::selectProductCategory", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 688da3061d9..fc7e72388ea 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -171,8 +171,8 @@ class modTicket extends DolibarrModules 0=>array('file'=>'box_last_ticket.php', 'enabledbydefaulton'=>'Home'), 1=>array('file'=>'box_last_modified_ticket.php', 'enabledbydefaulton'=>'Home'), 2=>array('file'=>'box_ticket_by_severity.php', 'enabledbydefaulton'=>'ticketindex'), - 3=>array('file'=>'box_nb_ticket_last_x_days.php', 'enabledbydefaulton'=>'ticketindex'), - 4=>array('file'=>'box_nb_tickets_type.php', 'enabledbydefaulton'=>'ticketindex'), + 3=>array('file'=>'box_graph_nb_ticket_last_x_days.php', 'enabledbydefaulton'=>'ticketindex'), + 4=>array('file'=>'box_graph_nb_tickets_type.php', 'enabledbydefaulton'=>'ticketindex'), 5=>array('file'=>'box_new_vs_close_ticket.php', 'enabledbydefaulton'=>'ticketindex') ); // Boxes list diff --git a/htdocs/ticket/index.php b/htdocs/ticket/index.php index b55c81f72fa..8e6e09f3fcf 100644 --- a/htdocs/ticket/index.php +++ b/htdocs/ticket/index.php @@ -55,8 +55,9 @@ $userid = $user->id; // Security check $result = restrictedArea($user, 'ticket', 0, '', '', '', ''); -$nowyear = strftime("%Y", dol_now()); -$year = GETPOST('year') > 0 ? GETPOST('year') : $nowyear; +$nowarray = dol_getdate(dol_now(), true); +$nowyear = $nowarray['year']; +$year = GETPOST('year', 'int') > 0 ? GETPOST('year', 'int') : $nowyear; $startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS))); $endyear = $year; @@ -76,7 +77,6 @@ $object = new Ticket($db); $resultboxes = FormOther::getBoxesArea($user, "11"); // Load $resultboxes (selectboxlist + boxactivated + boxlista + boxlistb) $form = new Form($db); -$tickesupstatic = new Ticket($db); llxHeader('', $langs->trans('TicketsIndex'), ''); @@ -108,7 +108,6 @@ if (empty($shownb) && empty($showtot)) { $shownb = 0; } -$nowarray = dol_getdate(dol_now(), true); if (empty($endyear)) { $endyear = $nowarray['year']; } @@ -204,21 +203,21 @@ if ($result) { $dataseries = array(); $colorseries = array(); - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_NOT_READ]), 'data' => round($tick['unread'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_NOT_READ]), 'data' => round($tick['unread'])); $colorseries[Ticket::STATUS_NOT_READ] = '-'.$badgeStatus0; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_READ]), 'data' => round($tick['read'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_READ]), 'data' => round($tick['read'])); $colorseries[Ticket::STATUS_READ] = $badgeStatus1; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_ASSIGNED]), 'data' => round($tick['assigned'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_ASSIGNED]), 'data' => round($tick['assigned'])); $colorseries[Ticket::STATUS_ASSIGNED] = $badgeStatus3; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_IN_PROGRESS]), 'data' => round($tick['inprogress'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_IN_PROGRESS]), 'data' => round($tick['inprogress'])); $colorseries[Ticket::STATUS_IN_PROGRESS] = $badgeStatus4; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_WAITING]), 'data' => round($tick['waiting'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_WAITING]), 'data' => round($tick['waiting'])); $colorseries[Ticket::STATUS_WAITING] = '-'.$badgeStatus4; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_NEED_MORE_INFO]), 'data' => round($tick['needmoreinfo'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_NEED_MORE_INFO]), 'data' => round($tick['needmoreinfo'])); $colorseries[Ticket::STATUS_NEED_MORE_INFO] = '-'.$badgeStatus3; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_CANCELED]), 'data' => round($tick['canceled'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_CANCELED]), 'data' => round($tick['canceled'])); $colorseries[Ticket::STATUS_CANCELED] = $badgeStatus9; - $dataseries[] = array('label' => $langs->transnoentitiesnoconv($tickesupstatic->statuts_short[Ticket::STATUS_CLOSED]), 'data' => round($tick['closed'])); + $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_CLOSED]), 'data' => round($tick['closed'])); $colorseries[Ticket::STATUS_CLOSED] = $badgeStatus6; } else { dol_print_error($db); @@ -358,18 +357,18 @@ if ($result) { while ($i < $num) { $objp = $db->fetch_object($result); - $tickesupstatic->id = $objp->rowid; - $tickesupstatic->ref = $objp->ref; - $tickesupstatic->track_id = $objp->track_id; - $tickesupstatic->fk_statut = $objp->fk_statut; - $tickesupstatic->progress = $objp->progress; - $tickesupstatic->subject = $objp->subject; + $object->id = $objp->rowid; + $object->ref = $objp->ref; + $object->track_id = $objp->track_id; + $object->fk_statut = $objp->fk_statut; + $object->progress = $objp->progress; + $object->subject = $objp->subject; print '
'; - print $tickesupstatic->getNomUrl(1); + print $object->getNomUrl(1); print "'; - print $tickesupstatic->getLibStatut(5); + print $object->getLibStatut(5); print "
'.$langs->trans("NoRecordFound").'
"; - print ''; - print ''; + // If no record found + if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print '
'.$langs->trans("NoRecordFound").'
'."\n"; + print '
'."\n"; + + print ''."\n"; } else { dol_print_error($db); } diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 2ef50801717..5937eda916c 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2415,16 +2415,27 @@ if ($resql) { include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; } + // If no record found + if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''.$langs->trans("NoRecordFound").''; + } + $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); - $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - print "\n"; - print '
'; + print ''."\n"; + print ''."\n"; - print "\n"; + print ''."\n"; // Show the file area only when this page is not opend from the Extended POS if ($contextpage != 'poslist') { diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 8d63e52256e..082a485f817 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -713,16 +713,35 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } - print ''; + print ''."\n"; + $i++; } // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; -print ''; -print ''; -print ''; +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''.$langs->trans("NoRecordFound").''; +} + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print ''."\n"; +print ''."\n"; + +print ''."\n"; // End of page llxFooter(); diff --git a/htdocs/compta/tva/list.php b/htdocs/compta/tva/list.php index f1731420852..5f76b2e9190 100644 --- a/htdocs/compta/tva/list.php +++ b/htdocs/compta/tva/list.php @@ -190,8 +190,8 @@ $sql .= $db->order($sortfield, $sortorder); $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $result = $db->query($sql); - $nbtotalofrecords = $db->num_rows($result); + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); // if total resultset is smaller then paging size (filtering), goto and load page 0 if (($page * $limit) > $nbtotalofrecords) { @@ -202,15 +202,15 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { $sql .= $db->plimit($limit + 1, $offset); -$result = $db->query($sql); -if (!$result) { +$resql = $db->query($sql); +if (!$resql) { dol_print_error($db); llxFooter(); $db->close(); exit; } -$num = $db->num_rows($result); +$num = $db->num_rows($resql); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER['PHP_SELF']) { @@ -429,7 +429,7 @@ print ''; $i = 0; $totalarray = array(); while ($i < min($num, $limit)) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); $tva_static->id = $obj->rowid; $tva_static->ref = $obj->rowid; @@ -549,11 +549,27 @@ $totalarray['nbfield']++; // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; -print ''; -print ''; -print ''; +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''.$langs->trans("NoRecordFound").''; +} -$db->free($result); +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print ''."\n"; +print ''."\n"; + +print ''."\n"; // End of page llxFooter(); diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index 631bf932640..02813cee469 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -355,7 +355,7 @@ if (empty($elementTypeArray) && !$object->thirdparty->client && !$object->thirdp // Define type of elements $typeElementString = $form->selectarray("type_element", $elementTypeArray, GETPOST('type_element'), $showempty, 0, 0, '', 0, 0, $disabled, '', 'maxwidth150onsmartphone'); -$button = ''; +$button = ''; $param = ''; $param .= "&sref=".urlencode($sref); diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 31b2153c2c8..93d61f8a903 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -1309,19 +1309,31 @@ while ($i < min($num, $limit)) { $i++; } +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''.$langs->trans("NoRecordFound").''; +} + $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; -print ""; -print ""; - -//if ($num > $limit || $page) print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies.png', 0, '', '', $limit, 1); - -print ''; +print ''."\n"; +print ''."\n"; +print ''."\n"; +// End of page llxFooter(); $db->close(); diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 8771ad0f9b6..9638eb4ce7f 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -811,7 +811,7 @@ if ($num == 0) { $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); -$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; print ''."\n"; diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 746b4dc0db0..e7b9e5097ea 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -863,9 +863,6 @@ $arrayofmassactions = array( // 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), ); //if($user->rights->societe->creer) $arrayofmassactions['createbills']=$langs->trans("CreateInvoiceForThisCustomer"); -if ($user->rights->societe->supprimer) { - $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); -} if ($user->rights->societe->creer) { $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } @@ -881,6 +878,9 @@ if ($user->rights->societe->creer) { if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag', 'preenable', 'preclose'))) { $arrayofmassactions = array(); } +if ($user->rights->societe->supprimer) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} $massactionbutton = $form->selectMassAction('', $arrayofmassactions); $typefilter = ''; From e3ff7b43ab699f4d1a6dbe9a1b001d372a7b12d2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 11:39:55 +0200 Subject: [PATCH 421/473] Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop --- htdocs/accountancy/journal/sellsjournal.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index a4cda49af64..426bc6d7795 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -422,6 +422,9 @@ if ($action == 'writebookkeeping') { if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) { $bookkeeping->subledger_account = $tabcompany[$key]['code_compta']; $bookkeeping->subledger_label = $tabcompany[$key]['name']; + } else { + $bookkeeping->subledger_account = ''; + $bookkeeping->subledger_label = ''; } } else { $bookkeeping->subledger_account = ''; From 7e94d53882ee35c99bf42182846a0b45a6842505 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 11:51:39 +0200 Subject: [PATCH 422/473] Clean not used files --- build/makepack-dolibarr.pl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 906601d94d4..b648bd7aff7 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -582,9 +582,7 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/teclib*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/timesheet*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/webmail*`; - $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/oblyon*`; - $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/allscreen*`; - $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/theme/common/octicons/LICENSE`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/theme/common/fontawesome-5/svgs`; # Removed other test files $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/public/test`; From 218749ead4cdb8093a2b0487be0d4450d925682a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 11:52:22 +0200 Subject: [PATCH 423/473] Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop --- .../theme/common/weather/weather-clear-night.png | Bin 2276 -> 0 bytes htdocs/theme/common/weather/weather-clear.png | Bin 7439 -> 0 bytes .../common/weather/weather-clouds-night.png | Bin 4363 -> 0 bytes htdocs/theme/common/weather/weather-clouds.png | Bin 6267 -> 0 bytes .../common/weather/weather-few-clouds-night.png | Bin 2212 -> 0 bytes .../theme/common/weather/weather-few-clouds.png | Bin 5730 -> 0 bytes .../common/weather/weather-freezing-rain.png | Bin 5046 -> 0 bytes htdocs/theme/common/weather/weather-hail.png | Bin 5090 -> 0 bytes .../theme/common/weather/weather-many-clouds.png | Bin 4399 -> 0 bytes htdocs/theme/common/weather/weather-mist.png | Bin 1524 -> 0 bytes .../theme/common/weather/weather-showers-day.png | Bin 6954 -> 0 bytes .../common/weather/weather-showers-night.png | Bin 6123 -> 0 bytes .../weather/weather-showers-scattered-day.png | Bin 6317 -> 0 bytes .../weather/weather-showers-scattered-night.png | Bin 5171 -> 0 bytes .../common/weather/weather-showers-scattered.png | Bin 4937 -> 0 bytes htdocs/theme/common/weather/weather-showers.png | Bin 5138 -> 0 bytes .../theme/common/weather/weather-snow-rain.png | Bin 5406 -> 0 bytes .../weather/weather-snow-scattered-day.png | Bin 6823 -> 0 bytes .../weather/weather-snow-scattered-night.png | Bin 5583 -> 0 bytes .../common/weather/weather-snow-scattered.png | Bin 5038 -> 0 bytes htdocs/theme/common/weather/weather-snow.png | Bin 5332 -> 0 bytes .../theme/common/weather/weather-storm-day.png | Bin 7437 -> 0 bytes .../theme/common/weather/weather-storm-night.png | Bin 7471 -> 0 bytes htdocs/theme/common/weather/weather-storm.png | Bin 7261 -> 0 bytes 24 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 htdocs/theme/common/weather/weather-clear-night.png delete mode 100644 htdocs/theme/common/weather/weather-clear.png delete mode 100644 htdocs/theme/common/weather/weather-clouds-night.png delete mode 100644 htdocs/theme/common/weather/weather-clouds.png delete mode 100644 htdocs/theme/common/weather/weather-few-clouds-night.png delete mode 100644 htdocs/theme/common/weather/weather-few-clouds.png delete mode 100644 htdocs/theme/common/weather/weather-freezing-rain.png delete mode 100644 htdocs/theme/common/weather/weather-hail.png delete mode 100644 htdocs/theme/common/weather/weather-many-clouds.png delete mode 100644 htdocs/theme/common/weather/weather-mist.png delete mode 100644 htdocs/theme/common/weather/weather-showers-day.png delete mode 100644 htdocs/theme/common/weather/weather-showers-night.png delete mode 100644 htdocs/theme/common/weather/weather-showers-scattered-day.png delete mode 100644 htdocs/theme/common/weather/weather-showers-scattered-night.png delete mode 100644 htdocs/theme/common/weather/weather-showers-scattered.png delete mode 100644 htdocs/theme/common/weather/weather-showers.png delete mode 100644 htdocs/theme/common/weather/weather-snow-rain.png delete mode 100644 htdocs/theme/common/weather/weather-snow-scattered-day.png delete mode 100644 htdocs/theme/common/weather/weather-snow-scattered-night.png delete mode 100644 htdocs/theme/common/weather/weather-snow-scattered.png delete mode 100644 htdocs/theme/common/weather/weather-snow.png delete mode 100644 htdocs/theme/common/weather/weather-storm-day.png delete mode 100644 htdocs/theme/common/weather/weather-storm-night.png delete mode 100644 htdocs/theme/common/weather/weather-storm.png diff --git a/htdocs/theme/common/weather/weather-clear-night.png b/htdocs/theme/common/weather/weather-clear-night.png deleted file mode 100644 index f89b2ad8cada273150187dffce8aeae88aa91083..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2276 zcmVDgE0yw36#QR45dvp8emRp(IPtQNR*?KecbElxdV$G=m z&<5RKhOgXu@N(zBWb-_|)9kJ<(I#Wcv1$3U!S}!Wx$Y-!f7D4Ssmw_QQ1HV2Zu1rA z-F27KTxn<9#mB?PMOR8vQYwxl(+~gP2WeX*8Ond1krrtt53_Vw4E^=y_F4huNI3Y8!nT7X9zpNtHTLKp!x97?`AT)V@Q zKNuuJ*f;>%{r%6f=UwMHO{O4q8n}#zK?n{Zj?CC4Aj42$N%e|{! z{^oN2j`r@0cl_YhyHAtiQ7P>y%SfL$5sqF<^vaY8IRU3@nwLE6qWIQq z6hO}ZLHj*VY@RzHBLPYVtP@jG0wsn1GLRc0ERo=*j46pIsaRx3$GrI6J8kD3z_6ScOX!IHyDaOck`CWWtzVv6mr^FvlbU?Xm52?|Z_qg|iU=rT>+?c;Lij zRMI(+#S~WI^WS?u#KEQH2q^{23>nLYB}Vep*>R(XULN0W1OT&Md;i_StqBo14t>BO zCnZN1lw>T@W(k*=SmvyRl#p-;pMVOZJamkC=vo_RBLL2uw+FXaCBWqX70Z;Y$z*km z+#Zm#pEWXE3?)W>D5!)uV1kR~7&Qu9{{K7=zZ|}u6~K}Q@3~>vOUYI5KjW}mUSi3$ zFJC|F;qY^Y%+V$$qtL5U-6srLC1y=oaWJ=w8h^dyy}u^Fpiy3PiX(Lm1xIk0BcVY9 zkCK!cE-@2|qjt2+VHt76mG%**7RPBIYy*(IVQINWH?MYN{R~<)XsXaiJ8R%=5UanwW6eN1`^M0L4phjIO+l(xm;ZmNR|?4 zkTIZ1NrQPT2~9i|tHu8Q*m#tA)`7#l*#H>3MZ=QPW28{7oL>==Q86T?&jL96FcW}R1#y9;p`QrQu^&f|6M+PhWhW5d>|dJ9n1N>A{rZ>*mXeS;JT;^ap$5=-8WO;$EyeiilB+nV;efiKVIONWs53{0 zJ}&m>TcVi&43t;++_VUB@ilPvStX$W*)Ni}4ZeC}M=mh*@IV%AXm%cJOmo@ER$xQ~ zUzkg0lz{3=2ZL{=)M?SeW1>;Z(7`9BMGaR~&|()Iphl0Ow6?%lcFeFel|@(6QBs`w zBPKV@2(WEhf8R(=#G^rtruH@8qN|;>&DDU*k zr6;V)QZX5oLY#(q&Ok(s4lb66;`fIg7gtUxDFt8ztbIKtD$;m!nXDoG%D6Vp5fBMX7wWi5L*?JNLueBPuoopd6fYc)NQ~zkO6=_Ly}I z9t+ga01klmOGQp1%v^P1_2;q7&smLYcfZ0O3d05ggiu^#|J80Y*fSuYB;_c}twh1(G_mI_KOu_JPq0_M67Edt$rUq zW=ce&^t-sUG32Bq)Al`X^_F@>WlrP_Ngll6jGugtxy)`nEOYqusmq3y0>Mx_FDS8k z%?f3FVEesq@!@)WLT5-20^WD#pZTErUABikJQB5|CM{6vQ5F;&D^I|RZNC4k55Lk+ zgG}L1!dWtRf8(_mT7QUtnZBuE)M|H_#qB8jOIjWQRd~RgV$a9W7~(G_I|R@lsdR8^-t{Da~bc#-nqm7 z?=|L)hoP{ebi611arl+_k6r4Qt%zK~PtmzzgHyUmuu@xV4q892Pus=#qJs-hv)oO+ y%uyROr}}KU1u*Cjy`Vo7dc$jTZLZC=xqb};coKLhwc*160000 diff --git a/htdocs/theme/common/weather/weather-clear.png b/htdocs/theme/common/weather/weather-clear.png deleted file mode 100644 index ed1d48065f3fb3aee5b7d47cef6f0d869b6ccca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7439 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 l$L+Wsx8ru)j@xlN{y+LoGz5R`r|zkH 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 UJ;M`Knu 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 M07*qoM6N<$f^50evj6}9 diff --git a/htdocs/theme/common/weather/weather-hail.png b/htdocs/theme/common/weather/weather-hail.png deleted file mode 100644 index 9df0bdc24d720eefffadef0e5bd4727de341b2db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5090 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 diff --git a/htdocs/theme/common/weather/weather-mist.png b/htdocs/theme/common/weather/weather-mist.png deleted file mode 100644 index a2b57a5e408e01d4324463b276d147fa6f97cf13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1524 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 diff --git a/htdocs/theme/common/weather/weather-showers-night.png b/htdocs/theme/common/weather/weather-showers-night.png deleted file mode 100644 index 1fff3febf5c3132287309a8eede8dd0e70c122be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6123 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 diff --git a/htdocs/theme/common/weather/weather-showers-scattered-day.png b/htdocs/theme/common/weather/weather-showers-scattered-day.png deleted file mode 100644 index ae098117351df526fee6029e0a03bad1359ac36e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6317 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 diff --git a/htdocs/theme/common/weather/weather-showers-scattered-night.png b/htdocs/theme/common/weather/weather-showers-scattered-night.png deleted file mode 100644 index ad0283a08db6c9ea96cae7dc4e6705e128b0e9ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5171 zcmV-36wK?1P)s+qP{xS=;7C`m4M%vGvqdQ#1Fl|G)q4bFOT* z&9>P#+oo)mtVb3Kg^W*jZ*Q-wtE zp$(1z1H84h)pzNomsX~wrCp@Y5xKd!@jjnVJRXnmR*-y)%jJRy855WyQWBxo84MjsFA&{UyMo_OMkhji^33l}b|U#Eukj{v}b^UXKm3l=Q6sH&=J zZFqRNCn6$(ND6PFJ~A@mfCYG1SQtPhHZ~T}qyS{m&w8YZsCq~bdF{2=zR@*KSh;fL z`y%3pg!P61oYl%6cG_vD%_=J^TMb|wN7nK2@q%eyLxNzC0B}g)tzu! zQzu48N9C=z-fC4+4qdiv*@u6G1p7bCdC!FxUU-axSPm%K6fEsBI5;SJaZ=wcx#$iO*wDHzs(5S)z&e+JvNK_(PTZ%sX@WV^A)|{d1jc_{r=L8&a#1R$_ z?!No(($v%x@%7hVuU4RmNFNYJwgx<87&9qAI}$fChJd!VHk3dc^?`YknVCr+-?T%F zXmLGy$&w}aU3uk|cj!8#!oN$vIp>^XsneF%YgsWdiCzU7&!qf;7dzQt8{zZQ3NwCE`G1Jw)XhPAAg*v;UwUs zuC7k>$_rpq)yZG_h%^!wjLHrezz+-z@OJJ2^f4bo^fE*nkr#;8$P1?aov8iynKbyr z1hA=5WM^lm+$af7-Bc^xZMd_ z4{U(H`s%9yG#48jcaAb5$U8YX+1Z~y(g2yax3}|~xex?!qD^Wz^#C<+G2;IN1Vfmv zyZ0-vypp)rUVDwQ?5`3~Qc@yYZMBs{(VchRY3T*UPE1T>BbRQRq4)HIb-~I{KmGIz zRlv>~`K@#e$Bm2P%|%B=5h4>xSJIz;eS}+q? zzyaP=ddNd9w9`gi(EkO_tuZSri$2zY9N%rX-L{hwaObZPKpxxrMMw+t*ERxC=m1~*y6H0 zN{rthK(g{JX=V}TNRC8d$(d#sxuy$-nVFfHF3Wt}>(X^^yVt#6`+itvW@fBuX6|a2 zU0`S0+V_9)#W0WB`ebKG%7_;)KB{Ej``2fgo&maIt&0uIWfaDfl2=K><5=b1FNd_A53fB~U_ z?-F*%I)p-atc`N&jgU)GWe-_(BM{tB%nKl_ibeVD!4cO$aprke@J`dc0qK^si)^!U zmH4^<2&qPvITE}cH0W9&IG-s=u%~p8$kw-$O-BFNg0+LrgE~KbC8}7aDzHs!& z5xK|_+zI8OILtw5Mq&f80D1@AA`$oi3|V1^r%?7~exI7`bpa5oG1N!`M*JC5#f-F4 zk9v6;j)ticD*^5sz45yupnM^4i1ON8%GaTDs#U8o;?K2eVjj_(b$~!$*tUSe#tQvL z@2p}jm&*lWT;ie zpfNGS6A%^!2N)ytEgsbCwZNVZ6H{4(f|p%>d06@1|D@CeO8bqGAC_eK^TI#?@td_p zF&$tBzm>KDmihnYDDnE0pv0BG^dwkJmPhGCcgP^c8c`$GP6zfQcz}Kk$3Ij zVw6S;hH5QOTf-2E1^foUnykVY0Xv$?D9CSTMYWm<#CpJ*GqW>ceJ~K4hT5;n3|ZZR z^@SI;0>)wepg&OR+e>;>ZL!K)+#soT`7_wRE&%=h`dDS_mZ)3dfdw%v9%2o@F$SPq zEV2rI&wUf_lAv2%%A>e^$&|Mh!K`U)VIFgg<~)T7WQt@pJwRj?a|MmCgIV>O(fmpk zX}lM}i_%J8j3H3fF`+T6*=mO?uev&%r-RYAzWGfU!o2@H{q)m&RoI2sYuTqh^-)F5 z-ncv8y=JP@xdcJ{lx6~(P*?|CGHIZ)FpB=f2_6PLLwTFyWwg3wg9&Las=f;GrQ(SF z5zvJ6qpX%YP{@I0?U`MQ0w!!jX@W2D$WMjz2#574^}N5<^HTb2d-v`A^9w7xh8JCQ zL8*I!R|UaJja!BTJ9g~)O0&^ioSN!fujkb62ni#wh+bevRxGH(LC+OEjn<~nIB^ib zia_9kS-Kn#lew4)sK04`Y4O1>IXE+DG#8|sgtgV zDR^5Aso@E=yb78x|4)es z%0y%$^gvbDx;k`68=WDdtVR7qu%sJ%V(_xp&-O}frnol`rcQb94vH*qZh;$=BdD%) z-6Gf`mvym;cvP{yNY{;R3uoP1Z#LW9SH8jpC>%IB?cH}^qSjTr7vW2M+i0&%t0pW# zN?ny-L}&wf0uZ=`=XcVagvb%VEM9@;8Ps>>cm~~Hp|CgDgw*BX8<5aNoB9Uv9YwY@UW~i2Tc)PV4#Tk zrU{8fBa|ioqqHl6;7D18H3AGEP{b*$58p{+{I+$;3M6Rk!0;XSbIZdjtLm)Wb?_|% zSWHrkz{OO8m$(HdT8!iIlznTft7pDD+}b>>dx;br0NQuI`&}qGp6$-}MBihw-kgHs zs)AqC!WL%*X9M*%nhyI)O#hf$(RC$9PQn=|A%LK{r#$N3musq0Bb8N zE8*rFZy2p_jCLG8eDvG@{m*}X^umrEI~5FdQ#Es5CP%{eDN<;zyw?I|0TWWf`hQ>1 z$p)k?Q`QO^Y7FKloj8$Rb6x@qFseppXP3Ig4`ZS!k6XEgkp{Msa*JXN_+CO7^W@fY z-5JHIm6_?eQ!%Eo1K^GSU<^O`@ehhyZoYASe!jb^f@M`#U^l2zyf)L@J-1^;FO#9G zT}l|*G`{;>lpkphN|5%*9P~y*RF0O;Xabsjql1c->0Vx=oL7CkBAQ`6R`8vXw1>hl z$lZ?4UU|FKzC>^6NR`8#sm^in^!3|KH{FzUTU7kR1s4 zBUZ-eU2wOCQ=d^8#sVVNL|7A?*Lf+7)l*RxfTBL~U}s=!Yen|tM`89tLG~YyOFx7q z059}DfB{rH!IEhbE|r~g_BkJrOXX|*!IxurllF^W{35Qb>`=JRZ#n0j<%ek}6wSDD%3N5ZEs8>A`QjErlA54w(#?_iu_j2-q|tTcwh31OFaTnX zvA}5HfiQrevw<6|vDX@!#ClS5F;)R@0H}Pnz)5DKLXh0Wi4(`a#ELg<-}=_K;(-H) zYJ-i6pUPwSZX9Cx^Mfj z*y?*rfu*{g@*hnMbr6ww|m3l!nQ9;u$01 zHfLEJ3cO6zM6-URG**FvZ|c#81VzDyES8HIy{%$gFUrYOEt?z{<7%2S)Yyq?nzJ>Q zHkx1mMT|8)G=@$ba& z9@0Z9&rUw_}-Xq%H-2ipwy6R66MffxBH zU^F~G6H#PeBrFB>8YW1v04B!A(a_aJ8Ce#Sle1KAK|Z0>2=Ru()B~?M>oTfaE`9aR zhtJ(&RqywXkT($o187=NADgN^EZ`0njTL;b10h7Y=ISeXe?({6 z@1R|5W+9S@{dQMZ zyXB)b1p^COVN{7xR5~11Pd?=o6-$gkeAK>od~6%o@y5#$Ma62TZE?xxK6POCTOt6o zh(cemHNWRwA5E@)_ycqCo=ssfq#Q-?R}%hAzbA!%@#T9TIp2Bu$(s-bVT`>xioj*J zI{_$&LLsT$b){KZ;b2e!K(N$U>keDQ3Ut=G(>C~b9AXgCI?F324!T$;wy%X)w7rJ5 zEzdqBt6}R6vDET<4m7rHb^XWDQdj*3=k_*je8s(3At)@c+R=dn>$}TJ0r2=I(!OTz zNx9`#F=+#Ulhv`A&%SsMKm>nh+^keI8M>#w_+|>piV(^Gz!2?ldina@rmWT!EF{ey z9FmfGr&7d`+Hi8Qx%R{Z7B~wmKXdgl1^UeVdjQagp>zGteS24}?@zh_Xj!fOjE;%c zN*E?`5Q8O+v4&g@FII$<-M3$ehDS!rF~tWxIjQV%$=fQ7Yjnm8fShKFHm%mY@F~D@ z1P$GGsYp=8>K8WGj}Kl1-G~+c5l8IAZJUd{^!Q63!t=zth++QwH|G70_ncU0)$3lr zW!~Urha*92pZU`Lhurp=3iGCYh{v>L9^x=$)KxH=EOFV|0eu^{ZPVJB-HQa#@aaB$ z^}Q(s-~AAAXidVQ0Q88#GyCqxQeeu4<+9q5H*H-qaPV445GxqWtdJ@qj@-7rjXgWv z=FsPC(1-t{!ToMNcHjHIRrT5HZ=8%x;n)Z-6c!ikYbIe3A}Lq_7%U|^S2f6hgVi(K)_XO7g00000lv1?TsySzQgfWJ; z)`HpZHRp`(|Ign0>+bK~dytz7a*~Iza*+eqA69)ZdPfyRE*VfkdVBYY3 zUu?^Y*QO<0s4_G(^!vfV!S6IRHQjdRnP--g$z&88zu|l17+dsQfnvo!_U+rJKv)tR z{K^SfX zIf*p*ms~E_GBPsqKFA)%Sb$E!xJMhmH*}6YCjgMZ3@BF%UEyKh=Y}JrqbbL>GsDBf zzMwU?wEXpdG{=fEpuhB3}u>lNnTR~Z680-cOhVkry{*J;}-AIX{Xc8mEbzQSstp*+z zKo6FdmekD5tWhi$j8dr#T@r40_tt7xS8E7hH%7s;-sEdv`FVli0pC2hva)g~{?8%eytB_fdz}-W6Aox- zXh;HpJ+-xUJy_qO^7L*93lYvzu2!Vhs!2r=|Lceh;AP5HtFCfAPf@KzGNDo+Hrui# zQaTcN4~^$8nW3ne$W*oK-yTg-Gy{}OLte- z*>~S_&o@#vH5Yy38{e2j=?v=Y>($0~-g)P#8*jW(F@B>BRbteKy!uwXe5SS;CH z-8}{j@xS%0@3`<sW{(*xlV7J(;wzd@pk6=jI37T8~;yr_%M5H*ndurP3-XR5C&n zfWW0_95?}KU`5D%D31S>O(g(=Bm5l!BwQkn&8k4o&_w|~q|riwNfqQi_y%?baHlXE?X&A>TnR-+S1Ze2e9*ti;E8q z9~tSJMUHLXzPo(#$-Vv)k*6gvF<&UG(33C~#@Xl=*`0=~nsib^%y~cxRf>ueoQSe0 zlMHMAXVqX;&_N~W5ymP134l5+s(8kFu|-*ML+S5HrmFFYXt`Ft@jEdzDk zHaMV3j2>5Tpo5>fDj0AzqKqk_d||4akqtu1$5kZ6UDXVYLCLnQU?QODu|A90B*xk|D@z2do zO@D`D>vklV1MgC2dQ2;;Vo&1=LwW&TbYpMDWrzk72+p%&@L;4v-OzJkq(S1Ew7~|k zVt;lTs3SlzXtWG_yaCr-0U4IdWp2W?k%BDYSR9SS?S~O@)7%TZ5fPW(a?4F`85
    oRr5e97(GvE8|1M!?#XOPSqo47n^dqotrmrYH?kU3R5wbM|z1yFoa2B zs;;gQbo3slJXDeIAJ$kJ%|y z4vvY02ziNgkhWZfu&{J?}E)P+Y~O@^9{xG;b7&?97cFtTDTFO|y*rBW*?LLj76 zERrkW`2@#kn9y)m5K9wlOq>Mtp~h)q3$-C}XVW|q%dnCJf+IN7f-(_Ni0>mPn5V;7 zR+B9)&8H3xC%=#PmBpX_^rzewT!V&}8EWUwooZxkJVa|mI~92)WN0eJyk#k43TQ7` zOa&oA+JkYJ)8jEv0puM;MdMQ*!9Y3X4HD|;h(U-WA!epH@3ryTIK_2oJoVzeYz!XP zqZ7EcxvoK{Ky3IFk44iY$eY%OhAfmn`d_)6yTz=i* z;gL(0R|=y|xvbaM*QWu98(wv(Q%*X;U0E#-OioOlcmI9&UfS0`FbJBQb5 zO2$$U21|HdcCazmh%#arG%9`}66e3~G31E09*f5j6=ZO2yw8$JBiwu=7Bfu1RmjRvG-6OlN9lE%g{} z@7}#pdwaWg`d=!(JU2(_*^dfUj$_R7jy(k^hEX#hVUz(H=1yqJ? zjVU&OrGeALr>hG=V|5@G=mS=H?O{pFXg1e8z$ns@7%|P(Pn5LR^K`U%u1_5ZJnxIk ztJ&Vx{%-)@!g=Lmq8_JRam5wV*Ef(b?ZmMl#>588d7`~MXLD~2|lqHuOM0c){DuMEK z6lnl>G-oPBFGytMdHQBTl*|NGy|#Kg3dFBTi|P|;&sW(H)I z$4>cFI#~m+z8i-A3wH(@R8({nkhC-)G$01V_X2vF%0%>{pcy*eS%nCK_>2H_f)k;y z*T*$a(h!10If76q`Eu2*CH2>*)kZ3ALIU<8MuKSKWH`mxWoJ=Kd!Hb~tL_LGH2ZyJB`~R0YnWWQT zSWYgVFSO3iEjHKIq+9MEEFA1^H}m;0+k4W#{q-ro`_45BJGz4}pqAS8rh9KTn;8v* z$edox_xODATH{Q$H08>NNAp`I=fdsBAFRFXmZj`Jny&i$L)oeSM(MNjrIPx^??+zy zn*ZDXH9ns$t@`%NiqSEh?L4<~WV-wGZKY4)(K{amo;$zfHs5jA*q+@xYRAYpaE>RU z3T-XTBW~aqt5vVkSeL4(XQTb8U3&m*90~&f{O2|8tY&60qw8U|?Hy*@YiHX&+qP}n zwr$(C`Neh~ZLF=Kq@n_qmzAN!gjBq?u8FK4G;AQ~WWix&-Hv48kTf$mrE&XJl{@K~VXGMC7Ea>*`QZ zVIc|*4k9tEn)V9GSSUm$_aM0x%%;2M%(i8Fwh>7Qu_!$)4b|4xpys9~B+cS>R5Y!t z=W=rK+~OiUKfjEWSzLq)^71hF(c}#BRTC#2xU1z@$uSKdNCm)gAcQe>hYVcVA{hbD z0K`&p5KF`XT;K_kgg-)pfwY48$8OThTXLVyBO(#6YyuxyywlT@W;j+^cI~nCA)ic8 zh)!HzQb4yAnt=@qEi_!Jgy1bsWec0l6UJ`_01SRM-M|qwm2>w$kkO5_*6mVHhBt&E zK^m7VZPZE=)v1yJ{*b39sNqyikz{ck!~3kgLzWEa2sNp|>fBpU+p`CgZeB!z$2{v7 zO>5kE>7kNQL6f{o8fKEvL)ajoo+_ddf#5Y55k)OpcP2?}fC4`o!SInK)ckD# z)G&C0>W=|6jtmfn@yVrYi>RcyxtA=m?chI5TR<(9q~MngcG(jMugdxM@@#Jlnf5VA z)v*ToR?TI0uAXPi?$W{!0DQr1YajI7c=4gQT6D93W)=ou3QxPY3C9{Vt~~$1EPmt> z03gG!y^(v-JXPncsd`dc=?aC5j$di--?z7G&S;jJO#u~ztU$UW7g;9^QVFP; zW~=K_L?h(g5LGW9*xscSmUliG_?19Kj|+}DQ^mOxb~$?%PHsoD6W|gNg1Ce~ zKm3lgd>cq!6*JYGv&O1OvCAVXmz;d4WSE^KXB>)C2x|G~E?JrosL(Fh)6x|ZPTPED#bvtl`rGREL{qihz4>2BG=r>s)<9^d0Hh;n<2q2bcJ6{ zvRyS>Qm<|OmxjMO9&KUjj!jeExiPdXB7E@n%bo>`9{?}w%_pqris|{)OWVY>YG+N@ zeon!#CK-M>!E{>yZyY|rqjtqSuYxZOf2o!f|K4j4nM4hHC*q>lxvyvML$@9}Bu~8o z0HW{~eyRf!rP-5=B73FdVovh#W6{Amf9W=1l`yXKb z=(Y5|q-Jo%hxQA<3n^B#F#sRs2h><4o(_MW|Ni^$zyBTq%*`4ie7}bp00000NkvXX Hu0mjfn)^)Q diff --git a/htdocs/theme/common/weather/weather-showers.png b/htdocs/theme/common/weather/weather-showers.png deleted file mode 100644 index 38cd41f03b512a5199eadd727722dfb41c233914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5138 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 A)Bpeg diff --git a/htdocs/theme/common/weather/weather-snow-rain.png b/htdocs/theme/common/weather/weather-snow-rain.png deleted file mode 100644 index dc742aa1c4c7872fa28f7b862f5d710bd44318b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5406 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 IM6N<$g78RZ!~g&Q diff --git a/htdocs/theme/common/weather/weather-snow-scattered-day.png b/htdocs/theme/common/weather/weather-snow-scattered-day.png deleted file mode 100644 index 0048fec3df022aee9473c8896c1b34e2aef75ba7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6823 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 VXn=*I4|D(k002ovPDHLkV1hQR51{}6 diff --git a/htdocs/theme/common/weather/weather-snow-scattered-night.png b/htdocs/theme/common/weather/weather-snow-scattered-night.png deleted file mode 100644 index d8b0ccaa7ff12a3b92460a113a497ab758135e84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5583 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 m7ylScFu?>9OfbO&6J7#*#BHSJbzbfO0000; z1CT6D)`p*xnWgTT?wRSiw)y{S+qUfut`%4_xPi581=hCt857^VW6yLCT2+;2t7{!t zd*6t(pZ7%azb@gQBz*|*1RzB=Pr~pvLLExwz!b_D&_KBea))0R&rvma3m${E19W>4-SG`nUiu#fKmoppa1f!3|(cXYlk;K0g5Q9{@n#0^A58#?Z!UU_+5GQXvu5L@7#$6+#e4 zDfM1SO^J(6p3`wgiq%<6!WTOJDlZ0+9XN0nlrKHiiI0N}w7i zAVY%IJd6lss;Mx9CsDznDj=B%JzyKyRHZ3GQ=ugyo3DLO54Zm{4~r_hp0~Qziq)sz zSX!L@z_DY8!yo_nM?ZZ3``!fgCP+eQDFzL3)q?V*xOpx zqwSU+%KD5eae@g9dAny_-i)iv*2c|5rN%VEk}8W|`{`&l?Vt6ah1KLqt7}bD2!JGs zGzuf__4{*`SYH3W_r3GImtA&Q6Y&3Z0A<*p!;oNAY>WwOsO~`63moiha(sEx-zsDO z*<{D{hvTuM64v%2)=|ns)@#vSpQN*VRWIMV+x7&MeH*)N5LrLQ>)`77g@`tCZr%ZVUX}3q~!nd-kC$65n z!o1+%;?lZMKHlcW2*x^+B#|hJM8rszroNx1Ad=UHl3qX6cyn|67a#h-Tkp5Bve?Wr z4V%r?9*~WUjF@J#DL@L~_#1Tg>{)sC(&^yr*IZbOn#1bGPKt?cFjC#xeY|mL#M1Pw z+|c!Jxa$UYv_WLBZW}2dU#3#3Wh$Xyz!{{P{ReB!5uhoXzd#y3sV-i0I%W{i*bF*X-5YMoPS9j+)5 z0R`_>0X5c=Wx0r$L0_?dSNr``)|wlxT1|AcUiZ!gGMGOzJNxEGKjQAscl;T8*ux%X zY;kJ6*dUJMppqoJE7j^Ps+G#U&z?JX$Ab27p64cxk|_5%0Aoks*fM42_y43?p377t~wpY#xN6L{W^h zj^ZqzrkRR(RfWMFym|?&#g@tF=2lyJy-da%k<{xoQ>>LVO?7j#cJoUvxg-|;gdY9q zM+YZQo;(wV;q|jD+ZK`CwOZ|t2M!**>3E~D+k095< z`<4kqrJuqtuG_=qGbfpv-M|x~eG0YTsft|BPapR8FFN~w02#U_lFHNs5U%ZhUg!4^q za+A;)69E3#KW$t*GAKThY<#?NbocIE&pmna)LoaCmo|eSj7LXD8pXi{**?~lw52#u z3kg7)DVf)z%!uMWZ1&Hw)&C)N*X8Qzgda~Fr_&S0#u|tL0m8tMrri=imS^}p2hAw} zZNuH;+TCGR{DId%YoFj>&!I+3JSTCJkPqwzV@IEgiOvL!* zm6eH8Cyw^qz3z3dMv^3V7m?G&4%_P07IX(LH=3>1d=!R&&n3qTOq8arFpWZKzaZtnomRl+yibr4B;rxcZ!K zcY6>G3?>ZM>c8Z}EP|Xzk}sZ;+-{k=-TW~O|6!S#nfbI#m&NPwb(xvrvdp`~%*-D% zHG`oonY8a08R6lnjtaHQQYrK0%a>W!dWS7>EE~#G3M1unm?Tz0fhD0i~Q7og*ZC3xjNO$jg3vb`n1z`UOYN7y1mh8q~2-RP}=T>lT$OP zUP6XR!x0u7l5s>?MnS)0$4qbZFc!NqIusM&9;q2HXONpApOj2VJ?nbHz1$Q1cZEb415?DfMyb_NO> z>@jJTsWfZmVVY4(R#w(}Yu%M@PV{+cb#!#Q)G`vaifp)6tJ~62J%|g1cyfFMCrs>s z(r##GicU&hmO+{2y_&MIC30Ma*gBeEN&K|8SktDh*K;k=IX2}a+bHsp)$4Vut*x2` z6_ZLExb;x+R-)%pE0@aJGc)O*#5AXCP9SA~C7U|J8HSX@YIQV}z=hafZ??oR`h^&v zOzTRw5a6=8*@dOcFTd*h>y7bl^q~)Z_>1G?V`m7sKvEAujA&-Mibz(e6v;pG##ry^ zWq=d{qiDtmgfhZ}Gq5B{5wZ+@AgH8@fXdm#cvX2ns#&#?_7p{_-MZ%Wo)RJku&U(* zp{4&jRumHo`kpZqIRg+#-h)%^G%+u&;!Up`z)U{42#3Z8?24tpT}9x~p(FSI^Iw;J zarZ+vU-QsI*JL@pJhsfE=hFi9*funlSHls>`69}xtm%*no}aqrwU(DLlp~ZH09cp! zYCUhQR!g7BJ2T}b&cX^~4-A%tHY~%yJWcxoYuKizW1?=gdP`3B5kfs1X}<_zV;|j{ ziVbO?lvQ*~`feC)$dm4EEj#TIede|VR1wI;KftUq55|ilJ;_|A#Z-`an!T9)O zP_H-a#OzAe=_uD@=><#_P-#2KMAUHOhM8^E>Y1Ot@80_w^YimRl5HurM6Z9t8(vwd zRGw{S5h8}0(OxhVQT59CbjwcSgn zA-Bf9ycb}@0EV%sy%Oask&j)uHPMH1rHs?w2N;6e7PH#yFZQel?M@OPbO>vr^uP}F zD^a;r$}8CMp1lWV#e#pRlLb|a-ucdVzItY6`bCOt=&dC+IZvb{A}m?JKosOWv<_5e zh@Nq?+f61zf5eIZp?Ji)Q(k{XiO~?C=`(*`quqH}rCSC-ksc)}J=#;ytdz@igckY! z+)t(9O6su}DJQTBnHVF0L#h?;R~oxpl)y&4(fY$5|8(9np7DQs|MHi=7$c`Lb91BF z{D4ZumK+cE6O6EYsRV@;VUG@jBPigI7Lg_qMzAc#`H1N1-kc>M3j+kg^6VT&i_$U9 z8Uw@0Zw+UHrdlcOOOvAj^c*M)V2PieT=XcBo?4_8*S6Bm5N@v4cD2_nfKNd11&}0w z+0kRiZknH;z4=2Q`Vd5S0QAGc4Rf>eKij%>%V#ArV=5EG0;A}-FqZswa`Z9S5yb(F zh=Lv>rk52x;(-U#^WRmRG+C=Pp)DY3o#?m?h+{bxI5_1M)>)znz|K0?5_$`1{U8AR z;V?iA#|6r4&~MA$Rzg}pw9bDnx$MZ;*w`I94Bd9;op=BJ)1Ufi#rRZ1X_%KYS?L-f7Sis-_S5T$r2USrK5d<7>TdDOJ%=Z}A;o9yCfW*>{ zpApD?A3%j*x?b=Mn=zc~0N_oPY$LDH7{8ZjFaSsE>V%0n-@z)`-nCs1?K*nxbvJ!O zy7}XJZT_-ruf2NZnrp7HM~>(l-}r{956G65m&&UvE9W#D&FZPyxlpa_keZQ@+E1x- zs)iT^x|l9Ost`d%&y7WN)|HDmf?AWOt`3yfkW!|4ulg?*M6MBLFpJqI$}YBMt_|(f z&jtFDi5*<&|0${1L@SQdlt+`(nr-X3wggcB)X7s9k5!*_;F3#z)3+xWIkmq52O&BB z|C=^$e7)MtiqOxrNuX1fNjWX@yfaIUNWcUMQwf9Uxaj+BJ)w7RDPoD2K}}rOJu(t~ zh}6*yD<$%TcK{@j<{p^FTE>ae3?K$;7V-$y$PhywAFvG4bRdpy0tlR^OH^vxi4)B| zJ9lnf`PHw!+_NVcIc-8ejdH9>@On7RnOg=7a*;^7a))RD4gn1GrEL}fJzHH%9jvG) zfcjP`6{zWG1vI8=(DZ1+BGZ~XXE-fJz$kLNt@WN*hia4m*r2A`Xl}ZSuD*d)=IwEZ zZc(Y&6)>^vBi;Nwfhcd-xG_zo3-%Nv`tgr{Y!_X0QMP;coYc|$f94KC*`X6(i zrm-=X<$)S=xWE{MkaeyYNbQbQ=gW$Gxg66o;uOz4LPT@E7wQhcL|fP9dWtZ@6hL7P z0syK(DE8!Be31hx6zw(@g19P-1H zD}RURLt8~A)$^izN)#i5=}9~C(ip%57}yo_0t2)hy+`0Wz~^jG0SrN;S3q>ds+Kd6 zKW~VKbYQzEHK`L=j+aOx zD18F}aF8_=99nv>;5nZek)m^pi1t9lpn0c5Z$bZ%+4Eoc8hh5Wo@tvmpJCg!ooSml zov!;zcI5D3&JT)oNGd^fXPmAMXdqU2lSCjKfF|h(BQtE$%#Tzm|JP{NThfDrN{+_S zqemadfWbKLyz@wh^wvA?tjV8+rNyOsrBnnYBON?n+o-c2Wdm~3X^WmQX;hdDjD#Us zme)PxC#4KQlSBG$Vj?!07F7Ge2k+BqaEo#LK7Ra=Kx$eP2f9YQ8^^#{?{zTvp@e}g z08IIn;*k~^ZMYlTCm|*_Z{G672!g&dkhwdMTIN_4&_#{$Jnv*0;J(2*9ge^(y=Q?|+{O zi1z5r>ATeE{JPst?^PT7LW$g2O$C3Y*$qzYKQP@1M$cGomP$|G$zE=31my##`PI8e z&02LU47ZK6pnoXP0|>P0$S|c$01exn`}W(j&a4VpZC*QOmtP;*!TOlJ>uG1({(X1a z{8H0K%3U3ib9QpJre{NAzpL)c+Y8Q0CA?%GfOKs=?J77?Mz!H*FvK}WDb7q)qOeim zY|`%l!ILt8@&5O}pG*In-~486{G4;{KX&J?U2^R&y{uQn)8&Pg;d*WPc`IY*T&NUy z+S1Zqa#ifetlo;OTI^b_Td_0V@HV^akN>ulCyo;ZTWJp2#wjr%uG-S#x;4d)|CVbG z&~fH%8^51n#?i#AW7etDt*y1|x5lDg+uqvzHoI+5w@Es&Ce|RCcqW+1829(jIm_zh z`ghJ_U(bzepy!!^?;QzZcUS0XZzfS>!b*dX@(A>W=%^49`eu;dyomZ<8l~w(xSp+n zv2iRgTPO&bvm8p#ABF&TGg_4{dxd;(}G=uh#PYpaTNacdalsxF+tck3>GFQz8{QLJ~b7dz)E?i2ksvjogQiV>= zfjnK8tt-IYs?V3U2RU&CE(|ud5DVRDGut(ac7rx@fGyo>HOtUOYf4T|cHAbwzmET? z*XVvB{i9UnMY-}`w5kRcTeqR*e^p|91sEo`Y$`cI4J9n`AZ6ZgJ-YEx&M{C!8L z%h_(9_~Ak(%crNMIL*!7#ZC(vGEFU2#WKx|@k{59WGPz>?Uge9w*tWcm&eD3Ss2#r)|g4{cGAA;{0la|zjh=A5K1f3F$-TSDf1z+3X>r751FPcVTH`|$g$ zgyly@yGAahP1^j;E0J?Q-U;6`V`oz2!aWzF0TzMJur1Gwd+M{{MP=5fDyrl3e|*h9*>}-e_rDcS>q~ zJF^W1zVo*%ej|PKk}YQjj+(KJ@yvm|=?Ra2HG;z#LVM_oysC+7PL)K@dpUv|_$+<( z(c%Zz9VuGk95kN~ck=H?fUe<+A-S}oxL2mM0>O#x>@_glmnXf(_D+}@y)OAc+g|t{ zl{8mw(iv?*(R3O|?6b1${O-}hT`Rr%?7qlBDTIN}BTQwAwx$-{TP{M;?)iz4+uJp! zS}u=1L~noslgZKDZM0PLy1AKXF)z_|=;`?~DQsH($hhGN5n;|w@hvRYg8hqDF3aj} zYd85NES)(yF=X)JvYL|G%#$@%h=8_wl~v!<)oC$l%<#X!Ys3e0xdXR93f~hnVkt9x z>KZODc+H4sKe^uHAGcx_+{UD>XP) z8OR|*tS0-EHa1}^Ii|d_2EQsU#W{WZ&sh4+?tsxBr|0I9)c+;Ie>bXW@Gm0t8XOrC z>pw)-)u{rH_5R@YOa%NAQ*gp&kHEo!%iw3^rksB+^~j-x7cZ4@1bo=6P_=V4YMgB} zz$%Rf-qRUC!{@;=J?ht5fKCSlv$F_B3i%M8nJZhh;<=LwCns>X*}$F8hd8~#Fv&A6 zc$I&Mcg(P1UOzpo+cPl$pe2LtR}p}2tFAx&-oCfhWuKgmnlR#Rx4;35;5MSCCvFQ% zh>VAyQFG<(l#;ZsQy2`|Tw*YXrB-#g4V%0~88dZrvl)To<_v4}db2dOR2F2g+JM0T z0hQdeurNJK3pfY{!>H_1MHE>y_=^8kDa)_AA>hrt61j4{c?}UVn9k~;J z3qq!U6ubSh$`Lv5>+`pZxp>ca>fw*Pdl-I>`(uz_h|baqJY6j_>$mRBQEYs1zmJp8 zij9)&jtwNomtD^=uwVY@)(3S8v$>=U->#|0SKt4-Y|cN<)mk2WH3MJRoisz$j2)yq zJiC1RnZ$z^6~?H<-R}bc1%!z^(q3HtX=X9}7DO%naPgiSP3RH5WjEZ3I~iE;J&b^z z6DiL%^9!XoisZ6F(SXGypYyA0aqq;(58g<=r1&m93%#=P&|jv+vf6sQCMm#RBEXgp z50~$Izf6nco;|L4=fmW1a=a?105|0p*<;G9jE8Sz=t4jI5TTFwr#~D&@{xD8z;6Sc zDIT(5G5`tG``|Ko6=VF`lv3Z(@9it8L{3Ew#+FF2zq|oAeto+5)qfnR#-tSanY==b zB++q}SY2~YKE81MI?^+9(7&|Y_|?o+`wqGUFPtjLa|HAWK!iM5C&#tqTytvWI2sY* zH-YkbVLIFkx2NLaE{t4u>fv{bx-eqym+3%AOG8SMgVaYKWz%NAoO1J2xgJj?Rh=a% zaEv@$8F}kBNSL>fhaXiW#Y7Sf2S^v#Ey+bcGR$pPV{c!(%r8gL7Z;E!BvaBU!ZW2P zfPbBTzX*E7z3P(q=;RYL&!quy7o1qOZ2&;OBTm?6v9?1C&2`l`i_4H7)DNa369gwt zyv5>LsYt7;-R>n8_ZJ9YyrvVjwY9-Bc02S4`LLD8gW2kCc$r2ADVGEDJjAf0w-@9t z&M=y?!4oll5NxwTxSJ~+@#MoIMEvyx7!VZ@5jUZ~5bSz)xQ*b14PoIE66esEB3HPL zyaSuR`gHZWshYC)UZD_>#fDI^5M~}ca_+$mv*OO1TUxgI`??CWTDY#&!zBg<%5E)W zI*VW|5#*9i12T;oZcr4=AtLxRwZj^n4sQB-!yZppNb+!n&ln5P-~h%0eGy zBUTZ^Q%H=_tY`Kiq)RZEtZO9uBo~%obafq`B&m`_(q>Yv0%J*<^q0wy@vEi)!O>cJ zJQHridC;0M31h=&xo{{zyO{;|VeVWCl}a!;5T<#!!^`kKq8jWyVB!m!~9cThRjO6p+Gov1&$vI^G`cbz3p#c9n zc87gXkJhwIg3#6h$bv=fb*WxI@09ZgCNJ;X17kS934Qkk7vB1k6YFJcT z13h$rP5?kQtIzF0!SnTinqJ5;nP8H^0;jDMoOV#KQQZMEbb2^UQe{0!i}A!>k0~lc zFZdl`3caHrU<$7b()V!evUFR^NbA(ykyoB?YOw6)j0Nib#vhFRR3BNf(g^ z_aP%6T}f)Bk*=X6Lyb& z5;Eb>PAL(96uK|To2|Kg9bMr!f(CyOy4%3l-3=z`dZ7s@fWMUhnH@-Ta)L+uetV?= zB&1Wso<5C#9|3Gt(BI1gmUVW)VXXm<@^~=C!wW=z3juCsBgf4Ro~I}<>U8iKod$d| zPxJDI;s5s?vj5ToNF+!TaUjvt1LpPWA&<@kaC3nL-QBR4?F827NLW-XMbE#S0DT52 zGYiGeZm`Z>4BLqJm+-hS%x(i$tq$HVmqKMX1Fi!NQbo@2*W=nXImSyqXwr##cX^|ue-#eYo^6uTczkJLw$9(SSqmOQ2YK$>|+W@3= zw?6vOkFJNX-&(tN?c-r>DwfaZd56+e5_gV=vV4!@nD2PzxK*oGiCV2D?z-!)`_bO< zAOG;6pwK;dCo`Q|sj`6O8U$E8wfjaJ%qT~R0$s2HqDO9w$9pp0()e&6@C z%jo|8y;`ku?X6q4c6aR9@xGHzI_bxV9o?rs^{Ic8F~EB3Ti<#DEPFnzT1^4z`**!w zr(*iT7+M_t{D!dv0%HjjE`DEGSs_@3V$D5h;^42%&NZIDefy=~`rPL}FYmnbj@y3p zqaW?n*#ET|K%f82XFfA|@4fe4y?OKI2>_t2N((!VLnXArsdA(^0w5IzQ|Jb0bQ6F@ zHniJqew&-`h~SXkg(C+mut*}CZUJOX9{0K+tN(9{b> zST45k-OgB#WNhoQbIv~HyKj8cTc3H;jn|+1t#5sE=WmnS{8OgXfBeUPe4bVwR->X2 zk`_*>%$CxfcQlSm10-9T2BC0IOixdP0fF$SJX{8fTNaeJEUfDorBYF@s#a__pR<%Q zHu<4?$ID*+`Wsg2-aj8SaoA6$rVblK0ClR>)kTPqK{Elg{8`tRe@s#HU;p)AV*B>( z5;py4^0{_1q93nW@qm zAf`=e0t|s?z9yDsCZ=hS&YlTG>LT0yVaV^~11m5hvxP(mmv1_uXCeQ6&)|Kh8Rl4}+5JUF#^^Klq5vUl&^ zqmMiG*eOJ3Dsji1cap|%11cZK3BDuc2?V|0LKKFXT+S775;Gn@;~7sE4?g&iIB?(qO_jj%#ZrlM@4!X$H9kHmTAc{N z4P|iC2N;sdPE2kT4FCZhI9>(;$3scJ17H9mv6ptI$kae-GDUH0LN~**5KIY_X)Lw7 zhVO?)ZFR*cSIQ;=rvZbgR;hFn%JQu7Ybf3iP_KXe>*W-j36?w_R>2sSkQxp>ZVp5r|J@sH2H=JjtZJ?)v#a)0vUA7!8Zw5J!3I_l^w zikU-(h6X=&=%I(b4FW!{T&_HRY<&DkC|3fNO!}lHjZDU7BE~xbh?9gtF7M_^=T@^x zp$UL2!dGMD^*s7rFfJ#`It@Zu+t$8r5d?6Y5nn5cKqm$VYFNugW^f3Go|kpV2*dMz zh5Za06bFL|lEJv3rz^|zJ;ooz60W>^&%V2-Hm&)wgyJ7NGu5<^(;ORJ6K?%-Rbzqv!-UWAHZ)0 zhJ0AX#N-SD3Imyr%n(5YVN3-i1_NmoVmynSIHC39C{Bx=Sj5T_5rXq-F+(SwOc|C`*83F&re!5=@Dh?Lqa#^^X)XZa+P%$m5GPX=$NHb0#kcuHs z$he_d2Ipn`u<1I&tS>j>ma0eA3t#xcw~mjEJq?0cP~L`uvfgYNb8{;u)|S}Jaxf7f zPIGSE4YOf`S@21HvocH;Gcdkb})Ny(9%qs8|GRVp|{sKV|$% zSlV)NK{_iRic%;FtbxMvqFQkwNdl7#N$WG%=e0iMHkbZqfL57sWj z6$)5460kVIY_&ZD@?nn6u^lj|=Xt8pXnJ7E&UU+X#>B+f89)5~7azr0C1Gks={b`q zsE6`M3+Q2kIMKdi>-eFxrEpOgNZWS-9%H2qbqI*w2*UfMuALSxh)5XExh!$hG{JSi zI?_|G=Yt_|FZ#R0w^GT1YF2#$zjMyu5p`)60MPAmoh z05->XpA{*}XR|gkw5C$t@a`>Jwzg5AeH}9Un!>WtY%Z+!R>u&S1qBZq5I#Wl<{*gT zu3$;p%`};_!4lk6!a@YPVNOJ!k02nrn76?m(vj~_(l#ai)U^8LEZ0z28_NQ4hIWy7 z3BW@Zi32dqWLiXGVg$Fqq5{fn6lDb5M{9Rm*e}p5L@GAO5Lg?k#9SM$4Uh&iNR=5J zsFH=n`r-J^vHz=*gx(&kVbZU3js^&M>2e{hFsx`mNnQ$<#gbHVEM940`Ze^CS%)zJ z7nK5oSQrVWIh&MMc;-C)nTsauH%->}q%LR-dLv?kVGx{52^n-F`aKk68~~yEu?O^4 z71Rv#A>qFbx!eU}0p-v~mQH zLa>i1#7v7Ku9s+~I1V!zZ!iXi^4T8-J|GVi;sIl^nI4&`i=APdKzV=j{QT@KuX@$1 z5|Liki(d4?rFN$$i-p1wwv<_VfWZQX6`alj*o?~P;zBDaNnb^4s2J489hTr&VQA2z zv_B%CP>o{)rcr@=z&==qVB^%tw1z3X^DdS5Dz^#0I?uatXj2l{0Tf&KISuAfMe=SAJ$699s@0n zh-fC)XOV@*BeJ04d`B^ZdH+v;y$1m&BM1)NFs4hufLsUe$)fE39Xs}3cm2)(3p~Ej zYR+GN-L==O{H*c>;6MNKKSi}#QA^89h5E|M6p*XT&d!;L0XBk{8Deu#iNS<^pU?*> zdZAb(OOR@*yso#qD0ZMUpZzeTl2pggmUd7DqJD=@GnU{Ry4a`)3m^iJ7E}QPDrv(y zUh*CRlsE_|58?#f6w#hEk6Dt_06d`09GLmLO690WFTM1KiTD+lL_{>;hc@c_!$wC& zpMlD+V9>&e(dl)mh%WSK869Do0lSamT4Wd-n9;@3$^4E#EsdSbHLBc7ru}6zj-N zMQBZvzr{fqhkj3Blu8k|^l}g~!5pR{RB3n*6xo34Fau2Iki{pV= zCeqIYok5wPz$Nhwh6#Mq+?HUF{4s9|uchCHxB~!ajOHpZ8og*Z&by5fqcD48aXnmMBzmunw#t5(+)DE!Je1^ zp+d#8jlBsBE~Z-63aAWO`?E?F45$hWwZk}m%-GoEmY2QkWizLqdaC+W4B(~H!@xkT zV~EmLWq3D$Iz6m00n65)I4Z_|>gxj#F*Rvn_zpo79%EXP@0NtnP>=--gBVj=7{&ZW z$oG{v@ua7SqmDjWjE!v&6B8T6=;(T(jDpy+dpAp66sfRqhHfCZra_=sIZBGJ8I=Oi z(ZN+&%vO4Mk|`F7hqgPdUZq;yi7KOUO5qb5{F)7>q}6N#!hk(w2gZR-{DlZNv3hluM`r^oZ`-~_ z3=NGVc)DVGdKYSlwy?4$?iTk>80iHmF9AXTx>Nat?gRjIHVWw)0G$j`F$Riw_1M_> z`|&>pb=YBtf9uLCuU!0f0Pq5Oh9zZ$4W|(o?tvy7f&M70ZA6J78eIsHiJ@#@)SH2D zWIzkVRNg|NL?;xB%K;85p;$9oAafE{g@_%wEX!g|=bT#*<+3Y!P-baqCyui#;>6>R z5xe#+3S`XGuTkLiG!qiKln+Ju-3!0~UGqnbGa)iUqzr|kiG7RSpZi=;8=tx#h0YI9W8c?kc1}X|wy6VMS2~d~{ph2E zky+lb+|K8ZSR4Kfc%Xb*>tFjo8IIi&IS0&PDvWr*5lvTAN)A(5rt65iA9_R_v#BZ? zpm5yWC$6}`5<8n!@%)oFi$@;53pDJAb|Dg_q7(;ao0w~I{cE<^;>1n9fOjy?gs3uu zSTGeLfb(ZC7?asYXLL808?iIa*rrXJjQ=awECAZDwl{tvIK*%#^>%@}LKV8YySoeh zukJ3hZv0pG(vIp@#*n(;Zo!E{5;P%#6LQ|o9?zJ&{oKwnq(>#GgrG*5bb3tDn4>^V#;n+Bno z2~Ag3XYE!`(OYY^wFVc*=I$i0uyJzkl%-LVYEjL38bzstNbFqSzi)45X^G%@ZL3*l zWsTO9>fW(~nWgA1gKbF>%Y*|MmXvgJmWP$LrnSb&zPV14UFBtNVZ)}GVi{2fRZCN= zQc_v3_35a8LmXx?>S^*PPo5ayr{dvzf;MF3y`k=dc9}VL8_#j+KGvb@fX&W34;*6* zUwM9c7r$Kx1Gnt-9J&0&icuSHvMU980)JsG$0%&TSFcK^T2i4X2M?7o$< zc;@y;LGw0#k*z34U3_M(Y{QP=eY=iDoPHfGdGO?=A|$V{MW9lnJ|nw1{y|)I^xRWV z`O9zQ;n?XrkDs~naKV97*G65w9@1_5jp*ewc6~nK@X=E?Ll$4#hx*S6Zomxj`>Xe z9k(rc2m#DYN$2<+R2$expcOqSqch zo4V=lb9rcTs(w^rI<>u+bi9e68aHp^><^)IqRL@Rw> zAD)$;St|~10fLzs+o?0p)hhd?ne))Gy#gbyS6qQMWZB80MqPv6tJhqrg}uwVyoe*d zjDzbOsYJn;28x8~$r{*{BdL^^>)vHE*axQv`0T4vHWpi2(Yn>uLmF|f)ar)jLMx4B z3^q5-)m7EfQbpykb;E)Y1O0eBmU&-=>7p6eXRTYEpsuKFa`Rn1F(9CO*WjF@tm4>^ zq89Lm3PEX0y;fb*+*sWNzXXnhKAvjXdEY{4!)wSYI&a)2ODpcCK`YO^(zx|qI|(hLW$-g+H%`b>DdxI{0N$_%2E43(&;7z3aU$A0_9ufLYm&^ci5 zIcS5^!Jp3I4yVH}0&@aoeo#_Acli6e;hQlBBlb&sz<;subTohM+2}@=T~|g*296d= zP%M>UIr-sV7K?BBqYp5|HFSi@FHX{DvI8YdI$V10Epe5k7jCCNxv*J0genl zmtF7n?`6``yg(_Fh~U4mTLeNeFvt>p6#0Kol7>22;Hq&nb4pzx-B7)ZtdJ#YjsB5C zV^grL`BzDom`(?`=W)69{U`U`%t#u4 zxHUPWwRdhoL-6aE+8#kc2uAuX4;ndm{)gM)w}ED2-)%;KQ3Stp$aGy#AF(--@9KN{ zYF0j4gIC|5|6xWA zdQZI=4TSJ;q(nYN%E^W)GLo%{4fGEUu zq5_BFlhKWwrc_m9EtwbYq~sv;as*P+$R$w1ODqEfG>^l-?eWX$a zdn(Fd1^HL2A+!Gu68%lCu7RUeD)24MVVZ+I93a`Jn9TxTsveg3xB{2V9dFsP;kJ`C z%=%Re(5a_~ci#~mnP8~1gLZKJ-s!;`5ipr*!s0+XQm${icy>eJSY^)XqZ9-rZgzKj zCQQ6~^Zwi|llp$yR9?2j-IZgb)xs-nEj%R|s8p?mSR#SLNkN|KlprFPuP9WQVrc=c z@=DmG(?PVW3mkIfK&S%;&eQ*ytUrfe8LE@_0zdc$CLNCon|~%1tz2h}hVLLW6e&dl zGH7^m8d1xBVR=$BQ615q@`FuWH3E76DO^>iVzczTymd`JST#T z|6YXxyh~meN`{Spu>|`R3$T+wfb?Ir2M`S9{7++{9jq>!hWZZkp2W5=I<-xv@EuH@ zNI?|u9PHpIX=N^P)S{I&aL&s5t5h6X$z)Ev3n$Xb_n8dfF6RM-w6L>rBMC8q z?l5hjn=!z)wuZqZlR4K=2ffI92s?G6=zrw`d^5!6>Y`EBLE^KRs>Z4}Dew)vdWBFZ z#2!QehPZpc3}Wa?$v8i#(ZLv5HS8mrf267kW)~NMmPUbUpnPQ?_N}Xf)SUvr+7?J6 zMv;G01Ke$J#`rN;df1d(SilBp|1FR;p z7_6;_+g4UE#@-2-e~SXVNk$9O_4iOH&_KHXIXV@rjj5WmGYtGZ49))11&E13D$@)` zJKDokqxKtjz;M_wL#=@;BtC5E@&{3==a(7-G|u5*|r(mwrzcgakkBepU+rKdSly3t6I-@y z8MIvjzYu?G{Qi+p zY+3z=g^!h#w5;d#dWFm7@?c684~m*{yejZH`1cjIfolI~a|n9XRaeO^Tec{T8Z~0s zY*xiWjl3RrA?FHh-n`lRs#x{@n#vlZOP4M(mj&9eQ4?m!6j7W`YxnNmB$LUQWo2dZ zb0=ExITkKl2)SHN!F+CAHza4ww5M#hMCfM%Py!NndLI`!)rI%WlUw*|2s_^s{g6%d8J-lk=^0%>G>diObG*Q$f z^3^#P=`5Q9p~ z%K9J|w`rJEpf4@cAo8>2aC$f#E{erskL7jaO|Rfl;cyDdC=Z9ixd+xf*s@EP9^)!1 zlifq%YK}xDu4^bLY#pmpCt&Q@x$h&)u?cgtOg006Ns%~FRh4K$5F`SoX-X8$BIGku z;xolz5Qai1c;Hngl5vvD>7;foKk@l}RH(upqD&=IomZ}0p^=|j0vBC$k%Gia(T*K7 zO~ZP6Jqw^qqlS&z)~;QvK0Y%$0vp3gSYR5)XE_M58!$83Y%~%rf1GjksbH-@wx+s9 zEssP_R#eZh!$-=!_GketX_vz(+JrFNLb4p=sVxdYVqn98Yu)8^QGo*3ZbZm@J}*8vN0PiWoAWd`F@fJEr#^XuQ4U+}@Ug~f-?VfBgWhh*JFdE+3j(6_dnY3@;Uc~@W zSW+f#xaBsvXXkcn?%a6_PTQzcr}ojoU~pP-amm1{s!#YZ3n0g_s|(*JOETMy!?4W% zA7*A|P71@!MPVokQ$d)SIm^t<%sZ2TZJKU_WJ~>WzIv`MSkRQmYDo|7x#ygF<;9*R zsJ1(u8BOjKoHh;8&@$HM3)9XFnMfX5xTt8eTLjee&Fso*lH9X!|AD7_tAC)^8`bCM zX2IEkdo@iIOtwxy<6;bu-UI|-V0`sjEt;E~i`hNFSE~vVaI|Kt*>r_aTKAcNpZtGcWeEg_EeexH0PrAg9q=w{n%rV$zyd^v)befRa#EWvq8MBg|}_n*6en= zGmYlTzFIZiefZ&rzhFGh8?9EWL$>?9p0d#}jEM!MO|K20EhGEdiH-6R*KNIA=b24| z!Qg4*QL(eroqfyV!k|Vrm0+rv;`CxrGJJ2ms{qmDe{bKP!t z_gZf)*Ffwx$?{P&KffiH<2q%tO0dEhMDbo5jZ3RUI*08#$U0O71duLtpS2ai`OYN@Y0+#d#lj(@r&?bBqk04J<@qVoUf>Jdxt2pOA|Xi&%_QKK)Ky+SVQyy z5Xwt78o5HdW71UDG_fVnD&@Rt0T69aG)Bjvka*ooj18efj14a157ctbxlRplG@)u$ zffy=8<1)WQT8^#Vtea#Zz(zDlnzQC)BrZu4R$*FO>t!~~#`Fm^O9E$P!(nENi;I~I z{Pz9(_I+>n?yX<^_{ZLN#dp5*oq}<3mJRozG3m%b-E5RgQw7e>{ykNSLx7tzHX9@W zE6@{v6Qp`|HfB&)T^O>!!37AQazA67i8>?;Dgsfe4mQYl=t&My9x~TKzw2W3<^%Ik|>r{T)kFhDh{=`@{D#% zP0cLKBQ4Z^eR9T1dIQI}s^&)~S)Lh(p0Bi8%~Wit-G0Yi`*-cy{*R-NKDsc1e&s7) z_3SO1H$6$4h%BrW^b9(o|8^W$KcG-oD@g^al6ivw1W7PZ)`fsEDXs$?*CeHy=B12> z%Em$9umpx62@c0N%ubSN2r!jP-U`{1Kn(NaJGsDS9M>5ugOywwUY-s8HE+rKw8%t- zgn4H8o8SEIlP8{d+^v8A``?Wt&hyblz5d`0T5tyg{d$I$rMV_1Vnrx@OoG`cE2$w1 zjGt@`GXYuiw5d>9<73M#Cr)&2OZyHGmOP+FPp}cVT4tVs8KOOb5qPO{uxH({FWSzN#w2%$8o~KfoFej3P8)O5TH5<#+{_>Z< z-=&wkQx6fe4$Bl0j$3c+cF-6}$z;P)fKY(| zOZP^!;#^ZHui3r#-1oW7n;&z>KmYl&b$gH_?)7?38BKb<{z>{_lz&t!9-@j`VH-iRtmo zMw>10B=6uq{H+g)3)(lR&T#X&2WWjvECaG2v%uKkIeYi+x#j4i4_p5E&%ex+4|>F! z#OpKG`JqB5w2-`WV>-|)7!5k}Yy$lgknxVr-z%%D%2a79hjMDY0xvC%*R8Fl1^=L% zqbvp&cZ{cU=voL^4=Bh4M!^Uh>3SJjZZaC$Zi`et6a7769IP^xLl{EiBPr5t*0dkw z7D_AYY}>jmSHhe<%n|8T*eml{S(FzqEG%73z(dh^q|CE&xQCZsM%@Ily2zsWn?QWJ-66G$s|S?8b32Z4Yx`+x!BwE_3Uz_50EE)YMZXiJD3ij=B+K z5u9C%QO~Ow;RFF8y}tA5;R9A0hel8;#~){=5HR zq&D^G%gZZAY1X4QZJzJOic;6;_c0h2n3TB!ADGnI3i@LMT$c&B-NtM?d;ewsYsvwtLqxwtc&B zcP+d7uDdW`Wf9q>8@&fUq8LLnM&B{%40%>Yj?7?);s*qub~^17d;PWHwr$(*l$?8a zXOU|A-%+amE=74+Q|PjoQR! z_*%%!_QXkYl`bEx#$ubAqKI;HXy}xY(r4MoEz9|93A#ng1P?{YRB4MVBU@b?+wScx zHi;%_lPyx$M~Q;YlAKLXx1g^rF5O|Py=8my6CY=H-n(G!dVo923rmKXBo=;<8R=P~ z)A|B4Bw$=pQne2sc{OJ4f92W*P@Czx2k`$FC&X}f>QsO_b$55Wr|#{#ySr;;h59OW zcii0}L4qbJ2}B_B-0w2%owHPquK#f7eQf5LH|*EQNhJDd&tQmQ+}U$&)@pf0+qZ8& z{qe^i+wOWb78@H2eT$AG_w6kez!Yq=b_{H5GY#i(nV!aW*l(HajH#i_)6SKLYg#4F z14FIo(m4#lptJuj7s|nybr=^d?A#F9Y2P`mi4ns^F6_*nNbCz`qY%-(-H=m~0y}#M zXK64Ji`%haq$kSDGSFf$LM9PHCgY*5-T;M+)7eIsv-lX%hfRQ>bKydV)xo}i7>>QO z%ACdG|KBql)VW-BG&eTh@8%-gw{6=t>s_zL)~s2BoxARH)K}yf+MI-W#Rd6CH4TlA zHrCazY}2V%->NBI->hkVp}gI<+`y4Lv>Kg5tyZI|T8-?2TBuYiIEH$zobhcj1I?C(>v@7E(@$sA;r7|_7}&Kh+KX>7Ltpn+DaBb`o58jZ%$ zX0#c29Bv)E3ZLflxGCq)pSO2wfjfKj(MNyUTRXa5TEXJ`?v@P+H=K>w8ojwCv!Fw& za6Qd48H4Ke6vB~7e9T6rPA3cQJ$RN^)ifE~+_AD#&H4PmSC9ke7yJRF$53ROEzzGZw z6-z6RDEK0#qN;qTT+C!Txdb~KbhcX|o>pUOW@E6ERO-SLP`%A=)7fl{R@r1U4C-mU z!Oo0Ijzg$Ee*C!O-@YC8AMqMDFd}qhRZeDVUD-uvCmzG|4;sl`GS|y^v&wCeI=?bt z_DIfGSvuJyj@0kL()jpymrZp2uF-GeFoi(iBdp0j@50`twE2WhFU_uw5*T^o-+69M zh^oP;KXCB7&!jRB*O}uZ0?ZwJYk;4}P#-T|u&TzER?%v(ese9|Md}|EQT^@SSLV+j zS=i8Is1NcH)s?_6rlLsO5G5_UajMjNC&)5LD(v_;CP<%^X$*7+=Z4;8x zX-kuaEb%GEgc>zz&R=h+*?A<_`cATjMDDX6Ui?OU%#w$`?J<1HBfL$qnKNS6>>Uoc za#rlgC?3D#Sk9mYuk;rMtmE!Dlr!c2L)lB^K?@|f3m*Ojt;&n0<5^|d#_B99SWY5^ zcdvl~&Pj26pRqFs?T-7rejmD2XC*1k29r(XZREIk2W~Aq^=ypn*{$9TgAO7_r3iH$ zZptcetgSb^;VO4|ZqbwhPc>;QWnyP;?=}-MEEY$L-rP}gt3@2|Xg4oy)0(*{s%$)V z-IlYiqNJo@aq*7Md4H?<=T278bmYv^muD0H;Ei9p& zlni=yf9&P6Z+&n)v8u+ds#a5FdbX~ztb!(?i&xb1Gj_&in0rim=2LWW4V}Pq4H?73 ze@7o?s%B!uT2KHwPib`ouRvyh|zaBAV?YGbQ z4gc^)Mn(e%KPUTFtD1vV1YiJQ!!JP*I#1Gn!Rv1T z5cXeu^r&0p8!w=nIWM1of9B)Ij6R?;h3 zx#s0N_oVAmirb0J^mpvbRyNbi2d_E$R-btX^~vexm+Bixdp(s#e|Ns-qvOgBn!NqE z34k+LA*0^t6S45CAJOF(seqQsxVF3>9(^Qi{9FCzZyU43H`pz*`|pyHV`Wp7vJyWt zAC*eT1OiO3*&RZLT5ESdFpn$n#BLFq*4k}Qu>tzQ&1jDGaH5X(b|`r~_@BL!Wg0$j z@UB5aLuAK~pGtBN9DD}7PG59Xe8UqDpd_-SE?wzw4C;hS^4F)GZ&R7t|gFnVk!l& zLolBmYF84{DTICd@Vj5;?*E{qjmB;`rhWT^(-G{?*CwUYgQ?k$$f6QU?6sS1eV=}Y zz(UmePsYWp{@`K!O8D+QmrMpA#Jza@jW=%Bxjes^_x5MxlT$${MP=tun5vo{`21+b z%i9i?Qrwx!Z__eqKyCqjr@KY%$!YXByRvg{BvU{^k$KPb&HKKR2QQu$pW+DozW}g< z@hCeGcNLb>T=s1Y5#iUNcyz|yzqWZW?qJB;V=Lav)l%=xDKyftxT5chO6U-KxO}!MuBq#({$?_b%*>@p<(2ehNd-N}{)~S@GR@Oysf`WP zk+cGmzx^XI8F?g6&!LE$IV44wUt|VI!k>4Ux^?CeNY)494n)qjCjoHLjYviw25lSE zWyRNX@=4+!h#3wZq(A=fia>0|0BdcN-P_YMOe({;W(}TfY{YuI9eSA*k4Pn$)1%+&FJvcAwq_MX8kw8CJ zX^S3LO&z!(;Gs&_f_PU2#%Q&;pshirMuTf$Fjp*wZ*3!X>J7La;E(6MToLE#hEI4r zpxuT`-5%5UUw^19$D_}xkR~Qad*WfjGH<+r`_)sLohyXtvRoCHh4|h1s z7R+~b!B{qsExH!GE*Im=;1GuJAK>BN#o_cc=qyOQ5Z`QRzL`-tR z1ap8YyB*IOT5(*{3XO{xA~w5BYBJh}j(`pT35AGmGvd9KC7}Jikm7E}L`w%$VBjDw zZfct0&G0eRRgU|r>!4)!1RGz7vZx5A0lzZ7)O*krk<_OL?&7m|iK(oj2xS#bSJu$f zQ|C!|=pZq78d`}-Bv)2bdVUdIIev+paS!onG+BK)CMmlKCw zc4FBeWF=;k1o!aSXT+pslY4F<1+u|#KYNDwzitcs0yJPbVCHh*Y%xH9d)Tstp{^hK zk8$uj(b@<<4|hy7v_fqs{0sgB0l2Cmj@SvScwC4W28o_-h&pzR{yG6bA;NsTu}Pyt ztlo%&5(%by`9S`c2*9;ua&mXWV+;ecUXM?B97q^|S)(QC6|=Z?yFY`e|mfO5Vx+0 rBJ%Ty2iCSNgd0iZT2x9B{L20p98TfA!HL{&00000NkvXXu0mjf{2wFn From 419fd940252948802230b477cbdc85d3bebc097f Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 10 May 2022 12:08:23 +0200 Subject: [PATCH 424/473] NEW uncheck send message when private message is checked --- htdocs/core/class/html.formticket.class.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index aba62587fa1..331fe542cb4 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1208,19 +1208,37 @@ class FormTicket jQuery(document).ready(function() { send_email=' . $send_email.'; if (send_email) { + if (!jQuery("#send_msg_email").is(":checked")) { + jQuery("#send_msg_email").prop("checked", true).trigger("change"); + } jQuery(".email_line").show(); } else { + if (!jQuery("#private_message").is(":checked")) { + jQuery("#private_message").prop("checked", true).trigger("change"); + } jQuery(".email_line").hide(); } jQuery("#send_msg_email").click(function() { if(jQuery(this).is(":checked")) { + if (jQuery("#private_message").is(":checked")) { + jQuery("#private_message").prop("checked", false).trigger("change"); + } jQuery(".email_line").show(); } else { jQuery(".email_line").hide(); } - });'; + }); + + jQuery("#private_message").click(function() { + if (jQuery(this).is(":checked")) { + if (jQuery("#send_msg_email").is(":checked")) { + jQuery("#send_msg_email").prop("checked", false).trigger("change"); + } + jQuery(".email_line").hide(); + } + });'; print '}); '; From 6f8eef9550fd9c886b7f8229cd98f29ef62e19d0 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 10 May 2022 12:56:22 +0200 Subject: [PATCH 425/473] FIX missing executeHooks --- htdocs/install/upgrade2.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index cda8fc0bc13..f7a97c8af82 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -173,7 +173,12 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ // Create the global $hookmanager object include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager = new HookManager($db); - $reshook = $hookmanager->initHooks(array('doUpgradeBefore')); + $hookmanager->initHooks(array('upgrade2')); + + $parameters = array('versionfrom' => $versionfrom, 'versionto' => $versionto); + $object = new stdClass(); + $action = "upgrade"; + $reshook = $hookmanager->executeHooks('doUpgradeBefore', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook >= 0 && is_array($hookmanager->resArray)) { // Example: $hookmanager->resArray = array(2, 3, 10); $listofentities = array_unique(array_merge($listofentities, $hookmanager->resArray)); From 8692038be2c48980ea19191998843cdf1df76440 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 10 May 2022 14:03:09 +0200 Subject: [PATCH 426/473] FIX missing loading of global conf --- htdocs/install/upgrade2.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index cda8fc0bc13..1818a1bc327 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -167,6 +167,9 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ } $conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey; + // Load global conf + $conf->setValues($db); + $listofentities = array(1); @@ -4616,7 +4619,7 @@ function migrate_user_photospath2() if ($entity > 1) { $dir = DOL_DATA_ROOT.'/'.$entity.'/users'; } else { - $dir = $conf->user->multidir_output[$entity]; // $conf->user->multidir_output[] for each entity is construct by the multicompany module + $dir = DOL_DATA_ROOT.'/users'; } if ($dir) { From 91d539bbefc24f2c8693887a05b014ce6d51e2cb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 14:38:40 +0200 Subject: [PATCH 427/473] Clean code of not used method --- htdocs/core/class/cunits.class.php | 30 ++++++++++++------- htdocs/core/class/validate.class.php | 15 ++++++---- .../class/ProductCombination.class.php | 25 ++++++++++------ 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/htdocs/core/class/cunits.class.php b/htdocs/core/class/cunits.class.php index d7571b8ca90..dfc22fd37ec 100644 --- a/htdocs/core/class/cunits.class.php +++ b/htdocs/core/class/cunits.class.php @@ -463,22 +463,30 @@ class CUnits // extends CommonObject } /** - * get scale of unit factor - * @param int $id id of unit in dictionary - * @return float|int + * Get scale of unit factor + * + * @param int $id Id of unit in dictionary + * @return float|int Scale of unit */ public function scaleOfUnitPow($id) { $base = 10; - // TODO : add base col into unit dictionary table - $unit = $this->db->getRow("SELECT scale, unit_type from ".$this->db->prefix()."c_units WHERE rowid = ".intval($id)); - if ($unit) { - // TODO : if base exist in unit dictionary table remove this convertion exception and update convertion infos in database exemple time hour currently scale 3600 will become scale 2 base 60 - if ($unit->unit_type == 'time') { - return floatval($unit->scale); - } - return pow($base, floatval($unit->scale)); + $sql = "SELECT scale, unit_type FROM ".$this->db->prefix()."c_units WHERE rowid = ".((int) $id); + + $resql = $this->db->query($sql); + if ($resql) { + // TODO : add base col into unit dictionary table + $unit = $this->db->fetch_object($sql); + if ($unit) { + // TODO : if base exists in unit dictionary table, remove this convertion exception and update convertion infos in database. + // Example time hour currently scale 3600 will become scale 2 base 60 + if ($unit->unit_type == 'time') { + return floatval($unit->scale); + } + + return pow($base, floatval($unit->scale)); + } } return 0; diff --git a/htdocs/core/class/validate.class.php b/htdocs/core/class/validate.class.php index d3aa5707c05..ac4c14f7937 100644 --- a/htdocs/core/class/validate.class.php +++ b/htdocs/core/class/validate.class.php @@ -281,14 +281,17 @@ class Validate } foreach ($value_arr as $val) { - $sql = "SELECT ".$col." FROM ".$this->db->prefix().$table." WHERE ".$col." = '".$this->db->escape($val)."'"; // nore quick than count(*) to check existing of a row - $resql = $this->db->getRow($sql); + $sql = "SELECT ".$col." FROM ".$this->db->prefix().$table." WHERE ".$col." = '".$this->db->escape($val)."' LIMIT 1"; // more quick than count(*) to check existing of a row + $resql = $this->db->query($sql); if ($resql) { - continue; - } else { - $this->error = $this->outputLang->trans('RequireValidExistingElement'); - return false; + $obj = $this->db->fetch_object($resql); + if ($obj) { + continue; + } } + // If something was wrong + $this->error = $this->outputLang->trans('RequireValidExistingElement'); + return false; } return true; diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index 2de511811a7..63e721c0d37 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -1057,12 +1057,16 @@ class ProductCombinationLevel */ public function fetch($rowid) { - $sql = "SELECT rowid, fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".(int) $rowid; + $sql = "SELECT rowid, fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " WHERE rowid = ".(int) $rowid; - $obj = $this->db->getRow($sql); - - if ($obj) { - return $this->fetchFormObj($obj); + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + return $this->fetchFormObj($obj); + } } return -1; @@ -1141,11 +1145,14 @@ class ProductCombinationLevel $sql = "SELECT rowid id"; $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE fk_product_attribute_combination = ".(int) $this->fk_product_attribute_combination; - $sql .= ' AND fk_price_level = '.intval($this->fk_price_level); + $sql .= ' AND fk_price_level = '.((int) $this->fk_price_level); - $existObj = $this->db->getRow($sql); - if ($existObj) { - $this->id = $existObj->id; + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + $this->id = $obj->id; + } } } From 8ef75ecc7c1dd5f47e59c7af5f676cf2870e8ff3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 15:27:43 +0200 Subject: [PATCH 428/473] Better fix fox #20807 --- htdocs/compta/bank/line.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/compta/bank/line.php b/htdocs/compta/bank/line.php index d1750a0bb94..90a35b30c86 100644 --- a/htdocs/compta/bank/line.php +++ b/htdocs/compta/bank/line.php @@ -52,11 +52,12 @@ if (!empty($conf->salaries->enabled)) { $id = GETPOST('rowid', 'int'); -$accountid = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('account', 'int')); +$rowid = GETPOST("rowid", 'int'); +$accountoldid = GETPOST('account', 'int'); // GETPOST('account') is old account id +$accountid = GETPOST('accountid', 'int'); // GETPOST('accountid') is new account id $ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); -$rowid = GETPOST("rowid", 'int'); $orig_account = GETPOST("orig_account"); $backtopage = GETPOST('backtopage', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); @@ -68,7 +69,7 @@ if ($user->socid) { $socid = $user->socid; } -$result = restrictedArea($user, 'banque', $accountid, 'bank_account'); +$result = restrictedArea($user, 'banque', $accountoldid, 'bank_account'); if (!$user->rights->banque->lire && !$user->rights->banque->consolidate) { accessforbidden(); } @@ -126,15 +127,19 @@ if ($user->rights->banque->modifier && $action == "update") { $acline->fetch($rowid); $acsource = new Account($db); - $acsource->fetch($id); + $acsource->fetch($accountoldid); $actarget = new Account($db); if (GETPOST('accountid', 'int') > 0 && !$acline->rappro && !$acline->getVentilExportCompta()) { // We ask to change bank account $actarget->fetch(GETPOST('accountid', 'int')); } else { - $actarget->fetch($id); + $actarget->fetch($accountoldid); } + if (!($actarget->id > 0)) { + setEventMessages($langs->trans("ErrorFailedToLoadBankAccount"), null, 'errors'); + $error++; + } if ($actarget->courant == Account::TYPE_CASH && GETPOST('value', 'alpha') != 'LIQ') { setEventMessages($langs->trans("ErrorCashAccountAcceptsOnlyCashMoney"), null, 'errors'); $error++; @@ -228,7 +233,7 @@ if ($user->rights->banque->consolidate && ($action == 'num_releve' || $action == $db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."bank"; - $sql .= " SET num_releve=".($num_rel ? "'".$db->escape($num_rel)."'" : "null"); + $sql .= " SET num_releve = ".($num_rel ? "'".$db->escape($num_rel)."'" : "null"); if (empty($num_rel)) { $sql .= ", rappro = 0"; } else { @@ -302,7 +307,6 @@ if ($result) { print ''; print ''; print ''; - print ''; print dol_get_fiche_head($head, 'bankline', $langs->trans('LineRecord'), 0, 'accountline', 0); @@ -607,11 +611,7 @@ if ($result) { print dol_get_fiche_end(); - if (!$objp->rappro) { - print '

    '; - } else { - print '

    '; - } + print '

    '; print ""; From f28dd2827bbbbddef81e2eead50cad2efd86f8c3 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 10 May 2022 15:41:38 +0200 Subject: [PATCH 429/473] Update Ticket::setProject method signature --- htdocs/ticket/class/ticket.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index d63fa68dbfb..2d517be8ef0 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2020,7 +2020,7 @@ class Ticket extends CommonObject * @param int $projectid Project id to link element to * @return int <0 if KO, >0 if OK */ - public function setProject($projectid) + public function setProject($projectid, $notrigger = 0) { if (!$this->table_element) { dol_syslog(get_class($this)."::setProject was called on objet with property table_element not defined", LOG_ERR); From a10e8c369656795d4ffe700e6ee070235c0cb65d Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 10 May 2022 15:44:41 +0200 Subject: [PATCH 430/473] Remove method Ticket::setProject because method already defined into parent CommonObject --- htdocs/ticket/class/ticket.class.php | 32 ---------------------------- 1 file changed, 32 deletions(-) diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 2d517be8ef0..72ec8625e0e 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2013,38 +2013,6 @@ class Ticket extends CommonObject } } - /** - * Link element with a project - * Override core function because of key name 'fk_project' used for this module - * - * @param int $projectid Project id to link element to - * @return int <0 if KO, >0 if OK - */ - public function setProject($projectid, $notrigger = 0) - { - if (!$this->table_element) { - dol_syslog(get_class($this)."::setProject was called on objet with property table_element not defined", LOG_ERR); - return -1; - } - - $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - if ($projectid) { - $sql .= ' SET fk_project = '.((int) $projectid); - } else { - $sql .= ' SET fk_project = NULL'; - } - $sql .= ' WHERE rowid = '.((int) $this->id); - - dol_syslog(get_class($this)."::setProject sql=".$sql); - if ($this->db->query($sql)) { - $this->fk_project = ((int) $projectid); - return 1; - } else { - dol_print_error($this->db); - return -1; - } - } - /** * Link element with a contract * From fea6771a7a883bbcd64a8e87656ddaec8389ee62 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 15:57:52 +0200 Subject: [PATCH 431/473] Module Partnership is stable --- htdocs/core/modules/modPartnership.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php index f37d7d2403d..8ebbd3029b7 100644 --- a/htdocs/core/modules/modPartnership.class.php +++ b/htdocs/core/modules/modPartnership.class.php @@ -75,7 +75,7 @@ class modPartnership extends DolibarrModules // $this->editor_url = 'https://www.example.com'; // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' - $this->version = 'experimental'; + $this->version = 'dolibarr'; // Url to the file with your last numberversion of this module //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; From c9a0dd327f8e2886329a56421759f119a7d5d09b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 16:04:20 +0200 Subject: [PATCH 432/473] Fix default value --- htdocs/core/lib/company.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 4bf8a0e7219..e98a25ddbee 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -271,7 +271,7 @@ function societe_prepare_head(Societe $object) $h++; } - if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'thirdparty') { + if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'thirdparty') { if (!empty($user->rights->partnership->read)) { $langs->load("partnership"); $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; From 3a5fe5063d4d2514d5c6acccb0b673cb71b5773f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 16:19:00 +0200 Subject: [PATCH 433/473] Debug v16 --- htdocs/adherents/partnership.php | 17 ++++++++++++----- htdocs/core/actions_massactions.inc.php | 6 +++--- htdocs/core/lib/company.lib.php | 2 +- htdocs/core/modules/modPartnership.class.php | 3 +-- htdocs/core/tpl/card_presend.tpl.php | 2 +- htdocs/core/tpl/massactions_pre.tpl.php | 2 +- htdocs/partnership/admin/setup.php | 6 +++--- htdocs/partnership/class/partnership.class.php | 2 +- .../class/partnershiputils.class.php | 4 ++-- htdocs/partnership/partnership_card.php | 2 +- htdocs/partnership/partnership_list.php | 2 +- htdocs/public/partnership/new.php | 4 ++-- htdocs/societe/partnership.php | 6 +++--- 13 files changed, 32 insertions(+), 26 deletions(-) diff --git a/htdocs/adherents/partnership.php b/htdocs/adherents/partnership.php index 160a037c187..a01e7d28ed2 100644 --- a/htdocs/adherents/partnership.php +++ b/htdocs/adherents/partnership.php @@ -85,11 +85,18 @@ $usercanclose = $user->rights->partnership->write; // Used by the include of $upload_dir = $conf->partnership->multidir_output[isset($object->entity) ? $object->entity : 1]; -if ($conf->global->PARTNERSHIP_IS_MANAGED_FOR != 'member') accessforbidden(); -if (empty($conf->partnership->enabled)) accessforbidden(); -if (empty($permissiontoread)) accessforbidden(); -if ($action == 'edit' && empty($permissiontoadd)) accessforbidden(); - +if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') != 'member') { + accessforbidden('Partnership module is not activated for members'); +} +if (empty($conf->partnership->enabled)) { + accessforbidden(); +} +if (empty($permissiontoread)) { + accessforbidden(); +} +if ($action == 'edit' && empty($permissiontoadd)) { + accessforbidden(); +} if (($action == 'update' || $action == 'edit') && $object->status != $object::STATUS_DRAFT) { accessforbidden(); } diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 383684b377a..b94655fbc14 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -90,7 +90,7 @@ if (!$error && $massaction == 'confirm_presend') { if ($objecttmp->element == 'expensereport') { $thirdparty = new User($db); } - if ($objecttmp->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + if ($objecttmp->element == 'partnership' && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $thirdparty = new Adherent($db); } if ($objecttmp->element == 'holiday') { @@ -110,7 +110,7 @@ if (!$error && $massaction == 'confirm_presend') { if ($objecttmp->element == 'expensereport') { $thirdpartyid = $objecttmp->fk_user_author; } - if ($objecttmp->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + if ($objecttmp->element == 'partnership' && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $thirdpartyid = $objecttmp->fk_member; } if ($objecttmp->element == 'holiday') { @@ -264,7 +264,7 @@ if (!$error && $massaction == 'confirm_presend') { $fuser = new User($db); $fuser->fetch($objectobj->fk_user_author); $sendto = $fuser->email; - } elseif ($objectobj->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + } elseif ($objectobj->element == 'partnership' && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $fadherent = new Adherent($db); $fadherent->fetch($objectobj->fk_member); $sendto = $fadherent->email; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 197a6c95687..4938d20c3c4 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -263,7 +263,7 @@ function societe_prepare_head(Societe $object) $h++; } - if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'thirdparty') { + if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'thirdparty') { if (!empty($user->rights->partnership->read)) { $langs->load("partnership"); $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php index 8ebbd3029b7..13877c7418f 100644 --- a/htdocs/core/modules/modPartnership.class.php +++ b/htdocs/core/modules/modPartnership.class.php @@ -177,8 +177,7 @@ class modPartnership extends DolibarrModules // Array to add new pages in new tabs $this->tabs = array(); - $tabtoadd = (!empty(getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR')) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') ? 'member' : 'thirdparty'; - + $tabtoadd = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if ($tabtoadd == 'member') { $fk_mainmenu = "members"; } else { diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 83f96c1bcb1..0c744e165d3 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -152,7 +152,7 @@ if ($action == 'presend') { $fuser = new User($db); $fuser->fetch($object->fk_user_author); $liste['thirdparty'] = $fuser->getFullName($outputlangs)." <".$fuser->email.">"; - } elseif ($object->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + } elseif ($object->element == 'partnership' && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $fadherent = new Adherent($db); $fadherent->fetch($object->fk_member); $liste['member'] = $fadherent->getFullName($outputlangs)." <".$fadherent->email.">"; diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index 207dc1b7265..678bf219bef 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -131,7 +131,7 @@ if ($massaction == 'presend') { $fuser = new User($db); $fuser->fetch($thirdpartyid); $liste['thirdparty'] = $fuser->getFullName($langs)." <".$fuser->email.">"; - } elseif ($objecttmp->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + } elseif ($objecttmp->element == 'partnership' && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $fadherent = new Adherent($db); $fadherent->fetch($objecttmp->fk_member); $liste['member'] = $fadherent->getFullName($langs)." <".$fadherent->email.">"; diff --git a/htdocs/partnership/admin/setup.php b/htdocs/partnership/admin/setup.php index 100dc7027a3..a398a6860b1 100644 --- a/htdocs/partnership/admin/setup.php +++ b/htdocs/partnership/admin/setup.php @@ -124,8 +124,8 @@ print ''; print ''.$langs->trans("PARTNERSHIP_IS_MANAGED_FOR").''; print ''; print ''; print ajax_combobox('select_PARTNERSHIP_IS_MANAGED_FOR'); print ''; @@ -133,7 +133,7 @@ print ''.$langs->trans("partnershipforthirdparty print ''; -//if (!empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { +//if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { print ''.$langs->trans("PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL").''; print ''; $dnbdays = '30'; diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 7d7d6a65d14..030cbf09e79 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -199,7 +199,7 @@ class Partnership extends CommonObject $this->db = $db; - if (!empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + if (!empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { $this->fields['fk_member'] = array('type'=>'integer:Adherent:adherents/class/adherent.class.php:1', 'label'=>'Member', 'enabled'=>'1', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'picto'=>'member', 'csslist'=>'tdoverflowmax150'); } else { $this->fields['fk_soc'] = array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'1', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'picto'=>'company', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150'); diff --git a/htdocs/partnership/class/partnershiputils.class.php b/htdocs/partnership/class/partnershiputils.class.php index ef4f7cfdeb4..9ad2e5b7ca2 100644 --- a/htdocs/partnership/class/partnershiputils.class.php +++ b/htdocs/partnership/class/partnershiputils.class.php @@ -64,7 +64,7 @@ class PartnershipUtils { global $conf, $langs, $user; - $managedfor = empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) ? 'thirdparty' : $conf->global->PARTNERSHIP_IS_MANAGED_FOR; + $managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if ($managedfor != 'member') { return 0; // If option 'PARTNERSHIP_IS_MANAGED_FOR' = 'thirdparty', this cron job does nothing. @@ -219,7 +219,7 @@ class PartnershipUtils { global $conf, $langs, $user; - $managedfor = $conf->global->PARTNERSHIP_IS_MANAGED_FOR; + $managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR'); $partnership = new Partnership($this->db); $MAXPERCALL = (empty($conf->global->PARTNERSHIP_MAX_WARNING_BACKLINK_PER_CALL) ? 10 : $conf->global->PARTNERSHIP_MAX_WARNING_BACKLINK_PER_CALL); // Limit to 10 per call diff --git a/htdocs/partnership/partnership_card.php b/htdocs/partnership/partnership_card.php index c83a83e6357..9752651ef29 100644 --- a/htdocs/partnership/partnership_card.php +++ b/htdocs/partnership/partnership_card.php @@ -79,7 +79,7 @@ $permissiontodelete = $user->rights->partnership->delete || ($permissiontoadd & $permissionnote = $user->rights->partnership->write; // Used by the include of actions_setnotes.inc.php $permissiondellink = $user->rights->partnership->write; // Used by the include of actions_dellink.inc.php $upload_dir = $conf->partnership->multidir_output[isset($object->entity) ? $object->entity : 1]; -$managedfor = empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) ? 'thirdparty' : $conf->global->PARTNERSHIP_IS_MANAGED_FOR; +$managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if (empty($conf->partnership->enabled)) accessforbidden(); if (empty($permissiontoread)) accessforbidden(); diff --git a/htdocs/partnership/partnership_list.php b/htdocs/partnership/partnership_list.php index 42d4354516e..014d576f5d6 100644 --- a/htdocs/partnership/partnership_list.php +++ b/htdocs/partnership/partnership_list.php @@ -74,7 +74,7 @@ $extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); -$managedfor = empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) ? 'thirdparty' : $conf->global->PARTNERSHIP_IS_MANAGED_FOR; +$managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if ($managedfor != 'member' && $sortfield == 'd.datefin') $sortfield = ''; diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index fe57f4ea424..d7ee25613a8 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -204,9 +204,9 @@ if (empty($reshook) && $action == 'add') { $partnership = new Partnership($db); // We try to find the thirdparty or the member - if (empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) || $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'thirdparty') { + if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'thirdparty') { $partnership->fk_member = 0; - } elseif ($conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + } elseif (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'member') { $partnership->fk_soc = 0; } diff --git a/htdocs/societe/partnership.php b/htdocs/societe/partnership.php index 2ce4884932e..05079d263a9 100644 --- a/htdocs/societe/partnership.php +++ b/htdocs/societe/partnership.php @@ -52,7 +52,7 @@ if (!empty($user->socid)) { $socid = $user->socid; } -if (empty($id) && $socid && (empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) || $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'thirdparty')) { +if (empty($id) && $socid && (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'thirdparty')) { $id = $socid; } @@ -94,8 +94,8 @@ $usercanclose = $user->rights->partnership->write; // Used by the include of act $upload_dir = $conf->partnership->multidir_output[isset($object->entity) ? $object->entity : 1]; -if (!empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) && $conf->global->PARTNERSHIP_IS_MANAGED_FOR != 'thirdparty') { - accessforbidden(); +if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') != 'thirdparty') { + accessforbidden('Partnership is not activated for thirdparties'); } if (empty($conf->partnership->enabled)) { accessforbidden(); From 1f59e329cd20eb246497877327deba9c3dbc6e28 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 May 2022 16:50:33 +0200 Subject: [PATCH 434/473] Work on public form for partnership --- htdocs/core/class/html.form.class.php | 4 +- htdocs/langs/en_US/partnership.lang | 16 +++---- htdocs/partnership/admin/website.php | 39 +++++----------- .../partnership/class/partnership.class.php | 2 +- htdocs/partnership/lib/partnership.lib.php | 2 +- htdocs/public/partnership/new.php | 44 +++++++------------ 6 files changed, 41 insertions(+), 66 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0feb7e6519d..b91fb4a243c 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7778,7 +7778,7 @@ class Form * * @param string $htmlname Name of html select area. Must start with "multi" if this is a multiselect * @param array $array Array like array(key => value) or array(key=>array('label'=>..., 'data-...'=>..., 'disabled'=>..., 'css'=>...)) - * @param string|string[] $id Preselected key or preselected keys for multiselect + * @param string|string[] $id Preselected key or preselected keys for multiselect. Use 'ifone' to autoselect record if there is only one record. * @param int|string $show_empty 0 no empty value allowed, 1 or string to add an empty value into list (If 1: key is -1 and value is '' or ' ', If placeholder string: key is -1 and value is the string), <0 to add an empty value with key that is this value. * @param int $key_in_label 1 to show key into label with format "[key] value" * @param int $value_as_key 1 to use value as key @@ -7895,7 +7895,7 @@ class Form } } else { $id = (string) $id; // if $id = 0, then $id = '0' - if ($id != '' && $id == $key && !$disabled) { + if ($id != '' && ($id == $key || ($id == 'ifone' && count($array) == 1)) && !$disabled) { $out .= ' selected'; // To preselect a value } } diff --git a/htdocs/langs/en_US/partnership.lang b/htdocs/langs/en_US/partnership.lang index 9c11e1cda2e..5c85e4d7830 100644 --- a/htdocs/langs/en_US/partnership.lang +++ b/htdocs/langs/en_US/partnership.lang @@ -42,6 +42,7 @@ PARTNERSHIP_BACKLINKS_TO_CHECK=Backlinks to check PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL=Nb of days before cancelling status of a partnership when a subscription has expired ReferingWebsiteCheck=Check of website referring ReferingWebsiteCheckDesc=You can enable a feature to check that your partners has added a backlink to your website domains on their own website. +PublicFormRegistrationPartnerDesc=Dolibarr can provide you a public URL/website to allow external visitors to request to be part of the partnership program. # # Object @@ -60,6 +61,11 @@ ConfirmClosePartnershipAsk=Are you sure you want to cancel this partnership? PartnershipType=Partnership type PartnershipRefApproved=Partnership %s approved KeywordToCheckInWebsite=If you want to check that a given keyword is present into the website of each partner, define this keyword here +PartnershipDraft=Draft +PartnershipAccepted=Accepted +PartnershipRefused=Refused +PartnershipCanceled=Canceled +PartnershipManagedFor=Partners are # # Template Mail @@ -83,12 +89,6 @@ CountLastUrlCheckError=Number of errors for last URL check LastCheckBacklink=Date of last URL check ReasonDeclineOrCancel=Reason for declining or canceling -# -# Status -# -PartnershipDraft=Draft -PartnershipAccepted=Accepted -PartnershipRefused=Refused -PartnershipCanceled=Canceled -PartnershipManagedFor=Partners are +NewPartnershipRequest=New partnership request +NewPartnershipRequestDesc=This form allows you to request to be part of one of our partnership program. If you need help to fill this form, please contact by email %s. diff --git a/htdocs/partnership/admin/website.php b/htdocs/partnership/admin/website.php index 5fb48248280..49fd7ff91df 100644 --- a/htdocs/partnership/admin/website.php +++ b/htdocs/partnership/admin/website.php @@ -78,12 +78,14 @@ if ($action == 'update') { $form = new Form($db); +$title = $langs->trans('PartnershipSetup'); +$help_url = ''; //$help_url = 'EN:Module_Partnership|FR:Module_Adhérents|ES:Módulo_Miembros'; -llxHeader('', $langs->trans("PartnershipsSetup"), $help_url); +llxHeader('', $title, $help_url); $linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("PartnershipsSetup"), $linkback, 'title_setup'); +print load_fiche_titre($title, $linkback, 'title_setup'); $head = partnershipAdminPrepareHead(); @@ -93,7 +95,7 @@ print '
    '; print ''; print ''; -print dol_get_fiche_head($head, 'website', $langs->trans("Partnerships"), -1, 'user'); +print dol_get_fiche_head($head, 'website', $langs->trans("Partnerships"), -1, 'partnership'); if ($conf->use_javascript_ajax) { print "\n".''; + // Lines to produce From 1555a6540b8cfab2494580b0fc22760bdf7c9420 Mon Sep 17 00:00:00 2001 From: atm-lena Date: Wed, 11 May 2022 12:40:51 +0200 Subject: [PATCH 454/473] Translation --- htdocs/mrp/mo_production.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index cbe25d529d9..d6dc4d250d0 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -1068,7 +1068,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print ''; - // traitement entrepot par défaut + // default warehouse processing print ''; + // TODO @LDR for the save button, in action "add", set parent var to return data and close the window + //$retstring .= 'setid '; + //$retstring .= 'setlabel'; + } + return $retstring; } } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 14281e47a69..8776381b922 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1575,36 +1575,70 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = * Such buttons must be included inside a HTML form. * * @param string $name A name for the html component - * @param string $label Label of button + * @param string $label Label shown in Popup title top bar * @param string $buttonstring button string * @param string $url Url to open * @param string $disabled Disabled text + * @param string $morecss More CSS + * @param string $backtopagejsfields The back to page must be managed using javascript instead of a redirect. + * Value is 'Name of html component to set with id:Name of html component to set with label' + * TODO Support this mode, for example when used from the page create a project on thirdparty creation. * @return string HTML component with button */ -function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '') +function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'button bordertransp', $backtopagejsfields = '') { if (strpos($url, '?') > 0) { - $url .= '&dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup=1'; + $url .= '&dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup='.urlencode($name); } else { - $url .= '?dol_hide_menuinpopup=1&dol_hide_leftmenu=1&dol_openinpopup=1'; + $url .= '?dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup='.urlencode($name); + } + + $out .= ''; + + $backtopagejsfieldsid = ''; $backtopagejsfieldslabel = ''; + if ($backtopagejsfields) { + $url .= '&backtopagejsfields='.urlencode($backtopagejsfields); + $tmpbacktopagejsfields = explode(':', $backtopagejsfields); + $backtopagejsfieldsid = empty($tmpbacktopagejsfields[0]) ? '' : $tmpbacktopagejsfields[0]; + $backtopagejsfieldslabel = empty($tmpbacktopagejsfields[1]) ? '' : $tmpbacktopagejsfields[1]; } //print ''; - $out = ''.$buttonstring.''; + $out .= ''."\n"; + $out .= ''.$buttonstring.''; + $out .= ''; + $out .= ''; + $out .= ''; $out .= ''; $out .= ''; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 21218f099fe..4581814f0f8 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1367,11 +1367,11 @@ if (!function_exists("llxHeader")) { print ''."\n"; // top menu and left menu area - if (empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu', 'int')) { + if ((empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu', 'int')) && !GETPOST('dol_openinpopup', 'aZ09')) { top_menu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url); } - if (empty($conf->dol_hide_leftmenu)) { + if (empty($conf->dol_hide_leftmenu) && !GETPOST('dol_openinpopup', 'aZ09')) { left_menu('', $help_url, '', '', 1, $title, 1); // $menumanager is retrieved with a global $menumanager inside this function } diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 6d5c807c3f0..002685415cc 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -87,13 +87,15 @@ $langs->loadLangs(array("mymodule@mymodule", "other")); // Get parameters $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); +$lineid = GETPOST('lineid', 'int'); + $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $cancel = GETPOST('cancel', 'aZ09'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'myobjectcard'; // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); -$lineid = GETPOST('lineid', 'int'); +$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09'); // Initialize technical objects $object = new MyObject($db); diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index c5fc08a6402..6a27472a7e3 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -46,8 +46,11 @@ $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$backtopagejsfields = GETPOST('backtopagejsfields', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $confirm = GETPOST('confirm', 'aZ09'); +$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09'); + $status = GETPOST('status', 'int'); $opp_status = GETPOST('opp_status', 'int'); $opp_percent = price2num(GETPOST('opp_percent', 'alpha')); @@ -505,9 +508,10 @@ if ($action == 'create' && $user->rights->projet->creer) { print load_fiche_titre($titlenew, '', 'project'); print ''; - print ''; print ''; + print ''; print ''; + print ''; print dol_get_fiche_head(); @@ -605,7 +609,7 @@ if ($action == 'create' && $user->rights->projet->creer) { if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) { $filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST; } - $text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx'); + $text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500'); if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile)) { $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty"); print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1); @@ -613,7 +617,12 @@ if ($action == 'create' && $user->rights->projet->creer) { print $text; } if (!GETPOSTISSET('backtopage')) { - print ' '; + $url = '/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create'); + $newbutton = ''; + // TODO @LDR Impletment this + //$tmpbacktopagejsfields = 'socid:search_socid'; + //print dolButtonToOpenUrlInDialogPopup('addthirdparty', $langs->transnoentitiesnoconv('AddThirdParty'), $newbutton, $url, '', '', $tmpbacktopagejsfields); + print ' '.$newbutton.''; } print ''; } diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 154a376cca7..cbb8de3cf28 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -84,7 +84,9 @@ $error = 0; $errors = array(); $action = (GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'); $cancel = GETPOST('cancel', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); +$backtopagejsfields = GETPOST('backtopagejsfields', 'alpha'); $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $socid = GETPOST('socid', 'int') ?GETPOST('socid', 'int') : GETPOST('id', 'int'); @@ -1262,8 +1264,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; // Chrome ignor autocomplete print ''; - print ''; print ''; + print ''; + print ''; print ''; print ''; print ''; @@ -1721,7 +1724,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print dol_get_fiche_end(); - print $form->buttonsSaveCancel("AddThirdParty"); + print $form->buttonsSaveCancel("AddThirdParty", 'Cancel', null, 0, '', $dol_openinpopup); print ''."\n"; } elseif ($action == 'edit') { diff --git a/htdocs/website/index.php b/htdocs/website/index.php index d454ec8f532..02926e2add8 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -68,6 +68,9 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'websitelist'; // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$dol_hide_topmenu = GETPOST('dol_hide_topmenu', 'int'); +$dol_hide_leftmenu = GETPOST('dol_hide_leftmenu', 'int'); +$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09'); $type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha'); @@ -2558,6 +2561,7 @@ print ''."\n"; print '
    '; print ''; print ''; +print ''; if ($action == 'createsite') { print ''; @@ -2638,7 +2642,7 @@ if (!GETPOST('hide_websitemenu')) { //var_dump($objectpage);exit; - print '
    '; + print '
    '; // // Toolbar for websites