Esempio n. 1
0
 public function getContent($params = array())
 {
     $this->request->restrictAccess(Acl::RESOURCE_OWN_FARMS, Acl::PERM_FARMS_CREATE);
     $projects = [];
     if ($this->getContainer()->analytics->enabled && $this->getEnvironment()->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID)) {
         $costCenter = $this->getContainer()->analytics->ccs->get($this->getEnvironment()->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID));
         $currentYear = (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y');
         $quarters = new Quarters(SettingEntity::getQuarters());
         $currentQuarter = $quarters->getQuarterForDate(new \DateTime('now', new \DateTimeZone('UTC')));
         if ($costCenter instanceof CostCentreEntity) {
             $projectsIterator = new SharedProjectsFilterIterator($costCenter->getProjects(), $costCenter->ccId, $this->user, $this->getEnvironment());
             foreach ($projectsIterator as $item) {
                 $quarterBudget = QuarterlyBudgetEntity::findOne([['year' => $currentYear], ['subjectType' => QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT], ['subjectId' => $item->projectId], ['quarter' => $currentQuarter]]);
                 $projects[] = array('projectId' => $item->projectId, 'name' => $item->name, 'budgetRemain' => !is_null($quarterBudget) && $quarterBudget->budget > 0 ? max(0, round($quarterBudget->budget - $quarterBudget->cumulativespend)) : null);
             }
             //$costCentreName = $costCenter->name;
             $isLocked = $costCenter->getProperty(CostCentrePropertyEntity::NAME_LOCKED);
             $accountCcs = AccountCostCenterEntity::findOne([['accountId' => $this->environment->clientId], ['ccId' => $costCenter->ccId]]);
             if ($isLocked || !$accountCcs instanceof AccountCostCenterEntity) {
                 $costCentreLocked = 1;
             } else {
                 $costCentreLocked = 0;
             }
         } else {
             $costCentreName = '';
             $costCentreLocked = 0;
         }
     }
     return ['costCenterLocked' => $costCentreLocked, 'projects' => $projects];
 }
Esempio n. 2
0
 /**
  * @test
  * @dataProvider providerConstructor
  */
 public function testConstructor($days, $fixtures)
 {
     $quarters = new Quarters($days);
     foreach ($fixtures as $i => $v) {
         $this->assertEquals($v['quarter'], $quarters->getQuarterForDate($v['date']), sprintf('The number of the quarter for the date "%s" is expected to be %d.', $v['date'], $v['quarter']));
         $period = $quarters->getPeriodForQuarter($v['quarter'], $v['year']);
         $this->assertInternalType('object', $period);
         $this->assertEquals($v['start'], $period->start->format('Y-m-d'), sprintf('Start date is expected to be "%s".', $v['start']));
         $this->assertEquals($v['end'], $period->end->format('Y-m-d'), sprintf('End date is expected to be "%s".', $v['end']));
         $this->assertEquals($v['year'], $period->year);
         $this->assertEquals($v['quarter'], $period->quarter);
         $periodForDate = $quarters->getPeriodForDate(new DateTime($v['date'], new DateTimeZone('UTC')));
         $this->assertEquals($v['start'], $periodForDate->start->format('Y-m-d'), sprintf('getPeriodForDate for fixture#%d failed. Start date is expected to be "%s".', $i, $v['start']));
         $this->assertEquals($v['end'], $periodForDate->end->format('Y-m-d'), sprintf('getPeriodForDate for fixture#%d failed. End date is expected to be "%s".', $i, $v['end']));
         $this->assertEquals($v['year'], $periodForDate->year, sprintf('getPeriodForDate for fixture#%d failed. Year is expected to be "%s".', $i, $v['year']));
         $this->assertEquals($v['quarter'], $periodForDate->quarter, sprintf('getPeriodForDate for fixture#%d failed. Quarter is expected to be "%s".', $i, $v['quarter']));
     }
 }
