Add new routes and enhance invoice handling in backend

Introduced new superuser-only routes for handling collected invoices, including viewing invoices per order/month, invoice totals, and transactions. Enhanced validation for invoice closure with processors and added support for database views in multiple classes and objects. These updates improve backend functionality and data granularity while maintaining strict permission control.
This commit is contained in:
Jepp9350
2025-04-01 11:53:54 +02:00
parent 21563449b9
commit 5f65c5ea65
4 changed files with 232 additions and 2 deletions
+7
View File
@@ -134,5 +134,12 @@ class db
return $return === 0;
}
public function getView(string $view): array
{
$sql = "SELECT * FROM $view";
$result = $this->query($sql);
return $this->fetch_all($result);
}
}
@@ -374,7 +374,7 @@ class collected_order_invoices_o extends db
// Require the invoice collection to be selected
self::requireSelected();
// Require the invoice collection to not be closed
if (!empty($this->closed_at->value())) {
if (!empty($this->closed_at->value()) && !empty($this->processor->value())) {
throw new Exception('Invoice collection is closed');
}
}
@@ -277,6 +277,203 @@ class orderInvoicesRoute
'list_collected_invoices_customers' => 'List ALL collected order invoices customers. This is a superuser-only route.'
]
);
$this->get('/collected-invoices/customers/invoicePerOrder', function () {
global $response;
self::requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('orderInvoices', 'global', 1, $user->id, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_PER_ORDER', 'User accessed the list of collected order invoices customers with invoice per order');
// Define the users
$users_o = new users_o();
$users_o->setView('customers_invoice_count_per_order');
$result = $users_o
->setSearchableFields([
'customer_number',
'display_name',
'active_invoices',
'closed_invoices',
])
->listObjectsWithPaginationIfSet(
function ($collected_order_invoice) use ($users_o) {
return [
'customer_number' => (int)$collected_order_invoice['customer_number'],
'display_name' => (string)$users_o->getCustomerName((int)$collected_order_invoice['customer_number']),
'active_invoices' => (int)$collected_order_invoice['active_invoices'],
'closed_invoices' => (int)$collected_order_invoice['closed_invoices'],
];
},
);
// Return the list of customers
$response->success($result);
} else {
(new logs_o())->add('orderInvoices', 'global', 0, 0, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_PER_ORDER', 'User tried to access the list of collected order invoices customers with invoice per order without a valid session');
$response->error('Invalid session', 400);
}
},
[
'list_collected_invoices_customers_invoice_per_order' => 'List ALL collected order invoices customers with invoice per order. This is a superuser-only route.'
]
);
$this->get('/collected-invoices/customers/invoicePerMonth', function () {
global $response;
self::requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('orderInvoices', 'global', 1, $user->id, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_PER_MONTH', 'User accessed the list of collected order invoices customers with invoice per month');
// Define the users
$users_o = new users_o();
$users_o->setView('customers_invoice_count_per_month');
$result = $users_o
->setSearchableFields([
'customer_number',
'customer_name',
'active_invoices',
'closed_invoices',
])
->listObjectsWithPaginationIfSet(
function ($collected_order_invoice) use ($users_o) {
return [
'customer_number' => (int)$collected_order_invoice['customer_number'],
'display_name' => (string)$users_o->getCustomerName((int)$collected_order_invoice['customer_number']),
'active_invoices' => (int)$collected_order_invoice['active_invoices'],
'closed_invoices' => (int)$collected_order_invoice['closed_invoices'],
];
},
);
// Return the list of customers
$response->success($result);
} else {
(new logs_o())->add('orderInvoices', 'global', 0, 0, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_PER_MONTH', 'User tried to access the list of collected order invoices customers with invoice per month without a valid session');
$response->error('Invalid session', 400);
}
},
[
'list_collected_invoices_customers_invoice_per_month' => 'List ALL collected order invoices customers with invoice per month. This is a superuser-only route.'
]
);
$this->post('/collected-invoices/customers/invoiceTotals', function () {
// This is a superuser-only route
global $response;
self::requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('orderInvoices', 'global', 1, $user->id, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_TOTALS', 'User accessed the list of collected order invoices customers with invoice totals');
// Require the customer_numbers parameter
self::requireParameters(['customer_numbers']);
// Print the customer_numbers parameter
$customer_numbers = self::getParameter('customer_numbers');
// validate the customer_numbers parameter
if (!is_array($customer_numbers)) {
$response->error('customer_numbers must be an array', 400);
}
// Validate the customer_numbers parameter
foreach ( $customer_numbers as $customer_number ) {
self::requireType((int)$customer_number, self::type_int());
if (!is_numeric($customer_number)) {
$response->error('customer_numbers must be an array of integers', 400);
}
if (!$customer_number || $customer_number < 1) {
$response->error('customer_numbers must be an array of integers greater than 0', 400);
}
}
// Now we can safely use the customer_numbers parameter
// Define the result array
$result = [];
// Loop through the customer_numbers array, and get the invoice totals for each customer
foreach ( $customer_numbers as $customer_number ) {
// Define the invoices array
$tmp_invoices = [
'closed_invoices' => [],
'open_invoices' => [],
];
// Define the total net amount
$tmp_total_net_amount = [
'closed_invoices' => 0,
'open_invoices' => 0,
];
// Define the collected order invoices
$collected_order_invoices = new collected_order_invoices_o();
// Get the collected order invoices for the customer
$collected_order_invoices->setView('invoices_with_completed_orders');
$tmp_invoice_collections = $collected_order_invoices->listObjectsWithPaginationIfSet(
function ($collected_order_invoice) use ($tmp_invoices, $customer_number, $collected_order_invoices) {
// Select the orders for each collected order invoice
$collected_order_invoices->select((int)$collected_order_invoice['id']);
// Get the details for the collected order invoice
return $this->getOrderInvoiceDetails($collected_order_invoice, new users_o(), $collected_order_invoices);
},
$collected_order_invoices->forceRestrictFilters([
'customer_number' => $customer_number,
])
);
// Loop through the collected order invoices, and get the total net amount
foreach ( $tmp_invoice_collections as $tmp_invoice_collection ) {
// Update the total net amount
if ($tmp_invoice_collection['closed_at'] !== null) {
$tmp_total_net_amount['closed_invoices'] += $tmp_invoice_collection['total_net_amount'];
// Add the closed invoice to the closed invoices array
$tmp_invoices['closed_invoices'][] = $tmp_invoice_collection;
} else {
$tmp_total_net_amount['open_invoices'] += $tmp_invoice_collection['total_net_amount'];
// Add the open invoice to the open invoices array
$tmp_invoices['open_invoices'][] = $tmp_invoice_collection;
}
}
$tmp_user = (new users_o())->getUserByCustomerNumber($customer_number);
// Add the customer to the result array
$result[$customer_number] = [
'customer_number' => (int)$customer_number,
'customer_name' => (string)$tmp_user->display_name->value(),
'user_id' => (int)$tmp_user->id,
'invoices' => $tmp_invoices,
'total_net_amount' => $tmp_total_net_amount,
];
}
// Return the list of customers
$response->success($result);
} else {
(new logs_o())->add('orderInvoices', 'global', 0, 0, 'LIST_COLLECTED_INVOICES_CUSTOMERS_INVOICE_TOTALS', 'User tried to access the list of collected order invoices customers with invoice totals without a valid session');
$response->error('Invalid session', 400);
}
});
$this->get('/collected-invoices/transactions', function () {
global $response;
self::requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('orderInvoices', 'global', 1, $user->id, 'LIST_COLLECTED_INVOICES_TRANSACTIONS', 'User accessed the list of collected order invoices transactions');
// Get the collected order invoices
$collected_order_invoices = new collected_order_invoices_o();
// Define the transactions
$transactions = $orders_o->listObjectsWithPaginationIfSet(
function ($order) use ($orders_o) {
// Select the orders for each collected order invoice
$orders_o->select((int)$order['id']);
return [
'id' => (int)$order['id'],
'customer_number' => (int)$order['customer_number'],
'external_id' => (string)$order['external_id'],
'created_at' => (string)$order['created_at'],
'updated_at' => (string)$order['updated_at'],
];
},
);
// Return the list of transactions
$response->success($transactions);
} else {
(new logs_o())->add('orderInvoices', 'global', 0, 0, 'LIST_COLLECTED_INVOICES_TRANSACTIONS', 'User tried to access the list of collected order invoices transactions without a valid session');
$response->error('Invalid session', 400);
}
},
[
'list_collected_invoices_transactions' => 'List ALL collected order invoices transactions. This is a superuser-only route.'
]
);
}
/**
+27 -1
View File
@@ -5,16 +5,29 @@ namespace traits;
use classes\db;
use classes\response;
use Exception;
use objects\bookings_new_o;
use objects\bookings_o;
use objects\branding_o;
use objects\categories_o;
use objects\collected_order_invoices_o;
use objects\cron_o;
use objects\currency_conversion_rates_o;
use objects\customer_codes_o;
use objects\customer_notes_o;
use objects\customer_vehicles_o;
use objects\department_categories_o;
use objects\department_daily_reports_o;
use objects\department_variables_o;
use objects\departments_o;
use objects\economic_module_orders;
use objects\form_submissions_o;
use objects\fxratesapi_conversion_rates_o;
use objects\groups_o;
use objects\groups_permissions_o;
use objects\logs_o;
use objects\module_action_logs_o;
use objects\motorapi_lookups_o;
use objects\notifications_o;
use objects\order_items_o;
use objects\orders_o;
use objects\plate_scanners_o;
@@ -22,6 +35,8 @@ use objects\plate_scans_o;
use objects\product_options_o;
use objects\products_o;
use objects\ratelimit_o;
use objects\stripe_module_customers_o;
use objects\stripe_module_orders_o;
use objects\tokens_o;
use objects\user_key_value_pairs_o;
use objects\user_price_overrides_o;
@@ -203,7 +218,7 @@ trait db_object_t
}
// Check if the value is "null", if it is, set it to null
foreach ( $temp as $key => $value ) {
if (strtolower($value) === 'null') {
if (!is_array($value) && strtolower($value) === 'null') {
$temp[$key] = null;
continue;
}
@@ -784,6 +799,17 @@ trait db_object_t
return $this;
}
/**
* Set the view, used on the pagination
* @param string $view The view to set
* @return users_o|bookings_new_o|bookings_o|branding_o|categories_o|collected_order_invoices_o|cron_o|currency_conversion_rates_o|customer_codes_o|customer_notes_o|customer_vehicles_o|department_categories_o|department_daily_reports_o|department_variables_o|departments_o|economic_module_orders|form_submissions_o|fxratesapi_conversion_rates_o|groups_o|groups_permissions_o|logs_o|module_action_logs_o|motorapi_lookups_o|notifications_o|order_items_o|orders_o|plate_scanners_o|plate_scans_o|product_options_o|products_o|ratelimit_o|stripe_module_customers_o|stripe_module_orders_o|tokens_o|user_key_value_pairs_o|user_price_overrides_o|db_object_t
*/
public function setView(string $view): self
{
$this->table = $view;
return $this;
}
/**
* Add an object to the database, using the data provided
* @param array $data The data to add the object with (E.g. ['name' => 'John', 'email' => 'email@example.com'])