Add department daily reports feature and improve product handling

Introduced functionality for managing department daily reports, including endpoints for creating, updating, listing, and viewing product sales data. Enhanced product handling in reports by adding support for water usage, notes, and detailed product sales metrics. These changes improve tracking and reporting accuracy across departments.
This commit is contained in:
Jepp9350
2025-03-04 11:39:38 +01:00
parent 9d005566cc
commit 4d593c2b17
7 changed files with 722 additions and 84 deletions
@@ -11,11 +11,38 @@ 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;
public object_property $category_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 object_property $updated_at;
public object_property $deleted_at;
public function structure(): void
@@ -23,40 +50,58 @@ class department_daily_reports_o extends db
$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(),
];
}
/**
* Add a department category, and set this object to the new object
* @param int $department_id
* @param int $category_id
* @return void
* 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 $category_id): void
public function add(
int $department_id,
int $water_usage,
int $water_usage_morning,
string $notes,
int $filled_by
): department_daily_reports_o
{
// Make sure we don't add the same department category twice
if (count(self::getFieldsWhere(
[
'department_id' => $department_id,
'category_id' => $category_id,
'deleted_at' => null
], ['id'])) > 0) {
throw new Exception('Department category already exists');
}
$tmp_id = self::add_object([
'department_id' => $department_id,
'category_id' => $category_id
$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,
]);
$this->id = $tmp_id;
self::getObjectProperties();
self::objectChanged();
$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->category_id = new object_property($this->table, $this->id, 'category_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);
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'string', false);
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'string', false);
}
public function objectChanged(): void
@@ -65,47 +110,219 @@ class department_daily_reports_o extends db
}
/**
* Get the categories for a department
* @param int $department_id
* @return array The categories for the department
* 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
* @return int The amount of products sold on the given date (Not counting products from removed orders)
*/
public function getCategoriesForDepartment(int $department_id, $parseFunction = null): array
public function getProductsSoldOnDate(string $date, int $department_id, int $product_id): int
{
$category_ids = self::getFieldsWhere(
[
'department_id' => $department_id,
'deleted_at' => null
],
['id', 'category_id']
global /** @var db $db */
$db;
$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) = ? AND o.deleted_at IS NULL'
);
$categories = [];
foreach ( $category_ids as $category_id ) {
$tmp = (new department_daily_reports_o())->select($category_id['id'])->asArray();
$tmp['category'] = (new categories_o())->select($tmp['category_id']);
$categories[] = $tmp;
}
if ($parseFunction) {
$tmp = [];
foreach ( $categories as $category ) {
$tmp[] = $parseFunction($category);
}
$categories = $tmp;
}
return $categories;
if ($stmt) {
$stmt->bind_param('iis', $department_id, $product_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;
}
public function asArray(): array
/**
* 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)
* @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): int
{
return [
'id' => (int)$this->id,
'department_id' => (int)$this->department_id->value(),
'category_id' => (int)$this->category_id->value(),
'created_at' => (string)$this->created_at->value(),
'updated_at' => (string)$this->updated_at->value(),
'deleted_at' => (string)$this->deleted_at->value()
];
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);
$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) = ? AND o.deleted_at IS NULL'
);
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;
}
/**
* 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
* @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): int
{
global /** @var db $db */
$db;
$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) = ? AND o.deleted_at IS NULL'
);
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;
}
/**
* 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
* @return int The amount of transactions on the given date (Not counting products from removed orders)
*/
public function getTransactionsOnDateCount(string $date, int $department_id): int
{
global /** @var db $db */
$db;
$conn = $db->conn();
$stmt = $conn->prepare(
'SELECT COUNT(*) as amount FROM orders o
WHERE o.department_id = ? AND DATE(o.created_at) = ? AND o.deleted_at IS NULL'
);
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;
}
/**
* 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
* @return bool True if the report exists, false otherwise
*/
public function doesDepartmentDailyReportExist(int $department_id): bool
{
global $db;
$conn = $db->conn();
$stmt = $conn->prepare(
'SELECT COUNT(*) as amount FROM department_daily_reports o
WHERE o.department_id = ? AND DATE(o.created_at) = CURDATE()'
);
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
$amount = $data['amount'];
$stmt->close(); // Close the statement
} else {
// Handle query preparation error
die('Query preparation failed: ' . $conn->error);
}
return (int)$amount > 0;
}
}
@@ -62,6 +62,12 @@ class product_options_o extends db
self::objectChanged();
}
/**
* Get all options for a product
* @param int $id The id of the product
* @return array
* @throws Exception If the object was not selected
*/
public function getProductOptions(int $id): array
{
$options = self::getFieldsWhere(['product_id' => $id],
@@ -89,4 +95,14 @@ class product_options_o extends db
}
return $tmp;
}
/**
* Get all products with a specific option
* @param int $product_id The id of the addon product
* @return array
*/
public function getOptionProducts(int $product_id): array
{
return self::getFieldsWhere(['option_id' => $product_id], ['product_id']);
}
}
+15 -1
View File
@@ -45,6 +45,16 @@ class products_o extends db
* @var object_property
*/
public object_property $apply_category_discount;
/**
* The timestamp of when the object was created
* @var object_property
*/
public object_property $created_at;
/**
* The timestamp of when the object was last updated
* @var object_property
*/
public object_property $updated_at;
public function structure(): void
{
@@ -78,6 +88,8 @@ class products_o extends db
$this->piktogram = new object_property($this->table, $this->id, 'piktogram', 'string', false);
$this->economic_product_id = new object_property($this->table, $this->id, 'economic_product_id', 'int', false);
$this->apply_category_discount = new object_property($this->table, $this->id, 'apply_category_discount', 'bool', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'string', false);
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'string', false);
}
public function add(string $name, string $description, int $price, string|bool $category = false, string|bool $piktogram = false, string|bool $economicProductId = false): void
@@ -162,7 +174,9 @@ class products_o extends db
'category' => $this->category->value(),
'piktogram' => $this->piktogram->value(),
'economic_product_id' => $this->economic_product_id->value(),
'apply_category_discount' => (bool)$this->apply_category_discount->value()
'apply_category_discount' => (bool)$this->apply_category_discount->value(),
'created_at' => (string)$this->created_at->value(),
'updated_at' => (string)$this->updated_at->value(),
];
}
@@ -107,7 +107,7 @@ class customerSearchRoute
}
},
[
'search_customers' => 'Search for customers'
'search_customers' => 'Search for customers, and list all customers if no search is provided'
]
);
}
@@ -3,7 +3,7 @@
namespace routes;
use classes\authentication;
use objects\departments_o;
use objects\department_daily_reports_o;
use objects\logs_o;
use traits\route_t;
@@ -13,7 +13,7 @@ class departmentDailyReportsRoute
public function run(): void
{
$this->get('/department/daily-reports', function () {
$this->get('/departments/daily-reports', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -23,45 +23,416 @@ class departmentDailyReportsRoute
if ($user) {
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'LIST_DEPARTMENT_DAILY_REPORTS', 'Successfully listed departments daily reports');
$department_daily_reports_o = new department_daily_reports_o();
// Return the list of departments
$response->success(
(new departments_o())
$department_daily_reports_o
->setSearchableFields([
// The fields that can be searched. This would otherwise make it possible to get secret information from the database, simply by searching for it and getting the result count back
'id',
'name',
'description',
'economic_department_id'
'water_usage',
'notes',
'filled_by',
'created_at'
])
->listObjectsWithPaginationIfSet(
function ($department) use ($user) {
$tmp_department = [
'id' => (int)$department['id'],
'name' => (string)$department['name'],
'description' => $department['description'],
'economic_department_id' => (int)$department['economic_department_id'],
'created_at' => (string)$department['created_at'],
'updated_at' => (string)$department['updated_at'],
'dimension' => (int)$department['dimension']
function ($department_report) use ($user) {
return [
'id' => (int)$department_report['id'],
'department_id' => (int)$department_report['department_id'],
'water_usage' => (int)$department_report['water_usage'],
'notes' => (string)$department_report['notes'],
'filled_by' => (int)$department_report['filled_by'],
'created_at' => (string)$department_report['created_at'],
];
// If the user has the permission to view the slack webhook, add it to the response
if ($user->hasPermission('view_slack_webhook')) {
$tmp_department['slack_webhook'] = $department['slack_webhook'];
}
return $tmp_department;
}
},
// This makes sure that the user can only see reports from the departments they explicitly have access to
$department_daily_reports_o->forceRestrictFilters(
[
// This makes sure that the user can only see orders from the departments they explicitly have access to
'department_id' => $user->getGroup()->getDepartments(),
]
)
)
);
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'LIST_DEPARTMENTS', 'No user found, or invalid session');
(new logs_o())->add('departments', 'global', 1, 0, 'LIST_DEPARTMENT_DAILY_REPORTS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_departments' => 'List all departments',
'view_slack_webhook' => 'View the slack webhook'
'list_department_daily_reports' => 'List the department daily reports, provided the user has access to the department',
'department_access_:id' => 'Access the department'
]
);
$this->post('/departments/daily-reports', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('create_department_daily_reports');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the required fields are set
self::requireParameters(
[
'department_id',
'water_usage',
'water_usage_morning',
'notes'
]
);
// Validate the department_id
self::requireType(
(int)self::fromRequest('department_id'),
self::type_int()
);
// Require the department_id to be above 0
self::requireMinValue(
(int)self::fromRequest('department_id'),
1
);
// Validate the water_usage
self::requireType(
(int)self::fromRequest('water_usage'),
self::type_int()
);
// Require the water_usage to be at least 0
self::requireMinValue(
(int)self::fromRequest('water_usage'),
0
);
// Validate the water_usage_morning
self::requireType(
(int)self::fromRequest('water_usage_morning'),
self::type_int()
);
// Require the water_usage_morning to be at least 0
self::requireMinValue(
(int)self::fromRequest('water_usage_morning'),
0
);
// Validate the notes
self::requireType(
(string)self::fromRequest('notes'),
self::type_string()
);
// Require the notes to be at least 0 characters long
self::requireMinLength(
(string)self::fromRequest('notes'),
0
);
// Require the notes to be at most 4000 characters long
self::requireMaxLength(
(string)self::fromRequest('notes'),
4000
);
// Determine if the user has access to the department
self::requireDepartmentAccess((int)self::fromRequest('department_id'));
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'CREATE_DEPARTMENT_DAILY_REPORTS', 'Successfully created department daily report');
// Return the list of departments
$response->success(
(new department_daily_reports_o())
->add(
(int)self::fromRequest('department_id'),
(int)self::fromRequest('water_usage'),
(int)self::fromRequest('water_usage_morning'),
(string)self::fromRequest('notes'),
$user->id
)->asArray()
);
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'CREATE_DEPARTMENT_DAILY_REPORTS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'create_department_daily_reports' => 'Create a new department daily report',
'department_access_:id' => 'Access the department'
]
);
$this->put('/departments/daily-reports', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('update_department_daily_reports');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the required fields are set
self::requireParameters(
[
'department_id',
]
);
// Validate the department_id
self::requireType(
(int)self::fromRequest('department_id'),
self::type_int()
);
// Require the department_id to be above 0
self::requireMinValue(
(int)self::fromRequest('department_id'),
1
);
// Determine if the user has access to the department
self::requireDepartmentAccess((int)self::fromRequest('department_id'));
// Check which fields are set
if (self::isParametersSet(['water_usage'])) {
// Validate the water_usage
self::requireType(
(int)self::fromRequest('water_usage'),
self::type_int()
);
// Require the water_usage to be at least 0
self::requireMinValue(
(int)self::fromRequest('water_usage'),
0
);
}
if (self::isParametersSet(['water_usage_morning'])) {
// Validate the water_usage_morning
self::requireType(
(int)self::fromRequest('water_usage_morning'),
self::type_int()
);
// Require the water_usage_morning to be at least 0
self::requireMinValue(
(int)self::fromRequest('water_usage_morning'),
0
);
}
if (self::isParametersSet(['notes'])) {
// Validate the notes
self::requireType(
(string)self::fromRequest('notes'),
self::type_string()
);
// Require the notes to be at least 0 characters long
self::requireMinLength(
(string)self::fromRequest('notes'),
0
);
// Require the notes to be at most 4000 characters long
self::requireMaxLength(
(string)self::fromRequest('notes'),
4000
);
}
// Check if the report exists
$department_daily_reports_o = new department_daily_reports_o();
if (!$department_daily_reports_o->doesDepartmentDailyReportExist((int)self::fromRequest('department_id'))) {
$response->error('Department daily report not found', 404);
}
// Update the department daily report
$department_daily_report = $department_daily_reports_o->selectDepartmentDailyReport((int)self::fromRequest('department_id'));
if (self::isParametersSet(['water_usage'])) {
$department_daily_report->water_usage->set((int)self::fromRequest('water_usage'));
}
if (self::isParametersSet(['water_usage_morning'])) {
$department_daily_report->water_usage_morning->set((int)self::fromRequest('water_usage_morning'));
}
if (self::isParametersSet(['notes'])) {
$department_daily_report->notes->set((string)self::fromRequest('notes'));
}
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'UPDATE_DEPARTMENT_DAILY_REPORTS', 'Successfully updated department daily report');
// Return the department daily report
$response->success($department_daily_report->asArray());
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'UPDATE_DEPARTMENT_DAILY_REPORTS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'update_department_daily_reports' => 'Update a department daily report',
'department_access_:id' => 'Access the department'
]
);
$this->get('/departments/daily-reports/product-count', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the required fields are set
self::requireParameters(
[
'date',
'department_id',
'product_id'
]
);
// Validate the date
self::requireType(
(string)self::getParameter('date'),
self::type_string()
);
// Require the date to be at least 0 characters long
self::requireMinLength(
'date',
0
);
// Require the date to be at most 10 characters long
self::requireMaxLength(
'date',
10
);
// Validate the date format (YYYY-MM-DD)
self::requireDateFormat(
(string)self::getParameter('date'),
'Y-m-d'
);
// Validate the department_id
self::requireType(
(int)self::getParameter('department_id'),
self::type_int()
);
// Require the department_id to be above 0
self::requireMinValue(
(int)self::getParameter('department_id'),
1
);
// Validate the product_id
self::requireType(
(int)self::getParameter('product_id'),
self::type_int()
);
// Require the product_id to be above 0
self::requireMinValue(
(int)self::getParameter('product_id'),
1
);
// Determine if the user has access to the department
self::requireDepartmentAccess((int)self::getParameter('department_id'));
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'LIST_DEPARTMENT_DAILY_REPORTS_PRODUCTS', 'Successfully listed departments daily reports products');
// Return the list of products sold on the selected date
$response->success(
[
'quantity' =>
(new department_daily_reports_o())
->getProductsSoldOnDate(
(string)self::getParameter('date'),
(int)self::getParameter('department_id'),
(int)self::getParameter('product_id')
),
'date' => (string)self::getParameter('date'),
'department_id' => (int)self::getParameter('department_id'),
'product_id' => (int)self::getParameter('product_id'),
// This is the amount of products sold on the selected date, that this product could have been sold as a part of. (Addons)
'out_of' => (int)(new department_daily_reports_o())->getProductsSoldWithAddonApplicable(
(string)self::getParameter('date'),
(int)self::getParameter('department_id'),
(int)self::getParameter('product_id')
)
]
);
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'LIST_DEPARTMENT_DAILY_REPORTS_PRODUCTS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_department_daily_reports' => 'List the department daily reports, provided the user has access to the department',
'department_access_:id' => 'Access the department'
]
);
$this->get('/departments/daily-reports/transaction-count', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the required fields are set
self::requireParameters(
[
'date',
'department_id'
]
);
// Validate the date
self::requireType(
(string)self::getParameter('date'),
self::type_string()
);
// Require the date to be at least 0 characters long
self::requireMinLength(
'date',
0
);
// Require the date to be at most 10 characters long
self::requireMaxLength(
'date',
10
);
// Validate the date format (YYYY-MM-DD)
self::requireDateFormat(
(string)self::getParameter('date'),
'Y-m-d'
);
// Validate the department_id
self::requireType(
(int)self::getParameter('department_id'),
self::type_int()
);
// Require the department_id to be above 0
self::requireMinValue(
(int)self::getParameter('department_id'),
1
);
// Determine if the user has access to the department
self::requireDepartmentAccess((int)self::getParameter('department_id'));
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'LIST_DEPARTMENT_DAILY_REPORTS_PRODUCTS', 'Successfully listed departments daily reports products');
// Return the list of products sold on the selected date
$response->success(
[
'quantity' =>
(new department_daily_reports_o())
->getTransactionsOnDateCount(
(string)self::getParameter('date'),
(int)self::getParameter('department_id')
),
'products' =>
(new department_daily_reports_o())
->getTransactionProductsOnDateCount(
(string)self::getParameter('date'),
(int)self::getParameter('department_id')
),
'date' => (string)self::getParameter('date'),
'department_id' => (int)self::getParameter('department_id')
]
);
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'LIST_DEPARTMENT_DAILY_REPORTS_PRODUCTS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_department_daily_reports' => 'List the department daily reports, provided the user has access to the department',
'department_access_:id' => 'Access the department'
]
);
}
@@ -39,6 +39,17 @@ class productsRoute
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the id is set in the request
if (self::isParametersSet(['id'])) {
// Log the incident
(new logs_o())->add('products', 'global', 1, $user->id, 'LIST_PRODUCTS', 'Successfully listed product with id ' . $response->getRequestParameter('id'));
// Return the product
$response->success(
parseProduct(
(new products_o())->select((int)self::getParameter('id'))->asArray()
)
);
}
// Check if the category is set in the request
$data = $_GET ?? [];
// Check if the category is set
+9
View File
@@ -39,6 +39,15 @@ trait route_t
return true;
}
public function requireDateFormat(string $date, string $format): void
{
global $response;
$d = \DateTime::createFromFormat($format, $date);
if (!$d || $d->format($format) !== $date) {
$response->error('Invalid date format. Expected: ' . $format . ' Got: ' . $date, 400);
}
}
public function requireMinValue(int $value, int $min): void
{
global $response;