Add support for dynamic currency conversion in invoices

Introduced dynamic currency handling in invoice generation by adding methods to set currency and retrieve conversion rates. Adjusted logic to ensure accurate currency conversions when processing orders, draft invoices, and customer data. Default behavior falls back to DKK if no currency is specified.
This commit is contained in:
Jepp9350
2025-03-31 14:42:19 +02:00
parent 67cf1c5880
commit 68ab9bc84c
6 changed files with 89 additions and 11 deletions
+3 -2
View File
@@ -92,10 +92,11 @@ class economic implements economic_i
/**
* Get a invoiceDraft (Helper) from the Economic system
* @param int $draft_invoice_number The Economic draft invoice number
* @param string $currency The conversion rate to use (default: DKK)
* @return economic_invoice_draft
*/
public function getInvoiceDraft(int $draft_invoice_number): economic_invoice_draft
public function getInvoiceDraft(int $draft_invoice_number, string $currency = 'DKK'): economic_invoice_draft
{
return new $this->helpers->economic_invoice_draft($draft_invoice_number);
return new $this->helpers->economic_invoice_draft($draft_invoice_number, $currency);
}
}
@@ -55,12 +55,13 @@ class economic_invoices_draft_endpoint
* Add an order to a draft invoice
* @param int $invoiceDraftId The invoice draft id to add the order to
* @param orders_o $order The order to add
* @param string $currency The currency to use (default: DKK)
* @return void
* @throws Exception If the request fails
*/
public function add_order(int $invoiceDraftId, orders_o $order): void
public function add_order(int $invoiceDraftId, orders_o $order, string $currency = 'DKK'): void
{
$draftInvoice = (new economic())->getInvoiceDraft($invoiceDraftId);
$draftInvoice = (new economic())->getInvoiceDraft($invoiceDraftId, strtoupper($currency));
// Add the transaction header (Timestamp, department, etc.)
$draftInvoice->addNewTransactionHeader($order);
// Add the order lines
@@ -101,7 +101,7 @@ class economic_invoices_drafts_endpoint
'other' => $external_id
],
// Set the currency TODO: Make this dynamic
// Set the currency
'currency' => $customer->getCurrency() ?? 'DKK',
// Set the recipient details
@@ -111,7 +111,7 @@ class economic_invoices_drafts_endpoint
'zip' => $customer_zip,
'city' => $customer_city,
'vatZone' => [
'vatZoneNumber' => 1
'vatZoneNumber' => (int)$customer->getVatZoneNumber(),
],
],
])
@@ -4,6 +4,7 @@ namespace helpers;
use classes\economic;
use Exception;
use objects\currency_conversion_rates_o;
use objects\departments_o;
use objects\orders_o;
@@ -26,15 +27,28 @@ class economic_invoice_draft
* @var object $draft_invoice_data
*/
protected object $draft_invoice_data;
/**
* The currency for the draft invoice
* @var string $currency
* @note The currency is set to DKK by default
*/
protected string $currency = 'DKK';
/**
* The currency conversion rate
* @var float $conversion_rate
* @note The conversion rate is set to 1.0 by default
*/
protected float $conversion_rate = 1.0;
/**
* Construct a new Economic draft invoice object
* @throws Exception if the invoice data is invalid or empty
*/
public function __construct(int $draft_invoice_number)
public function __construct(int $draft_invoice_number, string $currency = 'DKK')
{
$this->setDraftInvoiceNumber($draft_invoice_number);
$this->setCurrency(strtoupper($currency));
$this->fetchDraftInvoiceData();
$this->requireSelected();
}
@@ -49,6 +63,21 @@ class economic_invoice_draft
$this->draft_invoice_number = $draft_invoice_number;
}
/**
* Set the currency for the draft invoice
* @param string $currency The currency to set
* @return void
* @throws Exception If the currency is not valid
* @throws Exception If the conversion rate is not valid
*/
private function setCurrency(string $currency): void
{
// Set the currency for the draft invoice
$this->currency = $currency;
// Get the conversion rate for the currency
$this->conversion_rate = (float)(new currency_conversion_rates_o())->convertTo($this->currency, 1);
}
/**
* Fetch the draft invoice data from the Economic system
* @throws Exception If the request fails
@@ -268,7 +297,7 @@ class economic_invoice_draft
'productNumber' => $productNumber,
],
'quantity' => $quantity,
'unitNetPrice' => $unitNetPrice,
'unitNetPrice' => self::convertCurrency($unitNetPrice),
'discountPercentage' => 0,
'description' => $description,
];
@@ -283,6 +312,20 @@ class economic_invoice_draft
$this->draft_lines[] = $line;
}
private function convertCurrency(float $amount): float
{
// Convert the amount to the correct currency
$converted_value = $amount * self::getConversionRate();
// Round the value to 2 decimal places
return round($converted_value, 2);
}
private function getConversionRate(): float
{
// Get the conversion rate for the currency
return $this->conversion_rate;
}
/**
* Add a discount line to the draft invoice
* @note The lines won't be saved until the addLines() method is called.
@@ -299,7 +342,7 @@ class economic_invoice_draft
'productNumber' => 'TotDiscount',
],
'quantity' => 1,
'unitNetPrice' => -$discount,
'unitNetPrice' => self::convertCurrency(-$discount),
'discountPercentage' => 0,
'description' => 'Rabat',
];
@@ -620,12 +620,29 @@ class collected_order_invoices_o extends db
$economic = new economic();
$economic->invoices->draft->add_order(
self::getInvoiceDraftId(),
$order
$order,
(string)self::getCustomerCurrency($order->customer_id->value()),
);
return $this;
}
/**
* Get the customer currency
* @return string The customer currency
* @throws Exception If the request was not successful
* @throws Exception If the invoice collection is not set
*/
public function getCustomerCurrency(int $customer_number): string
{
// Require the invoice collection to be selected
self::requireSelected();
// Get the customer object
$customer = (new economic())->getCustomer($customer_number);
// Get the customer currency
return $customer->getCurrency();
}
/**
* Close the invoice collection
* @throws Exception If the request was not successful
@@ -169,12 +169,28 @@ class currency_conversion_rates_o extends db
if ($amount <= 0) {
throw new Exception('The amount is not valid.');
}
// Convert the amount
return self::getRate($currency) * $amount;
}
/**
* Get the conversion rate for a currency
* @param string $currency The currency to get (e.g. "DKK")
* @return float The conversion rate (e.g. 1.0)
* @throws Exception If the currency is not valid
*/
public function getRate(string $currency): float
{
// Check if the currency is valid
if (!self::validateCurrencyFormat($currency)) {
throw new Exception('The currency is not valid.');
}
// Get the conversion rate
$result = self::getFieldsWhere(['currency' => $currency], ['rate']);
if (empty($result)) {
throw new Exception('The currency conversion rate does not exist.');
}
return (float)$result[0]['rate'] * $amount;
return (float)$result[0]['rate'];
}
}