| @@ -1,10 +1,15 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace FluentSupport\App\Modules\Reporting; |
| 4 | 4 | |
| 5 | +/** | |
| 6 | + * Date range, bucketing and formatting helpers for reports. | |
| 7 | + */ | |
| 8 | + | |
| 5 | 9 | trait ReportingHelperTrait |
| 6 | 10 | { |
| 11 | + protected static $hourly = 'PT1H'; | |
| 7 | 12 | protected static $daily = 'P1D'; |
| 8 | 13 | protected static $weekly = 'P1W'; |
| 9 | 14 | protected static $monthly = 'P1M'; |
| 10 | 15 | |
| @@ -32,13 +37,24 @@ | ||
| 32 | 37 | |
| 33 | 38 | return new \DatePeriod($from, new \DateInterval($interval), $to); |
| 34 | 39 | } |
| 35 | 40 | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * Bucket size for the range: hourly for one day, daily up to 62 days, | |
| 44 | + * weekly up to 181, monthly beyond. | |
| 45 | + * | |
| 46 | + * @param $from | |
| 47 | + * @param $to | |
| 48 | + * @return string | |
| 49 | + */ | |
| 36 | 50 | protected function getFrequency($from, $to) |
| 37 | 51 | { |
| 38 | 52 | $numDays = $to->diff($from)->format("%a"); |
| 39 | - | |
| 40 | - if ($numDays > 62 && $numDays <= 181) { | |
| 53 | + if($numDays <= 0) { | |
| 54 | + return static::$hourly; | |
| 55 | + } | |
| 56 | + else if ($numDays > 62 && $numDays <= 181) { | |
| 41 | 57 | return static::$weekly; |
| 42 | 58 | } else if ($numDays > 181) { |
| 43 | 59 | return static::$monthly; |
| 44 | 60 | } |
| @@ -45,16 +61,35 @@ | ||
| 45 | 61 | |
| 46 | 62 | return static::$daily; |
| 47 | 63 | } |
| 48 | 64 | |
| 49 | - protected function prepareSelect($frequency, $dateField = 'created_at') | |
| 65 | + /** | |
| 66 | + * @param $frequency | |
| 67 | + * @param string $dateField | |
| 68 | + * @return array | |
| 69 | + */ | |
| 70 | + protected function prepareSelect($frequency, $dateField = 'created_at', $type = 'count_id') | |
| 50 | 71 | { |
| 72 | + switch ($type) { | |
| 73 | + case 'count_id': | |
| 74 | + $countField = 'COUNT(id) AS count'; | |
| 75 | + break; | |
| 76 | + case 'response_count': | |
| 77 | + $countField = 'SUM(response_count) AS count'; | |
| 78 | + break; | |
| 79 | + default: | |
| 80 | + $countField = 'COUNT(id) AS count'; | |
| 81 | + } | |
| 82 | + | |
| 51 | 83 | $select = [ |
| 52 | - $this->db()->raw('COUNT(id) AS count'), | |
| 53 | - $this->db()->raw('DATE('.$dateField.') AS date') | |
| 84 | + $this->db()->raw($countField), | |
| 85 | + $this->db()->raw('DATE('.$dateField.') AS date'), | |
| 86 | + $this->db()->raw('TIME('.$dateField.') AS time') | |
| 54 | 87 | ]; |
| 55 | 88 | |
| 56 | - if ($frequency == static::$weekly) { | |
| 89 | + if ($frequency == static::$hourly) { | |
| 90 | + $select[] = $this->db()->raw('HOUR(created_at) hourly'); | |
| 91 | + } else if ($frequency == static::$weekly) { | |
| 57 | 92 | $select[] = $this->db()->raw('WEEK(created_at) week'); |
| 58 | 93 | } else if ($frequency == static::$monthly) { |
| 59 | 94 | $select[] = $this->db()->raw('MONTH(created_at) month'); |
| 60 | 95 | } |
| @@ -61,13 +96,33 @@ | ||
| 61 | 96 | |
| 62 | 97 | return $select; |
| 63 | 98 | } |
| 64 | 99 | |
| 100 | + protected function prepareBetween($frequency, $from, $to) | |
| 101 | + { | |
| 102 | + if($frequency == static::$hourly){ | |
| 103 | + return [ | |
| 104 | + $from->format('Y-m-d')." 00:00:00", | |
| 105 | + $to->format('Y-m-d')." 23:59:59" | |
| 106 | + ]; | |
| 107 | + } | |
| 108 | + return [ | |
| 109 | + $from->format('Y-m-d')." 00:00:00", | |
| 110 | + $to->format('Y-m-d')." 23:59:59" | |
| 111 | + ]; | |
| 112 | + } | |
| 113 | + | |
| 114 | + /** | |
| 115 | + * @param $frequency | |
| 116 | + * @return string[] | |
| 117 | + */ | |
| 65 | 118 | protected function getGroupAndOrder($frequency) |
| 66 | 119 | { |
| 67 | 120 | $orderBy = $groupBy = 'date'; |
| 68 | 121 | |
| 69 | - if ($frequency == static::$weekly) { | |
| 122 | + if ($frequency == static::$hourly) { | |
| 123 | + $orderBy = $groupBy = 'hourly'; | |
| 124 | + } elseif ($frequency == static::$weekly) { | |
| 70 | 125 | $orderBy = $groupBy = 'week'; |
| 71 | 126 | } else if ($frequency == static::$monthly) { |
| 72 | 127 | $orderBy = $groupBy = 'month'; |
| 73 | 128 | } |
| @@ -98,15 +153,23 @@ | ||
| 98 | 153 | $range = $this->getDateRangeArray($period); |
| 99 | 154 | |
| 100 | 155 | $formatter = 'basicFormatter'; |
| 101 | 156 | |
| 102 | - if ($this->isMonthly($period)) { | |
| 157 | + if ($this->isHourly($period)) { | |
| 158 | + $formatter = 'hourlyFormatter'; | |
| 159 | + } | |
| 160 | + else if ($this->isMonthly($period)) { | |
| 103 | 161 | $formatter = 'monYearFormatter'; |
| 104 | 162 | } |
| 105 | 163 | |
| 106 | 164 | foreach ($items as $item) { |
| 107 | - $date = $this->{$formatter}($item->date); | |
| 108 | - $range[$date] = (int) $item->count; | |
| 165 | + if($this->isHourly($period)){ | |
| 166 | + $time = $this->{$formatter}($item->time); | |
| 167 | + $range[$time] = (int) $item->count; | |
| 168 | + }else{ | |
| 169 | + $date = $this->{$formatter}($item->date); | |
| 170 | + $range[$date] = (int) $item->count; | |
| 171 | + } | |
| 109 | 172 | } |
| 110 | 173 | |
| 111 | 174 | return $range; |
| 112 | 175 | } |
| @@ -115,8 +178,13 @@ | ||
| 115 | 178 | { |
| 116 | 179 | return !!$period->getDateInterval()->m; |
| 117 | 180 | } |
| 118 | 181 | |
| 182 | + protected function isHourly($period) | |
| 183 | + { | |
| 184 | + return !!$period->getDateInterval()->h; | |
| 185 | + } | |
| 186 | + | |
| 119 | 187 | protected function basicFormatter($date) |
| 120 | 188 | { |
| 121 | 189 | if (is_string($date)) { |
| 122 | 190 | $date = new \DateTime($date); |
| @@ -122,8 +190,17 @@ | ||
| 122 | 190 | $date = new \DateTime($date); |
| 123 | 191 | } |
| 124 | 192 | |
| 125 | 193 | return $date->format('Y-m-d'); |
| 194 | + } | |
| 195 | + | |
| 196 | + protected function hourlyFormatter($date) | |
| 197 | + { | |
| 198 | + if (is_string($date)) { | |
| 199 | + $date = new \DateTime($date); | |
| 200 | + } | |
| 201 | + | |
| 202 | + return $date->format('H').':00' .' - '. $date->format('H').':59'; | |
| 126 | 203 | } |
| 127 | 204 | |
| 128 | 205 | protected function monYearFormatter($date) |
| 129 | 206 | { |