card.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <?php
  2. /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (c) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  5. * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
  6. * Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
  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 <http://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/product/stats/card.php
  23. * \ingroup product
  24. * \brief Page of product statistics
  25. */
  26. require '../../main.inc.php';
  27. require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  29. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
  31. $WIDTH=DolGraph::getDefaultGraphSizeForStats('width',380);
  32. $HEIGHT=DolGraph::getDefaultGraphSizeForStats('height',160);
  33. $langs->load("companies");
  34. $langs->load("products");
  35. $langs->load("bills");
  36. $langs->load("other");
  37. $id = GETPOST('id','int'); // For this page, id can also be 'all'
  38. $ref = GETPOST('ref');
  39. $mode = (GETPOST('mode') ? GETPOST('mode') : 'byunit');
  40. $error = 0;
  41. $mesg = '';
  42. $socid='';
  43. if (! empty($user->societe_id)) $socid=$user->societe_id;
  44. // Security check
  45. $fieldvalue = (! empty($id) ? $id : $ref);
  46. $fieldtype = (! empty($ref) ? 'ref' : 'rowid');
  47. $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','','',$fieldtype);
  48. /*
  49. * View
  50. */
  51. $form = new Form($db);
  52. if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all')
  53. {
  54. $object = new Product($db);
  55. if (GETPOST('id') == 'all')
  56. {
  57. llxHeader("",$langs->trans("ProductStatistics"));
  58. $type = GETPOST('type');
  59. $helpurl='';
  60. if ($type == '0')
  61. {
  62. $helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
  63. //$title=$langs->trans("StatisticsOfProducts");
  64. $title=$langs->trans("Statistics");
  65. }
  66. else if ($type == '1')
  67. {
  68. $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
  69. //$title=$langs->trans("StatisticsOfServices");
  70. $title=$langs->trans("Statistics");
  71. }
  72. else
  73. {
  74. $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
  75. //$title=$langs->trans("StatisticsOfProductsOrServices");
  76. $title=$langs->trans("Statistics");
  77. }
  78. print load_fiche_titre($title, $mesg,'title_products.png');
  79. }
  80. else
  81. {
  82. $result = $object->fetch($id,$ref);
  83. llxHeader("",$langs->trans("CardProduct".$object->type));
  84. }
  85. if ($result && (! empty($id) || ! empty($ref)))
  86. {
  87. $head=product_prepare_head($object);
  88. $titre=$langs->trans("CardProduct".$object->type);
  89. $picto=($object->type==Product::TYPE_SERVICE?'service':'product');
  90. dol_fiche_head($head, 'stats', $titre, 0, $picto);
  91. $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php">'.$langs->trans("BackToList").'</a>';
  92. dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref');
  93. dol_fiche_end();
  94. }
  95. if (GETPOST('id') == 'all')
  96. {
  97. $h=0;
  98. $head = array();
  99. $head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php?id=all';
  100. $head[$h][1] = $langs->trans("Chart");
  101. $head[$h][2] = 'chart';
  102. $h++;
  103. $title = $langs->trans("ListProductServiceByPopularity");
  104. if ((string) $type == '1') {
  105. $title = $langs->trans("ListServiceByPopularity");
  106. }
  107. if ((string) $type == '0') {
  108. $title = $langs->trans("ListProductByPopularity");
  109. }
  110. $head[$h][0] = DOL_URL_ROOT.'/product/popuprop.php'.($type != ''?'?type='.$type:'');
  111. $head[$h][1] = $title;
  112. $head[$h][2] = 'popularityprop';
  113. $h++;
  114. dol_fiche_head($head,'chart',$langs->trans("Statistics"));
  115. }
  116. if ($result || GETPOST('id') == 'all')
  117. {
  118. if (GETPOST('id') == 'all')
  119. {
  120. // Choice of type of product
  121. if (! empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
  122. if ((string) $type != '0') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).'&type=0'.($mode?'&mode='.$mode:'').'">';
  123. else print img_picto('','tick').' ';
  124. print $langs->trans("Products");
  125. if ((string) $type != '0') print '</a>';
  126. if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
  127. else print ' &nbsp; / &nbsp; ';
  128. if ((string) $type != '1') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).'&type=1'.($mode?'&mode='.$mode:'').'">';
  129. else print img_picto('','tick').' ';
  130. print $langs->trans("Services");
  131. if ((string) $type != '1') print '</a>';
  132. if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
  133. else print ' &nbsp; / &nbsp; ';
  134. if ((string) $type == '0' || (string) $type == '1') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($mode?'&mode='.$mode:'').'">';
  135. else print img_picto('','tick').' ';
  136. print $langs->trans("ProductsAndServices");
  137. if ((string) $type == '0' || (string) $type == '1') print '</a>';
  138. if (! empty($conf->dol_use_jmobile)) print '</div></div>';
  139. else print '<br>';
  140. print '<br>';
  141. }
  142. // Choice of stats mode (byunit or bynumber)
  143. if (! empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
  144. if ($mode == 'bynumber') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=byunit">';
  145. else print img_picto('','tick').' ';
  146. print $langs->trans("StatsByNumberOfUnits");
  147. if ($mode == 'bynumber') print '</a>';
  148. if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
  149. else print ' &nbsp; / &nbsp; ';
  150. if ($mode == 'byunit') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=bynumber">';
  151. else print img_picto('','tick').' ';
  152. print $langs->trans("StatsByNumberOfEntities");
  153. if ($mode == 'byunit') print '</a>';
  154. if (! empty($conf->dol_use_jmobile)) print '</div></div>';
  155. else print '<br>';
  156. print '<br>';
  157. //print '<table width="100%">';
  158. // Generation des graphs
  159. if ($object->id > 0) // We are on statistics for a dedicated product
  160. {
  161. $dir = (! empty($conf->product->multidir_temp[$object->entity])?$conf->product->multidir_temp[$object->entity]:$conf->service->multidir_temp[$object->entity]);
  162. if (! file_exists($dir.'/'.$object->id))
  163. {
  164. if (dol_mkdir($dir.'/'.$object->id) < 0)
  165. {
  166. $mesg = $langs->trans("ErrorCanNotCreateDir",$dir);
  167. $error++;
  168. }
  169. }
  170. }
  171. $graphfiles=array(
  172. 'propal' =>array('modulepart'=>'productstats_proposals',
  173. 'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  174. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsProposals"):$langs->transnoentitiesnoconv("NumberOfProposals"))),
  175. 'proposalssuppliers'=>array('modulepart'=>'productstats_proposalssuppliers',
  176. 'file' => $object->id.'/proposalssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  177. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierProposals"):$langs->transnoentitiesnoconv("NumberOfSupplierProposals"))),
  178. 'orders' =>array('modulepart'=>'productstats_orders',
  179. 'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  180. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerOrders"):$langs->transnoentitiesnoconv("NumberOfCustomerOrders"))),
  181. 'orderssuppliers'=>array('modulepart'=>'productstats_orderssuppliers',
  182. 'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  183. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierOrders"):$langs->transnoentitiesnoconv("NumberOfSupplierOrders"))),
  184. 'invoices' =>array('modulepart'=>'productstats_invoices',
  185. 'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  186. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerInvoices"):$langs->transnoentitiesnoconv("NumberOfCustomerInvoices"))),
  187. 'invoicessuppliers'=>array('modulepart'=>'productstats_invoicessuppliers',
  188. 'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
  189. 'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierInvoices"):$langs->transnoentitiesnoconv("NumberOfSupplierInvoices"))),
  190. );
  191. $px = new DolGraph();
  192. if (! $error)
  193. {
  194. $mesg = $px->isGraphKo();
  195. if (! $mesg)
  196. {
  197. foreach($graphfiles as $key => $val)
  198. {
  199. if (! $graphfiles[$key]['file']) continue;
  200. $graph_data = array();
  201. if (dol_is_file($dir . '/' . $graphfiles[$key]['file']))
  202. {
  203. // TODO Load cachefile $graphfiles[$key]['file']
  204. }
  205. else
  206. {
  207. if ($key == 'propal') $graph_data = $object->get_nb_propal($socid,$mode,((string) $type != '' ? $type : -1));
  208. if ($key == 'orders') $graph_data = $object->get_nb_order($socid,$mode,((string) $type != '' ? $type : -1));
  209. if ($key == 'invoices') $graph_data = $object->get_nb_vente($socid,$mode,((string) $type != '' ? $type : -1));
  210. if ($key == 'proposalssuppliers') $graph_data = $object->get_nb_propalsupplier($socid,$mode,((string) $type != '' ? $type : -1));
  211. if ($key == 'invoicessuppliers') $graph_data = $object->get_nb_achat($socid,$mode,((string) $type != '' ? $type : -1));
  212. if ($key == 'orderssuppliers') $graph_data = $object->get_nb_ordersupplier($socid,$mode,((string) $type != '' ? $type : -1));
  213. // TODO Save cachefile $graphfiles[$key]['file']
  214. }
  215. if (is_array($graph_data))
  216. {
  217. $px->SetData($graph_data);
  218. $px->SetYLabel($graphfiles[$key]['label']);
  219. $px->SetMaxValue($px->GetCeilMaxValue()<0?0:$px->GetCeilMaxValue());
  220. $px->SetMinValue($px->GetFloorMinValue()>0?0:$px->GetFloorMinValue());
  221. $px->SetWidth($WIDTH);
  222. $px->SetHeight($HEIGHT);
  223. $px->SetHorizTickIncrement(1);
  224. $px->SetPrecisionY(0);
  225. $px->SetShading(3);
  226. //print 'x '.$key.' '.$graphfiles[$key]['file'];
  227. $url=DOL_URL_ROOT.'/viewimage.php?modulepart='.$graphfiles[$key]['modulepart'].'&entity='.$object->entity.'&file='.urlencode($graphfiles[$key]['file']);
  228. $px->draw($dir."/".$graphfiles[$key]['file'],$url);
  229. $graphfiles[$key]['output']=$px->show();
  230. }
  231. else
  232. {
  233. dol_print_error($db,'Error for calculating graph on key='.$key.' - '.$object->error);
  234. }
  235. }
  236. }
  237. $mesg = $langs->trans("ChartGenerated");
  238. }
  239. // Show graphs
  240. $i=0;
  241. foreach($graphfiles as $key => $val)
  242. {
  243. if (! $graphfiles[$key]['file']) continue;
  244. if ($graphfiles == 'propal' && ! $user->rights->propale->lire) continue;
  245. if ($graphfiles == 'order' && ! $user->rights->commande->lire) continue;
  246. if ($graphfiles == 'invoices' && ! $user->rights->facture->lire) continue;
  247. if ($graphfiles == 'proposals_suppliers' && ! $user->rights->supplier_proposal->lire) continue;
  248. if ($graphfiles == 'invoices_suppliers' && ! $user->rights->fournisseur->facture->lire) continue;
  249. if ($graphfiles == 'orders_suppliers' && ! $user->rights->fournisseur->commande->lire) continue;
  250. if ($i % 2 == 0)
  251. {
  252. print "\n".'<div class="fichecenter"><div class="fichehalfleft">'."\n";
  253. }
  254. else
  255. {
  256. print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
  257. }
  258. // Show graph
  259. print '<table class="noborder" width="100%">';
  260. // Label
  261. print '<tr class="liste_titre"><td colspan="2">';
  262. print $graphfiles[$key]['label'];
  263. print '</td></tr>';
  264. // Image
  265. print '<tr class="impair"><td colspan="2" class="nohover" align="center">';
  266. print $graphfiles[$key]['output'];
  267. print '</td></tr>';
  268. // Date generation
  269. print '<tr>';
  270. if ($graphfiles[$key]['output'] && ! $px->isGraphKo())
  271. {
  272. if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) print '<td>'.$langs->trans("GeneratedOn",dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']),"dayhour")).'</td>';
  273. else print '<td>'.$langs->trans("GeneratedOn",dol_print_date(dol_now(),"dayhour")).'</td>';
  274. }
  275. else
  276. {
  277. print '<td>'.($mesg?'<font class="error">'.$mesg.'</font>':$langs->trans("ChartNotGenerated")).'</td>';
  278. }
  279. print '<td align="center"><a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).((string) $type != ''?'&amp;type='.$type:'').'&amp;action=recalcul&amp;mode='.$mode.'">'.img_picto($langs->trans("ReCalculate"),'refresh').'</a></td>';
  280. print '</tr>';
  281. print '</table>';
  282. if ($i % 2 == 0)
  283. {
  284. print "\n".'</div>'."\n";
  285. }
  286. else
  287. {
  288. print "\n".'</div></div></div>';
  289. print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
  290. }
  291. $i++;
  292. }
  293. // div not closed
  294. if ($i % 2 == 1)
  295. {
  296. print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
  297. print "\n".'</div></div></div>';
  298. print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
  299. }
  300. }
  301. if (GETPOST('id') == 'all')
  302. {
  303. dol_fiche_end();
  304. }
  305. }
  306. else
  307. {
  308. dol_print_error();
  309. }
  310. llxFooter();
  311. $db->close();