CRM-16715 - Contribution Summary Report: add mode and median statistics; group by...
authorjitendrapurohit <jitendra.purohit@webaccessglobal.com>
Mon, 22 Jun 2015 05:55:53 +0000 (11:25 +0530)
committerjitendrapurohit <jitendra.purohit@webaccessglobal.com>
Tue, 23 Jun 2015 12:51:46 +0000 (18:21 +0530)
CRM/Report/Form/Contribute/Summary.php

index 4ce59b8e40bc93f7804ef0ac4e52b8485c0665c7..d42958f8dd3c4186ad99d26654d5b36815241994 100644 (file)
@@ -45,6 +45,19 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form {
 
   public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
 
+  /**
+   * To what frequency group-by a date column
+   *
+   * @var array
+   */
+  protected $_groupByDateFreq = array(
+    'MONTH' => 'Month',
+    'YEARWEEK' => 'Week',
+    'QUARTER' => 'Quarter',
+    'YEAR' => 'Year',
+    'FISCALYEAR' => 'Fiscal Year',
+  );
+
   /**
    */
   public function __construct() {
@@ -308,6 +321,17 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form {
                 $field['title'] = 'Year';
                 break;
 
+              case 'FISCALYEAR':
+                $config = CRM_Core_Config::singleton();
+                $fy = $config->fiscalYearStart;
+                $fiscal = self::fiscalYearOffset($field['dbAlias']);
+
+                $select[] = "DATE_ADD(MAKEDATE({$fiscal}, 1), INTERVAL ({$fy{'M'}})-1 MONTH) AS {$tableName}_{$fieldName}_start";
+                $select[] = "{$fiscal} AS {$tableName}_{$fieldName}_subtotal";
+                $select[] = "{$fiscal} AS {$tableName}_{$fieldName}_interval";
+                $field['title'] = 'Fiscal Year';
+                break;
+
               case 'MONTH':
                 $select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL (DAYOFMONTH({$field['dbAlias']})-1) DAY) as {$tableName}_{$fieldName}_start";
                 $select[] = "MONTH({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
@@ -474,7 +498,12 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form {
                 )) {
                   $append = '';
                 }
-                $this->_groupBy[] = "$append {$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
+                if ($this->_params['group_bys_freq'][$fieldName] == 'FISCALYEAR') {
+                  $this->_groupBy[] = self::fiscalYearOffset($field['dbAlias']);
+                }
+                else {
+                  $this->_groupBy[] = "$append {$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
+                }
                 $append = TRUE;
               }
               else {
@@ -527,12 +556,12 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form {
     $group = "\nGROUP BY {$this->_aliases['civicrm_contribution']}.currency";
 
     $this->from('contribution');
-    $contriSQL = "SELECT
+    $contriQuery = "
 COUNT({$this->_aliases['civicrm_contribution']}.total_amount )        as civicrm_contribution_total_amount_count,
 SUM({$this->_aliases['civicrm_contribution']}.total_amount )          as civicrm_contribution_total_amount_sum,
 ROUND(AVG({$this->_aliases['civicrm_contribution']}.total_amount), 2) as civicrm_contribution_total_amount_avg,
 {$this->_aliases['civicrm_contribution']}.currency                    as currency
-{$this->_from} {$this->_where} {$group} {$this->_having}";
+{$this->_from} {$this->_where}";
 
     if ($softCredit) {
       $this->from();
@@ -544,10 +573,11 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_
 {$this->_from} {$this->_where} {$group} {$this->_having}";
     }
 
+    $contriSQL = "SELECT {$contriQuery} {$group} {$this->_having}";
     $contriDAO = CRM_Core_DAO::executeQuery($contriSQL);
 
-    $totalAmount = $average = $softTotalAmount = $softAverage = array();
-    $count = $softCount = 0;
+    $totalAmount = $average = $mode = $median = $softTotalAmount = $softAverage = array();
+    $count = $midValue = $softCount = 0;
     while ($contriDAO->fetch()) {
       $totalAmount[]
         = CRM_Utils_Money::format($contriDAO->civicrm_contribution_total_amount_sum, $contriDAO->currency) .
@@ -556,6 +586,54 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_
       $count += $contriDAO->civicrm_contribution_total_amount_count;
     }
 
+    $groupBy = "\n{$group}, {$this->_aliases['civicrm_contribution']}.total_amount";
+    $orderBy = "\nORDER BY civicrm_contribution_total_amount_count DESC";
+    $modeSQL = "SELECT civicrm_contribution_total_amount_count, civicrm_contribution_total_amount, currency
+    FROM (SELECT {$this->_aliases['civicrm_contribution']}.total_amount as civicrm_contribution_total_amount,
+    {$contriQuery} {$groupBy} {$orderBy}) as mode GROUP BY currency";
+
+    $modeDAO = CRM_Core_DAO::executeQuery($modeSQL);
+    while ($modeDAO->fetch()) {
+      if ($modeDAO->civicrm_contribution_total_amount_count > 1) {
+        $mode[] = CRM_Utils_Money::format($modeDAO->civicrm_contribution_total_amount, $modeDAO->currency);
+      }
+      else {
+        $mode[] = 'N/A';
+      }
+    }
+
+    $currencies = CRM_Core_OptionGroup::values('currencies_enabled');
+    foreach ($currencies as $currency => $val) {
+      $where = "AND {$this->_aliases['civicrm_contribution']}.currency = '{$currency}'";
+      $rowCount = CRM_Core_DAO::singleValueQuery("SELECT count(*) as count {$this->_from} {$this->_where} {$where}");
+
+      $even = FALSE;
+      $offset = 1;
+      $medianRow = floor($rowCount / 2);
+      if ($rowCount % 2 == 0 && !empty($medianRow)) {
+        $even = TRUE;
+        $offset++;
+        $medianRow--;
+      }
+
+      $medianValue = "SELECT {$this->_aliases['civicrm_contribution']}.total_amount as median
+         {$this->_from} {$this->_where} {$where}
+         ORDER BY median LIMIT {$medianRow},{$offset}";
+      $medianValDAO = CRM_Core_DAO::executeQuery($medianValue);
+      while ($medianValDAO->fetch()) {
+        if ($even) {
+          $midValue = $midValue + $medianValDAO->median;
+        }
+        else {
+          $median[] = CRM_Utils_Money::format($medianValDAO->median, $currency);
+        }
+      }
+      if ($even) {
+        $midValue = $midValue/2;
+        $median[] = CRM_Utils_Money::format($midValue, $currency);
+      }
+    }
+
     if ($softCredit) {
       $softDAO = CRM_Core_DAO::executeQuery($softSQL);
       while ($softDAO->fetch()) {
@@ -582,6 +660,16 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_
         'value' => implode(',  ', $average),
         'type' => CRM_Utils_Type::T_STRING,
       );
+      $statistics['counts']['mode'] = array(
+        'title' => ts('Mode'),
+        'value' => implode(',  ', $mode),
+        'type' => CRM_Utils_Type::T_STRING,
+      );
+      $statistics['counts']['median'] = array(
+        'title' => ts('Median'),
+        'value' => implode(',  ', $median),
+        'type' => CRM_Utils_Type::T_STRING,
+      );
     }
     if ($softCredit) {
       $statistics['counts']['soft_amount'] = array(
@@ -755,6 +843,12 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_
             ));
             break;
 
+          case 'fiscalyear':
+            $dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'],
+              $dateEnd['d'] - 1, $dateEnd['Y'] + 1
+            ));
+            break;
+
           case 'yearweek':
             $dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'],
               $dateEnd['d'] + 6, $dateEnd['Y']