From c66695bd56e86f506fa78de2e18cd1f9021e4daf Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 30 May 2017 15:35:51 +0200 Subject: [PATCH 01/40] FIX : origin & originid on supplierproposal --- .../class/supplier_proposal.class.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 572735384e4..aa845169475 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -356,11 +356,13 @@ class SupplierProposal extends CommonObject * @param array $array_option extrafields array * @param string $ref_fourn Supplier price reference * @param int $fk_unit Id of the unit to use. + * @param string $origin 'order', 'supplier_proposal', ... + * @param int $origin_id Id of origin line * @return int >0 if OK, <0 if KO * * @see add_product */ - function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='') + function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='', $origin, $origin_id) { global $mysoc; @@ -462,7 +464,8 @@ class SupplierProposal extends CommonObject $this->line->special_code=$special_code; $this->line->fk_parent_line=$fk_parent_line; $this->line->fk_unit=$fk_unit; - + $this->line->origin=$origin; + $this->line->origin_id=$origin_id; $this->line->ref_fourn = $this->db->escape($ref_fourn); // infos marge @@ -880,7 +883,10 @@ class SupplierProposal extends CommonObject $this->lines[$i]->pa_ht, $this->lines[$i]->label, $this->lines[$i]->array_options, - $this->lines[$i]->ref_fourn + $this->lines[$i]->ref_fourn, + $this->lines[$i]->fk_unit, + 'supplier_proposal', + $this->lines[$i]->rowid ); if ($result < 0) From 6b7c4cbbe198063ee403792e542cbeb6182da0a5 Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 30 May 2017 16:00:21 +0200 Subject: [PATCH 02/40] FIX : default param --- htdocs/supplier_proposal/class/supplier_proposal.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index aa845169475..23c8257a4f5 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -362,7 +362,7 @@ class SupplierProposal extends CommonObject * * @see add_product */ - function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='', $origin, $origin_id) + function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='', $origin='', $origin_id=0) { global $mysoc; From 200f4010d89deb5487364b5ff74c2e396d6e1a55 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Tue, 30 May 2017 16:00:39 +0200 Subject: [PATCH 03/40] Fix special char and size limit in SEPA XML --- 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 f007fa41d21..814bece5bd1 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1574,10 +1574,10 @@ class BonPrelevement extends CommonObject $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; - $XML_DEBITOR .=' '.strtoupper(dol_string_unaccent($row_nom)).''.$CrLf; + $XML_DEBITOR .=' '.strtoupper(dol_string_unaccent(dolEscapeXML($row_nom))).''.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$row_country_code.''.$CrLf; - $XML_DEBITOR .=' '.dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))).''.$CrLf; + $XML_DEBITOR .=' '.dol_trunc(dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))),70,'right','UTF-8',true).''.$CrLf; $XML_DEBITOR .=' '.dol_string_unaccent($row_zip.' '.$row_town).''.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; From 510b1aedcf12d2ce16780bb0fd185bbdbb9cdd68 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Tue, 30 May 2017 16:13:49 +0200 Subject: [PATCH 04/40] Fix xml SEPA $ListOfFactures not used and was listing all invoices in each XML line --- .../prelevement/class/bonprelevement.class.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 814bece5bd1..2bfed9b0696 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1265,18 +1265,6 @@ class BonPrelevement extends CommonObject * section Debiteur (sepa Debiteurs bloc lines) */ - $tmp_invoices = array(); - - $sql = "SELECT f.facnumber as fac FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl, ".MAIN_DB_PREFIX."facture as f, ".MAIN_DB_PREFIX."prelevement_facture as pf, ".MAIN_DB_PREFIX."societe as soc, ".MAIN_DB_PREFIX."c_country as p, ".MAIN_DB_PREFIX."societe_rib as rib WHERE pl.fk_prelevement_bons = ".$this->id." AND pl.rowid = pf.fk_prelevement_lignes AND pf.fk_facture = f.rowid AND soc.fk_pays = p.rowid AND soc.rowid = f.fk_soc AND rib.fk_soc = f.fk_soc AND rib.default_rib = 1"; - $resql=$this->db->query($sql); - if ($resql) { - while ($objfac = $this->db->fetch_object($resql)) { - $tmp_invoices[] = $objfac->fac; - } - } - - $ListOfFactures = implode($tmp_invoices); - $sql = "SELECT soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; $sql.= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; $sql.= " f.facnumber as fac, pf.fk_facture as idfac, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum"; @@ -1303,7 +1291,7 @@ class BonPrelevement extends CommonObject while ($i < $num) { $obj = $this->db->fetch_object($resql); - $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $ListOfFactures, $obj->idfac, $obj->iban, $obj->bic, $this->db->jdate($obj->datec), $obj->drum); + $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->fac, $obj->idfac, $obj->iban, $obj->bic, $this->db->jdate($obj->datec), $obj->drum); $this->total = $this->total + $obj->somme; $i++; } From 7139a2dd9d420c9f4dec6179edd40e045f190276 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 31 May 2017 13:09:25 +0200 Subject: [PATCH 05/40] Update debian package --- build/debian/source/lintian-overrides | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/build/debian/source/lintian-overrides b/build/debian/source/lintian-overrides index b4c0956e90f..c878035b482 100644 --- a/build/debian/source/lintian-overrides +++ b/build/debian/source/lintian-overrides @@ -4,7 +4,12 @@ dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/* dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jstz/* # Those are false positives, the files are their own sources since # they are not minified -source-is-missing htdocs/includes/jsgantt/jsgantt.js * -source-is-missing htdocs/includes/jquery/plugins/colorpicker/jquery.colorpicker.js * -source-is-missing htdocs/includes/jquery/plugins/select2/select2.js * -source-is-missing htdocs/includes/jquery/plugins/select2/select2_locale_ar.js * +source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/a11yhelp/dialogs/lang/*.js +source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/specialchar/dialogs/lang/*.js +source-is-missing htdocs/includes/ckeditor/ckeditor/lang/*.js +source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/*/dialogs/*.js +source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/*/filter/*.js +source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/templates/templates/default.js +source-is-missing htdocs/includes/mobiledetect/mobiledetectlib/Mobile_Detect.json +source-is-missing htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/*.js + From 82ddf293b622c543e4e9740b775a23358008ab93 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 31 May 2017 13:29:31 +0200 Subject: [PATCH 06/40] Prepare 5.0.3 --- ChangeLog | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ChangeLog b/ChangeLog index 57824562787..78793b9d419 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,26 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 5.0.3 compared to 5.0.2 ***** +FIX: #6677 Expired contracts dashboard box does not show the name of the thirdparty +FIX: #6813 +FIX: 6863 +FIX: #6877 +FIX: #6881 +FIX: Better sanitizing of search all parameter. +FIX: Correction with author and validator user on orders +FIX: dialog window with md theme must not be hidden by left menu part. +FIX: doactions hook missing in invoice model page +FIX: Fullname when member is a moral entity with no name. +FIX: Link to files on bank account tab broken with multicompany FIX: Link to preview on thirdparty broken with multicompany +FIX: New vat code not correctly implemented if "1 price per customer". +FIX: Pagination of invoices +FIX: pagination on resources +FIX: REST API not possible to add agendaevents +FIX: situation invoice broken due to the all percent application form inside addline form +FIX: SQL injection on user/index.php parameter search_statut. +FIX: XSS + ***** ChangeLog for 5.0.2 compared to 5.0.1 ***** FIX: #6468 + Fix missing translation FIX: #6517 #6525 Autocompletion of thirdparty after n chars not implemented From 7c29e286f82f2ca3d3a77a6b67d0534067bad6b0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 31 May 2017 13:31:17 +0200 Subject: [PATCH 07/40] Prepare 4.0.7 --- htdocs/filefunc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index d2ca04278ff..13349d3c1da 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -31,7 +31,7 @@ */ if (! defined('DOL_APPLICATION_TITLE')) define('DOL_APPLICATION_TITLE','Dolibarr'); -if (! defined('DOL_VERSION')) define('DOL_VERSION','4.0.6'); +if (! defined('DOL_VERSION')) define('DOL_VERSION','4.0.7'); if (! defined('EURO')) define('EURO',chr(128)); From d70c14a411f520714656f2d5ca8c0a64d300742c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 31 May 2017 19:07:39 +0200 Subject: [PATCH 08/40] Update bonprelevement.class.php --- 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 2bfed9b0696..dd6b773af9f 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1562,11 +1562,11 @@ class BonPrelevement extends CommonObject $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; - $XML_DEBITOR .=' '.strtoupper(dol_string_unaccent(dolEscapeXML($row_nom))).''.$CrLf; + $XML_DEBITOR .=' '.strtoupper(dolEscapeXML(dol_string_unaccent($row_nom))).''.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$row_country_code.''.$CrLf; $XML_DEBITOR .=' '.dol_trunc(dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))),70,'right','UTF-8',true).''.$CrLf; - $XML_DEBITOR .=' '.dol_string_unaccent($row_zip.' '.$row_town).''.$CrLf; + $XML_DEBITOR .=' '.dolEscapeXML(dol_string_unaccent($row_zip.' '.$row_town)).''.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; $XML_DEBITOR .=' '.$CrLf; From fa3cd267f48f98cd4312e90c5779849fd1bbe60a Mon Sep 17 00:00:00 2001 From: Inovea Conseil Date: Thu, 1 Jun 2017 10:51:30 +0200 Subject: [PATCH 09/40] Fix bug of prepare_head of card Delete the call of commande_prepare_head function because do not use in skeleton --- dev/skeletons/skeleton_card.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dev/skeletons/skeleton_card.php b/dev/skeletons/skeleton_card.php index f0a9dd23c26..8c487dee776 100644 --- a/dev/skeletons/skeleton_card.php +++ b/dev/skeletons/skeleton_card.php @@ -297,9 +297,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea { $res = $object->fetch_optionals($object->id, $extralabels); - $head = commande_prepare_head($object); - dol_fiche_head($head, 'order', $langs->trans("CustomerOrder"), 0, 'order'); - + print load_fiche_titre($langs->trans("MyModule")); dol_fiche_head(); From 40dd6fc61c0a08118d2d5b1914a2a17c8a44a0d5 Mon Sep 17 00:00:00 2001 From: Inovea Conseil Date: Thu, 1 Jun 2017 11:22:08 +0200 Subject: [PATCH 10/40] Fix bug to display value Fix bug to display the values in the future card.php --- dev/skeletons/build_class_from_table.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/skeletons/build_class_from_table.php b/dev/skeletons/build_class_from_table.php index 537975365ef..532da3131a6 100755 --- a/dev/skeletons/build_class_from_table.php +++ b/dev/skeletons/build_class_from_table.php @@ -1,6 +1,7 @@ #!/usr/bin/env php + * Copyright (C) 2017 Nicolas ZABOURI * * 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 @@ -649,7 +650,7 @@ foreach ($skeletonfiles as $skeletonfile => $outfile) { if ($prop['field'] != 'rowid' && $prop['field'] != 'id' && ! $prop['istime']) { - $varprop.="print ''.\$langs->trans(\"Field".$prop['field']."\").'\$object->".$prop['field']."';\n"; + $varprop.="print ''.\$langs->trans(\"Field".$prop['field']."\").''.\$object->".$prop['field'].".'';\n"; } } $targetcontent=preg_replace('/LIST_OF_TD_LABEL_FIELDS_VIEW/', $varprop, $targetcontent); From 77df19009db350893462e42caaad9bad2c50924e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 1 Jun 2017 12:11:45 +0200 Subject: [PATCH 11/40] Removed duplicated code --- htdocs/admin/agenda_other.php | 57 +++---- htdocs/admin/barcode.php | 36 +--- htdocs/admin/commande.php | 31 +--- htdocs/admin/contract.php | 31 +--- htdocs/admin/expedition.php | 32 +--- htdocs/admin/expensereport.php | 32 +--- htdocs/admin/facture.php | 27 +-- htdocs/admin/fichinter.php | 32 +--- htdocs/admin/livraison.php | 32 +--- htdocs/admin/propal.php | 32 +--- htdocs/admin/supplier_payment.php | 35 +--- htdocs/admin/supplier_proposal.php | 36 +--- htdocs/admin/user.php | 32 +--- htdocs/admin/usergroup.php | 32 +--- htdocs/core/actions_setmoduleoptions.inc.php | 86 ++++++++++ htdocs/core/lib/files.lib.php | 160 +++++++++--------- .../doc/doc_generic_contract_odt.modules.php | 41 +---- htdocs/langs/en_US/admin.lang | 2 + htdocs/modulebuilder/template/admin/setup.php | 9 +- htdocs/product/admin/product.php | 45 +---- htdocs/projet/admin/project.php | 39 +---- htdocs/societe/admin/societe.php | 32 +--- 22 files changed, 265 insertions(+), 626 deletions(-) create mode 100644 htdocs/core/actions_setmoduleoptions.inc.php diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index bd9587a4440..44ec3ade889 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -49,6 +49,8 @@ $type = 'action'; * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if (preg_match('/set_(.*)/',$action,$reg)) { $code=$reg[1]; @@ -77,21 +79,6 @@ if (preg_match('/del_(.*)/',$action,$reg)) dol_print_error($db); } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - if (! $error) - { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} if ($action == 'set') { dolibarr_set_const($db, 'AGENDA_USE_EVENT_TYPE_DEFAULT', GETPOST('AGENDA_USE_EVENT_TYPE_DEFAULT'), 'chaine', 0, '', $conf->entity); @@ -233,7 +220,7 @@ else if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { print load_fiche_titre($langs->trans("AgendaModelModule"),'',''); - + print ''."\n"; print ''."\n"; print ''."\n"; @@ -243,13 +230,13 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print ''; print ''; print ''."\n"; - + clearstatcache(); - + foreach ($dirmodels as $reldir) { $dir = dol_buildpath($reldir."core/modules/action/doc/"); - + if (is_dir($dir)) { $handle=opendir($dir); @@ -261,10 +248,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { $name = substr($file, 4, dol_strlen($file) -16); $classname = substr($file, 0, dol_strlen($file) -12); - + require_once $dir.'/'.$file; - $module = new $classname($db, new ActionComm($db)); - + $module = new $classname($db, new ActionComm($db)); + print ''."\n"; print "\n"; - + // Active if (in_array($name, $def)) { - + print '"; } - + // Default print ''; - + // Info $htmltooltip = ''.$langs->trans("Name").': '.$module->name; $htmltooltip.='
'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown")); @@ -326,7 +313,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print ''; - + print "\n"; } } @@ -366,7 +353,7 @@ print ''."\n"; if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - + print ''; print ''."\n"; print ''."\n"; @@ -404,30 +391,30 @@ print ''."\n"; // AGENDA NOTIFICATION if ($conf->global->MAIN_FEATURES_LEVEL > 0) { - + print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; } else { print ''.img_picto($langs->trans('Enabled'),'switch_on').''; print ''."\n"; - + print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; } } diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index db81c9a325f..ba649fe9223 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -39,6 +39,8 @@ $action = GETPOST('action','alpha'); * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'setbarcodeproducton') { $res=dolibarr_set_const($db, "BARCODE_PRODUCT_ADDON_NUM", GETPOST('value'), 'chaine', 0, '', $conf->entity); @@ -72,33 +74,7 @@ else if ($action == 'update') else if ($action == 'updateengine') { // TODO Update engines. - -} -// define constants for models generator that need parameters -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - } - } - if (! $res > 0) $error++; - - if (! $error) - { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - setEventMessages($langs->trans("Error"), null, 'errors'); - } } if ($action && $action != 'setcoder' && $action != 'setModuleOptions') @@ -276,7 +252,7 @@ if ($resql) print '\n"; - + $i++; } } @@ -312,7 +288,7 @@ print ''; // Chemin du binaire genbarcode sous linux if (! isset($_SERVER['WINDIR'])) { - + print ''; print ''; print ''; print ''; print ''; print ''; print '\n"; print "'; $texte.= '
'.$langs->trans("Name").''.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
"; print (empty($module->name)?$name:$module->name); @@ -272,16 +259,16 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print "\n"; require_once $dir.$file; $module = new $classname($db,$specimenthirdparty); - if (method_exists($module,'info')) + if (method_exists($module,'info')) print $module->info($langs); - else + else print $module->description; print "'."\n"; if ($conf->global->ACTION_EVENT_ADDON_PDF != "$name") { @@ -301,7 +288,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print 'scandir.'&label='.urlencode($module->name).'&type=action">'.img_picto($langs->trans("Disabled"),'switch_off').''; print "'; if ($conf->global->ACTION_EVENT_ADDON_PDF == "$name") @@ -313,7 +300,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print 'scandir.'&label='.urlencode($module->name).'&type=action"" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; } print ''; print ''.img_object($langs->trans("Preview"),'order').''; print '
'.$langs->trans("AGENDA_USE_EVENT_TYPE_DEFAULT").'
'.$langs->trans('AGENDA_NOTIFICATION').' '."\n"; - + if (empty($conf->global->AGENDA_NOTIFICATION)) { print ''.img_picto($langs->trans('Disabled'),'switch_off').''; print '
'.$langs->trans('AGENDA_NOTIFICATION_SOUND').' '."\n"; - + if (empty($conf->global->AGENDA_NOTIFICATION_SOUND)) { print ''.img_picto($langs->trans('Disabled'),'switch_off').''; } else { print ''.img_picto($langs->trans('Enabled'),'switch_on').''; } - + print '
'; print $formbarcode->setBarcodeEncoder($obj->coder,$barcodelist,$obj->rowid,'form'.$i); print "
'.$langs->trans("GenbarcodeLocation").''; @@ -328,7 +304,7 @@ if (! isset($_SERVER['WINDIR'])) // Module products if (! empty($conf->product->enabled)) { - + print '
'.$langs->trans("SetDefaultBarcodeTypeProducts").''; @@ -339,7 +315,7 @@ if (! empty($conf->product->enabled)) // Module thirdparty if (! empty($conf->societe->enabled)) { - + print '
'.$langs->trans("SetDefaultBarcodeTypeThirdParties").''; diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 6d92ad21999..3f3c997b0d8 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -54,6 +54,8 @@ $type = 'order'; * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconstorder=GETPOST('maskconstorder','alpha'); @@ -118,35 +120,6 @@ else if ($action == 'specimen') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index 47e53a05048..206d9020022 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -50,6 +50,8 @@ if (empty($conf->global->CONTRACT_ADDON)) * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconst = GETPOST('maskconstcontract','alpha'); @@ -113,35 +115,6 @@ else if ($action == 'specimen') // For contract } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php index e9a9aaedb18..6182538f820 100644 --- a/htdocs/admin/expedition.php +++ b/htdocs/admin/expedition.php @@ -57,6 +57,9 @@ if (empty($conf->global->EXPEDITION_ADDON_NUMBER)) /* * Actions */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconst=GETPOST('maskconstexpedition','alpha'); @@ -142,35 +145,6 @@ else if ($action == 'specimen') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -else if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php index 92ba9375927..6c659181c4c 100644 --- a/htdocs/admin/expensereport.php +++ b/htdocs/admin/expensereport.php @@ -51,6 +51,9 @@ $type='expensereport'; /* * Actions */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconst=GETPOST('maskconst','alpha'); @@ -116,35 +119,6 @@ else if ($action == 'specimen') // For fiche inter } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index 64ae1abdde6..115a685a3f2 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -51,6 +51,8 @@ $type='invoice'; * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconstinvoice=GETPOST('maskconstinvoice','alpha'); @@ -123,31 +125,6 @@ if ($action == 'specimen') } } -// define constants for models generator that need parameters -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - } - } - if (! $res > 0) $error++; - - if (! $error) - { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/fichinter.php b/htdocs/admin/fichinter.php index e3000231c38..25c46164783 100644 --- a/htdocs/admin/fichinter.php +++ b/htdocs/admin/fichinter.php @@ -51,6 +51,9 @@ $type='ficheinter'; /* * Actions */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconst=GETPOST('maskconst','alpha'); @@ -114,35 +117,6 @@ else if ($action == 'specimen') // For fiche inter } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { diff --git a/htdocs/admin/livraison.php b/htdocs/admin/livraison.php index cf97b397e44..ef73ec7a757 100644 --- a/htdocs/admin/livraison.php +++ b/htdocs/admin/livraison.php @@ -47,10 +47,13 @@ $label = GETPOST('label','alpha'); $scandir = GETPOST('scandir','alpha'); $type='delivery'; + /* * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconstdelivery=GETPOST('maskconstdelivery','alpha'); @@ -131,35 +134,6 @@ if ($action == 'specimen') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - if ($action == 'set') { $ret = addDocumentModel($value, $type, $label, $scandir); diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php index e0dc1d3b5b4..9fa8dad0c0c 100644 --- a/htdocs/admin/propal.php +++ b/htdocs/admin/propal.php @@ -49,6 +49,9 @@ $type='propal'; /* * Actions */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + $error=0; if ($action == 'updateMask') { @@ -180,35 +183,6 @@ if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model if ($action == 'set') { diff --git a/htdocs/admin/supplier_payment.php b/htdocs/admin/supplier_payment.php index adaa114b1ca..4227f4d4221 100644 --- a/htdocs/admin/supplier_payment.php +++ b/htdocs/admin/supplier_payment.php @@ -47,6 +47,8 @@ $type='supplier_payment'; * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconstsupplierpayment=GETPOST('maskconstsupplierpayment','alpha'); @@ -68,31 +70,6 @@ if ($action == 'updateMask') dolibarr_set_const($db, "SUPPLIER_PAYMENT_ADDON", $value, 'chaine', 0, '', $conf->entity); } -// define constants for models generator that need parameters -else if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - } - } - if (! $res > 0) $error++; - - if (! $error) - { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { @@ -195,7 +172,7 @@ dol_fiche_head($head, 'supplierpayment', $langs->trans("Suppliers"), -1, 'compan */ if (empty($conf->global->SUPPLIER_PAYMENT_ADDON)) $conf->global->SUPPLIER_PAYMENT_ADDON = 'mod_supplier_payment_bronan'; - + print load_fiche_titre($langs->trans("PaymentsNumberingModule"), '', ''); // Load array def with activated templates @@ -265,7 +242,7 @@ foreach ($dirmodels as $reldir) require_once $dir.$filebis; $module = new $classname($db); - + // Show modules according to features level if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue; if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue; @@ -375,7 +352,7 @@ foreach ($dirmodels as $reldir) { while (($file = readdir($handle))!==false) { - if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file)) + if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file)) { $name = substr($file, 4, dol_strlen($file) -16); $classname = substr($file, 0, dol_strlen($file) -12); @@ -383,7 +360,7 @@ foreach ($dirmodels as $reldir) require_once $dir.'/'.$file; $module = new $classname($db, new PaiementFourn($db)); - + print "
"; print (empty($module->name)?$name:$module->name); diff --git a/htdocs/admin/supplier_proposal.php b/htdocs/admin/supplier_proposal.php index 82eeddd594c..210d601c33c 100644 --- a/htdocs/admin/supplier_proposal.php +++ b/htdocs/admin/supplier_proposal.php @@ -41,10 +41,15 @@ $label = GETPOST('label','alpha'); $scandir = GETPOST('scandir','alpha'); $type='supplier_proposal'; +$error=0; + + /* * Actions */ -$error=0; + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'updateMask') { $maskconstsupplier_proposal=GETPOST('maskconstsupplier_proposal','alpha'); @@ -159,35 +164,6 @@ if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_PROPOSAL') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model if ($action == 'set') { diff --git a/htdocs/admin/user.php b/htdocs/admin/user.php index 0c7574b7ec4..31efcb22474 100644 --- a/htdocs/admin/user.php +++ b/htdocs/admin/user.php @@ -47,37 +47,9 @@ $type='user'; * Action */ -// Activate a model +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} -elseif ($action == 'set_default') +if ($action == 'set_default') { $ret = addDocumentModel($value, $type, $label, $scandir); $res = true; diff --git a/htdocs/admin/usergroup.php b/htdocs/admin/usergroup.php index 4642e6d3183..8d098ee6923 100644 --- a/htdocs/admin/usergroup.php +++ b/htdocs/admin/usergroup.php @@ -47,37 +47,9 @@ $type='group'; * Action */ -// Activate a model +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} -elseif ($action == 'set_default') +if ($action == 'set_default') { $ret = addDocumentModel($value, $type, $label, $scandir); $res = true; diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php new file mode 100644 index 00000000000..03b33b19eb1 --- /dev/null +++ b/htdocs/core/actions_setmoduleoptions.inc.php @@ -0,0 +1,86 @@ + + * + * 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 . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/actions_setnotes.inc.php + * \brief Code for actions on setting notes of object page + */ + + +// $action must be defined +// $_FILES may be defined +// $nomessageinsetmoduleoptions can be set to 1 + +// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) +if ($action == 'setModuleOptions') +{ + $db->begin(); + + // Process common param fields + foreach($_POST as $key => $val) + { + if (preg_match('/^param(\d*)$/', $key, $reg)) // Works for POST['param'], POST['param1'], POST['param2'], ... + { + $param=GETPOST("param".$reg[1],'alpha'); + $value=GETPOST("value".$reg[1],'alpha'); + if ($param) + { + $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + } + } + } + + // Process upload fields + if (GETPOST('upload','alpha') && GETPOST('keyforuploaddir','aZ09')) + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $keyforuploaddir=GETPOST('keyforuploaddir','aZ09'); + $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->$keyforuploaddir))); + foreach($listofdir as $key=>$tmpdir) + { + $tmpdir=trim($tmpdir); + $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); + if (! $tmpdir) { + unset($listofdir[$key]); continue; + } + if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0); + else + { + $upload_dir=$tmpdir; + } + } + if ($upload_dir) + { + $result = dol_add_file_process($upload_dir, 0, 1, 'uploadfile', ''); + if ($result <= 0) $error++; + } + } + + if (! $error) + { + $db->commit(); + if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } + else + { + $db->rollback(); + if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupNotSaved"), null, 'errors'); + } +} + diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 95fca68aa5d..85aace9db0b 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -44,7 +44,7 @@ function dol_basename($pathfile) * @param string $path Starting path from which to search. This is a full path. * @param string $types Can be "directories", "files", or "all" * @param int $recursive Determines whether subdirectories are searched - * @param string $filter Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function, + * @param string $filter Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function, * but must not contains the start and end '/'. Filter is checked into basename only. * @param array $excludefilter Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.')). Exclude is checked into fullpath. * @param string $sortcriteria Sort criteria ("","fullname","name","date","size") @@ -71,9 +71,9 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil $reshook = 0; $file_list = array(); - + $hookmanager->resArray=array(); - + if (! $nohook) { $hookmanager->initHooks(array('fileslib')); @@ -196,9 +196,9 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil } } } - + $file_list = array_merge($file_list, $hookmanager->resArray); - + return $file_list; } @@ -219,7 +219,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0) { global $conf, $db; - + $sql=" SELECT rowid, label, entity, filename, filepath, fullpath_orig, keywords, cover, gen_or_uploaded, extraparams, date_c, date_m, fk_user_c, fk_user_m, acl, position"; if ($mode) $sql.=", description"; $sql.=" FROM ".MAIN_DB_PREFIX."ecm_files"; @@ -234,7 +234,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc $i = 0; while ($i < $num) { - $obj = $db->fetch_object($resql); + $obj = $db->fetch_object($resql); if ($obj) { preg_match('/([^\/]+)\/[^\/]+$/',DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,$reg); @@ -258,7 +258,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc } $i++; } - + // Obtain a list of columns if (! empty($sortcriteria)) { @@ -270,7 +270,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc // Sort the data if ($sortorder) array_multisort($myarray, $sortorder, $file_list); } - + return $file_list; } else @@ -279,7 +279,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc return array(); } } - + /** * Fast compare of 2 files identified by their properties ->name, ->date and ->size @@ -460,10 +460,10 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, if (empty($srcfile)) return -1; if (empty($destfile)) $destfile=$srcfile; - + $destexists=dol_is_file($destfile); if (($destfile != $srcfile) && $destexists) return 0; - + $tmpdestfile=$destfile.'.tmp'; $newpathofsrcfile=dol_osencode($srcfile); @@ -481,17 +481,17 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING); return -2; } - + dol_delete_file($tmpdestfile); - + // Create $newpathoftmpdestfile from $newpathofsrcfile $content=file_get_contents($newpathofsrcfile, 'r'); - + $content = make_substitutions($content, $arrayreplacement, null); - + file_put_contents($newpathoftmpdestfile, $content); @chmod($newpathoftmpdestfile, octdec($newmask)); - + // Rename $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0), 0, $indexdatabase); if (! $result) @@ -589,7 +589,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep $destexists=dol_is_dir($destfile); //if (! $overwriteifexists && $destexists) return 0; // The overwriteifexists is for files only, so propagated to dol_copy only. - + if (! $destexists) { // We must set mask just before creating dir, becaause it can be set differently by dol_copy @@ -599,7 +599,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files dol_mkdir($destfile, '', decoct($dirmaskdec)); } - + $ossrcfile=dol_osencode($srcfile); $osdestfile=dol_osencode($destfile); @@ -639,7 +639,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep $result=$tmpresult; } if ($result < 0) break; - + } } closedir($dir_handle); @@ -656,10 +656,10 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep /** * Move a file into another name. - * Note: + * Note: * - This function differs from dol_move_uploaded_file, because it can be called in any context. * - Database of files is updated. - * - Test on antivirus is done only if param testvirus is provided and an antivirus was set. + * - Test on antivirus is done only if param testvirus is provided and an antivirus was set. * * @param string $srcfile Source file (can't be a directory. use native php @rename() to move a directory) * @param string $destfile Destination file (can't be a directory. use native php @rename() to move a directory) @@ -679,12 +679,12 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi $srcexists=dol_is_file($srcfile); $destexists=dol_is_file($destfile); - if (! $srcexists) + if (! $srcexists) { dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request."); return false; } - + if ($overwriteifexists || ! $destexists) { $newpathofsrcfile=dol_osencode($srcfile); @@ -695,7 +695,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi if ($testvirus) { $testvirusarray=dolCheckVirus($newpathofsrcfile); - if (count($testvirusarray)) + if (count($testvirusarray)) { dol_syslog("files.lib.php::dol_move canceled because a virus was found into source file. we ignore the move request.", LOG_WARNING); return false; @@ -729,14 +729,14 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG); include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; - + $ecmfiletarget=new EcmFiles($db); $resultecmtarget = $ecmfiletarget->fetch(0, '', $rel_filetorenameafter); if ($resultecmtarget > 0) // An entry for target name already exists for target, we delete it, a new one will be created. { $ecmfiletarget->delete($user); } - + $ecmfile=new EcmFiles($db); $resultecm = $ecmfile->fetch(0, '', $rel_filetorenamebefore); if ($resultecm > 0) // If an entry was found for src file, we use it to move entry @@ -745,7 +745,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi $rel_dir = dirname($rel_filetorenameafter); $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); - + $ecmfile->filepath = $rel_dir; $ecmfile->filename = $filename; $resultecm = $ecmfile->update($user); @@ -756,7 +756,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi $rel_dir = dirname($rel_filetorenameafter); $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); - + $ecmfile->filepath = $rel_dir; $ecmfile->filename = $filename; $ecmfile->label = md5_file(dol_osencode($destfile)); // $destfile is a full path to file @@ -774,12 +774,12 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi { setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); } - + if ($resultecm > 0) $result=true; else $result = false; - } + } } - + if (empty($newmask)) $newmask=empty($conf->global->MAIN_UMASK)?'0755':$conf->global->MAIN_UMASK; $newmaskdec=octdec($newmask); // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too) @@ -809,14 +809,14 @@ function dol_unescapefile($filename) /** * Check virus into a file - * + * * @param string $src_file Source file to check * @return array Array of errors or empty array if not virus found */ function dolCheckVirus($src_file) { global $conf; - + if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { if (! class_exists('AntiVir')) { @@ -837,10 +837,10 @@ function dolCheckVirus($src_file) /** * Make control on an uploaded file from an GUI page and move it to final destination. * If there is errors (virus found, antivir in error, bad filename), file is not moved. - * Note: + * Note: * - This function can be used only into a HTML page context. Use dol_move if you are outside. - * - Database of files is not updated. * - Test on antivirus is always done (if antivirus set). + * - Database of files is NOT updated. * * @param string $src_file Source full path filename ($_FILES['field']['tmp_name']) * @param string $dest_file Target full path filename ($_FILES['field']['name']) @@ -867,7 +867,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable $parameters=array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite); $reshook=$hookmanager->executeHooks('moveUploadedFile', $parameters, $object); } - + if (empty($reshook)) { // If an upload error has been reported @@ -897,7 +897,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable break; } } - + // If we need to make a virus scan if (empty($disablevirusscan) && file_exists($src_file)) { @@ -908,7 +908,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable return 'ErrorFileIsInfectedWithAVirus: '.join(',',$checkvirusarray); } } - + // Security: // Disallow file with some extensions. We renamed them. // Car si on a mis le rep documents dans un rep de la racine web (pas bien), cela permet d'executer du code a la demande. @@ -916,7 +916,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable { $file_name.= '.noexe'; } - + // Security: // We refuse cache files/dirs, upload using .. and pipes into filenames. if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file)) @@ -924,7 +924,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING); return -1; } - + // Security: // On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers. if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file)) @@ -933,7 +933,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable return -2; } } - + if ($reshook < 0) // At least one blocking error returned by one hook { $errmsg = join(',', $hookmanager->errors); @@ -1005,7 +1005,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n dol_syslog("Refused to delete file ".$file, LOG_WARNING); return False; } - + if (empty($nohook)) { $hookmanager->initHooks(array('fileslib')); @@ -1042,16 +1042,16 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n { if ($nophperrors) $ok=@unlink($filename); else $ok=unlink($filename); - if ($ok) + if ($ok) { dol_syslog("Removed file ".$filename, LOG_DEBUG); - + // Delete entry into ecm database $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename); if (! preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete)) // If not a tmp file { $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete); - + dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG); include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; $ecmfile=new EcmFiles($db); @@ -1079,7 +1079,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n if ($nophperrors) $ok=@unlink($file_osencoded); else $ok=unlink($file_osencoded); if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG); - else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING); + else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING); } return $ok; @@ -1104,7 +1104,7 @@ function dol_delete_dir($dir,$nophperrors=0) dol_syslog("Refused to delete dir ".$dir, LOG_WARNING); return False; } - + $dir_osencoded=dol_osencode($dir); return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded)); } @@ -1340,7 +1340,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio global $db,$user,$conf,$langs; $res = 0; - + if (! empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error'] { dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG); @@ -1354,17 +1354,17 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $val = array($val); } } - + $nbfile = count($TFile['name']); - + for ($i = 0; $i < $nbfile; $i++) { // Define $destfull (path to file including filename) and $destfile (only filename) $destfull=$upload_dir . "/" . $TFile['name'][$i]; $destfile=$TFile['name'][$i]; - + $savingdocmask = dol_sanitizeFileName($savingdocmask); - + if ($savingdocmask) { $destfull=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask); @@ -1378,26 +1378,26 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $destfile = $info['filename'].'.'.strtolower($info['extension']); $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles); - + if (is_numeric($resupload) && $resupload > 0) // $resupload can be 'ErrorFileAlreadyExists' { global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini; - + include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; - + // Generate thumbs. if (image_format_supported($destfull) == 1) { // Create thumbs // We can't use $object->addThumbs here because there is no $object known - + // Used on logon for example $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); // Create mini thumbs for image (Ratio is near 16/9) // Used on menu or for setup page for example $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); } - + // Update session if (empty($donotupdatesession)) { @@ -1406,18 +1406,18 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $formmail->trackid = $trackid; $formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]); } - + // Update table of files - if ($donotupdatesession) + if ($donotupdatesession) { $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir); - + if (! preg_match('/[\\/]temp[\\/]/', $rel_dir)) // If not a tmp dir { $filename = basename($destfile); $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); - + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; $ecmfile=new EcmFiles($db); $ecmfile->filepath = $rel_dir; @@ -1455,7 +1455,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio } } } - + } } elseif ($link) { require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; @@ -1478,7 +1478,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $langs->load("errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("File")), null, 'errors'); } - + return $res; } @@ -1718,11 +1718,11 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip") if (class_exists('ZipArchive')) { $foundhandler=1; - + // Initialize archive object $zip = new ZipArchive(); $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE); - + // Create recursive directory iterator /** @var SplFileInfo[] $files */ $files = new RecursiveIteratorIterator( @@ -1738,15 +1738,15 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip") // Get real and relative path for current file $filePath = $file->getRealPath(); $relativePath = substr($filePath, strlen($inputdir) + 1); - + // Add current file to archive $zip->addFile($filePath, $relativePath); } } - + // Zip archive will be created only after closing object - $zip->close(); - + $zip->close(); + return 1; } } @@ -1793,7 +1793,7 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta * @param string $entity Restrict onto entity (0=no restriction) * @param User $fuser User object (forced) * @param string $refname Ref of object to check permission for external users (autodetect if not provided) - * @param string $mode Check permission for 'read' or 'write' + * @param string $mode Check permission for 'read' or 'write' * @return mixed Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name) * @see restrictedArea */ @@ -1801,7 +1801,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, { global $user, $conf, $db; global $dolibarr_main_data_root; - + if (! is_object($fuser)) $fuser=$user; if (empty($modulepart)) return 'ErrorBadParameter'; @@ -1823,7 +1823,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, { $lire='creer'; $read='write'; $download='upload'; } - + // Wrapping for some images if (($modulepart == 'mycompany' || $modulepart == 'companylogo') && !empty($conf->mycompany->dir_output)) { @@ -2022,7 +2022,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file=$conf->user->dir_output.'/'.$original_file; } - + // Wrapping for third parties else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output)) { @@ -2119,7 +2119,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file=$conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } - + // Wrapping for interventions else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output)) { @@ -2185,7 +2185,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } // Wrapping pour les commandes fournisseurs - else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) + else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) { if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file)) { @@ -2317,7 +2317,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file=$conf->resource->dir_output.'/'.$original_file; } - + // Wrapping pour les remises de cheques else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output)) { @@ -2361,14 +2361,14 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $accessallowed=1; $original_file=$conf->fckeditor->dir_output.'/'.$original_file; } - + // Wrapping for miscellaneous medias files elseif ($modulepart == 'medias' && !empty($dolibarr_main_data_root)) { $accessallowed=1; $original_file=$dolibarr_main_data_root.'/medias/'.$original_file; } - + // Wrapping for backups else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output)) { @@ -2416,7 +2416,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, // If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart else { - if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path. + if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path. if ($fuser->admin) $accessallowed=1; // If user is admin // Define $accessallowed diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index a58d00455e8..64d0da9b5fd 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -102,16 +102,10 @@ class doc_generic_contract_odt extends ModelePDFContract $form = new Form($this->db); $texte = $this->description.".
\n"; - $texte.= '
'; + $texte.= ''; $texte.= ''; $texte.= ''; $texte.= ''; - if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0) - { - $texte.= ''; - $texte.= ''; - $texte.= ''; - } $texte.= ''; // List of directories area @@ -144,40 +138,21 @@ class doc_generic_contract_odt extends ModelePDFContract $texte.=$conf->global->CONTRACT_ADDON_PDF_ODT_PATH; $texte.= ''; $texte.= '
'; - $texte.= ''; + $texte.= ''; $texte.= '
'; // Scan directories if (count($listofdir)) { $texte.=$langs->trans("NumberOfModelFilesFound").': '.count($listoffiles).''; - - if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0) - { - // Model for creation - $liste=ModelePDFContract::liste_modeles($this->db); - $texte.= '
'; - $texte.= ''; - $texte.= ''; - $texte.= '"; - - $texte.= ''; - $texte.= ''; - $texte.= '"; - $texte.= ''; - - $texte.= ''; - $texte.= '"; - $texte.= '
'.$langs->trans("DefaultModelPropalCreate").''; - $texte.= $form->selectarray('value2',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_DEFAULT); - $texte.= "
'.$langs->trans("DefaultModelPropalToBill").''; - $texte.= $form->selectarray('value3',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_TOBILL); - $texte.= "
'.$langs->trans("DefaultModelPropalClosed").''; - $texte.= $form->selectarray('value4',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_CLOSED); - $texte.= "
'; - } } + // Add select to upload a new template file. TODO Copy this feature on other admin pages. + $texte.= '
'.$langs->trans("UploadNewTemplate").' '; + $texte.= ''; + $texte.= ''; + $texte.= '
'; + $texte.= '
'; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index fe547931908..5b213135878 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -48,6 +48,7 @@ InternalUsers=Internal users ExternalUsers=External users GUISetup=Display SetupArea=Setup area +UploadNewTemplate=Upload new template(s) FormToTestFileUploadForm=Form to test file upload (according to setup) IfModuleEnabled=Note: yes is effective only if module %s is enabled RemoveLock=Remove file %s if it exists to allow usage of the update tool. @@ -873,6 +874,7 @@ DictionaryProspectStatus=Prospection status DictionaryHolidayTypes=Types of leaves DictionaryOpportunityStatus=Opportunity status for project/lead SetupSaved=Setup saved +SetupNotSaved=Setup not saved BackToModuleList=Back to modules list BackToDictionaryList=Back to dictionaries list VATManagement=VAT Management diff --git a/htdocs/modulebuilder/template/admin/setup.php b/htdocs/modulebuilder/template/admin/setup.php index 63b92bc6468..b3f2cc87d73 100644 --- a/htdocs/modulebuilder/template/admin/setup.php +++ b/htdocs/modulebuilder/template/admin/setup.php @@ -39,20 +39,23 @@ require_once '../lib/mymodule.lib.php'; $langs->load("mymodule@mymodule"); // Access control -if (! $user->admin) { - accessforbidden(); -} +if (! $user->admin) accessforbidden(); // Parameters $action = GETPOST('action', 'alpha'); + /* * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + + /* * View */ + $page_name = "MyModuleSetup"; llxHeader('', $langs->trans($page_name)); diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index 5183eeb3382..172bdd9354c 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -74,6 +74,9 @@ $error = 0; * Actions */ +$nomessageinsetmoduleoptions=1; +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'setcodeproduct') { if (dolibarr_set_const($db, "PRODUCT_CODEPRODUCT_ADDON",$value,'chaine',0,'',$conf->entity) > 0) @@ -87,36 +90,6 @@ if ($action == 'setcodeproduct') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - //setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - // message yet present at the bottom if($action) - //setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - if ($action == 'other' && GETPOST('value_PRODUIT_LIMIT_SIZE') >= 0) { $res = dolibarr_set_const($db, "PRODUIT_LIMIT_SIZE", GETPOST('value_PRODUIT_LIMIT_SIZE'),'chaine',0,'',$conf->entity); @@ -278,7 +251,7 @@ if ($action) } else { - setEventMessages($langs->trans("Error"), null, 'errors'); + setEventMessages($langs->trans("SetupNotError"), null, 'errors'); } } @@ -543,7 +516,7 @@ foreach ($dirmodels as $reldir) print '
'; print "
"; - + /* * Other conf */ @@ -598,7 +571,7 @@ print ''; // multiprix nombre de prix a proposer if (! empty($conf->global->PRODUIT_MULTIPRICES)) { - + print ''; print ''.$langs->trans("MultiPricesNumPrices").''; print ''; @@ -640,7 +613,7 @@ print ''; if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { - + print ''; print ''.$langs->trans("NumberOfProductShowInSelect").''; print ''; @@ -681,7 +654,7 @@ print ''; // View product description in thirdparty language if (! empty($conf->global->MAIN_MULTILANGS)) { - + print ''; print ''.$langs->trans("ViewProductDescInThirdpartyLanguageAbility").''; print ''; @@ -723,7 +696,7 @@ if (! empty($conf->global->PRODUCT_CANVAS_ABILITY)) if ($conf->$module->enabled) { - + print ""; print $object->description; diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php index fbcecf032cf..9e35ea77e0b 100644 --- a/htdocs/projet/admin/project.php +++ b/htdocs/projet/admin/project.php @@ -51,6 +51,8 @@ $type='project'; * Actions */ +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'setmainoptions') { if (GETPOST('PROJECT_USE_OPPORTUNITIES')) dolibarr_set_const($db, "PROJECT_USE_OPPORTUNITIES",GETPOST('PROJECT_USE_OPPORTUNITIES'),'chaine',0,'',$conf->entity); @@ -104,7 +106,7 @@ else if ($action == 'specimen') $project = new Project($db); $project->initAsSpecimen(); - + // Search template files $file=''; $classname=''; $filefound=0; $dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']); @@ -188,35 +190,6 @@ else if ($action == 'specimentask') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a model else if ($action == 'set') { @@ -414,7 +387,7 @@ foreach ($dirmodels as $reldir) if ($module->isEnabled()) { - + print ''.$module->name."\n"; print $module->info(); print ''; @@ -518,7 +491,7 @@ if (empty($conf->global->PROJECT_HIDE_TASKS)) if ($module->isEnabled()) { - + print ''.$module->name."\n"; print $module->info(); print ''; @@ -660,7 +633,7 @@ foreach ($dirmodels as $reldir) if ($modulequalified) { - + print ''; print (empty($module->name)?$name:$module->name); print "\n"; diff --git a/htdocs/societe/admin/societe.php b/htdocs/societe/admin/societe.php index 63ba12197fd..5c84be25521 100644 --- a/htdocs/societe/admin/societe.php +++ b/htdocs/societe/admin/societe.php @@ -42,6 +42,9 @@ if (!$user->admin) accessforbidden(); /* * Actions */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + if ($action == 'setcodeclient') { if (dolibarr_set_const($db, "SOCIETE_CODECLIENT_ADDON",$value,'chaine',0,'',$conf->entity) > 0) @@ -101,35 +104,6 @@ if ($action == 'updateoptions') } } -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $post_size=count($_POST); - - $db->begin(); - - for($i=0;$i < $post_size;$i++) - { - if (array_key_exists('param'.$i,$_POST)) - { - $param=GETPOST("param".$i,'alpha'); - $value=GETPOST("value".$i,'alpha'); - if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - if (! $error) - { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } -} - // Activate a document generator module if ($action == 'set') { From 07a6bb56642f06d32840e2bb2681a84e8b828296 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 1 Jun 2017 12:26:17 +0200 Subject: [PATCH 12/40] More files to delete in migration --- htdocs/install/upgrade2.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 42c8f50632e..33cfd088ebe 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -413,10 +413,10 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) { // 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); - + // Reload modules (this must be always and only into last targeted version) $listofmodule=array( 'MAIN_MODULE_ACCOUNTING'=>'newboxdefonly', @@ -426,11 +426,11 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) 'MAIN_MODULE_PRINTING'=>'newboxdefonly', ); migrate_reload_modules($db,$langs,$conf,$listofmodule); - + // Reload menus (this must be always and only into last targeted version) migrate_reload_menu($db,$langs,$conf,$versionto); } - + // Can force activation of some module during migration with third paramater = MAIN_MODULE_XXX,MAIN_MODULE_YYY,... if ($enablemodules) { @@ -456,8 +456,8 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) // Actions for all versions (not in database) migrate_delete_old_files($db, $langs, $conf); migrate_delete_old_dir($db, $langs, $conf); - - + + dol_mkdir(DOL_DATA_ROOT.'/bank'); migrate_directories($db, $langs, $conf, '/banque/bordereau', '/bank/checkdeposits'); } @@ -3927,10 +3927,13 @@ function migrate_delete_old_files($db,$langs,$conf) DOL_DOCUMENT_ROOT.'/core/modules/mailings/kiwi.modules.php', DOL_DOCUMENT_ROOT.'/core/modules/facture/pdf_crabe.modules.php', DOL_DOCUMENT_ROOT.'/core/modules/facture/pdf_oursin.modules.php', - + DOL_DOCUMENT_ROOT.'/compta/facture/class/api_invoice.class.php', DOL_DOCUMENT_ROOT.'/commande/class/api_commande.class.php', - DOL_DOCUMENT_ROOT.'/user/class/api_user.class.php' + DOL_DOCUMENT_ROOT.'/user/class/api_user.class.php', + DOL_DOCUMENT_ROOT.'/product/class/api_product.class.php', + DOL_DOCUMENT_ROOT.'/societe/class/api_contact.class.php', + DOL_DOCUMENT_ROOT.'/societe/class/api_thirdparty.class.php' ); foreach ($filetodeletearray as $filetodelete) From 733d1caac6578da19a998b7a206e799c3ebdea9e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 1 Jun 2017 12:37:16 +0200 Subject: [PATCH 13/40] Correct usage of parameter 'none' in GETPOST --- htdocs/admin/chequereceipts.php | 2 +- htdocs/admin/commande.php | 2 +- htdocs/admin/contract.php | 2 +- htdocs/admin/expedition.php | 2 +- htdocs/admin/expensereport.php | 2 +- htdocs/admin/facture.php | 2 +- htdocs/admin/fichinter.php | 2 +- htdocs/admin/livraison.php | 2 +- htdocs/admin/payment.php | 17 ++--------------- htdocs/admin/propal.php | 2 +- htdocs/admin/supplier_invoice.php | 2 +- htdocs/admin/supplier_order.php | 2 +- htdocs/admin/supplier_proposal.php | 2 +- htdocs/don/admin/donation.php | 4 ++-- htdocs/install/mysql/migration/repair.sql | 2 +- 15 files changed, 17 insertions(+), 30 deletions(-) diff --git a/htdocs/admin/chequereceipts.php b/htdocs/admin/chequereceipts.php index bc55eb4b9f6..f88dfc6f5a6 100644 --- a/htdocs/admin/chequereceipts.php +++ b/htdocs/admin/chequereceipts.php @@ -77,7 +77,7 @@ if ($action == 'setmod') if ($action == 'set_BANK_CHEQUERECEIPT_FREE_TEXT') { - $freetext = GETPOST('BANK_CHEQUERECEIPT_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('BANK_CHEQUERECEIPT_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "BANK_CHEQUERECEIPT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 3f3c997b0d8..f4104e2007f 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -180,7 +180,7 @@ else if ($action == 'set_COMMANDE_DRAFT_WATERMARK') else if ($action == 'set_ORDER_FREE_TEXT') { - $freetext = GETPOST("ORDER_FREE_TEXT"); // No alpha here, we want exact string + $freetext = GETPOST("ORDER_FREE_TEXT",'none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "ORDER_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index 206d9020022..7f9465b6f65 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -158,7 +158,7 @@ else if ($action == 'setmod') else if ($action == 'set_other') { - $freetext= GETPOST('CONTRACT_FREE_TEXT'); // No alpha here, we want exact string + $freetext= GETPOST('CONTRACT_FREE_TEXT','none'); // No alpha here, we want exact string $res1 = dolibarr_set_const($db, "CONTRACT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); $draft= GETPOST('CONTRACT_DRAFT_WATERMARK','alpha'); diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php index 6182538f820..12d0b7951d5 100644 --- a/htdocs/admin/expedition.php +++ b/htdocs/admin/expedition.php @@ -78,7 +78,7 @@ if ($action == 'updateMask') else if ($action == 'set_param') { - $freetext=GETPOST('SHIPPING_FREE_TEXT'); // No alpha here, we want exact string + $freetext=GETPOST('SHIPPING_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "SHIPPING_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); if ($res <= 0) { diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php index 6c659181c4c..24aaeede5b4 100644 --- a/htdocs/admin/expensereport.php +++ b/htdocs/admin/expensereport.php @@ -168,7 +168,7 @@ else if ($action == 'setoptions') { $db->begin(); - $freetext= GETPOST('EXPENSEREPORT_FREE_TEXT'); // No alpha here, we want exact string + $freetext= GETPOST('EXPENSEREPORT_FREE_TEXT','none'); // No alpha here, we want exact string $res1 = dolibarr_set_const($db, "EXPENSEREPORT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); $draft= GETPOST('EXPENSEREPORT_DRAFT_WATERMARK','alpha'); diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index 115a685a3f2..df371639cde 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -206,7 +206,7 @@ if ($action == 'set_FACTURE_DRAFT_WATERMARK') if ($action == 'set_INVOICE_FREE_TEXT') { - $freetext = GETPOST('INVOICE_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('INVOICE_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "INVOICE_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/admin/fichinter.php b/htdocs/admin/fichinter.php index 25c46164783..43ad7ad8178 100644 --- a/htdocs/admin/fichinter.php +++ b/htdocs/admin/fichinter.php @@ -160,7 +160,7 @@ else if ($action == 'setmod') else if ($action == 'set_FICHINTER_FREE_TEXT') { - $freetext= GETPOST('FICHINTER_FREE_TEXT'); // No alpha here, we want exact string + $freetext= GETPOST('FICHINTER_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "FICHINTER_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); if (! $res > 0) $error++; diff --git a/htdocs/admin/livraison.php b/htdocs/admin/livraison.php index ef73ec7a757..0136f6cc9d9 100644 --- a/htdocs/admin/livraison.php +++ b/htdocs/admin/livraison.php @@ -74,7 +74,7 @@ if ($action == 'updateMask') if ($action == 'set_DELIVERY_FREE_TEXT') { - $free=GETPOST('DELIVERY_FREE_TEXT'); // No alpha here, we want exact string + $free=GETPOST('DELIVERY_FREE_TEXT','none'); // No alpha here, we want exact string $res=dolibarr_set_const($db, "DELIVERY_FREE_TEXT",$free,'chaine',0,'',$conf->entity); if (! $res > 0) $error++; diff --git a/htdocs/admin/payment.php b/htdocs/admin/payment.php index 88f2d8cd1c1..061b9d50f6a 100644 --- a/htdocs/admin/payment.php +++ b/htdocs/admin/payment.php @@ -71,7 +71,7 @@ if ($action == 'setmod') if ($action == 'setparams') { - $freetext = GETPOST('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS'); // No alpha here, we want exact string + $freetext = GETPOST('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS",$freetext,'chaine',0,'',$conf->entity); @@ -81,24 +81,11 @@ if ($action == 'setparams') { setEventMessages($langs->trans("Error"), null, 'errors'); } - - /* - $freetext = GETPOST('INVOICE_AUTO_FILLJS'); // No alpha here, we want exact string - - $res = dolibarr_set_const($db, "INVOICE_AUTO_FILLJS",$freetext,'chaine',0,'',$conf->entity); - - if (! $res > 0) $error++; - - if ($error) - { - setEventMessages($langs->trans("Error"), null, 'errors'); - }*/ - if (! $error) { setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); } - + } diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php index 9fa8dad0c0c..8acbf19f939 100644 --- a/htdocs/admin/propal.php +++ b/htdocs/admin/propal.php @@ -135,7 +135,7 @@ if ($action == 'set_PROPALE_DRAFT_WATERMARK') if ($action == 'set_PROPOSAL_FREE_TEXT') { - $freetext = GETPOST('PROPOSAL_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('PROPOSAL_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "PROPOSAL_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/admin/supplier_invoice.php b/htdocs/admin/supplier_invoice.php index 549bb93809b..17501cdb4f9 100644 --- a/htdocs/admin/supplier_invoice.php +++ b/htdocs/admin/supplier_invoice.php @@ -172,7 +172,7 @@ if ($action == 'addcat') if ($action == 'set_SUPPLIER_INVOICE_FREE_TEXT') { - $freetext = GETPOST('SUPPLIER_INVOICE_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('SUPPLIER_INVOICE_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "SUPPLIER_INVOICE_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/admin/supplier_order.php b/htdocs/admin/supplier_order.php index 55e4e4b3d07..13499af551a 100644 --- a/htdocs/admin/supplier_order.php +++ b/htdocs/admin/supplier_order.php @@ -169,7 +169,7 @@ else if ($action == 'addcat') else if ($action == 'set_SUPPLIER_ORDER_OTHER') { - $freetext = GETPOST('SUPPLIER_ORDER_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('SUPPLIER_ORDER_FREE_TEXT','none'); // No alpha here, we want exact string $doubleapproval = GETPOST('SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED','alpha'); $doubleapproval = price2num($doubleapproval ); diff --git a/htdocs/admin/supplier_proposal.php b/htdocs/admin/supplier_proposal.php index 210d601c33c..8c52ee83dda 100644 --- a/htdocs/admin/supplier_proposal.php +++ b/htdocs/admin/supplier_proposal.php @@ -132,7 +132,7 @@ if ($action == 'set_SUPPLIER_PROPOSAL_DRAFT_WATERMARK') if ($action == 'set_SUPPLIER_PROPOSAL_FREE_TEXT') { - $freetext = GETPOST('SUPPLIER_PROPOSAL_FREE_TEXT'); // No alpha here, we want exact string + $freetext = GETPOST('SUPPLIER_PROPOSAL_FREE_TEXT','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "SUPPLIER_PROPOSAL_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); diff --git a/htdocs/don/admin/donation.php b/htdocs/don/admin/donation.php index c8d8be2461d..2ca1cba1083 100644 --- a/htdocs/don/admin/donation.php +++ b/htdocs/don/admin/donation.php @@ -121,7 +121,7 @@ else if ($action == 'del') // Options if ($action == 'set_DONATION_ACCOUNTINGACCOUNT') { - $account = GETPOST('DONATION_ACCOUNTINGACCOUNT'); // No alpha here, we want exact string + $account = GETPOST('DONATION_ACCOUNTINGACCOUNT','alpha'); $res = dolibarr_set_const($db, "DONATION_ACCOUNTINGACCOUNT",$account,'chaine',0,'',$conf->entity); @@ -139,7 +139,7 @@ if ($action == 'set_DONATION_ACCOUNTINGACCOUNT') if ($action == 'set_DONATION_MESSAGE') { - $freemessage = GETPOST('DONATION_MESSAGE'); // No alpha here, we want exact string + $freemessage = GETPOST('DONATION_MESSAGE','none'); // No alpha here, we want exact string $res = dolibarr_set_const($db, "DONATION_MESSAGE",$freemessage,'chaine',0,'',$conf->entity); diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 6ff7356847f..0277f7e996b 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -28,7 +28,7 @@ --- Requests to clean corrupted database +-- Requests to clean corrupted data UPDATE llx_user set api_key = null where api_key = ''; From 7ad92c3a4d52c7dc0f456d92bed4756ba0efb079 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 1 Jun 2017 13:32:20 +0200 Subject: [PATCH 14/40] Fix new generic substitution system --- htdocs/admin/contract.php | 2 +- htdocs/contrat/class/contrat.class.php | 23 +++++++------- htdocs/core/lib/functions.lib.php | 30 ++++++++++--------- htdocs/core/lib/pdf.lib.php | 17 ++++++----- .../contract/doc/pdf_strato.modules.php | 17 ++++++----- 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index 7f9465b6f65..e2f865f61f6 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -474,7 +474,7 @@ print ''.$langs->trans("Value").''; print "\n"; $var=true; -$substitutionarray=pdf_getSubstitutionArray($langs); +$substitutionarray=pdf_getSubstitutionArray($langs, array('objectamount')); $substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation"); $htmltext = ''.$langs->trans("AvailableVariables").':
'; foreach($substitutionarray as $key => $val) $htmltext.=$key.'
'; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index db6464edb6a..b11e19d114b 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -46,7 +46,7 @@ class Contrat extends CommonObject public $fk_element='fk_contrat'; protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe public $picto='contract'; - + /** * {@inheritdoc} */ @@ -530,7 +530,7 @@ class Contrat extends CommonObject $this->fin_validite = $this->db->jdate($result["fin_validite"]); $this->date_cloture = $this->db->jdate($result["date_cloture"]); - + $this->user_author_id = $result["fk_user_author"]; $this->commercial_signature_id = $result["fk_commercial_signature"]; @@ -613,7 +613,7 @@ class Contrat extends CommonObject $this->lines=array(); $pos = 0; - + // Selectionne les lignes contrats liees a un produit $sql = "SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref,"; $sql.= " d.rowid, d.fk_contrat, d.statut, d.description, d.price_ht, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.remise_percent, d.subprice, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht,"; @@ -1858,7 +1858,7 @@ class Contrat extends CommonObject $url = DOL_URL_ROOT.'/contrat/card.php?id='.$this->id; $picto = 'contract'; $label = ''; - + if ($user->rights->contrat->lire) { $label = ''.$langs->trans("ShowContract").''; $label .= '
'.$langs->trans('Ref').': '.$this->ref; @@ -1874,7 +1874,7 @@ class Contrat extends CommonObject $label .= '
'.$langs->trans('AmountTTC').': '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency); } } - + $linkclose=''; if (empty($notooltip) && $user->rights->contrat->lire) { @@ -1890,7 +1890,7 @@ class Contrat extends CommonObject $linkstart = ''; $linkend=''; - + if ($withpicto) $result.=($linkstart.img_object(($notooltip?'':$label), $picto, ($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).$linkend); if ($withpicto && $withpicto != 2) $result.=' '; $result.=$linkstart.$this->ref.$linkend; @@ -2225,7 +2225,11 @@ class Contrat extends CommonObject $line->total_ht=90; $line->total_ttc=107.64; // 90 * 1.196 $line->total_tva=17.64; - if ($num_prods > 0) + $line->date_ouverture = dol_now() - 200000; + $line->date_ouverture_prevue = dol_now() - 500000; + $line->date_fin_validite = dol_now() + 500000; + $line->date_cloture = dol_now() - 100000; + if ($num_prods > 0) { $prodid = mt_rand(1, $num_prods); $line->fk_product=$prodids[$prodid]; @@ -2233,11 +2237,6 @@ class Contrat extends CommonObject $this->lines[$xnbp]=$line; $xnbp++; } - - $this->amount_ht = $xnbp*100; - $this->total_ht = $xnbp*100; - $this->total_tva = $xnbp*19.6; - $this->total_ttc = $xnbp*119.6; } /** diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a18b9e14110..dd4f720b378 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -239,7 +239,7 @@ function dol_shutdown() /** * Return value of a param into GET or POST supervariable. * Use the property $user->default_values[path]['creatform'] and/or $user->default_values[path]['filters'] and/or $user->default_values[path]['sortorder'] - * Note: The property $user->default_values is loaded by the main when loading the user. + * Note: The property $user->default_values is loaded by main.php when loading the user. * * @param string $paramname Name of parameter to found * @param string $check Type of check @@ -359,32 +359,34 @@ function GETPOST($paramname, $check='', $method=0, $filter=NULL, $options=NULL) if (! empty($check)) { - // Replace vars like __DAY__, __MONTH__, __YEAR__, __MYCOUNTRYID__, __USERID__, __ENTITYID__, ... - if (! is_array($out)) + // Substitution variables for GETPOST (used to get final url with variable parameters or final default value with variable paramaters) + // Example of variables: __DAY__, __MONTH__, __YEAR__, __MYCOUNTRYID__, __USERID__, __ENTITYID__, ... + // We do this only if var is a GET. If it is a POST, may be we want to post the text with vars as the setup text. + if (! is_array($out) && empty($_POST[$paramname])) { $maxloop=20; $loopnb=0; // Protection against infinite loop while (preg_match('/__([A-Z0-9]+_?[A-Z0-9]+)__/i', $out, $reg) && ($loopnb < $maxloop)) // Detect '__ABCDEF__' as key 'ABCDEF' and '__ABC_DEF__' as key 'ABC_DEF'. Detection is also correct when 2 vars are side by side. { $loopnb++; $newout = ''; - if ($reg[1] == 'DAY') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['mday']; } - elseif ($reg[1] == 'MONTH') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['mon']; } - elseif ($reg[1] == 'YEAR') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['year']; } + if ($reg[1] == 'DAY') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['mday']; } + elseif ($reg[1] == 'MONTH') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['mon']; } + elseif ($reg[1] == 'YEAR') { $tmp=dol_getdate(dol_now(), true); $newout = $tmp['year']; } elseif ($reg[1] == 'PREVIOUS_DAY') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_prev_day($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['day']; } elseif ($reg[1] == 'PREVIOUS_MONTH') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_prev_month($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['month']; } elseif ($reg[1] == 'PREVIOUS_YEAR') { $tmp=dol_getdate(dol_now(), true); $newout = ($tmp['year'] - 1); } - elseif ($reg[1] == 'NEXT_DAY') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['day']; } - elseif ($reg[1] == 'NEXT_MONTH') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_next_month($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['month']; } - elseif ($reg[1] == 'NEXT_YEAR') { $tmp=dol_getdate(dol_now(), true); $newout = ($tmp['year'] + 1); } - elseif ($reg[1] == 'MYCOUNTRYID') + elseif ($reg[1] == 'NEXT_DAY') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['day']; } + elseif ($reg[1] == 'NEXT_MONTH') { $tmp=dol_getdate(dol_now(), true); $tmp2=dol_get_next_month($tmp['mday'], $tmp['mon'], $tmp['year']); $newout = $tmp2['month']; } + elseif ($reg[1] == 'NEXT_YEAR') { $tmp=dol_getdate(dol_now(), true); $newout = ($tmp['year'] + 1); } + elseif ($reg[1] == 'MYCOUNTRY_ID' || $reg[1] == 'MYCOUNTRYID') { $newout = $mysoc->country_id; } - elseif ($reg[1] == 'USERID') + elseif ($reg[1] == 'USER_ID' || $reg[1] == 'USERID') { $newout = $user->id; } - elseif ($reg[1] == 'SUPERVISORID') + elseif ($reg[1] == 'SUPERVISOR_ID' || $reg[1] == 'SUPERVISORID') { $newout = $user->fk_user; } @@ -5020,7 +5022,7 @@ function dol_concatdesc($text1,$text2,$forxml=false) * * @param Translate $outputlangs Output language * @param int $onlykey Do not calculate heavy values of keys (performance enhancement when we need only the keys) - * @param array $exclude Array of family keys we want to exclude. For example array('mycompany', 'object', 'date', 'user', ...) + * @param array $exclude Array of family keys we want to exclude. For example array('mycompany', 'objectamount', 'date', 'user', ...) * @param Object $object Object for keys on object * @return array Array of substitutions */ @@ -5045,7 +5047,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob '__MYCOMPANY_COUNTRY_ID__' => $mysoc->country_id )); } - if (empty($exclude) || ! in_array('object', $exclude)) + if (empty($exclude) || ! in_array('objectamount', $exclude)) { if (is_object($object)) // For backward compatibility { diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 8c48e2301e3..9220725dc8e 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -591,12 +591,13 @@ function pdf_pagehead(&$pdf,$outputlangs,$page_height) * Return array of possible substitutions for PDF content (without external module substitutions). * * @param Translate $outputlangs Output language + * @param array $exclude Array of family keys we want to exclude. For example array('mycompany', 'object', 'date', 'user', ...) * @param Object $object Object * @return array Array of substitutions */ -function pdf_getSubstitutionArray($outputlangs, $object=null) +function pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null) { - $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object); + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $exclude, $object); $substitutionarray['__FROM_NAME__']='__FROM_NAME__'; $substitutionarray['__FROM_EMAIL__']='__FROM_EMAIL__'; return $substitutionarray; @@ -625,9 +626,9 @@ function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text) elseif ($unit=='in') $k=72; // Make substitution - $substitutionarray=pdf_getSubstitutionArray($outputlangs,null); - complete_substitutions_array($substitutionarray,$outputlangs,null); - $text=make_substitutions($text,$substitutionarray,$outputlangs); + $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, null); + complete_substitutions_array($substitutionarray, $outputlangs, null); + $text=make_substitutions($text, $substitutionarray, $outputlangs); $text=$outputlangs->convToOutputCharset($text); $savx=$pdf->getX(); $savy=$pdf->getY(); @@ -854,12 +855,12 @@ function pdf_pagefoot(&$pdf,$outputlangs,$paramfreetext,$fromcompany,$marge_bass // Line of free text if (empty($hidefreetext) && ! empty($conf->global->$paramfreetext)) { - $substitutionarray=pdf_getSubstitutionArray($outputlangs, $object); + $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object); // More substitution keys $substitutionarray['__FROM_NAME__']=$fromcompany->name; $substitutionarray['__FROM_EMAIL__']=$fromcompany->email; - complete_substitutions_array($substitutionarray,$outputlangs,$object); - $newfreetext=make_substitutions($conf->global->$paramfreetext,$substitutionarray,$outputlangs); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $newfreetext=make_substitutions($conf->global->$paramfreetext, $substitutionarray, $outputlangs); $line.=$outputlangs->convToOutputCharset($newfreetext); } diff --git a/htdocs/core/modules/contract/doc/pdf_strato.modules.php b/htdocs/core/modules/contract/doc/pdf_strato.modules.php index 411b3deadf3..c06882fa121 100644 --- a/htdocs/core/modules/contract/doc/pdf_strato.modules.php +++ b/htdocs/core/modules/contract/doc/pdf_strato.modules.php @@ -294,22 +294,25 @@ class pdf_strato extends ModelePDFContract } else { $datere = $langs->trans("Unknown"); } - + $txtpredefinedservice=''; - $txtpredefinedservice = $objectligne->product_ref; + $txtpredefinedservice = $objectligne->product_label; if ($objectligne->product_label) { $txtpredefinedservice .= ' - '; $txtpredefinedservice .= $objectligne->product_label; } - $txt=''.dol_htmlentitiesbr($outputlangs->transnoentities("DateStartPlannedShort")." : ".$datei." - ".$outputlangs->transnoentities("DateEndPlanned")." : ".$datee,1,$outputlangs->charset_output).''; + $desc=dol_htmlentitiesbr($objectligne->desc,1); // Desc (not empty for free lines) + $txt=''; + $txt.=$outputlangs->transnoentities("Quantity").' : '.$objectligne->qty.' - '.$outputlangs->transnoentities("UnitPrice").' : '.price($objectligne->subprice).''; // Desc (not empty for free lines) $txt.='
'; - $txt.=''.dol_htmlentitiesbr($outputlangs->transnoentities("DateStartRealShort")." : ".$daters,1,$outputlangs->charset_output); - if ($objectligne->date_cloture) $txt.=dol_htmlentitiesbr(" - ".$outputlangs->transnoentities("DateEndRealShort")." : ".$datere,1,$outputlangs->charset_output).''; - $desc=dol_htmlentitiesbr($objectligne->desc,1); + $txt.=$outputlangs->transnoentities("DateStartPlannedShort")." : ".$datei." - ".$outputlangs->transnoentities("DateEndPlanned")." : ".$datee.''; + $txt.='
'; + $txt.=$outputlangs->transnoentities("DateStartRealShort")." : ".$daters.''; + if ($objectligne->date_cloture) $txt.=" - ".$outputlangs->transnoentities("DateEndRealShort")." : ''".$datere.''; - $pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txt,dol_concatdesc($txtpredefinedservice,$desc)), 0, 1, 0); + $pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txtpredefinedservice, dol_concatdesc($txt, $desc)), 0, 1, 0); $nexY = $pdf->GetY() + 2; $pageposafter=$pdf->getPage(); From f4cdb6b25475ece60ec0bcf8bfcc82bc739d3e5e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 1 Jun 2017 15:33:23 +0200 Subject: [PATCH 15/40] Fix month on 2 chars. Some setup return on 1 char only. More phpunit assert. --- htdocs/core/lib/functions.lib.php | 173 +++++++++++++++--------------- test/phpunit/DateLibTest.php | 39 ++++--- 2 files changed, 109 insertions(+), 103 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index c678e0bc7df..0943bc1a7af 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -102,14 +102,14 @@ function getDoliDBInstance($type, $host, $user, $pass, $name, $port) /** * Get list of entity id to use * - * @param string $element Current element - * 'societe', 'socpeople', 'actioncomm', 'agenda', 'resource', + * @param string $element Current element + * 'societe', 'socpeople', 'actioncomm', 'agenda', 'resource', * 'product', 'productprice', 'stock', * 'propal', 'facture', 'facture_fourn', - * 'categorie', 'bank_account', 'bank_account', 'adherent', 'user', + * 'categorie', 'bank_account', 'bank_account', 'adherent', 'user', * 'commande', 'commande_fournisseur', 'expedition', 'intervention', 'survey', * 'contract', 'tax', 'expensereport', 'holiday', 'multicurrency', 'project', - * 'email_template', 'event', + * 'email_template', 'event', * @param int $shared 0=Return id of entity, 1=Return id entity + shared entities * @return mixed Entity id(s) to use */ @@ -121,7 +121,7 @@ function getEntity($element=false, $shared=0) if ($element == 'actioncomm') $element='agenda'; if ($element == 'fichinter') $element='intervention'; if ($element == 'categorie') $element='category'; - + if (is_object($mc)) { return $mc->getEntity($element, $shared); @@ -203,7 +203,7 @@ function getBrowserInfo($user_agent) elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name='opera'; $version=$reg[2]; } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];\srv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name='ie'; $version=end($reg); } // MS products at end elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { $name='lynxlinks'; $version=$reg[4]; } - + if ($tablet) { $layout = 'tablet'; } elseif ($phone) { @@ -268,7 +268,7 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL) { $tmp=dol_getdate(dol_now(), true); $out = $tmp['mon']; - } + } elseif ($reg[1] == 'YEAR') { $tmp=dol_getdate(dol_now(), true); @@ -280,7 +280,7 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL) $out = $mysoc->country_id; } } - + switch ($check) { case 'int': @@ -337,13 +337,13 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL) * This prefix is unique for instance and avoid conflict between multi-instances, * even when having two instances with one root dir or two instances in virtual servers * - * @param string $mode '' or 'email' + * @param string $mode '' or 'email' * @return string A calculated prefix */ function dol_getprefix($mode='') { global $conf; - + // If MAIL_PREFIX_FOR_EMAIL_ID is set and prefix is for email if ($mode == 'email' && ! empty($conf->global->MAIL_PREFIX_FOR_EMAIL_ID)) { @@ -425,15 +425,15 @@ function dol_buildpath($path, $type=0) if ($type == 1) $res = DOL_URL_ROOT.'/'.$path; // Standard value if ($type == 2) $res = DOL_MAIN_URL_ROOT.'/'.$path; // Standard value if ($type == 3) $res = DOL_URL_ROOT.'/'.$path; - + foreach ($conf->file->dol_document_root as $key => $dirroot) // ex: array(["main"]=>"/home/main/htdocs", ["alt0"]=>"/home/dirmod/htdocs", ...) { - if ($key == 'main') + if ($key == 'main') { if ($type == 3) { global $dolibarr_main_url_root; - + // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file @@ -460,12 +460,12 @@ function dol_buildpath($path, $type=0) if ($type == 3) { global $dolibarr_main_url_root; - + // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - + $res=(preg_match('/^http/i',$conf->file->dol_url_root[$key])?'':$urlwithroot).$conf->file->dol_url_root[$key].'/'.$path; // Test on start with http is for old conf syntax } break; @@ -732,13 +732,13 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' throw new Exception('Incorrect log level'); } if ($level > $conf->global->SYSLOG_LEVEL) return; - + // If adding log inside HTML page is required if (! empty($_REQUEST['logtohtml']) && (! empty($conf->global->MAIN_ENABLE_LOG_TO_HTML) || ! empty($conf->global->MAIN_LOGTOHTML))) // MAIN_LOGTOHTML kept for backward compatibility { $conf->logbuffer[] = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".$message; } - + //TODO: Remove this. MAIN_ENABLE_LOG_INLINE_HTML should be deprecated and use a log handler dedicated to HTML output // If enable html log tag enabled and url parameter log defined, we show output log on HTML comments if (! empty($conf->global->MAIN_ENABLE_LOG_INLINE_HTML) && ! empty($_GET["log"])) @@ -747,7 +747,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' print $message."\n"; print "Log end -->\n"; } - + $data = array( 'message' => $message, 'script' => (isset($_SERVER['PHP_SELF'])? basename($_SERVER['PHP_SELF'],'.php') : false), @@ -755,7 +755,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' 'user' => ((is_object($user) && $user->id) ? $user->login : false), 'ip' => false ); - + if (! empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) else if (! empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR']; @@ -814,7 +814,7 @@ function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $pi global $conf, $langs, $hookmanager; if ($notab == -1) $notab = 0; // For better compatiblity with modules for 6.0 - + $out="\n".'
'."\n"; // Show title @@ -944,7 +944,7 @@ function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $pi { $out = $hookmanager->resPrint; } - + return $out; } @@ -1003,7 +1003,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($object->element == 'member') $modulepart='memberphoto'; if ($object->element == 'user') $modulepart='userphoto'; if ($object->element == 'product') $modulepart='product'; - + if ($object->element == 'product') { $width=80; $cssclass='photoref'; @@ -1011,7 +1011,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r $maxvisiblephotos=(isset($conf->global->PRODUCT_MAX_VISIBLE_PHOTO)?$conf->global->PRODUCT_MAX_VISIBLE_PHOTO:5); if ($conf->browser->phone) $maxvisiblephotos=1; if ($showimage) $morehtmlleft.='
'.$object->show_photos($conf->product->multidir_output[$object->entity],'small',$maxvisiblephotos,0,0,0,$width,0).'
'; - else + else { if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) { $nophoto=''; @@ -1023,11 +1023,11 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r } } } - else + else { - if ($showimage) + if ($showimage) { - if ($modulepart != 'unknown') + if ($modulepart != 'unknown') { $phototoshow = $form->showphoto($modulepart,$object,0,0,0,'photoref','small',1,0,$maxvisiblephotos); if ($phototoshow) @@ -1040,7 +1040,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r elseif ($conf->browser->layout != 'phone') // Show No photo link (picto of pbject) { $morehtmlleft.='
'; - if ($object->element == 'action') + if ($object->element == 'action') { $cssclass='photorefcenter'; $nophoto=img_picto('', 'title_agenda', '', false, 1); @@ -1061,7 +1061,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($showbarcode) $morehtmlleft.='
'.$form->showbarcode($object).'
'; if ($object->element == 'societe' && ! empty($conf->use_javascript_ajax) && $user->rights->societe->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { $morehtmlstatus.=ajax_object_onoff($object, 'status', 'status', 'InActivity', 'ActivityCeased'); - } + } elseif ($object->element == 'product') { //$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Sell").') '; @@ -1081,39 +1081,39 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r elseif ($object->element == 'facture' || $object->element == 'invoice' || $object->element == 'invoice_supplier') { $tmptxt=$object->getLibStatut(6, $object->totalpaye); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); $morehtmlstatus.=$tmptxt; } elseif ($object->element == 'chargesociales') { $tmptxt=$object->getLibStatut(6, $object->totalpaye); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); $morehtmlstatus.=$tmptxt; } elseif ($object->element == 'loan') { $tmptxt=$object->getLibStatut(6, $object->totalpaye); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5, $object->totalpaye); $morehtmlstatus.=$tmptxt; } - elseif ($object->element == 'contrat') + elseif ($object->element == 'contrat') { if ($object->statut==0) $morehtmlstatus.=$object->getLibStatut(2); else $morehtmlstatus.=$object->getLibStatut(4); } else { // Generic case $tmptxt=$object->getLibStatut(6); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || $conf->browser->layout=='phone') $tmptxt=$object->getLibStatut(5); $morehtmlstatus.=$tmptxt; } if (! empty($object->name_alias)) $morehtmlref.='
'.$object->name_alias.'
'; // For thirdparty - + if ($object->element == 'product' || $object->element == 'bank_account') { if(! empty($object->label)) $morehtmlref.='
'.$object->label.'
'; } - if ($object->element != 'product' && $object->element != 'bookmark') + if ($object->element != 'product' && $object->element != 'bookmark') { $morehtmlref.='
'; $morehtmlref.=$object->getBannerAddress('refaddress',$object); @@ -1125,7 +1125,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r $morehtmlref.=$langs->trans("TechnicalID").': '.$object->id; $morehtmlref.='
'; } - + print '
'; print $form->showrefnav($object, $paramid, $morehtml, $shownav, $fieldid, $fieldref, $morehtmlref, $moreparam, $nodbprefix, $morehtmlleft, $morehtmlstatus, $morehtmlright); print '
'; @@ -1301,9 +1301,9 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e $reduceformat=(! empty($conf->dol_optimize_smallscreen) && in_array($format,array('day','dayhour')))?1:0; $formatwithoutreduce = preg_replace('/reduceformat/','',$format); if ($formatwithoutreduce != $format) { $format = $formatwithoutreduce; $reduceformat=1; } // so format 'dayreduceformat' is processed like day - + // Change predefined format into computer format. If found translation in lang file we use it, otherwise we use default. - // TODO Add format daysmallyear and dayhoursmallyear + // TODO Add format daysmallyear and dayhoursmallyear if ($format == 'day') $format=($outputlangs->trans("FormatDateShort")!="FormatDateShort"?$outputlangs->trans("FormatDateShort"):$conf->format_date_short); else if ($format == 'hour') $format=($outputlangs->trans("FormatHourShort")!="FormatHourShort"?$outputlangs->trans("FormatHourShort"):$conf->format_hour_short); else if ($format == 'hourduration') $format=($outputlangs->trans("FormatHourShortDuration")!="FormatHourShortDuration"?$outputlangs->trans("FormatHourShortDuration"):$conf->format_hour_short_duration); @@ -1375,7 +1375,8 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e if (preg_match('/__b__/i',$format)) { // Here ret is string in PHP setup language (strftime was used). Now we convert to $outputlangs. - $month=adodb_strftime('%m',$time+$offsettz+$offsetdst); // TODO Remove this + $month=adodb_strftime('%m',$time+$offsettz+$offsetdst); // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. + $month=sprintf("%02d", $month); // $month may be return with format '06' on some installation and '6' on other, so we force it to '06'. if ($encodetooutput) { $monthtext=$outputlangs->transnoentities('Month'.$month); @@ -1805,7 +1806,7 @@ function dol_print_phone($phone,$countrycode='',$cid=0,$socid=0,$addlink='',$sep $newphone=($separ!=''?'(':'').substr($newphone,0,3).($separ!=''?')':'').$separ.substr($newphone,3,3).($separ!=''?'-':'').substr($newphone,6,4); } } - + if (! empty($addlink)) // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set) { if (! empty($conf->browser->phone) || (! empty($conf->clicktodial->enabled) && ! empty($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) // If phone or option for, we use link of phone @@ -1935,7 +1936,7 @@ function dol_user_country() * @param int $mode thirdparty|contact|member|other * @param int $id Id of object * @param int $noprint No output. Result is the function return - * @param string $charfornl Char to use instead of nl2br. '' means we use a standad nl2br. + * @param string $charfornl Char to use instead of nl2br. '' means we use a standad nl2br. * @return string|void Nothing if noprint is 0, formatted address if noprint is 1 * @see dol_format_address */ @@ -1956,7 +1957,7 @@ function dol_print_address($address, $htmlid, $mode, $id, $noprint=0, $charfornl { if (empty($charfornl)) $out.=nl2br($address); else $out.=preg_replace('/[\r\n]+/', $charfornl, $address); - + $showgmap=$showomap=0; // TODO Add a hook here @@ -2084,7 +2085,7 @@ function dol_print_graph($htmlid,$width,$height,$data,$showlegend=0,$type='pie', print '
'.$langs->trans("NotEnoughDataYet").'
'; return; } - + if (empty($conf->use_javascript_ajax)) return; $jsgraphlib='flot'; $datacolor=array(); @@ -2253,7 +2254,7 @@ function dol_trunc($string,$size=40,$trunc='right',$stringencoding='UTF-8',$nodo global $conf; if ($size==0 || ! empty($conf->global->MAIN_DISABLE_TRUNC)) return $string; - + if (empty($stringencoding)) $stringencoding='UTF-8'; // reduce for small screen if ($conf->dol_optimize_smallscreen==1 && $display==1) $size = round($size/3); @@ -3206,7 +3207,7 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', * @param string $options More parameters for links ('' by default, does not include sortfield neither sortorder) * @param string $sortfield Field to sort on ('' by default) * @param string $sortorder Order to sort ('' by default) - * @param string $center String in the middle ('' by default). We often find here string $massaction comming from $form->selectMassAction() + * @param string $center String in the middle ('' by default). We often find here string $massaction comming from $form->selectMassAction() * @param int $num Number of records found by select with limit+1 * @param int|string $totalnboflines Total number of records/lines for all pages (if known). Use a negative value of number to not show number. Use '' if unknown. * @param string $picto Icon to use before title (should be a 32x32 transparent png file) @@ -3220,11 +3221,11 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1, $totalnboflines='', $picto='title_generic.png', $pictoisfullpath=0, $morehtml='', $morecss='', $limit=-1, $hideselectlimit=0) { global $conf,$langs; - + $savlimit = $limit; $savtotalnboflines = $totalnboflines; $totalnboflines=abs($totalnboflines); - + if ($picto == 'setup') $picto='title_setup.png'; if (($conf->browser->name == 'ie') && $picto=='title_generic.png') $picto='title.gif'; if ($limit < 0) $limit = $conf->liste_limit; @@ -3237,7 +3238,7 @@ function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $so $nextpage = 0; } //print 'totalnboflines='.$totalnboflines.'-savlimit='.$savlimit.'-limit='.$limit.'-num='.$num.'-nextpage='.$nextpage; - + print "\n"; print "\n"; print ''; @@ -3338,7 +3339,7 @@ function print_fleche_navigation($page, $file, $options='', $nextpage=0, $betwee //$pagesizechoices.=',0:'.$langs->trans("All"); // Not yet supported //$pagesizechoices.=',2:2'; if (! empty($conf->global->MAIN_PAGESIZE_CHOICES)) $pagesizechoices=$conf->global->MAIN_PAGESIZE_CHOICES; - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // EMail - + print ''."\n"; @@ -331,19 +340,19 @@ if (GETPOST("source") == 'order' && $valid) $fulltag=dol_string_unaccent($fulltag); // Creditor - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // EMail - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // EMail - + print ''."\n"; // Debitor - + print ''."\n"; // Quantity - + $label=$langs->trans("Quantity"); $qty=1; $duration=''; @@ -616,7 +625,7 @@ if (GETPOST("source") == 'contractline' && $valid) print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // EMail - + print ''."\n"; // Debitor - + print ''."\n"; // Last subscription amount - + print ''."\n"; @@ -725,7 +734,7 @@ if (GETPOST("source") == 'membersubscription' && $valid) } // Amount - + print ''."\n"; // Tag - + print ''."\n"; // EMail - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Quantity - + $label=$langs->trans("Quantity"); $qty=1; $duration=''; @@ -843,7 +852,7 @@ if (GETPOST("source") == 'contractline') print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Last subscription amount - + print ''."\n"; @@ -972,7 +981,7 @@ if (GETPOST("source") == 'membersubscription') } // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Quantity - + $label=$langs->trans("Quantity"); $qty=1; $duration=''; @@ -760,7 +770,7 @@ if (GETPOST("source") == 'contractline') print ''."\n"; // Amount - + print ''."\n"; // Tag - + print ''."\n"; // Debitor - + print ''."\n"; // Last subscription amount - + print ''."\n"; @@ -889,7 +900,7 @@ if (GETPOST("source") == 'membersubscription') } // Amount - + print ''."\n"; // Tag - + print ''; print ''; print '\n"; @@ -713,31 +725,33 @@ if ($id > 0) if (empty($reshook)) { print '
'; - + // Edit if ($user->rights->loan->write) { + print ''.$langs->trans('CreateCalcSchedule').''; + print ''.$langs->trans("Modify").''; } - + // Emit payment if ($object->paid == 0 && ((price2num($object->capital) > 0 && round($staytopay) < 0) || (price2num($object->capital) > 0 && round($staytopay) > 0)) && $user->rights->loan->write) { print ''.$langs->trans("DoPayment").''; } - + // Classify 'paid' if ($object->paid == 0 && round($staytopay) <=0 && $user->rights->loan->write) { print ''.$langs->trans("ClassifyPaid").''; } - + // Delete if ($user->rights->loan->delete) { print ''.$langs->trans("Delete").''; } - + print "
"; } } diff --git a/htdocs/loan/class/loanschedule.class.php b/htdocs/loan/class/loanschedule.class.php new file mode 100644 index 00000000000..1e519e6a2af --- /dev/null +++ b/htdocs/loan/class/loanschedule.class.php @@ -0,0 +1,526 @@ + + * + * 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/loan/class/loanschedule.class.php + * \ingroup facture + * \brief File of class to manage schedule of loans + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; + + +/** \class LoanSchedule + * \brief Class to manage Schedule of loans + */ +class LoanSchedule extends CommonObject +{ + public $element='loan_schedule'; //!< Id that identify managed objects + public $table_element='loan_schedule'; //!< Name of table without prefix where object is stored + + var $fk_loan; + var $datec=''; + var $tms=''; + var $datep=''; + var $amounts=array(); // Array of amounts + var $amount_capital; // Total amount of payment + var $amount_insurance; + var $amount_interest; + var $fk_typepayment; + var $num_payment; + var $fk_bank; + var $fk_user_creat; + var $fk_user_modif; + var $lines=array(); + + /** + * @deprecated + * @see amount, amounts + */ + var $total; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + $this->db = $db; + } + + /** + * Create payment of loan into database. + * Use this->amounts to have list of lines for the payment + * + * @param User $user User making payment + * @return int <0 if KO, id of payment if OK + */ + function create($user) + { + global $conf, $langs; + + $error=0; + + $now=dol_now(); + + // Validate parameters + if (! $this->datepaid) + { + $this->error='ErrorBadValueForParameter'; + return -1; + } + + // Clean parameters + if (isset($this->fk_loan)) $this->fk_loan = trim($this->fk_loan); + if (isset($this->amount_capital)) $this->amount_capital = trim($this->amount_capital?$this->amount_capital:0); + if (isset($this->amount_insurance)) $this->amount_insurance = trim($this->amount_insurance?$this->amount_insurance:0); + if (isset($this->amount_interest)) $this->amount_interest = trim($this->amount_interest?$this->amount_interest:0); + if (isset($this->fk_typepayment)) $this->fk_typepayment = trim($this->fk_typepayment); + if (isset($this->fk_bank)) $this->fk_bank = trim($this->fk_bank); + if (isset($this->fk_user_creat)) $this->fk_user_creat = trim($this->fk_user_creat); + if (isset($this->fk_user_modif)) $this->fk_user_modif = trim($this->fk_user_modif); + + $totalamount = $this->amount_capital + $this->amount_insurance + $this->amount_interest; + $totalamount = price2num($totalamount); + + // Check parameters + if ($totalamount == 0) { + $this->errors[]='step1'; + return -1; // Negative amounts are accepted for reject prelevement but not null + } + + + $this->db->begin(); + + if ($totalamount != 0) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (fk_loan, datec, datep, amount_capital, amount_insurance, amount_interest,"; + $sql.= " fk_typepayment, fk_user_creat, fk_bank)"; + $sql.= " VALUES (".$this->fk_loan.", '".$this->db->idate($now)."',"; + $sql.= " '".$this->db->idate($this->datepaid)."',"; + $sql.= " ".$this->amount_capital.","; + $sql.= " ".$this->amount_insurance.","; + $sql.= " ".$this->amount_interest.","; + $sql.= " ".$this->fk_typepayment.", "; + $sql.= " ".$user->id.","; + $sql.= " ".$this->fk_bank . ")"; + + dol_syslog(get_class($this)."::create", LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."payment_loan"); + } + else + { + $this->error=$this->db->lasterror(); + $error++; + } + + } + + if ($totalamount != 0 && ! $error) + { + $this->amount_capital=$totalamount; + $this->total=$totalamount; // deprecated + $this->db->commit(); + return $this->id; + } + else + { + $this->errors[]=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from database + * + * @param int $id Id object + * @return int <0 if KO, >0 if OK + */ + function fetch($id) + { + global $langs; + $sql = "SELECT"; + $sql.= " t.rowid,"; + $sql.= " t.fk_loan,"; + $sql.= " t.datec,"; + $sql.= " t.tms,"; + $sql.= " t.datep,"; + $sql.= " t.amount_capital,"; + $sql.= " t.amount_insurance,"; + $sql.= " t.amount_interest,"; + $sql.= " t.fk_typepayment,"; + $sql.= " t.num_payment,"; + $sql.= " t.note_private,"; + $sql.= " t.note_public,"; + $sql.= " t.fk_bank,"; + $sql.= " t.fk_user_creat,"; + $sql.= " t.fk_user_modif,"; + $sql.= " pt.code as type_code, pt.libelle as type_libelle,"; + $sql.= ' b.fk_account'; + $sql.= " FROM (".MAIN_DB_PREFIX."c_paiement as pt, ".MAIN_DB_PREFIX.$this->table_element." as t)"; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON t.fk_bank = b.rowid'; + $sql.= " WHERE t.rowid = ".$id." AND t.fk_typepayment = pt.id"; + + dol_syslog(get_class($this)."::fetch", LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + if ($this->db->num_rows($resql)) + { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + $this->ref = $obj->rowid; + + $this->fk_loan = $obj->fk_loan; + $this->datec = $this->db->jdate($obj->datec); + $this->tms = $this->db->jdate($obj->tms); + $this->datep = $this->db->jdate($obj->datep); + $this->amount_capital = $obj->amount_capital; + $this->amount_insurance = $obj->amount_insurance; + $this->amount_interest = $obj->amount_interest; + $this->fk_typepayment = $obj->fk_typepayment; + $this->num_payment = $obj->num_payment; + $this->note_private = $obj->note_private; + $this->note_public = $obj->note_public; + $this->fk_bank = $obj->fk_bank; + $this->fk_user_creat = $obj->fk_user_creat; + $this->fk_user_modif = $obj->fk_user_modif; + + $this->type_code = $obj->type_code; + $this->type_libelle = $obj->type_libelle; + + $this->bank_account = $obj->fk_account; + $this->bank_line = $obj->fk_bank; + } + $this->db->free($resql); + + return 1; + } + else + { + $this->error="Error ".$this->db->lasterror(); + return -1; + } + } + + + /** + * Update database + * + * @param User $user User that modify + * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @return int <0 if KO, >0 if OK + */ + function update($user=0, $notrigger=0) + { + global $conf, $langs; + $error=0; + + // Clean parameters + if (isset($this->fk_loan)) $this->fk_loan=trim($this->fk_loan); + if (isset($this->amount_capital)) $this->amount_capital=trim($this->amount_capital); + if (isset($this->amount_insurance)) $this->amount_insurance=trim($this->amount_insurance); + if (isset($this->amount_interest)) $this->amount_interest=trim($this->amount_interest); + if (isset($this->fk_typepayment)) $this->fk_typepayment=trim($this->fk_typepayment); + if (isset($this->num_payment)) $this->num_payment=trim($this->num_payment); + if (isset($this->note_private)) $this->note_private=trim($this->note_private); + if (isset($this->note_public)) $this->note_public=trim($this->note_public); + if (isset($this->fk_bank)) $this->fk_bank=trim($this->fk_bank); + if (isset($this->fk_user_creat)) $this->fk_user_creat=trim($this->fk_user_creat); + if (isset($this->fk_user_modif)) $this->fk_user_modif=trim($this->fk_user_modif); + + // Check parameters + // Put here code to add control on parameters values + + // Update request + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; + + $sql.= " fk_loan=".(isset($this->fk_loan)?$this->fk_loan:"null").","; + $sql.= " datec=".(dol_strlen($this->datec)!=0 ? "'".$this->db->idate($this->datec)."'" : 'null').","; + $sql.= " tms=".(dol_strlen($this->tms)!=0 ? "'".$this->db->idate($this->tms)."'" : 'null').","; + $sql.= " datep=".(dol_strlen($this->datep)!=0 ? "'".$this->db->idate($this->datep)."'" : 'null').","; + $sql.= " amount_capital=".(isset($this->amount_capital)?$this->amount_capital:"null").","; + $sql.= " amount_insurance=".(isset($this->amount_insurance)?$this->amount_insurance:"null").","; + $sql.= " amount_interest=".(isset($this->amount_interest)?$this->amount_interest:"null").","; + $sql.= " fk_typepayment=".(isset($this->fk_typepayment)?$this->fk_typepayment:"null").","; + $sql.= " num_payment=".(isset($this->num_payment)?"'".$this->db->escape($this->num_payment)."'":"null").","; + $sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").","; + $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").","; + $sql.= " fk_bank=".(isset($this->fk_bank)?$this->fk_bank:"null").","; + $sql.= " fk_user_creat=".(isset($this->fk_user_creat)?$this->fk_user_creat:"null").","; + $sql.= " fk_user_modif=".(isset($this->fk_user_modif)?$this->fk_user_modif:"null").""; + + $sql.= " WHERE rowid=".$this->id; + + $this->db->begin(); + + dol_syslog(get_class($this)."::update", LOG_DEBUG); + $resql = $this->db->query($sql); + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } + + if (! $error) + { + if (! $notrigger) + { + // Uncomment this and change MYOBJECT to your own tag if you + // want this action call a trigger. + + //// Call triggers + //include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + //$interface=new Interfaces($this->db); + //$result=$interface->run_triggers('MYOBJECT_MODIFY',$this,$user,$langs,$conf); + //if ($result < 0) { $error++; $this->errors=$interface->errors; } + //// End call triggers + } + } + + // Commit or rollback + if ($error) + { + $this->db->rollback(); + return -1*$error; + } + else + { + $this->db->commit(); + return 1; + } + } + + + /** + * Delete object in database + * + * @param User $user User that delete + * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @return int <0 if KO, >0 if OK + */ + function delete($user, $notrigger=0) + { + global $conf, $langs; + $error=0; + + $this->db->begin(); + + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql.= " WHERE rowid=".$this->id; + + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql = $this->db->query($sql); + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } + } + + if (! $error) + { + if (! $notrigger) + { + // Uncomment this and change MYOBJECT to your own tag if you + // want this action call a trigger. + + //// Call triggers + //include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + //$interface=new Interfaces($this->db); + //$result=$interface->run_triggers('MYOBJECT_DELETE',$this,$user,$langs,$conf); + //if ($result < 0) { $error++; $this->errors=$interface->errors; } + //// End call triggers + } + } + + // Commit or rollback + if ($error) + { + foreach($this->errors as $errmsg) + { + dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); + $this->error.=($this->error?', '.$errmsg:$errmsg); + } + $this->db->rollback(); + return -1*$error; + } + else + { + $this->db->commit(); + return 1; + } + } + + function calc_mens($capital,$rate,$nbterm) + { + $result=''; + + if (!empty($capital)&&!empty($rate)&&!empty($nbterm)) + { + $result=($capital*($rate/12))/(1-pow((1+($rate/12)),($nbterm*-1))); + } + + return $result; + } + + + /** + * Load all object in memory from database + * + * @param int $id Id object + * @return int <0 if KO, >0 if OK + */ + function fetchall($loan) + { + global $langs; + + $sql = "SELECT"; + $sql.= " t.rowid,"; + $sql.= " t.fk_loan,"; + $sql.= " t.datec,"; + $sql.= " t.tms,"; + $sql.= " t.datep,"; + $sql.= " t.amount_capital,"; + $sql.= " t.amount_insurance,"; + $sql.= " t.amount_interest,"; + $sql.= " t.fk_typepayment,"; + $sql.= " t.num_payment,"; + $sql.= " t.note_private,"; + $sql.= " t.note_public,"; + $sql.= " t.fk_bank,"; + $sql.= " t.fk_user_creat,"; + $sql.= " t.fk_user_modif"; + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql.= " WHERE t.fk_loan = ".$loan; + + dol_syslog(get_class($this)."::fetchall", LOG_DEBUG); + $resql=$this->db->query($sql); + + if ($resql) + { + while($obj = $this->db->fetch_object($resql)) + { + $line = New LoanSchedule($this->db); + $line->id = $obj->rowid; + $line->ref = $obj->rowid; + + $line->fk_loan = $obj->fk_loan; + $line->datec = $this->db->jdate($obj->datec); + $line->tms = $this->db->jdate($obj->tms); + $line->datep = $this->db->jdate($obj->datep); + $line->amount_capital = $obj->amount_capital; + $line->amount_insurance = $obj->amount_insurance; + $line->amount_interest = $obj->amount_interest; + $line->fk_typepayment = $obj->fk_typepayment; + $line->num_payment = $obj->num_payment; + $line->note_private = $obj->note_private; + $line->note_public = $obj->note_public; + $line->fk_bank = $obj->fk_bank; + $line->fk_user_creat = $obj->fk_user_creat; + $line->fk_user_modif = $obj->fk_user_modif; + + $this->lines[] = $line; + } + $this->db->free($resql); + return 1; + } + else + { + $this->error="Error ".$this->db->lasterror(); + return -1; + } + } + + function trans_paiment() + { + require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/loan.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + $toinsert = array(); + + $sql = "SELECT l.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."loan as l "; + $sql.= " WHERE l.paid = 0"; + $resql=$this->db->query($sql); + + if($resql){ + while($obj = $this->db->fetch_object($resql)){ + $lastrecorded = $this->lastpaiment($obj->rowid); + $toinsert = $this->paimenttorecord($obj->rowid, $lastrecorded); + if(count($toinsert)>0){ + foreach ($toinsert as $echid){ + $this->db->begin(); + $sql = "INSERT INTO " .MAIN_DB_PREFIX . "payment_loan "; + $sql.= "(fk_loan,datec,tms,datep,amount_capital,amount_insurance,amount_interest,fk_typepayment,num_payment,note_private,note_public,fk_bank,fk_user_creat,fk_user_modif) "; + $sql.= "SELECT fk_loan,datec,tms,datep,amount_capital,amount_insurance,amount_interest,fk_typepayment,num_payment,note_private,note_public,fk_bank,fk_user_creat,fk_user_modif FROM " . MAIN_DB_PREFIX . "loan_schedule WHERE rowid =" .$echid; + $res=$this->db->query($sql); + if($res){ + $this->db->commit(); + }else { + $this->db->rollback(); + } + } + } + } + } + } + + + function lastpaiment($loan) + { + $sql = "SELECT p.datep"; + $sql.= " FROM ".MAIN_DB_PREFIX."payment_loan as p "; + $sql.= " WHERE p.fk_loan = " . $loan; + $sql.= " ORDER BY p.datep DESC "; + $sql.= " LIMIT 1 "; + + $resql=$this->db->query($sql); + + if($resql){ + $obj = $this->db->fetch_object($resql); + return $this->db->jdate($obj->datep); + }else{ + return -1; + } + } + + function paimenttorecord($loan,$datemax) + { + $sql = "SELECT p.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." as p "; + $sql.= " WHERE p.fk_loan = " . $loan; + if(!empty($datemax)){ $sql.= " AND p.datep > '" . $this->db->idate($datemax) ."'";} + $sql.= " AND p.datep <= '" . $this->db->idate(dol_now()). "'"; + + + $resql=$this->db->query($sql); + + if($resql){ + while($obj = $this->db->fetch_object($resql)) + { + $result[] = $obj->rowid; + + } + + } + + return $result; + } +} + diff --git a/htdocs/loan/createschedule.php b/htdocs/loan/createschedule.php new file mode 100644 index 00000000000..0d15d1b2de6 --- /dev/null +++ b/htdocs/loan/createschedule.php @@ -0,0 +1,208 @@ + + * + * 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/loan/createecheancier.php + * \ingroup loan + * \brief Schedule card + */ + +require '../main.inc.php'; + +require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/loan.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/loan/class/loanschedule.class.php'; + +global $user; + +$loanid = GETPOST('loanid', 'int'); +$action = GETPOST('action'); + +$object = new Loan($db); +$object->fetch($loanid); + +$langs->load('loan'); + +if ($action == 'createecheancier') { + + $i=1; + while($i <$object->nbterm+1){ + + $date = GETPOST('hi_date'.$i,'int'); + $mens = GETPOST('mens'.$i); + $int = GETPOST('hi_interets'.$i); + + $echeance = new LoanSchedule($db); + + $echeance->fk_loan = $object->id; + $echeance->datec = dol_now(); + $echeance->tms = dol_now(); + $echeance->datepaid = $date; + $echeance->amount_capital = $mens-$int; + $echeance->amount_insurance = 0; + $echeance->amount_interest = $int; + $echeance->fk_typepayment = 3; + $echeance->fk_bank = 1; + $echeance->fk_user_creat = $user->id; + $echeance->fk_user_modif = $user->id; + $result=$echeance->create($user); + if ($result<0) { + setEventMessages(null, $echeance->errors,'errors'); + } + $i++; + } +} + +if ($action == 'updateecheancier') { + + $i=1; + while($i <$object->nbterm+1){ + + $mens = GETPOST('mens'.$i); + $int = GETPOST('hi_interets'.$i); + $id = GETPOST('hi_rowid'.$i); + $echeance = new LoanSchedule($db); + $echeance->fetch($id); + $echeance->tms = dol_now(); + $echeance->amount_capital = $mens-$int; + $echeance->amount_insurance = 0; + $echeance->amount_interest = $int; + $echeance->fk_user_modif = $user->id; + $result= $echeance->update($user,0); + if ($result<0) { + setEventMessages(null, $echeance->errors,'errors'); + } + $i++; + } +} + +$echeance = new LoanSchedule($db); +$echeance->fetchall($object->id); + +top_htmlhead('', ''); +$var = ! $var; + + +?> + +'; +print ''; +print ''; +if(count($echeance->lines)>0){ + print ''; +}else{ + print ''; +} +print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -286,7 +295,7 @@ if (! GETPOST("source") && $valid) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -294,7 +303,7 @@ if (! GETPOST("source") && $valid) print '
'.$langs->trans("YourEMail"); print ' ('.$langs->trans("ToComplete").')'; print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$order->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentOrderRef",$order->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -352,7 +361,7 @@ if (GETPOST("source") == 'order' && $valid) print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -372,7 +381,7 @@ if (GETPOST("source") == 'order' && $valid) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -380,7 +389,7 @@ if (GETPOST("source") == 'order' && $valid) print '
'.$langs->trans("YourEMail"); print ' ('.$langs->trans("ToComplete").')'; $email=$order->thirdparty->email; @@ -419,19 +428,19 @@ if (GETPOST("source") == 'invoice' && $valid) $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$invoice->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentInvoiceRef",$invoice->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -440,7 +449,7 @@ if (GETPOST("source") == 'invoice' && $valid) print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -460,7 +469,7 @@ if (GETPOST("source") == 'invoice' && $valid) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -468,7 +477,7 @@ if (GETPOST("source") == 'invoice' && $valid) print '
'.$langs->trans("YourEMail"); print ' ('.$langs->trans("ToComplete").')'; $email=$invoice->thirdparty->email; @@ -553,19 +562,19 @@ if (GETPOST("source") == 'contractline' && $valid) if (GETPOST('qty')) $qty=GETPOST('qty'); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$contract->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentRenewContractId",$contract->ref,$contractline->ref).''; if ($contractline->fk_product) { @@ -588,7 +597,7 @@ if (GETPOST("source") == 'contractline' && $valid) print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -636,7 +645,7 @@ if (GETPOST("source") == 'contractline' && $valid) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -644,7 +653,7 @@ if (GETPOST("source") == 'contractline' && $valid) print '
'.$langs->trans("YourEMail"); print ' ('.$langs->trans("ToComplete").')'; $email=$contract->thirdparty->email; @@ -684,14 +693,14 @@ if (GETPOST("source") == 'membersubscription' && $valid) $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Member"); print ''; if ($member->morphy == 'mor' && ! empty($member->societe)) print $member->societe; @@ -699,7 +708,7 @@ if (GETPOST("source") == 'membersubscription' && $valid) print ''; // Object - + $text=''.$langs->trans("PaymentSubscription").''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -710,13 +719,13 @@ if (GETPOST("source") == 'membersubscription' && $valid) if ($member->last_subscription_date || $member->last_subscription_amount) { // Last subscription date - + print '
'.$langs->trans("LastSubscriptionDate"); print ''.dol_print_date($member->last_subscription_date,'day'); print '
'.$langs->trans("LastSubscriptionAmount"); print ''.price($member->last_subscription_amount); print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -749,7 +758,7 @@ if (GETPOST("source") == 'membersubscription' && $valid) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -757,7 +766,7 @@ if (GETPOST("source") == 'membersubscription' && $valid) print '
'.$langs->trans("YourEMail"); $email=$member->email; $email=(GETPOST("email")?GETPOST("email"):(isValidEmail($email)?$email:'')); diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 788321b6212..cdfaaa2afc6 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -156,10 +156,10 @@ $urlko=preg_replace('/&$/','',$urlko); // Remove last & if (! empty($conf->paypal->enabled)) { $langs->load("paypal"); - + require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php'; require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php'; - + $PAYPAL_API_OK=""; if ($urlok) $PAYPAL_API_OK=$urlok; $PAYPAL_API_KO=""; @@ -194,7 +194,7 @@ if (! empty($conf->paypal->enabled)) $token = $conf->global->PAYPAL_SECURITY_TOKEN; } if ($SECUREKEY != $token) $valid=false; - + if (! $valid) { print '
Bad value for key.
'; @@ -202,16 +202,16 @@ if (! empty($conf->paypal->enabled)) exit; } } - + $validpaymentmethod['paypal']='valid'; } if (! empty($conf->paybox->enabled)) { $langs->load("paybox"); - + // TODO - + $validpaymentmethod['paybox']='valid'; } @@ -256,10 +256,10 @@ if (empty($validpaymentmethod)) accessforbidden('', 0, 0, 1); if ($action == 'dopayment') { if ($paymentmethod == 'paypal') - { + { $PAYPAL_API_PRICE=price2num(GETPOST("newamount"),'MT'); $PAYPAL_PAYMENT_TYPE='Sale'; - + $origfulltag=GETPOST("fulltag",'alpha'); $shipToName=GETPOST("shipToName"); $shipToStreet=GETPOST("shipToStreet"); @@ -271,24 +271,24 @@ if ($action == 'dopayment') $phoneNum=GETPOST("phoneNum"); $email=GETPOST("email"); $desc=GETPOST("desc"); - + $mesg=''; if (empty($PAYPAL_API_PRICE) || ! is_numeric($PAYPAL_API_PRICE)) $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Amount")); //elseif (empty($EMAIL)) $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("YourEMail")); //elseif (! isValidEMail($EMAIL)) $mesg=$langs->trans("ErrorBadEMail",$EMAIL); elseif (! $origfulltag) $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("PaymentCode")); - + //var_dump($_POST); if (empty($mesg)) { dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG); - + // Other $PAYPAL_API_DEVISE="USD"; //if ($currency == 'EUR') $PAYPAL_API_DEVISE="EUR"; //if ($currency == 'USD') $PAYPAL_API_DEVISE="USD"; if (! empty($currency)) $PAYPAL_API_DEVISE=$currency; - + dol_syslog("Submit Paypal form", LOG_DEBUG); dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG); //dol_syslog("PAYPAL_API_PASSWORD: $PAYPAL_API_PASSWORD", LOG_DEBUG); // No password into log files @@ -308,15 +308,15 @@ if ($action == 'dopayment') dol_syslog("phoneNum: $phoneNum", LOG_DEBUG); dol_syslog("email: $email", LOG_DEBUG); dol_syslog("desc: $desc", LOG_DEBUG); - + dol_syslog("SCRIPT_URI: ".(empty($_SERVER["SCRIPT_URI"])?'':$_SERVER["SCRIPT_URI"]), LOG_DEBUG); // If defined script uri must match domain of PAYPAL_API_OK and PAYPAL_API_KO //$_SESSION["PaymentType"]=$PAYPAL_PAYMENT_TYPE; //$_SESSION["currencyCodeType"]=$PAYPAL_API_DEVISE; //$_SESSION["Payment_Amount"]=$PAYPAL_API_PRICE; - + // A redirect is added if API call successfull print_paypal_redirect($PAYPAL_API_PRICE,$PAYPAL_API_DEVISE,$PAYPAL_PAYMENT_TYPE,$PAYPAL_API_OK,$PAYPAL_API_KO, $FULLTAG); - + exit; } } @@ -335,19 +335,28 @@ $conf->dol_hide_leftmenu=1; llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody'); +// Check link validity +if (! empty($SOURCE) && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', ''))) +{ + $langs->load("errors"); + dol_print_error_email('BADREFINPAYMENTFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $SOURCE, $ref)); + llxFooter(); + $db->close(); + exit; +} if (! empty($conf->paypal->enabled)) { - if (! empty($PAYPAL_API_SANDBOX)) - { - dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning'); - } - // Common variables $creditor=$mysoc->name; $paramcreditor='PAYPAL_CREDITOR_'.$suffix; if (! empty($conf->global->$paramcreditor)) $creditor=$conf->global->$paramcreditor; else if (! empty($conf->global->PAYPAL_CREDITOR)) $creditor=$conf->global->PAYPAL_CREDITOR; + + if (! empty($PAYPAL_API_SANDBOX)) + { + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning'); + } } print ''."\n"; @@ -442,14 +451,14 @@ if (! GETPOST("source")) $fulltag=$tag; // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -469,7 +478,7 @@ if (! GETPOST("source")) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -507,26 +516,26 @@ if (GETPOST("source") == 'order') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='ORD='.$order->ref.'.CUS='.$order->thirdparty->id; //$fulltag.='.NAM='.strtr($order->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$order->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentOrderRef",$order->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -535,7 +544,7 @@ if (GETPOST("source") == 'order') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -555,7 +564,7 @@ if (GETPOST("source") == 'order') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -617,26 +626,26 @@ if (GETPOST("source") == 'invoice') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='INV='.$invoice->ref.'.CUS='.$invoice->thirdparty->id; //$fulltag.='.NAM='.strtr($invoice->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$invoice->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentInvoiceRef",$invoice->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -645,7 +654,7 @@ if (GETPOST("source") == 'invoice') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -665,7 +674,7 @@ if (GETPOST("source") == 'invoice') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -745,7 +754,7 @@ if (GETPOST("source") == 'contractline') { $product=new Product($db); $result=$product->fetch($contractline->fk_product); - + // We define price for product (TODO Put this in a method in product class) if (! empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -759,7 +768,7 @@ if (GETPOST("source") == 'contractline') $pu_ttc = $product->price_ttc; $price_base_type = $product->price_base_type; } - + $amount=$pu_ttc; if (empty($amount)) { @@ -780,19 +789,19 @@ if (GETPOST("source") == 'contractline') if (GETPOST('qty')) $qty=GETPOST('qty'); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$contract->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentRenewContractId",$contract->ref,$contractline->ref).''; if ($contractline->fk_product) { @@ -815,7 +824,7 @@ if (GETPOST("source") == 'contractline') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -863,7 +872,7 @@ if (GETPOST("source") == 'contractline') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -925,20 +934,20 @@ if (GETPOST("source") == 'membersubscription') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='MEM='.$member->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M'); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Member"); print ''; if ($member->morphy == 'mor' && ! empty($member->societe)) print $member->societe; @@ -946,7 +955,7 @@ if (GETPOST("source") == 'membersubscription') print ''; // Object - + $text=''.$langs->trans("PaymentSubscription").''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -957,13 +966,13 @@ if (GETPOST("source") == 'membersubscription') if ($member->last_subscription_date || $member->last_subscription_amount) { // Last subscription date - + print '
'.$langs->trans("LastSubscriptionDate"); print ''.dol_print_date($member->last_subscription_date,'day'); print '
'.$langs->trans("LastSubscriptionAmount"); print ''.price($member->last_subscription_amount); print '
'.$langs->trans("Amount"); if (empty($amount)) { @@ -1001,7 +1010,7 @@ if (GETPOST("source") == 'membersubscription') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -1051,11 +1060,11 @@ if ($action != 'dopayment') if ($found && ! $error) // We are in a management option and no error { // Buttons for all payments registration methods - + if (! empty($conf->paypal->enabled)) { if (empty($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY)) $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY='integral'; - + if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral') { print '
'; @@ -1065,13 +1074,13 @@ if ($action != 'dopayment') print '
'; } } - + if (! empty($conf->paybox->enabled)) { - - + + } - + // TODO Other methods } else diff --git a/htdocs/public/paypal/newpayment.php b/htdocs/public/paypal/newpayment.php index 6de2cb8a441..65fbfbd38a7 100644 --- a/htdocs/public/paypal/newpayment.php +++ b/htdocs/public/paypal/newpayment.php @@ -265,17 +265,27 @@ $conf->dol_hide_leftmenu=1; llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody'); -if (! empty($conf->global->PAYPAL_API_SANDBOX)) -{ - dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning'); -} - // Common variables $creditor=$mysoc->name; $paramcreditor='PAYPAL_CREDITOR_'.$suffix; if (! empty($conf->global->$paramcreditor)) $creditor=$conf->global->$paramcreditor; else if (! empty($conf->global->PAYPAL_CREDITOR)) $creditor=$conf->global->PAYPAL_CREDITOR; +// Check link validity +if (! empty($SOURCE) && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', ''))) +{ + $langs->load("errors"); + dol_print_error_email('BADREFINPAYMENTFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $SOURCE, $ref)); + llxFooter(); + $db->close(); + exit; +} + +if (! empty($conf->global->PAYPAL_API_SANDBOX)) +{ + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning'); +} + print ''."\n"; print '
'."\n"; print ''."\n"; @@ -359,14 +369,14 @@ if (! GETPOST("source")) $fulltag=$tag; // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -386,7 +396,7 @@ if (! GETPOST("source")) print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -424,26 +434,26 @@ if (GETPOST("source") == 'order') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='ORD='.$order->ref.'.CUS='.$order->thirdparty->id; //$fulltag.='.NAM='.strtr($order->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$order->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentOrderRef",$order->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -452,7 +462,7 @@ if (GETPOST("source") == 'order') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -472,7 +482,7 @@ if (GETPOST("source") == 'order') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -534,26 +544,26 @@ if (GETPOST("source") == 'invoice') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='INV='.$invoice->ref.'.CUS='.$invoice->thirdparty->id; //$fulltag.='.NAM='.strtr($invoice->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$invoice->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentInvoiceRef",$invoice->ref).''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -562,7 +572,7 @@ if (GETPOST("source") == 'invoice') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -582,7 +592,7 @@ if (GETPOST("source") == 'invoice') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -662,7 +672,7 @@ if (GETPOST("source") == 'contractline') { $product=new Product($db); $result=$product->fetch($contractline->fk_product); - + // We define price for product (TODO Put this in a method in product class) if (! empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -676,7 +686,7 @@ if (GETPOST("source") == 'contractline') $pu_ttc = $product->price_ttc; $price_base_type = $product->price_base_type; } - + $amount=$pu_ttc; if (empty($amount)) { @@ -697,19 +707,19 @@ if (GETPOST("source") == 'contractline') if (GETPOST('qty')) $qty=GETPOST('qty'); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("ThirdParty"); print ''.$contract->thirdparty->name.''; // Object - + $text=''.$langs->trans("PaymentRenewContractId",$contract->ref,$contractline->ref).''; if ($contractline->fk_product) { @@ -732,7 +742,7 @@ if (GETPOST("source") == 'contractline') print '
'.$langs->trans("Amount"); if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; print ''; @@ -780,7 +790,7 @@ if (GETPOST("source") == 'contractline') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; @@ -824,6 +834,7 @@ if (GETPOST("source") == 'membersubscription') require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php'; + $member=new Adherent($db); $result=$member->fetch('',$ref); if ($result < 0) @@ -842,20 +853,20 @@ if (GETPOST("source") == 'membersubscription') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='MEM='.$member->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M'); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); // Creditor - + print '
'.$langs->trans("Creditor"); print ''.$creditor.''; print ''; print '
'.$langs->trans("Member"); print ''; if ($member->morphy == 'mor' && ! empty($member->societe)) print $member->societe; @@ -863,7 +874,7 @@ if (GETPOST("source") == 'membersubscription') print ''; // Object - + $text=''.$langs->trans("PaymentSubscription").''; print '
'.$langs->trans("Designation"); print ''.$text; @@ -874,13 +885,13 @@ if (GETPOST("source") == 'membersubscription') if ($member->last_subscription_date || $member->last_subscription_amount) { // Last subscription date - + print '
'.$langs->trans("LastSubscriptionDate"); print ''.dol_print_date($member->last_subscription_date,'day'); print '
'.$langs->trans("LastSubscriptionAmount"); print ''.price($member->last_subscription_amount); print '
'.$langs->trans("Amount"); if (empty($amount)) { @@ -918,7 +929,7 @@ if (GETPOST("source") == 'membersubscription') print '
'.$langs->trans("PaymentCode"); print ''.$fulltag.''; print ''; diff --git a/htdocs/public/stripe/newpayment.php b/htdocs/public/stripe/newpayment.php index 01ae19c7032..af0c880d3c8 100644 --- a/htdocs/public/stripe/newpayment.php +++ b/htdocs/public/stripe/newpayment.php @@ -196,7 +196,7 @@ else if (! empty($conf->global->STRIPE_CREDITOR)) $creditor=$conf->global->STRIP if ($action == 'dopayment') // We click on button Create payment { if (GETPOST('newamount')) $amount = GETPOST('newamount'); - else + else { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors'); $action = ''; @@ -209,18 +209,18 @@ if ($action == 'charge') // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); if (! in_array($currency, $arrayzerounitcurrency)) $amount=$amount * 100; - + dol_syslog("POST keys : ".join(',', array_keys($_POST)), LOG_DEBUG, 0, '_stripe'); dol_syslog("POST values: ".join(',', $_POST), LOG_DEBUG, 0, '_stripe'); - + $stripeToken = GETPOST("stripeToken",'alpha'); $email = GETPOST("stripeEmail",'alpha'); dol_syslog("stripeToken = ".$stripeToken, LOG_DEBUG, 0, '_stripe'); dol_syslog("stripeEmail = ".$stripeEmail, LOG_DEBUG, 0, '_stripe'); - + $error = 0; - + try { dol_syslog("Create customer", LOG_DEBUG, 0, '_stripe'); $customer = \Stripe\Customer::create(array( @@ -230,7 +230,7 @@ if ($action == 'charge') 'source' => $stripeToken // source can be a token OR array('object'=>'card', 'exp_month'=>xx, 'exp_year'=>xxxx, 'number'=>xxxxxxx, 'cvc'=>xxx, 'name'=>'Cardholder's full name', zip ?) )); // TODO Add 'business_vat_id' ? - + dol_syslog("Create charge", LOG_DEBUG, 0, '_stripe'); $charge = \Stripe\Charge::create(array( 'customer' => $customer->id, @@ -244,14 +244,14 @@ if ($action == 'charge') // Since it's a decline, \Stripe\Error\Card will be caught $body = $e->getJsonBody(); $err = $body['error']; - + print('Status is:' . $e->getHttpStatus() . "\n"); print('Type is:' . $err['type'] . "\n"); print('Code is:' . $err['code'] . "\n"); // param is '' in this case print('Param is:' . $err['param'] . "\n"); print('Message is:' . $err['message'] . "\n"); - + $error++; setEventMessages($e->getMessage(), null, 'errors'); dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); @@ -295,7 +295,7 @@ if ($action == 'charge') setEventMessages($e->getMessage(), null, 'errors'); $action=''; } - + $_SESSION["onlinetoken"] = $stripeToken; $_SESSION["FinalPaymentAmt"] = $amount; $_SESSION["currencyCodeType"] = $currency; @@ -303,12 +303,12 @@ if ($action == 'charge') $_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR']; // Payer ip $_SESSION['payerID'] = is_object($customer)?$customer->id:''; $_SESSION['TRANSACTIONID'] = is_object($charge)?$charge->id:''; - + dol_syslog("Action charge stripe result=".$error." ip=".$_SESSION['ipaddress'], LOG_DEBUG, 0, '_stripe'); dol_syslog("onlinetoken=".$_SESSION["onlinetoken"]." FinalPaymentAmt=".$_SESSION["FinalPaymentAmt"]." currencyCodeType=".$_SESSION["currencyCodeType"]." payerID=".$_SESSION['payerID']." TRANSACTIONID=".$_SESSION['TRANSACTIONID'], LOG_DEBUG, 0, '_stripe'); dol_syslog("FULLTAG=".$FULLTAG, LOG_DEBUG, 0, '_stripe'); dol_syslog("Now call the redirect to paymentok or paymentko", LOG_DEBUG, 0, '_stripe'); - + if ($error) { header("Location: ".$urlko); @@ -319,7 +319,7 @@ if ($action == 'charge') header("Location: ".$urlok); exit; } - + } @@ -335,6 +335,16 @@ $conf->dol_hide_leftmenu=1; llxHeader($head, $langs->trans("PaymentForm"), '', '', 0, 0, '', '', '', 'onlinepaymentbody'); +// Check link validity +if (! empty($SOURCE) && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', ''))) +{ + $langs->load("errors"); + dol_print_error_email('BADREFINPAYMENTFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $SOURCE, $ref)); + llxFooter(); + $db->close(); + exit; +} + if (empty($conf->global->STRIPE_LIVE)) { dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning'); @@ -420,7 +430,7 @@ if (! GETPOST("source")) $found=true; $tag=GETPOST("tag"); $fulltag=$tag; - + // Creditor print '
'.$langs->trans("Creditor"); print ''.$creditor.''; @@ -485,7 +495,7 @@ if (GETPOST("source") == 'order') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='ORD='.$order->ref.'.CUS='.$order->thirdparty->id; //$fulltag.='.NAM='.strtr($order->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } @@ -600,7 +610,7 @@ if (GETPOST("source") == 'invoice') //$fulltag.='.NAM='.strtr($invoice->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); - + // Creditor print '
'.$langs->trans("Creditor"); @@ -723,7 +733,7 @@ if (GETPOST("source") == 'contractline') { $product=new Product($db); $result=$product->fetch($contractline->fk_product); - + // We define price for product (TODO Put this in a method in product class) if (! empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -737,7 +747,7 @@ if (GETPOST("source") == 'contractline') $pu_ttc = $product->price_ttc; $price_base_type = $product->price_base_type; } - + $amount=$pu_ttc; if (empty($amount)) { @@ -749,7 +759,7 @@ if (GETPOST("source") == 'contractline') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='COL='.$contractline->ref.'.CON='.$contract->ref.'.CUS='.$contract->thirdparty->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M'); //$fulltag.='.NAM='.strtr($contract->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } @@ -904,7 +914,7 @@ if (GETPOST("source") == 'membersubscription') if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); $amount=price2num($amount); } - + $fulltag='MEM='.$member->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M'); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); @@ -1059,7 +1069,7 @@ if (preg_match('/^dopayment/',$action)) data-description="'.$ref.'"> '; */ - + // Personalized checkout print ''; - + print ' - +
'; @@ -1106,11 +1116,11 @@ if (preg_match('/^dopayment/',$action)) print ''; print ''."\n"; print ''."\n"; - + print '
- +
@@ -1126,22 +1136,22 @@ if (preg_match('/^dopayment/',$action))
- + - + - + '; + print ''; } From bebf2b33eaa3f4439543d012d7f9e97cb7f457cd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 09:25:35 +0200 Subject: [PATCH 24/40] CSS enhancement for mobile --- htdocs/theme/eldy/style.css.php | 9 ++++++++ htdocs/theme/md/style.css.php | 41 ++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index c66fa33dfaa..4227b86ca51 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -712,6 +712,7 @@ div.fiche>form>div.div-table-responsive { align-self: flex-start; } + /* ============================================================================== */ /* Styles to hide objects */ /* ============================================================================== */ @@ -2795,6 +2796,9 @@ div.tabBar .noborder { @media only screen and (max-width: 767px) { + .thumbstat { + flex: 1 1 110px; + } .thumbstat150 { flex: 1 1 110px; } @@ -4594,6 +4598,11 @@ div.tabsElem a.tab { background: #FFF; } + .login_vertical_align { + padding-left: 20px; + padding-right: 20px; + } + /* Reduce login top right info */ .help { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index a1851dc4a76..6e31fc3ed11 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -317,7 +317,7 @@ textarea { border-left:solid 1px rgba(0,0,0,.1); border-right:solid 1px rgba(0,0,0,.1); border-bottom:solid 1px rgba(0,0,0,.2); - + background-color: #FFF; padding:4px; margin-left:1px; @@ -867,10 +867,10 @@ div.fiche>form>div.div-table-responsive { width: 20px; object-fit: contain; } - + div.statusref { padding-right: 10px; - } + } } .linkobject { cursor: pointer; } @@ -1557,12 +1557,12 @@ foreach($mainmenuusedarray as $val) display: table; position: absolute; height: 100%; - width: 100%; + width: 100%; } .login_center { display: table-cell; vertical-align: middle; -} +} .login_vertical_align { padding: 10px; padding-bottom: 80px; @@ -1992,14 +1992,14 @@ div.tabBar { border-top: 1px solid #CCC; width: auto; background: rgb(); - border-bottom: 1px solid #aaa; + border-bottom: 1px solid #aaa; } div.tabBar div.titre { - padding-top: 10px; + padding-top: 10px; } div.tabBarWithBottom { padding-bottom: 18px; - border-bottom: 1px solid #aaa; + border-bottom: 1px solid #aaa; } div.tabBar table.tableforservicepart2:last-child { border-bottom: 1px solid #aaa; @@ -2720,7 +2720,7 @@ tr.liste_titre th, tr.liste_titre td, th.liste_titre, form.liste_titre div, div. { border-bottom: 1px solid #; } -/* TODO Once title line is moved under title search, make border bottom of all th black and force to whit when it's first tr */ +/* TODO Once title line is moved under title search, make border bottom of all th black and force to whit when it's first tr */ tr:first-child th.liste_titre { border-bottom: 1px solid #FFF ! important; } @@ -2826,7 +2826,7 @@ div .tdtop { /* Prepare to remove class pair - impair */ -.noborder > tbody > tr:nth-child(even):not(.liste_titre), .liste > tbody > tr:nth-child(even):not(.liste_titre) { +.noborder > tbody > tr:nth-child(even):not(.liste_titre), .liste > tbody > tr:nth-child(even):not(.liste_titre) { background: linear-gradient(bottom, rgb() 85%, rgb() 100%); background: -o-linear-gradient(bottom, rgb() 85%, rgb() 100%); background: -moz-linear-gradient(bottom, rgb() 85%, rgb() 100%); @@ -2852,7 +2852,7 @@ div .tdtop { /* * Boxes */ - + .ficheaddleft div.boxstats { border: none; } @@ -2866,29 +2866,32 @@ div .tdtop { text-align: center; border-radius: 2px; } -.boxstats, .boxstats130, .boxstatscontent { +.boxstats, .boxstats130, .boxstatscontent { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .boxstats { padding: 3px; - width: 105px; + width: 105px; } .boxstats130 { - width: 135px; + width: 135px; height: 48px; - padding: 3px + padding: 3px } @media only screen and (max-width: 767px) { + .thumbstat { + flex: 1 1 110px; + } .thumbstat150 { flex: 1 1 110px; } .boxstats, .boxstats130 { - width: 90px; + width: 90px; } - .dashboardlineindicator { + .dashboardlineindicator { float: left; padding-left: 5px; } @@ -2927,7 +2930,7 @@ span.dashboardlineko { padding: 1px 6px 1px 6px; background-color: #8c4446; color: #FFFFFF ! important; - border-radius: .25em; + border-radius: .25em; } .boxtable { margin-bottom: 8px !important; @@ -4047,7 +4050,7 @@ div.dataTables_length select { border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } -.select2-container-active .select2-choice, .select2-container-active .select2-choices +.select2-container-active .select2-choice, .select2-container-active .select2-choices { outline: none; border-top: none; From df883a601b53ead931a2d6187d2e1576a44d09ef Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 2 Jun 2017 12:28:50 +0200 Subject: [PATCH 25/40] FIX contratligne update --- htdocs/contrat/class/contrat.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index a97391de170..9878e08d447 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2743,6 +2743,8 @@ class ContratLigne extends CommonObjectLine if (empty($this->total_ht)) $this->total_ht = 0; if (empty($this->total_tva)) $this->total_tva = 0; if (empty($this->total_ttc)) $this->total_ttc = 0; + if (empty($this->localtax1_tx)) $this->localtax1_tx = 0; + if (empty($this->localtax2_tx)) $this->localtax2_tx = 0; // Check parameters // Put here code to add control on parameters values From 64cd1e0923755d4fddcf2c8788e2fe323f953d8d Mon Sep 17 00:00:00 2001 From: phf Date: Fri, 2 Jun 2017 12:31:03 +0200 Subject: [PATCH 26/40] Fix get extrafields value from getOptionalsFromPost give an error with chkbxlst type on propaldet for exemple --- htdocs/core/class/extrafields.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index c89fc593745..bd1daca8886 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1681,7 +1681,7 @@ class ExtraFields // Clean parameters $value_key=dol_mktime($_POST[$keysuffix."options_".$key.$keyprefix."hour"], $_POST[$keysuffix."options_".$key.$keyprefix."min"], 0, $_POST[$keysuffix."options_".$key.$keyprefix."month"], $_POST[$keysuffix."options_".$key.$keyprefix."day"], $_POST[$keysuffix."options_".$key.$keyprefix."year"]); } - else if (in_array($key_type,array('checkbox'))) + else if (in_array($key_type,array('checkbox', 'chkbxlst'))) { $value_arr=GETPOST($keysuffix."options_".$key.$keyprefix); // Make sure we get an array even if there's only one checkbox From c59d216cf5f82572f7b3a24de978dda8037845ae Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 12:27:46 +0200 Subject: [PATCH 27/40] NEW Can read time spent of others (hierarchy only or all if granted) --- htdocs/core/actions_setmoduleoptions.inc.php | 86 ------------ htdocs/core/class/html.form.class.php | 8 +- htdocs/core/class/html.formcompany.class.php | 19 +-- htdocs/core/class/html.formprojet.class.php | 52 ++++---- htdocs/core/js/timesheet.js | 4 +- htdocs/core/lib/project.lib.php | 130 +++++++++++-------- htdocs/langs/en_US/admin.lang | 2 +- htdocs/langs/en_US/projects.lang | 9 +- htdocs/projet/activity/perday.php | 100 +++++++------- htdocs/projet/activity/perweek.php | 114 ++++++++-------- htdocs/projet/card.php | 60 +++++---- htdocs/theme/eldy/style.css.php | 14 +- htdocs/theme/md/style.css.php | 9 +- 13 files changed, 269 insertions(+), 338 deletions(-) delete mode 100644 htdocs/core/actions_setmoduleoptions.inc.php diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php deleted file mode 100644 index 03b33b19eb1..00000000000 --- a/htdocs/core/actions_setmoduleoptions.inc.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * 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 . - * or see http://www.gnu.org/ - */ - -/** - * \file htdocs/core/actions_setnotes.inc.php - * \brief Code for actions on setting notes of object page - */ - - -// $action must be defined -// $_FILES may be defined -// $nomessageinsetmoduleoptions can be set to 1 - -// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') -{ - $db->begin(); - - // Process common param fields - foreach($_POST as $key => $val) - { - if (preg_match('/^param(\d*)$/', $key, $reg)) // Works for POST['param'], POST['param1'], POST['param2'], ... - { - $param=GETPOST("param".$reg[1],'alpha'); - $value=GETPOST("value".$reg[1],'alpha'); - if ($param) - { - $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - } - } - } - - // Process upload fields - if (GETPOST('upload','alpha') && GETPOST('keyforuploaddir','aZ09')) - { - include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - $keyforuploaddir=GETPOST('keyforuploaddir','aZ09'); - $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->$keyforuploaddir))); - foreach($listofdir as $key=>$tmpdir) - { - $tmpdir=trim($tmpdir); - $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); - if (! $tmpdir) { - unset($listofdir[$key]); continue; - } - if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0); - else - { - $upload_dir=$tmpdir; - } - } - if ($upload_dir) - { - $result = dol_add_file_process($upload_dir, 0, 1, 'uploadfile', ''); - if ($result <= 0) $error++; - } - } - - if (! $error) - { - $db->commit(); - if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } - else - { - $db->rollback(); - if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupNotSaved"), null, 'errors'); - } -} - diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index cf6ae18f568..34693cba67a 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1391,7 +1391,7 @@ class Form * @deprecated * @see select_dolusers() */ - function select_users($selected='',$htmlname='userid',$show_empty=0,$exclude='',$disabled=0,$include='',$enableonly='',$force_entity=0) + function select_users($selected='',$htmlname='userid',$show_empty=0,$exclude=null,$disabled=0,$include='',$enableonly='',$force_entity=0) { print $this->select_dolusers($selected,$htmlname,$show_empty,$exclude,$disabled,$include,$enableonly,$force_entity); } @@ -1411,13 +1411,13 @@ class Form * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request * @param integer $show_every 0=default list, 1=add also a value "Everybody" at beginning of list - * @param string $enableonlytext If option $enableonly is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty. + * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty. * @param string $morecss More css * @param int $noactive Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on). * @return string HTML select string * @see select_dolgroups */ - function select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $noactive=0) + function select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $noactive=0) { global $conf,$user,$langs; @@ -1613,7 +1613,7 @@ class Form * @return string HTML select string * @see select_dolgroups */ - function select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='') + function select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='') { global $conf,$user,$langs; diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index bcff0981a70..88ebb816a31 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -358,7 +358,7 @@ class FormCompany * * @param string $selected Title preselected * @param string $htmlname Name of HTML select combo field - * @param string $morecss Add more css on SELECT element + * @param string $morecss Add more css on SELECT element * @return string String with HTML select */ function select_civility($selected='',$htmlname='civility_id',$morecss='maxwidth100') @@ -563,11 +563,11 @@ class FormCompany $events=array(); // Add an entry 'method' to say 'yes, we must execute url with param action = method'; // Add an entry 'url' to say which url to execute - // Add an entry htmlname to say which element we must change once url is called - // Add entry params => array('cssid' => 'attr') to say to remov or add attribute attr if answer of url return 0 or >0 lines + // Add an entry htmlname to say which element we must change once url is called + // Add entry params => array('cssid' => 'attr') to say to remov or add attribute attr if answer of url return 0 or >0 lines // To refresh contacts list on thirdparty list change $events[]=array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php',1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled')); - + if (count($events)) // If there is some ajax events to run once selection is done, we add code here to run events { print ''; } -elseif ($object->id > 0) +elseif ($object->id > 0) { /* * Show or edit */ - + $res=$object->fetch_optionals($object->id,$extralabels); // To verify role of users @@ -711,10 +711,11 @@ elseif ($object->id > 0) print ''; $head=project_prepare_head($object); - dol_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public?'projectpub':'project')); if ($action == 'edit' && $userWrite > 0) { + dol_fiche_head($head, 'project', $langs->trans("Project"), 0, ($object->public?'projectpub':'project')); + print ''; // Ref @@ -835,27 +836,30 @@ elseif ($object->id > 0) } else { + dol_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public?'projectpub':'project')); + // Project card - + $linkback = ''.$langs->trans("BackToList").''; - + $morehtmlref='
'; // Title $morehtmlref.=$object->title; // Thirdparty - if ($object->thirdparty->id > 0) + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : '; + if ($object->thirdparty->id > 0) { - $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1, 'project'); + $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project'); } $morehtmlref.='
'; - + // Define a complementary filter for search of next/prev ref. if (! $user->rights->projet->all->lire) { $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0); $object->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")"; } - + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); @@ -889,7 +893,7 @@ elseif ($object->id > 0) if (strcmp($object->opp_amount,'')) print price($object->opp_amount,0,$langs,1,0,0,$conf->currency); print ''; } - + // Date start - end print ''; - + // Budget print '
'.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").''; $start = dol_print_date($object->date_start,'dayhour'); @@ -899,7 +903,7 @@ elseif ($object->id > 0) print ($end?$end:'?'); if ($object->hasDelay()) print img_warning("Late"); print '
'.$langs->trans("Budget").''; if (strcmp($object->budget_amount, '')) print price($object->budget_amount,0,$langs,1,0,0,$conf->currency); @@ -908,16 +912,16 @@ elseif ($object->id > 0) // Other attributes $cols = 2; include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; - + print '
'; - + print ''; print '
'; print '
'; print '
'; - + print ''; - + // Description print '"; } - + print '
'.$langs->trans("Description").''; print nl2br($object->description); @@ -929,13 +933,13 @@ elseif ($object->id > 0) print $form->showCategories($object->id,'project',1); print "
'; - + print '
'; print '
'; print ''; - + print '
'; } @@ -956,7 +960,7 @@ elseif ($object->id > 0) { $defaultcheckedwhenoppclose=1; if (empty($conf->global->PROJECT_HIDE_TASKS)) $defaultcheckedwhenoppclose=0; - + print ''; print ''; + + // Loan card - + $linkback = '' . $langs->trans("BackToList") . ''; - + $morehtmlref='
'; // Ref loan $morehtmlref.=$form->editfieldkey("Label", 'label', $object->label, $object, $user->rights->loan->write, 'string', '', 0, 1); @@ -458,7 +470,7 @@ if ($id > 0) } } $morehtmlref.='
'; - + $object->totalpaid = $totalpaid; // To give a chance to dol_banner_tab to use already paid amount to show correct status dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlright); @@ -652,7 +664,7 @@ if ($id > 0) while ($i < $num) { $objp = $db->fetch_object($resql); - + print '
'.img_object($langs->trans("Payment"),"payment").' '.$objp->rowid.''.dol_print_date($db->jdate($objp->dp),'day')."
'; +print ''; +print '"; +print ''; + +print ''; +Print ''; +Print ''; +Print ''; +Print ''; +Print ''; +print ''; + +if ($object->nbterm > 0 && count($echeance->lines)==0) +{ + $i=1; + $capital = $object->capital; + while($i <$object->nbterm+1){ + $mens = round($echeance->calc_mens($capital, $object->rate/100, $object->nbterm-$i+1),2,PHP_ROUND_HALF_UP); + $int = ($capital*($object->rate/12))/100; + $int = round($int ,2,PHP_ROUND_HALF_UP); + $cap_rest = round($capital - ($mens-$int),2,PHP_ROUND_HALF_UP); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $i++; + $capital = $cap_rest; + } +}elseif(count($echeance->lines)>0){ + $i=1; + $capital = $object->capital; + foreach ($echeance->lines as $line){ + $mens = $line->amount_capital+$line->amount_insurance+$line->amount_interest; + $int = $line->amount_interest; + $cap_rest = round($capital - ($mens-$int),2,PHP_ROUND_HALF_UP); + print ''; + print ''; + print ''; + if($line->datep > dol_now()){ + print ''; + }else{ + print ''; + } + print ''; + print ''; + print ''; + $i++; + $capital = $cap_rest; + } +} + +print '
' . "Création d'échéancier
Echéance Date Montant Intérêts Capital restant du
' . $i .'' . dol_print_date(dol_time_plus_duree($object->datestart, $i-1, 'm'),'day') . ''.price($int,0,'',1).' €'.price($cap_rest).' €
' . $i .'' . dol_print_date($line->datep,'day') . '' . price($mens) . ' €'.price($int,0,'',1).' €'.price($cap_rest).' €
'; +print '
'; +print '
'; +print '
'; +print ''; + +llxFooter(); +$db->close(); + + + From 1761df2bc243ec9f333f38195ece72c533f83553 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 19:28:22 +0200 Subject: [PATCH 30/40] NEW Add page statistics for project tasks --- htdocs/core/menus/init_menu_auguria.sql | 1 + htdocs/core/menus/standard/eldy.lib.php | 45 +-- htdocs/langs/en_US/projects.lang | 3 + htdocs/projet/class/taskstats.class.php | 471 ++++++++++++++++++++++++ htdocs/projet/tasks/stats/index.php | 218 +++++++++++ 5 files changed, 716 insertions(+), 22 deletions(-) create mode 100644 htdocs/projet/class/taskstats.class.php create mode 100644 htdocs/projet/tasks/stats/index.php diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 9106c345fda..7a60f330727 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -288,6 +288,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->projet->enabled', __HANDLER__, 'left', 3701__+MAX_llx_menu__, 'project', '', 3700__+MAX_llx_menu__, '/projet/tasks.php?leftmenu=projects&action=create', 'NewTask', 1, 'projects', '$user->rights->projet->creer', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->projet->enabled', __HANDLER__, 'left', 3702__+MAX_llx_menu__, 'project', '', 3700__+MAX_llx_menu__, '/projet/tasks/list.php?leftmenu=projects', 'List', 1, 'projects', '$user->rights->projet->lire', '', 2, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->projet->enabled', __HANDLER__, 'left', 3703__+MAX_llx_menu__, 'project', '', 3700__+MAX_llx_menu__, '/projet/activity/perweek.php?leftmenu=projects', 'NewTimeSpent', 1, 'projects', '$user->rights->projet->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->projet->enabled', __HANDLER__, 'left', 3704__+MAX_llx_menu__, 'project', '', 3600__+MAX_llx_menu__, '/projet/tasks/stats/index.php?leftmenu=projects', 'Statistics', 1, 'projects', '$user->rights->projet->lire', '', 2, 4, __ENTITY__); -- Project - Categories insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->categorie->enabled', __HANDLER__, 'left', 3804__+MAX_llx_menu__, 'project', 'cat', 3__+MAX_llx_menu__, '/categories/index.php?leftmenu=cat&type=6', 'Categories', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 6248f294476..38a9a66a137 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -52,7 +52,7 @@ function print_eldy_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0,$mode if (empty($noout)) print_start_menu_array(); $usemenuhider = (GETPOST('testmenuhider','int') || ! empty($conf->global->MAIN_TESTMENUHIDER)); - + // Show/Hide vertical menu if ($mode != 'jmobile' && $mode != 'topnb' && $usemenuhider && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { @@ -437,7 +437,7 @@ function print_end_menu_array() /** * Core function to output left menu eldy * Fill &$menu (example with $forcemainmenu='home' $forceleftmenu='all', return left menu tree of Home) - * + * * @param DoliDB $db Database handler * @param array $menu_array_before Table of menu entries to show before entries of menu handler (menu->liste filled with menu->add) * @param array $menu_array_after Table of menu entries to show after entries of menu handler (menu->liste filled with menu->add) @@ -445,7 +445,7 @@ function print_end_menu_array() * @param Menu $menu Object Menu to return back list of menu entries * @param int $noout Disable output (Initialise &$menu only). * @param string $forcemainmenu 'x'=Force mainmenu to mainmenu='x' - * @param string $forceleftmenu 'all'=Force leftmenu to '' (= all). If value come being '', we change it to value in session and 'none' if not efined in session. + * @param string $forceleftmenu 'all'=Force leftmenu to '' (= all). If value come being '', we change it to value in session and 'none' if not efined in session. * @param array $moredata An array with more data to output * @return int nb of menu entries */ @@ -459,7 +459,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $leftmenu=($forceleftmenu?'':(empty($_SESSION["leftmenu"])?'none':$_SESSION["leftmenu"])); $usemenuhider = (GETPOST('testmenuhider','int') || ! empty($conf->global->MAIN_TESTMENUHIDER)); - + // Show logo company if (empty($conf->global->MAIN_MENU_INVERT) && empty($noout) && ! empty($conf->global->MAIN_SHOW_LOGO) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { @@ -503,7 +503,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu print '
'."\n"; print "\n"; } - + /** * We update newmenu with entries found into database * -------------------------------------------------- @@ -605,7 +605,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/user/group/index.php?leftmenu=users", $langs->trans("ListOfGroups"), 2, ($conf->global->MAIN_USE_ADVANCED_PERMS?$user->rights->user->group_advance->read:$user->rights->user->user->lire) || $user->admin); } } - + } @@ -839,7 +839,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu } $newmenu->add("/fourn/facture/paiement.php", $langs->trans("Payments"),1,$user->rights->fournisseur->facture->lire); - + $newmenu->add("/fourn/facture/rapport.php",$langs->trans("Reportings"),2,$user->rights->fournisseur->facture->lire); $newmenu->add("/compta/facture/stats/index.php?mode=supplier", $langs->trans("Statistics"),1,$user->rights->fournisseur->facture->lire); @@ -957,29 +957,29 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/accountancy/admin/account.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("Chartofaccounts"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_chart', 30); if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/accountancy/admin/categories_list.php?id=32&search_country_id=".$mysoc->country_id."&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("AccountingCategory"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_chart', 31); if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/accountancy/admin/defaultaccounts.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuDefaultAccounts"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_default', 40); - if (! empty($conf->facture->enabled) || ! empty($conf->fournisseur->enabled)) + if (! empty($conf->facture->enabled) || ! empty($conf->fournisseur->enabled)) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/admin/dict.php?id=10&from=accountancy&search_country_id=".$mysoc->country_id."&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuVatAccounts"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_default', 50); } - if (! empty($conf->tax->enabled)) + if (! empty($conf->tax->enabled)) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/admin/dict.php?id=7&from=accountancy&search_country_id=".$mysoc->country_id."&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuTaxAccounts"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_default', 50); } - if (! empty($conf->expensereport->enabled)) + if (! empty($conf->expensereport->enabled)) { if (preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/admin/dict.php?id=17&from=accountancy&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuExpenseReportAccounts"),2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_default', 50); } /* not required yet, already supported by default account - if (! empty($conf->loan->enabled)) + if (! empty($conf->loan->enabled)) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/admin/loan.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuLoanAccounts"), 2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_loan', 45); } - if (! empty($conf->don->enabled)) + if (! empty($conf->don->enabled)) { if (preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/don/admin/donation.php?from=accountancy&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuDonationAccounts"), 2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_donation', 47); }*/ if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/',$leftmenu)) $newmenu->add("/accountancy/admin/productaccount.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuProductsAccounts"), 2, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_product', 60); - + // Binding if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy/',$leftmenu)) $newmenu->add("/accountancy/customer/index.php?leftmenu=accountancy_dispatch_customer&mainmenu=accountancy",$langs->trans("CustomersVentilation"),1,$user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_customer'); if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_customer/',$leftmenu)) $newmenu->add("/accountancy/customer/list.php?mainmenu=accountancy&leftmenu=accountancy_dispatch_customer",$langs->trans("ToBind"),2,$user->rights->accounting->bind->write); @@ -1023,19 +1023,19 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $objp = $db->fetch_object($resql); $nature=''; - // Must match array $sourceList defined into journals_list.php + // Must match array $sourceList defined into journals_list.php if ($objp->nature == 2) $nature="sells"; if ($objp->nature == 3) $nature="purchases"; if ($objp->nature == 4) $nature="bank"; if ($objp->nature == 1) $nature="various"; if ($objp->nature == 9) $nature="hasnew"; - + // To enable when page exists if (empty($conf->global->MAIN_FEATURES_LEVEL)) { - if ($nature == 'various' || $nature == 'hasnew') $nature=''; + if ($nature == 'various' || $nature == 'hasnew') $nature=''; } - + if ($nature) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy/',$leftmenu)) $newmenu->add('/accountancy/journal/'.$nature.'journal.php?mainmenu=accountancy&leftmenu=accountancy_journal&code_journal='.$objp->code,dol_trunc($objp->label,25),2,$user->rights->accounting->comptarapport->lire); @@ -1275,7 +1275,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/product/inventory/list.php", $langs->trans("List"), 1, $user->rights->stock->lire); } } - + // Expeditions if (! empty($conf->expedition->enabled)) { @@ -1299,9 +1299,9 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu if (! empty($conf->projet->enabled)) { $langs->load("projects"); - + $search_project_user = GETPOST('search_project_user','int'); - + // Project affected to user $newmenu->add("/projet/index.php?leftmenu=projects".($search_project_user?'&search_project_user='.$search_project_user:''), $langs->trans("Projects"), 0, $user->rights->projet->lire, '', $mainmenu, 'projects'); $newmenu->add("/projet/card.php?leftmenu=projects&action=create".($search_project_user?'&search_project_user='.$search_project_user:''), $langs->trans("NewProject"), 1, $user->rights->projet->creer); @@ -1314,7 +1314,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/projet/list.php?leftmenu=projects&search_status=99", $langs->trans("List"), 1, $user->rights->projet->lire && $user->rights->projet->lire); */ $newmenu->add("/projet/stats/index.php?leftmenu=projects", $langs->trans("Statistics"), 1, $user->rights->projet->lire); - + if (empty($conf->global->PROJECT_HIDE_TASKS)) { // Project affected to user @@ -1322,6 +1322,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/projet/tasks.php?leftmenu=tasks&action=create", $langs->trans("NewTask"), 1, $user->rights->projet->creer); $newmenu->add("/projet/tasks/list.php?leftmenu=tasks".($search_project_user?'&search_project_user='.$search_project_user:''), $langs->trans("List"), 1, $user->rights->projet->lire); $newmenu->add("/projet/activity/perweek.php?leftmenu=tasks".($search_project_user?'&search_project_user='.$search_project_user:''), $langs->trans("NewTimeSpent"), 1, $user->rights->projet->lire); + $newmenu->add("/projet/tasks/stats/index.php?leftmenu=projects", $langs->trans("Statistics"), 1, $user->rights->projet->lire); // All project i have permission on /*$newmenu->add("/projet/activity/index.php", $langs->trans("Activities"), 0, $user->rights->projet->lire && $user->rights->projet->lire); @@ -1445,7 +1446,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/adherents/stats/index.php?leftmenu=members",$langs->trans("MenuMembersStats"),1,$user->rights->adherent->lire); if (! empty($conf->global->MEMBER_LINK_TO_HTPASSWDFILE) && ($usemenuhider || empty($leftmenu) || $leftmenu=="export")) $newmenu->add("/adherents/htpasswd.php?leftmenu=export",$langs->trans("Filehtpasswd"),1,$user->rights->adherent->export); if ($usemenuhider || empty($leftmenu) || $leftmenu=="export") $newmenu->add("/adherents/cartes/carte.php?leftmenu=export",$langs->trans("MembersCards"),1,$user->rights->adherent->export); - + $newmenu->add("/adherents/index.php?leftmenu=members&mainmenu=members",$langs->trans("Subscriptions"),0,$user->rights->adherent->cotisation->lire); $newmenu->add("/adherents/list.php?leftmenu=members&statut=-1,1&mainmenu=members",$langs->trans("NewSubscription"),1,$user->rights->adherent->cotisation->creer); $newmenu->add("/adherents/subscription/list.php?leftmenu=members",$langs->trans("List"),1,$user->rights->adherent->cotisation->lire); diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 3b4e4f4d14f..b3317df9c8e 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -41,6 +41,7 @@ ShowProject=Show project SetProject=Set project NoProject=No project defined or owned NbOfProjects=Nb of projects +NbOfTasks=Nb of tasks TimeSpent=Time spent TimeSpentByYou=Time spent by you TimeSpentByUser=Time spent by user @@ -181,10 +182,12 @@ ProjectOverview=Overview ManageTasks=Use projects to follow tasks and time ManageOpportunitiesStatus=Use projects to follow leads/opportinuties ProjectNbProjectByMonth=Nb of created projects by month +ProjectNbTaskByMonth=Nb of created tasks by month ProjectOppAmountOfProjectsByMonth=Amount of opportunities by month ProjectWeightedOppAmountOfProjectsByMonth=Weighted amount of opportunities by month ProjectOpenedProjectByOppStatus=Open project/lead by opportunity status ProjectsStatistics=Statistics on projects/leads +TasksStatistics=Statistics on project/lead tasks TaskAssignedToEnterTime=Task assigned. Entering time on this task should be possible. IdTaskTime=Id task time YouCanCompleteRef=If you want to complete the ref with some information (to use it as search filters), it is recommanded to add a - character to separate it, so the automatic numbering will still work correctly for next projects. For example %s-ABC. You may also prefer to add search keys into label. But best practice may be to add a dedicated field, also called complementary attributes. diff --git a/htdocs/projet/class/taskstats.class.php b/htdocs/projet/class/taskstats.class.php new file mode 100644 index 00000000000..c0a0530bc75 --- /dev/null +++ b/htdocs/projet/class/taskstats.class.php @@ -0,0 +1,471 @@ + + * + * 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 . + */ +include_once DOL_DOCUMENT_ROOT . '/core/class/stats.class.php'; +include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; + + +/** + * Class to manage statistics on project tasks + */ +class TaskStats extends Stats +{ + private $project; + public $userid; + public $socid; + public $year; + + function __construct($db) + { + global $conf, $user; + + $this->db = $db; + + require_once 'task.class.php'; + $this->task = new Task($this->db); + } + + + /** + * Return all tasks grouped by status. + * + * @param int $limit Limit results + * @return array|int Array with value or -1 if error + * @throws Exception + */ + function getAllTaskByStatus($limit = 5) + { + global $conf, $user, $langs; + + $datay = array (); + + $sql = "SELECT"; + $sql .= " COUNT(t.rowid), t.priority"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + $sql .= $this->buildWhere(); + //$sql .= " AND t.fk_statut <> 0"; // We want historic also, so all task not draft + $sql .= " GROUP BY t.priority"; + + $result = array (); + $res = array (); + + dol_syslog(get_class($this) . '::' . __METHOD__ . "", LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + $other = 0; + while ( $i < $num ) { + $row = $this->db->fetch_row($resql); + if ($i < $limit || $num == $limit) + { + $result[$i] = array( + $row[1], + $row[0] + ); + } + else + $other += $row[1]; + $i++; + } + if ($num > $limit) + $result[$i] = array ( + $langs->transnoentitiesnoconv("Other"), + $other + ); + $this->db->free($resql); + } else { + $this->error = "Error " . $this->db->lasterror(); + dol_syslog(get_class($this) . '::' . __METHOD__ . ' ' . $this->error, LOG_ERR); + return -1; + } + + return $result; + } + + /** + * Return count, and sum of products + * + * @return array of values + */ + function getAllByYear() + { + global $conf, $user, $langs; + + $datay = array (); + + $wonlostfilter=0; // No filter on status WON/LOST + + $sql = "SELECT date_format(t.datec,'%Y') as year, COUNT(t.rowid) as nb"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql.= $this->buildWhere(); + $sql.= " GROUP BY year"; + $sql.= $this->db->order('year', 'DESC'); + + return $this->_getAllByYear($sql); + } + + + /** + * Build the where part + * + * @return string + */ + public function buildWhere() + { + $sqlwhere_str = ''; + $sqlwhere = array(); + + $sqlwhere[] = ' t.entity IN (' . getEntity('project') . ')'; + + if (! empty($this->userid)) + $sqlwhere[] = ' t.fk_user_resp=' . $this->userid; + if (! empty($this->socid)) + $sqlwhere[] = ' t.fk_soc=' . $this->socid; + if (! empty($this->year) && empty($this->yearmonth)) + $sqlwhere[] = " date_format(t.datec,'%Y')='" . $this->db->escape($this->year) . "'"; + if (! empty($this->yearmonth)) + $sqlwhere[] = " t.datec BETWEEN '" . $this->db->idate(dol_get_first_day($this->yearmonth)) . "' AND '" . $this->db->idate(dol_get_last_day($this->yearmonth)) . "'"; + + if (! empty($this->status)) + $sqlwhere[] = " t.priority IN (" . $this->priority . ")"; + + if (count($sqlwhere) > 0) { + $sqlwhere_str = ' WHERE ' . implode(' AND ', $sqlwhere); + } + + return $sqlwhere_str; + } + + /** + * Return Task number by month for a year + * + * @param int $year scan + * @return array of values + */ + function getNbByMonth($year) + { + global $user; + + $this->yearmonth = $year; + + $sql = "SELECT date_format(t.datec,'%m') as dm, COUNT(t.rowid) as nb"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= $this->buildWhere(); + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + $this->yearmonth=0; + + $res = $this->_getNbByMonth($year, $sql); + // var_dump($res);print '
'; + return $res; + } + + /** + * Return the Task amount by month for a year + * + * @param int $year scan + * @return array with amount by month + */ + /* + function getAmountByMonth($year) + { + global $user; + + $this->yearmonth = $year; + + $sql = "SELECT date_format(t.datec,'%m') as dm, COUNT(t.rowid)"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= $this->buildWhere(); + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + $this->yearmonth=0; + + $res = $this->_getAmountByMonth($year, $sql); + // var_dump($res);print '
'; + return $res; + }*/ + + + /** + * Return amount of elements by month for several years + * + * @param int $endyear Start year + * @param int $startyear End year + * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) + * @param int $wonlostfilter Add a filter on status won/lost + * @return array Array of values + */ + /* + function getWeightedAmountByMonthWithPrevYear($endyear,$startyear,$cachedelay=0,$wonlostfilter=1) + { + global $conf,$user,$langs; + + if ($startyear > $endyear) return -1; + + $datay=array(); + + // Search into cache + if (! empty($cachedelay)) + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; + } + + $newpathofdestfile=$conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix)?'':$this->cachefilesuffix.'_').$langs->defaultlang.'_user'.$user->id.'.cache'; + $newmask='0644'; + + $nowgmt = dol_now(); + + $foundintocache=0; + if ($cachedelay > 0) + { + $filedate=dol_filemtime($newpathofdestfile); + if ($filedate >= ($nowgmt - $cachedelay)) + { + $foundintocache=1; + + $this->_lastfetchdate[get_class($this).'_'.__FUNCTION__]=$filedate; + } + else + { + dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it."); + } + } + + // Load file into $data + if ($foundintocache) // Cache file found and is not too old + { + dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate."."); + $data = json_decode(file_get_contents($newpathofdestfile), true); + } + else + { + $year=$startyear; + while($year <= $endyear) + { + $datay[$year] = $this->getWeightedAmountByMonth($year,$wonlostfilter); + $year++; + } + + $data = array(); + // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...) + for ($i = 0 ; $i < 12 ; $i++) + { + $data[$i][]=$datay[$endyear][$i][0]; // set label + $year=$startyear; + while($year <= $endyear) + { + $data[$i][]=$datay[$year][$i][1]; // set yval for x=i + $year++; + } + } + } + + // Save cache file + if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1)) + { + dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk."); + if (! dol_is_dir($conf->user->dir_temp)) dol_mkdir($conf->user->dir_temp); + $fp = fopen($newpathofdestfile, 'w'); + if ($fp) + { + fwrite($fp, json_encode($data)); + fclose($fp); + if (! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK; + @chmod($newpathofdestfile, octdec($newmask)); + } + else dol_syslog("Failed to write cache file", LOG_ERR); + $this->_lastfetchdate[get_class($this).'_'.__FUNCTION__]=$nowgmt; + } + + return $data; + } + */ + + + /** + * Return the Task weighted opp amount by month for a year. + * + * @param int $year Year to scan + * @param int $wonlostfilter Add a filter on status won/lost + * @return array Array with amount by month + */ + /* + function getWeightedAmountByMonth($year, $wonlostfilter=1) + { + global $user; + + $this->yearmonth = $year; + + $sql = "SELECT date_format(t.datec,'%m') as dm"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= $this->buildWhere(); + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + $this->yearmonth=0; + + $res = $this->_getAmountByMonth($year, $sql); + // var_dump($res);print '
'; + return $res; + }*/ + + /** + * Return amount of elements by month for several years + * + * @param int $endyear End year + * @param int $startyear Start year + * @param int $cachedelay accept for cache file (0=No read, no save of cache, -1=No read but save) + * @return array of values + */ + /* + function getTransformRateByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0) + { + global $conf, $user, $langs; + + if ($startyear > $endyear) return - 1; + + $datay = array(); + + // Search into cache + if (! empty($cachedelay)) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + include_once DOL_DOCUMENT_ROOT . '/core/lib/json.lib.php'; + } + + $newpathofdestfile = $conf->user->dir_temp . '/' . get_class($this) . '_' . __FUNCTION__ . '_' . (empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix . '_') . $langs->defaultlang . '_user' . $user->id . '.cache'; + $newmask = '0644'; + + $nowgmt = dol_now(); + + $foundintocache = 0; + if ($cachedelay > 0) { + $filedate = dol_filemtime($newpathofdestfile); + if ($filedate >= ($nowgmt - $cachedelay)) { + $foundintocache = 1; + + $this->_lastfetchdate[get_class($this) . '_' . __FUNCTION__] = $filedate; + } else { + dol_syslog(get_class($this) . '::' . __FUNCTION__ . " cache file " . $newpathofdestfile . " is not found or older than now - cachedelay (" . $nowgmt . " - " . $cachedelay . ") so we can't use it."); + } + } + + // Load file into $data + if ($foundintocache) // Cache file found and is not too old + { + dol_syslog(get_class($this) . '::' . __FUNCTION__ . " read data from cache file " . $newpathofdestfile . " " . $filedate . "."); + $data = json_decode(file_get_contents($newpathofdestfile), true); + } else { + $year = $startyear; + while ( $year <= $endyear ) { + $datay[$year] = $this->getTransformRateByMonth($year); + $year ++; + } + + $data = array (); + // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...) + for($i = 0; $i < 12; $i ++) { + $data[$i][] = $datay[$endyear][$i][0]; // set label + $year = $startyear; + while ( $year <= $endyear ) { + $data[$i][] = $datay[$year][$i][1]; // set yval for x=i + $year ++; + } + } + } + + // Save cache file + if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == - 1)) { + dol_syslog(get_class($this) . '::' . __FUNCTION__ . " save cache file " . $newpathofdestfile . " onto disk."); + if (! dol_is_dir($conf->user->dir_temp)) + dol_mkdir($conf->user->dir_temp); + $fp = fopen($newpathofdestfile, 'w'); + fwrite($fp, json_encode($data)); + fclose($fp); + if (! empty($conf->global->MAIN_UMASK)) + $newmask = $conf->global->MAIN_UMASK; + @chmod($newpathofdestfile, octdec($newmask)); + + $this->_lastfetchdate[get_class($this) . '_' . __FUNCTION__] = $nowgmt; + } + + return $data; + }*/ + + /** + * Return the Task transformation rate by month for a year + * + * @param int $year scan + * @return array with amount by month + */ + /* + function getTransformRateByMonth($year) + { + global $user; + + $this->yearmonth = $year; + + $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.rowid)"; + $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= $this->buildWhere(); + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + $res_total = $this->_getNbByMonth($year, $sql); + + $this->status=6; + + $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.rowid)"; + $sql .= " FROM " . MAIN_DB_PREFIX . "projet_task as t"; + if (! $user->rights->societe->client->voir && ! $user->societe_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= $this->buildWhere(); + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + $this->status=0; + $this->yearmonth=0; + + $res_only_wined = $this->_getNbByMonth($year, $sql); + + $res=array(); + + foreach($res_total as $key=>$total_row) { + //var_dump($total_row); + if (!empty($total_row[1])) { + $res[$key]=array($total_row[0],(100*$res_only_wined[$key][1])/$total_row[1]); + } else { + $res[$key]=array($total_row[0],0); + } + + } + // var_dump($res);print '
'; + return $res; + }*/ +} diff --git a/htdocs/projet/tasks/stats/index.php b/htdocs/projet/tasks/stats/index.php new file mode 100644 index 00000000000..b03d01a8006 --- /dev/null +++ b/htdocs/projet/tasks/stats/index.php @@ -0,0 +1,218 @@ + + * Copyright (C) 2015 Laurent Destailleur + * + * 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/projet/tasks/stats/index.php + * \ingroup project + * \brief Page for tasks statistics + */ + +require '../../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/taskstats.class.php'; + +// Security check +if (! $user->rights->projet->lire) + accessforbidden(); + + +$WIDTH=DolGraph::getDefaultGraphSizeForStats('width'); +$HEIGHT=DolGraph::getDefaultGraphSizeForStats('height'); + +$userid=GETPOST('userid','int'); +$socid=GETPOST('socid','int'); +// Security check +if ($user->societe_id > 0) +{ + $action = ''; + $socid = $user->societe_id; +} +$nowyear=strftime("%Y", dol_now()); +$year = GETPOST('year')>0?GETPOST('year'):$nowyear; +//$startyear=$year-2; +$startyear=$year-1; +$endyear=$year; + +$langs->load('companies'); +$langs->load('projects'); + + +/* + * View + */ + +$form=new Form($db); + +$includeuserlist=array(); + + +llxHeader('', $langs->trans('Tasks')); + +$title=$langs->trans("TasksStatistics"); +$dir=$conf->projet->dir_output.'/temp'; + +print load_fiche_titre($title,'','title_project.png'); + +dol_mkdir($dir); + + +$stats_tasks= new TaskStats($db); +if (!empty($userid) && $userid!=-1) $stats_tasks->userid=$userid; +if (!empty($socid) && $socid!=-1) $stats_tasks->socid=$socid; +if (!empty($year)) $stats_tasks->year=$year; + + + +// Build graphic number of object +// $data = array(array('Lib',val1,val2,val3),...) +$data = $stats_tasks->getNbByMonthWithPrevYear($endyear,$startyear); +//var_dump($data); + +$filenamenb = $conf->project->dir_output . "/stats/tasknbprevyear-".$year.".png"; +$fileurlnb = DOL_URL_ROOT . '/viewimage.php?modulepart=taskstats&file=tasknbprevyear-'.$year.'.png'; + +$px1 = new DolGraph(); +$mesg = $px1->isGraphKo(); +if (! $mesg) +{ + $px1->SetData($data); + $px1->SetPrecisionY(0); + $i=$startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px1->SetLegend($legend); + $px1->SetMaxValue($px1->GetCeilMaxValue()); + $px1->SetWidth($WIDTH); + $px1->SetHeight($HEIGHT); + $px1->SetYLabel($langs->trans("ProjectNbTask")); + $px1->SetShading(3); + $px1->SetHorizTickIncrement(1); + $px1->SetPrecisionY(0); + $px1->mode='depth'; + $px1->SetTitle($langs->trans("ProjectNbTaskByMonth")); + + $px1->draw($filenamenb,$fileurlnb); +} + + +// Show array +$stats_tasks->year=0; +$data_all_year = $stats_tasks->getAllByYear(); + +if (!empty($year)) $stats_tasks->year=$year; +$arrayyears=array(); +foreach($data_all_year as $val) { + $arrayyears[$val['year']]=$val['year']; +} +if (! count($arrayyears)) $arrayyears[$nowyear]=$nowyear; + + +$h=0; +$head = array(); +$head[$h][0] = DOL_URL_ROOT . '/projet/tasks/stats/index.php?mode='.$mode; +$head[$h][1] = $langs->trans("ByMonthYear"); +$head[$h][2] = 'byyear'; +$h++; + +complete_head_from_modules($conf,$langs,null,$head,$h,$type); + +dol_fiche_head($head,'byyear',$langs->trans("Statistics"), -1, ''); + + +print '
'; + +print '
'; + +print ''; +print ''; +// Company +/*print ''; +*/ +// User +/*print '';*/ +// Year +print ''; +print ''; +print '
'.$langs->trans("Filter").'
'.$langs->trans("ThirdParty").''; +if ($mode == 'customer') $filter='s.client in (1,2,3)'; +if ($mode == 'supplier') $filter='s.fournisseur = 1'; +print $form->select_company($socid,'socid',$filter,1,0,0,array(),0,'','style="width: 95%"'); +print '
'.$langs->trans("ProjectCommercial").''; +print $form->select_dolusers($userid, 'userid', 1, array(),0,$includeuserlist); +print '
'.$langs->trans("Year").''; +if (! in_array($year,$arrayyears)) $arrayyears[$year]=$year; +if (! in_array($nowyear,$arrayyears)) $arrayyears[$nowyear]=$nowyear; +arsort($arrayyears); +print $form->selectarray('year',$arrayyears,$year,0); +print '
'; +print '
'; +print '

