diff --git a/services/nginx/app/classes/redis.php b/services/nginx/app/classes/redis.php index a8c0f023..59ff40c4 100644 --- a/services/nginx/app/classes/redis.php +++ b/services/nginx/app/classes/redis.php @@ -397,5 +397,4 @@ class redis implements redis_i // Get multiple keys from Redis return $this->redis->mget($array_map); } - } \ No newline at end of file diff --git a/services/nginx/app/objects/department_daily_reports_o.php b/services/nginx/app/objects/department_daily_reports_o.php index eec94cdc..af19a9bf 100644 --- a/services/nginx/app/objects/department_daily_reports_o.php +++ b/services/nginx/app/objects/department_daily_reports_o.php @@ -75,17 +75,18 @@ class department_daily_reports_o extends db */ public function getProductsSoldOnDate(string $date, int $department_id, int $product_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - $department = (new departments_o())->select($department_id); - if (!$department) { - throw new Exception("Department with ID {$department_id} not found"); - } - return $department->getTotalAddonsSoldInDepartment([$product_id], $date, $date_to, $department_id); + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function () use ($date, $department_id, $product_id, $date_to) { + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day + } + // Method cache for 2 minutes + $department = (new departments_o())->select($department_id); + $department->requireSelected(); + return $department->getTotalAddonsSoldInDepartment([$product_id], $date, $date_to, $department_id); + }); } /** @@ -127,37 +128,39 @@ class department_daily_reports_o extends db */ public function getTransactionProductsOnDateCount(string $date, int $department_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - // Set the date time to cover the entire day - $date = date('Y-m-d 00:00:00', strtotime($date)); - $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); - $conn = $db->conn(); - $stmt = $conn->prepare( - 'SELECT SUM(oi.quantity) as amount FROM orders o - JOIN order_items oi ON o.id = oi.order_id - WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' - ); + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($date, $department_id, $date_to) { + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day + } + // Set the date time to cover the entire day + $date = date('Y-m-d 00:00:00', strtotime($date)); + $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); + $conn = $db->conn(); + $stmt = $conn->prepare( + 'SELECT SUM(oi.quantity) as amount FROM orders o + JOIN order_items oi ON o.id = oi.order_id + WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' + ); - if ($stmt) { - $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array + if ($stmt) { + $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array - // Access the "amount" field - $amount = $data['amount']; + // Access the "amount" field + $amount = $data['amount']; - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - return (int)$amount; + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + return (int)$amount; + }); } /** @@ -170,38 +173,40 @@ class department_daily_reports_o extends db */ public function getTransactionsOnDateCount(string $date, int $department_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - // Set the date time to cover the entire day - $date = date('Y-m-d 00:00:00', strtotime($date)); - $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); - $conn = $db->conn(); - // Make sure only to count orders with at least one non-deleted order item - $stmt = $conn->prepare( - 'SELECT COUNT(DISTINCT o.id) as amount FROM orders o - JOIN order_items oi ON o.id = oi.order_id - WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' - ); + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($date, $department_id, $date_to) { + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day + } + // Set the date time to cover the entire day + $date = date('Y-m-d 00:00:00', strtotime($date)); + $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); + $conn = $db->conn(); + // Make sure only to count orders with at least one non-deleted order item + $stmt = $conn->prepare( + 'SELECT COUNT(DISTINCT o.id) as amount FROM orders o + JOIN order_items oi ON o.id = oi.order_id + WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' + ); - if ($stmt) { - $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array + if ($stmt) { + $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array - // Access the "amount" field - $amount = $data['amount']; + // Access the "amount" field + $amount = $data['amount']; - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - return (int)$amount; + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + return (int)$amount; + }); } /** @@ -314,41 +319,44 @@ class department_daily_reports_o extends db public function getTransactionsOnDateEarnings(string $date, int $department_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - // Set the date time to cover the entire day - $date = date('Y-m-d 00:00:00', strtotime($date)); - $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); - $conn = $db->conn(); - // Get all the product prices, in all the orders (Not counting removed orders), for the given date and department, and sum them - $stmt = $conn->prepare( - 'SELECT SUM(oi.price * oi.quantity) as amount FROM orders o - JOIN order_items oi ON o.id = oi.order_id - WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' - ); - if ($stmt) { - $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($date, $department_id, $date_to) { - // Access the "amount" field - if (!$data) { - // If there are no orders, set the amount to 0 - $amount = 0; - } else { - $amount = $data['amount']; + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day } - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - return (int)$amount; + // Set the date time to cover the entire day + $date = date('Y-m-d 00:00:00', strtotime($date)); + $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); + $conn = $db->conn(); + // Get all the product prices, in all the orders (Not counting removed orders), for the given date and department, and sum them + $stmt = $conn->prepare( + 'SELECT SUM(oi.price * oi.quantity) as amount FROM orders o + JOIN order_items oi ON o.id = oi.order_id + WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL' + ); + if ($stmt) { + $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array + + // Access the "amount" field + if (!$data) { + // If there are no orders, set the amount to 0 + $amount = 0; + } else { + $amount = $data['amount']; + } + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + return (int)$amount; + }); } /** @@ -501,42 +509,44 @@ class department_daily_reports_o extends db */ public function getTransactionsOnDateWashesCount(string $date, int $department_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - // Set the date time to cover the entire day - $date = date('Y-m-d 00:00:00', strtotime($date)); - $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); - $conn = $db->conn(); - // Get all the product prices, in all the orders (Not counting removed orders), for the given date and department, and sum them - $stmt = $conn->prepare( - 'SELECT COUNT(DISTINCT o.id) as amount FROM orders o - JOIN order_items oi ON o.id = oi.order_id - JOIN products p ON oi.product_id = p.id - WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL AND p.is_wash = 1' - ); - if ($stmt) { - $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array - - // Access the "amount" field - if (!$data) { - // If there are no orders, set the amount to 0 - $amount = 0; - } else { - $amount = $data['amount']; + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($date, $department_id, $date_to) { + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day } - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - return (int)$amount; + // Set the date time to cover the entire day + $date = date('Y-m-d 00:00:00', strtotime($date)); + $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); + $conn = $db->conn(); + // Get all the product prices, in all the orders (Not counting removed orders), for the given date and department, and sum them + $stmt = $conn->prepare( + 'SELECT COUNT(DISTINCT o.id) as amount FROM orders o + JOIN order_items oi ON o.id = oi.order_id + JOIN products p ON oi.product_id = p.id + WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL AND oi.deleted_at IS NULL AND p.is_wash = 1' + ); + if ($stmt) { + $stmt->bind_param('iss', $department_id, $date, $date_to); // Bind parameters (i = integer, s = string) + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array + + // Access the "amount" field + if (!$data) { + // If there are no orders, set the amount to 0 + $amount = 0; + } else { + $amount = $data['amount']; + } + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + return (int)$amount; + }); } /** @@ -552,48 +562,51 @@ class department_daily_reports_o extends db */ public function getTransactionsOnDateWaterUsage(string $date, int $department_id, string $date_to = null): int { - global /** @var db $db */ - $db; - // If the date_to is null, set it to the date - if ($date_to === null) { - $date_to = $date; // Making the report for an entire day - } - // Set the date time to cover the entire day - $date = date('Y-m-d 00:00:00', strtotime($date)); - $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); - $conn = $db->conn(); - // Get the earliest report before the given date - $stmt = $conn->prepare( - 'SELECT water_usage FROM department_daily_reports o - WHERE o.created_at < ? AND o.department_id = ? AND o.water_usage > 0 ORDER BY o.created_at DESC LIMIT 1' - ); - if ($stmt) { - $stmt->bind_param('si', $date, $department_id); // Bind parameters - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array - $earliest_usage = $data ? (int)$data['water_usage'] : 0; - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - // Get the report closest to the date_to, but not after - $stmt = $conn->prepare( - 'SELECT water_usage FROM department_daily_reports o - WHERE o.created_at <= ? AND o.department_id = ? AND o.water_usage > 0 ORDER BY o.created_at DESC LIMIT 1' - ); - if ($stmt) { - $stmt->bind_param('si', $date_to, $department_id); // Bind parameters - $stmt->execute(); - $result = $stmt->get_result(); // Get the result set from the statement - $data = $result->fetch_assoc(); // Fetch the result as an associative array - $latest_usage = $data ? (int)$data['water_usage'] : 0; - $stmt->close(); // Close the statement - } else { - // Handle query preparation error - die('Query preparation failed: ' . $conn->error); - } - return $latest_usage - $earliest_usage; + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($date, $department_id, $date_to) { + global /** @var db $db */ + $db; + // If the date_to is null, set it to the date + if ($date_to === null) { + $date_to = $date; // Making the report for an entire day + } + // Set the date time to cover the entire day + $date = date('Y-m-d 00:00:00', strtotime($date)); + $date_to = date('Y-m-d 23:59:59', strtotime($date_to)); + $conn = $db->conn(); + // Get the earliest report before the given date + $stmt = $conn->prepare( + 'SELECT water_usage FROM department_daily_reports o + WHERE o.created_at < ? AND o.department_id = ? AND o.water_usage > 0 ORDER BY o.created_at DESC LIMIT 1' + ); + if ($stmt) { + $stmt->bind_param('si', $date, $department_id); // Bind parameters + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array + $earliest_usage = $data ? (int)$data['water_usage'] : 0; + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + // Get the report closest to the date_to, but not after + $stmt = $conn->prepare( + 'SELECT water_usage FROM department_daily_reports o + WHERE o.created_at <= ? AND o.department_id = ? AND o.water_usage > 0 ORDER BY o.created_at DESC LIMIT 1' + ); + if ($stmt) { + $stmt->bind_param('si', $date_to, $department_id); // Bind parameters + $stmt->execute(); + $result = $stmt->get_result(); // Get the result set from the statement + $data = $result->fetch_assoc(); // Fetch the result as an associative array + $latest_usage = $data ? (int)$data['water_usage'] : 0; + $stmt->close(); // Close the statement + } else { + // Handle query preparation error + die('Query preparation failed: ' . $conn->error); + } + return $latest_usage - $earliest_usage; + }); } + } \ No newline at end of file diff --git a/services/nginx/app/objects/departments_o.php b/services/nginx/app/objects/departments_o.php index 9480b739..17bcecc9 100644 --- a/services/nginx/app/objects/departments_o.php +++ b/services/nginx/app/objects/departments_o.php @@ -654,12 +654,14 @@ class departments_o extends db */ public function getTotalMaxAddonsInDepartment(array $product_ids, string $date_start, string $date_end, int $department_id): int { - $total_max_addons = 0; - foreach ($product_ids as $product_id) { - $addon_max_count = (new product_options_o())->getMaxAddonsInDateRange($product_id, $date_start, $date_end, $department_id); - $total_max_addons += $addon_max_count; - } - return $total_max_addons; + return self::methodCacheWithParameters(__METHOD__, func_get_args(), 120, function() use ($product_ids, $date_start, $date_end, $department_id) { + $total_max_addons = 0; + foreach ($product_ids as $product_id) { + $addon_max_count = (new product_options_o())->getMaxAddonsInDateRange($product_id, $date_start, $date_end, $department_id); + $total_max_addons += $addon_max_count; + } + return $total_max_addons; + }); } /** diff --git a/services/nginx/app/traits/db_object_t.php b/services/nginx/app/traits/db_object_t.php index 6225652a..4a7bc11e 100644 --- a/services/nginx/app/traits/db_object_t.php +++ b/services/nginx/app/traits/db_object_t.php @@ -1005,6 +1005,39 @@ trait db_object_t return $data; } + /** + * Method cache with parameters + * @param string $method The method to cache the result of + * @param array $params The parameters to pass to the method + * @param int $expiration The expiration time in seconds + * @param callable|null $function The function to call if the cached result is not found, it should return the result to be cached + * @return mixed The cached result of the method + */ + public function methodCacheWithParameters(string $method, array $params = [], int $expiration = 120, callable $function = null): mixed + { + // Generate the cache key + $objectId = "methodCacheWithParameters"; + $key = $method . '_' . md5(serialize($params)); + // Try to get the cached result + $cachedResult = $this->getCached($key, $objectId); + // If the cached result is found, return it + if ($cachedResult !== null) { + return $cachedResult; + } + // If the cached result is not found, call the function to get the result + if ($function) { + $result = call_user_func_array($function, $params); + } else { + // If no function is provided, call the method on this object + $result = call_user_func_array([$this, $method], $params); + } + // Cache the result + $this->cache($key, $result, $objectId); + // Set the expiration time + $this->setCachedExpiration($key, $expiration, $objectId); + return $result; + } + /** * Delete cached object * @param string $key The key to delete the cached object