Since: 5.0 (23.06.2014)
Author: Vitaliy Demidov (vitaliy@scalr.com)
Inheritance: extends Scalr\Model\AbstractEntity, implements Scalr\DataType\AccessPermissionsInterface, implements Scalr\DataType\ScopeInterface
Example #1
0
 /**
  * Saves/modifies/deletes reports
  *
  * @param array $settings    Array of reports to create/modify
  * @param string $projectId  optional Projects id.
  * @throws Scalr_UI_Exception_NotFound
  * @throws \Scalr\Exception\AnalyticsException
  * @throws \Scalr\Exception\ModelException
  */
 protected function saveReports($settings, $projectId = null)
 {
     $uuids = [];
     foreach ($settings['items'] as $item) {
         $report = new ReportEntity();
         if ($item['uuid']) {
             $report->findPk($item['uuid']);
             if (!$report->hasAccessPermissions($this->getUser())) {
                 continue;
             }
         }
         $report->subjectType = $item['subjectType'];
         $subject = null;
         if ($report->subjectType == ReportEntity::SUBJECT_TYPE_CC && $item['subjectId']) {
             $subject = $this->getContainer()->analytics->ccs->get($item['subjectId']);
         } elseif ($report->subjectType == ReportEntity::SUBJECT_TYPE_PROJECT && $item['subjectId']) {
             $subject = $this->getContainer()->analytics->projects->get($item['subjectId']);
         } elseif ($item['subjectType'] == -1) {
             $report->subjectType = null;
             $report->subjectId = null;
         }
         if ($report->subjectType) {
             if ($item['subjectId'] && !$subject) {
                 throw new Scalr_UI_Exception_NotFound();
             }
             $report->subjectId = $item['subjectId'] ? $item['subjectId'] : null;
         }
         $report->period = $item['period'];
         $report->emails = $item['emails'];
         $report->status = $item['status'];
         $report->save();
         $uuids[] = $report->uuid;
     }
     $criteria = [['accountId' => null]];
     if ($projectId) {
         $criteria[] = ['subjectId' => $projectId];
     }
     foreach (ReportEntity::find($criteria) as $report) {
         /* @var $report ReportEntity */
         if (!in_array($report->uuid, $uuids) && $report->hasAccessPermissions($this->getUser())) {
             $report->delete();
         }
     }
 }
Example #2
0
 private function saveReports($settings)
 {
     $uuids = [];
     foreach ($settings['items'] as $item) {
         $report = new ReportEntity();
         if ($item['uuid']) {
             $report->findPk($item['uuid']);
         }
         $report->subjectType = $item['subjectType'];
         $subject = null;
         if ($report->subjectType == ReportEntity::SUBJECT_TYPE_CC && $item['subjectId']) {
             $subject = $this->getContainer()->analytics->ccs->get($item['subjectId']);
         } elseif ($report->subjectType == ReportEntity::SUBJECT_TYPE_PROJECT && $item['subjectId']) {
             $subject = $this->getContainer()->analytics->projects->get($item['subjectId']);
         } elseif ($item['subjectType'] == -1) {
             $report->subjectType = null;
             $report->subjectId = null;
         }
         if ($report->subjectType) {
             if ($item['subjectId'] && !$subject) {
                 throw new Scalr_UI_Exception_NotFound();
             }
             $report->subjectId = $item['subjectId'] ? $item['subjectId'] : null;
         }
         $report->period = $item['period'];
         $report->emails = $item['emails'];
         $report->status = $item['status'];
         $report->save();
         $uuids[] = $report->uuid;
     }
     foreach (ReportEntity::all() as $report) {
         if (!in_array($report->uuid, $uuids)) {
             $report->delete();
         }
     }
 }
