public function showSinglestat($statID) { if (Auth::check()) { return Redirect::route('connect.connect'); } else { try { $user = User::find(1); Auth::login($user); $currentMetrics = Calculator::currentMetrics(); $metricValues = Metric::where('user', Auth::user()->id)->where('date', '<', Carbon::now())->orderBy('date', 'desc')->take(31)->get(); foreach ($currentMetrics as $metricID => $statClassName) { if ($metricID == $statID) { $metricsArray = array(); foreach ($metricValues as $metric) { $metricsArray[$metric->date] = $metric->{$metricID}; } ksort($metricsArray); $allMetrics[$metricID] = $metricsArray; } } if (isset($currentMetrics[$statID])) { return View::make('demo.single_stat', array('data' => $currentMetrics[$statID]['metricClass']::show($allMetrics[$statID], true), 'metricDetails' => $currentMetrics[$statID], Auth::logout())); } return Redirect::route('demo.dashboard')->with('error', 'Statistic does not exist.'); } catch (Exception $e) { Auth::logout(); Log::error($e); return Redirect::route('demo.dashboard')->with('error', 'Something went wrong, we will return shortly.'); } } }
/** * Get stat on given day * * @param timestamp, current day timestamp * * @return int (cents) or null if data not exist */ public static function getStatOnDay($timeStamp) { $day = date('Y-m-d', $timeStamp); $stats = Metric::where('date', $day)->where('user', Auth::user()->id)->first(); if ($stats) { $statValue = $stats->{self::$statID}; return $statValue; } else { return null; } }
/** * daily metric calculator - called from cron script * @param $user * * @return null */ public static function calculateMetrics($user, $time) { // get needed time vars if ($time) { $timestamp = $time; } else { $timestamp = time(); } $today = date('Y-m-d', $timestamp); $yesterday = date('Y-m-d', $timestamp - 86400); // get today's metrics $metrics = Metric::firstOrNew(array('user' => $user->id, 'date' => $today)); // get yesterday's metrics // this should never return an empty array $yesterdayMetric = Metric::where('user', $user->id)->where('date', $yesterday)->first(); if (!$yesterdayMetric) { Calculator::calculateMetrics($user, $timestamp - 86400); $yesterdayMetric = Metric::where('user', $user->id)->where('date', $yesterday)->first(); } // get today's events $events = Event::where('user', $user->id)->where('date', $today)->get(); // events have a provider, needs merging // FIXME!!!! // calculate all the metrics // monthly recurring revenue // return int $metrics->mrr = MrrStat::calculate($yesterdayMetric->mrr, $events); // active users // return int $metrics->au = AUStat::calculate($yesterdayMetric->au, $events); // annual recurring revenue // return int $metrics->arr = ArrStat::calculate($metrics->mrr); // average recurring revenue per active user // return int $metrics->arpu = ArpuStat::calculate($metrics->mrr, $metrics->au); // daily and monthly cancellations // return array list($daily, $monthly) = CancellationStat::calculate($events, $user); $metrics->cancellations = $daily; $metrics->monthlyCancellations = $monthly; // user churn // return float $metrics->uc = UserChurnStat::calculate($metrics->monthlyCancellations, $user, $timestamp); // save everything $metrics->save(); }
/** * Prepare data for full statistics (for single_stat) * * @return array */ public static function showFullStat($metrics) { // helpers $currentDay = time(); $lastMonthTime = $currentDay - 30 * 24 * 60 * 60; $twoMonthTime = $currentDay - 2 * 30 * 24 * 60 * 60; $threeMonthTime = $currentDay - 3 * 30 * 24 * 60 * 60; $sixMonthTime = $currentDay - 6 * 30 * 24 * 60 * 60; $nineMonthTime = $currentDay - 9 * 30 * 24 * 60 * 60; $lastYearTime = $currentDay - 365 * 24 * 60 * 60; // return array $data = array(); $data = self::showSimpleStat($metrics); $firstDay = Event::where('user', Auth::user()->id)->orderBy('date', 'asc')->first(); if ($firstDay) { $firstDay = strtotime($firstDay->date); } else { $firstDay = time(); } $data['firstDay'] = date('d-m-Y', $firstDay); $fullMetricHistory = Metric::where('user', Auth::user()->id)->orderBy('date', 'asc')->get(); foreach ($fullMetricHistory as $metric) { $data['fullHistory'][$metric->date] = $metric->cancellations; } if (!isset($data['fullHistory'])) { $data['fullHistory'] = array(); } // past values (null if not available) $lastMonthValue = static::getIndicatorStatOnDay($lastMonthTime); $twoMonthValue = static::getIndicatorStatOnDay($twoMonthTime); $threeMonthValue = static::getIndicatorStatOnDay($threeMonthTime); $sixMonthValue = static::getIndicatorStatOnDay($sixMonthTime); $nineMonthValue = static::getIndicatorStatOnDay($nineMonthTime); $oneYearValue = static::getIndicatorStatOnDay($lastYearTime); // 30 days ago $data['oneMonth'] = $lastMonthValue; // 6 months ago $data['sixMonth'] = $sixMonthValue; // 1 year ago $data['oneYear'] = $oneYearValue; // check if data is available, so we don't divide by null // we have 30 days change if ($twoMonthValue) { $changeInPercent = $data['currentValue'] / $twoMonthValue * 100 - 100; $data['twoMonthChange'] = round($changeInPercent) . '%'; } else { $data['twoMonthChange'] = null; } if ($threeMonthValue) { $changeInPercent = $data['currentValue'] / $threeMonthValue * 100 - 100; $data['threeMonthChange'] = round($changeInPercent) . '%'; } else { $data['threeMonthChange'] = null; } if ($sixMonthValue) { $changeInPercent = $data['currentValue'] / $sixMonthValue * 100 - 100; $data['sixMonthChange'] = round($changeInPercent) . '%'; } else { $data['sixMonthChange'] = null; } if ($nineMonthValue) { $changeInPercent = $data['currentValue'] / $nineMonthValue * 100 - 100; $data['nineMonthChange'] = round($changeInPercent) . '%'; } else { $data['nineMonthChange'] = null; } if ($oneYearValue) { $changeInPercent = $data['currentValue'] / $oneYearValue * 100 - 100; $data['oneYearChange'] = round($changeInPercent) . '%'; } else { $data['oneYearChange'] = null; } // time interval for shown statistics // right now, only last 30 days $startDate = date('d-m-Y', $lastMonthTime); $stopDate = date('d-m-Y', $currentDay); $data['dateInterval'] = array('startDate' => $startDate, 'stopDate' => $stopDate); // positiveIsGood, for front end colors $data['positiveIsGood'] = false; return $data; }
public function showSinglestat($statID) { // check if trial period is ended if (Auth::user()->isTrialEnded()) { return Redirect::route('auth.plan')->with('error', 'Trial period ended.'); } $currentMetrics = Calculator::currentMetrics(); $metricValues = Metric::where('user', Auth::user()->id)->orderBy('date', 'desc')->take(31)->get(); foreach ($currentMetrics as $metricID => $statClassName) { $metricsArray = array(); foreach ($metricValues as $metric) { $metricsArray[$metric->date] = $metric->{$metricID}; } ksort($metricsArray); $allMetrics[$metricID] = $metricsArray; } if (isset($currentMetrics[$statID])) { return View::make('auth.single_stat', array('data' => $currentMetrics[$statID]['metricClass']::show($allMetrics[$statID], true), 'metricDetails' => $currentMetrics[$statID])); } else { return Redirect::route('auth.dashboard')->with('error', 'Statistic does not exist.'); } }
/** * Execute the console command. * * @return mixed */ public function fire() { // get all the users $users = User::all(); $previousDayDate = Carbon::yesterday()->toDateString(); // currently calculated metrics $currentMetrics = Calculator::currentMetrics(); // for each user send email with their metrics $dailyEmailSent = 0; $weeklyEmailSent = 0; foreach ($users as $user) { // check if user finished the connect process if ($user->isConnected() && $user->ready == 'connected' && !$user->isTrialEnded()) { switch ($user->summaryEmailFrequency) { case 'none': // no summary email break; case 'daily': // default behavior, send yesterday's data // get the user's metrics $metric = Metric::where('user', $user->id)->where('date', $previousDayDate)->first(); if ($metric) { $previousMetrics = Metric::where('user', $user->id)->where('date', '<=', Carbon::yesterday()->subDays(30)->toDateString())->orderBy('date', 'desc')->first(); $changes = array(); foreach ($currentMetrics as $metricID => $metricDetails) { // get the correct color $changes[$metricID]['positiveIsGood'] = $metricDetails['metricClass']::POSITIVE_IS_GOOD; $date = $metric->date; if ($previousMetrics) { if ($previousMetrics->{$metricID} != 0) { $value = $metric->{$metricID} / $previousMetrics->{$metricID} * 100 - 100; $changes[$metricID][$date]['isBigger'] = $value > 0 ? true : false; $changes[$metricID][$date]['value'] = round($value) . ' %'; } else { $changes[$metricID][$date]['value'] = null; } } else { $changes[$metricID][$date]['value'] = null; } } // format metrics to presentable data $metric->formatMetrics(); // this line is for making the daily email the same format as the weekly // so we only need one email template $metrics = array($metric->date => $metric); $data = array('metrics' => $metrics, 'currentMetrics' => $currentMetrics, 'changes' => $changes, 'isDaily' => true, 'index' => 0); $email = Mailman::make('emails.summary')->with($data)->to($user->email)->subject('Daily summary')->send(); //File::put(public_path().'/summary_email.html',$email); $dailyEmailSent++; } break; case 'weekly': // send a weekly summary to the user with their numbers // check if today is monday (we send weekly emails on monday) /* improvment idea change this if to switch-case with days for user controlled daily send */ if (Carbon::now()->dayOfWeek == Carbon::WEDNESDAY) { // get the user's metrics $metrics = Metric::where('user', $user->id)->where('date', '<=', $previousDayDate)->orderBy('date', 'desc')->take(7)->get(); $previousMetrics = Metric::where('user', $user->id)->where('date', '<=', Carbon::yesterday()->subDays(30)->toDateString())->orderBy('date', 'desc')->take(7)->get(); $changes = array(); foreach ($currentMetrics as $metricID => $metricDetails) { // get the correct color $changes[$metricID]['positiveIsGood'] = $metricDetails['metricClass']::POSITIVE_IS_GOOD; foreach ($previousMetrics as $id => $prevMetric) { $date = $metrics[$id]->date; if ($prevMetric->{$metricID} != 0) { $value = $metrics[$id]->{$metricID} / $prevMetric->{$metricID} * 100 - 100; $changes[$metricID][$date]['isBigger'] = $value > 0 ? true : false; $changes[$metricID][$date]['value'] = round($value) . ' %'; } else { $changes[$metricID][$date]['value'] = null; } } } // format metrics to presentable data $weeklyMetrics = array(); foreach ($metrics as $metric) { $metric->formatMetrics(); $weeklyMetrics[$metric->date] = $metric; } $data = array('metrics' => $weeklyMetrics, 'currentMetrics' => $currentMetrics, 'changes' => $changes, 'isDaily' => false, 'index' => 0); // login the user (necessary to get the email address) // Auth::login($user); // send the email to the user $email = Mailman::make('emails.summary')->with($data)->to($user->email)->subject('Weekly summary')->send(); //File::put(public_path().'/summary_email.html',$email); $weeklyEmailSent++; } break; default: Log::error('notifications string has been changed, check the email sending code'); break; } // /switch } // /isConnected } // /foreach Log::info($dailyEmailSent . ' daily summary emails sent out of ' . count($users) . ' users'); Log::info($weeklyEmailSent . ' daily summary emails sent out of ' . count($users) . ' users'); Log::info('Total of ' . $dailyEmailSent + $weeklyEmailSent . ' emails sent'); }
/** * calculate and save metrics on connect * @param object - user */ public static function firstTime($user) { $metrics = Metric::where('date', Carbon::now()->format('Y-m-d'))->where('user', $user->id)->first(); $customers = self::getCustomers($user); $subscriptions = self::getSubscriptions($user); if ($metrics) { // we already have data for the metric, update it $metrics->mrr = self::getMRR($user, $subscriptions, $metrics->mrr); $metrics->au = self::getAU($user, $customers, $metrics->au); $metrics->arr = $metrics->mrr * 12; $metrics->arpu = $metrics->au != 0 ? round($metrics->mrr / $metrics->au) : null; } else { // we dont have any data yet $metrics = new Metric(); $metrics->user = $user->id; $metrics->date = Carbon::now()->format('Y-m-d'); $metrics->mrr = self::getMRR($user, $subscriptions); $metrics->au = self::getAU($user, $customers); $metrics->arr = $metrics->mrr * 12; $metrics->arpu = $metrics->au != 0 ? round($metrics->mrr / $metrics->au) : null; $metrics->uc = null; $metrics->cancellations = 0; $metrics->monthlyCancellations = null; } $metrics->save(); }