From 82a59185fcb8fd49797e3d6f24a3ba2c0d8f72c6 Mon Sep 17 00:00:00 2001 From: scottshipman Date: Wed, 28 Nov 2018 10:23:53 -0500 Subject: [PATCH 1/2] fix query and tz shifting on client stats chart on client view page --- Model/ContactClientModel.php | 110 +++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/Model/ContactClientModel.php b/Model/ContactClientModel.php index e6b6c510..33b16a97 100644 --- a/Model/ContactClientModel.php +++ b/Model/ContactClientModel.php @@ -322,8 +322,8 @@ public function getEventRepository() } /** - * @param ContactClient $contactClient - * @param $unit + * @param ContactClient $contactClient + * @param $unit * @param \DateTime|null $dateFrom * @param \DateTime|null $dateTo * @param null $campaignId @@ -341,17 +341,9 @@ public function getStats( $dateFormat = null, $canViewOthers = true ) { - $localDateFrom = date_modify($dateFrom, 'midnight'); - $utcDateFrom = clone $localDateFrom; - $utcDateFrom->setTimezone(new \DateTimeZone('UTC')); - - $localDateTo = date_modify($dateTo, 'midnight +1 day -1 sec'); - $utcDateTo = clone $localDateTo; - $utcDateTo->setTimezone(new \DateTimeZone('UTC')); - - $unit = (null === $unit) ? $this->getTimeUnitFromDateRange($utcDateFrom, $utcDateTo) : $unit; - $chart = new LineChart($unit, $localDateFrom, $localDateTo, $dateFormat); - $query = new ChartQuery($this->em->getConnection(), $utcDateFrom, $utcDateTo, $unit); + $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo, $unit); + $unit = (null === $unit) ? $this->getTimeUnitFromDateRange($dateFrom, $dateTo) : $unit; + $chart = new LineChart($unit, $dateFrom, $dateTo, $dateFormat); $stat = new Stat(); $params = ['contactclient_id' => $contactClient->getId()]; @@ -368,6 +360,40 @@ public function getStats( $params ); + if (!in_array($unit, ['H', 'i', 's'])) { + // For some reason, Mautic only sets UTC in Query Date builder + // if its an intra-day date range ¯\_(ツ)_/¯ + // so we have to do it here. + $userTZ = new \DateTime('now'); + $userTzName = $userTZ->getTimezone()->getName(); + $paramDateTo = $q->getParameter('dateTo'); + $paramDateFrom = $q->getParameter('dateFrom'); + $paramDateTo = new \DateTime($paramDateTo); + $paramDateTo->setTimeZone(new \DateTimeZone('UTC')); + $q->setParameter('dateTo', $paramDateTo->format('Y-m-d H:i:s')); + $paramDateFrom = new \DateTime($paramDateFrom); + $paramDateFrom->setTimeZone(new \DateTimeZone('UTC')); + $q->setParameter('dateFrom', $paramDateFrom->format('Y-m-d H:i:s')); + $select = $q->getQueryPart('select')[0]; + $newSelect = str_replace( + 't.date_added,', + "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),", + $select + ); + $q->resetQueryPart('select'); + $q->select($newSelect); + + // AND adjust the group By, since its using db timezone Date values + $groupBy = $q->getQueryPart('groupBy')[0]; + $newGroupBy = str_replace( + 't.date_added,', + "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),", + $groupBy + ); + $q->resetQueryPart('groupBy'); + $q->groupBy($newGroupBy); + } + if (!$canViewOthers) { $this->limitQueryToCreator($q); } @@ -437,9 +463,9 @@ public function limitQueryToCreator(QueryBuilder $q) } /** - * @param ContactClient $contactClient - * @param $unit - * @param $type + * @param ContactClient $contactClient + * @param $unit + * @param $type * @param \DateTime|null $dateFrom * @param \DateTime|null $dateTo * @param null $campaignId @@ -460,22 +486,25 @@ public function getStatsBySource( ) { $unit = (null === $unit) ? $this->getTimeUnitFromDateRange($dateFrom, $dateTo) : $unit; $dateToAdjusted = clone $dateTo; - if (in_array($unit, ['H', 'i', 's'])) { - // draw the chart with the correct intervals for intra-day - $dateToAdjusted->setTime(23, 59, 59); - } + $dateToAdjusted->setTime(23, 59, 59); $chart = new LineChart($unit, $dateFrom, $dateToAdjusted, $dateFormat); $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateToAdjusted, $unit); - $utmSources = $this->getStatRepository()->getSourcesByClient($contactClient->getId(), $dateFrom, $dateToAdjusted); + $utmSources = $this->getStatRepository()->getSourcesByClient( + $contactClient->getId(), + $dateFrom, + $dateToAdjusted + ); - if (isset($campaignId)) { + //if (isset($campaignId)) { + if (!empty($campaignId)) { $params['campaign_id'] = (int) $campaignId; } + $params['contactclient_id'] = $contactClient->getId(); if ('revenue' != $type) { $params['type'] = $type; foreach ($utmSources as $utmSource) { - $params['utm_source'] = $utmSource; + $params['utm_source'] = empty($utmSource) ? ['expression' => 'isNull'] : $utmSource; $q = $query->prepareTimeDataQuery( 'contactclient_stats', 'date_added', @@ -486,6 +515,8 @@ public function getStatsBySource( // For some reason, Mautic only sets UTC in Query Date builder // if its an intra-day date range ¯\_(ツ)_/¯ // so we have to do it here. + $userTZ = new \DateTime('now'); + $userTzName = $userTZ->getTimezone()->getName(); $paramDateTo = $q->getParameter('dateTo'); $paramDateFrom = $q->getParameter('dateFrom'); $paramDateTo = new \DateTime($paramDateTo); @@ -494,14 +525,20 @@ public function getStatsBySource( $paramDateFrom = new \DateTime($paramDateFrom); $paramDateFrom->setTimeZone(new \DateTimeZone('UTC')); $q->setParameter('dateFrom', $paramDateFrom->format('Y-m-d H:i:s')); + $select = $q->getQueryPart('select')[0]; + $newSelect = str_replace( + 't.date_added,', + "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),", + $select + ); + $q->resetQueryPart('select'); + $q->select($newSelect); // AND adjust the group By, since its using db timezone Date values - $userTZ = new \DateTime('now'); - $interval = abs($userTZ->getOffset() / 3600); $groupBy = $q->getQueryPart('groupBy')[0]; $newGroupBy = str_replace( - 'DATE_FORMAT(t.date_added,', - "DATE_FORMAT(DATE_SUB(t.date_added, INTERVAL $interval HOUR),", + 't.date_added,', + "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),", $groupBy ); $q->resetQueryPart('groupBy'); @@ -538,9 +575,14 @@ public function getStatsBySource( $dateConstruct = 'DATE_FORMAT(t.date_added, \''.$dbUnit.'\')'; foreach ($utmSources as $utmSource) { $q->select($dateConstruct.' AS date, ROUND(SUM(t.attribution), 2) AS count') - ->where('utm_source = :utmSource') - ->setParameter('utmSource', $utmSource) ->groupBy($dateConstruct); + if (empty($utmSource)) { // utmSource can be a NULL value + $q->where('utm_source IS NULL'); + } else { + $q->where('utm_source = :utmSource') + ->setParameter('utmSource', $utmSource); + } + $data = $query->loadAndBuildTimeData($q); foreach ($data as $val) { if (0 !== $val) { @@ -664,6 +706,14 @@ public function getCampaigns($contactclientId) /** @var CampaignRepository $campaignRepo */ $campaignRepo = $this->em->getRepository('MauticCampaignBundle:Campaign'); - return $campaignRepo->getEntities(['filter'=>['column' => 'canvasSettings', 'expr' => 'like', 'value' => "%'contactclient': $contactclientId,%"]]); + return $campaignRepo->getEntities( + [ + 'filter' => [ + 'column' => 'canvasSettings', + 'expr' => 'like', + 'value' => "%'contactclient': $contactclientId,%", + ], + ] + ); } } From 71dc7abdc64c6f8d77c7c3248b0965eb56185f98 Mon Sep 17 00:00:00 2001 From: scottshipman Date: Wed, 28 Nov 2018 10:52:57 -0500 Subject: [PATCH 2/2] fix query on revenue by source version of client stat chart --- Model/ContactClientModel.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Model/ContactClientModel.php b/Model/ContactClientModel.php index 33b16a97..efcf6f68 100644 --- a/Model/ContactClientModel.php +++ b/Model/ContactClientModel.php @@ -501,6 +501,9 @@ public function getStatsBySource( } $params['contactclient_id'] = $contactClient->getId(); + $userTZ = new \DateTime('now'); + $userTzName = $userTZ->getTimezone()->getName(); + if ('revenue' != $type) { $params['type'] = $type; foreach ($utmSources as $utmSource) { @@ -515,8 +518,6 @@ public function getStatsBySource( // For some reason, Mautic only sets UTC in Query Date builder // if its an intra-day date range ¯\_(ツ)_/¯ // so we have to do it here. - $userTZ = new \DateTime('now'); - $userTzName = $userTZ->getTimezone()->getName(); $paramDateTo = $q->getParameter('dateTo'); $paramDateFrom = $q->getParameter('dateFrom'); $paramDateTo = new \DateTime($paramDateTo); @@ -572,14 +573,14 @@ public function getStatsBySource( } $dbUnit = $query->getTimeUnitFromDateRange($dateFrom, $dateTo); $dbUnit = $query->translateTimeUnit($dbUnit); - $dateConstruct = 'DATE_FORMAT(t.date_added, \''.$dbUnit.'\')'; + $dateConstruct = "DATE_FORMAT(CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'), '$dbUnit.')"; foreach ($utmSources as $utmSource) { $q->select($dateConstruct.' AS date, ROUND(SUM(t.attribution), 2) AS count') ->groupBy($dateConstruct); if (empty($utmSource)) { // utmSource can be a NULL value - $q->where('utm_source IS NULL'); + $q->andWhere('utm_source IS NULL'); } else { - $q->where('utm_source = :utmSource') + $q->andWhere('utm_source = :utmSource') ->setParameter('utmSource', $utmSource); }