Esempio n. 3
0
 /**
  * Gets budgeted cost for all quarters of specified year
  *
  * @param    int      $year       The year
  * @param    string   $ccId       optional The identifier of the cost centre or parent cost centre
  * @param    string   $projectId  optional The identifier of the project
  * @throws   InvalidArgumentException
  */
 protected function getBudgetInfo($year, $ccId = null, $projectId = null)
 {
     if (!empty($projectId)) {
         $subjectId = $projectId;
         $subjectType = QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT;
         $subjectEntity = ProjectEntity::findPk($projectId);
     } else {
         if (!empty($ccId)) {
             $subjectId = $ccId;
             $subjectType = QuarterlyBudgetEntity::SUBJECT_TYPE_CC;
             $subjectEntity = CostCentreEntity::findPk($ccId);
         }
     }
     if ($subjectEntity->accountId !== $this->user->getAccountId()) {
         //throw new Scalr_Exception_InsufficientPermissions();
     }
     if (empty($subjectId) || !preg_match('/^[[:xdigit:]-]{36}$/', $subjectId)) {
         throw new InvalidArgumentException(sprintf("Invalid identifier of the project or cost center."));
     }
     if (!preg_match('/^\\d{4}$/', $year)) {
         throw new InvalidArgumentException(sprintf("Invalid year."));
     }
     if ($subjectType == QuarterlyBudgetEntity::SUBJECT_TYPE_CC) {
         $collection = QuarterlyBudgetEntity::getCcBudget($year, $subjectId);
         $prevCollection = QuarterlyBudgetEntity::getCcBudget($year - 1, $subjectId);
     } else {
         $collection = QuarterlyBudgetEntity::getProjectBudget($year, $subjectId);
         $prevCollection = QuarterlyBudgetEntity::getProjectBudget($year - 1, $subjectId);
     }
     $quarters = new Quarters(SettingEntity::getQuarters(true));
     $today = new DateTime('now', new DateTimeZone('UTC'));
     //Start dates for an each quarter
     $startDates = $quarters->getDays();
     $budgets = [];
     for ($quarter = 1; $quarter <= 4; ++$quarter) {
         $period = $quarters->getPeriodForQuarter($quarter, $year);
         $prevPeriod = $quarters->getPeriodForQuarter($quarter, $year - 1);
         //Finds budget for specified quarter in the collection
         $entity = current($collection->filterByQuarter($quarter));
         //Previous Year entity
         $prevEntity = current($prevCollection->filterByQuarter($quarter));
         if ($entity instanceof QuarterlyBudgetEntity) {
             $budget = ['budget' => round($entity->budget), 'budgetFinalSpent' => round($entity->cumulativespend), 'spentondate' => $entity->spentondate instanceof DateTime ? $entity->spentondate->format('Y-m-d') : null, 'budgetSpent' => round($entity->cumulativespend)];
             if ($budget['budget']) {
                 $budget['budgetOverspend'] = max(round($entity->cumulativespend - $entity->budget), 0);
                 $budget['budgetOverspendPct'] = round($budget['budgetOverspend'] / $budget['budget'] * 100);
             }
         } else {
             //Budget has not been set yet.
             $budget = ['budget' => 0, 'budgetFinalSpent' => 0, 'spentondate' => null, 'budgetSpent' => 0, 'budgetOverspend' => 0, 'budgetOverspendPct' => 0];
         }
         $budget['year'] = $year;
         $budget['quarter'] = $quarter;
         $budget['startDate'] = $startDates[$quarter - 1];
         //Whether this quarter has been closed or not
         $budget['closed'] = $period->end->format('Y-m-d') < gmdate('Y-m-d');
         //The number of the days in the current quarter
         $daysInQuarter = $period->start->diff($period->end, true)->days + 1;
         //In case quarter is closed projection should be calculated
         if (!$budget['closed']) {
             $daysPassed = $period->start->diff($today, true)->days + 1;
             $budget['dailyAverage'] = $daysPassed == 0 ? 0 : round($budget['budgetSpent'] / $daysPassed, 2);
             $budget['projection'] = round($daysInQuarter * $budget['dailyAverage']);
         } else {
             $budget['dailyAverage'] = $daysInQuarter == 0 ? 0 : round($budget['budgetFinalSpent'] / $daysInQuarter, 2);
         }
         $budget['costVariance'] = round((isset($budget['projection']) ? $budget['projection'] : $budget['budgetSpent']) - $budget['budget'], 2);
         $budget['costVariancePct'] = $budget['budget'] == 0 ? null : round(abs($budget['costVariance']) / $budget['budget'] * 100);
         $budget['monthlyAverage'] = round($budget['dailyAverage'] * 30);
         if ($prevEntity instanceof QuarterlyBudgetEntity) {
             $budget['prev'] = ['budget' => $prevEntity->budget, 'budgetFinalSpent' => $prevEntity->cumulativespend, 'spentondate' => $prevEntity->spentondate instanceof DateTime ? $prevEntity->spentondate->format('Y-m-d') : null, 'closed' => $prevPeriod->end->format('Y-m-d') < gmdate('Y-m-d'), 'costVariance' => $prevEntity->cumulativespend - $prevEntity->budget, 'costVariancePct' => $prevEntity->budget == 0 ? null : round(abs($prevEntity->cumulativespend - $prevEntity->budget) / $prevEntity->budget * 100)];
         } else {
             $budget['prev'] = ['budget' => null, 'budgetFinalSpent' => 0, 'spentondate' => null, 'closed' => $prevPeriod->end->format('Y-m-d') < gmdate('Y-m-d'), 'budgetSpent' => 0, 'costVariance' => 0, 'costVariancePct' => 0];
         }
         $budgets[] = $budget;
     }
     $result = ['budgets' => $budgets, 'ccId' => $ccId, 'projectId' => $projectId, 'quarter' => $quarters->getQuarterForDate(), 'year' => $year];
     if (!empty($projectId)) {
         $result['shared'] = $subjectEntity->shared;
     }
     return $result;
 }
 /**
  * Saves project or cost center notification
  *
  * @param ProjectEntity|CostCentreEntity $subject       Project or cost center entity
  * @param NotificationEntity             $notification  Current notification object
  * @throws InvalidArgumentException
  */
 private function saveNotificationData($subject, NotificationEntity $notification)
 {
     $baseUrl = rtrim(\Scalr::getContainer()->config('scalr.endpoint.scheme') . "://" . \Scalr::getContainer()->config('scalr.endpoint.host'), '/');
     $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') . ')';
     if ($subject instanceof ProjectEntity) {
         $getPeriodicSubjectData = 'getProjectPeriodData';
         $subjects = 'projects';
         $childItems = 'farms';
         $subjectIdName = 'projectId';
         $subjectName = 'project';
     } else {
         if ($subject instanceof CostCentreEntity) {
             $getPeriodicSubjectData = 'getCostCenterPeriodData';
             $subjects = 'costcenters';
             $childItems = 'projects';
             $subjectIdName = 'ccId';
             $subjectName = 'cc';
         } else {
             throw new InvalidArgumentException("Invalid subject parameter. It must be either ProjectEntity or CostCentreEntity type.");
         }
     }
     $periodSubjectData = \Scalr::getContainer()->analytics->usage->{$getPeriodicSubjectData}($subject->{$subjectIdName}, 'quarter', $date->start->format('Y-m-d'), $date->end->format('Y-m-d'));
     $subjectAnalytics = ['budget' => $periodSubjectData['totals']['budget'], 'name' => $subject->name, 'trends' => $periodSubjectData['totals']['trends'], 'forecastCost' => $periodSubjectData['totals']['forecastCost'], 'interval' => $periodSubjectData['interval'], 'date' => $formatedTitle, 'detailsUrl' => $baseUrl . '#/analytics/' . $subjects . '?' . $subjectIdName . '=' . $subject->{$subjectIdName}, 'jsonVersion' => '1.0.0', $childItems => []];
     if (!empty($periodSubjectData['totals'][$childItems])) {
         $subjectAnalytics[$childItems] = $this->getSubjectChildItems($subject, $periodSubjectData['totals'][$childItems], $date);
     }
     if ($notification->notificationType === NotificationEntity::NOTIFICATION_TYPE_USAGE) {
         $reportType = $subjectName . 'Usage';
         $budgetThreshold = 'budgetSpentPct';
         $emailSubject = $subjectAnalytics['name'] . ' usage notification.';
     } else {
         if ($notification->notificationType === NotificationEntity::NOTIFICATION_TYPE_PROJECTED_OVERSPEND) {
             $reportType = $subjectName . 'Overspend';
             $budgetThreshold = 'estimateOverspendPct';
             $emailSubject = $subjectAnalytics['name'] . ' overspend notification.';
         }
     }
     if ($subjectAnalytics['budget'][$budgetThreshold] >= $notification->threshold) {
         $subjectAnalytics['reportType'] = $reportType;
         $entity = ReportPayloadEntity::init([$notification->notificationType, $notification->subjectType, $subject->{$subjectIdName}, $notification->threshold], $subjectAnalytics);
         if (!ReportPayloadEntity::findPk($entity->uuid)) {
             $payload = json_decode($entity->payload, true);
             if (!empty($subjectAnalytics['budget']['estimateDate'])) {
                 $subjectAnalytics['budget']['estimateDate'] = (new DateTime($subjectAnalytics['budget']['estimateDate'], new DateTimeZone('UTC')))->format('M j, Y');
                 $subjectAnalytics['reportUrl'] = $payload['reportUrl'];
             }
             \Scalr::getContainer()->mailer->setSubject($emailSubject)->setContentType('text/html')->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/budget_notification_' . $subjectName . '.html.php', $subjectAnalytics, $notification->emails);
             $this->getLogger()->info('Notification email has been sent');
             $payload['date'] = $entity->created->format('Y-m-d');
             $entity->payload = json_encode($payload);
             $entity->save();
         }
     }
 }
