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.
196 lines
6.6 KiB
PHP
196 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace objects;
|
|
|
|
use classes\db;
|
|
use classes\object_property;
|
|
use Exception;
|
|
use traits\db_object_t;
|
|
|
|
class currency_conversion_rates_o extends db
|
|
{
|
|
use db_object_t;
|
|
|
|
public object_property $currency;
|
|
public object_property $rate;
|
|
public object_property $updated_at;
|
|
public object_property $created_at;
|
|
|
|
|
|
public function structure(): void
|
|
{
|
|
$this->setTable('currency_conversion_rates');
|
|
}
|
|
|
|
public function asArray(): array
|
|
{
|
|
return [
|
|
'id' => (int)$this->id,
|
|
'currency' => (string)$this->currency->value(),
|
|
'rate' => (float)$this->rate->value(),
|
|
'updated_at' => (string)$this->updated_at->value(),
|
|
'created_at' => (string)$this->created_at->value(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Update (or create) the conversion rates
|
|
* @param object $currencies The currencies to update (e.g. { "DKK": 1.0, "EUR": 0.5 })
|
|
* @return void
|
|
* @throws Exception If the currency is not valid
|
|
* @throws Exception If the rate is not valid
|
|
*/
|
|
public function setMany(object $currencies): void
|
|
{
|
|
// Check if the currencies are valid
|
|
if (!is_object($currencies)) {
|
|
throw new Exception('The currencies are not valid.');
|
|
}
|
|
// Check if the currencies are empty
|
|
if (empty($currencies)) {
|
|
throw new Exception('The currencies are empty.');
|
|
}
|
|
// Transform the object to an array
|
|
$currencies = (array)$currencies;
|
|
foreach ( $currencies as $currency => $relative_rate ) {
|
|
// Check if the currency is valid
|
|
if (!self::validateCurrencyFormat($currency)) {
|
|
throw new Exception('The currency is not valid. (' . $currency . ')');
|
|
}
|
|
// Check if the rate is valid
|
|
if ($relative_rate <= 0) {
|
|
throw new Exception('The rate is not valid.');
|
|
}
|
|
// Update the conversion rate
|
|
self::set($currency, $relative_rate);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate the format of a currency
|
|
* @note This simply checks if the currency is in the format of up to three uppercase letters.
|
|
* @note This does not check if the currency is actually valid.
|
|
* @param string $currency
|
|
* @return bool
|
|
*/
|
|
public static function validateCurrencyFormat(string $currency): bool
|
|
{
|
|
return (bool)preg_match('/^[A-Z]{1,3}$/', $currency);
|
|
}
|
|
|
|
/**
|
|
* Update (or create) the conversion rate for a currency
|
|
* @param string $currency The currency to update (e.g. "DKK")
|
|
* @param float $relative_rate The conversion rate to update (e.g. 1.0)
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function set(string $currency, float $relative_rate): void
|
|
{
|
|
global /** @var db $db */
|
|
$db;
|
|
// Check if the object exists
|
|
if (!self::countRowsWhere(['currency' => $currency])) {
|
|
// If not, add it
|
|
self::add($currency, $relative_rate);
|
|
return;
|
|
}
|
|
// If it does, update it
|
|
// Get the object
|
|
$result = self::getFieldsWhere(['currency' => $currency], ['id']);
|
|
if (empty($result)) {
|
|
throw new Exception('The currency conversion rate does exist, but the id was not found.');
|
|
}
|
|
self::select((int)$result[0]['id']);
|
|
// Update the object
|
|
$this->rate->set((float)$relative_rate);
|
|
self::objectChanged();
|
|
}
|
|
|
|
/**
|
|
* Add a new object to the database
|
|
* @param string $currency The currency to update (e.g. "DKK")
|
|
* @param float $relative_rate The conversion rate to update (e.g. 1.0)
|
|
* @return currency_conversion_rates_o
|
|
* @throws Exception If the object was not created successfully
|
|
*/
|
|
public function add(string $currency, float $relative_rate): self
|
|
{
|
|
global /** @var db $db */
|
|
$db;
|
|
// Sanitize the input
|
|
$currency = $db->escape_string($currency);
|
|
$relative_rate = (float)$relative_rate;
|
|
// Check if the currency is valid
|
|
if (!self::validateCurrencyFormat($currency)) {
|
|
throw new Exception('The currency is not valid.');
|
|
}
|
|
// Check if the rate is valid
|
|
if ($relative_rate <= 0) {
|
|
throw new Exception('The rate is not valid.');
|
|
}
|
|
// Add the object
|
|
$tmp_id = self::add_object([
|
|
'currency' => $currency,
|
|
'rate' => $relative_rate,
|
|
]);
|
|
$this->id = $tmp_id;
|
|
self::getObjectProperties();
|
|
self::objectChanged();
|
|
return $this;
|
|
}
|
|
|
|
public function getObjectProperties(): void
|
|
{
|
|
$this->currency = new object_property($this->table, $this->id, 'currency', 'string', false);
|
|
$this->rate = new object_property($this->table, $this->id, 'rate', 'float', false);
|
|
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'datetime', false);
|
|
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'datetime', false);
|
|
}
|
|
|
|
public function objectChanged(): void
|
|
{
|
|
//TODO: Add cache invalidation
|
|
}
|
|
|
|
/**
|
|
* Convert an amount from the base currency to the target currency
|
|
* @param string $currency The target currency (e.g. "EUR")
|
|
* @param float $amount The amount to convert in the base currency (e.g. 100) which is 100 DKK
|
|
* @throws Exception
|
|
*/
|
|
public function convertTo(string $currency, float $amount): float
|
|
{
|
|
// Check if the currency is valid
|
|
if (!self::validateCurrencyFormat($currency)) {
|
|
throw new Exception('The currency is not valid.');
|
|
}
|
|
// Check if the amount is valid
|
|
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'];
|
|
}
|
|
|
|
} |