'; + +print ''; +print ''; +print ''; +print ''; +print ''; + +$oldyear=0; +$var=true; +foreach ($data_all_year as $val) +{ + $year = $val['year']; + while ($year && $oldyear > $year+1) + { // If we have empty year + $oldyear--; + + print ''; + print ''; + print ''; + print ''; + } + + print ''; + print ''; + print ''; + print ''; + $oldyear=$year; +} + +print '
'.$langs->trans("Year").''.$langs->trans("NbOfTasks").'
0?'&userid='.$userid:'').'">'.$oldyear.'0
0?'&userid='.$userid:'').'">'.$year.''.$val['nb'].'
'; + +print '
'; + +$stringtoshow.= '
'; +if ($mesg) { print $mesg; } +else { + $stringtoshow.= $px1->show(); + $stringtoshow.= "
\n"; +} +$stringtoshow.= '
'; + +print $stringtoshow; + + +print '
'; +print '
'; + + +llxFooter(); +$db->close(); From bfa50b8d1d8574151d9bdac304d487f84f39da0e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 19:36:03 +0200 Subject: [PATCH 31/40] Fix some security issues --- htdocs/projet/class/projectstats.class.php | 41 +-- htdocs/projet/class/taskstats.class.php | 297 +-------------------- 2 files changed, 27 insertions(+), 311 deletions(-) diff --git a/htdocs/projet/class/projectstats.class.php b/htdocs/projet/class/projectstats.class.php index 4485117fb0f..a47d28d1b43 100644 --- a/htdocs/projet/class/projectstats.class.php +++ b/htdocs/projet/class/projectstats.class.php @@ -28,8 +28,8 @@ class ProjectStats extends Stats public $userid; public $socid; public $year; - - function __construct($db) + + function __construct($db) { global $conf, $user; @@ -41,7 +41,7 @@ class ProjectStats extends Stats /** - * Return all leads grouped by status. + * Return all leads grouped by opportunity status. * Warning: There is no filter on WON/LOST because we want this for statistics. * * @param int $limit Limit results @@ -56,7 +56,10 @@ class ProjectStats extends Stats $sql = "SELECT"; $sql .= " SUM(t.opp_amount), t.fk_opp_status, cls.code, cls.label"; - $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t, ".MAIN_DB_PREFIX."c_lead_status as cls"; + $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; + if (! $user->rights->societe->client->voir && ! $user->socid) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; + $sql .= ", ".MAIN_DB_PREFIX."c_lead_status as cls"; $sql .= $this->buildWhere(); $sql .= " AND t.fk_opp_status = cls.rowid"; $sql .= " AND t.fk_statut <> 0"; // We want historic also, so all projects not draft @@ -112,11 +115,11 @@ class ProjectStats extends Stats $datay = array (); $wonlostfilter=0; // No filter on status WON/LOST - + $sql = "SELECT date_format(t.datec,'%Y') as year, COUNT(t.rowid) as nb, SUM(t.opp_amount) as total, AVG(t.opp_amount) as avg,"; $sql.= " SUM(t.opp_amount * ".$this->db->ifsql("t.opp_percent IS NULL".($wonlostfilter?" OR cls.code IN ('WON','LOST')":""), '0', 't.opp_percent')." / 100) as weighted"; $sql.= " FROM " . MAIN_DB_PREFIX . "projet as t LEFT JOIN ".MAIN_DB_PREFIX."c_lead_status as cls ON cls.rowid = t.fk_opp_status"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql.= $this->buildWhere(); $sql.= " GROUP BY year"; @@ -124,14 +127,14 @@ class ProjectStats extends Stats return $this->_getAllByYear($sql); } - - + + /** * Build the where part - * + * * @return string */ - public function buildWhere() + public function buildWhere() { $sqlwhere_str = ''; $sqlwhere = array(); @@ -163,7 +166,7 @@ class ProjectStats extends Stats * @param int $year scan * @return array of values */ - function getNbByMonth($year) + function getNbByMonth($year) { global $user; @@ -171,7 +174,7 @@ class ProjectStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, COUNT(*) as nb"; $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; @@ -190,7 +193,7 @@ class ProjectStats extends Stats * @param int $year scan * @return array with amount by month */ - function getAmountByMonth($year) + function getAmountByMonth($year) { global $user; @@ -198,7 +201,7 @@ class ProjectStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, SUM(t.opp_amount)"; $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; @@ -313,7 +316,7 @@ class ProjectStats extends Stats * @param int $wonlostfilter Add a filter on status won/lost * @return array Array with amount by month */ - function getWeightedAmountByMonth($year, $wonlostfilter=1) + function getWeightedAmountByMonth($year, $wonlostfilter=1) { global $user; @@ -321,7 +324,7 @@ class ProjectStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, SUM(t.opp_amount * ".$this->db->ifsql("t.opp_percent IS NULL".($wonlostfilter?" OR cls.code IN ('WON','LOST')":""), '0', 't.opp_percent')." / 100)"; $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t LEFT JOIN ".MAIN_DB_PREFIX.'c_lead_status as cls ON t.fk_opp_status = cls.rowid'; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; @@ -421,7 +424,7 @@ class ProjectStats extends Stats * @param int $year scan * @return array with amount by month */ - function getTransformRateByMonth($year) + function getTransformRateByMonth($year) { global $user; @@ -429,7 +432,7 @@ class ProjectStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.opp_amount)"; $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; @@ -441,7 +444,7 @@ class ProjectStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.opp_amount)"; $sql .= " FROM " . MAIN_DB_PREFIX . "projet as t"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; diff --git a/htdocs/projet/class/taskstats.class.php b/htdocs/projet/class/taskstats.class.php index c0a0530bc75..b71c88f3d6b 100644 --- a/htdocs/projet/class/taskstats.class.php +++ b/htdocs/projet/class/taskstats.class.php @@ -51,11 +51,13 @@ class TaskStats extends Stats { global $conf, $user, $langs; - $datay = array (); + $datay = array(); $sql = "SELECT"; $sql .= " COUNT(t.rowid), t.priority"; $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; + if (! $user->rights->societe->client->voir && ! $user->soc_id) + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); //$sql .= " AND t.fk_statut <> 0"; // We want historic also, so all task not draft $sql .= " GROUP BY t.priority"; @@ -112,7 +114,7 @@ class TaskStats extends Stats $sql = "SELECT date_format(t.datec,'%Y') as year, COUNT(t.rowid) as nb"; $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql.= $this->buildWhere(); $sql.= " GROUP BY year"; @@ -167,7 +169,7 @@ class TaskStats extends Stats $sql = "SELECT date_format(t.datec,'%m') as dm, COUNT(t.rowid) as nb"; $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) + if (! $user->rights->societe->client->voir && ! $user->soc_id) $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; $sql .= $this->buildWhere(); $sql .= " GROUP BY dm"; @@ -179,293 +181,4 @@ class TaskStats extends Stats // var_dump($res);print '
'; return $res; } - - /** - * Return the Task amount by month for a year - * - * @param int $year scan - * @return array with amount by month - */ - /* - function getAmountByMonth($year) - { - global $user; - - $this->yearmonth = $year; - - $sql = "SELECT date_format(t.datec,'%m') as dm, COUNT(t.rowid)"; - $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; - $sql .= $this->buildWhere(); - $sql .= " GROUP BY dm"; - $sql .= $this->db->order('dm', 'DESC'); - $this->yearmonth=0; - - $res = $this->_getAmountByMonth($year, $sql); - // var_dump($res);print '
'; - return $res; - }*/ - - - /** - * Return amount of elements by month for several years - * - * @param int $endyear Start year - * @param int $startyear End year - * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) - * @param int $wonlostfilter Add a filter on status won/lost - * @return array Array of values - */ - /* - function getWeightedAmountByMonthWithPrevYear($endyear,$startyear,$cachedelay=0,$wonlostfilter=1) - { - global $conf,$user,$langs; - - if ($startyear > $endyear) return -1; - - $datay=array(); - - // Search into cache - if (! empty($cachedelay)) - { - include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; - } - - $newpathofdestfile=$conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix)?'':$this->cachefilesuffix.'_').$langs->defaultlang.'_user'.$user->id.'.cache'; - $newmask='0644'; - - $nowgmt = dol_now(); - - $foundintocache=0; - if ($cachedelay > 0) - { - $filedate=dol_filemtime($newpathofdestfile); - if ($filedate >= ($nowgmt - $cachedelay)) - { - $foundintocache=1; - - $this->_lastfetchdate[get_class($this).'_'.__FUNCTION__]=$filedate; - } - else - { - dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it."); - } - } - - // Load file into $data - if ($foundintocache) // Cache file found and is not too old - { - dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate."."); - $data = json_decode(file_get_contents($newpathofdestfile), true); - } - else - { - $year=$startyear; - while($year <= $endyear) - { - $datay[$year] = $this->getWeightedAmountByMonth($year,$wonlostfilter); - $year++; - } - - $data = array(); - // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...) - for ($i = 0 ; $i < 12 ; $i++) - { - $data[$i][]=$datay[$endyear][$i][0]; // set label - $year=$startyear; - while($year <= $endyear) - { - $data[$i][]=$datay[$year][$i][1]; // set yval for x=i - $year++; - } - } - } - - // Save cache file - if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1)) - { - dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk."); - if (! dol_is_dir($conf->user->dir_temp)) dol_mkdir($conf->user->dir_temp); - $fp = fopen($newpathofdestfile, 'w'); - if ($fp) - { - fwrite($fp, json_encode($data)); - fclose($fp); - if (! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK; - @chmod($newpathofdestfile, octdec($newmask)); - } - else dol_syslog("Failed to write cache file", LOG_ERR); - $this->_lastfetchdate[get_class($this).'_'.__FUNCTION__]=$nowgmt; - } - - return $data; - } - */ - - - /** - * Return the Task weighted opp amount by month for a year. - * - * @param int $year Year to scan - * @param int $wonlostfilter Add a filter on status won/lost - * @return array Array with amount by month - */ - /* - function getWeightedAmountByMonth($year, $wonlostfilter=1) - { - global $user; - - $this->yearmonth = $year; - - $sql = "SELECT date_format(t.datec,'%m') as dm"; - $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; - $sql .= $this->buildWhere(); - $sql .= " GROUP BY dm"; - $sql .= $this->db->order('dm', 'DESC'); - $this->yearmonth=0; - - $res = $this->_getAmountByMonth($year, $sql); - // var_dump($res);print '
'; - return $res; - }*/ - - /** - * Return amount of elements by month for several years - * - * @param int $endyear End year - * @param int $startyear Start year - * @param int $cachedelay accept for cache file (0=No read, no save of cache, -1=No read but save) - * @return array of values - */ - /* - function getTransformRateByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0) - { - global $conf, $user, $langs; - - if ($startyear > $endyear) return - 1; - - $datay = array(); - - // Search into cache - if (! empty($cachedelay)) - { - include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; - include_once DOL_DOCUMENT_ROOT . '/core/lib/json.lib.php'; - } - - $newpathofdestfile = $conf->user->dir_temp . '/' . get_class($this) . '_' . __FUNCTION__ . '_' . (empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix . '_') . $langs->defaultlang . '_user' . $user->id . '.cache'; - $newmask = '0644'; - - $nowgmt = dol_now(); - - $foundintocache = 0; - if ($cachedelay > 0) { - $filedate = dol_filemtime($newpathofdestfile); - if ($filedate >= ($nowgmt - $cachedelay)) { - $foundintocache = 1; - - $this->_lastfetchdate[get_class($this) . '_' . __FUNCTION__] = $filedate; - } else { - dol_syslog(get_class($this) . '::' . __FUNCTION__ . " cache file " . $newpathofdestfile . " is not found or older than now - cachedelay (" . $nowgmt . " - " . $cachedelay . ") so we can't use it."); - } - } - - // Load file into $data - if ($foundintocache) // Cache file found and is not too old - { - dol_syslog(get_class($this) . '::' . __FUNCTION__ . " read data from cache file " . $newpathofdestfile . " " . $filedate . "."); - $data = json_decode(file_get_contents($newpathofdestfile), true); - } else { - $year = $startyear; - while ( $year <= $endyear ) { - $datay[$year] = $this->getTransformRateByMonth($year); - $year ++; - } - - $data = array (); - // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...) - for($i = 0; $i < 12; $i ++) { - $data[$i][] = $datay[$endyear][$i][0]; // set label - $year = $startyear; - while ( $year <= $endyear ) { - $data[$i][] = $datay[$year][$i][1]; // set yval for x=i - $year ++; - } - } - } - - // Save cache file - if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == - 1)) { - dol_syslog(get_class($this) . '::' . __FUNCTION__ . " save cache file " . $newpathofdestfile . " onto disk."); - if (! dol_is_dir($conf->user->dir_temp)) - dol_mkdir($conf->user->dir_temp); - $fp = fopen($newpathofdestfile, 'w'); - fwrite($fp, json_encode($data)); - fclose($fp); - if (! empty($conf->global->MAIN_UMASK)) - $newmask = $conf->global->MAIN_UMASK; - @chmod($newpathofdestfile, octdec($newmask)); - - $this->_lastfetchdate[get_class($this) . '_' . __FUNCTION__] = $nowgmt; - } - - return $data; - }*/ - - /** - * Return the Task transformation rate by month for a year - * - * @param int $year scan - * @return array with amount by month - */ - /* - function getTransformRateByMonth($year) - { - global $user; - - $this->yearmonth = $year; - - $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.rowid)"; - $sql.= " FROM ". MAIN_DB_PREFIX . "projet_task as t INNER JOIN " . MAIN_DB_PREFIX . "projet as p ON p.rowid = t.fk_projet"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; - $sql .= $this->buildWhere(); - $sql .= " GROUP BY dm"; - $sql .= $this->db->order('dm', 'DESC'); - - $res_total = $this->_getNbByMonth($year, $sql); - - $this->status=6; - - $sql = "SELECT date_format(t.datec,'%m') as dm, count(t.rowid)"; - $sql .= " FROM " . MAIN_DB_PREFIX . "projet_task as t"; - if (! $user->rights->societe->client->voir && ! $user->societe_id) - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as sc ON sc.fk_soc=t.fk_soc AND sc.fk_user=" . $user->id; - $sql .= $this->buildWhere(); - $sql .= " GROUP BY dm"; - $sql .= $this->db->order('dm', 'DESC'); - - $this->status=0; - $this->yearmonth=0; - - $res_only_wined = $this->_getNbByMonth($year, $sql); - - $res=array(); - - foreach($res_total as $key=>$total_row) { - //var_dump($total_row); - if (!empty($total_row[1])) { - $res[$key]=array($total_row[0],(100*$res_only_wined[$key][1])/$total_row[1]); - } else { - $res[$key]=array($total_row[0],0); - } - - } - // var_dump($res);print '
'; - return $res; - }*/ } From 9e629bdb0290561813a1ebe22d40828132301c6a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 20:01:25 +0200 Subject: [PATCH 32/40] Work on modulebuilder --- htdocs/core/class/interfaces.class.php | 14 +++++++------- htdocs/core/lib/functions.lib.php | 1 + .../modulebuilder/template/img/object_mytest.png | Bin 0 -> 360 bytes htdocs/theme/eldy/style.css.php | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 htdocs/modulebuilder/template/img/object_mytest.png diff --git a/htdocs/core/class/interfaces.class.php b/htdocs/core/class/interfaces.class.php index cd4a56f4174..625b30e3ac2 100644 --- a/htdocs/core/class/interfaces.class.php +++ b/htdocs/core/class/interfaces.class.php @@ -76,14 +76,14 @@ class Interfaces global $db; $user = new User($db); } - + $nbfile = $nbtotal = $nbok = $nbko = 0; $files = array(); $modules = array(); $orders = array(); $i=0; - + $dirtriggers=array_merge(array('/core/triggers'),$conf->modules_parts['triggers']); foreach($dirtriggers as $reldir) { @@ -106,7 +106,7 @@ class Interfaces $part3=$reg[3]; $nbfile++; - + // Check if trigger file is disabled by name if (preg_match('/NORUN$/i',$file)) continue; // Check if trigger file is for a particular module @@ -132,7 +132,7 @@ class Interfaces dol_syslog(get_class($this)."::run_triggers action=".$action." ".$langs->trans("ErrorDuplicateTrigger", $newdir."/".$file, $fullpathfiles[$modName]), LOG_WARNING); continue; } - + try { //print 'Todo for '.$modName." : ".$newdir.'/'.$file."\n"; include_once $newdir.'/'.$file; @@ -142,7 +142,7 @@ class Interfaces { dol_syslog('ko for '.$modName." ".$e->getMessage()."\n", LOG_ERR); } - + $modules[$i] = $modName; $files[$i] = $file; $fullpathfiles[$modName] = $newdir.'/'.$file; @@ -155,7 +155,7 @@ class Interfaces } asort($orders); - + // Loop on each trigger foreach ($orders as $key => $value) { @@ -246,7 +246,7 @@ class Interfaces { $dirtriggers=$forcedirtriggers; } - + foreach($dirtriggers as $reldir) { $dir=dol_buildpath($reldir,0); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ef03b0c00cc..3569cdd006d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2556,6 +2556,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $picto = $regs[1]; $path = $regs[2]; // $path is $mymodule } + // Clean parameters if (! preg_match('/(\.png|\.gif)$/i',$picto)) $picto .= '.png'; // If alt path are defined, define url where img file is, according to physical path diff --git a/htdocs/modulebuilder/template/img/object_mytest.png b/htdocs/modulebuilder/template/img/object_mytest.png new file mode 100644 index 0000000000000000000000000000000000000000..5a307bfc62f85df909a3cf024f27ee87d44be275 GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt)eIT^vI+ zChono-m4{0gyqBiz=Ju)w^;&N<{#X1a0!1>bC%GsW3bBL=<%|p84;9-@5SwA|2OIEL% zb=QtBT0T9C&(LA{syqXqqW_DHn`b;(x5}@uA-g2{Ncy)Mhpp~Sy0eY()*3IP6|4C4 z(mDEHWvtPCEP7WZe7{4e?P9&>AE%^j|Mz!&9rL?{G_w^d>;^y&GkCiCxvX Date: Fri, 2 Jun 2017 20:17:08 +0200 Subject: [PATCH 33/40] Init of the onlinesign --- htdocs/public/onlinesign/newonlinesign.php | 640 +++++++++++++++++++++ 1 file changed, 640 insertions(+) create mode 100644 htdocs/public/onlinesign/newonlinesign.php diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php new file mode 100644 index 00000000000..73d9f41eab0 --- /dev/null +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -0,0 +1,640 @@ + + * Copyright (C) 2006-2017 Laurent Destailleur + * Copyright (C) 2009-2012 Regis Houssin + * + * 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 . + * + * For paypal test: https://developer.paypal.com/ + * For paybox test: ??? + */ + +/** + * \file htdocs/public/onlinesign/newsign.php + * \ingroup core + * \brief File to offer a way to make an online signature for a particular Dolibarr entity + */ + +define("NOLOGIN",1); // This means this output page does not require to be logged. +define("NOCSRFCHECK",1); // We accept to go on this page from external web site. + +// For MultiCompany module. +// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php +// TODO This should be useless. Because entity must be retreive from object ref and not from url. +$entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1)); +if (is_numeric($entity)) define("DOLENTITY", $entity); + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + +// Security check +// No check on module enabled. Done later according to $validpaymentmethod + +$langs->load("main"); +$langs->load("other"); +$langs->load("dict"); +$langs->load("bills"); +$langs->load("companies"); +$langs->load("errors"); +$langs->load("paybox"); // File with generic data + +$action=GETPOST('action','alpha'); + +// Input are: +// type ('invoice','order','contractline'), +// id (object id), +// amount (required if id is empty), +// tag (a free text, required if type is empty) +// currency (iso code) + +$suffix=GETPOST("suffix",'alpha'); +$SOURCE=GETPOST("source",'alpha'); +$ref=$REF=GETPOST("ref",'alpha'); + +if (! $action) +{ + if ($source && ! $ref) + { + dol_print_error('',$langs->trans('ErrorBadParameters')." - ref"); + exit; + } +} + + +$paymentmethod=''; +$validpaymentmethod=array(); + + + + +// Define $urlwithroot +//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost. + + +// Complete urls for post treatment +$SECUREKEY=GETPOST("securekey"); // Secure key + +if (! empty($SOURCE)) +{ + $urlok.='source='.urlencode($SOURCE).'&'; + $urlko.='source='.urlencode($SOURCE).'&'; +} +if (! empty($REF)) +{ + $urlok.='ref='.urlencode($REF).'&'; + $urlko.='ref='.urlencode($REF).'&'; +} +if (! empty($SECUREKEY)) +{ + $urlok.='securekey='.urlencode($SECUREKEY).'&'; + $urlko.='securekey='.urlencode($SECUREKEY).'&'; +} +if (! empty($entity)) +{ + $urlok.='entity='.urlencode($entity).'&'; + $urlko.='entity='.urlencode($entity).'&'; +} +$urlok=preg_replace('/&$/','',$urlok); // Remove last & +$urlko=preg_replace('/&$/','',$urlko); // Remove last & + + + + +/* + * Actions + */ + + +if ($action == 'dosign') +{ + // TODO + +} + + +/* + * View + */ + +$head=''; +if (! empty($conf->global->MAIN_SIGN_CSS_URL)) $head=''."\n"; + +$conf->dol_hide_topmenu=1; +$conf->dol_hide_leftmenu=1; + +llxHeader($head, $langs->trans("OnlineSignature"), '', '', 0, 0, '', '', '', 'onlinepaymentbody'); + +// Check link validity +if (! empty($SOURCE) && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', ''))) +{ + $langs->load("errors"); + dol_print_error_email('BADREFINONLINESIGNFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $SOURCE, $ref)); + llxFooter(); + $db->close(); + exit; +} + +print ''."\n"; +print '
'."\n"; +print '
'."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''; +print "\n"; +print ''."\n"; + +print ''."\n"; + +// Show logo (search order: logo defined by PAYBOX_LOGO_suffix, then PAYBOX_LOGO, then small company logo, large company logo, theme logo, common logo) +$width=0; +// Define logo and logosmall +$logosmall=$mysoc->logo_small; +$logo=$mysoc->logo; +$paramlogo='ONLINE_SIGN_LOGO_'.$suffix; +if (! empty($conf->global->$paramlogo)) $logosmall=$conf->global->$paramlogo; +else if (! empty($conf->global->ONLINE_SIGN_LOGO)) $logosmall=$conf->global->ONLINE_SIGN_LOGO; +//print ''."\n"; +// Define urllogo +$urllogo=''; +if (! empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) +{ + $urllogo=DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&file='.urlencode('thumbs/'.$logosmall); +} +elseif (! empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) +{ + $urllogo=DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&file='.urlencode($logo); + $width=96; +} +// Output html code for logo +if ($urllogo) +{ + print ''; + print ''; + print ''."\n"; +} + +// Output introduction text +$text=''; +if (! empty($conf->global->ONLINE_SIGN_NEWFORM_TEXT)) +{ + $langs->load("members"); + if (preg_match('/^\((.*)\)$/',$conf->global->ONLINE_SIGN_NEWFORM_TEXT,$reg)) $text.=$langs->trans($reg[1])."
\n"; + else $text.=$conf->global->ONLINE_SIGN_NEWFORM_TEXT."
\n"; + $text=''."\n"; +} +if (empty($text)) +{ + $text.=''."\n"; + $text.=''."\n"; +} +print $text; + +// Output payment summary form +print ''."\n"; + +print '

'.$text.'

'.$langs->trans("WelcomeOnOnlineSignaturePage").'

'.$langs->trans("ThisScreenAllowsYouToSignDocFrom",$creditor).'

'; +print ''; +print ''."\n"; + +$found=false; +$error=0; +$var=false; + +// Free payment +if (! GETPOST("source")) +{ + $found=true; + $tag=GETPOST("tag"); + $fulltag=$tag; + + // Creditor + + print ''."\n"; + + + + // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum + // as they don't exists (buyer is unknown, tag is free). +} + + +// Payment on customer order +if (GETPOST("source") == 'order') +{ + $found=true; + $langs->load("orders"); + + require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; + + $order=new Commande($db); + $result=$order->fetch('',$ref); + if ($result < 0) + { + $mesg=$order->error; + $error++; + } + else + { + $result=$order->fetch_thirdparty($order->socid); + } + + // Creditor + + print ''."\n"; + + // Debitor + + print ''."\n"; + + +} + + +// Payment on customer invoice +if (GETPOST("source") == 'invoice') +{ + $found=true; + $langs->load("bills"); + + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + + $invoice=new Facture($db); + $result=$invoice->fetch('',$ref); + if ($result < 0) + { + $mesg=$invoice->error; + $error++; + } + else + { + $result=$invoice->fetch_thirdparty($invoice->socid); + } + + if ($action != 'dosign') // Do not change amount if we just click on first dosign + { + $amount=price2num($invoice->total_ttc - $invoice->getSommePaiement()); + if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); + $amount=price2num($amount); + } + + // Creditor + + print ''."\n"; + + // Debitor + + print ''."\n"; + +} + +// Payment on contract line +if (GETPOST("source") == 'contractline') +{ + $found=true; + $langs->load("contracts"); + + require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; + + $contractline=new ContratLigne($db); + $result=$contractline->fetch('',$ref); + if ($result < 0) + { + $mesg=$contractline->error; + $error++; + } + else + { + if ($contractline->fk_contrat > 0) + { + $contract=new Contrat($db); + $result=$contract->fetch($contractline->fk_contrat); + if ($result > 0) + { + $result=$contract->fetch_thirdparty($contract->socid); + } + else + { + $mesg=$contract->error; + $error++; + } + } + else + { + $mesg='ErrorRecordNotFound'; + $error++; + } + } + + if ($action != 'dosign') // Do not change amount if we just click on first dosign + { + $amount=$contractline->total_ttc; + if ($contractline->fk_product) + { + $product=new Product($db); + $result=$product->fetch($contractline->fk_product); + + // We define price for product (TODO Put this in a method in product class) + if (! empty($conf->global->PRODUIT_MULTIPRICES)) + { + $pu_ht = $product->multiprices[$contract->thirdparty->price_level]; + $pu_ttc = $product->multiprices_ttc[$contract->thirdparty->price_level]; + $price_base_type = $product->multiprices_base_type[$contract->thirdparty->price_level]; + } + else + { + $pu_ht = $product->price; + $pu_ttc = $product->price_ttc; + $price_base_type = $product->price_base_type; + } + + $amount=$pu_ttc; + if (empty($amount)) + { + dol_print_error('','ErrorNoPriceDefinedForThisProduct'); + exit; + } + } + if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); + $amount=price2num($amount); + } + + $qty=1; + if (GETPOST('qty')) $qty=GETPOST('qty'); + + // Creditor + + print ''."\n"; + + // Debitor + + print ''."\n"; + + // Quantity + + $label=$langs->trans("Quantity"); + $qty=1; + $duration=''; + if ($contractline->fk_product) + { + if ($product->isService() && $product->duration_value > 0) + { + $label=$langs->trans("Duration"); + + // TODO Put this in a global method + if ($product->duration_value > 1) + { + $dur=array("h"=>$langs->trans("Hours"),"d"=>$langs->trans("DurationDays"),"w"=>$langs->trans("DurationWeeks"),"m"=>$langs->trans("DurationMonths"),"y"=>$langs->trans("DurationYears")); + } + else + { + $dur=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("DurationDay"),"w"=>$langs->trans("DurationWeek"),"m"=>$langs->trans("DurationMonth"),"y"=>$langs->trans("DurationYear")); + } + $duration=$product->duration_value.' '.$dur[$product->duration_unit]; + } + } + print ''; + print ''."\n"; + + // Amount + + print ''."\n"; + +} + +// Payment on member subscription +if (GETPOST("source") == 'membersubscription') +{ + $found=true; + $langs->load("members"); + + require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; + require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php'; + + $member=new Adherent($db); + $result=$member->fetch('',$ref); + if ($result < 0) + { + $mesg=$member->error; + $error++; + } + else + { + $subscription=new Subscription($db); + } + + if ($action != 'dosign') // Do not change amount if we just click on first dosign + { + $amount=$subscription->total_ttc; + if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int'); + $amount=price2num($amount); + } + + $fulltag='MEM='.$member->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M'); + if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } + $fulltag=dol_string_unaccent($fulltag); + + // Creditor + + print ''."\n"; + + // Debitor + + print ''."\n"; + + if ($member->last_subscription_date || $member->last_subscription_amount) + { + // Last subscription date + + print ''."\n"; + + // Last subscription amount + + print ''."\n"; + + if (empty($amount) && ! GETPOST('newamount')) $_GET['newamount']=$member->last_subscription_amount; + } + + // Amount + + print ''."\n"; + +} + + + + +if (! $found && ! $mesg) $mesg=$langs->trans("ErrorBadParameters"); + +if ($mesg) print ''."\n"; + +print '
'.$langs->trans("ThisIsInformationOnDocumentToSign").' :
'.$langs->trans("Creditor"); + print ''.$creditor.''; + print ''; + print '
'.$langs->trans("Creditor"); + print ''.$creditor.''; + print ''; + print '
'.$langs->trans("ThirdParty"); + print ''.$order->thirdparty->name.''; + + // Object + + $text=''.$langs->trans("PaymentOrderRef",$order->ref).''; + print '
'.$langs->trans("Designation"); + print ''.$text; + print ''; + print ''; + print '
'.$langs->trans("Creditor"); + print ''.$creditor.''; + print ''; + print '
'.$langs->trans("ThirdParty"); + print ''.$invoice->thirdparty->name.''; + + // Object + + $text=''.$langs->trans("PaymentInvoiceRef",$invoice->ref).''; + print '
'.$langs->trans("Designation"); + print ''.$text; + print ''; + print ''; + print '
'.$langs->trans("Creditor"); + print ''.$creditor.''; + print ''; + print '
'.$langs->trans("ThirdParty"); + print ''.$contract->thirdparty->name.''; + + // Object + + $text=''.$langs->trans("PaymentRenewContractId",$contract->ref,$contractline->ref).''; + if ($contractline->fk_product) + { + $text.='
'.$product->ref.($product->label?' - '.$product->label:''); + } + if ($contractline->description) $text.='
'.dol_htmlentitiesbr($contractline->description); + //if ($contractline->date_fin_validite) { + // $text.='
'.$langs->trans("DateEndPlanned").': '; + // $text.=dol_print_date($contractline->date_fin_validite); + //} + if ($contractline->date_fin_validite) + { + $text.='
'.$langs->trans("ExpiredSince").': '.dol_print_date($contractline->date_fin_validite); + } + + print '
'.$langs->trans("Designation"); + print ''.$text; + print ''; + print ''; + print '
'.$label.''.($duration?$duration:$qty).''; + print ''; + print '
'.$langs->trans("Amount"); + if (empty($amount)) print ' ('.$langs->trans("ToComplete").')'; + print ''; + if (empty($amount) || ! is_numeric($amount)) + { + print ''; + print ''; + } + else { + print ''.price($amount).''; + print ''; + print ''; + } + // Currency + print ' '.$langs->trans("Currency".$currency).''; + print ''; + print '
'.$langs->trans("Creditor"); + print ''.$creditor.''; + print ''; + print '
'.$langs->trans("Member"); + print ''; + if ($member->morphy == 'mor' && ! empty($member->societe)) print $member->societe; + else print $member->getFullName($langs); + print ''; + + // Object + + $text=''.$langs->trans("PaymentSubscription").''; + print '
'.$langs->trans("Designation"); + print ''.$text; + print ''; + print ''; + print '
'.$langs->trans("LastSubscriptionDate"); + print ''.dol_print_date($member->last_subscription_date,'day'); + print '
'.$langs->trans("LastSubscriptionAmount"); + print ''.price($member->last_subscription_amount); + print '
'.$langs->trans("Amount"); + if (empty($amount)) + { + print ' ('.$langs->trans("ToComplete"); + if (! empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) print ' - '.$langs->trans("SeeHere").''; + print ')'; + } + print ''; + if (empty($amount) || ! is_numeric($amount)) + { + $valtoshow=GETPOST("newamount",'int'); + if (! empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) $valtoshow=max($conf->global->MEMBER_MIN_AMOUNT,$valtoshow); + print ''; + print ''; + } + else { + $valtoshow=$amount; + if (! empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) $valtoshow=max($conf->global->MEMBER_MIN_AMOUNT,$valtoshow); + print ''.price($valtoshow).''; + print ''; + print ''; + } + // Currency + print ' '.$langs->trans("Currency".$currency).''; + print ''; + print '

'.$mesg.'
'."\n"; +print "\n"; + +if ($action != 'dosign') +{ + if ($found && ! $error) // We are in a management option and no error + { + + + } + else + { + dol_print_error_email('ERRORNEWONLINESIGNPAYPAL'); + } +} +else +{ + // Print +} + +print '
'."\n"; +print '
'."\n"; +print '
'."\n"; +print '
'; + + +htmlPrintOnlinePaymentFooter($mysoc,$langs); + +llxFooter('', 'public'); + +$db->close(); From 70a188c0421045c87a07d6df39f15e5fc9727c1b Mon Sep 17 00:00:00 2001 From: atm-ph Date: Fri, 2 Jun 2017 21:45:02 +0200 Subject: [PATCH 34/40] Fix missing column entity on llx_accounting_journal after init demo with the bash --- htdocs/install/mysql/migration/5.0.0-6.0.0.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index 11a86724cf0..4680d451e39 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -159,6 +159,9 @@ CREATE TABLE llx_product_attribute_combination ALTER TABLE llx_bank_account drop foreign key bank_fk_accountancy_journal; +-- Fix missing entity column after init demo +ALTER TABLE llx_accounting_journal ADD COLUMN entity integer DEFAULT 1; + -- Add journal entries INSERT INTO llx_accounting_journal (rowid, code, label, nature, active) VALUES (1,'VT', 'Sale journal', 2, 1); INSERT INTO llx_accounting_journal (rowid, code, label, nature, active) VALUES (2,'AC', 'Purchase journal', 3, 1); @@ -355,4 +358,4 @@ delete from llx_categorie_member where fk_categorie not in (select rowid from ll delete from llx_categorie_contact where fk_categorie not in (select rowid from llx_categorie where type = 4); delete from llx_categorie_project where fk_categorie not in (select rowid from llx_categorie where type = 5); -ALTER TABLE llx_inventory ADD COLUMN ref varchar(48); \ No newline at end of file +ALTER TABLE llx_inventory ADD COLUMN ref varchar(48); From 66420d0e80d8fb3e43ffa4c96373154d2f7c779c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 23:02:48 +0200 Subject: [PATCH 35/40] Restore lost file and better generation of modules --- htdocs/core/actions_setmoduleoptions.inc.php | 86 +++++++++++++++ htdocs/core/class/hookmanager.class.php | 17 +-- htdocs/core/class/html.form.class.php | 19 +++- htdocs/core/modules/DolibarrModules.class.php | 102 ++++++++++-------- .../template/langs/en_US/mymodule.lang | 10 +- .../template/langs/fr_FR/mymodule.lang | 10 +- 6 files changed, 173 insertions(+), 71 deletions(-) create mode 100644 htdocs/core/actions_setmoduleoptions.inc.php diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php new file mode 100644 index 00000000000..03b33b19eb1 --- /dev/null +++ b/htdocs/core/actions_setmoduleoptions.inc.php @@ -0,0 +1,86 @@ + + * + * 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 . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/actions_setnotes.inc.php + * \brief Code for actions on setting notes of object page + */ + + +// $action must be defined +// $_FILES may be defined +// $nomessageinsetmoduleoptions can be set to 1 + +// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) +if ($action == 'setModuleOptions') +{ + $db->begin(); + + // Process common param fields + foreach($_POST as $key => $val) + { + if (preg_match('/^param(\d*)$/', $key, $reg)) // Works for POST['param'], POST['param1'], POST['param2'], ... + { + $param=GETPOST("param".$reg[1],'alpha'); + $value=GETPOST("value".$reg[1],'alpha'); + if ($param) + { + $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + } + } + } + + // Process upload fields + if (GETPOST('upload','alpha') && GETPOST('keyforuploaddir','aZ09')) + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $keyforuploaddir=GETPOST('keyforuploaddir','aZ09'); + $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->$keyforuploaddir))); + foreach($listofdir as $key=>$tmpdir) + { + $tmpdir=trim($tmpdir); + $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); + if (! $tmpdir) { + unset($listofdir[$key]); continue; + } + if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0); + else + { + $upload_dir=$tmpdir; + } + } + if ($upload_dir) + { + $result = dol_add_file_process($upload_dir, 0, 1, 'uploadfile', ''); + if ($result <= 0) $error++; + } + } + + if (! $error) + { + $db->commit(); + if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } + else + { + $db->rollback(); + if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupNotSaved"), null, 'errors'); + } +} + diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 590f8060296..1e20ee6ce31 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -133,10 +133,12 @@ class HookManager if (in_array( $method, array( - 'addMoreActionsButtons', + 'addCalendarChoice', + 'addMoreActionsButtons', + 'addMoreMassActions', 'addSearchEntry', 'addStatisticLine', - 'deleteFile', + 'deleteFile', 'doActions', 'formCreateThirdpartyOptions', 'formObjectOptions', @@ -169,7 +171,6 @@ class HookManager 'printSearchForm', 'printTabsHead', 'formatEvent', - 'addCalendarChoice', 'printObjectLine', 'printObjectSubLine', 'createDictionaryFieldList', @@ -181,14 +182,16 @@ class HookManager if ($method == 'insertExtraFields') { - $hooktype='returnvalue'; // deprecated. TODO Remove all code with "executeHooks('insertExtraFields'" as soon as there is a trigger available. + $hooktype='returnvalue'; // @deprecated. TODO Remove all code with "executeHooks('insertExtraFields'" as soon as there is a trigger available. dol_syslog("Warning: The hook 'insertExtraFields' is deprecated and must not be used. Use instead trigger on CRUD event (ask it to dev team if not implemented)", LOG_WARNING); } + // Init return properties + $this->resPrint=''; $this->resArray=array(); + // Loop on each hook to qualify modules that have declared context $modulealreadyexecuted=array(); $resaction=0; $error=0; $result=''; - $this->resPrint=''; $this->resArray=array(); foreach($this->hooks as $context => $modules) // $this->hooks is an array with context as key and value is an array of modules that handle this context { if (! empty($modules)) @@ -202,9 +205,9 @@ class HookManager // test to avoid running twice a hook, when a module implements several active contexts if (in_array($module,$modulealreadyexecuted)) continue; - + dol_syslog(get_class($this).'::executeHooks a qualified hook was found for method='.$method.' module='.$module." action=".$action." context=".$context); - + $modulealreadyexecuted[$module]=$module; // Use the $currentcontext in method to avoid running twice // Clean class (an error may have been set from a previous call of another method for same module/hook) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 34693cba67a..997bc94cc42 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -545,11 +545,20 @@ class Form $disabled=0; $ret='
'; $ret.=''; // Warning: if you set submit button to disabled, post using 'Enter' will no more work. $ret.=''; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 71de341a769..a79f17b1fdc 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -50,13 +50,13 @@ class DolibarrModules // Can not be abstract, because we need to insta * @since 4.0.0 */ public $editor_name; - + /** * @var string URL of module at publisher site * @since 4.0.0 */ public $editor_url; - + /** * @var string Family * @see familyinfo @@ -80,13 +80,13 @@ class DolibarrModules // Can not be abstract, because we need to insta * */ public $familyinfo; - + /** * @var int Module position * @since 3.9.0 */ public $module_position=500; - + /** * @var string Module name * @@ -214,7 +214,7 @@ class DolibarrModules // Can not be abstract, because we need to insta * HTML content supported. */ public $descriptionlong; - + /** * @var string Module export code */ @@ -249,7 +249,7 @@ class DolibarrModules // Can not be abstract, because we need to insta * @var bool Module is enabled globally (Multicompany support) */ public $core_enabled; - + /** * @var string Relative path to module style sheet * @deprecated @@ -286,7 +286,7 @@ class DolibarrModules // Can not be abstract, because we need to insta */ public $config_page_url; - + /** * @var string[] List of module class names that must be enabled if this module is enabled. * @@ -309,22 +309,22 @@ class DolibarrModules // Can not be abstract, because we need to insta * @var string[] Module language files */ public $langfiles; - + /** * @var string[] Array of warnings to show when we activate the module - * + * * array('always'='text') or array('FR'='text') */ public $warnings_activation; - + /** * @var string[] Array of warnings to show when we activate an external module - * + * * array('always'='text') or array('FR'='text') */ public $warnings_activation_ext; - - + + /** * @var array() Minimum version of PHP required by module. * e.g.: PHP ≥ 5.3 = array(5, 3) @@ -342,7 +342,7 @@ class DolibarrModules // Can not be abstract, because we need to insta */ public $hidden = false; - + /** * Constructor. Define names, constants, directories, boxes, permissions * @@ -538,8 +538,8 @@ class DolibarrModules // Can not be abstract, because we need to insta return $langs->trans("Module".$this->numero."Name"); } else - { - // If module name translation using it's unique id does not exists, we take use its name to find translation + { + // If module name translation using it's unique id does not exists, we try to use its name to find translation if (is_array($this->langfiles)) { foreach($this->langfiles as $val) @@ -547,6 +547,14 @@ class DolibarrModules // Can not be abstract, because we need to insta if ($val) $langs->load($val); } } + + if ($langs->trans("Module".$this->name."Name") != ("Module".$this->name."Name")) + { + // If module name translation exists + return $langs->trans("Module".$this->name."Name"); + } + + // Last change with simple product label return $langs->trans($this->name); } } @@ -591,13 +599,13 @@ class DolibarrModules // Can not be abstract, because we need to insta { global $langs; $langs->load("admin"); - + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; $filefound= false; - - // Define path to file README.md. + + // Define path to file README.md. // First check README-la_LA.md then README.md $pathoffile = dol_buildpath(strtolower($this->name).'/README-'.$langs->defaultlang.'.md', 0); if (dol_is_file($pathoffile)) @@ -612,11 +620,11 @@ class DolibarrModules // Can not be abstract, because we need to insta $filefound = true; } } - + if ($filefound) // Mostly for external modules { $content = file_get_contents($pathoffile); - + if ((float) DOL_VERSION >= 6.0) { @include_once DOL_DOCUMENT_ROOT.'/core/lib/parsemd.lib.php'; @@ -638,14 +646,14 @@ class DolibarrModules // Can not be abstract, because we need to insta if ($val) $langs->load($val); } } - + $content = $langs->trans($this->descriptionlong); } } - + return $content; } - + /** * Gives the publisher name * @@ -655,7 +663,7 @@ class DolibarrModules // Can not be abstract, because we need to insta { return $this->editor_name; } - + /** * Gives the publisher url * @@ -665,7 +673,7 @@ class DolibarrModules // Can not be abstract, because we need to insta { return $this->editor_url; } - + /** * Gives module version (translated if param $translated is on) * For 'experimental' modules, gives 'experimental' translation @@ -768,7 +776,7 @@ class DolibarrModules // Can not be abstract, because we need to insta } } - + /** * Gives the last date of activation * @@ -777,11 +785,11 @@ class DolibarrModules // Can not be abstract, because we need to insta function getLastActivationDate() { global $conf; - + $sql = "SELECT tms FROM ".MAIN_DB_PREFIX."const"; $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'"; $sql.= " AND entity IN (0, ".$conf->entity.")"; - + dol_syslog(get_class($this)."::getLastActiveDate", LOG_DEBUG); $resql=$this->db->query($sql); if (! $resql) $err++; @@ -790,11 +798,11 @@ class DolibarrModules // Can not be abstract, because we need to insta $obj=$this->db->fetch_object($resql); if ($obj) return $this->db->jdate($obj->tms); } - + return ''; } - - + + /** * Gives the last author of activation * @@ -803,11 +811,11 @@ class DolibarrModules // Can not be abstract, because we need to insta function getLastActivationInfo() { global $conf; - + $sql = "SELECT tms, note FROM ".MAIN_DB_PREFIX."const"; $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'"; $sql.= " AND entity IN (0, ".$conf->entity.")"; - + dol_syslog(get_class($this)."::getLastActiveDate", LOG_DEBUG); $resql=$this->db->query($sql); if (! $resql) $err++; @@ -821,11 +829,11 @@ class DolibarrModules // Can not be abstract, because we need to insta } if ($obj) return array('authorid'=>$tmp['authorid'], 'ip'=>$tmp['ip'], 'lastactivationdate'=>$this->db->jdate($obj->tms)); } - + return array(); } - - + + /** * Insert constants for module activation * @@ -929,7 +937,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $files[] = $file; } sort($files); - foreach ($files as $file) + foreach ($files as $file) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data') { @@ -947,7 +955,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $files[] = $file; } sort($files); - foreach ($files as $file) + foreach ($files as $file) { if (preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data') { @@ -965,7 +973,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $files[] = $file; } sort($files); - foreach ($files as $file) + foreach ($files as $file) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'data') { @@ -983,7 +991,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $files[] = $file; } sort($files); - foreach ($files as $file) + foreach ($files as $file) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,6) == 'update') { @@ -1123,19 +1131,19 @@ class DolibarrModules // Can not be abstract, because we need to insta //$titre = $this->boxes[$key][0]; $file = $this->boxes[$key]['file']; //$note = $this->boxes[$key][2]; - + // TODO If the box is also included by another module and the other module is still on, we should not remove it. // For the moment, we manage this with hard coded exception //print "Remove box ".$file.'
'; if ($file == 'box_graph_product_distribution.php') { - if (! empty($conf->produit->enabled) || ! empty($conf->service->enabled)) + if (! empty($conf->produit->enabled) || ! empty($conf->service->enabled)) { dol_syslog("We discard disabling of module ".$file." because another module still active require it."); continue; } } - + if (empty($file)) $file = isset($this->boxes[$key][1])?$this->boxes[$key][1]:''; // For backward compatibility if ($this->db->type == 'sqlite3') { @@ -1210,7 +1218,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $status = isset($this->cronjobs[$key]['status'])?$this->cronjobs[$key]['status']:''; $priority = isset($this->cronjobs[$key]['priority'])?$this->cronjobs[$key]['priority']:''; $test = isset($this->cronjobs[$key]['test'])?$this->cronjobs[$key]['test']:''; // Line must be visible - + // Search if boxes def already present $sql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."cronjob"; $sql.= " WHERE module_name = '".$this->db->escape($this->rights_class)."'"; @@ -1645,7 +1653,7 @@ class DolibarrModules // Can not be abstract, because we need to insta /** * Removes access rights - * + * * @return int Error count (0 if OK) */ function delete_permissions() @@ -1678,7 +1686,7 @@ class DolibarrModules // Can not be abstract, because we need to insta global $user; if (! is_array($this->menu) || empty($this->menu)) return 0; - + require_once DOL_DOCUMENT_ROOT . '/core/class/menubase.class.php'; $err=0; diff --git a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang index 53c6205386c..c33f2453fc4 100644 --- a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang +++ b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang @@ -18,12 +18,10 @@ # Generic # -# Module label 'ModuleXXXName' -# (where XXX is value of numeric property 'numero' of module) -Module500000Name = My module -# Module description 'ModuleXXXDesc' -# (where XXX is value of numeric property 'numero' of module) -Module500000Desc = My module description +# Module label 'ModuleMyModuleName' +ModuleMyModuleName = My module +# Module description 'ModuleMyModuleDesc' +ModuleMyModuleDesc = My module description # # Admin page diff --git a/htdocs/modulebuilder/template/langs/fr_FR/mymodule.lang b/htdocs/modulebuilder/template/langs/fr_FR/mymodule.lang index d15d37f0ebf..06e7ba33885 100644 --- a/htdocs/modulebuilder/template/langs/fr_FR/mymodule.lang +++ b/htdocs/modulebuilder/template/langs/fr_FR/mymodule.lang @@ -18,12 +18,10 @@ # Générique # -# Module label 'ModuleXXXName' -# (where XXX is value of numeric property 'numero' of module) -Module500000Name = Mon module -# Module description 'ModuleXXXDesc' -# (where XXX is value of numeric property 'numero' of module) -Module500000Desc = Description de mon module +# Module label 'ModuleMyModuleName' +ModuleMyModuleName = Mon module +# Module description 'ModuleMyModuleDesc' +ModuleMyModuleDesc = Description de mon module # # Page d'administration From 111087dfdc5b32330ab6b3d45fe1b5ca2586abf7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 2 Jun 2017 23:41:18 +0200 Subject: [PATCH 36/40] Work on module template --- htdocs/core/actions_massactions.inc.php | 49 +++++----- htdocs/core/class/hookmanager.class.php | 1 + htdocs/core/class/html.form.class.php | 2 +- .../template/class/actions_mymodule.class.php | 89 +++++++++++++++++-- 4 files changed, 113 insertions(+), 28 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 92d1011b923..fde828fd6d4 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -24,20 +24,22 @@ // $massaction must be defined // $objectclass and $$objectlabel must be defined -// $uploaddir (example $conf->projet->dir_output . "/";) +// $parameters, $object, $action must be defined for the hook. + +// $uploaddir may be defined (example to $conf->projet->dir_output."/";) // $toselect may be defined // Protection -if (empty($objectclass) || empty($uploaddir)) +if (empty($objectclass) || empty($uploaddir)) { dol_print_error(null, 'include of actions_massactions.inc.php is done but var $massaction or $objectclass or $uploaddir was not defined'); exit; } -// Mass actions. Controls on number of lines checked -$maxformassaction=1000; +// Mass actions. Controls on number of lines checked. +$maxformassaction=(empty($conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS)?1000:$conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS); if (! empty($massaction) && count($toselect) < 1) { $error++; @@ -87,7 +89,7 @@ if (! $error && $massaction == 'confirm_presend') } } //var_dump($listofobjectthirdparties);exit; - + foreach ($listofobjectthirdparties as $thirdpartyid) { $result = $thirdparty->fetch($thirdpartyid); @@ -144,7 +146,7 @@ if (! $error && $massaction == 'confirm_presend') { //var_dump($object); //var_dump($thirdpartyid.' - '.$objectid.' - '.$object->statut); - + if ($objectclass == 'Facture' && $object->statut != Facture::STATUS_VALIDATED) { $nbignored++; @@ -157,7 +159,7 @@ if (! $error && $massaction == 'confirm_presend') $resaction.='
'.$langs->trans('ErrorOnlyOrderNotDraftCanBeSentInMassAction',$object->ref).'

'; continue; } - + // Read document // TODO Use future field $object->fullpathdoc to know where is stored default file // TODO If not defined, use $object->modelpdf (or defaut invoice config) to know what is template to use to regenerate doc. @@ -202,7 +204,7 @@ if (! $error && $massaction == 'confirm_presend') dol_syslog('Failed to read file: '.$file, LOG_WARNING); continue; } - + //var_dump($listofqualifiedref); } @@ -252,9 +254,9 @@ if (! $error && $massaction == 'confirm_presend') $filepath = $attachedfiles['paths']; $filename = $attachedfiles['names']; $mimetype = $attachedfiles['mimes']; - + //var_dump($filepath); - + // Send mail require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'); $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1); @@ -280,7 +282,7 @@ if (! $error && $massaction == 'confirm_presend') if ($objectclass == 'Supplier_Proposal') $actiontypecode='AC_SUP_PRO'; if ($objectclass == 'CommandeFournisseur') $actiontypecode='AC_SUP_ORD'; if ($objectclass == 'FactureFournisseur') $actiontypecode='AC_SUP_INV';*/ - + $actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto; if ($message) { @@ -290,7 +292,7 @@ if (! $error && $massaction == 'confirm_presend') $actionmsg = dol_concatdesc($actionmsg, $message); } $actionmsg2=''; - + // Initialisation donnees $object->sendtoid = 0; $object->actionmsg = $actionmsg; // Long text @@ -335,7 +337,7 @@ if (! $error && $massaction == 'confirm_presend') $resaction.=$langs->trans("NbSelected").': '.count($toselect)."\n
"; $resaction.=$langs->trans("NbIgnored").': '.($nbignored?$nbignored:0)."\n
"; $resaction.=$langs->trans("NbSent").': '.($nbsent?$nbsent:0)."\n
"; - + if ($nbsent) { $action=''; // Do not show form post if there was at least one successfull sent @@ -359,7 +361,7 @@ if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_se require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; - + $objecttmp=new $objectclass($db); $listofobjectid=array(); $listofobjectthirdparties=array(); @@ -425,21 +427,21 @@ if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_se if (count($files)>0) { - + $now=dol_now(); $file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf'; - + $input_files = ''; foreach($files as $f) { $input_files.=' '.escapeshellarg($f); } - + $cmd = 'pdftk '.$input_files.' cat output '.escapeshellarg($file); exec($cmd); - + if (! empty($conf->global->MAIN_UMASK)) @chmod($file, octdec($conf->global->MAIN_UMASK)); - + $langs->load("exports"); setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs'); } @@ -447,7 +449,7 @@ if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_se { setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors'); } - + } else { // Create empty PDF @@ -481,7 +483,7 @@ if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_se // Defined name of merged file $filename=strtolower(dol_sanitizeFileName($langs->transnoentities($objectlabel))); $filename=preg_replace('/\s/','_',$filename); - + // Save merged file if ($filter=='paye:0') { @@ -565,6 +567,11 @@ if (! $error && $massaction == 'delete' && $permtodelete) //var_dump($listofobjectthirdparties);exit; } +$parameters['toselect']=$toselect; +$parameters['uploaddir']=$uploaddir; + +$reshook=$hookmanager->executeHooks('doMassActions',$parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 1e20ee6ce31..40ed4153060 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -140,6 +140,7 @@ class HookManager 'addStatisticLine', 'deleteFile', 'doActions', + 'doMassActions', 'formCreateThirdpartyOptions', 'formObjectOptions', 'formattachOptions', diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 997bc94cc42..b14f72a1b7b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -546,7 +546,7 @@ class Form $ret='
'; $ret.=''; - // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['context'] completed by executeHooks. + // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks. $parameters=array(); $reshook=$hookmanager->executeHooks('addMoreMassActions',$parameters); // Note that $action and $object may have been modified by hook if (empty($reshook)) diff --git a/htdocs/modulebuilder/template/class/actions_mymodule.class.php b/htdocs/modulebuilder/template/class/actions_mymodule.class.php index f3ce5963aa6..7f1897c80ae 100644 --- a/htdocs/modulebuilder/template/class/actions_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/actions_mymodule.class.php @@ -62,24 +62,101 @@ class ActionsMyModule */ public function doActions($parameters, &$object, &$action, $hookmanager) { + global $conf, $user, $langs; + $error = 0; // Error counter - $myvalue = 'test'; // A result value + /* print_r($parameters); - echo "action: " . $action; print_r($object); + echo "action: " . $action; + */ + + if (in_array($parameters['currentcontext'], array('somecontext1','somecontext2'))) { // do something only for the context 'somecontext1' or 'somecontext2' + - if (in_array('somecontext', explode(':', $parameters['context']))) { - // do something only for the context 'somecontext' } if (! $error) { - $this->results = array('myreturn' => $myvalue); + $this->results = array('myreturn' => 999); $this->resprints = 'A text to show'; - return 0; // or return 1 to replace standard code + return 0; // or return 1 to replace standard code } else { $this->errors[] = 'Error message'; return -1; } } + + + /** + * Overloading the doActions function : replacing the parent's function with the one below + * + * @param array() $parameters Hook metadatas (context, etc...) + * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...) + * @param string $action Current action (if set). Generally create or edit or null + * @param HookManager $hookmanager Hook manager propagated to allow calling another hook + * @return int < 0 on error, 0 on success, 1 to replace standard code + */ + public function doMassActions($parameters, &$object, &$action, $hookmanager) + { + global $conf, $user, $langs; + + $error = 0; // Error counter + + /* + print_r($parameters); + print_r($object); + echo "action: " . $action; + */ + + if (in_array($parameters['currentcontext'], array('somecontext1','somecontext2'))) { // do something only for the context 'somecontext1' or 'somecontext2' + + foreach($parameters['toselect'] as $objectid) + { + // Do action on each object id + + } + } + + if (! $error) { + $this->results = array('myreturn' => 999); + $this->resprints = 'A text to show'; + return 0; // or return 1 to replace standard code + } else { + $this->errors[] = 'Error message'; + return -1; + } + } + + + /** + * Overloading the addMoreMassActions function : replacing the parent's function with the one below + * + * @param array() $parameters Hook metadatas (context, etc...) + * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...) + * @param string $action Current action (if set). Generally create or edit or null + * @param HookManager $hookmanager Hook manager propagated to allow calling another hook + * @return int < 0 on error, 0 on success, 1 to replace standard code + */ + public function addMoreMassActions($parameters, &$object, &$action, $hookmanager) + { + global $conf, $user, $langs; + + $error = 0; // Error counter + + if (in_array($parameters['currentcontext'], array('somecontext1','somecontext2'))) // do something only for the context 'somecontext' + { + $this->resprints = ''; + } + + if (! $error) { + return 0; // or return 1 to replace standard code + } else { + $this->errors[] = 'Error message'; + return -1; + } + } + + + } From af584bc9c01950efb993182bc5dab705645d5908 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 3 Jun 2017 00:58:51 +0200 Subject: [PATCH 38/40] FIX #6880 #6925 --- htdocs/projet/card.php | 67 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index f69b54cffdc..727ef1d7fdd 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -134,7 +134,7 @@ if (empty($reshook)) $error++; setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors'); } - + if (! $error) { $error=0; @@ -308,8 +308,8 @@ if (empty($reshook)) setEventMessages($langs->trans("FailedToCloseProject").':'.$object->error, $object->errors, 'errors'); } } - - + + if ($error) { $db->rollback(); @@ -322,7 +322,7 @@ if (empty($reshook)) if (GETPOST('socid','int') > 0) $object->fetch_thirdparty(GETPOST('socid','int')); else unset($object->thirdparty); } - + } // Build doc @@ -619,7 +619,7 @@ if ($action == 'create' && $user->rights->projet->creer) { print '     '; print ''; - } + } print '
'; print ''; @@ -641,12 +641,12 @@ if ($action == 'create' && $user->rights->projet->creer) }); '; } -elseif ($object->id > 0) +elseif ($object->id > 0) { /* * Show or edit */ - + $res=$object->fetch_optionals($object->id,$extralabels); // To verify role of users @@ -828,26 +828,26 @@ elseif ($object->id > 0) else { // Project card - + $linkback = ''.$langs->trans("BackToList").''; - + $morehtmlref='
'; // Title $morehtmlref.=$object->title; // Thirdparty - if ($object->thirdparty->id > 0) + if ($object->thirdparty->id > 0) { $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1, 'project'); } $morehtmlref.='
'; - + // Define a complementary filter for search of next/prev ref. if (! $user->rights->projet->all->lire) { $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0); $object->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")"; } - + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); @@ -881,18 +881,18 @@ elseif ($object->id > 0) if (strcmp($object->opp_amount,'')) print price($object->opp_amount,0,$langs,1,0,0,$conf->currency); print ''; } - + // Date start - end print ''.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").''; print dol_print_date($object->date_start,'day'); $end=dol_print_date($object->date_end,'day'); - if ($end) + if ($end) { print ' - '.$end; if ($object->hasDelay()) print img_warning($langs->trans('Late')); } print ''; - + // Budget print ''.$langs->trans("Budget").''; if (strcmp($object->budget_amount, '')) print price($object->budget_amount,0,$langs,1,0,0,$conf->currency); @@ -901,16 +901,16 @@ elseif ($object->id > 0) // Other attributes $cols = 2; include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; - + print ''; - + print '
'; print '
'; print '
'; print '
'; - + print ''; - + // Description print '"; } - + print '
'.$langs->trans("Description").''; print nl2br($object->description); @@ -922,13 +922,13 @@ elseif ($object->id > 0) print $form->showCategories($object->id,'project',1); print "
'; - + print '
'; print '
'; print '
'; - + print '
'; } @@ -947,9 +947,10 @@ elseif ($object->id > 0) // Change probability from status if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { + // Default value to close or not when we set opp to 'WON'. $defaultcheckedwhenoppclose=1; if (empty($conf->global->PROJECT_HIDE_TASKS)) $defaultcheckedwhenoppclose=0; - + print ''; print '