dolibarr  19.0.0-dev
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  $sql = "SELECT cls.rowid, cls.code, cls.percent, cls.label";
102  $sql .= " FROM ".MAIN_DB_PREFIX."c_lead_status as cls";
103  $sql .= " WHERE active=1";
104  $sql .= " AND cls.code <> 'LOST'";
105  $sql .= $this->db->order('cls.rowid', 'ASC');
106  $resql = $this->db->query($sql);
107  if ($resql) {
108  $num = $this->db->num_rows($resql);
109  $i = 0;
110 
111  while ($i < $num) {
112  $objp = $this->db->fetch_object($resql);
113  $listofoppstatus[$objp->rowid] = $objp->percent;
114  $listofopplabel[$objp->rowid] = $objp->label;
115  $listofoppcode[$objp->rowid] = $objp->code;
116  switch ($objp->code) {
117  case 'PROSP':
118  $colorseriesstat[$objp->rowid] = '-'.$badgeStatus0;
119  break;
120  case 'QUAL':
121  $colorseriesstat[$objp->rowid] = '-'.$badgeStatus1;
122  break;
123  case 'PROPO':
124  $colorseriesstat[$objp->rowid] = $badgeStatus1;
125  break;
126  case 'NEGO':
127  $colorseriesstat[$objp->rowid] = $badgeStatus4;
128  break;
129  case 'WON':
130  $colorseriesstat[$objp->rowid] = $badgeStatus6;
131  break;
132  default:
133  break;
134  }
135  $i++;
136  }
137  } else {
138  dol_print_error($this->db);
139  }
140 
141  global $conf, $user, $langs;
142  $this->max = $max;
143 
144  $this->info_box_head = array(
145  'text' => $langs->trans("Statistics").' - '.$langs->trans("BoxTitleFunnelOfProspection"),
146  'graph' => '1'
147  );
148 
149  if ($user->hasRight('projet', 'lire') || getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
150  $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";
151  $sql .= " FROM ".MAIN_DB_PREFIX."projet as p, ".MAIN_DB_PREFIX."c_lead_status as cls";
152  $sql .= " WHERE p.entity IN (".getEntity('project').")";
153  $sql .= " AND p.fk_opp_status = cls.rowid";
154  $sql .= " AND p.fk_statut = 1"; // Opend projects only
155  $sql .= " AND cls.code NOT IN ('LOST')";
156  $sql .= " GROUP BY p.fk_opp_status, cls.code";
157  $resql = $this->db->query($sql);
158 
159  $form = new Form($this->db);
160  if ($resql) {
161  $num = $this->db->num_rows($resql);
162  $i = 0;
163 
164  $totalnb = 0;
165  $totaloppnb = 0;
166  $totalamount = 0;
167  $ponderated_opp_amount = 0;
168  $valsnb = array();
169  $valsamount = array();
170  $dataseries = array();
171 
172  while ($i < $num) {
173  $obj = $this->db->fetch_object($resql);
174  if ($obj) {
175  $valsnb[$obj->opp_status] = $obj->nb;
176  $valsamount[$obj->opp_status] = $obj->opp_amount;
177  $totalnb += $obj->nb;
178  if ($obj->opp_status) {
179  $totaloppnb += $obj->nb;
180  }
181  if (!in_array($obj->code, array('WON', 'LOST'))) {
182  $totalamount += $obj->opp_amount;
183  $ponderated_opp_amount += $obj->ponderated_opp_amount;
184  }
185  }
186  $i++;
187  }
188  $this->db->free($resql);
189  $ponderated_opp_amount = $ponderated_opp_amount / 100;
190 
191  $stringtoprint = '';
192  $stringtoprint .= '<div class="div-table-responsive-no-min ">';
193  $listofstatus = array_keys($listofoppstatus);
194  $liststatus = array();
195  $data = array('');
196  $customlabels = array();
197  $total = 0;
198  foreach ($listofstatus as $status) {
199  $customlabel = '';
200  $labelStatus = '';
201  if ($status != 7) {
202  $code = dol_getIdFromCode($this->db, $status, 'c_lead_status', 'rowid', 'code');
203  if ($code) {
204  $labelStatus = $langs->transnoentitiesnoconv("OppStatus".$code);
205  }
206  if (empty($labelStatus)) {
207  $labelStatus = $listofopplabel[$status];
208  }
209  $amount = (isset($valsamount[$status]) ? (float) $valsamount[$status] : 0);
210  $data[] = $amount;
211  $customlabel = $amount;
212  $liststatus[] = $labelStatus;
213  if (!$conf->use_javascript_ajax) {
214  $stringtoprint .= '<tr class="oddeven">';
215  $stringtoprint .= '<td>'.$labelStatus.'</td>';
216  $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>';
217  $stringtoprint .= "</tr>\n";
218  }
219  }
220  $customlabels[] = $customlabel;
221  }
222  $dataseries[] = $data;
223  if ($conf->use_javascript_ajax) {
224  include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
225  $dolgraph = new DolGraph();
226  $dolgraph->SetMinValue(0);
227  $dolgraph->SetData($dataseries);
228  $dolgraph->SetLegend($liststatus);
229  $dolgraph->setHideXValues(true);
230  $dolgraph->SetDataColor(array_values($colorseriesstat));
231  //$dolgraph->setBorderColor(array_values($bordercolorseries));
232  $dolgraph->setShowLegend(2);
233  if (!empty($conf->dol_optimize_smallscreen)) {
234  $dolgraph->SetWidth(320);
235  }
236  $dolgraph->setShowPercent(1);
237  $dolgraph->setMirrorGraphValues(true);
238  $dolgraph->setBorderWidth(2);
239  $dolgraph->SetType(array('horizontalbars'));
240  $dolgraph->SetHeight('200');
241  $dolgraph->SetWidth('600');
242  $dolgraph->setTooltipsTitles($liststatus);
243  $dolgraph->setTooltipsLabels($customlabels);
244  $dolgraph->mode = 'depth';
245  $dolgraph->draw('idgraphleadfunnel');
246  $stringtoprint .= $dolgraph->show($totaloppnb ? 0 : 1);
247  }
248  $stringtoprint .= '</div>';
249 
250  $line = 0;
251  $this->info_box_contents[$line][] = array(
252  'tr' => 'class="nohover left "',
253  'text' => ''
254  );
255  $this->info_box_contents[$line][] = array(
256  'tr' => 'class="nohover left "',
257  'text' => ''
258  );
259  $line++;
260  $this->info_box_contents[$line][] = array(
261  'tr' => '',
262  'td' => 'class="center nopaddingleftimp nopaddingrightimp" colspan="2"',
263  'text' => $stringtoprint
264  );
265  $line++;
266  $this->info_box_contents[$line][] = array(
267  'tr' => 'class="oddeven"',
268  'td' => 'class="left "',
269  'maxlength' => 500,
270  'text' => $langs->trans("OpportunityTotalAmount").' ('.$langs->trans("WonLostExcluded").')'
271  );
272  $this->info_box_contents[$line][] = array(
273  'tr' => 'class="oddeven"',
274  'td' => 'class="nowraponall right amount"',
275  'maxlength' => 500,
276  'text' => price($totalamount, 0, '', 1, -1, -1, $conf->currency)
277  );
278  $line++;
279  $this->info_box_contents[$line][] = array(
280  'tr' => 'class="oddeven"',
281  'td' => 'class="left "',
282  'maxlength' => 500,
283  'text' => $form->textwithpicto($langs->trans("OpportunityPonderatedAmount").' ('.$langs->trans("WonLostExcluded").')', $langs->trans("OpportunityPonderatedAmountDesc"), 1)
284 
285  );
286  $this->info_box_contents[$line][] = array(
287  'td' => 'class="nowraponall right amount"',
288  'maxlength' => 500,
289  'text' => price(price2num($ponderated_opp_amount, 'MT'), 0, '', 1, -1, -1, $conf->currency)
290  );
291  } else {
292  $this->info_box_contents[0][0] = array(
293  'td' => 'class="center opacitymedium"',
294  'text' => $langs->trans("NoRecordedCustomers")
295  );
296  }
297  } else {
298  $this->info_box_contents[0][0] = array(
299  'td' => '',
300  'text' => $langs->trans("ReadPermissionNotAllowed")
301  );
302  }
303  }
304 
313  public function showBox($head = null, $contents = null, $nooutput = 0)
314  {
315  return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput);
316  }
317 }
Class to build graphs.
Class to manage generation of HTML components Only common components must be here.
Class ModeleBoxes.
Class to manage the box to show funnel of prospections.
showBox($head=null, $contents=null, $nooutput=0)
Method to show box.
__construct($db, $param='')
Constructor.
loadBox($max=5)
Load data for box to show them later.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
div float
Buy price without taxes.
Definition: style.css.php:921