From 0491a2ad1b7862f516095f1aa328c807ea44dd4a Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Mon, 26 Jan 2026 19:24:51 +0100 Subject: [PATCH] Add `VISITS` criteria type and implement visit counting logic in `goals_criteria` - Introduce `VISITS` as a new goal criteria type in `goals_criteria_type` enum. - Extend `goals_criteria` with `countVisits` method to compute unique visit counts based on criteria filters. - Update result computation logic in `goals_criteria` to support `VISITS`. --- .../modules/goals/classes/goals_criteria.php | 28 +++++++++++++++++++ .../goals/helpers/goals_criteria_type.php | 2 ++ 2 files changed, 30 insertions(+) diff --git a/services/nginx/app/modules/goals/classes/goals_criteria.php b/services/nginx/app/modules/goals/classes/goals_criteria.php index 2b374e4d..590e70c6 100644 --- a/services/nginx/app/modules/goals/classes/goals_criteria.php +++ b/services/nginx/app/modules/goals/classes/goals_criteria.php @@ -190,6 +190,7 @@ class goals_criteria implements goals_criteria_i return match ($this->type) { goals_criteria_type::PRODUCT => $this->products->count($this), goals_criteria_type::REVENUE => $this->sumRevenue(), + goals_criteria_type::VISITS => $this->countVisits(), default => 0, }; } @@ -221,6 +222,33 @@ class goals_criteria implements goals_criteria_i return $sum; } + /** + * Count visits within the criteria filters. + * In this domain a "visit" corresponds to unique order records. + */ + private function countVisits(): int + { + $datetime_start = $this->start ?? new \DateTime(); + $datetime_end = $this->end ?? new \DateTime(); + + $items = order_items_o::getListByCriteria( + department_ids: $this->departments?->listIDs() ?? [], + product_ids: $this->products?->listIDs() ?? [], + customer_numbers: $this->users?->listCustomerNumbers() ?? [], + datetime_start: $datetime_start, + datetime_end: $datetime_end, + ); + + // Use an associative array to track unique order IDs + $unique_orders = []; + foreach ($items as $item) { + $order_id = (int)$item->order_id->value(); + $unique_orders[$order_id] = true; // Value doesn't matter + } + + return count($unique_orders); + } + /** * Public accessor for the current result based on criteria type. * Allows external callers (e.g., goals class) to retrieve the computed result diff --git a/services/nginx/app/modules/goals/helpers/goals_criteria_type.php b/services/nginx/app/modules/goals/helpers/goals_criteria_type.php index f096e231..4b01bbe2 100644 --- a/services/nginx/app/modules/goals/helpers/goals_criteria_type.php +++ b/services/nginx/app/modules/goals/helpers/goals_criteria_type.php @@ -6,6 +6,7 @@ enum goals_criteria_type { case PRODUCT; // When the goal is related to a product case REVENUE; // When the goal is related to revenue + case VISITS; // When the goal is related to visits case NONE; // When there is no specific criteria public static function tryFrom(string $param): ?goals_criteria_type @@ -13,6 +14,7 @@ enum goals_criteria_type return match (strtoupper($param)) { 'PRODUCT' => goals_criteria_type::PRODUCT, 'REVENUE' => goals_criteria_type::REVENUE, + 'VISITS' => goals_criteria_type::VISITS, 'NONE' => goals_criteria_type::NONE, default => null, };