From 274caf61ebac81b5061bb062023abe46f04f8eea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur <eldy@destailleur.fr> Date: Mon, 25 Jan 2016 13:31:43 +0100 Subject: [PATCH] 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 | 109 +++--- .../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, 645 insertions(+), 91 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 '<div class="fichecenter"><div class="fichethirdleft">'; print '</td></tr>'; // Status print '<tr><td align="left">'.$langs->trans("Status").'</td><td align="left">'; - $formpropal->selectProposalStatus($object_statut,0,1); + $formpropal->selectProposalStatus($object_statut,0,1,1,$mode); print '</td></tr>'; // Year print '<tr><td align="left">'.$langs->trans("Year").'</td><td align="left">'; 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 '<div class="fichecenter"><div class="fichethirdleft">'; print '<table class="noborder" width="100%">'; print '<tr class="liste_titre" height="24">'; print '<td align="center">'.$langs->trans("Year").'</td>'; -print '<td align="center">'.$langs->trans("NbOfOrders").'</td>'; -print '<td align="center">%</td>'; -print '<td align="center">'.$langs->trans("AmountTotal").'</td>'; -print '<td align="center">%</td>'; -print '<td align="center">'.$langs->trans("AmountAverage").'</td>'; -print '<td align="center">%</td>'; +print '<td align="right">'.$langs->trans("NbOfOrders").'</td>'; +print '<td align="right">%</td>'; +print '<td align="right">'.$langs->trans("AmountTotal").'</td>'; +print '<td align="right">%</td>'; +print '<td align="right">'.$langs->trans("AmountAverage").'</td>'; +print '<td align="right">%</td>'; print '</tr>'; $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') + { + $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 { - print '<select class="flat" name="propal_statut">'; - if ($showempty) print '<option value=""> </option>'; - $num = $this->db->num_rows($resql); - $i = 0; - if ($num) + $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) { - while ($i < $num) + $num = $this->db->num_rows($resql); + $i = 0; + if ($num) { - $obj = $this->db->fetch_object($resql); - if ($excludedraft) + while ($i < $num) { - if ($obj->code == 'Draft' || $obj->code == 'PR_DRAFT') - { - $i++; - continue; - } + $obj = $this->db->fetch_object($resql); + $listofstatus[$obj->id]=array('id'=>$obj->id,'code'=>$obj->code,'label'=>$obj->label); } - if ($selected == $obj->id) - { - print '<option value="'.$obj->id.'" selected>'; - } - else - { - print '<option value="'.$obj->id.'">'; - } - $key=$obj->code; - if ($langs->trans("PropalStatus".$key.($short?'Short':'')) != "PropalStatus".$key.($short?'Short':'')) - { - print $langs->trans("PropalStatus".$key.($short?'Short':'')); - } - else - { - $conv_to_new_code=array('PR_DRAFT'=>'Draft','PR_OPEN'=>'Opened','PR_CLOSED'=>'Closed','PR_SIGNED'=>'Signed','PR_NOTSIGNED'=>'NotSigned','PR_FAC'=>'Billed'); - if (! empty($conv_to_new_code[$obj->code])) $key=$conv_to_new_code[$obj->code]; - print ($langs->trans("PropalStatus".$key.($short?'Short':''))!="PropalStatus".$key.($short?'Short':''))?$langs->trans("PropalStatus".$key.($short?'Short':'')):$obj->label; - } - print '</option>'; - $i++; } } - print '</select>'; + else + { + dol_print_error($this->db); + } } - else + + print '<select class="flat" name="propal_statut">'; + if ($showempty) print '<option value=""> </option>'; + + foreach($listofstatus as $key => $obj) { - dol_print_error($this->db); + if ($excludedraft) + { + if ($obj['code'] == 'Draft' || $obj['code'] == 'PR_DRAFT') + { + $i++; + continue; + } + } + if ($selected == $obj['id']) + { + print '<option value="'.$obj['id'].'" selected>'; + } + else + { + print '<option value="'.$obj['id'].'">'; + } + $key=$obj['code']; + if ($langs->trans($prefix."PropalStatus".$key.($short?'Short':'')) != $prefix."PropalStatus".$key.($short?'Short':'')) + { + print $langs->trans($prefix."PropalStatus".$key.($short?'Short':'')); + } + else + { + $conv_to_new_code=array('PR_DRAFT'=>'Draft','PR_OPEN'=>'Opened','PR_CLOSED'=>'Closed','PR_SIGNED'=>'Signed','PR_NOTSIGNED'=>'NotSigned','PR_FAC'=>'Billed'); + if (! empty($conv_to_new_code[$obj['code']])) $key=$conv_to_new_code[$obj['code']]; + print ($langs->trans($prefix.$key.($short?'Short':''))!=$prefix.$key.($short?'Short':''))?$langs->trans($prefix.$key.($short?'Short':'')):$obj['label']; + } + print '</option>'; + $i++; } + print '</select>'; } - } 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 '<tr><td>'.$langs->trans("TotalDuration").'</td>'; print '<td colspan="3">'.convertSecondToTime($object->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).'</td>'; print '</tr>'; - - // Date create - print '<tr><td>'.$langs->trans("Datec").'</td>'; - print '<td colspan="3">'; - print $object->datec ? dol_print_date($object->datec, 'daytext') : ' '; - print '</td>'; - print '</tr>'; - - // Date Validation - print '<tr><td>'.$langs->trans("Datev").'</td>'; - print '<td colspan="3">'; - print $object->datev ? dol_print_date($object->datev, 'daytext') : ' '; - print '</td>'; - print '</tr>'; - + } + + if (! empty($conf->global->FICHINTER_USE_PLANNED_AND_DONE_DATES)) + { // Date Start print '<tr><td>'.$langs->trans("Dateo").'</td>'; print '<td colspan="3">'; 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 @@ +<?php +/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org> + * Copyright (c) 2005-2013 Laurent Destailleur <eldy@users.sourceforge.net> + * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com> + * Copyright (C) 2012 Marcos GarcĂa <marcosgdf@gmail.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +/** + * \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 @@ +<?php +/* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +/** + * \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 '<div class="fichecenter"><div class="fichethirdleft">'; + + +//if (empty($socid)) +//{ + // Show filter box + print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">'; + print '<input type="hidden" name="mode" value="'.$mode.'">'; + print '<table class="noborder" width="100%">'; + print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>'; + // Company + print '<tr><td align="left">'.$langs->trans("ThirdParty").'</td><td align="left">'; + 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 '</td></tr>'; + // User + print '<tr><td align="left">'.$langs->trans("CreatedBy").'</td><td align="left">'; + print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300'); + // Year + print '<tr><td align="left">'.$langs->trans("Year").'</td><td align="left">'; + 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 '</td></tr>'; + print '<tr><td align="center" colspan="2"><input type="submit" name="submit" class="button" value="'.$langs->trans("Refresh").'"></td></tr>'; + print '</table>'; + print '</form>'; + print '<br><br>'; +//} + +print '<table class="noborder" width="100%">'; +print '<tr class="liste_titre" height="24">'; +print '<td align="center">'.$langs->trans("Year").'</td>'; +print '<td align="right">'.$langs->trans("NbOfinterventions").'</td>'; +print '<td align="right">%</td>'; +print '<td align="right">'.$langs->trans("AmountTotal").'</td>'; +print '<td align="right">%</td>'; +print '<td align="right">'.$langs->trans("AmountAverage").'</td>'; +print '<td align="right">%</td>'; +print '</tr>'; + +$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 '<tr '.$bc[$var].' height="24">'; + print '<td align="center"><a href="'.$_SERVER["PHP_SELF"].'?year='.$oldyear.'&mode='.$mode.($socid>0?'&socid='.$socid:'').($userid>0?'&userid='.$userid:'').'">'.$oldyear.'</a></td>'; + + print '<td align="right">0</td>'; + print '<td align="right"></td>'; + print '<td align="right">0</td>'; + print '<td align="right"></td>'; + print '<td align="right">0</td>'; + print '<td align="right"></td>'; + print '</tr>'; + } + + $var=!$var; + print '<tr '.$bc[$var].' height="24">'; + print '<td align="center"><a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&mode='.$mode.($socid>0?'&socid='.$socid:'').($userid>0?'&userid='.$userid:'').'">'.$year.'</a></td>'; + print '<td align="right">'.$val['nb'].'</td>'; + print '<td align="right" style="'.(($val['nb_diff'] >= 0) ? 'color: green;':'color: red;').'">'.round($val['nb_diff']).'</td>'; + print '<td align="right">'.price(price2num($val['total'],'MT'),1).'</td>'; + print '<td align="right" style="'.(($val['total_diff'] >= 0) ? 'color: green;':'color: red;').'">'.round($val['total_diff']).'</td>'; + print '<td align="right">'.price(price2num($val['avg'],'MT'),1).'</td>'; + print '<td align="right" style="'.(($val['avg_diff'] >= 0) ? 'color: green;':'color: red;').'">'.round($val['avg_diff']).'</td>'; + print '</tr>'; + $oldyear=$year; +} + +print '</table>'; + + +print '</div><div class="fichetwothirdright"><div class="ficheaddleft">'; + + +// Show graphs +print '<table class="border" width="100%"><tr valign="top"><td align="center">'; +if ($mesg) { print $mesg; } +else { + print $px1->show(); + /*print "<br>\n"; + print $px2->show(); + print "<br>\n"; + print $px3->show();*/ +} +print '</td></tr></table>'; + + +print '</div></div></div>'; +print '<div style="clear:both"></div>'; + +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 -- GitLab