work on visualisation

This commit is contained in:
Rich Lott / Artful Robot 2025-03-25 20:21:32 +00:00
parent 6cf63f5b42
commit 92db3be27e
8 changed files with 370 additions and 26 deletions

View file

@ -40,20 +40,27 @@ class GetFlows extends \Civi\Api4\Generic\AbstractAction {
// occurred *on* the given date.
$getValidDate = fn(?string $input) => $input ? (new DateTimeImmutable($input))->modify('+1 day')->format('Ymd'): FALSE;
$endDate = NULL;
$startDate = $getValidDate($this->startDate);
if (!$startDate) {
throw new CRM_Core_Exception(E::ts("Cannot parse given start date."));
}
$endDate = $getValidDate($this->endDate);
if (!$endDate) {
throw new CRM_Core_Exception(E::ts("Cannot parse given end date."));
if (!empty($this->endDate)) {
$endDate = $getValidDate($this->endDate);
if (!$endDate) {
throw new CRM_Core_Exception(E::ts("Cannot parse given end date."));
}
if (!($endDate > $startDate)) {
throw new CRM_Core_Exception(E::ts("This version of CiviCRM does not support twisting the space time continuum. End date cannot be before start date."));
}
}
if (!($endDate > $startDate)) {
throw new CRM_Core_Exception(E::ts("This version of CiviCRM does not support twisting the space time continuum. End date cannot be before start date."));
else if ($startDate > date('Ymd', strtotime('tomorrow'))) {
throw new CRM_Core_Exception(E::ts("This version of CiviCRM does not support predicting the future. Start time cannot be in the future."));
}
$result['windowFunctionsSupported'] = $this->windowFunctionsSupported();
if ($result['windowFunctionsSupported']) {
// $result['windowFunctionsSupported'] = $this->windowFunctionsSupported();
// if ($result['windowFunctionsSupported']) {
if ($this->windowFunctionsSupported()) {
$this->solveWithWindowFunctions($result, $startDate, $endDate);
}
else {
@ -98,7 +105,7 @@ class GetFlows extends \Civi\Api4\Generic\AbstractAction {
/**
*
*/
protected function solveWithWindowFunctions(Result $result, string $startDateYmd, string $endDateYmd) {
protected function solveWithWindowFunctions(Result $result, string $startDateYmd, ?string $endDateYmd) {
$sql = <<<SQL
/* Identify the relevant activities for the contacts */
@ -112,8 +119,8 @@ class GetFlows extends \Civi\Api4\Generic\AbstractAction {
WHERE a.activity_type_id = 89
),
/* activities1 is the latest activity before the window's start date */
activities1 AS (
/* startActivity is the latest activity before the window's start date */
startActivity AS (
SELECT contact_id, activity_id,
ROW_NUMBER() OVER (
PARTITION BY (contact_id)
@ -123,41 +130,48 @@ class GetFlows extends \Civi\Api4\Generic\AbstractAction {
WHERE a1.activity_date_time < %1
),
/* activities1 is the latest activity before the window's end date */
activities2 AS (
/* endActivity is the latest activity before the window's end date */
endActivity AS (
SELECT contact_id, activity_id,
ROW_NUMBER() OVER (
PARTITION BY (contact_id)
ORDER BY activity_date_time DESC
) rn
FROM activities a2
WHERE a2.activity_date_time < %2
WHERE a2.activity_date_time BETWEEN %1 AND %2
)
/* join activities1 and 2 to count changes between each shift */
/* join startActivity and 2 to count changes between each shift */
SELECT cat1.new_category_id from_category_id, cat2.new_category_id to_category_id, count(*) contact_count
FROM activities2
FROM endActivity
INNER JOIN civicrm_value_category_chan_41 cat1
ON activities2.activity_id = cat1.entity_id
ON endActivity.activity_id = cat1.entity_id
LEFT JOIN (
activities1
startActivity
INNER JOIN civicrm_value_category_chan_41 cat2
ON activities1.activity_id = cat2.entity_id
ON startActivity.activity_id = cat2.entity_id
)
ON activities1.contact_id = activities2.contact_id AND activities1.rn = 1
WHERE activities2.rn = 1
ON startActivity.contact_id = endActivity.contact_id AND startActivity.rn = 1
WHERE endActivity.rn = 1
GROUP BY from_category_id, to_category_id
;
SQL;
if (!$endDateYmd) {
$endDateYmd = date('Ymd', strtotime('tomorrow'));
}
$data = CRM_Core_DAO::executeQuery($sql, [
1 => [$endDateYmd, 'Int'],
2 => [$startDateYmd, 'Int'],
1 => [$startDateYmd, 'Int'],
2 => [$endDateYmd, 'Int'],
])->fetchAll();
// Don't use exchange array so as not to gazump non-array data(?)
foreach ($data as $row) {
$result[] = $row;
$result[] = [
'from_category_id' => (int) $row['new_category_id'],
'to_category_id' => (int) $row['to_category_id'],
'contact_count' => (int) $row['contact_count'],
];
}
}