Example #3
0
 /**
  * @param JsonData $notifications
  */
 public function xSaveAction(JsonData $notifications)
 {
     $data = [];
     foreach ($notifications as $id => $settings) {
         if ($id == 'reports') {
             $this->saveReports($settings);
             $data[$id] = ReportEntity::find([['accountId' => null]])->getArrayCopy();
         } elseif ($id == 'notifications.ccs') {
             $this->saveNotifications(NotificationEntity::SUBJECT_TYPE_CC, $settings);
             $data[$id] = NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC)->getArrayCopy();
         } elseif ($id == 'notifications.projects') {
             $this->saveNotifications(NotificationEntity::SUBJECT_TYPE_PROJECT, $settings);
             $data[$id] = NotificationEntity::find([['accountId' => null], ['subjectType' => NotificationEntity::SUBJECT_TYPE_PROJECT]])->getArrayCopy();
         }
     }
     $this->response->data($data);
     $this->response->success('Notifications successfully saved');
 }
Example #4
0
 /**
  * @param JsonData $notifications
  */
 public function xSaveAction(JsonData $notifications)
 {
     $data = [];
     $projects = [];
     foreach ($this->getContainer()->analytics->projects->getAccountProjects($this->user->getAccountId()) as $project) {
         /* @var $project ProjectEntity */
         if (!$project->archived && $project->shared === ProjectEntity::SHARED_WITHIN_ACCOUNT) {
             $projects[$project->projectId] = $project->name;
         }
     }
     foreach ($notifications as $id => $settings) {
         if ($id == 'reports') {
             $this->saveReports($settings);
             $data[$id] = ReportEntity::find([['subjectType' => ReportEntity::SUBJECT_TYPE_PROJECT], ['$or' => [['subjectId' => ['$in' => array_keys($projects)]], ['subjectId' => null]]]])->getArrayCopy();
         } elseif ($id == 'notifications.projects') {
             $this->saveNotifications(NotificationEntity::SUBJECT_TYPE_PROJECT, $settings);
             $data[$id] = NotificationEntity::find([['subjectType' => NotificationEntity::SUBJECT_TYPE_PROJECT], ['$or' => [['subjectId' => ['$in' => array_keys($projects)]], ['subjectId' => null]]]])->getArrayCopy();
         }
     }
     $this->response->data($data);
     $this->response->success('Notifications successfully saved');
 }
Example #5
0
 public function delete()
 {
     parent::delete();
     ReportEntity::deleteByAccountId($this->id);
     NotificationEntity::deleteByAccountId($this->id);
 }
