1019 lines
48 KiB
PHP
1019 lines
48 KiB
PHP
<?php
|
|
|
|
namespace routes;
|
|
|
|
use attachments\helpers\attachment_content;
|
|
use classes\attachment_store;
|
|
use classes\attachments;
|
|
use classes\authentication;
|
|
use classes\response;
|
|
use classes\stripe;
|
|
use JetBrains\PhpStorm\NoReturn;
|
|
use objects\collected_order_invoices_o;
|
|
use objects\departments_o;
|
|
use objects\economic_module_orders;
|
|
use objects\logs_o;
|
|
use objects\orders_o;
|
|
use objects\stripe_module_orders_o;
|
|
use objects\stripe_payment_intents_o;
|
|
use objects\users_o;
|
|
use traits\route_t;
|
|
|
|
class ordersRoute
|
|
{
|
|
use route_t;
|
|
|
|
public function run(): void
|
|
{
|
|
$this->get('/orders', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$restrict_only_own = false;
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Check if the user has the permission to list their own orders
|
|
$can_list_own_orders = $this->hasPermission('list_own_orders');
|
|
$can_list_all_orders = $this->hasPermission('list_orders');
|
|
if (!$can_list_own_orders && !$can_list_all_orders) {
|
|
$response->error('You do not have permission to list orders, neither your own nor all orders', 403);
|
|
};
|
|
if ($can_list_own_orders && !$can_list_all_orders) {
|
|
$restrict_only_own = true;
|
|
}
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, $user->id, 'LIST_ORDERS', 'Successfully listed orders');
|
|
// Create economic_module_orders object
|
|
//$economic_module_orders = new economic_module_orders();
|
|
$orders = new orders_o();
|
|
if (!$restrict_only_own) {
|
|
$department_ids = $user->getGroup()->getDepartments();
|
|
} else {
|
|
$department_ids = [];
|
|
}
|
|
if (self::isParametersSet(['show_wash_subscription'])) {
|
|
// Check if the boolean is true
|
|
if (self::getParameter('show_wash_subscription') === 'true') {
|
|
// add the '10' to the department_ids
|
|
$department_ids[] = '10';
|
|
}
|
|
}
|
|
// Return the list of departments
|
|
$orders->setView('orders_with_invoice_collections');
|
|
$response->success(
|
|
$orders->listObjectsWithPaginationIfSet(
|
|
function ($order) {
|
|
$order_obj = new orders_o();
|
|
// Get the order object
|
|
$order_obj->select((int)$order['id']);
|
|
// Add the invoice status to the order
|
|
$order['economic_invoice_module'] = (new economic_module_orders())->getByOrderId($order['id'])->asArray();
|
|
// Add the total amount to the order
|
|
$order['total_net_amount'] = $order_obj->getNetAmount();
|
|
// Add the stripe status to the order
|
|
$stripe_module_orders = (new stripe_module_orders_o())->select($order['id']);
|
|
if ($stripe_module_orders->exists()) {
|
|
$order['stripe_invoice_module'] = $stripe_module_orders->asArray();
|
|
}
|
|
// If the invoice collection is set, add it to the order
|
|
if (!empty($order['invoice_collection_id'])) {
|
|
$collected_order_invoices_obj = new collected_order_invoices_o();
|
|
$collected_order_invoices_obj->select((int)$order['invoice_collection_id']);
|
|
$order['invoice_collection'] = [
|
|
'id' => $order['invoice_collection_id'],
|
|
'closed_at' => $collected_order_invoices_obj->closed_at->value(),
|
|
'booked_invoice_id' => $collected_order_invoices_obj->booked_invoice_id->value() ?? null,
|
|
'processor' => (int)$collected_order_invoices_obj->processor->value() ?? null,
|
|
];
|
|
}
|
|
// Get the customer
|
|
$tmp_customer = (new users_o())->getCustomerByIdOrCustomerNumber((int)$order['customer_id']);
|
|
// Add the customer name to the order
|
|
$order['customer_name'] = (new users_o())->getCustomerName((int)$tmp_customer->customer_number->value());
|
|
$order['user_id'] = (int)$tmp_customer->id;
|
|
// Add the cashier name to the order
|
|
$order['cashier_name'] = (new users_o())->getCashierName((int)$order['cashier_id']);
|
|
$order['pending_handheld'] = $order_obj->isPendingHandheld();
|
|
$order['attachments'] = $order_obj->listAttachments();
|
|
$order['po'] = $order['po'] ?? null;
|
|
$order['lane'] = $order['lane'] ?? null;
|
|
/** @var array $order */
|
|
return $order;
|
|
},
|
|
$orders->forceRestrictFilters(
|
|
[
|
|
// This makes sure that the user can only see orders from the departments they explicitly have access to
|
|
'department_id' => $department_ids,
|
|
...($restrict_only_own ? [
|
|
'customer_id' => $user->customer_number->value(),
|
|
] : []),
|
|
]
|
|
)
|
|
)
|
|
);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'LIST_ORDERS', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'list_orders' => 'List all orders',
|
|
'list_own_orders' => 'List own orders',
|
|
]
|
|
);
|
|
|
|
|
|
$this->post('/orders', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('add_order');
|
|
// 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
|
|
$data = $this->getData($data, $response);
|
|
// This is used to determine if the order is created from a handheld device,
|
|
// If it is, we will add an indicator "pending" to the order, in the cache.
|
|
// This will automatically be removed at midnight, or when the order is completed.
|
|
if (isset($data['is_handheld']) && !is_bool($data['is_handheld'])) {
|
|
$response->error('is_handheld must be a boolean', 400);
|
|
}
|
|
if (isset($data['is_handheld'])) {
|
|
$isHandHeld = (bool)$data['is_handheld'];
|
|
unset($data['is_handheld']);
|
|
} else {
|
|
$isHandHeld = false;
|
|
}
|
|
// Validate the department
|
|
if (!(new departments_o())->getDepartmentById((int)$data['department_id'])) {
|
|
$response->error('Department not found', 400);
|
|
}
|
|
// Make sure the customer number set is valid
|
|
$targetUser = (new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id']);
|
|
if (!$targetUser->exists()) {
|
|
$response->error('Customer not found', 400);
|
|
}
|
|
|
|
// Check if the user requires a reference
|
|
if ($targetUser->requiresReference() && empty($data['reference'])) {
|
|
$response->error('Reference is required by the customer', 400);
|
|
}
|
|
// Get the registration number
|
|
$reg_1 = $data['reg_1'];
|
|
// Get the registration numbers (If they are set, they 2-3 are optional)
|
|
$reg_2 = $data['reg_2'] ?? '';
|
|
$reg_3 = $data['reg_3'] ?? '';
|
|
// Strip the registration numbers of any whitespace
|
|
$reg_1 = preg_replace('/\s+/', '', $reg_1);
|
|
$reg_2 = preg_replace('/\s+/', '', $reg_2);
|
|
$reg_3 = preg_replace('/\s+/', '', $reg_3);
|
|
$new_data = [
|
|
'customer_id' => (int)$data['customer_id'],
|
|
'department_id' => (int)$data['department_id'],
|
|
'reference' => (string)$data['reference'] ?? '',
|
|
'cashier_id' => (int)$user->id, // The user who created the order
|
|
'notes' => (string)$data['notes'] ?? '',
|
|
'reg_1' => (string)$reg_1,
|
|
'reg_2' => (string)$reg_2,
|
|
'reg_3' => (string)$reg_3,
|
|
...(!empty($data['lane']) ? ['lane' => (int)$data['lane']] : []), // Optional lane
|
|
...(!empty($data['wash_id']) ? ['wash_id' => (string)$data['wash_id']] : []), // Optional wash ID
|
|
...(!empty($data['booking_id']) ? ['booking_id' => (int)$data['booking_id']] : []), // Optional booking ID
|
|
'created_at' => (string)($data['created_at'] ?? date('Y-m-d H:i:s')), // Default to current time if not set
|
|
];
|
|
// Create the order
|
|
//$order = (new orders_o())->add((int)$data['customer_id'], $user->id, $data['reference'], $data['notes'], (int)$data['department_id'], (string)$reg_1, (string)$reg_2, (string)$reg_3);
|
|
$order = (new orders_o())->addArray($new_data);
|
|
// If the order is created from a handheld device, we will add an indicator "pending" to the order, in the cache.
|
|
if ($isHandHeld) {
|
|
$order->setPendingHandheldIndicator();
|
|
}
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $data['department_id'], 1, $user->id, 'ADD_ORDER', 'Successfully added an order (ID: ' . $data['department_id'] . ')');
|
|
// Return a success message, containing the orders array
|
|
$response->success($order->asArray());
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'ADD_ORDER', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'add_order' => 'Add an order'
|
|
]
|
|
);
|
|
|
|
$this->put('/order', function () {
|
|
self::updateOrder();
|
|
},
|
|
[
|
|
'edit_order' => 'Edit an order'
|
|
]
|
|
);
|
|
|
|
$this->put('/orders', function () {
|
|
self::updateOrder();
|
|
},
|
|
[
|
|
'edit_order' => 'Edit an order'
|
|
]
|
|
);
|
|
|
|
$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);
|
|
}
|
|
// Check if the user has access to the department
|
|
self::requireDepartmentAccess((int)$order->department_id->value());
|
|
// Delete the order
|
|
$order->delete();
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 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);
|
|
}
|
|
},
|
|
[
|
|
'delete_order' => 'Delete an order'
|
|
]
|
|
);
|
|
|
|
$this->get('/orders/attachments/download', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$isCustomerAccess = ($this->hasPermission('user') && !($this->hasPermission('download_order_attachments')));
|
|
if (!$isCustomerAccess) {
|
|
$this->requirePermission('download_order_attachments');
|
|
} else {
|
|
$this->requirePermission('download_order_attachments_own');
|
|
}
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Get the order ID and attachment ID from the request
|
|
self::requireParameters([
|
|
'order_id',
|
|
'attachment_id'
|
|
]);
|
|
$order_id = self::getParameter('order_id');
|
|
$attachment_id = self::getParameter('attachment_id');
|
|
if (!is_numeric($order_id) || (int)$order_id < 1) {
|
|
$response->error('Invalid order ID', 400);
|
|
}
|
|
if (!is_numeric($attachment_id) || (int)$attachment_id < 1) {
|
|
$response->error('Invalid attachment ID', 400);
|
|
}
|
|
// Get the current order
|
|
$order = (new orders_o())->getOrderById((int)$order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 400);
|
|
}
|
|
// Check if the user has customer edit access
|
|
if ($isCustomerAccess) {
|
|
if ($order->isOwnOrder($user->customer_number->value()) === false) {
|
|
$response->error('You do not have permission to download this order', 400);
|
|
}
|
|
}
|
|
// Get the attachment
|
|
$attachment = $order->getAttachment((int)$attachment_id);
|
|
if (!$attachment->exists()) {
|
|
$response->error('Attachment not found', 400);
|
|
}
|
|
// Create a download link
|
|
$attachment_store = new attachment_store();
|
|
$attachments = new attachments();
|
|
$attachment_formatted = $attachments->format($attachment);
|
|
$download_link = $attachment_store->generateDirectDownloadUrl(
|
|
$attachment_formatted->content->document
|
|
);
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'DOWNLOAD_ORDER_ATTACHMENT', 'Successfully downloaded an attachment for an order (Order ID: ' . $order_id . ', Attachment ID: ' . $attachment_id . ')');
|
|
// Return the download link
|
|
$response->success(['download_link' => $download_link]);
|
|
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'DOWNLOAD_ORDER_ATTACHMENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'download_order_attachments' => 'Download attachments for an order',
|
|
'download_order_attachments_own' => 'Download attachments for an order (Only for own orders)'
|
|
]
|
|
);
|
|
|
|
$this->get('/orders/attachments', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Get the order ID from the request
|
|
self::requireParameters([
|
|
'id'
|
|
]);
|
|
$order_id = self::getParameter('id');
|
|
if (!is_numeric($order_id) || (int)$order_id < 1) {
|
|
$response->error('Invalid order ID', 400);
|
|
}
|
|
// Get the current order
|
|
$order = (new orders_o())->getOrderById((int)$order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 400);
|
|
}
|
|
/**
|
|
* Permissions
|
|
*/
|
|
$hasPermissionOwn = self::hasPermission('list_own_order_attachments');
|
|
$hasPermissionAll = self::hasPermission('list_order_attachments');
|
|
$hasPermission = false;
|
|
if ($hasPermissionOwn || !$hasPermissionAll) {
|
|
// Check if the order belongs to the user
|
|
if ($order->isOwnOrder($user->customer_number->value())) {
|
|
$hasPermission = true;
|
|
self::requirePermission('list_own_order_attachments');
|
|
}
|
|
}
|
|
if (!$hasPermission) {
|
|
self::requirePermission('list_order_attachments');
|
|
}
|
|
// Get the attachments
|
|
$attachments = $order->listAttachments();
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'LIST_ORDER_ATTACHMENTS', 'Successfully listed attachments for an order (ID: ' . $order_id . ')');
|
|
// Return the attachments
|
|
$response->success($attachments);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'LIST_ORDER_ATTACHMENTS', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'list_order_attachments' => 'List attachments for an order',
|
|
'list_own_order_attachments' => 'List attachments for an order (Only for own orders)'
|
|
]
|
|
);
|
|
|
|
$this->post('/orders/attachments/upload', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('add_order_attachments');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Check if the order ID and file are set
|
|
$this->requireParameters(['order_id', 'base64_file', 'file_name']);
|
|
$order_id = (int)$this->getParameter('order_id');
|
|
if (!is_numeric($order_id) || (int)$order_id < 1) {
|
|
$response->error('Invalid order ID', 400);
|
|
}
|
|
// Get the current order
|
|
$order = (new orders_o())->getOrderById((int)$order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 400);
|
|
}
|
|
// Get the base64 file
|
|
$base64_file = (string)$this->getParameter('base64_file');
|
|
$attachment_store = new attachment_store();
|
|
// Determine the file extension from the file name
|
|
$file_name = (string)$this->getParameter('file_name');
|
|
$extension = pathinfo($file_name, PATHINFO_EXTENSION);
|
|
$object_name = $attachment_store->storeTempFileFromBase64(
|
|
$base64_file,
|
|
$extension
|
|
);
|
|
if ($object_name === false) {
|
|
$response->error('Failed to store the attachment file.', 500);
|
|
}
|
|
$object_attachment = $order->addAttachment((new attachment_content())->setDocument($object_name)->setOther((string)self::getParameter('file_name')));
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'ADD_ORDER_ATTACHMENT', 'Successfully added an attachment for an order (Order ID: ' . $order_id . ')');
|
|
// Return a success message
|
|
$attachments = new attachments();
|
|
$response->success($attachments->format($attachments->get($object_attachment->id)));
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'ADD_ORDER_ATTACHMENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'add_order_attachments' => 'Add attachments for an order'
|
|
]
|
|
);
|
|
|
|
$this->delete('/orders/attachments', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('delete_order_attachments');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Get the order ID and attachment ID from the request
|
|
self::requireParameters([
|
|
'order_id',
|
|
'attachment_id'
|
|
]);
|
|
$order_id = self::getParameter('order_id');
|
|
$attachment_id = self::getParameter('attachment_id');
|
|
if (!is_numeric($order_id) || (int)$order_id < 1) {
|
|
$response->error('Invalid order ID', 400);
|
|
}
|
|
if (!is_numeric($attachment_id) || (int)$attachment_id < 1) {
|
|
$response->error('Invalid attachment ID', 400);
|
|
}
|
|
// Get the current order
|
|
$order = (new orders_o())->getOrderById((int)$order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 400);
|
|
}
|
|
// Delete the attachment
|
|
$order->removeAttachment((int)$attachment_id);
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'DELETE_ORDER_ATTACHMENT', 'Successfully deleted an attachment for an order (Order ID: ' . $order_id . ', Attachment ID: ' . $attachment_id . ')');
|
|
// Return a success message
|
|
$response->success(['message' => 'Attachment deleted successfully']);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'DELETE_ORDER_ATTACHMENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'delete_order_attachments' => 'Delete attachments for an order'
|
|
]
|
|
);
|
|
|
|
$this->post('/orders/mark_as_completed', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('mark_order_as_completed');
|
|
// 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('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);
|
|
}
|
|
// Mark the order as completed
|
|
$order->markAsCompleted();
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'MARK_ORDER_AS_COMPLETED', 'Successfully marked an order as completed (ID: ' . $data['id'] . ')');
|
|
// Return a success message
|
|
$response->success(['message' => 'Order marked as completed successfully']);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'MARK_ORDER_AS_COMPLETED', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'mark_order_as_completed' => 'Mark an order as completed'
|
|
]
|
|
);
|
|
|
|
$this->post('/orders/module/stripe/payment_intent', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('charge_order');
|
|
// 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('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);
|
|
}
|
|
// Get the department
|
|
$department = (new departments_o())->selectId((int)$order->department_id->value());
|
|
// Check if the department is configured for Stripe payments
|
|
if (!$department->isStripeConfigured()) {
|
|
$response->error('Department is not configured for Stripe payments', 400);
|
|
}
|
|
// Check if the reader is set
|
|
if (!isset($data['reader'])) {
|
|
$response->error('Reader ID is required', 400);
|
|
}
|
|
// Get the tax percentage (if any)
|
|
$tax_percentage = (isset($data['tax_percentage'])) ? (int)$data['tax_percentage'] : null;
|
|
// Check if the tax percentage is valid
|
|
if ($tax_percentage !== null && ($tax_percentage < 0 || $tax_percentage > 100)) {
|
|
$response->error('Invalid tax percentage', 400);
|
|
}
|
|
function addTaxNetAmount($net_amount, $tax_percentage): float
|
|
{
|
|
// Check if the tax percentage is above 0
|
|
if (empty($tax_percentage) || $tax_percentage <= 0) {
|
|
return $net_amount;
|
|
}
|
|
return $net_amount + ($net_amount * ($tax_percentage / 100));
|
|
}
|
|
|
|
// Get the Stripe payment intent
|
|
$stripe = new stripe();
|
|
$paymentIntent = $stripe->payment_intents->create(
|
|
addTaxNetAmount(
|
|
(float)$order->getNetAmount() * 100,
|
|
$tax_percentage ?? 0
|
|
),
|
|
[
|
|
'description' => 'Order ID: ' . $order->id,
|
|
'metadata' => [
|
|
'order_id' => $order->id,
|
|
'customer_id' => $order->customer_id->value(),
|
|
'department_id' => $order->department_id->value(),
|
|
'tax_percentage' => $tax_percentage ?? 0,
|
|
],
|
|
'payment_method_types' => ['card_present'],
|
|
'capture_method' => 'manual',
|
|
]
|
|
);
|
|
// Validate the payment intent
|
|
try {
|
|
$stripe->payment_intents->get($paymentIntent->id);
|
|
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
|
$response->error('Payment intent not found', 400);
|
|
}
|
|
// Set the payment intent ID in the order
|
|
$stripe_payment_intents = new stripe_payment_intents_o();
|
|
$stripe_payment_intents->add(
|
|
(int)$order->id,
|
|
$paymentIntent->id,
|
|
$paymentIntent->client_secret,
|
|
$paymentIntent->toJSON()
|
|
);
|
|
|
|
// Send the payment intent to the reader
|
|
$stripe->readers->sendPaymentIntent(
|
|
$data['reader'],
|
|
$paymentIntent->id,
|
|
);
|
|
// Set the reader on the stripe payment intent
|
|
$stripe_payment_intents->reader_id->set($data['reader']);
|
|
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'CHARGE_ORDER', 'Successfully charged an order (ID: ' . $data['id'] . ')');
|
|
|
|
$response->success([
|
|
'payment_intent' => $paymentIntent->id,
|
|
'client_secret' => $paymentIntent->client_secret,
|
|
]);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'CHARGE_ORDER', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'charge_order' => 'Charge an order'
|
|
]
|
|
);
|
|
|
|
$this->get('/orders/module/stripe/payment_intent', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('get_payment_intent');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Get the post data
|
|
self::requireParameters([
|
|
'id'
|
|
]);
|
|
// Check if the required fields are set
|
|
$id = self::getParameter('id');
|
|
if (!isset($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);
|
|
}
|
|
// Check if the order has a payment intent
|
|
$stripe_payment_intents = new stripe_payment_intents_o();
|
|
if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) {
|
|
$response->error('Order does not have a payment intent', 400);
|
|
}
|
|
$stripe_payment_intents->selectOrderPaymentIntent((int)$order->id);
|
|
// Get the Stripe payment intent
|
|
$stripe = new stripe();
|
|
try {
|
|
$payment_intent = $stripe->payment_intents->get(
|
|
$stripe_payment_intents->payment_intent_id->value(),
|
|
[
|
|
//'expand' => ['latest_charge'], // This is used to get the latest charge, that can be used to check if the payment has been refunded.
|
|
]
|
|
);
|
|
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
|
$response->error('Payment intent not found', 400);
|
|
}
|
|
$response->success(
|
|
$payment_intent->toJSON()
|
|
);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'GET_PAYMENT_INTENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'get_payment_intent' => 'Get a payment intent'
|
|
]
|
|
);
|
|
|
|
$this->delete('/orders/module/stripe/payment_intent', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('charge_order');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Get the data
|
|
self::requireParameters([
|
|
'id'
|
|
]);
|
|
$id = self::fromRequest('id');
|
|
// 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);
|
|
}
|
|
// Check if the order has a payment intent
|
|
$stripe_payment_intents = new stripe_payment_intents_o();
|
|
if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) {
|
|
$response->error('Order does not have a payment intent', 400);
|
|
}
|
|
$stripe_payment_intents->selectOrderPaymentIntent((int)$order->id);
|
|
try {
|
|
$stripe_payment_intents->delete();
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'DELETE_PAYMENT_INTENT', 'Successfully deleted a payment intent (ID: ' . $id . ')');
|
|
// Return a success message
|
|
$response->success(['message' => 'Payment intent deleted successfully']);
|
|
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
|
$response->error('Payment intent not found', 400);
|
|
}
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'DELETE_PAYMENT_INTENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'charge_order' => 'Delete a payment intent'
|
|
]
|
|
);
|
|
|
|
$this->post('/orders/module/stripe/payment_intent/capture', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('confirm_payment_intent');
|
|
// 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('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);
|
|
}
|
|
// Check if the order has a payment intent
|
|
$stripe_payment_intents = new stripe_payment_intents_o();
|
|
if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) {
|
|
$response->error('Order does not have a payment intent', 400);
|
|
}
|
|
$stripe_payment_intents->selectOrderPaymentIntent((int)$order->id);
|
|
// Confirm the payment intent
|
|
$stripe = new stripe();
|
|
try {
|
|
$paymentIntent = $stripe->payment_intents->capture(
|
|
$stripe_payment_intents->payment_intent_id->value(),
|
|
[] // Since we are capturing the payment, we don't need to pass any data
|
|
);
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'CONFIRM_PAYMENT_INTENT', 'Successfully confirmed a payment intent (ID: ' . $data['id'] . ')');
|
|
// Check if the payment intent was successful
|
|
if ($paymentIntent->status !== 'succeeded') {
|
|
$response->error('Payment intent not successful', 400);
|
|
} else {
|
|
// Update the order collection to reflect the payment
|
|
$order_collection = $order->getOrderCollection();
|
|
$order_collection->paidWithStripe($paymentIntent->id);
|
|
}
|
|
// Return a success message
|
|
$response->success($paymentIntent->toJSON());
|
|
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
|
$response->error('Payment intent not found', 400);
|
|
}
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'CONFIRM_PAYMENT_INTENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'confirm_payment_intent' => 'Confirm a payment intent'
|
|
]
|
|
);
|
|
|
|
$this->post('/orders/module/stripe/debug/simulate_payment', function () {
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('debug_simulate_payment_intent');
|
|
// 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('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);
|
|
}
|
|
// Check if the order has a payment intent
|
|
$stripe_payment_intents = new stripe_payment_intents_o();
|
|
if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) {
|
|
$response->error('Order does not have a payment intent', 400);
|
|
}
|
|
$stripe_payment_intents->selectOrderPaymentIntent((int)$order->id);
|
|
// Simulate the payment
|
|
$stripe = new stripe();
|
|
//$paymentIntent = $stripe->readers->simulatePayment(
|
|
// $stripe_payment_intents->payment_intent_id->value(),
|
|
//);
|
|
$response->success('TEST_SUCCESS', 200);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'SIMULATE_PAYMENT_INTENT', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'simulate_payment_intent' => 'Simulate a payment intent, this is only for testing purposes and should under no circumstances be used in production'
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @throws \Exception
|
|
*/
|
|
#[NoReturn] private function updateOrder(): void
|
|
{
|
|
// Require the user to be logged in
|
|
global $response;
|
|
// Check if the user has permission to partially edit the order
|
|
$isCustomerAccess = ((new authentication())->get_user()->hasPermission('user') && !((new authentication())->get_user()->hasPermission('edit_order')));
|
|
if (!$isCustomerAccess) {
|
|
$this->requirePermission('edit_order');
|
|
} else {
|
|
$this->requirePermission('user'); // This is used to allow the user to edit their own order
|
|
}
|
|
// 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('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);
|
|
}
|
|
// Check if the user has customer edit access
|
|
if ($isCustomerAccess) {
|
|
if ($order->customer_id->value() !== $user->customer_number->value()) {
|
|
$response->error('You do not have permission to edit this order', 400);
|
|
}
|
|
// Allowed to edit list
|
|
$allowed_to_edit = [
|
|
// Include the order ID (Even though it is not editable)
|
|
'id',
|
|
'po',
|
|
];
|
|
// Check if the $data contains any non-allowed keys
|
|
foreach ( $data as $key => $value ) {
|
|
if (!in_array($key, $allowed_to_edit)) {
|
|
$response->error('You do not have permission to edit this order field (key: ' . $key . ')', 400);
|
|
break;
|
|
}
|
|
};
|
|
// PO
|
|
if (isset($data['po'])) {
|
|
$order->po->set((string)$data['po']);
|
|
}
|
|
// Registration numbers
|
|
if (isset($data['reg_1'])) {
|
|
$order->reg_1->set((string)$data['reg_1']);
|
|
}
|
|
if (isset($data['reg_2'])) {
|
|
$order->reg_2->set((string)$data['reg_2']);
|
|
}
|
|
if (isset($data['reg_3'])) {
|
|
$order->reg_3->set((string)$data['reg_3']);
|
|
}
|
|
// Reference
|
|
if (isset($data['reference'])) {
|
|
$order->reference->set((string)$data['reference']);
|
|
}
|
|
// Notes
|
|
if (isset($data['notes'])) {
|
|
$order->notes->set((string)$data['notes']);
|
|
}
|
|
// Register the change
|
|
$order->objectChanged();
|
|
// Return a success message
|
|
$response->success($order->asArray());
|
|
}
|
|
/** Departmental access */
|
|
// 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 registration number 2 is set, validate it
|
|
if (isset($data['reg_2'])) {
|
|
$order->reg_2->set($data['reg_2']);
|
|
}
|
|
// If the registration number 3 is set, validate it
|
|
if (isset($data['reg_3'])) {
|
|
$order->reg_3->set($data['reg_3']);
|
|
}
|
|
// If the PO is set, validate it
|
|
if (isset($data['po'])) {
|
|
$order->po->set((string)$data['po']);
|
|
}
|
|
// If the lane is set, validate it
|
|
if (isset($data['lane'])) {
|
|
$order->lane->set((int)$data['lane']);
|
|
}
|
|
// If the department ID is set, validate it
|
|
if (isset($data['department_id'])) {
|
|
if (!(new departments_o())->getDepartmentById((int)$data['department_id'])) {
|
|
$response->error('Department not found', 400);
|
|
}
|
|
$order->department_id->set((int)$data['department_id']);
|
|
}
|
|
// If the booking ID is set, validate it
|
|
if (isset($data['booking_id'])) {
|
|
$order->booking_id->set((int)$data['booking_id']);
|
|
}
|
|
// Check if the invoice collection is set
|
|
if (isset($data['invoice_collection_id'])) {
|
|
$order->invoice_collection_id->set((int)$data['invoice_collection_id']);
|
|
}
|
|
// Check if the wash_id is set
|
|
if (isset($data['wash_id'])) {
|
|
$order->wash_id->set($data['wash_id']);
|
|
}
|
|
// Check if the created_at is set
|
|
if (isset($data['created_at'])) {
|
|
$order->created_at->set($data['created_at']);
|
|
}
|
|
// Void any cached key for the order
|
|
$order->objectChanged();
|
|
// Log the incident
|
|
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'EDIT_ORDER', 'Successfully updated an order (ID: ' . $data['id'] . ')');
|
|
// Return a success message
|
|
$response->success(['message' => 'Order updated successfully']);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('orders', 'global', 1, 0, 'EDIT_ORDER', 'No user found, or invalid session');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param mixed $data
|
|
* @param response $response
|
|
* @return mixed
|
|
*/
|
|
private function getData(mixed $data, response $response): mixed
|
|
{
|
|
if (!isset($data['customer_id'])) {
|
|
$response->error('Customer ID is required', 400);
|
|
}
|
|
if ((int)$data['customer_id'] < 1 || !is_numeric((int)$data['customer_id'])) {
|
|
$response->error('Customer ID is required', 400);
|
|
}
|
|
if (!isset($data['department_id'])) {
|
|
$response->error('Department ID is required', 400);
|
|
}
|
|
if (!isset($data['reference'])) {
|
|
$response->error('Reference is required', 400);
|
|
}
|
|
if (!isset($data['notes'])) {
|
|
$response->error('Notes is required', 400);
|
|
}
|
|
if (!isset($data['reg_1'])) {
|
|
$response->error('Registration number 1 is required', 400);
|
|
}
|
|
if (strlen($data['reg_1']) < 4) {
|
|
$response->error('Registration number 1 must be at least 4 characters', 400);
|
|
}
|
|
// Optional fields are not checked here, as they are optional and can be empty
|
|
return $data;
|
|
}
|
|
} |