Esempio n. 5
0
 private function getFarmCostData($farmId)
 {
     $result = [];
     $costCenter = $this->getContainer()->analytics->ccs->get($this->getEnvironment()->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID));
     $currentYear = (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y');
     $quarters = new Quarters(SettingEntity::getQuarters());
     $currentQuarter = $quarters->getQuarterForDate(new \DateTime('now', new \DateTimeZone('UTC')));
     $projects = [];
     if ($farmId) {
         $farm = DBFarm::LoadByID($farmId);
         $currentProjectId = $farm->GetSetting(Entity\FarmSetting::PROJECT_ID);
         $currentProject = ProjectEntity::findPk($currentProjectId);
         /* @var $currentProject ProjectEntity */
         if (!empty($currentProject)) {
             $quarterBudget = QuarterlyBudgetEntity::findOne([['year' => $currentYear], ['subjectType' => QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT], ['subjectId' => $currentProject->projectId], ['quarter' => $currentQuarter]]);
             $projects[] = ['projectId' => $currentProject->projectId, 'name' => "{$currentProject->name} / {$currentProject->getCostCenter()->name}", 'budgetRemain' => !is_null($quarterBudget) && $quarterBudget->budget > 0 ? max(0, round($quarterBudget->budget - $quarterBudget->cumulativespend)) : null];
         }
         $result['projectId'] = $farm->GetSetting(Entity\FarmSetting::PROJECT_ID);
         $result['farmCostMetering'] = $result['projectId'] ? $this->getContainer()->analytics->usage->getFarmCostMetering($this->user->getAccountId(), $farmId) : null;
     }
     if ($costCenter instanceof CostCentreEntity) {
         $projectsIterator = new SharedProjectsFilterIterator($costCenter->getProjects(), $costCenter->ccId, $this->user, $this->getEnvironment());
         foreach ($projectsIterator as $item) {
             /* @var $item Scalr\Stats\CostAnalytics\Entity\ProjectEntity */
             if (!empty($currentProjectId) && $item->projectId == $currentProjectId) {
                 continue;
             }
             $quarterBudget = QuarterlyBudgetEntity::findOne([['year' => $currentYear], ['subjectType' => QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT], ['subjectId' => $item->projectId], ['quarter' => $currentQuarter]]);
             $projects[] = array('projectId' => $item->projectId, 'name' => "{$item->name} / {$costCenter->name}", 'budgetRemain' => !is_null($quarterBudget) && $quarterBudget->budget > 0 ? max(0, round($quarterBudget->budget - $quarterBudget->cumulativespend)) : null);
         }
         $costCentreName = $costCenter->name;
         $isLocked = $costCenter->getProperty(CostCentrePropertyEntity::NAME_LOCKED);
         $accountCcs = AccountCostCenterEntity::findOne([['accountId' => $this->environment->clientId], ['ccId' => $costCenter->ccId]]);
         if ($isLocked || !$accountCcs instanceof AccountCostCenterEntity) {
             $costCentreLocked = 1;
         } else {
             $costCentreLocked = 0;
         }
     } else {
         $costCentreName = '';
         $costCentreLocked = 0;
     }
     $supportedClouds = $this->getContainer()->analytics->prices->getSupportedClouds();
     $result['analytics'] = array('costCenterName' => $costCentreName, 'costCenterLocked' => $costCentreLocked, 'projects' => $projects, 'unsupportedClouds' => array_values(array_diff($this->environment->getEnabledPlatforms(), $supportedClouds)));
     return $result;
 }
Esempio n. 6
0
 /**
  * Returns iterator for current quarter
  *
  * @return Iterator\ChartQuarterlyIterator
  */
 public function getCurrentQuarterIterator()
 {
     $quarters = new Quarters(SettingEntity::getQuarters());
     $currentQuarter = $quarters->getQuarterForDate(new \DateTime('now', new \DateTimeZone('UTC')));
     $currentYear = (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y');
     if ($currentQuarter === 1) {
         $quarter = 4;
         $year = $currentYear - 1;
     } else {
         $quarter = $currentQuarter - 1;
         $year = $currentYear;
     }
     $date = $quarters->getPeriodForQuarter($quarter, $year);
     $iterator = ChartPeriodIterator::create('quarter', $date->start, $date->end, 'UTC');
     return $iterator;
 }
 /**
  * {@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;
 }