402 lines
21 KiB
PHP
402 lines
21 KiB
PHP
<?php
|
|
|
|
namespace routes;
|
|
|
|
use classes\authentication;
|
|
use classes\response;
|
|
use classes\router;
|
|
use economic_invoice_draft_mo;
|
|
use objects\departments_o;
|
|
use objects\economic_module_orders;
|
|
use objects\logs_o;
|
|
use objects\orders_o;
|
|
use objects\users_o;
|
|
use traits\route_t;
|
|
|
|
class economicInvoiceRoute
|
|
{
|
|
use route_t;
|
|
|
|
public function run(): void
|
|
{
|
|
global /** @var response $response */
|
|
/** @var router $router */
|
|
$router, $response;
|
|
|
|
|
|
$this->post('/economic/invoice/draft/export', function () {
|
|
global $response;
|
|
$this->requirePermission('economic_invoice_draft_export');
|
|
$user = (new authentication())->get_user();
|
|
if ($user) {
|
|
$order_id = $response->getRequestParameter('order_id');
|
|
if (!isset($order_id)) {
|
|
$response->error('Order ID is required', 400);
|
|
}
|
|
// Validate the order ID is a number
|
|
if (!is_numeric($order_id)) {
|
|
$response->error('Order ID must be a number', 400);
|
|
}
|
|
$order = (new orders_o())->getOrderById($order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 404);
|
|
}
|
|
// Get the order items
|
|
$order_items = (new orders_o())->getOrderItems($order_id);
|
|
// Apply the department pricing
|
|
$order_items = (new orders_o())->applyDepartmentPrices($order_items, $order->department_id->value());
|
|
// Get the customer
|
|
$customer = (new orders_o())->getCustomerByOrderId($order_id);
|
|
// Check if the customer exists
|
|
if (!$customer->exists()) {
|
|
$response->error('Customer not found', 404);
|
|
}
|
|
// Get the customer economic number
|
|
$customer_economic = $customer->getCustomerEcocomicData()->economic_customer;
|
|
$economic_invoice_draft = (new economic_invoice_draft_mo());
|
|
// Set the customer number
|
|
$economic_invoice_draft->setCustomerNumber((int)$customer_economic->customer_number);
|
|
// Set the recipient
|
|
$economic_invoice_draft->setRecipient(
|
|
$customer_economic->name ?? 'Ukendt',
|
|
$customer_economic->address ?? 'Ukendt',
|
|
$customer_economic->zip ?? 'Ukendt',
|
|
$customer_economic->city ?? 'Ukendt'
|
|
);
|
|
// Make sure there are order items
|
|
if (count($order_items) === 0) {
|
|
$response->error('No order items found', 404);
|
|
}
|
|
// Get the department
|
|
$department = (new departments_o())->getDepartmentById($order->department_id->value());
|
|
// Add the department, date, reference
|
|
$this->addTheDepartmentDateReference($economic_invoice_draft, $department['name'], $order);
|
|
|
|
// Add the lines to the invoice
|
|
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);
|
|
}
|
|
// Check if the user has an open invoice draft
|
|
$hasOpenInvoiceDraft = $customer->hasOpenInvoiceDraft();
|
|
if ($hasOpenInvoiceDraft && !$customer->invoicePerOrder()) {
|
|
// Get the open invoice draft
|
|
$openInvoiceDraft = $customer->getOpenInvoiceDraft();
|
|
// Add the order to the invoice draft
|
|
$result = $this->addOrderToInvoiceDraft($openInvoiceDraft, $order, $customer, $order_items);
|
|
}
|
|
// If the customer doesn't want to be billed per order, or if there's no open invoice draft, we'll create a new one
|
|
// Create the invoice draft
|
|
if (!isset($result)) {
|
|
$result = $economic_invoice_draft->createInvoiceDraftExample();
|
|
}
|
|
// Check if the invoice draft was created, or if the lines were added (lines is an array, and should not be empty)
|
|
if (!isset($result->draftInvoiceNumber) && !isset($result->lines[0])) {
|
|
// Log the error
|
|
(new logs_o())->add('economic_invoice_draft', 'global', 3, $user->id, 'ECONOMIC_INVOICE_DRAFT_EXPORT', 'Failed to create economic invoice draft');
|
|
// Check if we can get the errors from the response
|
|
if (isset($result->errors)) {
|
|
$response->add_meta('economic_errors', $result->errors);
|
|
}
|
|
$response->add_meta('economic_result', $result);
|
|
// Try to parse the error message
|
|
$response->error($result->message ?? 'Failed to create economic invoice draft', 500);
|
|
}
|
|
// Add the economic invoice draft to the order
|
|
$economic_module_orders = (new economic_module_orders())->getByOrderId($order_id);
|
|
// Remove the existing invoice draft (if any)
|
|
if ($economic_module_orders->economic_invoice_draft_id->value() > 0) {
|
|
$economic_invoice_draft->deleteInvoiceDraft($economic_module_orders->economic_invoice_draft_id->value());
|
|
}
|
|
$economic_module_orders->economic_invoice_draft_id->set($result->draftInvoiceNumber ?? $customer->getOpenInvoiceDraft());
|
|
if (!$customer->invoicePerOrder()) {
|
|
// If the customer wants to be billed per order, we'll add the order to the invoice draft
|
|
$customer->setOpenInvoiceDraft($result->draftInvoiceNumber ?? $customer->getOpenInvoiceDraft());
|
|
} else {
|
|
// If the customer doesn't want to be billed per order, we'll remove the open invoice draft
|
|
$customer->unsetOpenInvoiceDraft();
|
|
}
|
|
// Return the response
|
|
(new logs_o())->add('economic_invoice_draft', 'global', 1, $user->id, 'ECONOMIC_INVOICE_DRAFT_EXPORT', 'Successfully exported an economic invoice draft');
|
|
$response->success($economic_module_orders->getArray());
|
|
} else {
|
|
(new logs_o())->add('economic_invoice_draft', 'global', 1, 0, 'ECONOMIC_INVOICE_DRAFT_EXPORT', 'No user found, or invalid session');
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
}, [
|
|
'economic_invoice_draft_export' => 'Export an economic invoice draft'
|
|
]);
|
|
|
|
$this->delete('/economic/invoice/draft/delete', function () {
|
|
|
|
global /** @var response $response */
|
|
$response;
|
|
$this->requirePermission('economic_invoice_draft_delete');
|
|
$user = (new authentication())->get_user();
|
|
if ($user) {
|
|
$order_id = $response->getRequestParameter('order_id');
|
|
if (!isset($order_id)) {
|
|
$response->error('Order ID is required', 400);
|
|
}
|
|
$order = (new orders_o())->getOrderById($order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 404);
|
|
}
|
|
// Make sure the order has an economic invoice draft
|
|
$economic_module_orders = (new economic_module_orders())->getByOrderId($order_id);
|
|
if ($economic_module_orders->economic_invoice_draft_id->value() === 0) {
|
|
$response->error('No economic invoice draft found', 404);
|
|
}
|
|
$economic_invoice_draft = (new economic_invoice_draft_mo());
|
|
// Get the invoice draft number
|
|
$invoiceDraftId = $economic_module_orders->economic_invoice_draft_id->value();
|
|
$customer = (new orders_o())->getCustomerByOrderId($order_id);
|
|
if (!$customer->invoicePerOrder()) {
|
|
// Check if the customer has an open invoice draft
|
|
if ($customer->hasOpenInvoiceDraft()) {
|
|
// Check if it's the same as the order's invoice draft
|
|
if ((int)$customer->getOpenInvoiceDraft() === (int)$invoiceDraftId) {
|
|
// Remove the open invoice draft from the customer
|
|
$customer->deleteOpenInvoiceDraft();
|
|
}
|
|
}
|
|
}
|
|
// Delete the invoice draft
|
|
$economic_invoice_draft->deleteInvoiceDraft($invoiceDraftId);
|
|
// Remove the economic invoice draft from the order
|
|
$economic_module_orders->economic_invoice_draft_id->set(null);
|
|
// Return the response
|
|
(new logs_o())->add('economic_invoice_draft', 'global', 1, $user->id, 'ECONOMIC_INVOICE_DRAFT_DELETE', 'Successfully deleted an economic invoice draft');
|
|
$response->success($economic_module_orders->getArray());
|
|
} else {
|
|
(new logs_o())->add('economic_invoice_draft', 'global', 1, 0, 'ECONOMIC_INVOICE_DRAFT_DELETE', 'No user found, or invalid session');
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
}, [
|
|
'economic_invoice_draft_delete' => 'Delete an economic invoice draft'
|
|
]);
|
|
|
|
$this->post('/economic/invoice/export', function () {
|
|
global $response;
|
|
$this->requirePermission('economic_invoice_export');
|
|
$user = (new authentication())->get_user();
|
|
if ($user) {
|
|
$order_id = $response->getRequestParameter('order_id');
|
|
if (!isset($order_id)) {
|
|
$response->error('Order ID is required', 400);
|
|
}
|
|
$order = (new orders_o())->getOrderById($order_id);
|
|
// Check if the order exists
|
|
if (!$order->exists()) {
|
|
$response->error('Order not found', 404);
|
|
}
|
|
// Get the customer
|
|
$customer = (new orders_o())->getCustomerByOrderId($order_id);
|
|
// Check if the customer exists
|
|
if (!$customer->exists()) {
|
|
$response->error('Customer not found', 404);
|
|
}
|
|
// Make sure the order has an economic invoice draft
|
|
$economic_module_orders = (new economic_module_orders())->getByOrderId($order_id);
|
|
if ($economic_module_orders->economic_invoice_draft_id->value() === 0) {
|
|
$response->error('No economic invoice draft found', 404);
|
|
}
|
|
$economic_invoice_draft = (new economic_invoice_draft_mo());
|
|
// Get the invoice draft number
|
|
$invoiceDraftId = $economic_module_orders->economic_invoice_draft_id->value();
|
|
// Make sure there's not already an invoice created
|
|
$invoiceId = $economic_module_orders->economic_invoice_id->value();
|
|
if ($invoiceId > 0) {
|
|
$response->error('An invoice has already been created, invoice ID: ' . $invoiceId, 400);
|
|
}
|
|
// Publish the invoice draft
|
|
$result = $economic_invoice_draft->publishInvoiceDraft((int)$invoiceDraftId);
|
|
// Check if the invoice was created
|
|
if (!isset($result->bookedInvoiceNumber)) {
|
|
// Log the error
|
|
(new logs_o())->add('economic_invoice', 'global', 3, $user->id, 'ECONOMIC_INVOICE_EXPORT', 'Failed to create economic invoice from draft: ' . $invoiceDraftId);
|
|
// Check if we can get the errors from the response
|
|
if (isset($result->errors)) {
|
|
$response->add_meta('economic_errors', $result->errors);
|
|
}
|
|
// Try to parse the error message
|
|
$response->error($result->message ?? 'Failed to create economic invoice', 500);
|
|
}
|
|
// Add the economic invoice to the order
|
|
$economic_module_orders = (new economic_module_orders())->getByOrderId($order_id);
|
|
$economic_module_orders->economic_invoice_id->set($result->bookedInvoiceNumber);
|
|
// Remove the economic invoice draft from the customer
|
|
$customer->unsetOpenInvoiceDraft();
|
|
// Return the response
|
|
(new logs_o())->add('economic_invoice', 'global', 1, $user->id, 'ECONOMIC_INVOICE_EXPORT', 'Successfully exported an economic invoice');
|
|
$response->success($economic_module_orders->getArray());
|
|
} else {
|
|
(new logs_o())->add('economic_invoice', 'global', 1, 0, 'ECONOMIC_INVOICE_EXPORT', 'No user found, or invalid session');
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
}, [
|
|
'economic_invoice_export' => 'Export an economic invoice'
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @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:
|
|
// Truck Wash - [department name], [date], (?)Ref(erence): [reference], Reg 1: [reg_1], (?)Reg 2: [reg_2], (?)Reg 3: [reg_3]
|
|
// (?)[note]
|
|
// Example:
|
|
// 12-02-2025 13:27, Truck Wash - Administration, Ref: 123456, Reg 1: ABC123, Reg 2: DEF456, Reg 3: GHI789
|
|
// This is a note for the invoice
|
|
//
|
|
// (?) = Optional
|
|
$parsed_date = date('d/m/Y H:i', strtotime($order->created_at->value()));
|
|
$economic_invoice_draft->addLineTEXT("[ " . $parsed_date . ' ' . $department_name . ' #' . $order->id . " ]");
|
|
// If there's a reference, add it to the invoice
|
|
if ($order->reference->value() !== '') {
|
|
$economic_invoice_draft->addLineTEXT('Reference:');
|
|
// Add "# " in the beginning of each line (If there's more than one line, otherwise we just add the prefix once)
|
|
if (str_contains($order->reference->value(), "\n")) {
|
|
foreach ( explode("\n", $order->reference->value()) as $line ) {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $line);
|
|
}
|
|
} else {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $order->reference->value());
|
|
}
|
|
}
|
|
// Add the registration numbers (if any)
|
|
$line_reg = '';
|
|
if ($order->reg_1->value() !== '') {
|
|
$line_reg .= 'Reg 1: ' . strtoupper($order->reg_1->value());
|
|
}
|
|
if ($order->reg_2->value() !== '')
|
|
$line_reg .= ', Reg 2: ' . strtoupper($order->reg_2->value());
|
|
if ($order->reg_3->value() !== '')
|
|
$line_reg .= ', Reg 3: ' . strtoupper($order->reg_3->value());
|
|
// Add the line to the invoice
|
|
$economic_invoice_draft->addLineTEXT($line_reg);
|
|
// If there's a note, add it to the invoice
|
|
if ($order->notes->value() !== '') {
|
|
$economic_invoice_draft->addLineTEXT('Notat:');
|
|
// Add "# " in the beginning of each line (If there's more than one line, otherwise we just add the prefix once)
|
|
if (str_contains($order->notes->value(), "\n")) {
|
|
foreach ( explode("\n", $order->notes->value()) as $line ) {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $line);
|
|
}
|
|
} else {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $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
|
|
* @throws \Exception
|
|
*/
|
|
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%)
|
|
// Get the department
|
|
$department = $order->getDepartmentByOrderId($order->id);
|
|
$economic_department_id = $department['economic_department_id'];
|
|
$economic_dimension_id = $department['economic_dimension_id'] ?? 0;
|
|
|
|
// Add the line to the invoice
|
|
$economic_invoice_draft->addLine(
|
|
(string)$order_item['product']['economic_product_id'],
|
|
(string)$order_item['product']['name'],
|
|
(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)
|
|
(int)$economic_department_id ?? 0,
|
|
(int)$economic_dimension_id ?? 0 // If the department is not set, we'll set it to 0
|
|
);
|
|
// Calculate the discount percentage
|
|
$discountPercentage = round((($order_item['product']['price'] - $order_item['price']) / $order_item['product']['price']) * 100, 0);
|
|
|
|
// If the price is different from the product price, add it to the line
|
|
if ($order_item['price'] !== $order_item['product']['price'])
|
|
$economic_invoice_draft->addLineTEXT('Rabat: ' . ($order_item['price'] - $order_item['product']['price']) . ' DKK (' . $discountPercentage . '%)');
|
|
|
|
// If there's a reference, add it to the line
|
|
if ($order_item['reference'] !== '') {
|
|
$economic_invoice_draft->addLineTEXT('Reference:');
|
|
// Add "# " in the beginning of each line (If there's more than one line, otherwise we just add the prefix once)
|
|
if (str_contains($order_item['reference'], "\n")) {
|
|
foreach ( explode("\n", $order_item['reference']) as $line ) {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $line);
|
|
}
|
|
} else {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $order_item['reference']);
|
|
}
|
|
}
|
|
|
|
// Add the registration numbers (if they exist, and the customer requires it)
|
|
if ($customer->doesUserHaveAttribute('requiresRegistrationNumbersInvoice')) {
|
|
$line_reg = '';
|
|
if ($order->reg_1->value() !== '') {
|
|
$line_reg .= 'Reg 1: ' . strtoupper($order->reg_1->value());
|
|
}
|
|
if ($order->reg_2->value() !== '') {
|
|
$line_reg .= ', Reg 2: ' . strtoupper($order->reg_2->value());
|
|
}
|
|
if ($order->reg_3->value() !== '') {
|
|
$line_reg .= ', Reg 3: ' . strtoupper($order->reg_3->value());
|
|
}
|
|
$economic_invoice_draft->addLineTEXT($line_reg);
|
|
}
|
|
|
|
// If there's a note, add it to the line
|
|
if ($order_item['notes'] !== '') {
|
|
$economic_invoice_draft->addLineTEXT('Notat:');
|
|
// Add "# " in the beginning of each line (If there's more than one line, otherwise we just add the prefix once)
|
|
if (str_contains($order_item['notes'], "\n")) {
|
|
foreach ( explode("\n", $order_item['notes']) as $line ) {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $line);
|
|
}
|
|
} else {
|
|
$economic_invoice_draft->addLineTEXT('# ' . $order_item['notes']);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function addOrderToInvoiceDraft(int $economic_invoice_draft_id, orders_o $order, users_o $customer, array $order_items): object
|
|
{
|
|
$economic_invoice_draft = (new economic_invoice_draft_mo());
|
|
// Add two empty lines to the invoice, to separate the orders
|
|
$economic_invoice_draft->addLineTEXT('');
|
|
$economic_invoice_draft->addLineTEXT('');
|
|
// Add the department, date, reference
|
|
$this->addTheDepartmentDateReference($economic_invoice_draft, $order->getDepartmentByOrderId($order->id)['name'], $order);
|
|
// Add the lines to the invoice
|
|
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);
|
|
}
|
|
return $economic_invoice_draft->addLinesToInvoiceDraft($economic_invoice_draft_id);
|
|
}
|
|
} |