PageRenderTime 88ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 12ms

/modules/Charts/code/Chart_lead_source_by_outcome.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 448 lines | 324 code | 59 blank | 65 comment | 60 complexity | 57dce3ab6e6a551a361dfabd471808f7 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
  3. /*********************************************************************************
  4. * SugarCRM Community Edition is a customer relationship management program developed by
  5. * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it under
  8. * the terms of the GNU Affero General Public License version 3 as published by the
  9. * Free Software Foundation with the addition of the following permission added
  10. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  11. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  12. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License along with
  20. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  21. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22. * 02110-1301 USA.
  23. *
  24. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  25. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  26. *
  27. * The interactive user interfaces in modified source and object code versions
  28. * of this program must display Appropriate Legal Notices, as required under
  29. * Section 5 of the GNU Affero General Public License version 3.
  30. *
  31. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  32. * these Appropriate Legal Notices must retain the display of the "Powered by
  33. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  34. * technical reasons, the Appropriate Legal Notices must display the words
  35. * "Powered by SugarCRM".
  36. ********************************************************************************/
  37. /*********************************************************************************
  38. * Description: returns HTML for client-side image map.
  39. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
  40. * All Rights Reserved.
  41. * Contributor(s): ______________________________________..
  42. ********************************************************************************/
  43. require_once('include/charts/Charts.php');
  44. class Chart_lead_source_by_outcome
  45. {
  46. var $modules = array('Opportunities');
  47. var $order = 0;
  48. function Chart_lead_source_by_outcome()
  49. {
  50. }
  51. function draw($extra_tools)
  52. {
  53. global $app_list_strings, $current_language, $sugar_config, $currentModule, $action,$theme;
  54. $current_module_strings = return_module_language($current_language, 'Charts');
  55. if (isset($_REQUEST['lsbo_refresh'])) { $refresh = $_REQUEST['lsbo_refresh']; }
  56. else { $refresh = false; }
  57. $tempx = array();
  58. $datax = array();
  59. $selected_datax = array();
  60. //get list of sales stage keys to display
  61. global $current_user;
  62. $tempx = $current_user->getPreference('lsbo_lead_sources');
  63. if (!empty($lsbo_lead_sources) && count($lsbo_lead_sources) > 0 && !isset($_REQUEST['lsbo_lead_sources'])) {
  64. $GLOBALS['log']->fatal("user->getPreference('lsbo_lead_sources') is:");
  65. $GLOBALS['log']->fatal($tempx);
  66. }
  67. elseif (isset($_REQUEST['lsbo_lead_sources']) && count($_REQUEST['lsbo_lead_sources']) > 0) {
  68. $tempx = $_REQUEST['lsbo_lead_sources'];
  69. $current_user->setPreference('lsbo_lead_sources', $_REQUEST['lsbo_lead_sources']);
  70. $GLOBALS['log']->fatal("_REQUEST['lsbo_lead_sources'] is:");
  71. $GLOBALS['log']->fatal($_REQUEST['lsbo_lead_sources']);
  72. $GLOBALS['log']->fatal("user->getPreference('lsbo_lead_sources') is:");
  73. $GLOBALS['log']->fatal($current_user->getPreference('lsbo_lead_sources'));
  74. }
  75. //set $datax using selected sales stage keys
  76. if (!empty($tempx) && sizeof($tempx) > 0) {
  77. foreach ($tempx as $key) {
  78. $datax[$key] = $app_list_strings['lead_source_dom'][$key];
  79. array_push($selected_datax,$key);
  80. }
  81. }
  82. else {
  83. $datax = $app_list_strings['lead_source_dom'];
  84. $selected_datax = array_keys($app_list_strings['lead_source_dom']);
  85. }
  86. $ids =$current_user->getPreference('lsbo_ids');
  87. //get list of user ids for which to display data
  88. if (!empty($ids) && count($ids) != 0 && !isset($_REQUEST['lsbo_ids'])) {
  89. $GLOBALS['log']->debug("_SESSION['lsbo_ids'] is:");
  90. $GLOBALS['log']->debug($ids);
  91. }
  92. elseif (isset($_REQUEST['lsbo_ids']) && count($_REQUEST['lsbo_ids']) > 0) {
  93. $ids = $_REQUEST['lsbo_ids'];
  94. $current_user->setPreference('lsbo_ids', $_REQUEST['lsbo_ids']);
  95. $GLOBALS['log']->debug("_REQUEST['lsbo_ids'] is:");
  96. $GLOBALS['log']->debug($_REQUEST['lsbo_ids']);
  97. $GLOBALS['log']->debug("user->getPreference('lsbo_ids') is:");
  98. $GLOBALS['log']->debug($current_user->getPreference('lsbo_ids'));
  99. }
  100. else {
  101. $ids = get_user_array(false);
  102. $ids = array_keys($ids);
  103. }
  104. //create unique prefix based on selected users for image files
  105. $id_hash = '1';
  106. if (isset($ids)) {
  107. sort($ids);
  108. $id_hash = crc32(implode('',$ids));
  109. if($id_hash < 0)
  110. {
  111. $id_hash = $id_hash * -1;
  112. }
  113. }
  114. $GLOBALS['log']->debug("ids is:");
  115. $GLOBALS['log']->debug($ids);
  116. $id_md5 = substr(md5($current_user->id),0,9);
  117. $seps = array("-", "/");
  118. $dates = array(date($GLOBALS['timedate']->dbDayFormat), $GLOBALS['timedate']->dbDayFormat);
  119. $dateFileNameSafe = str_replace($seps, "_", $dates);
  120. $cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_lead_source_by_outcome_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml";
  121. $GLOBALS['log']->debug("cache file name is: $cache_file_name");
  122. $tools='<div align="right"><a href="index.php?module='.$currentModule.'&action='. $action .'&lsbo_refresh=true" class="tabFormAdvLink">'.SugarThemeRegistry::current()->getImage('refresh','border="0" align="absmiddle"', null,null,'.gif',$mod_strings['LBL_REFRESH']).'&nbsp;'.$current_module_strings['LBL_REFRESH'].'</a>&nbsp;&nbsp;<a href="javascript: toggleDisplay(\'lsbo_edit\');" class="tabFormAdvLink">'.SugarThemeRegistry::current()->getImage('edit','border="0" align="absmiddle"',null,null,'.gif',$mod_strings['LBL_EDIT']).'&nbsp;'. $current_module_strings['LBL_EDIT'].'</a>&nbsp;&nbsp;'.$extra_tools.'</div>';
  123. ?>
  124. <?php
  125. echo '<span onmouseover="this.style.cursor=\'move\'" id="chart_handle_' . $this->order . '">' . get_form_header($current_module_strings['LBL_LEAD_SOURCE_BY_OUTCOME'],$tools,false) . '</span>';
  126. if (empty($_SESSION['lsbo_ids'])) $_SESSION['lsbo_ids'] = "";
  127. ?>
  128. <p>
  129. <div id='lsbo_edit' style='display: none;'>
  130. <form action="index.php" method="post" >
  131. <input type="hidden" name="module" value="<?php echo $currentModule;?>">
  132. <input type="hidden" name="action" value="<?php echo $action;?>">
  133. <input type="hidden" name="lsbo_refresh" value="true">
  134. <table cellpadding="0" cellspacing="0" border="0" class="edit view" align="center">
  135. <tr>
  136. <td valign='top' nowrap><b><?php echo $current_module_strings['LBL_LEAD_SOURCES'];?></b></td>
  137. <td valign='top'><select name="lsbo_lead_sources[]" multiple size='3'><?php echo get_select_options_with_id($app_list_strings['lead_source_dom'],$selected_datax); ?></select></td>
  138. </tr>
  139. <tr>
  140. <td valign='top' nowrap><b><?php echo $current_module_strings['LBL_USERS'];?></b></td>
  141. <td valign='top'><select name="lsbo_ids[]" multiple size='3'><?php echo get_select_options_with_id(get_user_array(false),$ids); ?></select></td>
  142. </tr>
  143. <tr>
  144. <?php
  145. global $app_strings;
  146. ?>
  147. <td align="right" colspan="2"> <input class="button" type="submit" title="<?php echo $app_strings['LBL_SELECT_BUTTON_TITLE']; ?>" value="<?php echo $app_strings['LBL_SELECT_BUTTON_LABEL']?>" /><input class="button" onClick="javascript: toggleDisplay('lsbo_edit');" type="button" title="<?php echo $app_strings['LBL_CANCEL_BUTTON_TITLE']; ?>" accessKey="<?php echo $app_strings['LBL_CANCEL_BUTTON_KEY'];?>" value="<?php echo $app_strings['LBL_CANCEL_BUTTON_LABEL']?>"/></td>
  148. </tr>
  149. </table>
  150. </form>
  151. </div>
  152. </p>
  153. <?php
  154. echo "<p align='center'>".$this->gen_xml($datax, $ids, $cache_file_name, $refresh,$current_module_strings)."</p>";
  155. echo "<P align='center'><span class='chartFootnote'>".$current_module_strings['LBL_LEAD_SOURCE_BY_OUTCOME_DESC']."</span></P>";
  156. if (file_exists($cache_file_name)) {
  157. global $timedate;
  158. $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name)));
  159. }
  160. else {
  161. $file_date = '';
  162. }
  163. ?>
  164. <span class='chartFootnote'>
  165. <p align="right"><i><?php echo $current_module_strings['LBL_CREATED_ON'].' '.$file_date; ?></i></p>
  166. </span>
  167. <?php
  168. }
  169. /**
  170. * Creates lead_source_by_outcome pipeline image as a HORIZONAL accumlated bar graph for multiple users.
  171. * param $datay- the lead source data to display in the x-axis
  172. * param $ids - list of assigned users of opps to find
  173. * param $cache_file_name - file name to write image to
  174. * param $refresh - boolean whether to rebuild image if exists
  175. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  176. * All Rights Reserved..
  177. * Contributor(s): ______________________________________..
  178. */
  179. function gen_xml($datay=array('foo','bar'), $user_id=array('1'), $cache_file_name='a_file', $refresh=false,$current_module_strings) {
  180. global $app_strings, $charset, $lang, $barChartColors,$app_list_strings, $current_user;
  181. $kDelim = $current_user->getPreference('num_grp_sep');
  182. if (!file_exists($cache_file_name) || $refresh == true) {
  183. $GLOBALS['log']->debug("datay is:");
  184. $GLOBALS['log']->debug($datay);
  185. $GLOBALS['log']->debug("user_id is: ");
  186. $GLOBALS['log']->debug($user_id);
  187. $GLOBALS['log']->debug("cache_file_name is: $cache_file_name");
  188. $opp = new Opportunity();
  189. $where="";
  190. //build the where clause for the query that matches $user
  191. $count = count($user_id);
  192. $id = array();
  193. if ($count>0) {
  194. foreach ($user_id as $the_id) {
  195. $id[] = "'".$the_id."'";
  196. }
  197. $ids = join(",",$id);
  198. $where .= "opportunities.assigned_user_id IN ($ids) ";
  199. }
  200. //build the where clause for the query that matches $datay
  201. $count = count($datay);
  202. $datayArr = array();
  203. if ($count>0) {
  204. foreach ($datay as $key=>$value) {
  205. $datayArr[] = "'".$key."'";
  206. }
  207. $datayArr = join(",",$datayArr);
  208. $where .= "AND opportunities.lead_source IN ($datayArr) ";
  209. }
  210. $query = "SELECT lead_source,sales_stage,sum(amount_usdollar/1000) as total,count(*) as opp_count FROM opportunities ";
  211. $query .= "WHERE " .$where." AND opportunities.deleted=0 ";
  212. $query .= " GROUP BY sales_stage,lead_source ORDER BY lead_source,sales_stage";
  213. //Now do the db queries
  214. //query for opportunity data that matches $datay and $user
  215. $result = $opp->db->query($query, true);
  216. //build pipeline by sales stage data
  217. $total = 0;
  218. $div = 1;
  219. global $sugar_config;
  220. $symbol = $sugar_config['default_currency_symbol'];
  221. $other = $current_module_strings['LBL_LEAD_SOURCE_OTHER'];
  222. $rowTotalArr = array();
  223. $rowTotalArr[] = 0;
  224. global $current_user;
  225. $salesStages = array("Closed Lost"=>$app_list_strings['sales_stage_dom']["Closed Lost"],"Closed Won"=>$app_list_strings['sales_stage_dom']["Closed Won"],"Other"=>$other);
  226. if($current_user->getPreference('currency') ){
  227. $currency = new Currency();
  228. $currency->retrieve($current_user->getPreference('currency'));
  229. $div = $currency->conversion_rate;
  230. $symbol = $currency->symbol;
  231. }
  232. $fileContents = ' <yData defaultAltText="'.$current_module_strings['LBL_ROLLOVER_DETAILS'].'">'."\n";
  233. $leadSourceArr = array();
  234. while($row = $opp->db->fetchByAssoc($result, false))
  235. {
  236. if($row['total']*$div<=100){
  237. $sum = round($row['total']*$div, 2);
  238. } else {
  239. $sum = round($row['total']*$div);
  240. }
  241. if($row['lead_source'] == ''){
  242. $row['lead_source'] = $current_module_strings['NTC_NO_LEGENDS'];
  243. }
  244. if($row['sales_stage'] == 'Closed Won' || $row['sales_stage'] == 'Closed Lost'){
  245. $salesStage = $row['sales_stage'];
  246. $salesStageT = $app_list_strings['sales_stage_dom'][$row['sales_stage']];
  247. } else {
  248. $salesStage = "Other";
  249. $salesStageT = $other;
  250. }
  251. if(!isset($leadSourceArr[$row['lead_source']]['row_total'])) {$leadSourceArr[$row['lead_source']]['row_total']=0;}
  252. $leadSourceArr[$row['lead_source']][$salesStage]['opp_count'][] = $row['opp_count'];
  253. $leadSourceArr[$row['lead_source']][$salesStage]['total'][] = $sum;
  254. $leadSourceArr[$row['lead_source']]['outcome'][$salesStage]=$salesStageT;
  255. $leadSourceArr[$row['lead_source']]['row_total'] += $sum;
  256. $total += $sum;
  257. }
  258. foreach ($datay as $key=>$translation) {
  259. if ($key == '') {
  260. $key = $current_module_strings['NTC_NO_LEGENDS'];
  261. $translation = $current_module_strings['NTC_NO_LEGENDS'];
  262. }
  263. if(!isset($leadSourceArr[$key])){
  264. $leadSourceArr[$key] = $key;
  265. }
  266. if(isset($leadSourceArr[$key]['row_total'])){$rowTotalArr[]=$leadSourceArr[$key]['row_total'];}
  267. if(isset($leadSourceArr[$key]['row_total']) && $leadSourceArr[$key]['row_total']>100){
  268. $leadSourceArr[$key]['row_total'] = round($leadSourceArr[$key]['row_total']);
  269. }
  270. $fileContents .= ' <dataRow title="'.$translation.'" endLabel="'.currency_format_number($leadSourceArr[$key]['row_total'], array('currency_symbol' => true)) . '">'."\n";
  271. if(is_array($leadSourceArr[$key]['outcome'])){
  272. foreach ($leadSourceArr[$key]['outcome'] as $outcome=>$outcome_translation){
  273. $fileContents .= ' <bar id="'.$outcome.'" totalSize="'.array_sum($leadSourceArr[$key][$outcome]['total']).'" altText="'.format_number(array_sum($leadSourceArr[$key][$outcome]['opp_count']),0,0).' '.$current_module_strings['LBL_OPPS_WORTH'].' '.currency_format_number(array_sum($leadSourceArr[$key][$outcome]['total']),array('currency_symbol' => true)).$current_module_strings['LBL_OPP_THOUSANDS'].' '.$current_module_strings['LBL_OPPS_OUTCOME'].' '.$outcome_translation.'" url="index.php?module=Opportunities&action=index&lead_source='.$key.'&sales_stage='.urlencode($outcome).'&query=true&searchFormTab=advanced_search"/>'."\n";
  274. }
  275. }
  276. $fileContents .= ' </dataRow>'."\n";
  277. }
  278. $fileContents .= ' </yData>'."\n";
  279. $max = get_max($rowTotalArr);
  280. $fileContents .= ' <xData min="0" max="'.$max.'" length="10" kDelim="'.$kDelim.'" prefix="'.$symbol.'" suffix=""/>' . "\n";
  281. $fileContents .= ' <colorLegend status="on">'."\n";
  282. $i=0;
  283. foreach ($salesStages as $outcome=>$outcome_translation) {
  284. $color = generate_graphcolor($outcome,$i);
  285. $fileContents .= ' <mapping id="'.$outcome.'" name="'.$outcome_translation.'" color="'.$color.'"/>'."\n";
  286. $i++;
  287. }
  288. $fileContents .= ' </colorLegend>'."\n";
  289. $fileContents .= ' <graphInfo>'."\n";
  290. $fileContents .= ' <![CDATA['.$current_module_strings['LBL_OPP_SIZE'].' '.$symbol.'1'.$current_module_strings['LBL_OPP_THOUSANDS'].']]>'."\n";
  291. $fileContents .= ' </graphInfo>'."\n";
  292. $fileContents .= ' <chartColors ';
  293. foreach ($barChartColors as $key => $value) {
  294. $fileContents .= ' '.$key.'='.'"'.$value.'" ';
  295. }
  296. $fileContents .= ' />'."\n";
  297. $fileContents .= '</graphData>'."\n";
  298. $total = round($total, 2);
  299. $title = '<graphData title="'.$current_module_strings['LBL_ALL_OPPORTUNITIES'].currency_format_number($total, array('currency_symbol' => true)).$app_strings['LBL_THOUSANDS_SYMBOL'].'">'."\n";
  300. $fileContents = $title.$fileContents;
  301. save_xml_file($cache_file_name, $fileContents);
  302. }
  303. $return = create_chart('hBarF',$cache_file_name);
  304. return $return;
  305. }
  306. function constructQuery(){
  307. global $current_user;
  308. global $app_list_strings;
  309. $tempx = array();
  310. $datax = array();
  311. $selected_datax = array();
  312. //get list of sales stage keys to display
  313. $tempx = $current_user->getPreference('lsbo_lead_sources');
  314. if (!empty($lsbo_lead_sources) && count($lsbo_lead_sources) > 0 && !isset($_REQUEST['lsbo_lead_sources'])) {
  315. $GLOBALS['log']->fatal("user->getPreference('lsbo_lead_sources') is:");
  316. $GLOBALS['log']->fatal($tempx);
  317. }
  318. elseif (isset($_REQUEST['lsbo_lead_sources']) && count($_REQUEST['lsbo_lead_sources']) > 0) {
  319. $tempx = $_REQUEST['lsbo_lead_sources'];
  320. $current_user->setPreference('lsbo_lead_sources', $_REQUEST['lsbo_lead_sources']);
  321. $GLOBALS['log']->fatal("_REQUEST['lsbo_lead_sources'] is:");
  322. $GLOBALS['log']->fatal($_REQUEST['lsbo_lead_sources']);
  323. $GLOBALS['log']->fatal("user->getPreference('lsbo_lead_sources') is:");
  324. $GLOBALS['log']->fatal($current_user->getPreference('lsbo_lead_sources'));
  325. }
  326. //set $datax using selected sales stage keys
  327. if (!empty($tempx) && sizeof($tempx) > 0) {
  328. foreach ($tempx as $key) {
  329. $datax[$key] = $app_list_strings['lead_source_dom'][$key];
  330. array_push($selected_datax,$key);
  331. }
  332. }
  333. else {
  334. $datax = $app_list_strings['lead_source_dom'];
  335. $selected_datax = array_keys($app_list_strings['lead_source_dom']);
  336. }
  337. $datay = $datax;
  338. $ids =$current_user->getPreference('lsbo_ids');
  339. //get list of user ids for which to display data
  340. if (!empty($ids) && count($ids) != 0 && !isset($_REQUEST['lsbo_ids'])) {
  341. $GLOBALS['log']->debug("_SESSION['lsbo_ids'] is:");
  342. $GLOBALS['log']->debug($ids);
  343. }
  344. elseif (isset($_REQUEST['lsbo_ids']) && count($_REQUEST['lsbo_ids']) > 0) {
  345. $ids = $_REQUEST['lsbo_ids'];
  346. $current_user->setPreference('lsbo_ids', $_REQUEST['lsbo_ids']);
  347. $GLOBALS['log']->debug("_REQUEST['lsbo_ids'] is:");
  348. $GLOBALS['log']->debug($_REQUEST['lsbo_ids']);
  349. $GLOBALS['log']->debug("user->getPreference('lsbo_ids') is:");
  350. $GLOBALS['log']->debug($current_user->getPreference('lsbo_ids'));
  351. }
  352. else {
  353. $ids = get_user_array(false);
  354. $ids = array_keys($ids);
  355. }
  356. $user_id = $ids;
  357. $opp = new Opportunity();
  358. $where="";
  359. //build the where clause for the query that matches $user
  360. $count = count($user_id);
  361. $id = array();
  362. if ($count>0) {
  363. foreach ($user_id as $the_id) {
  364. $id[] = "'".$the_id."'";
  365. }
  366. $ids = join(",",$id);
  367. $where .= "opportunities.assigned_user_id IN ($ids) ";
  368. }
  369. //build the where clause for the query that matches $datay
  370. $count = count($datay);
  371. $datayArr = array();
  372. if ($count>0) {
  373. foreach ($datay as $key=>$value) {
  374. $datayArr[] = "'".$key."'";
  375. }
  376. $datayArr = join(",",$datayArr);
  377. $where .= "AND opportunities.lead_source IN ($datayArr) ";
  378. }
  379. $query = "SELECT lead_source,sales_stage,sum(amount_usdollar/1000) as total,count(*) as opp_count FROM opportunities ";
  380. $query .= "WHERE " .$where." AND opportunities.deleted=0 ";
  381. $query .= " GROUP BY sales_stage,lead_source ORDER BY lead_source,sales_stage";
  382. return $query;
  383. }
  384. function constructGroupBy(){
  385. return array( 'lead_source', 'sales_stage' );
  386. }
  387. }
  388. ?>