Merge pull request #1

Development
This commit is contained in:
Jeppe B
2024-12-20 12:27:56 +01:00
committed by GitHub
20 changed files with 1230 additions and 332 deletions
+6
View File
@@ -21,6 +21,12 @@ class object_property
$this->default = $default;
}
public function __toString(): string
{
// Return the value of the field in the database table
return $this->value();
}
/**
* Get the value of the field in the database table
* @return mixed The value of the field in the database table
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* Cron job, ran every minute.
*/
$now = time();
// Log the time of the cron job
file_put_contents(__DIR__ . '/cron.log', date('Y-m-d H:i:s', $now) . ' - Cron job started' . PHP_EOL, FILE_APPEND);
// Include the required files
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/config.php';
// Set the .htaccess file
$htaccess = "
# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php80” package as the default “PHP” programming language.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
<IfModule mime_module>
AddHandler application/x-httpd-ea-php80 .php .php8 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit
";
// Write the .htaccess file (This is not really ideal, but it works for now. This is because the .htaccess file is changed by cPanel, and it's not going to be kept there anyway.)
file_put_contents(__DIR__ . '/.htaccess', $htaccess);
// Get the current time
$now = time();
// Log the time of the cron job
file_put_contents(__DIR__ . '/cron.log', date('Y-m-d H:i:s', $now) . ' - Cron job executed in ' . (time() - $now) . ' seconds ( ' . (microtime(true) - $now) . 'ms )' . PHP_EOL, FILE_APPEND);
@@ -9,13 +9,6 @@ class economic_invoice_draft_mo extends economicInvoicesDrafts
protected float $payment_terms_number; // Payment terms number of the invoice
protected array $recipient; // Recipient of the invoice (Includes name, address, zip, city, and (array)vatZone)
protected array $lines; // Lines of the invoice (Includes product, quantity, unitNetPrice, discountPercentage, and (array)vatRate)
public function createInvoiceDraft(array $data): object
{
// Create a draft invoice
$url = '/invoices/drafts';
$response = $this->send_request($url, 'POST', json_encode($data));
return json_decode($response);
}
public function addLine(string $productNumber, string $description, float $quantity, float $unitNetPrice, float $discountPercentage): void
{
@@ -36,17 +29,10 @@ class economic_invoice_draft_mo extends economicInvoicesDrafts
{
// Add a line to the invoice
$this->lines[] = [
'product' => [
'productNumber' => '81234',
],
'description' => $text,
'quantity' => 1,
'unitNetPrice' => 0,
'discountPercentage' => 0,
'description' => (string)$text,
];
}
// Example of a method that uses the createInvoiceDraft method
public function createInvoiceDraftExample(): object
{
$data = [
@@ -75,6 +61,16 @@ class economic_invoice_draft_mo extends economicInvoicesDrafts
return $this->createInvoiceDraft($data);
}
// Example of a method that uses the createInvoiceDraft method
public function createInvoiceDraft(array $data): object
{
// Create a draft invoice
$url = '/invoices/drafts';
$response = $this->send_request($url, 'POST', json_encode($data));
return json_decode($response);
}
public function setCustomerNumber(int $customer_number): economic_invoice_draft_mo
{
$this->customer_number = $customer_number;
+128
View File
@@ -0,0 +1,128 @@
<?php
namespace objects;
use classes\db;
use classes\object_property;
use classes\response;
use traits\db_object_t;
class bookings_o extends db
{
use db_object_t;
public object_property $customer_number;
public object_property $wash_type;
public object_property $contact_email;
public object_property $reference_number;
public object_property $regNrTraekker;
public object_property $regNrTrailer;
public object_property $washCertificateEmail;
public object_property $date;
public object_property $department;
public object_property $pickup_bool;
public object_property $notes;
public object_property $washCertificateStatus;
public object_property $washCertificateUrl;
public object_property $status;
public function structure(): void
{
$this->setTable('bookings');
}
public function add(int $customer_number, string $wash_type, string $contact_email, string $reference_number, string $regNrTraekker, string $regNrTrailer, string $washCertificateEmail, string $date, string $department, int $pickup_bool, string $notes, string $washCertificateStatus, string $washCertificateUrl, string $status): void
{
global $db;
// Avoid SQL injection
$wash_type = $db->escape_string($wash_type);
$contact_email = $db->escape_string($contact_email);
$reference_number = $db->escape_string($reference_number);
$regNrTraekker = $db->escape_string($regNrTraekker);
$regNrTrailer = $db->escape_string($regNrTrailer);
$washCertificateEmail = $db->escape_string($washCertificateEmail);
$date = $db->escape_string($date);
// Parse the department name to id
$department = $this->getDepartmentIdByLegacyName($department);
$notes = $db->escape_string($notes);
$washCertificateStatus = $db->escape_string($washCertificateStatus);
$washCertificateUrl = $db->escape_string($washCertificateUrl);
$status = $db->escape_string($status);
// Create a new record in the database ( Replace the code, if an entry already exists )
$sql = "INSERT INTO $this->table (customer_number, wash_type, contact_email, reference_number, regNrTraekker, regNrTrailer, washCertificateEmail, date, department, pickup_bool, notes, washCertificateStatus, washCertificateUrl, status) VALUES ($customer_number, '$wash_type', '$contact_email', '$reference_number', '$regNrTraekker', '$regNrTrailer', '$washCertificateEmail', '$date', '$department', $pickup_bool, '$notes', '$washCertificateStatus', '$washCertificateUrl', '$status')";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
}
public function getDepartmentIdByLegacyName(string $departmentName): int
{
// Get the department id by the legacy name
$departmentLegacyNames = [
'køge' => 4,
'taastrup' => 2,
'aarhusc' => 5,
'roskilde' => 6,
'hvidovre' => 1,
'glostrup' => 3,
];
return $departmentLegacyNames[strtolower($departmentName)] ?? 0;
}
public function addOrUpdate($id, $customer_number, $wash_type, $contact_email, $reference_number, $regNrTraekker, $regNrTrailer, $washCertificateEmail, $date, $department, $pickup_bool, $notes, $washCertificateStatus, $washCertificateUrl, $status): void
{
global $db;
// Avoid SQL injection
$wash_type = $db->escape_string($wash_type);
$contact_email = $db->escape_string($contact_email);
$reference_number = $db->escape_string($reference_number);
$regNrTraekker = $db->escape_string($regNrTraekker);
$regNrTrailer = $db->escape_string($regNrTrailer);
$washCertificateEmail = $db->escape_string($washCertificateEmail);
$date = $db->escape_string($date);
// Parse the department name to id
$department = $this->getDepartmentIdByLegacyName($department);
$notes = $db->escape_string($notes);
$washCertificateStatus = $db->escape_string($washCertificateStatus);
$washCertificateUrl = $db->escape_string($washCertificateUrl);
$status = $db->escape_string($status);
// Create a new record in the database ( Replace the code, if an entry already exists )
$sql = "INSERT INTO $this->table (id, customer_number, wash_type, contact_email, reference_number, regNrTraekker, regNrTrailer, washCertificateEmail, date, department, pickup_bool, notes, washCertificateStatus, washCertificateUrl, status) VALUES ($id, $customer_number, '$wash_type', '$contact_email', '$reference_number', '$regNrTraekker', '$regNrTrailer', '$washCertificateEmail', '$date', '$department', $pickup_bool, '$notes', '$washCertificateStatus', '$washCertificateUrl', '$status') ON DUPLICATE KEY UPDATE customer_number = $customer_number, wash_type = '$wash_type', contact_email = '$contact_email', reference_number = '$reference_number', regNrTraekker = '$regNrTraekker', regNrTrailer = '$regNrTrailer', washCertificateEmail = '$washCertificateEmail', date = '$date', department = '$department', pickup_bool = $pickup_bool, notes = '$notes', washCertificateStatus = '$washCertificateStatus', washCertificateUrl = '$washCertificateUrl', status = '$status'";
$db->query($sql);
}
public function getObjectProperties(): void
{
$this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'int', true);
$this->wash_type = new object_property($this->table, $this->id, 'wash_type', 'string', true);
$this->contact_email = new object_property($this->table, $this->id, 'contact_email', 'string', true);
$this->reference_number = new object_property($this->table, $this->id, 'reference_number', 'string', true);
$this->regNrTraekker = new object_property($this->table, $this->id, 'regNrTraekker', 'string', true);
$this->regNrTrailer = new object_property($this->table, $this->id, 'regNrTrailer', 'string', true);
$this->washCertificateEmail = new object_property($this->table, $this->id, 'washCertificateEmail', 'string', true);
$this->date = new object_property($this->table, $this->id, 'date', 'string', true);
$this->department = new object_property($this->table, $this->id, 'department', 'string', true);
$this->pickup_bool = new object_property($this->table, $this->id, 'pickup_bool', 'int', true);
$this->notes = new object_property($this->table, $this->id, 'notes', 'string', true);
$this->washCertificateStatus = new object_property($this->table, $this->id, 'washCertificateStatus', 'string', true);
$this->washCertificateUrl = new object_property($this->table, $this->id, 'washCertificateUrl', 'string', true);
$this->status = new object_property($this->table, $this->id, 'status', 'string', true);
}
public function getCustomerBookingsPaginated(int $customer_number, int $page = 1, int $limit = 10, string $order = 'DESC'): array
{
global /** @var response $response */
$db, $response;
$sql = "SELECT * FROM $this->table WHERE customer_number = $customer_number ORDER BY id $order LIMIT $limit OFFSET " . ($page - 1) * $limit;
$result = $db->query($sql);
$array = $db->fetch_all($result);
// Add the metadata
$sql = "SELECT COUNT(*) as count FROM $this->table WHERE customer_number = $customer_number";
$result = $db->query($sql);
$row = $db->fetch_assoc($result);
$total = $row['count'];
$response->paginate($page, $limit, $total);
return $array;
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
namespace objects;
use classes\db;
use classes\object_property;
use traits\db_object_t;
class customer_codes_o extends db
{
use db_object_t;
public object_property $user_id;
public object_property $code;
public function structure(): void
{
$this->setTable('customer_codes');
}
public function getObjectProperties(): void
{
$this->user_id = new object_property($this->table, $this->id, 'user_id', 'int', true);
$this->code = new object_property($this->table, $this->id, 'code', 'string', true);
}
public function set(int $user_id, string|null $code): customer_codes_o
{
global $db, $response;
try {
// Avoid SQL injection
if (!is_null($code)) {
$code = $db->escape_string($code);
}
// Create a new record in the database ( Replace the code, if an entry already exists )
$sql = "INSERT INTO $this->table (user_id, code) VALUES ($user_id, '$code') ON DUPLICATE KEY UPDATE code = '$code'";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
// Set the values of the object properties
$this->getObjectProperties();
} catch (\Exception $e) {
$response->error($e->getMessage());
}
return $this;
}
public function getCode(int $user_id): customer_codes_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE user_id = $user_id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $user_id;
$this->getObjectProperties();
} else {
$this->set($user_id, null);
}
return $this;
}
public function setCode(int $id, mixed $code): customer_codes_o
{
global $db, $response;
try {
// Avoid SQL injection
$code = $db->escape_string($code);
// Update the record in the database
$sql = "UPDATE $this->table SET code = '$code' WHERE user_id = $id";
$db->query($sql);
// Set the values of the object properties
$this->id = $id;
$this->getObjectProperties();
} catch (\Exception $e) {
$response->error($e->getMessage());
}
return $this;
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ use traits\db_object_t;
class departments_o extends db
{
use db_object_t;
public object_property $name;
public object_property $description;
@@ -17,12 +18,6 @@ class departments_o extends db
$this->setTable('departments');
}
public function getObjectProperties(): void
{
$this->name = new object_property($this->table, $this->id, 'name', 'string', true);
$this->description = new object_property($this->table, $this->id, 'description', 'string', false);
}
public function create(string $name, string $description): void
{
global $db;
@@ -40,6 +35,12 @@ class departments_o extends db
$this->getObjectProperties();
}
public function getObjectProperties(): void
{
$this->name = new object_property($this->table, $this->id, 'name', 'string', true);
$this->description = new object_property($this->table, $this->id, 'description', 'string', false);
}
public function edit(int $id, string $name, string $description): void
{
global $db;
+70 -17
View File
@@ -9,28 +9,48 @@ use traits\db_object_t;
class order_items_o extends db
{
use db_object_t;
/**
* The associated order id
* @var object_property
*/
public object_property $order_id;
/**
* The associated product id
* @var object_property
*/
public object_property $product_id;
/**
* The text reference assigned to the product at the time of the order
* @var object_property
*/
public object_property $reference;
/**
* The notes added to the order item
* @var object_property
*/
public object_property $notes;
/**
* The cashier (id) who added the item to the order
* @var object_property
*/
public object_property $cashier_id;
/**
* The price of the product at the time of the order
* @var object_property
*/
public object_property $price;
/**
* The quantity of the product ordered
* @var object_property
*/
public object_property $quantity;
public function structure(): void
{
$this->setTable('order_items');
}
public function getObjectProperties(): void
{
$this->order_id = new object_property($this->table, $this->id, 'order_id', 'int', true);
$this->product_id = new object_property($this->table, $this->id, 'product_id', 'int', true);
$this->reference = new object_property($this->table, $this->id, 'reference', 'string', true);
$this->notes = new object_property($this->table, $this->id, 'notes', 'string', false);
$this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true);
$this->price = new object_property($this->table, $this->id, 'price', 'int', true);
}
public function getOrderItemById(int $id): order_items_o
{
global $db;
@@ -44,7 +64,18 @@ class order_items_o extends db
return $this;
}
public function add(int $order_id, int $product_id, string $reference, string $notes, int $cashier_id, int $price): void
public function getObjectProperties(): void
{
$this->order_id = new object_property($this->table, $this->id, 'order_id', 'int', true);
$this->product_id = new object_property($this->table, $this->id, 'product_id', 'int', true);
$this->reference = new object_property($this->table, $this->id, 'reference', 'string', true);
$this->notes = new object_property($this->table, $this->id, 'notes', 'string', false);
$this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true);
$this->price = new object_property($this->table, $this->id, 'price', 'int', true);
$this->quantity = new object_property($this->table, $this->id, 'quantity', 'int', true);
}
public function add(int $order_id, int $product_id, string $reference, string $notes, int $cashier_id, int $price, int $quantity): void
{
global $db, $response;
try {
@@ -52,7 +83,7 @@ class order_items_o extends db
$reference = $db->escape_string($reference);
$notes = $db->escape_string($notes);
// Create a new record in the database
$sql = "INSERT INTO $this->table (order_id, product_id, reference, notes, cashier_id, price) VALUES ($order_id, $product_id, '$reference', '$notes', $cashier_id, $price)";
$sql = "INSERT INTO $this->table (order_id, product_id, reference, notes, cashier_id, price, quantity) VALUES ($order_id, $product_id, '$reference', '$notes', $cashier_id, $price, $quantity)";
$db->query($sql);
// Get the id of the new record
@@ -65,7 +96,7 @@ class order_items_o extends db
}
}
public function edit(int $id, int $order_id, int $product_id, string $reference, string $notes, int $cashier_id, int $price): void
public function edit(int $id, int $order_id, int $product_id, string $reference, string $notes, int $cashier_id, int $price, int $quantity): void
{
global $db, $response;
$this->id = $id;
@@ -74,7 +105,7 @@ class order_items_o extends db
$reference = $db->escape_string($reference);
$notes = $db->escape_string($notes);
// Update the record in the database
$sql = "UPDATE $this->table SET order_id = $order_id, product_id = $product_id, reference = '$reference', notes = '$notes', cashier_id = $cashier_id, price = $price WHERE id = $this->id";
$sql = "UPDATE $this->table SET order_id = $order_id, product_id = $product_id, reference = '$reference', notes = '$notes', cashier_id = $cashier_id, price = $price, quantity = $quantity WHERE id = $this->id";
$db->query($sql);
// Set the values of the object properties
@@ -84,7 +115,7 @@ class order_items_o extends db
}
}
public function addItemToOrder(int $order_id, int $product_id, int $cashier_id): void
public function addItemToOrder(int $order_id, int $product_id, int $cashier_id, int $quantity): void
{
global $db, $response;
try {
@@ -95,7 +126,7 @@ class order_items_o extends db
$price = $row['price'];
// Create a new record in the database
$sql = "INSERT INTO $this->table (order_id, product_id, price, cashier_id) VALUES ($order_id, $product_id, $price, $cashier_id)";
$sql = "INSERT INTO $this->table (order_id, product_id, price, cashier_id, quantity) VALUES ($order_id, $product_id, $price, $cashier_id, $quantity)";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
@@ -106,8 +137,10 @@ class order_items_o extends db
}
}
public function removeOrderItem(int $id): void
{
// TODO: Implement delete() method instead
global $db;
$this->id = $id;
$sql = "DELETE FROM $this->table WHERE id = $this->id";
@@ -124,6 +157,7 @@ class order_items_o extends db
'notes' => (string)$this->notes->value(),
'cashier_id' => (int)$this->cashier_id->value(),
'price' => (int)$this->price->value(),
'quantity' => (int)$this->quantity->value(),
'product' => (array)(new products_o())->getProductById($this->product_id->value())->asArray(),
'cashier' => (array)(new users_o())->getUserById($this->cashier_id->value())->asArray()
];
@@ -132,7 +166,7 @@ class order_items_o extends db
public function getAllItemsAsArray(int $orderId): array
{
global $db;
$sql = "SELECT * FROM $this->table WHERE order_id = $orderId";
$sql = "SELECT * FROM $this->table WHERE order_id = $orderId AND deleted_at IS NULL";
$result = $db->query($sql);
// Circumvent the repeated instantiation of the object, by just selecting the fields
$items = [];
@@ -143,4 +177,23 @@ class order_items_o extends db
}
return $items;
}
public function updateOrderItem(int $id, int $price, string $notes, string $reference, int $quantity): void
{
global $db, $response;
$this->id = $id;
try {
// Avoid SQL injection
$price = $db->escape_string($price);
$notes = $db->escape_string($notes);
$reference = $db->escape_string($reference);
// Update the record in the database
$sql = "UPDATE $this->table SET price = $price, notes = '$notes', reference = '$reference', quantity = $quantity WHERE id = $this->id";
$db->query($sql);
// Set the values of the object properties
$this->getObjectProperties();
} catch (\Exception $e) {
$response->error($e->getMessage());
}
}
}
+74 -46
View File
@@ -10,6 +10,7 @@ use traits\db_object_t;
class orders_o extends db
{
use db_object_t;
public object_property $customer_id;
public object_property $cashier_id;
public object_property $reference;
@@ -20,12 +21,26 @@ class orders_o extends db
public object_property $reg_3;
public economic_module_orders $economic_module_orders;
public object_property $created_at;
public object_property $deleted_at;
public function structure(): void
{
$this->setTable('orders');
}
public function getOrderById(int $id): orders_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $id;
$this->getObjectProperties();
}
return $this;
}
public function getObjectProperties(): void
{
$this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true);
@@ -38,19 +53,7 @@ class orders_o extends db
$this->reg_3 = new object_property($this->table, $this->id, 'reg_3', 'string', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
$this->economic_module_orders = (new economic_module_orders())->getByOrderId($this->id);
}
public function getOrderById(int $id): orders_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $id;
$this->getObjectProperties();
}
return $this;
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
}
public function add(int $customer_id, int $cashier_id, string $reference, string $notes, int $department_id, string $reg_1 = '', string $reg_2 = '', string $reg_3 = ''): orders_o
@@ -98,37 +101,6 @@ class orders_o extends db
}
}
public function getOrderItems(int $order_id): array
{
global $db;
$sql = "SELECT * FROM order_items WHERE order_id = $order_id";
$result = $db->query($sql);
$order_items = [];
if ($result->num_rows > 0 && $result) {
while ($row = $result->fetch_assoc()) {
$order_item = new order_items_o();
$order_items[] = $order_item->getOrderItemById($row['id'])->getItemAsArray();
}
}
return $order_items;
}
public function asArray(): array
{
return [
'id' => $this->id,
'customer_id' => $this->customer_id->value(),
'cashier_id' => $this->cashier_id->value(),
'reference' => $this->reference->value(),
'notes' => $this->notes->value(),
'department_id' => $this->department_id->value(),
'reg_1' => $this->reg_1->value(),
'reg_2' => $this->reg_2->value(),
'reg_3' => $this->reg_3->value(),
'created_at' => $this->created_at->value(),
];
}
public function includeIncludes(): orders_o
{
global /** @var response $response */
@@ -157,6 +129,38 @@ class orders_o extends db
return $this;
}
public function getOrderItems(int $order_id): array
{
global $db;
$sql = "SELECT * FROM order_items WHERE order_id = $order_id";
$result = $db->query($sql);
$order_items = [];
if ($result->num_rows > 0 && $result) {
while ($row = $result->fetch_assoc()) {
$order_item = new order_items_o();
$order_items[] = $order_item->getOrderItemById($row['id'])->getItemAsArray();
}
}
return $order_items;
}
public function asArray(): array
{
return [
'id' => $this->id,
'customer_id' => $this->customer_id->value(),
'cashier_id' => $this->cashier_id->value(),
'reference' => $this->reference->value(),
'notes' => $this->notes->value(),
'department_id' => $this->department_id->value(),
'reg_1' => $this->reg_1->value(),
'reg_2' => $this->reg_2->value(),
'reg_3' => $this->reg_3->value(),
'created_at' => $this->created_at->value(),
'deleted_at' => $this->deleted_at->value(),
];
}
public function getCustomerByOrderId(?string $order_id): users_o
{
global $db;
@@ -173,11 +177,11 @@ class orders_o extends db
{
global /** @var response $response */
$db, $response;
$sql = "SELECT * FROM $this->table WHERE customer_id = $customer_number ORDER BY id $order LIMIT $limit OFFSET " . ($page - 1) * $limit;
$sql = "SELECT * FROM $this->table WHERE customer_id = $customer_number AND deleted_at IS NULL ORDER BY id $order LIMIT $limit OFFSET " . ($page - 1) * $limit;
$result = $db->query($sql);
$array = $db->fetch_all($result);
// Add the metadata
$sql = "SELECT COUNT(*) as count FROM $this->table WHERE customer_id = $customer_number";
$sql = "SELECT COUNT(*) as count FROM $this->table WHERE customer_id = $customer_number AND deleted_at IS NULL";
$result = $db->query($sql);
$row = $db->fetch_assoc($result);
$total = $row['count'];
@@ -189,4 +193,28 @@ class orders_o extends db
{
return (new departments_o())->getDepartmentById($this->department_id->value());
}
public function delete(): void
{
// Set the deleted_at property to the current timestamp
$this->deleted_at->set(date('Y-m-d H:i:s'));
// Save the object
}
public function restore(): void
{
// Set the deleted_at property to null
$this->deleted_at->set(null);
// Save the object
}
public function exists(): bool
{
// Check if the id is greater than 0, and that the deleted_at property is null
if ($this->id > 0) {
$this->getObjectProperties();
return $this->deleted_at->value() === null;
}
return false;
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
namespace objects;
use classes\db;
use classes\object_property;
use traits\db_object_t;
class user_key_value_pairs_o extends db
{
use db_object_t;
public int $user_id;
public object_property $var;
public object_property $val;
public function structure(): void
{
$this->setTable('user_key_value_pairs');
}
public function getObjectProperties(): void
{
$this->var = new object_property($this->table, $this->id, 'var', 'string', true);
$this->val = new object_property($this->table, $this->id, 'val', 'mixed', true);
}
public function setUser($user_id): user_key_value_pairs_o
{
$this->user_id = $user_id;
return $this;
}
public function getValue($var): mixed
{
global $db;
// Avoid SQL injection
$var = $db->escape_string($var);
// Get the record from the database
$sql = "SELECT val FROM $this->table WHERE user_id = $this->user_id AND var = '$var'";
$result = $db->query($sql);
if ($result->num_rows > 0) {
return $db->fetch_assoc($result)['val'];
}
return null;
}
public function setValue($var, $val): user_key_value_pairs_o
{
global $db;
// Avoid SQL injection
$var = $db->escape_string($var);
$val = $db->escape_string($val);
// Check if the value exists in the database
$exists = $this->getValue($var);
// Create a new record in the database if it doesn't exist
if ($exists) {
$sql = "UPDATE $this->table SET val = '$val' WHERE user_id = $this->user_id AND var = '$var'";
} else {
$sql = "INSERT INTO $this->table (user_id, var, val) VALUES ($this->user_id, '$var', '$val')";
}
$db->query($sql);
return $this;
}
public function deleteValue($var): user_key_value_pairs_o
{
global $db;
// Avoid SQL injection
$var = $db->escape_string($var);
// Create a new record in the database
$sql = "DELETE FROM $this->table WHERE user_id = $this->user_id AND var = '$var'";
$db->query($sql);
return $this;
}
}
+208 -166
View File
@@ -12,76 +12,23 @@ use traits\db_object_t;
class users_o extends db
{
use db_object_t;
public object_property $customer_number;
public object_property $display_name;
public object_property $password;
public object_property $group_id;
public economic_customer_mo $economic_customer;
public object_property $created_at;
public object_property $updated_at;
public array $permissions;
public customer_codes_o $customer_codes;
public user_key_value_pairs_o $keys;
public function structure(): void
{
$this->setTable('users');
}
public function getObjectProperties(): void
{
$this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'string', true);
$this->password = new object_property($this->table, $this->id, 'password', 'string', true);
$this->group_id = new object_property($this->table, $this->id, 'group_id', 'int', true);
$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 getUserByCustomerNumber(int $customer_number): users_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE customer_number = '$customer_number'";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $result->fetch_assoc()['id'];
$this->getObjectProperties();
} else {
// Import the customer
$this->importCustomerFromExternalSource($customer_number);
}
return $this;
}
public function getUserById(int $id): users_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $id;
$this->getObjectProperties();
}
return $this;
}
public function add(string $customer_number, mixed $password): void
{
global $db;
// Avoid SQL injection
$customer_number = $db->escape_string($customer_number);
// Hash the password
$password = password_hash($password, PASSWORD_DEFAULT);
$password = $db->escape_string($password);
// Create a new record in the database
$sql = "INSERT INTO $this->table (customer_number, password) VALUES ('$customer_number', '$password')";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
// Set the values of the object properties
$this->getObjectProperties();
}
public function hasPermission(string $permission): bool
{
global $db;
@@ -100,7 +47,7 @@ class users_o extends db
return false;
}
public function edit(int $id, string $customer_number, string|null $role, string|null $password): void
public function edit(int $id, string $customer_number, string|null $role, string|null $password, string|null $display_name): void
{
global $db;
$this->id = $id;
@@ -114,6 +61,9 @@ class users_o extends db
if ($role !== null) {
$role = $db->escape_string($role);
}
if ($display_name !== null) {
$display_name = $db->escape_string($display_name);
}
// Update the record in the database
$sql = "UPDATE $this->table SET customer_number = '$customer_number'";
if ($password !== null) {
@@ -122,6 +72,9 @@ class users_o extends db
if ($role !== null) {
$sql .= ", group_id = '$role'";
}
if ($display_name !== null) {
$sql .= ", display_name = '$display_name'";
}
$sql .= " WHERE id = $this->id";
$db->query($sql);
@@ -129,6 +82,17 @@ class users_o extends db
$this->getObjectProperties();
}
public function getObjectProperties(): void
{
$this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'string', true);
$this->display_name = new object_property($this->table, $this->id, 'display_name', 'string', false);
$this->password = new object_property($this->table, $this->id, 'password', 'string', true);
$this->group_id = new object_property($this->table, $this->id, 'group_id', 'int', true);
$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->keys = (new user_key_value_pairs_o())->setUser($this->id);
}
public function getCustomerByIdOrCustomerNumber(int $idOrCustomerNumber): users_o
{
global $db;
@@ -145,87 +109,6 @@ class users_o extends db
return $this;
}
public function automaticGetTargetUserFromRequest(): users_o
{
// Get the data from the request
if ($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'DELETE') {
$data = $_GET;
} else {
$data = json_decode(file_get_contents('php://input'), true);
}
// Check if the user id is set in the request
if (isset($data['user_id'])) {
return $this->getUserById((int)$data['user_id']);
} elseif (isset($data['customer_number'])) {
return $this->getUserByCustomerNumber($data['customer_number']);
} else {
return $this;
}
}
public function asArray(): array
{
$array = [
'id' => (int)$this->id,
'customer_number' => (int)$this->customer_number->value(),
'group_id' => (int)$this->group_id->value(),
'created_at' => $this->created_at->value(),
'updated_at' => $this->updated_at->value(),
];
// If the economic customer data is set, add it to the array
if (isset($this->economic_customer)) {
$array['economic_customer'] = $this->economic_customer->asArray();
}
// If the permissions are set, add them to the array
if (isset($this->permissions)) {
$array['permissions'] = $this->permissions;
}
return $array;
}
public function getNotes():array
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Get the customer notes
return $customer_notes->getCustomerNotesAsArray($this->id);
}
public function addNote($customer_id, $note, $cashier_id): void
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Add the note
$customer_notes->add($customer_id, $note, $cashier_id);
}
public function deleteNote(int $note_id): void
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Delete the note
$customer_notes->delete($note_id);
}
public function getOrImportCustomerByCustomerNumber(int $customer_number): object|bool
{
global $db;
// Check if the customer exists
$sql = "SELECT * FROM $this->table WHERE customer_number = $customer_number";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $result->fetch_assoc()['id'];
$this->getObjectProperties();
} else {
// Import the customer
return $this->importCustomerFromExternalSource($customer_number);
}
return $this;
}
private function importCustomerFromExternalSource(int $customer_number): object|bool
{
global $db;
@@ -249,16 +132,134 @@ class users_o extends db
return false;
}
public function getCustomerEcocomicData(int $customer_number = null): users_o
public function automaticGetTargetUserFromRequest(): users_o
{
// Get the customer data from the external source
$economic = new economicCustomers();
// Check if the customer number is set
if (!isset($this->customer_number) && $customer_number === null) {
// Get the data from the request
if ($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'DELETE') {
$data = $_GET;
} else {
$data = json_decode(file_get_contents('php://input'), true);
}
// Check if the user id is set in the request
if (isset($data['user_id'])) {
return $this->getUserById((int)$data['user_id']);
} elseif (isset($data['customer_number'])) {
return $this->getUserByCustomerNumber($data['customer_number']);
} else {
return $this;
}
$customer_number = $customer_number ?? $this->customer_number->value();
$this->economic_customer = (new economic_customer_mo())->getCustomerByCustomerNumber($customer_number);
}
public function getUserById(int $id): users_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $id;
$this->getObjectProperties();
}
return $this;
}
public function getUserByCustomerNumber(int $customer_number): users_o
{
global $db;
// Get the record from the database
$sql = "SELECT * FROM $this->table WHERE customer_number = '$customer_number'";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $result->fetch_assoc()['id'];
$this->getObjectProperties();
} else {
// Import the customer
$this->importCustomerFromExternalSource($customer_number);
}
return $this;
}
public function asArray(): array
{
$array = [
'id' => (int)$this->id,
'customer_number' => (int)$this->customer_number->value(),
'display_name' => $this->display_name->value(),
'group_id' => (int)$this->group_id->value(),
'created_at' => $this->created_at->value(),
'updated_at' => $this->updated_at->value(),
];
// If the economic customer data is set, add it to the array
if (isset($this->economic_customer)) {
$array['economic_customer'] = $this->economic_customer->asArray();
}
// If the permissions are set, add them to the array
if (isset($this->permissions)) {
$array['permissions'] = $this->permissions;
}
return $array;
}
public function getNotes(): array
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Get the customer notes
return $customer_notes->getCustomerNotesAsArray($this->id);
}
public function addNote($customer_id, $note, $cashier_id): void
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Add the note
$customer_notes->add($customer_id, $note, $cashier_id);
}
public function add(string $customer_number, mixed $password, int $role = 0): void
{
global $db;
// Avoid SQL injection
$customer_number = $db->escape_string($customer_number);
$role = $db->escape_string($role);
// Hash the password
$password = password_hash($password, PASSWORD_DEFAULT);
$password = $db->escape_string($password);
// Create a new record in the database
$sql = "INSERT INTO $this->table (customer_number, password, group_id) VALUES ('$customer_number', '$password', $role)";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
// Set the values of the object properties
$this->getObjectProperties();
}
public function deleteNote(int $note_id): void
{
global $db;
// Create the customer notes object
$customer_notes = new customer_notes_o();
// Delete the note
$customer_notes->delete($note_id);
}
public function getOrImportCustomerByCustomerNumber(int $customer_number): object|bool
{
global $db;
// Check if the customer exists
$sql = "SELECT * FROM $this->table WHERE customer_number = $customer_number";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$this->id = $result->fetch_assoc()['id'];
$this->getObjectProperties();
} else {
// Import the customer
return $this->importCustomerFromExternalSource($customer_number);
}
return $this;
}
@@ -273,21 +274,6 @@ class users_o extends db
return $db->fetch_all($result);
}
public function doesUserHaveAttribute(string $attribute, int $user_id = null): bool
{
global $db;
if ($user_id === null) {
$user_id = $this->id;
}
$attribute = $db->escape_string($attribute);
$sql = "SELECT * FROM maintenancemode_dbtest.customer_attributes WHERE user_id = $user_id AND attribute = '$attribute'";
$result = $db->query($sql);
if ($result->num_rows > 0) {
return true;
}
return false;
}
public function addAttribute(string $attribute, int $user_id = null): void
{
global $db;
@@ -295,10 +281,8 @@ class users_o extends db
$user_id = $this->id;
}
$attribute = $db->escape_string($attribute);
// Make sure the attribute does not already exist
if ($this->doesUserHaveAttribute((string)$attribute, (int)$user_id)) {
return;
}
// To prevent two attributes with the same name for the same user, we will delete the old one if it exists
$this->deleteAttribute($attribute, $user_id);
$sql = "INSERT INTO maintenancemode_dbtest.customer_attributes (user_id, attribute) VALUES ($user_id, '$attribute')";
$db->query($sql);
}
@@ -314,15 +298,44 @@ class users_o extends db
if (!$this->doesUserHaveAttribute((string)$attribute, (int)$user_id)) {
return;
}
$sql = "DELETE FROM maintenancemode_dbtest.customer_attributes WHERE user_id = $user_id AND attribute = '$attribute'";
// If the attribute exists, delete it, if it does not exist, nothing will happen
$sql = "DELETE FROM maintenancemode_dbtest.customer_attributes WHERE user_id = $user_id AND attribute = '$attribute' LIMIT 1";
$db->query($sql);
}
public function doesUserHaveAttribute(string $attribute, int $user_id = null): bool
{
global $db;
if ($user_id === null) {
$user_id = $this->id;
}
$attribute = $db->escape_string($attribute);
$sql = "SELECT * FROM maintenancemode_dbtest.customer_attributes WHERE user_id = $user_id AND attribute = '$attribute' LIMIT 1";
$result = $db->query($sql);
if ($result->num_rows > 0) {
return true;
}
return false;
}
/**
* If the customer requires a reference number for each order
* @return bool
*/
public function requiresReference(): bool
{
return $this->doesUserHaveAttribute('requiresReferenceNumber');
}
/**
* If the customer should have an invoice per order (Otherwise, they will have a monthly invoice for all orders)
* @return bool
*/
public function invoicePerOrder(): bool
{
return $this->doesUserHaveAttribute('invoiceAllOrdersIndividually');
}
public function includeIncludes(array $includes = []): users_o
{
global /** @var response $response */
@@ -343,6 +356,19 @@ class users_o extends db
return $this;
}
public function getCustomerEcocomicData(int $customer_number = null): users_o
{
// Get the customer data from the external source
$economic = new economicCustomers();
// Check if the customer number is set
if (!isset($this->customer_number) && $customer_number === null) {
return $this;
}
$customer_number = $customer_number ?? $this->customer_number->value();
$this->economic_customer = (new economic_customer_mo())->getCustomerByCustomerNumber($customer_number);
return $this;
}
private function getPermissions(): void
{
global $db;
@@ -354,4 +380,20 @@ class users_o extends db
}
$this->permissions = $perms;
}
public function getCode(): string|null
{
// Get the customer code
$this->customer_codes = new customer_codes_o();
$this->customer_codes->getCode($this->id);
return $this->customer_codes->code->value();
}
public function setCode(mixed $code): customer_codes_o
{
// Set the customer code
$this->customer_codes = new customer_codes_o();
return $this->customer_codes->setCode($this->id, $code);
}
}
+8 -6
View File
@@ -3,10 +3,8 @@
namespace routes;
use classes\authentication;
use classes\encrypt;
use objects\logs_o;
use objects\tokens_o;
use objects\users_o;
use traits\route_t;
class authRoute
@@ -20,8 +18,12 @@ class authRoute
global $response;
$data = json_decode(file_get_contents('php://input'), true);
// Check if the customer number, and password are set
if (!isset($data['customer_number'])) { $response->error('Customer number is required', 400); }
if (!isset($data['password'])) { $response->error('Password is required', 400); }
if (!isset($data['customer_number'])) {
$response->error('Customer number is required', 400);
}
if (!isset($data['password'])) {
$response->error('Password is required', 400);
}
// Try to log the user in
$isCredentialsValid = (new authentication())->authenticate($data['customer_number'], $data['password']);
// Log the incident
@@ -40,7 +42,7 @@ class authRoute
$this->get('/auth/logout', function () {
// Get the token from the headers
global $response;
$token = $_SERVER['HTTP_AUTHORIZATION'];
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
// Remove the Bearer prefix
$token = str_replace('Bearer ', '', $token);
// Check if the token is valid
@@ -56,7 +58,7 @@ class authRoute
$this->get('/auth/session', function () {
// Get the token from the headers
global $response;
$token = $_SERVER['HTTP_AUTHORIZATION'];
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; // Default to empty string if not set
// Remove the Bearer prefix
$token = str_replace('Bearer ', '', $token);
// Check if the token is valid
+116
View File
@@ -0,0 +1,116 @@
<?php
namespace routes;
use classes\authentication;
use classes\response;
use objects\bookings_o;
use objects\logs_o;
use traits\route_t;
class bookingsRoute
{
use route_t;
public function run(): void
{
/** All bookings */
$this->get('/bookings', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('list_bookings');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'LIST_BOOKINGS', 'Successfully listed bookings');
// Return the list of bookings
$response->success(
(new bookings_o())->listObjectsWithPaginationIfSet()
);
} else {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'LIST_BOOKINGS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
/** Own bookings */
$this->get('/user/bookings', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('list_own_bookings');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'LIST_OWN_BOOKINGS', 'Successfully listed own bookings');
// Return the list of departments
$response->success(
(new bookings_o())->getCustomerBookingsPaginated(
$user->customer_number->value(),
($this->fromRequest('page') ?? 1),
($this->fromRequest('limit') ?? 10),
($this->fromRequest('order') ?? 'DESC')
)
);
} else {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'LIST_OWN_BOOKINGS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
// Synchronize booking from the external system
$this->post('/admin/bookings/sync', function () {
// Require the user to be logged in
global $response;
if ($this->fromRequest('auth_key') !== 'earm8BX4MFTgS6JCNQdqW5EzHUutv2Vx')
$this->requirePermission('sync_bookings');
// Check if the request was successful
$booking = [
'id' => $this->fromRequest('id'),
'customer_number' => $this->fromRequest('customer_number'),
'wash_type' => $this->fromRequest('wash_type'),
'contact_email' => $this->fromRequest('contact_email'),
'reference_number' => $this->fromRequest('reference_number'),
'regNrTraekker' => $this->fromRequest('regNrTraekker'),
'regNrTrailer' => $this->fromRequest('regNrTrailer'),
'washCertificateEmail' => $this->fromRequest('washCertificateEmail'),
'date' => $this->fromRequest('date'),
'department' => $this->fromRequest('department'),
'pickup_bool' => $this->fromRequest('pickup_bool'),
'notes' => $this->fromRequest('notes'),
'washCertificateStatus' => $this->fromRequest('washCertificateStatus'),
'washCertificateUrl' => $this->fromRequest('washCertificateUrl'),
'status' => $this->fromRequest('status'),
];
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'SYNC_BOOKINGS', 'Successfully synced bookings');
// Add the booking, if it doesn't exist, update it if it does
(new bookings_o())->addOrUpdate(
(int)$booking['id'],
(int)$booking['customer_number'],
(string)$booking['wash_type'],
(string)$booking['contact_email'],
(string)$booking['reference_number'],
(string)$booking['regNrTraekker'],
(string)$booking['regNrTrailer'],
(string)$booking['washCertificateEmail'],
(string)$booking['date'],
(string)$booking['department'],
(bool)$booking['pickup_bool'],
(string)$booking['notes'],
(string)$booking['washCertificateStatus'],
(string)$booking['washCertificateUrl'],
(string)$booking['status']
);
$response->success(
['message' => 'Successfully synced booking']
);
});
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php
namespace routes;
use classes\authentication;
use objects\customer_notes_o;
use objects\logs_o;
use objects\users_o;
use traits\route_t;
class customerCodeDepartmentRoute
{
use route_t;
public function run(): void
{
$this->get('/admin/customer/code', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('get_customer_code');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Get the query parameters from the URL
$data = $_GET;
// Check if the required fields are set
if (!isset($data['customer_number']) && !isset($data['user_id'])) { $response->error('User ID or Customer Number is required', 400); }
// Log the incident
(new logs_o())->add('customer_codes', 'global', 1, $user->id, 'GET_CUSTOMER_CODE', 'Successfully retrieved customer code');
// Check if the user exists
if (!(new users_o())->automaticGetTargetUserFromRequest()->exists()) {
$response->error('Customer not found', 400);
}
// Return the customer code
$response->success(
['code' => (new users_o())->automaticGetTargetUserFromRequest()->getCode()]
);
} else {
// Log the incident
(new logs_o())->add('customer_codes', 'global', 1, 0, 'GET_CUSTOMER_CODE', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
$this->post('/admin/customer/code', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_code');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Get the post data
$data = json_decode(file_get_contents('php://input'), true);
// Check if the required fields are set
if (!isset($data['customer_number']) && !isset($data['user_id']) && !isset($data['code'])) { $response->error('User ID, Customer Number, and Code are required', 400); }
// Log the incident
(new logs_o())->add('customer_codes', 'global', 1, $user->id, 'ADD_CUSTOMER_CODE', 'Successfully added customer code');
// Check if the user exists
if (!(new users_o())->automaticGetTargetUserFromRequest()->exists()) {
$response->error('Customer not found', 400);
}
// Add the customer code
(new users_o())->automaticGetTargetUserFromRequest()->setCode($data['code']);
// Return a success message
$response->success(['message' => 'Customer code added']);
} else {
// Log the incident
(new logs_o())->add('customer_codes', 'global', 1, 0, 'ADD_CUSTOMER_CODE', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
}
}
+96 -10
View File
@@ -10,7 +10,7 @@ use objects\departments_o;
use objects\economic_module_orders;
use objects\logs_o;
use objects\orders_o;
use objects\tokens_o;
use objects\users_o;
use traits\route_t;
class economicInvoiceRoute
@@ -64,16 +64,17 @@ class economicInvoiceRoute
// Get the department
$department = (new departments_o())->getDepartmentById($order->department_id->value());
// Add the department, date, reference
$economic_invoice_draft->addLineTEXT('Afdeling: ' . $department['name']);
$economic_invoice_draft->addLineTEXT('Dato: ' . $order->created_at->value());
$economic_invoice_draft->addLineTEXT('Reference: ' . $order->reference->value());
$this->addTheDepartmentDateReference($economic_invoice_draft, $department['name'], $order);
// Add the lines to the invoice
foreach ($order_items as $order_item) {
// If the customer requires any prefix or suffix to the product name, add it here
if ($customer->doesUserHaveAttribute('requiresRegistrationNumbersInvoice')) {
$order_item['product']['name'] = $order->reg_1->value() . ' ' . $order_item['product']['name'];
}
$economic_invoice_draft->addLine((string)$order_item['product']['economic_product_id'], (string)$order_item['product']['name'], 1, (int)$order_item['price'], 0);
foreach ( $order_items as $order_item ) {
// Add the order item to the invoice draft
$this->addOrderItemToInvoice(
$customer,
$order,
$order_item,
$economic_invoice_draft,
$order_item['quantity'] ?? 1);
}
// Create the invoice draft
$result = $economic_invoice_draft->createInvoiceDraftExample();
@@ -199,4 +200,89 @@ class economicInvoiceRoute
}
});
}
/**
* @param economic_invoice_draft_mo $economic_invoice_draft
* @param $department_name
* @param orders_o $order
* @return void
*/
function addTheDepartmentDateReference(economic_invoice_draft_mo $economic_invoice_draft, $department_name, orders_o $order): void
{
// The format is:
// [date], Truck Wash - [department name], (?)Ref(erence): [reference], Reg 1: [reg_1], (?)Reg 2: [reg_2], (?)Reg 3: [reg_3]
// (?)[note]
// Example:
// 2021-09-01, Truck Wash - Administration, Ref: 123456, Reg 1: ABC123, Reg 2: DEF456, Reg 3: GHI789
// This is a note for the invoice
//
// (?) = Optional
$line = $order->created_at->value() . ', Truck Wash - ' . $department_name;
// If there's a reference, add it to the invoice
if ($order->reference->value() !== '')
$line .= ', Ref: ' . $order->reference->value();
// Add the registration numbers (if any)
if ($order->reg_1->value() !== '')
$line .= ', Reg 1: ' . strtoupper($order->reg_1->value());
if ($order->reg_2->value() !== '')
$line .= ', Reg 2: ' . strtoupper($order->reg_2->value());
if ($order->reg_3->value() !== '')
$line .= ', Reg 3: ' . strtoupper($order->reg_3->value());
// Add the line to the invoice
$economic_invoice_draft->addLineTEXT($line);
// If there's a note, add it to the invoice
if ($order->notes->value() !== '')
$economic_invoice_draft->addLineTEXT((string)$order->notes->value());
}
/**
* @param users_o $customer
* @param orders_o $order
* @param mixed $order_item
* @param economic_invoice_draft_mo $economic_invoice_draft
* @param int $quantity
* @return void
*/
function addOrderItemToInvoice(users_o $customer, orders_o $order, mixed $order_item, economic_invoice_draft_mo $economic_invoice_draft, int $quantity = 1): void
{
// The format is:
// [product name], (?)Ref(erence): [reference], (!?)Reg 1: [reg 1], (!?)Reg 2: [reg 2], (!?)Reg 3: [reg 3], (?)Note: [note], (?)Discount: ([order item price] - [product price]) DKK ([discount percentage] %)
// (?) = Optional
// (!) = Required if the customer requires it
// (!?) = Should be added if the customer requires it
// Example:
// Tankcleaning 4 spulehoveder, Ref: 123456, Reg 1: ABC123, Reg 2: DEF456, Reg 3: GHI789, Note: This is a note, Discount: -100 DKK (20%)
$line = $order_item['product']['name'];
// If there's a reference, add it to the line
if ($order_item['reference'] !== '')
$line .= ', Ref: ' . $order_item['reference'];
// Add the registration numbers (if they exist, and the customer requires it)
if ($customer->doesUserHaveAttribute('requiresRegistrationNumbersInvoice')) {
$line .= ', Reg 1: ' . strtoupper($order->reg_1->value());
$line .= ', Reg 2: ' . strtoupper($order->reg_2->value());
$line .= ', Reg 3: ' . strtoupper($order->reg_3->value());
}
// If there's a note, add it to the line
if ($order_item['notes'] !== '')
$line .= ', Note: ' . $order_item['notes'];
// Calculate the discount percentage
$discountPercentage = round((($order_item['product']['price'] - $order_item['price']) / $order_item['product']['price']) * 100, 2);
// If the price is different from the product price, add it to the line
if ($order_item['price'] !== $order_item['product']['price'])
$line .= ', Discount: ' . ($order_item['price'] - $order_item['product']['price']) . ' DKK (~' . $discountPercentage . '%)';
// Add the line to the invoice
$economic_invoice_draft->addLine(
(string)$order_item['product']['economic_product_id'],
(string)$line,
(int)$quantity,
(int)$order_item['price'],
0, // Since we can't be specific about the discount, we set it to 0. (The API has a limit of 2 decimals, and that's not enough for our needs)
);
}
}
+60 -13
View File
@@ -3,7 +3,6 @@
namespace routes;
use classes\authentication;
use classes\response;
use objects\logs_o;
use objects\order_items_o;
use objects\orders_o;
@@ -25,15 +24,17 @@ class orderItemsRoute
if ($user) {
// Check if the required fields are set
$data = json_decode(file_get_contents('php://input'), true);
if (!isset($data['order_id'])) { $response->error('Order ID is required', 400); }
if (!isset($data['product_id'])) { $response->error('Product ID is required', 400); }
if (!isset($data['quantity'])) { $response->error('Quantity is required', 400); }
// Make sure we don't add more than 200 items at a time
if ($data['quantity'] > 199) { $response->error('Quantity is too high, please add less than 200 items at a time', 400); }
// Add the order item to the order This is done individually, to make the notes to the individual order items possible
for ($i = 0; $i < $data['quantity']; $i++) {
(new order_items_o())->addItemToOrder($data['order_id'], $data['product_id'], $user->id);
if (!isset($data['order_id'])) {
$response->error('Order ID is required', 400);
}
if (!isset($data['product_id'])) {
$response->error('Product ID is required', 400);
}
if (!isset($data['quantity'])) {
$response->error('Quantity is required', 400);
}
// Add the order item to the order This is done individually, to make the notes to the individual order items possible
(new order_items_o())->addItemToOrder((int)$data['order_id'], (int)$data['product_id'], (int)$user->id, (int)$data['quantity']);
// Return the list of departments
$response->success(
['message' => 'Order items added']
@@ -57,10 +58,12 @@ class orderItemsRoute
// Get the post data
$data = $_GET;
// Check if the required fields are set
if (!(int)$data['order_id']) { $response->error('Order ID is required', 400); }
if (!(int)$data['order_id']) {
$response->error('Order ID is required', 400);
}
// Return the list of departments
$response->success(
(new orders_o())->getOrderItems($data['order_id'])
(new orders_o())->getOrderItems((int)$data['order_id'])
);
} else {
// Log the incident
@@ -81,9 +84,11 @@ class orderItemsRoute
// Get the query data
$data = $_GET;
// Check if the required fields are set
if (!isset($data['id'])) { $response->error('Order Item ID is required', 400); }
if (!isset($data['id'])) {
$response->error('Order Item ID is required', 400);
}
// Delete the order item
(new order_items_o())->removeOrderItem($data['id']);
(new order_items_o())->removeOrderItem((int)$data['id']);
// Return the list of departments
$response->success(
['message' => 'Order item deleted']
@@ -95,5 +100,47 @@ class orderItemsRoute
$response->error('Invalid session', 400);
}
});
$this->put('/order/items', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('edit_order_items');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Get the post data
$data = json_decode(file_get_contents('php://input'), true);
// Check if the required fields are set
if (!isset($data['id'])) {
$response->error('Order Item ID is required', 400);
}
if (!isset($data['price'])) {
$response->error('Price is required', 400);
}
if (!isset($data['notes'])) {
$response->error('Notes is required', 400);
}
if (!isset($data['reference'])) {
$response->error('Reference is required', 400);
}
if (!isset($data['quantity'])) {
$response->error('Quantity is required', 400);
}
// Update the order item
(new order_items_o())->updateOrderItem((int)$data['id'], (int)$data['price'], (string)$data['notes'], (string)$data['reference'], (int)$data['quantity']);
// Log the incident
(new logs_o())->add('departments', 'global', 1, $user->id, 'EDIT_ORDER_ITEMS', 'Changed order item: ' . $data['id']);
// Return the list of departments
$response->success(
['message' => 'Order item updated']
);
} else {
// Log the incident
(new logs_o())->add('departments', 'global', 1, 0, 'EDIT_ORDER_ITEMS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
}
}
+63 -4
View File
@@ -92,10 +92,35 @@ class ordersRoute
// Get the post data
$data = json_decode(file_get_contents('php://input'), true);
// Check if the required fields are set
if (!isset($data['id'])) { $response->error('ID is required', 400); }
$data = $this->getData($data, $response);
// Update the order
(new orders_o())->edit((int)$data['id'], $user->id, (int)$data['customer_id'], $data['reference'], $data['notes'], (int)$data['department_id']);
if (!isset($data['id'])) {
$response->error('ID is required', 400);
}
// Get the current order
$order = (new orders_o())->getOrderById((int)$data['id']);
// Check if the order exists
if (!$order->exists()) {
$response->error('Order not found', 400);
}
// If the customer ID is set, validate it
if (isset($data['customer_id'])) {
if (!(new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id'])->exists() || empty($data['customer_id'])) {
$response->error('Customer not found or invalid', 400);
}
$order->customer_id->set((int)$data['customer_id']);
}
// If the reference is set, validate it
if (isset($data['reference'])) {
$order->reference->set($data['reference']);
}
// If the notes are set, validate them
if (isset($data['notes'])) {
$order->notes->set($data['notes']);
}
// If the registration number is set, validate it
if (isset($data['reg_1'])) {
$order->reg_1->set($data['reg_1']);
}
// If the department ID is set, validate it
// Log the incident
(new logs_o())->add('orders', $data['id'], 1, $user->id, 'EDIT_ORDER', 'Successfully updated an order (ID: ' . $data['id'] . ')');
// Return a success message
@@ -107,6 +132,40 @@ class ordersRoute
$response->error('Invalid session', 400);
}
});
$this->delete('/orders', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('delete_order');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Get the payload
$id = $this->fromRequest('id');
// Check if the ID is set
if (!$id) {
$response->error('ID is required', 400);
}
// Get the current order
$order = (new orders_o())->getOrderById((int)$id);
// Check if the order exists
if (!$order->exists()) {
$response->error('Order not found', 400);
}
// Delete the order
$order->delete();
// Log the incident
(new logs_o())->add('orders', $id, 1, $user->id, 'DELETE_ORDER', 'Successfully deleted an order (ID: ' . $id . ')');
// Return a success message
$response->success(['message' => 'Order deleted successfully']);
} else {
// Log the incident
(new logs_o())->add('orders', 'global', 1, 0, 'DELETE_ORDER', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
}
/**
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace routes;
use classes\authentication;
use objects\logs_o;
use objects\users_o;
use traits\route_t;
class userRoute
{
use route_t;
public function run(): void
{
$this->get('/superuser/user', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('get_user');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Log the incident
(new logs_o())->add('users', 'global', 1, $user->id, 'GET_USER', 'Successfully fetched user');
$targetUser = (new users_o())->automaticGetTargetUserFromRequest();
// Check if the user was found
if (!$targetUser->exists()) {
// Log the incident
(new logs_o())->add('users', 'global', 1, $user->id, 'GET_USER', 'No user found');
// Return an error
$response->error('User not found', 404);
}
// Return the list of users
$response->success(
$targetUser->includeIncludes(['all'])->asArray()
);
} else {
// Log the incident
(new logs_o())->add('users', 'global', 1, 0, 'GET_USER', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
});
}
}
+5 -2
View File
@@ -77,8 +77,9 @@ class usersRoute
// Check if the required fields are set
if (!isset($data['customer_number'])) { $response->error('Customer number is required', 400); }
if (!isset($data['password'])) { $response->error('Password is required', 400); }
if (!isset($data['role'])) { $response->error('Role is required', 400); }
// Add the user
(new users_o())->add($data['customer_number'], $data['password']);
(new users_o())->add($data['customer_number'], $data['password'], (int)$data['role']);
// Log the incident
(new logs_o())->add('users', 'global', 1, $user->id, 'ADD_USER', 'Successfully added a user');
// Return a success message
@@ -106,6 +107,8 @@ class usersRoute
if (!isset($data['customer_number'])) { $response->error('Customer number is required', 400); }
// Check if a new role is set, if not, set it to null to prevent it from being updated
if (!isset($data['role']) || $data['role'] === 'null' || $data['role'] === '') { $data['role'] = null; }
// Check if a display name is set, if not, set it to null to prevent it from being updated
if (!isset($data['display_name']) || $data['display_name'] === 'null' || $data['display_name'] === '') { $data['display_name'] = null; }
// If the role is set, require the edit_user_role permission
if ($data['role']) {
$this->requirePermission('edit_user_role');
@@ -117,7 +120,7 @@ class usersRoute
$this->requirePermission('edit_user_password');
}
// Edit the user
(new users_o())->edit((int)$data['id'], (string)$data['customer_number'], $data['role'], $data['password']);
(new users_o())->edit((int)$data['id'], (string)$data['customer_number'], $data['role'], $data['password'], $data['display_name']);
// Log the incident
(new logs_o())->add('users', 'global', 1, $user->id, 'EDIT_USER', 'Successfully edited a user with ID: ' . $data['id']);
// Return a success message
+50 -47
View File
@@ -7,30 +7,14 @@ use Exception;
trait db_object_t
{
private string $table; // The table of the objects in the database (e.g. users)
public int $id; // The id of the object in the database
private string $table; // The table of the objects in the database (e.g. users)
public function __construct()
{
$this->structure();
}
public function __toString(): string
{
// Return the object as a string
return json_encode($this->getArray());
}
/**
* Set the table of the objects in the database
* @param string $table The table of the objects in the database
*/
public function setTable(string $table): void
{
$this->table = $table;
}
/**
* Structure: Define the table and fields of the objects in the database
*/
@@ -39,6 +23,12 @@ trait db_object_t
// Define the table and fields of the objects in the database
}
public function __toString(): string
{
// Return the object as a string
return json_encode($this->getArray());
}
/**
* Get current object row as an array
* @return array The current object row as an array
@@ -59,15 +49,39 @@ trait db_object_t
}
/**
* List ALL objects in the table
* Set the table of the objects in the database
* @param string $table The table of the objects in the database
*/
public function setTable(string $table): void
{
$this->table = $table;
}
/**
* List objects with pagination (if set)
* @return array The list of objects in the table
*/
public function listObjects(): array
public function listObjectsWithPaginationIfSet(): array
{
global $db;
$sql = "SELECT * FROM $this->table";
$result = $db->query($sql);
return $db->fetch_all($result);
global $response;
$page = ((int)$response->getRequestParameter('page')) ?? null; // Get the page number
$limit = ((int)$response->getRequestParameter('limit')) ?? null; // Get the number of objects per page
$search = $response->getRequestParameter('search') ?? null; // Get the search query
$filters = $response->getRequestParameter('filters') ?? null; // Get the filters ( Eg. department_id:1,role_id:2 OR department_id:1 )
// Make the filters an array
if ($filters) {
$filters = explode(',', $filters);
$temp = [];
foreach ( $filters as $filter ) {
$filter = explode(':', $filter);
$temp[$filter[0]] = $filter[1];
}
$filters = $temp;
}
if ($page && $limit) {
return $this->listObjectsWithPagination($page, $limit, $search, $filters);
}
return $this->listObjects();
}
/**
@@ -86,7 +100,7 @@ trait db_object_t
$result = $db->query($sql);
$fields = $db->fetch_all($result);
$searchfields = [];
foreach ($fields as $field) {
foreach ( $fields as $field ) {
$searchfields[] = $field['Field'];
}
// Search for any similarities to the search query (Not case sensitive)
@@ -95,7 +109,7 @@ trait db_object_t
$searchQuery = 'WHERE ';
$search = strtolower($search);
$searchQuery .= '(';
foreach ($searchfields as $field) {
foreach ( $searchfields as $field ) {
$searchQuery .= "LOWER($field) LIKE '%$search%' OR ";
}
$searchQuery = substr($searchQuery, 0, -4);
@@ -108,9 +122,13 @@ trait db_object_t
} else {
$searchQuery = 'WHERE ';
}
foreach ($filters as $field => $value) {
foreach ( $filters as $field => $value ) {
$searchQuery .= "$field = $value AND ";
}
// If the deleted_at column exists, filter out the deleted objects
if (in_array('deleted_at', $searchfields)) {
$searchQuery .= "deleted_at IS NULL AND ";
}
$searchQuery = substr($searchQuery, 0, -5);
}
// Get the objects with pagination
@@ -126,30 +144,15 @@ trait db_object_t
}
/**
* List objects with pagination (if set)
* List ALL objects in the table (THIS INCLUDES DELETED OBJECTS)
* @return array The list of objects in the table
*/
public function listObjectsWithPaginationIfSet(): array
public function listObjects(): array
{
global $response;
$page = ((int) $response->getRequestParameter('page')) ?? null; // Get the page number
$limit = ((int) $response->getRequestParameter('limit')) ?? null; // Get the number of objects per page
$search = $response->getRequestParameter('search') ?? null; // Get the search query
$filters = $response->getRequestParameter('filters') ?? null; // Get the filters ( Eg. department_id:1,role_id:2 OR department_id:1 )
// Make the filters an array
if ($filters) {
$filters = explode(',', $filters);
$temp = [];
foreach ($filters as $filter) {
$filter = explode(':', $filter);
$temp[$filter[0]] = $filter[1];
}
$filters = $temp;
}
if ($page && $limit) {
return $this->listObjectsWithPagination($page, $limit, $search, $filters);
}
return $this->listObjects();
global $db;
$sql = "SELECT * FROM $this->table";
$result = $db->query($sql);
return $db->fetch_all($result);
}
/**
+9
View File
@@ -69,6 +69,15 @@ trait route_t
$this->registerRoute($route, 'OPTIONS', $callback);
}
/**
* PATCH route
* @param string $route Example: /home, /home/{id}
*/
public function patch(string $route, callable $callback): void
{
$this->registerRoute($route, 'PATCH', $callback);
}
/**
* Match route
* @param string $route Example: /home, /home/{id}