dolibarr  16.0.5
box_funnel_of_prospection.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2012-2014 Charles-François BENKE <charles.fr@benke.fr>
3  * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
4  * Copyright (C) 2015 Frederic France <frederic.france@free.fr>
5  * Copyright (C) 2016 Juan José Menent <jmenent@2byte.es>
6  * Copyright (C) 2020 Pierre Ardoin <mapiolca@me.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
27 include_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php";
28 
33 {
34  public $boxcode = "FunnelOfProspection";
35  public $boximg = "object_projectpub";
36  public $boxlabel = "BoxTitleFunnelOfProspection";
37  public $depends = array("projet");
38 
39  public $version = 'development';
40 
44  public $db;
45 
46  public $param;
47 
48  public $info_box_head = array();
49  public $info_box_contents = array();
50 
57  public function __construct($db, $param = '')
58  {
59  global $user, $langs, $conf;
60 
61  // Load translation files required by the page
62  $langs->loadLangs(array('boxes', 'projects'));
63 
64  $this->db = $db;
65 
66  $this->enabled = ($conf->global->MAIN_FEATURES_LEVEL >= 1 ? 1 : 0); // Not enabled by default, still need some work
67 
68  $this->hidden = empty($user->rights->projet->lire);
69  }
70 
77  public function loadBox($max = 5)
78  {
79  global $conf;
80 
81  // default values
82  $badgeStatus0 = '#cbd3d3'; // draft
83  $badgeStatus1 = '#bc9526'; // validated
84  $badgeStatus1b = '#bc9526'; // validated
85  $badgeStatus2 = '#9c9c26'; // approved
86  $badgeStatus3 = '#bca52b';
87  $badgeStatus4 = '#25a580'; // Color ok
88  $badgeStatus4b = '#25a580'; // Color ok
89  $badgeStatus5 = '#cad2d2';
90  $badgeStatus6 = '#cad2d2';
91  $badgeStatus7 = '#baa32b';
92  $badgeStatus8 = '#993013';
93  $badgeStatus9 = '#e7f0f0';
94  if (file_exists(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php')) {
95  include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php';
96  }
97  $listofoppstatus = array();
98  $listofopplabel = array();
99  $listofoppcode = array();
100  $colorseriesstat = array();
101  $bordercolorseries = array();
102  $sql = "SELECT cls.rowid, cls.code, cls.percent, cls.label";
103  $sql .= " FROM ".MAIN_DB_PREFIX."c_lead_status as cls";
104  $sql .= " WHERE active=1";
105  $sql .= " AND cls.code <> 'LOST'";
106  $sql .= $this->db->order('cls.rowid', 'ASC');
107  $resql = $this->db->query($sql);
108  if ($resql) {
109  $num = $this->db->num_rows($resql);
110  $i = 0;
111 
112  while ($i < $num) {
113  $objp = $this->db->fetch_object($resql);
114  $listofoppstatus[$objp->rowid] = $objp->percent;
115  $listofopplabel[$objp->rowid] = $objp->label;
116  $listofoppcode[$objp->rowid] = $objp->code;
117  switch ($objp->code) {
118  case 'PROSP':
119  $colorseriesstat[$objp->rowid] = '#FFFFFF';
120  $bordercolorseries[$objp->rowid] = $badgeStatus0;
121  break;
122  case 'QUAL':
123  $colorseriesstat[$objp->rowid] = '#FFFFFF';
124  $bordercolorseries[$objp->rowid] = $badgeStatus1;
125  break;
126  case 'PROPO':
127  $colorseriesstat[$objp->rowid] = $badgeStatus1;
128  $bordercolorseries[$objp->rowid] = $badgeStatus1;
129  break;
130  case 'NEGO':
131  $colorseriesstat[$objp->rowid] = $badgeStatus4;
132  $bordercolorseries[$objp->rowid] = $badgeStatus4;
133  break;
134  case 'WON':
135  $colorseriesstat[$objp->rowid] = $badgeStatus6;
136  $bordercolorseries[$objp->rowid] = $badgeStatus6;
137  break;
138  default:
139  break;
140  }
141  $i++;
142  }
143  } else {
144  dol_print_error($this->db);
145  }
146 
147  global $conf, $user, $langs;
148  $this->max = $max;
149 
150  $this->info_box_head = array(
151  'text' => $langs->trans("Statistics").' - '.$langs->trans("BoxTitleFunnelOfProspection"),
152  'graph' => '1'
153  );
154 
155  if ($user->rights->projet->lire || !empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
156  $sql = "SELECT p.fk_opp_status as opp_status, cls.code, COUNT(p.rowid) as nb, SUM(p.opp_amount) as opp_amount, SUM(p.opp_amount * p.opp_percent) as ponderated_opp_amount";
157  $sql .= " FROM ".MAIN_DB_PREFIX."projet as p, ".MAIN_DB_PREFIX."c_lead_status as cls";
158  $sql .= " WHERE p.entity IN (".getEntity('project').")";
159  $sql .= " AND p.fk_opp_status = cls.rowid";
160  $sql .= " AND p.fk_statut = 1"; // Opend projects only
161  $sql .= " AND cls.code NOT IN ('LOST')";
162  $sql .= " GROUP BY p.fk_opp_status, cls.code";
163  $resql = $this->db->query($sql);
164 
165  $form = new Form($this->db);
166  if ($resql) {
167  $num = $this->db->num_rows($resql);
168  $i = 0;
169 
170  $totalnb = 0;
171  $totaloppnb = 0;
172  $totalamount = 0;
173  $ponderated_opp_amount = 0;
174  $valsnb = array();
175  $valsamount = array();
176  $dataseries = array();
177 
178  while ($i < $num) {
179  $obj = $this->db->fetch_object($resql);
180  if ($obj) {
181  $valsnb[$obj->opp_status] = $obj->nb;
182  $valsamount[$obj->opp_status] = $obj->opp_amount;
183  $totalnb += $obj->nb;
184  if ($obj->opp_status) {
185  $totaloppnb += $obj->nb;
186  }
187  if (!in_array($obj->code, array('WON', 'LOST'))) {
188  $totalamount += $obj->opp_amount;
189  $ponderated_opp_amount += $obj->ponderated_opp_amount;
190  }
191  }
192  $i++;
193  }
194  $this->db->free($resql);
195  $ponderated_opp_amount = $ponderated_opp_amount / 100;
196 
197  $stringtoprint = '';
198  $stringtoprint .= '<div class="div-table-responsive-no-min ">';
199  $listofstatus = array_keys($listofoppstatus);
200  $liststatus = array();
201  $data = array('');
202  $customlabels = array();
203  $total = 0;
204  foreach ($listofstatus as $status) {
205  $customlabel = '';
206  $labelStatus = '';
207  if ($status != 7) {
208  $code = dol_getIdFromCode($this->db, $status, 'c_lead_status', 'rowid', 'code');
209  if ($code) {
210  $labelStatus = $langs->transnoentitiesnoconv("OppStatus".$code);
211  }
212  if (empty($labelStatus)) {
213  $labelStatus = $listofopplabel[$status];
214  }
215  $amount = (isset($valsamount[$status]) ? (float) $valsamount[$status] : 0);
216  $data[] = $amount;
217  $customlabel = $amount;
218  $liststatus[] = $labelStatus;
219  if (!$conf->use_javascript_ajax) {
220  $stringtoprint .= '<tr class="oddeven">';
221  $stringtoprint .= '<td>'.$labelStatus.'</td>';
222  $stringtoprint .= '<td class="nowraponall right amount"><a href="list.php?statut='.$status.'">'.price((isset($valsamount[$status]) ? (float) $valsamount[$status] : 0), 0, '', 1, -1, -1, $conf->currency).'</a></td>';
223  $stringtoprint .= "</tr>\n";
224  }
225  }
226  $customlabels[] = $customlabel;
227  }
228  $dataseries[] = $data;
229  if ($conf->use_javascript_ajax) {
230  include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
231  $dolgraph = new DolGraph();
232  $dolgraph->SetMinValue(0);
233  $dolgraph->SetData($dataseries);
234  $dolgraph->SetLegend($liststatus);
235  $dolgraph->setHideXValues(true);
236  $dolgraph->SetDataColor(array_values($colorseriesstat));
237  $dolgraph->setBorderColor(array_values($bordercolorseries));
238  $dolgraph->setShowLegend(2);
239  if (!empty($conf->dol_optimize_smallscreen)) {
240  $dolgraph->SetWidth(320);
241  }
242  $dolgraph->setShowPercent(1);
243  $dolgraph->setMirrorGraphValues(true);
244  $dolgraph->setBorderWidth(2);
245  $dolgraph->SetType(array('horizontalbars'));
246  $dolgraph->SetHeight('200');
247  $dolgraph->SetWidth('600');
248  $dolgraph->setTooltipsTitles($liststatus);
249  $dolgraph->setTooltipsLabels($customlabels);
250  $dolgraph->mode = 'depth';
251  $dolgraph->draw('idgraphleadfunnel');
252  $stringtoprint .= $dolgraph->show($totaloppnb ? 0 : 1);
253  }
254  $stringtoprint .= '</div>';
255 
256  $line = 0;
257  $this->info_box_contents[$line][] = array(
258  'tr' => 'class="nohover left "',
259  'text' => ''
260  );
261  $this->info_box_contents[$line][] = array(
262  'tr' => 'class="nohover left "',
263  'text' => ''
264  );
265  $line++;
266  $this->info_box_contents[$line][] = array(
267  'tr' => '',
268  'td' => 'class="center nopaddingleftimp nopaddingrightimp" colspan="2"',
269  'text' => $stringtoprint
270  );
271  $line++;
272  $this->info_box_contents[$line][] = array(
273  'tr' => 'class="oddeven"',
274  'td' => 'class="left "',
275  'maxlength' => 500,
276  'text' => $langs->trans("OpportunityTotalAmount").' ('.$langs->trans("WonLostExcluded").')'
277  );
278  $this->info_box_contents[$line][] = array(
279  'tr' => 'class="oddeven"',
280  'td' => 'class="nowraponall right amount"',
281  'maxlength' => 500,
282  'text' => price($totalamount, 0, '', 1, -1, -1, $conf->currency)
283  );
284  $line++;
285  $this->info_box_contents[$line][] = array(
286  'tr' => 'class="oddeven"',
287  'td' => 'class="left "',
288  'maxlength' => 500,
289  'text' => $form->textwithpicto($langs->trans("OpportunityPonderatedAmount").' ('.$langs->trans("WonLostExcluded").')', $langs->trans("OpportunityPonderatedAmountDesc"), 1)
290 
291  );
292  $this->info_box_contents[$line][] = array(
293  'td' => 'class="nowraponall right amount"',
294  'maxlength' => 500,
295  'text' => price(price2num($ponderated_opp_amount, 'MT'), 0, '', 1, -1, -1, $conf->currency)
296  );
297  } else {
298  $this->info_box_contents[0][0] = array(
299  'td' => 'class="center opacitymedium"',
300  'text' => $langs->trans("NoRecordedCustomers")
301  );
302  }
303  } else {
304  $this->info_box_contents[0][0] = array(
305  'td' => '',
306  'text' => $langs->trans("ReadPermissionNotAllowed")
307  );
308  }
309  }
310 
319  public function showBox($head = null, $contents = null, $nooutput = 0)
320  {
321  return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput);
322  }
323 }
db
$conf db
API class for accounts.
Definition: inc.php:41
box_funnel_of_prospection\loadBox
loadBox($max=5)
Load data for box to show them later.
Definition: box_funnel_of_prospection.php:77
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
DolGraph
Class to build graphs.
Definition: dolgraph.class.php:40
box_funnel_of_prospection\__construct
__construct($db, $param='')
Constructor.
Definition: box_funnel_of_prospection.php:57
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:142
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
dol_getIdFromCode
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
Definition: functions.lib.php:8535
box_funnel_of_prospection\showBox
showBox($head=null, $contents=null, $nooutput=0)
Method to show box.
Definition: box_funnel_of_prospection.php:319
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:52
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
box_funnel_of_prospection
Class to manage the box to show last projet.
Definition: box_funnel_of_prospection.php:32
price
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
Definition: functions.lib.php:5541
ModeleBoxes
Class ModeleBoxes.
Definition: modules_boxes.php:34
float
div float
Buy price without taxes.
Definition: style.css.php:809