From d65229998b293f37df19f9c0f995836362b6d57d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jan 2016 10:25:52 +0100 Subject: [PATCH 01/12] Work on website module --- htdocs/install/mysql/tables/llx_website.sql | 30 +++++++++++++++++++ .../mysql/tables/llx_website_pages.key.sql | 23 ++++++++++++++ .../mysql/tables/llx_website_pages.sql | 4 +++ 3 files changed, 57 insertions(+) create mode 100644 htdocs/install/mysql/tables/llx_website.sql create mode 100644 htdocs/install/mysql/tables/llx_website_pages.key.sql diff --git a/htdocs/install/mysql/tables/llx_website.sql b/htdocs/install/mysql/tables/llx_website.sql new file mode 100644 index 00000000000..e24a68b514b --- /dev/null +++ b/htdocs/install/mysql/tables/llx_website.sql @@ -0,0 +1,30 @@ +-- ======================================================================== +-- Copyright (C) 2016 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 . +-- +-- ======================================================================== + + +CREATE TABLE llx_website +( + rowid integer AUTO_INCREMENT NOT NULL PRIMARY KEY, + entity integer, + shortname varchar(24) NOT NULL, + description varchar(255), + status integer, + date_creation datetime, + date_modification datetime, + tms timestamp +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_website_pages.key.sql b/htdocs/install/mysql/tables/llx_website_pages.key.sql new file mode 100644 index 00000000000..cdaa38079b3 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_website_pages.key.sql @@ -0,0 +1,23 @@ +-- ============================================================================ +-- Copyright (C) 2016 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 . +-- +-- =========================================================================== + +ALTER TABLE llx_website_page ADD UNIQUE INDEX uk_website_page_url (fk_website,pageurl); + +ALTER TABLE llx_website_page ADD CONSTRAINT fk_website_page_website FOREIGN KEY (fk_website) REFERENCES llx_website (rowid); + + diff --git a/htdocs/install/mysql/tables/llx_website_pages.sql b/htdocs/install/mysql/tables/llx_website_pages.sql index 0a28153f5bf..379fa08582e 100644 --- a/htdocs/install/mysql/tables/llx_website_pages.sql +++ b/htdocs/install/mysql/tables/llx_website_pages.sql @@ -20,10 +20,14 @@ CREATE TABLE llx_website_page ( rowid integer AUTO_INCREMENT NOT NULL PRIMARY KEY, + fk_website integer, pageurl varchar(16) NOT NULL, title varchar(255), description varchar(255), keywords varchar(255), content text, + status integer, + date_creation datetime, + date_modification datetime, tms timestamp ) ENGINE=innodb; From 467dc12a7bc9ec4f5d044e55c94ebbf22940a26b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jan 2016 12:33:38 +0100 Subject: [PATCH 02/12] NEW Module "Supplier commercial proposal" (price request) is set to stable status. --- htdocs/comm/propal.php | 6 +-- .../comm/propal/class/propalestats.class.php | 44 +++++++++++++---- htdocs/comm/propal/stats/index.php | 27 ++++++++-- htdocs/commande/card.php | 15 +++--- htdocs/commande/stats/index.php | 4 +- htdocs/core/class/commonobject.class.php | 10 ++-- htdocs/core/class/html.form.class.php | 7 ++- htdocs/core/menus/init_menu_auguria.sql | 1 + htdocs/core/menus/standard/eldy.lib.php | 2 + .../modules/modSupplierProposal.class.php | 21 ++++++-- htdocs/fourn/commande/card.php | 34 +++++++------ .../mysql/tables/llx_supplier_proposal.sql | 2 +- .../install/mysql/tables/llx_website.key.sql | 23 +++++++++ htdocs/langs/en_US/propal.lang | 3 +- htdocs/supplier_proposal/card.php | 41 ++++++++++------ .../class/supplier_proposal.class.php | 49 +++++++++++-------- 16 files changed, 197 insertions(+), 92 deletions(-) create mode 100644 htdocs/install/mysql/tables/llx_website.key.sql diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index e039342dd38..aed5ee01a5d 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -2116,7 +2116,7 @@ if ($action == 'create') $form_close .= $object->note; $form_close .= ''; $form_close .= ''; - $form_close .= ''; + $form_close .= ''; $form_close .= '   '; $form_close .= ' '; $form_close .= ''; @@ -2204,10 +2204,10 @@ if ($action == 'create') } } - // Close + // Set accepted/refused if ($object->statut == Propal::STATUS_VALIDATED && $user->rights->propal->cloturer) { print ''; + print '>' . $langs->trans('SetAcceptedRefused') . ''; } // Clone diff --git a/htdocs/comm/propal/class/propalestats.class.php b/htdocs/comm/propal/class/propalestats.class.php index 07a5ff606bc..11014537337 100644 --- a/htdocs/comm/propal/class/propalestats.class.php +++ b/htdocs/comm/propal/class/propalestats.class.php @@ -26,6 +26,7 @@ include_once DOL_DOCUMENT_ROOT . '/core/class/stats.class.php'; include_once DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php'; +include_once DOL_DOCUMENT_ROOT . '/supplier_proposal/class/supplier_proposal.class.php'; include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; @@ -50,8 +51,9 @@ class PropaleStats extends Stats * @param DoliDB $db Database handler * @param int $socid Id third party for filter. This value must be forced during the new to external user company if user is an external user. * @param int $userid Id user for filter (creation user) + * @param string $mode Option ('customer', 'supplier') */ - function __construct($db, $socid=0, $userid=0) + function __construct($db, $socid=0, $userid=0, $mode='customer') { global $user, $conf; @@ -59,15 +61,37 @@ class PropaleStats extends Stats $this->socid = ($socid > 0 ? $socid : 0); $this->userid = $userid; - $object=new Propal($this->db); - - $this->from = MAIN_DB_PREFIX.$object->table_element." as p"; - $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; - - $this->field='total_ht'; - $this->field_line='total_ht'; - - $this->where.= " p.fk_statut > 0"; + if ($mode == 'customer') + { + $object=new Propal($this->db); + + $this->from = MAIN_DB_PREFIX.$object->table_element." as p"; + $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; + + $this->field='total_ht'; + $this->field_line='total_ht'; + + $this->where.= " p.fk_statut > 0"; + } + if ($mode == 'supplier') + { + $object=new SupplierProposal($this->db); + + $this->from = MAIN_DB_PREFIX.$object->table_element." as p"; + $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; + + $this->field='total_ht'; + $this->field_line='total_ht'; + + $this->where.= " p.fk_statut > 0"; + + $object=new CommandeFournisseur($this->db); + $this->from = MAIN_DB_PREFIX.$object->table_element." as c"; + $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; + $this->field='total_ht'; + $this->field_line='total_ht'; + $this->where.= " c.fk_statut > 2"; // Only approved & ordered + } //$this->where.= " AND p.fk_soc = s.rowid AND p.entity = ".$conf->entity; $this->where.= " AND p.entity IN (".getEntity('propal', 1).")"; if (!$user->rights->societe->client->voir && !$this->socid) $this->where .= " AND p.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; diff --git a/htdocs/comm/propal/stats/index.php b/htdocs/comm/propal/stats/index.php index 5ff5723a6c0..2f4c2ee342f 100644 --- a/htdocs/comm/propal/stats/index.php +++ b/htdocs/comm/propal/stats/index.php @@ -33,6 +33,10 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formpropal.class.php'; $WIDTH=DolGraph::getDefaultGraphSizeForStats('width'); $HEIGHT=DolGraph::getDefaultGraphSizeForStats('height'); +$mode=GETPOST("mode")?GETPOST("mode"):'customer'; +if ($mode == 'customer' && ! $user->rights->propale->lire) accessforbidden(); +if ($mode == 'supplier' && ! $user->rights->supplier_proposal->lire) accessforbidden(); + $object_statut=GETPOST('propal_statut'); $userid=GETPOST('userid','int'); @@ -50,7 +54,10 @@ $year = GETPOST('year')>0?GETPOST('year'):$nowyear; $startyear=$year-1; $endyear=$year; -$mode=GETPOST('mode'); +$langs->load('orders'); +$langs->load('companies'); +$langs->load('other'); +$langs->load('suppliers'); /* @@ -64,16 +71,26 @@ $langs->load('propal'); $langs->load('other'); $langs->load("companies"); -llxHeader('', $langs->trans("ProposalsStatistics")); +if ($mode == 'customer') +{ + $title=$langs->trans("ProposalsStatistics"); + $dir=$conf->propale->dir_temp; +} +if ($mode == 'supplier') +{ + $title=$langs->trans("ProposalsStatisticsSuppliers").' ('.$langs->trans("SentToSuppliers").")"; + $dir=$conf->supplier_proposal->dir_temp; +} -print load_fiche_titre($langs->trans("ProposalsStatistics"),'','title_commercial.png'); +llxHeader('', $title); + +print load_fiche_titre($title,'','title_commercial.png'); -$dir=$conf->propal->dir_temp; dol_mkdir($dir); -$stats = new PropaleStats($db, $socid, ($userid>0?$userid:0)); +$stats = new PropaleStats($db, $socid, ($userid>0?$userid:0), $mode); if ($object_statut != '' && $object_statut >= 0) $stats->where .= ' AND p.fk_statut IN ('.$object_statut.')'; // Build graphic number of object diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 9e7f5fae4f8..a152b005ee8 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -261,6 +261,13 @@ if (empty($reshook)) $object->fk_incoterms = GETPOST('incoterm_id', 'int'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); + // Fill array 'array_options' with data from add form + if (! $error) + { + $ret = $extrafields->setOptionalsFromPost($extralabels, $object); + if ($ret < 0) $error++; + } + // If creation from another object of another module (Example: origin=propal, originid=1) if (! empty($origin) && ! empty($originid)) { @@ -293,10 +300,6 @@ if (empty($reshook)) $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects); } - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost($extralabels, $object); - if ($ret < 0) $error++; - if (! $error) { $object_id = $object->create($user); @@ -386,10 +389,6 @@ if (empty($reshook)) $action = 'create'; } } else { - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost($extralabels, $object); - if ($ret < 0) $error++; - if (! $error) { $object_id = $object->create($user); diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index bf0331f251d..2bd1a592ba8 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -64,8 +64,6 @@ $langs->load('suppliers'); $form=new Form($db); -llxHeader(); - if ($mode == 'customer') { $title=$langs->trans("OrdersStatistics"); @@ -77,6 +75,8 @@ if ($mode == 'supplier') $dir=$conf->fournisseur->dir_output.'/commande/temp'; } +llxHeader('', $title); + print load_fiche_titre($title,'','title_commercial.png'); dol_mkdir($dir); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d1fa0b20448..005f4684322 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2384,14 +2384,14 @@ abstract class CommonObject { // Parse element/subelement (ex: project_task) $module = $element = $subelement = $objecttype; - if ($objecttype != 'order_supplier' && $objecttype != 'invoice_supplier' && preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs)) + if ($objecttype != 'supplier_proposal' && $objecttype != 'order_supplier' && $objecttype != 'invoice_supplier' + && preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs)) { $module = $element = $regs[1]; $subelement = $regs[2]; } $classpath = $element.'/class'; - // To work with non standard classpath or module name if ($objecttype == 'facture') { $classpath = 'compta/facture/class'; @@ -2427,7 +2427,10 @@ abstract class CommonObject else if ($objecttype == 'order_supplier') { $classfile = 'fournisseur.commande'; $classname = 'CommandeFournisseur'; } - + else if ($objecttype == 'supplier_proposal') { + $classfile = 'supplier_proposal'; $classname = 'SupplierProposal'; + } + // Here $module, $classfile and $classname are set if ($conf->$module->enabled && (($element != $this->element) || $alsosametype)) { @@ -2595,6 +2598,7 @@ abstract class CommonObject $error = 0; $trigkey=''; + if ($this->element == 'supplier_proposal' && $status == 2) $trigkey='SUPPLIER_PROPOSAL_CLOSE'; if ($this->element == 'fichinter' && $status == 2) $trigkey='FICHINTER_CLASSIFY_BILLED'; if ($this->element == 'fichinter' && $status == 1) $trigkey='FICHINTER_CLASSIFY_UNBILLED'; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 71c33a97e8c..6e1251e8703 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4967,13 +4967,13 @@ class Form { $tplpath = $element = $subelement = $objecttype; - if (preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs)) + if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs)) { $element = $regs[1]; $subelement = $regs[2]; $tplpath = $element.'/'.$subelement; } - + // To work with non standard path if ($objecttype == 'facture') { $tplpath = 'compta/'.$element; @@ -4984,7 +4984,6 @@ class Form if (empty($conf->propal->enabled)) continue; // Do not show if module disabled } else if ($objecttype == 'supplier_proposal') { - $tplpath = 'comm/'.$element; if (empty($conf->supplier_proposal->enabled)) continue; // Do not show if module disabled } else if ($objecttype == 'shipping' || $objecttype == 'shipment') { @@ -5001,7 +5000,7 @@ class Form else if ($objecttype == 'order_supplier') { $tplpath = 'fourn/commande'; } - + global $linkedObjectBlock; $linkedObjectBlock = $objects; diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 912b432174e..b54e9a560ac 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -162,6 +162,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->ficheinter->enabled', __HANDLER__, 'left', 1500__+MAX_llx_menu__, 'commercial', 'ficheinter', 5__+MAX_llx_menu__, '/fichinter/list.php?leftmenu=ficheinter', 'Interventions', 0, 'interventions', '$user->rights->ficheinter->lire', '', 2, 8, __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->ficheinter->enabled', __HANDLER__, 'left', 1501__+MAX_llx_menu__, 'commercial', '', 1500__+MAX_llx_menu__, '/fichinter/card.php?action=create&leftmenu=ficheinter', 'NewIntervention', 1, 'interventions', '$user->rights->ficheinter->creer', '', 2, 0, __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->ficheinter->enabled', __HANDLER__, 'left', 1502__+MAX_llx_menu__, 'commercial', '', 1500__+MAX_llx_menu__, '/fichinter/list.php?leftmenu=ficheinter', 'List', 1, 'interventions', '$user->rights->ficheinter->lire', '', 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->ficheinter->enabled', __HANDLER__, 'left', 1503__+MAX_llx_menu__, 'commercial', '', 1500__+MAX_llx_menu__, '/fichinter/stats/index.php?leftmenu=ficheinter', 'Statistics', 1, 'interventions', '$user->rights->ficheinter->lire', '', 2, 2, __ENTITY__); -- Accountancy - Supplier invoice 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->supplier_invoice->enabled', __HANDLER__, 'left', 1600__+MAX_llx_menu__, 'accountancy', 'supplier_bills', 6__+MAX_llx_menu__, '/fourn/facture/list.php?leftmenu=suppliers_bills', 'BillsSuppliers', 0, 'bills', '$user->rights->fournisseur->facture->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->supplier_invoice->enabled', __HANDLER__, 'left', 1601__+MAX_llx_menu__, 'accountancy', '', 1600__+MAX_llx_menu__, '/fourn/facture/card.php?action=create&leftmenu=suppliers_bills', 'NewBill', 1, 'bills', '$user->rights->fournisseur->facture->creer', '', 2, 0, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index ce8b166197b..d8649bc8e34 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -771,6 +771,8 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/fichinter/index.php?leftmenu=ficheinter", $langs->trans("Interventions"), 0, $user->rights->ficheinter->lire, '', $mainmenu, 'ficheinter', 2200); $newmenu->add("/fichinter/card.php?action=create&leftmenu=ficheinter", $langs->trans("NewIntervention"), 1, $user->rights->ficheinter->creer, '', '', '', 201); $newmenu->add("/fichinter/list.php?leftmenu=ficheinter", $langs->trans("List"), 1, $user->rights->ficheinter->lire, '', '', '', 202); + + $newmenu->add("/fichinter/stats/index.php?leftmenu=ficheinter", $langs->trans("Statistics"), 1, $user->rights->fournisseur->commande->lire); } } diff --git a/htdocs/core/modules/modSupplierProposal.class.php b/htdocs/core/modules/modSupplierProposal.class.php index 692cf2aefab..855ffde0ecf 100644 --- a/htdocs/core/modules/modSupplierProposal.class.php +++ b/htdocs/core/modules/modSupplierProposal.class.php @@ -52,7 +52,7 @@ class modSupplierProposal extends DolibarrModules $this->name = preg_replace('/^mod/i','',get_class($this)); $this->description = "supplier_proposalDESC"; - $this->version = 'experimental'; + $this->version = 'dolibarr'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->special = 0; @@ -114,15 +114,13 @@ class modSupplierProposal extends DolibarrModules $this->rights[$r][0] = $this->numero + $r; // id de la permission $this->rights[$r][1] = 'Validate supplier proposals'; // libelle de la permission $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut - $this->rights[$r][4] = ''; - $this->rights[$r][5] = 'validate'; + $this->rights[$r][4] = 'validate_advance'; $r++; $this->rights[$r][0] = $this->numero + $r; // id de la permission $this->rights[$r][1] = 'Envoyer les demandes fournisseurs'; // libelle de la permission $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut - $this->rights[$r][4] = ''; - $this->rights[$r][5] = 'send_advance'; + $this->rights[$r][4] = 'send_advance'; $r++; $this->rights[$r][0] = $this->numero + $r; // id de la permission @@ -178,6 +176,19 @@ class modSupplierProposal extends DolibarrModules 'position'=>302 ); $r++; + + $this->menu[$r]=array( + 'fk_menu'=>'fk_mainmenu=commercial,fk_leftmenu=supplier_proposalsubmenu', + 'type'=>'left', + 'titre'=>'Statistics', + 'url'=>'/comm/propal/stats/index.php?leftmenu=propals&mode=supplier', + 'langs'=>'supplier_proposal', + 'enabled'=>'$conf->supplier_proposal->enabled', + 'perms'=>'$user->rights->supplier_proposal->lire', + 'user'=>2, + 'position'=>303 + ); + $r++; } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 3b1fa498336..45bbb2c21cc 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -954,12 +954,12 @@ if (empty($reshook)) $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects); } - $object_id = $object->create($user); - if ($object_id > 0) + $id = $object->create($user); + if ($id > 0) { dol_include_once('/' . $element . '/class/' . $subelement . '.class.php'); - $classname = ucfirst($subelement); + $classname = 'SupplierProposal'; $srcobject = new $classname($db); dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines"); @@ -980,7 +980,7 @@ if (empty($reshook)) $num = count($lines); $productsupplier = new ProductFournisseur($db); - + for($i = 0; $i < $num; $i ++) { @@ -995,7 +995,7 @@ if (empty($reshook)) if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { $fk_parent_line = 0; } - + // Extrafields if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) // For avoid conflicts if // trigger used @@ -1003,10 +1003,13 @@ if (empty($reshook)) $lines[$i]->fetch_optionals($lines[$i]->rowid); $array_option = $lines[$i]->array_options; } - - $idprod = $productsupplier->find_min_price_product_fournisseur($lines[$i]->fk_product, $lines[$i]->qty); - $res = $productsupplier->fetch($idProductFourn); - + + $res = $productsupplier->find_min_price_product_fournisseur($lines[$i]->fk_product, $lines[$i]->qty); + /*if ($productsupplier->id > 0) + { + $res = $productsupplier->fetch($productsupplier->id); + }*/ + $result = $object->addline( $desc, $lines[$i]->subprice, @@ -1030,7 +1033,7 @@ if (empty($reshook)) ); if ($result < 0) { - $error ++; + $error++; break; } @@ -1040,10 +1043,13 @@ if (empty($reshook)) } } + // Add link between elements + + // Hooks $parameters = array('objFrom' => $srcobject); $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been - // modified by hook + if ($reshook < 0) $error ++; } else { @@ -1459,7 +1465,7 @@ if ($action=='create') dol_include_once('/' . $element . '/class/' . $subelement . '.class.php'); - $classname = ucfirst($subelement); + $classname = 'SupplierProposal'; $objectsrc = new $classname($db); $objectsrc->fetch($originid); if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) @@ -1604,8 +1610,6 @@ if ($action=='create') print ''; $newclassname = $classname; - if ($newclassname == 'SupplierProposal') - $newclassname = 'CommercialSupplierProposal'; print '' . $langs->trans($newclassname) . '' . $objectsrc->getNomUrl(1) . ''; print '' . $langs->trans('TotalHT') . '' . price($objectsrc->total_ht) . ''; print '' . $langs->trans('TotalVAT') . '' . price($objectsrc->total_tva) . ""; @@ -2830,7 +2834,7 @@ elseif (! empty($object->id)) // Linked object block $somethingshown = $form->showLinkedObjectBlock($object); - + // Show links to link elements //$linktoelem = $form->showLinkToObjectBlock($object); //if ($linktoelem) print '
'.$linktoelem; diff --git a/htdocs/install/mysql/tables/llx_supplier_proposal.sql b/htdocs/install/mysql/tables/llx_supplier_proposal.sql index ef307b85c9f..cb0324a3ad4 100644 --- a/htdocs/install/mysql/tables/llx_supplier_proposal.sql +++ b/htdocs/install/mysql/tables/llx_supplier_proposal.sql @@ -31,7 +31,7 @@ CREATE TABLE llx_supplier_proposal ( fk_user_modif integer DEFAULT NULL, fk_user_valid integer DEFAULT NULL, fk_user_cloture integer DEFAULT NULL, - fk_statut smallint NOT NULL DEFAULT '0', + fk_statut smallint NOT NULL DEFAULT '0', -- 0=draft, 1=validated, 2=accepted, 3=refused price double DEFAULT '0', remise_percent double DEFAULT '0', remise_absolue double DEFAULT '0', diff --git a/htdocs/install/mysql/tables/llx_website.key.sql b/htdocs/install/mysql/tables/llx_website.key.sql new file mode 100644 index 00000000000..cdaa38079b3 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_website.key.sql @@ -0,0 +1,23 @@ +-- ============================================================================ +-- Copyright (C) 2016 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 . +-- +-- =========================================================================== + +ALTER TABLE llx_website_page ADD UNIQUE INDEX uk_website_page_url (fk_website,pageurl); + +ALTER TABLE llx_website_page ADD CONSTRAINT fk_website_page_website FOREIGN KEY (fk_website) REFERENCES llx_website (rowid); + + diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index f78ac37601c..e93af58f26b 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -63,7 +63,8 @@ DatePropal=Date of proposal DateEndPropal=Validity ending date DateEndPropalShort=Date end ValidityDuration=Validity duration -CloseAs=Close with status +CloseAs=Set status to +SetAcceptedRefused=Set accepted/refused ClassifyBilled=Classify billed BuildBill=Build invoice ErrorPropalNotFound=Propal %s not found diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 2a64fa5d4c5..82eeb323a36 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2014 Laurent Destailleur + * Copyright (C) 2004-2016 Laurent Destailleur * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005 Marc Barilley / Ocebo * Copyright (C) 2005-2012 Regis Houssin @@ -45,6 +45,7 @@ $langs->load('companies'); $langs->load('supplier_proposal'); $langs->load('compta'); $langs->load('bills'); +$langs->load('propal'); $langs->load('orders'); $langs->load('products'); $langs->load("deliveries"); @@ -173,7 +174,7 @@ if (empty($reshook)) // Validation else if ($action == 'confirm_validate' && $confirm == 'yes' && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->creer)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate))) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate_advance))) ) { $result = $object->valid($user); @@ -434,6 +435,14 @@ if (empty($reshook)) } // Close proposal + else if ($action == 'close' && $user->rights->supplier_proposal->cloturer && ! GETPOST('cancel')) { + // prevent browser refresh from reopening proposal several times + if ($object->statut == 2) { + $object->setStatut(4); + } + } + + // Set accepted/refused else if ($action == 'setstatut' && $user->rights->supplier_proposal->cloturer && ! GETPOST('cancel')) { if (! GETPOST('statut')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("CloseAs")), null, 'errors'); @@ -441,7 +450,7 @@ if (empty($reshook)) } else { // prevent browser refresh from closing proposal several times if ($object->statut == 1) { - $object->cloture($user, GETPOST('statut'), GETPOST('note')); + $object->cloture($user, GETPOST('statut'), GETPOST('note')); } } } @@ -1596,11 +1605,9 @@ if ($action == 'create') if ($action == 'statut') { - /* - * Form to close proposal (signed or not) - */ + // Form to set proposal accepted/refused $form_close = '
'; - $form_close .= '