Example #6
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Model\AbstractEntity::delete()
  */
 public function delete()
 {
     if ($this->checkRemoval()) {
         //Completely remove it
         parent::delete();
         ReportEntity::deleteBy([['subjectId' => $this->projectId], ['subjectType' => ReportEntity::SUBJECT_TYPE_PROJECT]]);
         NotificationEntity::deleteBy([['subjectId' => $this->projectId], ['subjectType' => NotificationEntity::SUBJECT_TYPE_PROJECT]]);
     } else {
         //Archive it
         $this->archived = true;
         $this->save();
     }
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Zmq\Cron\TaskInterface::enqueue()
  */
 public function enqueue()
 {
     if (!\Scalr::getContainer()->analytics->enabled) {
         $this->getLogger()->info("Terminating the process as Cost analytics is disabled in the config.\n");
         return new ArrayObject();
     }
     $this->getLogger()->info("%s (UTC) Start Analytics Notifications process", gmdate('Y-m-d'));
     $notifications = NotificationEntity::find();
     $this->getLogger()->info('Calculating data for projects and cost centers notifications');
     foreach ($notifications as $notification) {
         /* @var $notification NotificationEntity */
         if ($notification->status === NotificationEntity::STATUS_DISABLED) {
             continue;
         }
         if ($notification->subjectType === NotificationEntity::SUBJECT_TYPE_CC) {
             $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\CostCentre';
         } else {
             if ($notification->subjectType === NotificationEntity::SUBJECT_TYPE_PROJECT) {
                 $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\Project';
             }
         }
         if (!empty($notification->subjectId)) {
             $subject = call_user_func($subjectEntityName . 'Entity::findPk', $notification->subjectId);
             $this->saveNotificationData($subject, $notification);
         } else {
             $subjects = call_user_func($subjectEntityName . 'Entity::find');
             foreach ($subjects as $subject) {
                 if ($subject->archived) {
                     continue;
                 }
                 $this->saveNotificationData($subject, $notification);
             }
         }
     }
     $this->getLogger()->info('Calculating data for reports');
     $reports = ReportEntity::find();
     foreach ($reports as $report) {
         /* @var $report ReportEntity */
         if ($report->status === ReportEntity::STATUS_DISABLED) {
             continue;
         }
         switch ($report->period) {
             case ReportEntity::PERIOD_DAILY:
                 $period = 'custom';
                 $start = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y-m-d');
                 $end = $start;
                 $startForecast = (new \DateTime('first day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                 $endForecast = (new \DateTime('last day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                 if ($startForecast == (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d')) {
                     $startForecast = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $endForecast = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                 }
                 $periodForecast = 'month';
                 $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j');
                 $formatedForecastDate = (new \DateTime($start, new \DateTimeZone('UTC')))->format('F');
                 break;
             case ReportEntity::PERIOD_MONTHLY:
                 $period = 'month';
                 $start = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                 $end = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                 $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M Y');
                 break;
             case ReportEntity::PERIOD_QUARTELY:
                 $period = 'quarter';
                 $quarters = new Quarters(SettingEntity::getQuarters());
                 $currentQuarter = $quarters->getQuarterForDate(new \DateTime('yesterday', new \DateTimeZone('UTC')));
                 $currentYear = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y');
                 if ($currentQuarter === 1) {
                     $quarter = 4;
                     $year = $currentYear - 1;
                 } else {
                     $quarter = $currentQuarter - 1;
                     $year = $currentYear;
                 }
                 $date = $quarters->getPeriodForQuarter($quarter, $year);
                 $start = $date->start->format('Y-m-d');
                 $end = $date->end->format('Y-m-d');
                 $formatedTitle = 'Q' . $quarter . ' ' . $year;
                 $formatedForecastDate = 'End of ' . $currentYear;
                 $startForecast = $currentYear . '-01-01';
                 $endForecast = $currentYear . '-12-31';
                 $periodForecast = 'year';
                 break;
             case ReportEntity::PERIOD_WEEKLY:
                 $period = 'week';
                 $end = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->modify('last saturday')->format('Y-m-d');
                 $start = (new \DateTime($end, new \DateTimeZone('UTC')))->modify('last sunday')->format('Y-m-d');
                 $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j') . ' - ' . (new \DateTime($end, new \DateTimeZone('UTC')))->format('M j');
                 break;
         }
         if ($report->period !== ReportEntity::PERIOD_DAILY && $report->period !== ReportEntity::PERIOD_QUARTELY) {
             $quarters = new Quarters(SettingEntity::getQuarters());
             $currentQuarter = $quarters->getQuarterForDate(new \DateTime($start, new \DateTimeZone('UTC')));
             $currentYear = (new \DateTime($start, new \DateTimeZone('UTC')))->format('Y');
             $date = $quarters->getPeriodForQuarter($currentQuarter, $currentYear);
             $formatedForecastDate = 'End of Q' . $currentQuarter;
             $startForecast = $date->start->format('Y-m-d');
             $endForecast = $date->end->format('Y-m-d');
             $periodForecast = 'quarter';
         }
         if ($report->subjectType === ReportEntity::SUBJECT_TYPE_CC) {
             $getPeriodicSubjectData = 'getCostCenterPeriodData';
             $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\CostCentre';
             $subjectId = 'ccId';
         } else {
             if ($report->subjectType === ReportEntity::SUBJECT_TYPE_PROJECT) {
                 $getPeriodicSubjectData = 'getProjectPeriodData';
                 $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\Project';
                 $subjectId = 'projectId';
             } else {
                 $baseUrl = rtrim(\Scalr::getContainer()->config('scalr.endpoint.scheme') . "://" . \Scalr::getContainer()->config('scalr.endpoint.host'), '/');
                 $periodData = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($period, $start, $end);
                 $periodDataForecast = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($periodForecast, $startForecast, $endForecast);
                 $periodData['period'] = $period;
                 $periodData['forecastPeriod'] = $formatedForecastDate;
                 $periodData['totals']['forecastCost'] = $periodDataForecast['totals']['forecastCost'];
                 $periodData['name'] = 'Cloud Cost Report';
                 $periodData['jsonVersion'] = '1.0.0';
                 $periodData['detailsUrl'] = $baseUrl . '#/analytics/dashboard';
                 $periodData['totals']['clouds'] = $this->changeCloudNames($periodData['totals']['clouds']);
                 $periodData['date'] = $formatedTitle;
                 $periodData['totals']['budget']['budget'] = null;
                 if ($period !== 'custom') {
                     $periodData['totals']['prevPeriodDate'] = (new \DateTime($periodData['previousStartDate'], new \DateTimeZone('UTC')))->format('M d') . " - " . (new \DateTime($periodData['previousEndDate'], new \DateTimeZone('UTC')))->format('M d');
                 } else {
                     $periodData['totals']['prevPeriodDate'] = (new \DateTime($periodData['previousEndDate'], new \DateTimeZone('UTC')))->format('M d');
                 }
                 if ($period == 'quarter') {
                     $periodData['totals']['budget'] = ['quarter' => $quarter, 'year' => $year, 'quarterStartDate' => $start, 'quarterEndDate' => $end];
                 } else {
                     if ($period == 'month') {
                         $periodData['totals']['budget'] = ['quarter' => $currentQuarter];
                     }
                 }
                 unset($periodData['projects'], $periodData['budget']['projects']);
                 if (count($periodData['costcenters'] > 1)) {
                     uasort($periodData['costcenters'], array($this, 'sortItems'));
                     if (count($periodData['costcenters'] > 6)) {
                         array_splice($periodData['costcenters'], 6, count($periodData['costcenters']));
                     }
                 }
                 if (count($periodData['totals']['clouds'] > 1)) {
                     usort($periodData['totals']['clouds'], array($this, 'sortItems'));
                 }
                 $entity = ReportPayloadEntity::init([$report->subjectType, $report->subjectId, $period], $periodData, $start);
                 if (!ReportPayloadEntity::findPk($entity->uuid)) {
                     $payload = json_decode($entity->payload, true);
                     \Scalr::getContainer()->mailer->setSubject('Summary report.')->setContentType('text/html')->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/report_summary.html.php', $payload, $report->emails);
                     $this->getLogger()->info('Summary report email has been sent');
                     $payload['date'] = $entity->created->format('Y-m-d');
                     $entity->payload = json_encode($payload);
                     $entity->save();
                 }
             }
         }
         unset($currentQuarter, $currentYear);
         if (!empty($report->subjectType) && !empty($report->subjectId)) {
             $subject = call_user_func($subjectEntityName . 'Entity::findPk', $report->subjectId);
             if ($subject->archived) {
                 continue;
             }
             $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $report->subjectId, $report->subjectType, $report->emails, $formatedTitle, $formatedForecastDate);
         } else {
             if (!empty($report->subjectType)) {
                 $subjects = call_user_func($subjectEntityName . 'Entity::find');
                 foreach ($subjects as $subject) {
                     if ($subject->archived) {
                         continue;
                     }
                     $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $subject->{$subjectId}, $report->subjectType, $report->emails, $formatedTitle, $formatedForecastDate);
                 }
             }
         }
     }
     $this->getLogger()->info('Done');
     return new ArrayObject();
 }
Example #8
0
 /**
  * {@inheritdoc}
  * @see Scalr_Model::delete()
  */
 public function delete($id = null)
 {
     $servers = \DBServer::listByFilter(['clientId' => $this->id]);
     foreach ($servers as $server) {
         /* @var $server \DBServer */
         $server->Remove();
     }
     try {
         $this->db->StartTrans();
         //TODO: Use models
         $this->db->Execute("\n                DELETE account_team_users FROM account_team_users, account_teams\n                WHERE account_teams.account_id = ?\n                AND account_team_users.team_id = account_teams.id\n            ", array($this->id));
         $this->db->Execute("DELETE FROM account_users WHERE account_id=?", array($this->id));
         $this->db->Execute("DELETE FROM account_teams WHERE account_id=?", array($this->id));
         $this->db->Execute("DELETE FROM account_limits WHERE account_id=?", array($this->id));
         /* @var $environment Environment */
         foreach (Environment::findByAccountId($this->id) as $environment) {
             $environment->delete(true);
         }
         CloudCredentials::deleteByAccountId($this->id);
         $this->db->Execute("\n                DELETE account_team_user_acls FROM account_team_user_acls, acl_account_roles\n                WHERE acl_account_roles.account_id = ?\n                AND account_team_user_acls.account_role_id = acl_account_roles.account_role_id\n            ", array($this->id));
         $this->db->Execute("DELETE FROM acl_account_roles WHERE account_id=?", array($this->id));
         $this->db->Execute("DELETE FROM ec2_ebs WHERE client_id=?", array($this->id));
         $this->db->Execute("DELETE FROM apache_vhosts WHERE client_id=?", array($this->id));
         $this->db->Execute("DELETE FROM scheduler WHERE account_id=?", array($this->id));
         foreach ($this->db->Execute("SELECT id FROM farms WHERE clientid=?", [$this->id]) as $farm) {
             $this->db->Execute("DELETE FROM farms WHERE id=?", array($farm["id"]));
             $this->db->Execute("DELETE FROM farm_roles WHERE farmid=?", array($farm["id"]));
             $this->db->Execute("DELETE FROM elastic_ips WHERE farmid=?", array($farm["id"]));
         }
         $roles = $this->db->GetAll("SELECT id FROM roles WHERE client_id = '{$this->id}'");
         foreach ($roles as $role) {
             $this->db->Execute("DELETE FROM roles WHERE id = ?", array($role['id']));
             $this->db->Execute("DELETE FROM role_behaviors WHERE role_id = ?", array($role['id']));
             $this->db->Execute("DELETE FROM role_images WHERE role_id = ?", array($role['id']));
             $this->db->Execute("DELETE FROM role_properties WHERE role_id = ?", array($role['id']));
             $this->db->Execute("DELETE FROM role_security_rules WHERE role_id = ?", array($role['id']));
         }
         //Removing cost centres and projects which are set up from this account
         $this->db->Execute("\n                DELETE project_properties FROM project_properties, projects\n                WHERE projects.project_id = project_properties.project_id\n                AND projects.account_id = ?\n            ", [$this->id]);
         $this->db->Execute("DELETE FROM projects WHERE account_id = ?", [$this->id]);
         $this->db->Execute("\n                DELETE cc_properties FROM cc_properties, ccs\n                WHERE ccs.cc_id = cc_properties.cc_id\n                AND ccs.account_id = ?\n            ", [$this->id]);
         $this->db->Execute("DELETE FROM ccs WHERE account_id = ?", [$this->id]);
         parent::delete();
         ReportEntity::deleteByAccountId($this->id);
         NotificationEntity::deleteByAccountId($this->id);
         $this->db->CompleteTrans();
     } catch (\Exception $e) {
         $this->db->RollbackTrans();
         throw $e;
     }
 }
Example #9
0
 /**
  * @param string $projectId
  * @param JsonData $notifications
  * @throws Scalr_Exception_InsufficientPermissions
  */
 public function xSaveNotificationsAction($projectId, JsonData $notifications)
 {
     $this->request->restrictAccess(Acl::RESOURCE_ANALYTICS_PROJECTS_ACCOUNT);
     $project = ProjectEntity::findPk($projectId);
     /* @var $project ProjectEntity */
     if (!$project->hasAccessPermissions($this->getUser())) {
         throw new Scalr_Exception_InsufficientPermissions();
     }
     $data = [];
     foreach ($notifications as $id => $settings) {
         if ($id == 'reports') {
             $this->saveReports($settings, $projectId);
             $data[$id] = ReportEntity::find([['subjectType' => ReportEntity::SUBJECT_TYPE_PROJECT], ['subjectId' => $projectId]])->getArrayCopy();
         } elseif ($id == 'notifications.projects') {
             $this->saveNotifications(NotificationEntity::SUBJECT_TYPE_PROJECT, $settings, $projectId);
             $data[$id] = NotificationEntity::find([['subjectType' => NotificationEntity::SUBJECT_TYPE_PROJECT], ['subjectId' => $projectId]])->getArrayCopy();
         }
     }
     $this->response->data($data);
     $this->response->success('Notifications successfully saved');
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Pcntl\ProcessInterface::OnStartForking()
  */
 public function OnStartForking()
 {
     if (!\Scalr::getContainer()->analytics->enabled) {
         die("Terminating the process as Cost analytics is disabled in the config.\n");
     }
     $this->console->out("%s (UTC) Start Analytics Notifications process", gmdate('Y-m-d'));
     if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_CCS_ENABLED) || SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_PROJECTS_ENABLED)) {
         $this->console->out('Calculating data for projects notifications');
         $quarters = new Quarters(SettingEntity::getQuarters());
         $date = $quarters->getPeriodForDate('yesterday');
         $formatedTitle = 'Q' . $quarters->getQuarterForDate('now') . ' budget (' . (new \DateTime('now', new \DateTimeZone('UTC')))->format('M j, Y') . ')';
         $projects = ProjectEntity::find();
         foreach ($projects as $project) {
             $periodProjectData = \Scalr::getContainer()->analytics->usage->getProjectPeriodData($project->projectId, 'quarter', $date->start->format('Y-m-d'), $date->end->format('Y-m-d'));
             $projectAnalytics[$project->projectId] = ['budget' => $periodProjectData['totals']['budget'], 'name' => $project->name, 'trends' => $periodProjectData['totals']['trends'], 'forecastCost' => $periodProjectData['totals']['forecastCost'], 'interval' => $periodProjectData['interval'], 'jsonVersion' => '1.0.0', 'farms' => []];
             if (!empty($periodProjectData['totals']['farms'])) {
                 foreach ($periodProjectData['totals']['farms'] as $farm) {
                     $projectAnalytics[$project->projectId]['farms'][] = ['id' => $farm['id'], 'name' => $farm['name'], 'median' => $farm['median'] / 7, 'cost' => $farm['cost'], 'costPct' => $farm['costPct']];
                 }
                 if (count($projectAnalytics[$project->projectId]['farms'] > 1)) {
                     usort($projectAnalytics[$project->projectId]['farms'], array($this, 'sortItems'));
                     if (count($projectAnalytics[$project->projectId]['farms'] > 6)) {
                         array_splice($projectAnalytics[$project->projectId]['farms'], 6, count($projectAnalytics[$project->projectId]['farms']));
                     }
                 }
             }
             $projectAnalytics[$project->projectId]['date'] = $formatedTitle;
             if ($project->archived) {
                 continue;
             }
             if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_PROJECTS_ENABLED)) {
                 $projectNotifications = NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_PROJECT);
                 foreach ($projectNotifications as $notification) {
                     $this->saveNotificationData('project', $notification, $project->projectId, $projectAnalytics);
                 }
             }
         }
     }
     if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_CCS_ENABLED)) {
         $this->console->out('Calculating data for cost center notifications');
         $ccs = CostCentreEntity::find();
         foreach ($ccs as $cc) {
             if ($cc->archived) {
                 continue;
             }
             $periodCostCenterData = \Scalr::getContainer()->analytics->usage->getCostCenterPeriodData($cc->ccId, 'quarter', $date->start->format('Y-m-d'), $date->end->format('Y-m-d'));
             $ccAnalytics[$cc->ccId] = ['budget' => $periodCostCenterData['totals']['budget'], 'name' => $cc->name, 'trends' => $periodCostCenterData['totals']['trends'], 'forecastCost' => $periodCostCenterData['totals']['forecastCost'], 'interval' => $periodCostCenterData['interval'], 'jsonVersion' => '1.0.0', 'projects' => []];
             if (!empty($periodCostCenterData['totals']['projects'])) {
                 foreach ($periodCostCenterData['totals']['projects'] as $key => $project) {
                     if (!empty($project['id'])) {
                         $projectBudget = $projectAnalytics[$project['id']]['budget'];
                         $projectBudget['name'] = $project['name'];
                         $projectBudget['id'] = $project['id'];
                         $projectBudget['median'] = $project['median'] / 7;
                         $ccAnalytics[$cc->ccId]['projects'][] = $projectBudget;
                     } else {
                         $otherProjectsKey = $key;
                     }
                 }
                 if (isset($otherProjectsKey)) {
                     $ccAnalytics[$cc->ccId]['projects'][] = ['id' => '', 'budgetSpent' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['cost'], 'median' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['median'] / 7, 'name' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['name'], 'estimateOverspend' => null];
                     unset($otherProjectsKey);
                 }
                 if (count($ccAnalytics[$cc->ccId]['projects'] > 1)) {
                     usort($ccAnalytics[$cc->ccId]['projects'], array($this, 'sortItems'));
                     if (count($ccAnalytics[$cc->ccId]['projects'] > 6)) {
                         array_splice($ccAnalytics[$cc->ccId]['projects'], 6, count($ccAnalytics[$cc->ccId]['projects']));
                     }
                 }
             }
             $ccAnalytics[$cc->ccId]['date'] = $formatedTitle;
             $ccsNotifications = NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC);
             foreach ($ccsNotifications as $notification) {
                 $this->saveNotificationData('cc', $notification, $cc->ccId, $ccAnalytics);
             }
         }
     }
     if (SettingEntity::getValue(SettingEntity::ID_REPORTS_ENABLED)) {
         $this->console->out('Calculating data for reports');
         $reports = ReportEntity::find();
         foreach ($reports as $report) {
             switch ($report->period) {
                 case ReportEntity::PERIOD_DAILY:
                     $period = 'custom';
                     $start = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $end = $start;
                     $startForecast = (new \DateTime('first day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $endForecast = (new \DateTime('last day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     if ($startForecast == (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d')) {
                         $startForecast = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                         $endForecast = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     }
                     $periodForecast = 'month';
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j');
                     break;
                 case ReportEntity::PERIOD_MONTHLY:
                     $period = 'month';
                     $start = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $end = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $quarters = new Quarters(SettingEntity::getQuarters());
                     $currentQuarter = $quarters->getQuarterForDate(new \DateTime($start, new \DateTimeZone('UTC')));
                     $currentYear = (new \DateTime($start, new \DateTimeZone('UTC')))->format('Y');
                     $date = $quarters->getPeriodForQuarter($currentQuarter, $currentYear);
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M Y');
                     $startForecast = $date->start->format('Y-m-d');
                     $endForecast = $date->end->format('Y-m-d');
                     $periodForecast = 'quarter';
                     break;
                 case ReportEntity::PERIOD_QUARTELY:
                     $period = 'quarter';
                     $quarters = new Quarters(SettingEntity::getQuarters());
                     $currentQuarter = $quarters->getQuarterForDate(new \DateTime('yesterday', new \DateTimeZone('UTC')));
                     $currentYear = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y');
                     if ($currentQuarter === 1) {
                         $quarter = 4;
                         $year = $currentYear - 1;
                     } else {
                         $quarter = $currentQuarter - 1;
                         $year = $currentYear;
                     }
                     $date = $quarters->getPeriodForQuarter($quarter, $year);
                     $start = $date->start->format('Y-m-d');
                     $end = $date->end->format('Y-m-d');
                     $formatedTitle = 'Q' . $quarter . ' ' . $year;
                     $startForecast = $currentYear . '-01-01';
                     $endForecast = $currentYear . '-12-31';
                     $periodForecast = 'year';
                     break;
                 case ReportEntity::PERIOD_WEEKLY:
                     $period = 'week';
                     $end = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->modify('last saturday')->format('Y-m-d');
                     $start = (new \DateTime($end, new \DateTimeZone('UTC')))->modify('last sunday')->format('Y-m-d');
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j') . ' - ' . (new \DateTime($end, new \DateTimeZone('UTC')))->format('M j');
                     $startForecast = (new \DateTime('first day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $endForecast = (new \DateTime('last day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     if ($startForecast == (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d')) {
                         $startForecast = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                         $endForecast = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     }
                     $periodForecast = 'month';
                     break;
             }
             if ($report->subjectType === ReportEntity::SUBJECT_TYPE_CC) {
                 $getPeriodicSubjectData = 'getCostCenterPeriodData';
                 $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\CostCentre';
                 $subjectId = 'ccId';
             } else {
                 if ($report->subjectType === ReportEntity::SUBJECT_TYPE_PROJECT) {
                     $getPeriodicSubjectData = 'getProjectPeriodData';
                     $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\Project';
                     $subjectId = 'projectId';
                 } else {
                     $periodData = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($period, $start, $end);
                     $periodDataForecast = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($periodForecast, $startForecast, $endForecast);
                     $periodData['period'] = $period;
                     $periodData['forecastPeriod'] = $periodForecast;
                     $periodData['totals']['forecastCost'] = $periodDataForecast['totals']['forecastCost'];
                     $periodData['totals']['trends'] = $periodDataForecast['totals']['trends'];
                     $periodData['name'] = 'Cloud Cost Report';
                     $periodData['jsonVersion'] = '1.0.0';
                     $periodData['totals']['clouds'] = $this->changeCloudNames($periodData['totals']['clouds']);
                     $periodData['date'] = $formatedTitle;
                     $periodData['totals']['budget']['budget'] = null;
                     if ($period == 'quarter') {
                         $periodData['totals']['budget'] = ['quarter' => $quarter, 'year' => $year, 'quarterStartDate' => $start, 'quarterEndDate' => $end];
                     } else {
                         if ($period == 'month') {
                             $periodData['totals']['budget'] = ['quarter' => $currentQuarter];
                         }
                     }
                     unset($periodData['projects'], $periodData['budget']['projects']);
                     if (count($periodData['costcenters'] > 1)) {
                         uasort($periodData['costcenters'], array($this, 'sortItems'));
                         if (count($periodData['costcenters'] > 6)) {
                             array_splice($periodData['costcenters'], 6, count($periodData['costcenters']));
                         }
                     }
                     if (count($periodData['totals']['clouds'] > 1)) {
                         usort($periodData['totals']['clouds'], array($this, 'sortItems'));
                     }
                     $entity = ReportPayloadEntity::init([$report->subjectType, $report->subjectId, $period], $periodData, $start);
                     if (!ReportPayloadEntity::findPk($entity->uuid)) {
                         $payload = json_decode($entity->payload, true);
                         \Scalr::getContainer()->mailer->setSubject('Summary report.')->setContentType('text/html')->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/report_summary.html.php', $payload, $report->emails);
                         $this->console->out('Summary report email has been sent');
                         $payload['date'] = $entity->created->format('Y-m-d');
                         $entity->payload = json_encode($payload);
                         $entity->save();
                     }
                 }
             }
             unset($currentQuarter, $currentYear);
             if (!empty($report->subjectType) && !empty($report->subjectId)) {
                 $subject = call_user_func($subjectEntityName . 'Entity::findPk', $report->subjectId);
                 if ($subject->archived) {
                     continue;
                 }
                 $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $report->subjectId, $report->subjectType, $report->emails, $formatedTitle);
             } else {
                 if (!empty($report->subjectType)) {
                     $subjects = call_user_func($subjectEntityName . 'Entity::find');
                     foreach ($subjects as $subject) {
                         if ($subject->archived) {
                             continue;
                         }
                         $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $subject->{$subjectId}, $report->subjectType, $report->emails, $formatedTitle);
                     }
                 }
             }
         }
     }
     $this->console->out('Done');
     exit;
 }