diff --git a/Controller/ReportContacts.php b/Controller/ReportContacts.php new file mode 100644 index 0000000..45f7af9 --- /dev/null +++ b/Controller/ReportContacts.php @@ -0,0 +1,119 @@ +loadData(); + $this->totals = ContactsReport::summary(); + $this->countries = ContactsReport::geoDistribution(); + + // charts + $this->loadNewContactsByMonth(); + $this->loadNewContactsByYear(); + $this->loadSourcesChart(); + $this->loadInterestsChart(); + + // period breakdowns and comparison for view tables + $this->sources_periods = ContactsReport::sourcesAnalysis(); + $this->interests_periods = ContactsReport::interestsAnalysis(); + $this->comparison = ContactsReport::comparison12vsPrevious12(); + $this->months_history = ContactsReport::historyByMonths(12); + $this->years_history = ContactsReport::historyByYears(); + } + + protected function loadData(): void + { + // nothing special for now + } + + protected function loadNewContactsByMonth(): void + { + $report = new Report(); + $report->type = Report::DEFAULT_TYPE; + $report->table = 'contactos'; + $report->xcolumn = 'fechaalta'; + $report->ycolumn = 'idcontacto'; + $report->xoperation = 'MONTHS'; + $report->yoperation = 'COUNT'; + $report->addFieldXName(''); + $report->addCustomFilter('fechaalta', '>=', '{-1 year}'); + $report->addCustomFilter('fechaalta', '<=', '{today}'); + + $this->charts['newByMonths'] = $report; + } + + protected function loadNewContactsByYear(): void + { + $report = new Report(); + $report->type = Report::TYPE_BAR; + $report->table = 'contactos'; + $report->xcolumn = 'fechaalta'; + $report->ycolumn = 'idcontacto'; + $report->xoperation = 'YEAR'; + $report->yoperation = 'COUNT'; + $report->addFieldXName(''); + + $this->charts['newByYears'] = $report; + } + + protected function loadSourcesChart(): void + { + $report = new Report(); + $report->type = Report::TYPE_DOUGHNUT; + $report->table = 'crm_fuentes2 f'; + $report->xcolumn = "COALESCE(f.nombre, '" . Tools::trans('no-data') . "')"; + $report->ycolumn = 'c.idcontacto'; + $report->yoperation = 'COUNT'; + + Report::activateAdvancedReport(true); + $report->addCustomJoin('LEFT JOIN contactos c ON c.idfuente = f.id'); + + $this->charts['sources'] = $report; + } + + protected function loadInterestsChart(): void + { + $report = new Report(); + $report->type = Report::TYPE_DOUGHNUT; + $report->table = 'crm_intereses i'; + $report->xcolumn = "COALESCE(i.nombre, '" . Tools::trans('no-data') . "')"; + $report->ycolumn = 'ic.id'; + $report->yoperation = 'COUNT'; + + Report::activateAdvancedReport(true); + $report->addCustomJoin('LEFT JOIN crm_intereses_contactos ic ON ic.idinteres = i.id'); + + $this->charts['interests'] = $report; + } +} diff --git a/Init.php b/Init.php index 93f41dd..1b92699 100644 --- a/Init.php +++ b/Init.php @@ -84,7 +84,7 @@ private function createRoleForPlugin(): void // checks the role permissions $nameControllers = [ 'ReportTreasury','ReportTransport','ReportTaxes','ReportResult', - 'ReportProducto','ReportClients','ReportBreakdown','ReportBooks', + 'ReportProducto','ReportClients','ReportContacts','ReportBreakdown','ReportBooks', 'ListReportAccounting','ListReport', 'EditReportLedger','EditReportBoard','EditReportBalance','EditReportAmount','EditReport','EditBalanceCode' ]; diff --git a/Lib/Informes/ContactsReport.php b/Lib/Informes/ContactsReport.php new file mode 100644 index 0000000..245e111 --- /dev/null +++ b/Lib/Informes/ContactsReport.php @@ -0,0 +1,137 @@ +select("SELECT COUNT(*) as total FROM contactos;")[0]['total']; + $out['verified'] = (int)$db->select("SELECT COUNT(*) as total FROM contactos WHERE verificado = " . $db->var2str(true) . ";")[0]['total']; + $out['verified_perc'] = $out['total'] > 0 ? round(($out['verified'] * 100) / $out['total'], 2) : 0; + $out['marketing'] = (int)$db->select("SELECT COUNT(*) as total FROM contactos WHERE admitemarketing = " . $db->var2str(true) . ";")[0]['total']; + $out['marketing_perc'] = $out['total'] > 0 ? round(($out['marketing'] * 100) / $out['total'], 2) : 0; + + return $out; + } + + public static function historyByMonths(int $months = 12): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $sql = "SELECT DATE_FORMAT(fechaalta, '%Y-%m') as ym, COUNT(*) as total + FROM contactos + WHERE fechaalta >= DATE_SUB(CURDATE(), INTERVAL " . (int)$months . " MONTH) + GROUP BY ym ORDER BY ym ASC;"; + + return $db->select($sql); + } + + public static function historyByYears(): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $sql = "SELECT DATE_FORMAT(fechaalta, '%Y') as y, COUNT(*) as total + FROM contactos + GROUP BY y ORDER BY y ASC;"; + + return $db->select($sql); + } + + public static function comparison12vsPrevious12(): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $last12 = self::historyByMonths(12); + + $sqlPrev = "SELECT DATE_FORMAT(fechaalta, '%Y-%m') as ym, COUNT(*) as total + FROM contactos + WHERE fechaalta >= DATE_SUB(CURDATE(), INTERVAL 24 MONTH) + AND fechaalta < DATE_SUB(CURDATE(), INTERVAL 12 MONTH) + GROUP BY ym ORDER BY ym ASC;"; + + $prev12 = $db->select($sqlPrev); + + return ['last12' => $last12, 'prev12' => $prev12]; + } + + public static function sourcesAnalysis(): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $periods = [30, 90, 365]; + $result = []; + + foreach ($periods as $days) { + $sql = "SELECT f.id, f.nombre, COUNT(c.idcontacto) AS total + FROM crm_fuentes2 f + LEFT JOIN contactos c ON c.idfuente = f.id AND c.fechaalta >= DATE_SUB(CURDATE(), INTERVAL " . (int)$days . " DAY) + GROUP BY f.id, f.nombre ORDER BY total DESC;"; + $result[$days] = $db->select($sql); + } + + return $result; + } + + public static function interestsAnalysis(): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $periods = [30, 90, 365]; + $result = []; + + foreach ($periods as $days) { + $sql = "SELECT i.id, i.nombre, COUNT(ic.id) AS total + FROM crm_intereses i + LEFT JOIN crm_intereses_contactos ic ON ic.idinteres = i.id AND ic.fecha >= DATE_SUB(CURDATE(), INTERVAL " . (int)$days . " DAY) + GROUP BY i.id, i.nombre ORDER BY total DESC;"; + $result[$days] = $db->select($sql); + } + + return $result; + } + + public static function geoDistribution(): array + { + $db = self::db(); + if (null === $db) { + return []; + } + + $sql = "SELECT c.codpais, p.codiso, p.nombre, COUNT(*) as total + FROM contactos c + LEFT JOIN paises p ON c.codpais = p.codpais + GROUP BY c.codpais, p.codiso, p.nombre ORDER BY total DESC;"; + + return $db->select($sql); + } +} diff --git a/Translation/es_ES.json b/Translation/es_ES.json index 922ac6d..5210fb0 100644 --- a/Translation/es_ES.json +++ b/Translation/es_ES.json @@ -248,5 +248,10 @@ "treemap": "Mapa de árbol", "voluntary-reserves": "Reservas voluntarias", "without-opening": "Sin apertura", - "y-operation": "Operación sobre Y" + "y-operation": "Operación sobre Y", + "sources": "Fuentes", + "r-contactos-sources-periods": "Fuentes (30/90/365 días)", + "interests": "Intereses", + "r-contactos-interests-periods": "Intereses (30/90/365 días)", + "marketing-permission": "Permiso de marketing" } diff --git a/View/ReportContacts.html.twig b/View/ReportContacts.html.twig new file mode 100644 index 0000000..573b869 --- /dev/null +++ b/View/ReportContacts.html.twig @@ -0,0 +1,211 @@ +{# + Informe Contactos - basado en ReportClients +#} + +{% extends "Master/MenuTemplate.html.twig" %} +{% import "Macro/Forms.html.twig" as forms %} + +{% block body %} +