Add endpoint to close invoice drafts and refactor routes

Introduced a new POST endpoint `/invoices/draft/close` to allow closing of draft invoices, enforcing user authentication and permissions. Refactored and reorganized route and utility methods to improve readability and maintainability, including restoring `match_route` and restructuring `fromRequest`. Removed unused methods for cleaner code.
This commit is contained in:
Jepp9350
2025-02-07 13:03:22 +01:00
parent f8cd736154
commit ac657d6130
5 changed files with 80 additions and 31 deletions
@@ -72,4 +72,18 @@ class economic_module_orders extends db
'invoice_id' => $this->economic_invoice_id->value(),
];
}
public function getUserFromDraftId(int $id): users_o|null
{
global $db;
$sql = "SELECT id FROM $this->table WHERE invoice_draft_id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
$orderId = $row['id'];
$order = new orders_o();
return $order->getOrderCustomer($orderId);
}
return null;
}
}
+1 -9
View File
@@ -303,13 +303,5 @@ class orders_o extends db
return $db->fetch_all($result);
}
public function listPendingOrders(\Closure $param): array
{
global $db;
// Get all orders that are not deleted, and that does not have an invoice draft or invoice
$sql = "SELECT * FROM $this->table WHERE deleted_at IS NULL AND id NOT IN (SELECT id FROM economic_module_orders WHERE invoice_draft_id IS NOT NULL OR invoice_id IS NOT NULL)";
$result = $db->query($sql);
$array = $db->fetch_all($result);
return array_map($param, $array);
}
}
@@ -22,6 +22,7 @@ class economicInvoiceRoute
global /** @var response $response */
/** @var router $router */
$router, $response;
$this->post('/economic/invoice/draft/export', function () {
global $response;
@@ -4,7 +4,9 @@ namespace routes;
use classes\authentication;
use classes\economic;
use objects\economic_module_orders;
use objects\logs_o;
use objects\users_o;
use traits\route_t;
class invoicesRoute
@@ -47,5 +49,37 @@ class invoicesRoute
}
});
$this->post('/invoices/draft/close', function () {
// Require the user to be logged in
global $response;
$this->requirePermission('close_invoice_draft');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the invoice id is set
if (!$this->fromRequest('id')) {
$response->error('id parameter is required', 400);
}
// Create economic object
$economic_module_orders = new economic_module_orders();
// Get the user object from the draft invoice id
/** @var users_o $target_user */
$target_user = $economic_module_orders->getUserFromDraftId($this->fromRequest('id'));
// Get the draft invoice
$target_user->unsetOpenInvoiceDraft();
// Log the incident
(new logs_o())->add('invoices', 'global', 1, $user->id, 'CLOSE_INVOICE', 'Successfully closed invoice');
// Return the list of departments
$response->success(
['message' => 'Invoice closed']
);
} 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);
}
});
}
}
+30 -22
View File
@@ -8,17 +8,12 @@ use objects\logs_o;
trait route_t
{
private string $route;
public function __construct()
{
$this->route = $_SERVER['REQUEST_URI'];
}
private function registerRoute($route, $method, $callback): void
{
global $router;
$router->add($route, $method, $callback);
}
public function run(): void
{
// Add the routes here
@@ -33,6 +28,12 @@ trait route_t
$this->registerRoute($route, 'GET', $callback);
}
private function registerRoute($route, $method, $callback): void
{
global $router;
$router->add($route, $method, $callback);
}
/**
* POST route
* @param string $route Example: /home, /home/{id}
@@ -78,16 +79,6 @@ trait route_t
$this->registerRoute($route, 'PATCH', $callback);
}
/**
* Match route
* @param string $route Example: /home, /home/{id}
*/
private function match_route(string $route): bool
{
// Check if route is the same, or if it matches the regex pattern
return $route === $this->route || preg_match($route, $this->route);
}
/**
* Get the parameter from the route URL by index
* @param string $index
@@ -118,7 +109,7 @@ trait route_t
}
if (!$user->hasPermission($permission)) {
(new logs_o())->add('global', 'global', 1, $user->id, 'PERMISSION_DENIED', 'Permission denied. Missing permission: ' . $permission);
$response->error('Permission denied. Missing permission: ' . $permission .' for user: ' . $user->id . ' In group: ' . $user->group_id->value(), 403);
$response->error('Permission denied. Missing permission: ' . $permission . ' for user: ' . $user->id . ' In group: ' . $user->group_id->value(), 403);
}
} catch (\Exception $e) {
$response->error($e->getMessage(), 400);
@@ -147,6 +138,23 @@ trait route_t
return true;
}
/**
* Get data from the request body or query string by name
* @param string $name
* @return string|null
*/
public function fromRequest(string $name): ?string
{
// If the $_POST variable is set, return the value from the POST variable, otherwise return the value from the query string
if (isset($_POST)) {
$data = json_decode(file_get_contents('php://input'), true);
if (isset($data[$name])) {
return $data[$name];
}
}
return (isset($_POST[$name])) ? $_POST[$name] : $this->fromQuery($name);
}
/**
* Get the parameter from the query string by name
* @param string $name
@@ -158,12 +166,12 @@ trait route_t
}
/**
* Get data from the request body or query string by name
* @param string $name
* @return string|null
* Match route
* @param string $route Example: /home, /home/{id}
*/
public function fromRequest(string $name): ?string
private function match_route(string $route): bool
{
return (isset($_POST[$name])) ? $_POST[$name] : $this->fromQuery($name);
// Check if route is the same, or if it matches the regex pattern
return $route === $this->route || preg_match($route, $this->route);
}
}