- Introduced `is_wash` field to `products_o` for marking wash-related products. - Updated `productsRoute` to handle `is_wash` in product creation and editing. - Added `getTransactionsOnDateWashesCount` method in `department_daily_reports_o` for calculating wash-related transactions in reports. - Adjusted department daily reports routes to include wash statistics output.
563 lines
23 KiB
PHP
563 lines
23 KiB
PHP
<?php
|
|
|
|
namespace objects;
|
|
|
|
use classes\db;
|
|
use classes\object_property;
|
|
use Exception;
|
|
use traits\db_object_t;
|
|
|
|
class department_daily_reports_o extends db
|
|
{
|
|
use db_object_t;
|
|
|
|
/**
|
|
* The id of the department
|
|
* @var object_property $department_id
|
|
*/
|
|
public object_property $department_id;
|
|
/**
|
|
* The cm3 of water used in the department today
|
|
* @var object_property $water_usage
|
|
*/
|
|
public object_property $water_usage;
|
|
/**
|
|
* The cm3 of water used in the department today
|
|
* @var object_property $water_usage_morning
|
|
*/
|
|
public object_property $water_usage_morning;
|
|
|
|
/**
|
|
* Any notes for the report
|
|
* @var object_property $notes
|
|
*/
|
|
public object_property $notes;
|
|
|
|
/**
|
|
* The user (id) that filled the report
|
|
* @var object_property $filled_by
|
|
*/
|
|
public object_property $filled_by;
|
|
/**
|
|
* The timestamp of when the object was created
|
|
* @var object_property $created_at
|
|
*/
|
|
public object_property $created_at;
|
|
|
|
|
|
public function structure(): void
|
|
{
|
|
$this->setTable('department_daily_reports');
|
|
}
|
|
|
|
public function asArray(): array
|
|
{
|
|
return [
|
|
'id' => (int)$this->id,
|
|
'department_id' => (int)$this->department_id->value(),
|
|
'water_usage' => (int)$this->water_usage->value(),
|
|
'water_usage_morning' => (int)$this->water_usage_morning->value(),
|
|
'notes' => (string)$this->notes->value(),
|
|
'filled_by' => (int)$this->filled_by->value(),
|
|
'created_at' => (string)$this->created_at->value(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get the amount of products sold on a given date
|
|
* @note This does not count products from removed orders, only products from orders that are still active
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @param int $department_id The id of the department
|
|
* @param int $product_id The id of the product
|
|
* @param string|null $date_to (Optional) The end date to get the report for (YYYY-MM-DD). If provided, the report will be for the date range between $date and $date_to
|
|
* @return int The amount of products sold on the given date (Not counting products from removed orders)
|
|
*/
|
|
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
|
|
}
|
|
$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 oi.product_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.deleted_at IS NULL'
|
|
);
|
|
|
|
if ($stmt) {
|
|
$stmt->bind_param('iiss', $department_id, $product_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'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount;
|
|
}
|
|
|
|
/**
|
|
* Get the amount of products sold, where the product would be applicable as an addon
|
|
* E.g. if the product is "Cheese" this would return the amount of "Pizza" sold
|
|
* @note This does not count products from removed orders, only products from orders that are still active
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @param int $department_id The id of the department
|
|
* @param int $product_id The id of the product (the addon)
|
|
* @param string|null $date_to (Optional) The end date to get the report for (YYYY-MM-DD). If provided, the report will be for the date range between $date and $date_to
|
|
* @return int The amount of products sold on the given date (Not counting products from removed orders)
|
|
*/
|
|
public function getProductsSoldWithAddonApplicable(string $date, int $department_id, int $product_id, string $date_to = null): int
|
|
{
|
|
global /** @var db $db */
|
|
$db;
|
|
// Get all the addons for the product
|
|
$addons = (new product_options_o())->getOptionProducts($product_id);
|
|
$addons = array_map(function ($addon) {
|
|
return $addon['product_id'];
|
|
}, $addons);
|
|
$addons = implode(',', $addons);
|
|
// 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
|
|
}
|
|
$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 oi.product_id IN (' . $addons . ') AND DATE(o.created_at) BETWEEN ? AND ? AND o.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
|
|
$amount = $data['amount'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount;
|
|
|
|
}
|
|
|
|
/**
|
|
* Get the amount of products sold on a given date
|
|
* @note This does not count products from removed orders, only products from orders that are still active
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @param int $department_id The id of the department
|
|
* @param string|null $date_to (Optional) The end date to get the report for (YYYY-MM-DD). If provided, the report will be for the date range between $date and $date_to
|
|
* @return int The amount of products sold on the given date (Not counting products from removed orders)
|
|
*/
|
|
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
|
|
}
|
|
$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'
|
|
);
|
|
|
|
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'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount;
|
|
}
|
|
|
|
/**
|
|
* Get the amount of transactions on a given date
|
|
* @note This does not count products from removed orders, only products from orders that are still active
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @param int $department_id The id of the department
|
|
* @param string|null $date_to (Optional) The end date to get the report for (YYYY-MM-DD). If provided, the report will be for the date range between $date and $date_to
|
|
* @return int The amount of transactions on the given date (Not counting products from removed orders)
|
|
*/
|
|
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
|
|
}
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT COUNT(*) as amount FROM orders o
|
|
WHERE o.department_id = ? AND DATE(o.created_at) BETWEEN ? AND ? AND o.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
|
|
$amount = $data['amount'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount;
|
|
}
|
|
|
|
/**
|
|
* Select the department daily report for today
|
|
* @param int $department_id The id of the department
|
|
* @return department_daily_reports_o The department daily report
|
|
* @throws Exception If a department daily report does not exist for today
|
|
* @throws Exception If the object was not selected
|
|
*/
|
|
public function selectDepartmentDailyReport(int $department_id): department_daily_reports_o
|
|
{
|
|
global $db;
|
|
if (!$this->doesDepartmentDailyReportExist($department_id)) {
|
|
throw new Exception('Department daily report does not exist');
|
|
}
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT id FROM department_daily_reports o
|
|
WHERE o.department_id = ? AND DATE(o.created_at) = CURDATE()'
|
|
);
|
|
// Check if the statement was prepared successfully
|
|
if ($stmt) {
|
|
$stmt->bind_param('i', $department_id); // 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
|
|
$id = $data['id'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
$this->select($id);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Check if a department daily report exists for today
|
|
* @param int $department_id The id of the department
|
|
* @param string $date The date to check for (YYYY-MM-DD)
|
|
* @return bool True if the report exists, false otherwise
|
|
*/
|
|
public function doesDepartmentDailyReportExist(int $department_id, string $date = 'today'): bool
|
|
{
|
|
global $db;
|
|
if ($date === 'today') {
|
|
$date = date('Y-m-d');
|
|
}
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT COUNT(*) as amount FROM department_daily_reports o
|
|
WHERE o.department_id = ? AND DATE(o.created_at) = ?'
|
|
);
|
|
|
|
if ($stmt) {
|
|
$stmt->bind_param('is', $department_id, $date); // 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'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount > 0;
|
|
}
|
|
|
|
/**
|
|
* Select the last department daily report for a department
|
|
* @param int $department_id The id of the department
|
|
* @return department_daily_reports_o The department daily report
|
|
* @throws Exception If the object was not selected
|
|
*/
|
|
public function selectLastDepartmentDailyReport(int $department_id): department_daily_reports_o
|
|
{
|
|
global $db;
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT id FROM department_daily_reports o
|
|
WHERE o.department_id = ? ORDER BY o.created_at DESC LIMIT 1'
|
|
);
|
|
// Check if the statement was prepared successfully
|
|
if ($stmt) {
|
|
$stmt->bind_param('i', $department_id); // 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 "id" field
|
|
if (!$data) {
|
|
throw new Exception('Department daily report does not exist');
|
|
}
|
|
$id = $data['id'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
$this->select($id);
|
|
return $this;
|
|
}
|
|
|
|
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
|
|
}
|
|
$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'
|
|
);
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Check if a department daily report exists for today
|
|
* @param int $department_id The id of the department
|
|
* @return bool True if the report exists, false otherwise
|
|
*/
|
|
public function hasReportForToday(int $department_id): bool
|
|
{
|
|
return $this->doesDepartmentDailyReportExist($department_id);
|
|
}
|
|
|
|
/**
|
|
* Select the department daily report for a given date
|
|
* @param int $department_id The id of the department
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @return department_daily_reports_o The department daily report
|
|
* @throws Exception If a department daily report does not exist for today
|
|
* @throws Exception If the object was not selected
|
|
*/
|
|
public function selectDepartmentReportByDate(int $department_id, string $date): department_daily_reports_o
|
|
{
|
|
global $db;
|
|
if (!$this->doesDepartmentDailyReportExist($department_id, $date)) {
|
|
// Create a new report for the given date, if it does not exist
|
|
return $this->add($department_id, 0, 0, '', 0, $date);
|
|
}
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT id FROM department_daily_reports o
|
|
WHERE o.department_id = ? AND DATE(o.created_at) = ?'
|
|
);
|
|
// Check if the statement was prepared successfully
|
|
if ($stmt) {
|
|
$stmt->bind_param('is', $department_id, $date); // 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) {
|
|
throw new Exception('Department daily report does not exist');
|
|
}
|
|
$id = $data['id'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
$this->select($id);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add a department daily report
|
|
* @param int $department_id The id of the department
|
|
* @param int $water_usage The cm3 of water used in the department today
|
|
* @param int $water_usage_morning The cm3 of water used in the department (Checked in the morning)
|
|
* @param string $notes Any notes for the report
|
|
* @param int $filled_by The user (id) that filled the report
|
|
* @return department_daily_reports_o
|
|
* @throws Exception If the object was not created successfully
|
|
*/
|
|
public function add(
|
|
int $department_id,
|
|
int $water_usage,
|
|
int $water_usage_morning,
|
|
string $notes,
|
|
int $filled_by,
|
|
string $created_at = null
|
|
): department_daily_reports_o
|
|
{
|
|
// Validate the created_at date, if provided
|
|
if ($created_at !== null) {
|
|
$dateTime = \DateTime::createFromFormat('Y-m-d', $created_at);
|
|
if (!$dateTime || $dateTime->format('Y-m-d') !== $created_at) {
|
|
throw new Exception('Invalid date format for created_at. Expected format: YYYY-MM-DD');
|
|
}
|
|
}
|
|
$tmp_id = $this->add_object([
|
|
'department_id' => (int)$department_id,
|
|
'water_usage' => (int)$water_usage,
|
|
'water_usage_morning' => (int)$water_usage_morning,
|
|
'notes' => (string)$notes,
|
|
'filled_by' => (int)$filled_by,
|
|
'created_at' => $created_at ? $created_at : date('Y-m-d H:i:s'),
|
|
]);
|
|
$this->id = $tmp_id;
|
|
$this->getObjectProperties();
|
|
$this->objectChanged();
|
|
return $this;
|
|
}
|
|
|
|
public function getObjectProperties(): void
|
|
{
|
|
$this->department_id = new object_property($this->table, $this->id, 'department_id', 'int', false);
|
|
$this->water_usage = new object_property($this->table, $this->id, 'water_usage', 'int', false);
|
|
$this->water_usage_morning = new object_property($this->table, $this->id, 'water_usage_morning', 'int', false);
|
|
$this->notes = new object_property($this->table, $this->id, 'notes', 'string', false);
|
|
$this->filled_by = new object_property($this->table, $this->id, 'filled_by', 'int', false);
|
|
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'string', false);
|
|
}
|
|
|
|
public function objectChanged(): void
|
|
{
|
|
//TODO: Add cache invalidation
|
|
}
|
|
|
|
public function hasReport(int $department_id, string $date): bool
|
|
{
|
|
return $this->doesDepartmentDailyReportExist($department_id, $date);
|
|
}
|
|
|
|
public function getBookingsOnDateCount(string $date, int $department_id, string $status): int
|
|
{
|
|
global /** @var db $db */
|
|
$db;
|
|
$conn = $db->conn();
|
|
$stmt = $conn->prepare(
|
|
'SELECT COUNT(*) as amount FROM bookings_new o
|
|
WHERE o.department = ? AND DATE(o.created_at) = ? AND o.status = ?'
|
|
);
|
|
|
|
if ($stmt) {
|
|
$stmt->bind_param('iss', $department_id, $date, $status); // 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'];
|
|
|
|
$stmt->close(); // Close the statement
|
|
} else {
|
|
// Handle query preparation error
|
|
die('Query preparation failed: ' . $conn->error);
|
|
}
|
|
return (int)$amount;
|
|
}
|
|
|
|
/**
|
|
* This function calculates how many of the transactions on a given date included a wash
|
|
* That is defined as any product that has the "is_wash" field set to true in the products table
|
|
* @note This does not count products from removed orders, only products from orders that are still active
|
|
* @param string $date The date to get the report for (YYYY-MM-DD)
|
|
* @param int $department_id The id of the department
|
|
* @param string|null $date_to (Optional) The end date to get the report for (YYYY-MM-DD). If provided, the report will be for the date range between $date and $date_to
|
|
* @return void
|
|
*/
|
|
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
|
|
}
|
|
$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 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;
|
|
}
|
|
} |