'.$langs->trans('SupplierProposalRefFournNotice').'

'; + if (! empty($conf->global->SUPPLIER_PROPOSAL_UPDATE_PRICE_ON_SUPPlIER_PROPOSAL)) $form_close .= '

'.$langs->trans('SupplierProposalRefFournNotice').'

'; // TODO Suggest a permanent checkbox instead of option $form_close .= ''; $form_close .= ''; $form_close .= ''; $form_close .= ''; $form_close .= '
' . $langs->trans("CloseAs") . ''; @@ -1615,9 +1622,9 @@ if ($action == 'create') $form_close .= $object->note; $form_close .= '
'; - $form_close .= ''; + $form_close .= ''; $form_close .= '   '; - $form_close .= ' '; + $form_close .= ' '; $form_close .= '
'; @@ -1640,7 +1647,7 @@ if ($action == 'create') // Validate if ($object->statut == 0 && $object->total_ttc >= 0 && count($object->lines) > 0 && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->creer)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate))) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate_advance))) ) { if (count($object->lines) > 0) print ''; @@ -1660,7 +1667,7 @@ if ($action == 'create') // Send if ($object->statut == 1 || $object->statut == 2) { - if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->supplier_proposal->send) { + if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->supplier_proposal->send_advance) { print ''; } else print ''; @@ -1673,12 +1680,18 @@ if ($action == 'create') } } - // Close + // Set accepted/refused if ($object->statut == 1 && $user->rights->supplier_proposal->cloturer) { - print ''; + print ''; } + // Close + if ($object->statut == 2 && $user->rights->supplier_proposal->cloturer) { + print ''; + } + // Clone if ($user->rights->supplier_proposal->creer) { print ''; diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 54a578a1e61..97f52526e66 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -27,7 +27,7 @@ */ /** - * \file htdocs/supplier_proposal/class/supplier_propal.class.php + * \file htdocs/supplier_proposal/class/supplier_proposal.class.php * \brief File of class to manage supplier proposals */ @@ -151,16 +151,16 @@ class SupplierProposal extends CommonObject $this->remise_absolue = 0; $langs->load("supplier_proposal"); - $this->labelstatut[0]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_DRAFT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_DRAFT_LABEL : $langs->trans("SupplierProposalStatusDraft")); - $this->labelstatut[1]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_VALIDATED_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_VALIDATED_LABEL : $langs->trans("SupplierProposalStatusValidated")); - $this->labelstatut[2]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_SIGNED_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_SIGNED_LABEL : $langs->trans("SupplierProposalStatusSigned")); - $this->labelstatut[3]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_NOTSIGNED_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_NOTSIGNED_LABEL : $langs->trans("SupplierProposalStatusNotSigned")); - $this->labelstatut[4]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_BILLED_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_BILLED_LABEL : $langs->trans("SupplierProposalStatusBilled")); - $this->labelstatut_short[0]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_DRAFTSHORT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_DRAFTSHORT_LABEL : $langs->trans("SupplierProposalStatusDraftShort")); - $this->labelstatut_short[1]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_VALIDATEDSHORT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_VALIDATEDSHORT_LABEL : $langs->trans("Opened")); - $this->labelstatut_short[2]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_SIGNEDSHORT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_SIGNEDSHORT_LABEL : $langs->trans("SupplierProposalStatusSignedShort")); - $this->labelstatut_short[3]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_NOTSIGNEDSHORT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_NOTSIGNEDSHORT_LABEL : $langs->trans("SupplierProposalStatusNotSignedShort")); - $this->labelstatut_short[4]=(! empty($conf->global->SUPPLIER_PROPOSAL_STATUS_BILLEDSHORT_LABEL) ? $conf->global->SUPPLIER_PROPOSAL_STATUS_BILLEDSHORT_LABEL : $langs->trans("SupplierProposalStatusBilledShort")); + $this->labelstatut[0]=$langs->trans("SupplierProposalStatusDraft"); + $this->labelstatut[1]=$langs->trans("SupplierProposalStatusValidated"); + $this->labelstatut[2]=$langs->trans("SupplierProposalStatusSigned"); + $this->labelstatut[3]=$langs->trans("SupplierProposalStatusNotSigned"); + $this->labelstatut[4]=$langs->trans("SupplierProposalStatusClosed"); + $this->labelstatut_short[0]=$langs->trans("SupplierProposalStatusDraftShort"); + $this->labelstatut_short[1]=$langs->trans("Opened"); + $this->labelstatut_short[2]=$langs->trans("SupplierProposalStatusSignedShort"); + $this->labelstatut_short[3]=$langs->trans("SupplierProposalStatusNotSignedShort"); + $this->labelstatut_short[4]=$langs->trans("SupplierProposalStatusClosedShort"); } @@ -1257,7 +1257,7 @@ class SupplierProposal extends CommonObject $now=dol_now(); if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->creer)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate))) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->supplier_proposal->validate_advance))) { $this->db->begin(); @@ -1545,7 +1545,7 @@ class SupplierProposal extends CommonObject $soc=new Societe($this->db); $soc->id = $this->socid; $result=$soc->set_as_client(); - + if ($result < 0) { $this->error=$this->db->error(); @@ -1554,14 +1554,17 @@ class SupplierProposal extends CommonObject } else { - $this->updateOrCreatePriceFournisseur($user); + if (! empty($conf->global->SUPPLIER_PROPOSAL_UPDATE_PRICE_ON_SUPPlIER_PROPOSAL)) // TODO This option was not tested correctly. Error if product ref does not exists + { + $result = $this->updateOrCreatePriceFournisseur($user); + } } } if ($statut == 4) { $trigger_name='SUPPLIER_PROPOSAL_CLASSIFY_BILLED'; } - + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { // Define output language @@ -1594,25 +1597,27 @@ class SupplierProposal extends CommonObject } else { - $this->error=$this->db->error(); + $this->error=$this->db->lasterror(); + $this->errors[]=$this->db->lasterror(); $this->db->rollback(); return -1; } } /** - * Choose between update or create ProductFournisseur + * Add or update supplier price according to result of proposal * - * @param User $user Object user + * @param User $user Object user + * @return int > 0 if OK */ function updateOrCreatePriceFournisseur($user) { $productsupplier = new ProductFournisseur($this->db); dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG); - foreach ($this->lines as $product) { - if ($product->subprice <= 0) - continue; + foreach ($this->lines as $product) + { + if ($product->subprice <= 0) continue; $idProductFourn = $productsupplier->find_min_price_product_fournisseur($product->fk_product, $product->qty); $res = $productsupplier->fetch($idProductFourn); @@ -1627,6 +1632,8 @@ class SupplierProposal extends CommonObject $this->createPriceFournisseur($product, $user); } } + + return 1; } /** From 274caf61ebac81b5061bb062023abe46f04f8eea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jan 2016 13:31:43 +0100 Subject: [PATCH 03/12] NEW Add statistics for interventions module --- .../comm/propal/class/propalestats.class.php | 31 +- htdocs/comm/propal/stats/index.php | 2 +- htdocs/commande/stats/index.php | 12 +- htdocs/core/class/html.formpropal.class.php | 119 ++++--- .../modules/modSupplierProposal.class.php | 7 +- htdocs/fichinter/card.php | 19 +- .../fichinter/class/fichinterstats.class.php | 211 +++++++++++ htdocs/fichinter/stats/index.php | 337 ++++++++++++++++++ htdocs/install/mysql/tables/llx_propal.sql | 2 +- .../mysql/tables/llx_supplier_proposal.sql | 2 +- htdocs/langs/en_US/interventions.lang | 3 + htdocs/langs/en_US/propal.lang | 1 + 12 files changed, 650 insertions(+), 96 deletions(-) create mode 100644 htdocs/fichinter/class/fichinterstats.class.php create mode 100644 htdocs/fichinter/stats/index.php diff --git a/htdocs/comm/propal/class/propalestats.class.php b/htdocs/comm/propal/class/propalestats.class.php index 11014537337..e38297a3377 100644 --- a/htdocs/comm/propal/class/propalestats.class.php +++ b/htdocs/comm/propal/class/propalestats.class.php @@ -67,7 +67,7 @@ class PropaleStats extends Stats $this->from = MAIN_DB_PREFIX.$object->table_element." as p"; $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; - + $this->field_date='p.datep'; $this->field='total_ht'; $this->field_line='total_ht'; @@ -79,18 +79,11 @@ class PropaleStats extends Stats $this->from = MAIN_DB_PREFIX.$object->table_element." as p"; $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; - + $this->field_date='p.date_valid'; $this->field='total_ht'; $this->field_line='total_ht'; - $this->where.= " p.fk_statut > 0"; - - $object=new CommandeFournisseur($this->db); - $this->from = MAIN_DB_PREFIX.$object->table_element." as c"; - $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; - $this->field='total_ht'; - $this->field_line='total_ht'; - $this->where.= " c.fk_statut > 2"; // Only approved & ordered + $this->where.= " p.fk_statut > 0"; // Validated, accepted, refused and closed } //$this->where.= " AND p.fk_soc = s.rowid AND p.entity = ".$conf->entity; $this->where.= " AND p.entity IN (".getEntity('propal', 1).")"; @@ -113,10 +106,10 @@ class PropaleStats extends Stats { global $user; - $sql = "SELECT date_format(p.datep,'%m') as dm, COUNT(*) as nb"; + $sql = "SELECT date_format(".$this->field_date.",'%m') as dm, COUNT(*) as nb"; $sql.= " FROM ".$this->from; if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE p.datep BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " WHERE ".$this->field_date." BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -135,7 +128,7 @@ class PropaleStats extends Stats { global $user; - $sql = "SELECT date_format(p.datep,'%Y') as dm, COUNT(*) as nb, SUM(c.".$this->field.")"; + $sql = "SELECT date_format(".$this->field_date.",'%Y') as dm, COUNT(*) as nb, SUM(c.".$this->field.")"; $sql.= " FROM ".$this->from; if (!$user->rights->societe->client->voir && !$this->socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE ".$this->where; @@ -155,10 +148,10 @@ class PropaleStats extends Stats { global $user; - $sql = "SELECT date_format(p.datep,'%m') as dm, SUM(p.".$this->field.")"; + $sql = "SELECT date_format(".$this->field_date.",'%m') as dm, SUM(p.".$this->field.")"; $sql.= " FROM ".$this->from; if (!$user->rights->societe->client->voir && !$this->socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE p.datep BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " WHERE ".$this->field_date." BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -177,10 +170,10 @@ class PropaleStats extends Stats { global $user; - $sql = "SELECT date_format(p.datep,'%m') as dm, AVG(p.".$this->field.")"; + $sql = "SELECT date_format(".$this->field_date.",'%m') as dm, AVG(p.".$this->field.")"; $sql.= " FROM ".$this->from; if (!$user->rights->societe->client->voir && !$this->socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE p.datep BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " WHERE ".$this->field_date." BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -197,7 +190,7 @@ class PropaleStats extends Stats { global $user; - $sql = "SELECT date_format(p.datep,'%Y') as year, COUNT(*) as nb, SUM(".$this->field.") as total, AVG(".$this->field.") as avg"; + $sql = "SELECT date_format(".$this->field_date.",'%Y') as year, COUNT(*) as nb, SUM(".$this->field.") as total, AVG(".$this->field.") as avg"; $sql.= " FROM ".$this->from; if (!$user->rights->societe->client->voir && !$this->socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE ".$this->where; @@ -224,7 +217,7 @@ class PropaleStats extends Stats if (!$user->rights->societe->client->voir && !$user->socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE ".$this->where; $sql.= " AND p.rowid = tl.fk_propal AND tl.fk_product = product.rowid"; - $sql.= " AND p.datep BETWEEN '".$this->db->idate(dol_get_first_day($year,1,false))."' AND '".$this->db->idate(dol_get_last_day($year,12,false))."'"; + $sql.= " AND ".$this->field_date." BETWEEN '".$this->db->idate(dol_get_first_day($year,1,false))."' AND '".$this->db->idate(dol_get_last_day($year,12,false))."'"; $sql.= " GROUP BY product.ref"; $sql.= $this->db->order('nb','DESC'); //$sql.= $this->db->plimit(20); diff --git a/htdocs/comm/propal/stats/index.php b/htdocs/comm/propal/stats/index.php index 2f4c2ee342f..2c93f874baa 100644 --- a/htdocs/comm/propal/stats/index.php +++ b/htdocs/comm/propal/stats/index.php @@ -265,7 +265,7 @@ print '
'; print ''; // Status print ''.$langs->trans("Status").''; - $formpropal->selectProposalStatus($object_statut,0,1); + $formpropal->selectProposalStatus($object_statut,0,1,1,$mode); print ''; // Year print ''.$langs->trans("Year").''; diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index 2bd1a592ba8..1f0f763bfd1 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -277,12 +277,12 @@ print '
'; print ''; print ''; print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; print ''; $oldyear=0; diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index e3f21212e8b..d64cd23e98d 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -49,66 +49,85 @@ class FormPropal * @param int $short Use short labels * @param int $excludedraft 0=All status, 1=Exclude draft status * @param int $showempty 1=Add empty line + * @param string $mode 'customer', 'supplier' * @return void */ - function selectProposalStatus($selected='',$short=0, $excludedraft=0, $showempty=1) + function selectProposalStatus($selected='',$short=0, $excludedraft=0, $showempty=1, $mode='customer') { global $langs; - $sql = "SELECT id, code, label, active FROM ".MAIN_DB_PREFIX."c_propalst"; - $sql .= " WHERE active = 1"; - - dol_syslog(get_class($this)."::selectProposalStatus", LOG_DEBUG); - $resql=$this->db->query($sql); - if ($resql) + $prefix=''; + $listofstatus=array(); + if ($mode == 'supplier') { - print ''; + $prefix='SupplierProposalStatus'; + + $langs->load("supplier_proposal"); + $listofstatus=array(0=>array('code'=>'PR_DRAFT'), 1=>array('code'=>'PR_OPEN'), 2=>array('code'=>'PR_SIGNED'), 3=>array('code'=>'PR_NOTSIGNED'), 4=>array('code'=>'PR_CLOSED')); } else { - dol_print_error($this->db); + $prefix="PropalStatus"; + + $sql = "SELECT id, code, label, active FROM ".MAIN_DB_PREFIX."c_propalst"; + $sql .= " WHERE active = 1"; + dol_syslog(get_class($this)."::selectProposalStatus", LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num = $this->db->num_rows($resql); + $i = 0; + if ($num) + { + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + $listofstatus[$obj->id]=array('id'=>$obj->id,'code'=>$obj->code,'label'=>$obj->label); + } + } + } + else + { + dol_print_error($this->db); + } } - } + print ''; + } } diff --git a/htdocs/core/modules/modSupplierProposal.class.php b/htdocs/core/modules/modSupplierProposal.class.php index 855ffde0ecf..f38ce9b7f7e 100644 --- a/htdocs/core/modules/modSupplierProposal.class.php +++ b/htdocs/core/modules/modSupplierProposal.class.php @@ -23,6 +23,7 @@ /** * \defgroup supplier_proposal Module supplier_proposal * \brief Module to request supplier price proposals + * * \file htdocs/core/modules/modSupplierProposal.class.php * \ingroup supplier_proposal * \brief File to describe and activate module SupplierProposal @@ -155,7 +156,7 @@ class modSupplierProposal extends DolibarrModules 'fk_menu'=>'fk_mainmenu=commercial,fk_leftmenu=supplier_proposalsubmenu', 'type'=>'left', 'titre'=>'SupplierProposalNew', - 'url'=>'/supplier_proposal/card.php?action=create', + 'url'=>'/supplier_proposal/card.php?action=create&leftmenu=supplier_proposals', 'langs'=>'supplier_proposal', 'enabled'=>'$conf->supplier_proposal->enabled', 'perms'=>'$user->rights->supplier_proposal->creer', @@ -168,7 +169,7 @@ class modSupplierProposal extends DolibarrModules 'fk_menu'=>'fk_mainmenu=commercial,fk_leftmenu=supplier_proposalsubmenu', 'type'=>'left', 'titre'=>'List', - 'url'=>'/supplier_proposal/list.php', + 'url'=>'/supplier_proposal/list.php?leftmenu=supplier_proposals', 'langs'=>'supplier_proposal', 'enabled'=>'$conf->supplier_proposal->enabled', 'perms'=>'$user->rights->supplier_proposal->lire', @@ -181,7 +182,7 @@ class modSupplierProposal extends DolibarrModules 'fk_menu'=>'fk_mainmenu=commercial,fk_leftmenu=supplier_proposalsubmenu', 'type'=>'left', 'titre'=>'Statistics', - 'url'=>'/comm/propal/stats/index.php?leftmenu=propals&mode=supplier', + 'url'=>'/comm/propal/stats/index.php?leftmenu=supplier_proposals&mode=supplier', 'langs'=>'supplier_proposal', 'enabled'=>'$conf->supplier_proposal->enabled', 'perms'=>'$user->rights->supplier_proposal->lire', diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 4d80ac04039..4ba91ba7e96 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1275,21 +1275,10 @@ else if ($id > 0 || ! empty($ref)) print ''; print ''; print ''; - - // Date create - print ''; - print ''; - print ''; - - // Date Validation - print ''; - print ''; - print ''; - + } + + if (! empty($conf->global->FICHINTER_USE_PLANNED_AND_DONE_DATES)) + { // Date Start print ''; print ''; } @@ -2039,7 +2039,7 @@ else print '
'.$langs->trans("Year").''.$langs->trans("NbOfOrders").'%'.$langs->trans("AmountTotal").'%'.$langs->trans("AmountAverage").'%'.$langs->trans("NbOfOrders").'%'.$langs->trans("AmountTotal").'%'.$langs->trans("AmountAverage").'%
'.$langs->trans("TotalDuration").''.convertSecondToTime($object->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).'
'.$langs->trans("Datec").''; - print $object->datec ? dol_print_date($object->datec, 'daytext') : ' '; - print '
'.$langs->trans("Datev").''; - print $object->datev ? dol_print_date($object->datev, 'daytext') : ' '; - print '
'.$langs->trans("Dateo").''; diff --git a/htdocs/fichinter/class/fichinterstats.class.php b/htdocs/fichinter/class/fichinterstats.class.php new file mode 100644 index 00000000000..1219a83d9e0 --- /dev/null +++ b/htdocs/fichinter/class/fichinterstats.class.php @@ -0,0 +1,211 @@ + + * Copyright (c) 2005-2013 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2012 Marcos García + * + * 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/fichinter/class/fichinterstats.class.php + * \ingroup fichinter + * \brief File of class to manage intervention statistics + */ +include_once DOL_DOCUMENT_ROOT . '/core/class/stats.class.php'; +include_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php'; +include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; + + +/** + * Class to manage intervention statistics + */ +class FichinterStats extends Stats +{ + public $table_element; + + var $socid; + var $userid; + + var $from; + var $field; + var $where; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param int $socid Id third party for filter. This value must be forced during the new to external user company if user is an external user. + * @param string $mode Option ('customer', 'supplier') + * @param int $userid Id user for filter (creation user) + */ + function __construct($db, $socid, $mode, $userid=0) + { + global $user, $conf; + + $this->db = $db; + + $this->socid = ($socid > 0 ? $socid : 0); + $this->userid = $userid; + $this->cachefilesuffix = $mode; + + if ($mode == 'customer') + { + $object=new Fichinter($this->db); + $this->from = MAIN_DB_PREFIX.$object->table_element." as c"; + $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; + $this->field='0'; + $this->field_line='0'; + $this->where.= " c.fk_statut > 0"; // Not draft and not cancelled + } + //$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity; + $this->where.= " AND c.entity = ".$conf->entity; + if (!$user->rights->societe->client->voir && !$this->socid) $this->where .= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; + if ($this->socid) + { + $this->where.=" AND c.fk_soc = ".$this->socid; + } + if ($this->userid > 0) $this->where.=' AND c.fk_user_author = '.$this->userid; + } + + /** + * Return intervention number by month for a year + * + * @param int $year Year to scan + * @return array Array with number by month + */ + function getNbByMonth($year) + { + global $user; + + $sql = "SELECT date_format(c.date_valid,'%m') as dm, COUNT(*) as nb"; + $sql.= " FROM ".$this->from; + if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + $res=$this->_getNbByMonth($year, $sql); + return $res; + } + + /** + * Return interventions number per year + * + * @return array Array with number by year + * + */ + function getNbByYear() + { + global $user; + + $sql = "SELECT date_format(c.date_valid,'%Y') as dm, COUNT(*) as nb, 0"; + $sql.= " FROM ".$this->from; + if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + return $this->_getNbByYear($sql); + } + + /** + * Return the intervention amount by month for a year + * + * @param int $year Year to scan + * @return array Array with amount by month + */ + function getAmountByMonth($year) + { + global $user; + + $sql = "SELECT date_format(c.date_valid,'%m') as dm, 0"; + $sql.= " FROM ".$this->from; + if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + $res=$this->_getAmountByMonth($year, $sql); + return $res; + } + + /** + * Return the intervention amount average by month for a year + * + * @param int $year year for stats + * @return array array with number by month + */ + function getAverageByMonth($year) + { + global $user; + + $sql = "SELECT date_format(c.date_valid,'%m') as dm, 0"; + $sql.= " FROM ".$this->from; + if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + return $this->_getAverageByMonth($year, $sql); + } + + /** + * Return nb, total and average + * + * @return array Array of values + */ + function getAllByYear() + { + global $user; + + $sql = "SELECT date_format(c.date_valid,'%Y') as year, COUNT(*) as nb, 0 as total, 0 as avg"; + $sql.= " FROM ".$this->from; + if (!$user->rights->societe->client->voir && !$this->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE ".$this->where; + $sql.= " GROUP BY year"; + $sql.= $this->db->order('year','DESC'); + + return $this->_getAllByYear($sql); + } + + /** + * Return nb, amount of predefined product for year + * + * @param int $year Year to scan + * @return array Array of values + */ + function getAllByProduct($year) + { + global $user; + + $sql = "SELECT product.ref, COUNT(product.ref) as nb, 0 as total, 0 as avg"; + $sql.= " FROM ".$this->from.", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product"; + //if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE ".$this->where; + $sql.= " AND c.rowid = tl.fk_fichinter AND tl.fk_product = product.rowid"; + $sql.= " AND c.date_valid BETWEEN '".$this->db->idate(dol_get_first_day($year,1,false))."' AND '".$this->db->idate(dol_get_last_day($year,12,false))."'"; + $sql.= " GROUP BY product.ref"; + $sql.= $this->db->order('nb','DESC'); + //$sql.= $this->db->plimit(20); + + return $this->_getAllByProduct($sql); + } + +} + diff --git a/htdocs/fichinter/stats/index.php b/htdocs/fichinter/stats/index.php new file mode 100644 index 00000000000..5cdd7923cbd --- /dev/null +++ b/htdocs/fichinter/stats/index.php @@ -0,0 +1,337 @@ + + * + * 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/fichinter/stats/index.php + * \ingroup fichinter + * \brief Page with interventions statistics + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinterstats.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; + +$WIDTH=DolGraph::getDefaultGraphSizeForStats('width'); +$HEIGHT=DolGraph::getDefaultGraphSizeForStats('height'); + +$mode='customer'; +if ($mode == 'customer' && ! $user->rights->ficheinter->lire) accessforbidden(); + +$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('interventions'); +$langs->load('companies'); +$langs->load('other'); +$langs->load('suppliers'); + + +/* + * View + */ + +$form=new Form($db); + +if ($mode == 'customer') +{ + $title=$langs->trans("InterventionStatistics"); + $dir=$conf->ficheinter->dir_temp; +} + +llxHeader('', $title); + +print load_fiche_titre($title,'','title_commercial.png'); + +dol_mkdir($dir); + +$stats = new FichinterStats($db, $socid, $mode, ($userid>0?$userid:0)); + +// Build graphic number of object +$data = $stats->getNbByMonthWithPrevYear($endyear,$startyear); +//var_dump($data); +// $data = array(array('Lib',val1,val2,val3),...) + + +if (!$user->rights->societe->client->voir || $user->societe_id) +{ + $filenamenb = $dir.'/interventionsnbinyear-'.$user->id.'-'.$year.'.png'; + if ($mode == 'customer') $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsnbinyear-'.$user->id.'-'.$year.'.png'; +} +else +{ + $filenamenb = $dir.'/interventionsnbinyear-'.$year.'.png'; + if ($mode == 'customer') $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsnbinyear-'.$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->SetMinValue(min(0,$px1->GetFloorMinValue())); + $px1->SetWidth($WIDTH); + $px1->SetHeight($HEIGHT); + $px1->SetYLabel($langs->trans("NbOfIntervention")); + $px1->SetShading(3); + $px1->SetHorizTickIncrement(1); + $px1->SetPrecisionY(0); + $px1->mode='depth'; + $px1->SetTitle($langs->trans("NumberOfInterventionsByMonth")); + + $px1->draw($filenamenb,$fileurlnb); +} + +// Build graphic amount of object +$data = $stats->getAmountByMonthWithPrevYear($endyear,$startyear); +//var_dump($data); +// $data = array(array('Lib',val1,val2,val3),...) + +if (!$user->rights->societe->client->voir || $user->societe_id) +{ + $filenameamount = $dir.'/interventionsamountinyear-'.$user->id.'-'.$year.'.png'; + if ($mode == 'customer') $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsamountinyear-'.$user->id.'-'.$year.'.png'; + if ($mode == 'supplier') $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstatssupplier&file=interventionsamountinyear-'.$user->id.'-'.$year.'.png'; +} +else +{ + $filenameamount = $dir.'/interventionsamountinyear-'.$year.'.png'; + if ($mode == 'customer') $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsamountinyear-'.$year.'.png'; + if ($mode == 'supplier') $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstatssupplier&file=interventionsamountinyear-'.$year.'.png'; +} + +$px2 = new DolGraph(); +$mesg = $px2->isGraphKo(); +if (! $mesg) +{ + $px2->SetData($data); + $i=$startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px2->SetLegend($legend); + $px2->SetMaxValue($px2->GetCeilMaxValue()); + $px2->SetMinValue(min(0,$px2->GetFloorMinValue())); + $px2->SetWidth($WIDTH); + $px2->SetHeight($HEIGHT); + $px2->SetYLabel($langs->trans("AmountOfinterventions")); + $px2->SetShading(3); + $px2->SetHorizTickIncrement(1); + $px2->SetPrecisionY(0); + $px2->mode='depth'; + $px2->SetTitle($langs->trans("AmountOfinterventionsByMonthHT")); + + $px2->draw($filenameamount,$fileurlamount); +} + + +$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear); + +if (!$user->rights->societe->client->voir || $user->societe_id) +{ + $filename_avg = $dir.'/interventionsaverage-'.$user->id.'-'.$year.'.png'; + if ($mode == 'customer') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsaverage-'.$user->id.'-'.$year.'.png'; + if ($mode == 'supplier') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstatssupplier&file=interventionsaverage-'.$user->id.'-'.$year.'.png'; +} +else +{ + $filename_avg = $dir.'/interventionsaverage-'.$year.'.png'; + if ($mode == 'customer') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstats&file=interventionsaverage-'.$year.'.png'; + if ($mode == 'supplier') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=interventionstatssupplier&file=interventionsaverage-'.$year.'.png'; +} + +$px3 = new DolGraph(); +$mesg = $px3->isGraphKo(); +if (! $mesg) +{ + $px3->SetData($data); + $i=$startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px3->SetLegend($legend); + $px3->SetYLabel($langs->trans("AmountAverage")); + $px3->SetMaxValue($px3->GetCeilMaxValue()); + $px3->SetMinValue($px3->GetFloorMinValue()); + $px3->SetWidth($WIDTH); + $px3->SetHeight($HEIGHT); + $px3->SetShading(3); + $px3->SetHorizTickIncrement(1); + $px3->SetPrecisionY(0); + $px3->mode='depth'; + $px3->SetTitle($langs->trans("AmountAverage")); + + $px3->draw($filename_avg,$fileurl_avg); +} + + + +// Show array +$data = $stats->getAllByYear(); +$arrayyears=array(); +foreach($data as $val) { + if (! empty($val['year'])) { + $arrayyears[$val['year']]=$val['year']; + } +} +if (! count($arrayyears)) $arrayyears[$nowyear]=$nowyear; + +$h=0; +$head = array(); +$head[$h][0] = DOL_URL_ROOT . '/commande/stats/index.php?mode='.$mode; +$head[$h][1] = $langs->trans("ByMonthYear"); +$head[$h][2] = 'byyear'; +$h++; + +if ($mode == 'customer') $type='order_stats'; +if ($mode == 'supplier') $type='supplier_order_stats'; + +complete_head_from_modules($conf,$langs,null,$head,$h,$type); + +dol_fiche_head($head,'byyear',$langs->trans("Statistics")); + + +print '
'; + + +//if (empty($socid)) +//{ + // Show filter box + print '
'; + print ''; + print ''; + print ''; + // Company + print ''; + // User + 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("CreatedBy").''; + print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300'); + // Year + 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 ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$oldyear=0; +$var=true; +foreach ($data as $val) +{ + $year = $val['year']; + while (! empty($year) && $oldyear > $year+1) + { // If we have empty year + $oldyear--; + $var=!$var; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + + $var=!$var; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $oldyear=$year; +} + +print '
'.$langs->trans("Year").''.$langs->trans("NbOfinterventions").'%'.$langs->trans("AmountTotal").'%'.$langs->trans("AmountAverage").'%
0?'&userid='.$userid:'').'">'.$oldyear.'000
0?'&userid='.$userid:'').'">'.$year.''.$val['nb'].''.round($val['nb_diff']).''.price(price2num($val['total'],'MT'),1).''.round($val['total_diff']).''.price(price2num($val['avg'],'MT'),1).''.round($val['avg_diff']).'
'; + + +print '
'; + + +// Show graphs +print '
'; +if ($mesg) { print $mesg; } +else { + print $px1->show(); + /*print "
\n"; + print $px2->show(); + print "
\n"; + print $px3->show();*/ +} +print '
'; + + +print '
'; +print '
'; + +dol_fiche_end(); + + +llxFooter(); + +$db->close(); diff --git a/htdocs/install/mysql/tables/llx_propal.sql b/htdocs/install/mysql/tables/llx_propal.sql index 8090b1fcb4d..402b141761f 100644 --- a/htdocs/install/mysql/tables/llx_propal.sql +++ b/htdocs/install/mysql/tables/llx_propal.sql @@ -42,7 +42,7 @@ create table llx_propal fk_user_modif integer, -- user making last change fk_user_valid integer, -- user validating fk_user_cloture integer, -- user closing (signed or not) - fk_statut smallint DEFAULT 0 NOT NULL, + fk_statut smallint DEFAULT 0 NOT NULL, -- 0=draft, 1=validated, 2=accepted, 3=refused, 4=billed/closed price real DEFAULT 0, -- (obsolete) remise_percent real DEFAULT 0, -- remise globale relative en pourcent (obsolete) remise_absolue real DEFAULT 0, -- remise globale absolue (obsolete) diff --git a/htdocs/install/mysql/tables/llx_supplier_proposal.sql b/htdocs/install/mysql/tables/llx_supplier_proposal.sql index cb0324a3ad4..e271d36ffe5 100644 --- a/htdocs/install/mysql/tables/llx_supplier_proposal.sql +++ b/htdocs/install/mysql/tables/llx_supplier_proposal.sql @@ -31,7 +31,7 @@ CREATE TABLE llx_supplier_proposal ( fk_user_modif integer DEFAULT NULL, fk_user_valid integer DEFAULT NULL, fk_user_cloture integer DEFAULT NULL, - fk_statut smallint NOT NULL DEFAULT '0', -- 0=draft, 1=validated, 2=accepted, 3=refused + fk_statut smallint NOT NULL DEFAULT '0', -- 0=draft, 1=validated, 2=accepted, 3=refused, 4=closed price double DEFAULT '0', remise_percent double DEFAULT '0', remise_absolue double DEFAULT '0', diff --git a/htdocs/langs/en_US/interventions.lang b/htdocs/langs/en_US/interventions.lang index 7e57d7da6a1..2d3a1d5a4a3 100644 --- a/htdocs/langs/en_US/interventions.lang +++ b/htdocs/langs/en_US/interventions.lang @@ -54,6 +54,9 @@ PacificNumRefModelDesc1=Return numero with format %syymm-nnnn where yy is year, PacificNumRefModelError=An intervention card starting with $syymm already exists and is not compatible with this model of sequence. Remove it or rename it to activate this module. PrintProductsOnFichinter=Print products on intervention card PrintProductsOnFichinterDetails=interventions generated from orders +InterventionStatistics=Statistics of interventions +NbOfinterventions=Nb of intervention cards +NumberOfInterventionsByMonth=Nb of intervention cards by month (date of validation) ##### Exports ##### InterId=Intervention id InterRef=Intervention ref. diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index e93af58f26b..15b10e7d92f 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -102,3 +102,4 @@ DefaultModelPropalCreate=Default model creation DefaultModelPropalToBill=Default template when closing a business proposal (to be invoiced) DefaultModelPropalClosed=Default template when closing a business proposal (unbilled) ProposalCustomerSignature=Written acceptance, company stamp, date and signature +ProposalsStatisticsSuppliers=Supplier proposals statistics \ No newline at end of file From 667651860d1417329488cf123069ca700e8acdae Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jan 2016 15:24:31 +0100 Subject: [PATCH 04/12] Fix sql injection #4341 --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index f1399655666..25176c6bc93 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -99,7 +99,7 @@ function test_sql_and_script_inject($val, $type) $sql_inj += preg_match('/'; -// Add a new project/task -print '
'; -print '
'; -print ''; -print ''; -print ''; -print ''; -print ''; -print $langs->trans("AssignTaskToMe").'
'; -$formproject->selectTasks($socid?$socid:-1, $taskid, 'taskid', 32, 0, 1, 1); -print $formcompany->selectTypeContact($object, '', 'type','internal','rowid', 0); -print ''; -print '
'; - - llxFooter(); $db->close(); diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index cc31d1090f8..13bfa001630 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -100,8 +100,10 @@ if (GETPOST('submitdateselect')) $action = ''; } -if ($action == 'assign') +if ($action == 'addtime' && GETPOST('assigntask')) { + $action = 'assigntask'; + if ($taskid > 0) { $result = $object->fetch($taskid, $ref); @@ -298,7 +300,24 @@ print "\n"; */ -print '
'.$nav.'
'; +// Add a new project/task +//print '
'; +//print '
'; +//print ''; +//print ''; +//print ''; +//print ''; +//print ''; +print '
'; +print $langs->trans("AssignTaskToMe").'
'; +$formproject->selectTasks($socid?$socid:-1, $taskid, 'taskid', 32, 0, 1, 1); +print $formcompany->selectTypeContact($object, '', 'type','internal','rowid', 0); +print ''; +//print ''; +print '
'; + +print '
'.$nav.'
'; +print '
'; print ''; @@ -378,22 +397,6 @@ print "});"; print ''; -// Add a new project/task -print '
'; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print $langs->trans("AssignTaskToMe").'
'; -$formproject->selectTasks($socid?$socid:-1, $taskid, 'taskid', 32, 0, 1, 1); -print $formcompany->selectTypeContact($object, '', 'type','internal','rowid', 0); -print ''; -print ''; - - - llxFooter(); $db->close(); diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 82027cd613b..ccb3f01d293 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -2547,6 +2547,10 @@ div.tabBar .noborder { background-color: #; } +span.boxstatstext { + opacity: 0.8; + line-height: 18px; +} span.boxstatsindicator { font-size: 110%; font-weight: normal; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 29f2294bd54..782eb0d66a2 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -2374,6 +2374,10 @@ div.tabBar .noborder { background-color: #; } +span.boxstatstext { + opacity: 0.8; + line-height: 18px; +} span.boxstatsindicator { font-size: 110%; font-weight: normal; From ce02f05d4378d89d6219963baec6226137f97652 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jan 2016 17:18:17 +0100 Subject: [PATCH 08/12] Translation of dashboard --- htdocs/core/menus/standard/eldy.lib.php | 2 +- htdocs/langs/en_US/main.lang | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index d8649bc8e34..6263b1b709d 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -487,7 +487,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $langs->load("users"); // Home - dashboard - $newmenu->add("/index.php?mainmenu=home&leftmenu=home", $langs->trans("Home"), 0, 1, '', $mainmenu, 'home'); + $newmenu->add("/index.php?mainmenu=home&leftmenu=home", $langs->trans("Dashboard"), 0, 1, '', $mainmenu, 'home'); // Setup $newmenu->add("/admin/index.php?mainmenu=home&leftmenu=setup", $langs->trans("Setup"), 0, $user->admin, '', $mainmenu, 'setup'); diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 7a23657123f..5990ee991d9 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -700,6 +700,7 @@ Test=Test Element=Element NoPhotoYet=No pictures available yet HomeDashboard=Home summary +Dashboard=Dashboard Deductible=Deductible from=from toward=toward From 06bbf4c966188a2ab141eec21ad4a51ae89b0015 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jan 2016 21:10:42 +0100 Subject: [PATCH 09/12] Fix empty keys are not allowed into select --- htdocs/core/class/extrafields.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 909afda913a..ee5f1465e3f 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -748,8 +748,9 @@ class ExtraFields $out.=''; } print ''."\n"; @@ -1110,12 +1110,13 @@ if ($action == 'create') $form->select_date($datecontrat,'',0,0,'',"contrat"); print ""; + // Project if (! empty($conf->projet->enabled)) { $formproject=new FormProjets($db); print '"; } @@ -1325,11 +1326,11 @@ else print '"; } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6e1251e8703..2230aebdbb5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3444,7 +3444,7 @@ class Form * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id) * @param int $selected Id pre-selected project * @param string $htmlname Name of select field - * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely,2=Disable) + * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely except $selected,2=Disable) * @param int $maxlength Max length * @param int $forcefocus Force focus on field (works with javascript only) * @return void @@ -3467,7 +3467,7 @@ class Form print ''; print '
'; - print $form->select_company('','socid','',1); + print $form->select_company('','socid','',1,1); print '
'.$langs->trans("Project").''; - $formproject->select_projects($soc->id,$projectid,"projectid"); + $formproject->select_projects(($soc->id>0?$soc->id:-1),$projectid,"projectid",0,0,1,1); print "
'; if ($action == "classify") { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id,$object->socid,$object->fk_project,"projectid", 0, 0, 1); + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, "projectid", 1, 0, 1); } else { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id,$object->socid,$object->fk_project,"none", 0, 0); + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, "none", 0, 0); } print "
'; print ''; print ''; print '
'; - $formproject->select_projects($socid,$selected,$htmlname,$maxlength,0,1,$discard_closed, $forcefocus); + $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus); print '
'; diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 3b26576b0fa..498604d9307 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -55,13 +55,13 @@ class FormProjets * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely,2=Disable) * @param int $forcefocus Force focus on field (works with javascript only) * @param int $disabled Disabled - * @param int $mode 0 for HTML mode and 1 for JSON mode - * @param string $filterkey Key to filter + * @param int $mode 0 for HTML mode and 1 for JSON mode + * @param string $filterkey Key to filter * @return int Nber of project if OK, <0 if KO */ function select_projects($socid=-1, $selected='', $htmlname='projectid', $maxlength=16, $option_only=0, $show_empty=1, $discard_closed=0, $forcefocus=0, $disabled=0, $mode = 0, $filterkey = '') { - global $langs,$conf; + global $langs,$conf,$form; if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PROJECT_USE_SEARCH_TO_SELECT)) { @@ -86,6 +86,14 @@ class FormProjets else { print $this->select_projects_list($socid, $selected, $htmlname, $maxlength, $option_only, $show_empty, $discard_closed, $forcefocus, $disabled, 0, $filterkey); + if ($discard_closed) + { + if (class_exists('Form')) + { + if (empty($form)) $form=new Form($this->db); + print $form->textwithpicto('', $langs->trans("ClosedProjectsAreHidden")); + } + } } } @@ -174,7 +182,7 @@ class FormProjets } else { - if ($discard_closed == 1 && $obj->fk_statut == 2) + if ($discard_closed == 1 && $obj->fk_statut == 2 && $obj->rowid != $selected) // We discard closed except if selected { $i++; continue; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index ca698c55d5c..c177eb7965c 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -137,6 +137,7 @@ class Fichinter extends CommonObject $sql.= ", ref"; $sql.= ", entity"; $sql.= ", fk_user_author"; + $sql.= ", fk_user_modif"; $sql.= ", description"; $sql.= ", model_pdf"; $sql.= ", fk_projet"; @@ -151,6 +152,7 @@ class Fichinter extends CommonObject $sql.= ", '".$this->db->escape($this->ref)."'"; $sql.= ", ".$conf->entity; $sql.= ", ".$user->id; + $sql.= ", ".$user->id; $sql.= ", ".($this->description?"'".$this->db->escape($this->description)."'":"null"); $sql.= ", '".$this->db->escape($this->modelpdf)."'"; $sql.= ", ".($this->fk_project ? $this->fk_project : 0); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 45bbb2c21cc..d7bd5d18696 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1985,7 +1985,7 @@ elseif (! empty($object->id)) //print "$object->id, $object->socid, $object->fk_project"; if ($action == 'classify') { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:'-1'), $object->fk_project, 'projectid', 0, 0, 1); + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:-1), $object->fk_project, 'projectid', 0, 0, 1); } else { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 2573b40baf4..ac630989ba0 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1470,7 +1470,7 @@ if ($action == 'create') $langs->load('projects'); print '
' . $langs->trans('Project') . ''; - $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$societe->id:'-1'), $projectid, 'projectid', 0); + $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$societe->id:-1), $projectid, 'projectid', 0, 0, 1, 1); print '
'; if ($action == 'classify') { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:'-1'), $object->fk_project, 'projectid', 0, 0, 1); + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:-1), $object->fk_project, 'projectid', 0, 0, 1); } else { diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 5ed20ca738a..95d6b7fe55f 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -14,6 +14,7 @@ ProjectsPublicTaskDesc=This view presents all projects and tasks you are allowed ProjectsDesc=This view presents all projects (your user permissions grant you permission to view everything). MyTasksDesc=This view is limited to projects or tasks you are a contact for (whatever is the type). OnlyOpenedProject=Only open projects are visible (projects in draft or closed status are not visible). +ClosedProjectsAreHidden=Closed projects are not visible. TasksPublicDesc=This view presents all projects and tasks you are allowed to read. TasksDesc=This view presents all projects and tasks (your user permissions grant you permission to view everything). AllTaskVisibleButEditIfYouAreAssigned=All tasks for such project are visible, but you can enter time only for task you are assigned on. Assign task to you if you want to enter time on it. From 7aecc5ed95d0456b739e7da362c3d277faf219ec Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Jan 2016 12:12:16 +0100 Subject: [PATCH 12/12] Fix picto private project was same than public project --- htdocs/theme/md/img/object_project.png | Bin 158 -> 269 bytes htdocs/theme/md/img/object_projectpub.png | Bin 158 -> 252 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/htdocs/theme/md/img/object_project.png b/htdocs/theme/md/img/object_project.png index 76139922af1f9fb5ac1f63c43fc79e2d3bfe8cfe..c873ff4f0dcb31c253566f41c5d81c677b6a9f47 100644 GIT binary patch delta 241 zcmV8OGiWi0IH26G5`Po32;bRa{vGf6951U69E94oEQKA00(qQ zO+^Rb0UQepBrctzP5=M^o=HSOR4C7_kvk58P!L7W04*+qMosK>3C5LJVEHycXJ~9q z+=*MTa3h4;jK$;qhz1I7HJ>}@76W6g*)X98igHhf1pr$bN@}2B&y}2-iVx6Zcso8OGiWi0IH26G5`Po32;bRa{vGf6951U69E94oEQKA00(qQ zO+^Rb0UQemEqrWADF6TfjY&j7R4C7_(Y+0VP#A^bCqRp1*rUyaE~{1#k8JobQ~QTs~P?`omceoQA^;tW=pjbOD(hj0000