diff --git a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php
index 3241d0f300..a02c864854 100644
--- a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php
+++ b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php
@@ -88,7 +88,7 @@ class UpdateRequest extends FormRequest
'notes',
];
- $this->floatFields = [
+ $this->floatFields = [ // not really floats, for validation.
'amount',
'foreign_amount',
];
@@ -408,8 +408,7 @@ class UpdateRequest extends FormRequest
if (array_key_exists($fieldName, $transaction)) {
$value = $transaction[$fieldName];
if (is_float($value)) {
- // TODO this effectively limits the max number of decimals in currencies to 14.
- $current[$fieldName] = sprintf('%.14f', $value);
+ $current[$fieldName] = sprintf('%.24f', $value);
}
if (!is_float($value)) {
$current[$fieldName] = (string) $value;
diff --git a/app/Api/V1/Requests/User/PreferenceStoreRequest.php b/app/Api/V1/Requests/User/PreferenceStoreRequest.php
index 06d3b51822..384c386d25 100644
--- a/app/Api/V1/Requests/User/PreferenceStoreRequest.php
+++ b/app/Api/V1/Requests/User/PreferenceStoreRequest.php
@@ -47,9 +47,8 @@ class PreferenceStoreRequest extends FormRequest
if ('false' === $array['data']) {
$array['data'] = false;
}
- // TODO remove float
if (is_numeric($array['data'])) {
- $array['data'] = (float) $array['data'];
+ $array['data'] = (float) $array['data']; // intentional float.
}
return $array;
diff --git a/app/Api/V1/Requests/User/PreferenceUpdateRequest.php b/app/Api/V1/Requests/User/PreferenceUpdateRequest.php
index 130ed7b376..d22fd73728 100644
--- a/app/Api/V1/Requests/User/PreferenceUpdateRequest.php
+++ b/app/Api/V1/Requests/User/PreferenceUpdateRequest.php
@@ -48,9 +48,8 @@ class PreferenceUpdateRequest extends FormRequest
if ('false' === $array['data']) {
$array['data'] = false;
}
- // TODO remove float
if (is_numeric($array['data'])) {
- $array['data'] = (float) $array['data'];
+ $array['data'] = (float) $array['data']; // intentional float.
}
return $array;
diff --git a/app/Http/Controllers/Report/TagController.php b/app/Http/Controllers/Report/TagController.php
index 9fb3828453..5cb8b7f3fe 100644
--- a/app/Http/Controllers/Report/TagController.php
+++ b/app/Http/Controllers/Report/TagController.php
@@ -543,7 +543,7 @@ class TagController extends Controller
$result[] = [
'description' => $journal['description'],
'transaction_group_id' => $journal['transaction_group_id'],
- 'amount_float' => (float) $journal['amount'],
+ 'amount_float' => (float) $journal['amount'], // intentional float.
'amount' => $journal['amount'],
'date' => $journal['date']->isoFormat($this->monthAndDayFormat),
'date_sort' => $journal['date']->format('Y-m-d'),
diff --git a/app/Http/Requests/RecurrenceFormRequest.php b/app/Http/Requests/RecurrenceFormRequest.php
index 439dd6e0ca..b607162ca0 100644
--- a/app/Http/Requests/RecurrenceFormRequest.php
+++ b/app/Http/Requests/RecurrenceFormRequest.php
@@ -100,7 +100,7 @@ class RecurrenceFormRequest extends FormRequest
];
// fill in foreign currency data
- if (null !== $this->convertFloat('foreign_amount')) {
+ if (null !== $this->convertFloat('foreign_amount')) { // intentional float, used because it defaults to null.
$return['transactions'][0]['foreign_amount'] = $this->convertString('foreign_amount');
$return['transactions'][0]['foreign_currency_id'] = $this->convertInteger('foreign_currency_id');
}
@@ -229,7 +229,7 @@ class RecurrenceFormRequest extends FormRequest
$rules['repetitions'] = 'required|numeric|between:0,254';
}
// if foreign amount, currency must be different.
- if (null !== $this->convertFloat('foreign_amount')) {
+ if (null !== $this->convertFloat('foreign_amount')) { // intentional float, used because it defaults to null.
$rules['foreign_currency_id'] = 'exists:transaction_currencies,id|different:transaction_currency_id';
}
diff --git a/app/Support/Amount.php b/app/Support/Amount.php
index f02340a4ec..485a9fa94d 100644
--- a/app/Support/Amount.php
+++ b/app/Support/Amount.php
@@ -70,21 +70,21 @@ class Amount
*/
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, bool $coloured = null): string
{
- $locale = app('steam')->getLocale();
-
+ $locale = app('steam')->getLocale();
+ $rounded = app('steam')->bcround($amount, $decimalPlaces);
$coloured = $coloured ?? true;
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
- $result = $fmt->format((float)app('steam')->bcround($amount, $decimalPlaces)); // intentional float
+ $result = $fmt->format((float)$rounded); // intentional float
if (true === $coloured) {
- if (1 === bccomp($amount, '0')) {
+ if (1 === bccomp($rounded, '0')) {
return sprintf('%s', $result);
}
- if (-1 === bccomp($amount, '0')) {
+ if (-1 === bccomp($rounded, '0')) {
return sprintf('%s', $result);
}
diff --git a/app/Support/Chart/Category/FrontpageChartGenerator.php b/app/Support/Chart/Category/FrontpageChartGenerator.php
index 0a1d86d042..b251399455 100644
--- a/app/Support/Chart/Category/FrontpageChartGenerator.php
+++ b/app/Support/Chart/Category/FrontpageChartGenerator.php
@@ -151,7 +151,7 @@ class FrontpageChartGenerator
$tempData[] = [
'name' => trans('firefly.no_category'),
'sum' => $currency['sum'],
- 'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places'] ?? 2),
+ 'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float
'currency_id' => (int) $currency['currency_id'],
];
}
diff --git a/app/Support/Http/Controllers/ModelInformation.php b/app/Support/Http/Controllers/ModelInformation.php
index c186933a76..7581e2b871 100644
--- a/app/Support/Http/Controllers/ModelInformation.php
+++ b/app/Support/Http/Controllers/ModelInformation.php
@@ -130,8 +130,8 @@ trait ModelInformation
$billTriggers = ['currency_is', 'amount_more', 'amount_less', 'description_contains'];
$values = [
$bill->transactionCurrency()->first()->name,
- round((float) $bill->amount_min, 24),
- round((float) $bill->amount_max, 24),
+ $bill->amount_min,
+ $bill->amount_max,
$bill->name,
];
foreach ($billTriggers as $index => $trigger) {
diff --git a/app/Support/Steam.php b/app/Support/Steam.php
index 5e2dd76dfb..1958cb78d0 100644
--- a/app/Support/Steam.php
+++ b/app/Support/Steam.php
@@ -104,13 +104,19 @@ class Steam
*/
public function bcround(?string $number, int $precision = 0): string
{
+
if(null === $number) {
return '0';
}
if('' === trim($number)) {
return '0';
}
- Log::debug(sprintf('Trying bcround("%",%d)', $number, $precision));
+ // if the number contains "E", it's in scientific notation, so we need to convert it to a normal number first.
+ if(false !== stripos($number,'e')) {
+ $number = sprintf('%.24f',$number);
+ }
+
+ Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
if (str_contains($number, '.')) {
if ($number[0] !== '-') {
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
@@ -584,8 +590,10 @@ class Steam
if ($mantis < 0) {
$post += abs((int)$mantis);
}
+ // TODO careless float could break financial math.
return number_format((float)$value, $post, '.', '');
}
+ // TODO careless float could break financial math.
return number_format((float)$value, 0, '.', '');
}
diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php
index a6227be244..cc56a4b3f8 100644
--- a/app/Transformers/AccountTransformer.php
+++ b/app/Transformers/AccountTransformer.php
@@ -78,7 +78,7 @@ class AccountTransformer extends AbstractTransformer
[$openingBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType);
[$interest, $interestPeriod] = $this->getInterest($account, $accountType);
- $openingBalance = number_format((float) $openingBalance, $decimalPlaces, '.', '');
+ $openingBalance = app('steam')->bcround($openingBalance, $decimalPlaces);
$includeNetWorth = '0' !== $this->repository->getMetaValue($account, 'include_net_worth');
$longitude = null;
$latitude = null;
@@ -109,7 +109,7 @@ class AccountTransformer extends AbstractTransformer
'currency_code' => $currencyCode,
'currency_symbol' => $currencySymbol,
'currency_decimal_places' => $decimalPlaces,
- 'current_balance' => number_format((float) app('steam')->balance($account, $date), $decimalPlaces, '.', ''),
+ 'current_balance' => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces),
'current_balance_date' => $date->toAtomString(),
'notes' => $this->repository->getNoteText($account),
'monthly_payment_date' => $monthlyPaymentDate,
@@ -117,7 +117,7 @@ class AccountTransformer extends AbstractTransformer
'account_number' => $this->repository->getMetaValue($account, 'account_number'),
'iban' => '' === $account->iban ? null : $account->iban,
'bic' => $this->repository->getMetaValue($account, 'BIC'),
- 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
+ 'virtual_balance' => app('steam')->bcround($account->virtual_balance, $decimalPlaces),
'opening_balance' => $openingBalance,
'opening_balance_date' => $openingBalanceDate,
'liability_type' => $liabilityType,
diff --git a/app/Transformers/AvailableBudgetTransformer.php b/app/Transformers/AvailableBudgetTransformer.php
index b9fd050673..62944bab86 100644
--- a/app/Transformers/AvailableBudgetTransformer.php
+++ b/app/Transformers/AvailableBudgetTransformer.php
@@ -69,7 +69,7 @@ class AvailableBudgetTransformer extends AbstractTransformer
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int) $currency->decimal_places,
- 'amount' => number_format((float) $availableBudget->amount, $currency->decimal_places, '.', ''),
+ 'amount' => app('steam')->bcround($availableBudget->amount, $currency->decimal_places),
'start' => $availableBudget->start_date->toAtomString(),
'end' => $availableBudget->end_date->endOfDay()->toAtomString(),
'spent_in_budgets' => [],
diff --git a/app/Transformers/BillTransformer.php b/app/Transformers/BillTransformer.php
index f469b0c698..54b1d11348 100644
--- a/app/Transformers/BillTransformer.php
+++ b/app/Transformers/BillTransformer.php
@@ -115,8 +115,8 @@ class BillTransformer extends AbstractTransformer
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int) $currency->decimal_places,
'name' => $bill->name,
- 'amount_min' => number_format((float) $bill->amount_min, $currency->decimal_places, '.', ''),
- 'amount_max' => number_format((float) $bill->amount_max, $currency->decimal_places, '.', ''),
+ 'amount_min' => app('steam')->bcround($bill->amount_min, $currency->decimal_places),
+ 'amount_max' => app('steam')->bcround($bill->amount_max, $currency->decimal_places),
'date' => $bill->date->toAtomString(),
'end_date' => $bill->end_date?->toAtomString(),
'extension_date' => $bill->extension_date?->toAtomString(),
diff --git a/app/Transformers/BudgetLimitTransformer.php b/app/Transformers/BudgetLimitTransformer.php
index d7431a77ff..6850d09487 100644
--- a/app/Transformers/BudgetLimitTransformer.php
+++ b/app/Transformers/BudgetLimitTransformer.php
@@ -84,7 +84,7 @@ class BudgetLimitTransformer extends AbstractTransformer
$currencySymbol = $currency->symbol;
$currencyDecimalPlaces = $currency->decimal_places;
}
- $amount = number_format((float) $amount, $currencyDecimalPlaces, '.', '');
+ $amount = app('steam')->bcround($amount, $currencyDecimalPlaces);
return [
'id' => (string) $budgetLimit->id,
diff --git a/app/Transformers/BudgetTransformer.php b/app/Transformers/BudgetTransformer.php
index 218083d9b2..e4b6f16dfc 100644
--- a/app/Transformers/BudgetTransformer.php
+++ b/app/Transformers/BudgetTransformer.php
@@ -84,7 +84,7 @@ class BudgetTransformer extends AbstractTransformer
$abCurrencyId = (string) $autoBudget->transactionCurrency->id;
$abCurrencyCode = $autoBudget->transactionCurrency->code;
$abType = $types[$autoBudget->auto_budget_type];
- $abAmount = number_format((float) $autoBudget->amount, $autoBudget->transactionCurrency->decimal_places, '.', '');
+ $abAmount = app('steam')->bcround($autoBudget->amount, $autoBudget->transactionCurrency->decimal_places);
$abPeriod = $autoBudget->period;
}
@@ -120,7 +120,7 @@ class BudgetTransformer extends AbstractTransformer
{
$return = [];
foreach ($array as $data) {
- $data['sum'] = number_format((float) $data['sum'], (int) $data['currency_decimal_places'], '.', '');
+ $data['sum'] = app('steam')->bcround($data['sum'], (int) $data['currency_decimal_places']);
$return[] = $data;
}
diff --git a/app/Transformers/CategoryTransformer.php b/app/Transformers/CategoryTransformer.php
index 295b30fa01..81fe257bf8 100644
--- a/app/Transformers/CategoryTransformer.php
+++ b/app/Transformers/CategoryTransformer.php
@@ -95,7 +95,7 @@ class CategoryTransformer extends AbstractTransformer
{
$return = [];
foreach ($array as $data) {
- $data['sum'] = number_format((float) $data['sum'], (int) $data['currency_decimal_places'], '.', '');
+ $data['sum'] = app('steam')->bcround($data['sum'], (int) $data['currency_decimal_places']);
$return[] = $data;
}
diff --git a/app/Transformers/PiggyBankEventTransformer.php b/app/Transformers/PiggyBankEventTransformer.php
index caa8b52042..5a925c6428 100644
--- a/app/Transformers/PiggyBankEventTransformer.php
+++ b/app/Transformers/PiggyBankEventTransformer.php
@@ -83,7 +83,7 @@ class PiggyBankEventTransformer extends AbstractTransformer
'id' => (string) $event->id,
'created_at' => $event->created_at->toAtomString(),
'updated_at' => $event->updated_at->toAtomString(),
- 'amount' => number_format((float) $event->amount, $currency->decimal_places, '.', ''),
+ 'amount' => app('steam')->bcround($event->amount, $currency->decimal_places),
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
diff --git a/app/Transformers/PiggyBankTransformer.php b/app/Transformers/PiggyBankTransformer.php
index 7a66774b43..aca43a7a69 100644
--- a/app/Transformers/PiggyBankTransformer.php
+++ b/app/Transformers/PiggyBankTransformer.php
@@ -53,7 +53,7 @@ class PiggyBankTransformer extends AbstractTransformer
/**
* Transform the piggy bank.
*
- * @param PiggyBank $piggyBank
+ * @param PiggyBank $piggyBank
*
* @return array
* @throws \FireflyIII\Exceptions\FireflyException
@@ -81,44 +81,44 @@ class PiggyBankTransformer extends AbstractTransformer
/** @var ObjectGroup $objectGroup */
$objectGroup = $piggyBank->objectGroups->first();
if (null !== $objectGroup) {
- $objectGroupId = (int) $objectGroup->id;
- $objectGroupOrder = (int) $objectGroup->order;
+ $objectGroupId = (int)$objectGroup->id;
+ $objectGroupOrder = (int)$objectGroup->order;
$objectGroupTitle = $objectGroup->title;
}
// get currently saved amount:
$currentAmountStr = $this->piggyRepos->getCurrentAmount($piggyBank);
- $currentAmount = number_format((float) $currentAmountStr, $currency->decimal_places, '.', '');
+ $currentAmount = app('steam')->bcround($currentAmountStr, $currency->decimal_places);
// Amounts, depending on 0.0 state of target amount
$percentage = null;
$targetAmountString = null;
$leftToSaveString = null;
$savePerMonth = null;
- if (0.000 !== (float) $piggyBank->targetamount) {
+ if (0 !== bccomp(app('steam')->bcround($currentAmountStr, $currency->decimal_places), '0')) {
$leftToSave = bcsub($piggyBank->targetamount, $currentAmountStr);
- $targetAmount = (string) $piggyBank->targetamount;
+ $targetAmount = (string)$piggyBank->targetamount;
$targetAmount = 1 === bccomp('0.01', $targetAmount) ? '0.01' : $targetAmount;
- $percentage = (int) (0 !== bccomp('0', $currentAmountStr) ? $currentAmountStr / $targetAmount * 100 : 0);
- $targetAmountString = number_format((float) $targetAmount, $currency->decimal_places, '.', '');
- $leftToSaveString = number_format((float) $leftToSave, $currency->decimal_places, '.', '');
- $savePerMonth = number_format((float) $this->piggyRepos->getSuggestedMonthlyAmount($piggyBank), $currency->decimal_places, '.', '');
+ $percentage = (int)(0 !== bccomp('0', $currentAmountStr) ? $currentAmountStr / $targetAmount * 100 : 0);
+ $targetAmountString = app('steam')->bcround($targetAmount, $currency->decimal_places);
+ $leftToSaveString = app('steam')->bcround($leftToSave, $currency->decimal_places);
+ $savePerMonth = app('steam')->bcround($this->piggyRepos->getSuggestedMonthlyAmount($piggyBank), $currency->decimal_places);
}
$startDate = $piggyBank->startdate?->toAtomString();
$targetDate = $piggyBank->targetdate?->toAtomString();
return [
- 'id' => (string) $piggyBank->id,
+ 'id' => (string)$piggyBank->id,
'created_at' => $piggyBank->created_at->toAtomString(),
'updated_at' => $piggyBank->updated_at->toAtomString(),
- 'account_id' => (string) $piggyBank->account_id,
+ 'account_id' => (string)$piggyBank->account_id,
'account_name' => $piggyBank->account->name,
'name' => $piggyBank->name,
- 'currency_id' => (string) $currency->id,
+ 'currency_id' => (string)$currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
- 'currency_decimal_places' => (int) $currency->decimal_places,
+ 'currency_decimal_places' => (int)$currency->decimal_places,
'target_amount' => $targetAmountString,
'percentage' => $percentage,
'current_amount' => $currentAmount,
@@ -126,16 +126,16 @@ class PiggyBankTransformer extends AbstractTransformer
'save_per_month' => $savePerMonth,
'start_date' => $startDate,
'target_date' => $targetDate,
- 'order' => (int) $piggyBank->order,
+ 'order' => (int)$piggyBank->order,
'active' => true,
'notes' => $notes,
- 'object_group_id' => $objectGroupId ? (string) $objectGroupId : null,
+ 'object_group_id' => $objectGroupId ? (string)$objectGroupId : null,
'object_group_order' => $objectGroupOrder,
'object_group_title' => $objectGroupTitle,
'links' => [
[
'rel' => 'self',
- 'uri' => '/piggy_banks/' . $piggyBank->id,
+ 'uri' => '/piggy_banks/'.$piggyBank->id,
],
],
];
diff --git a/app/Transformers/RecurrenceTransformer.php b/app/Transformers/RecurrenceTransformer.php
index 42172ea2e3..be829e8e4e 100644
--- a/app/Transformers/RecurrenceTransformer.php
+++ b/app/Transformers/RecurrenceTransformer.php
@@ -196,10 +196,10 @@ class RecurrenceTransformer extends AbstractTransformer
$destinationType = $destinationAccount->accountType->type;
$destinationIban = $destinationAccount->iban;
}
- $amount = number_format((float) $transaction->amount, $transaction->transactionCurrency->decimal_places, '.', '');
+ $amount = app('steam')->bcround($transaction->amount, $transaction->transactionCurrency->decimal_places);
$foreignAmount = null;
if (null !== $transaction->foreign_currency_id && null !== $transaction->foreign_amount) {
- $foreignAmount = number_format((float) $transaction->foreign_amount, $foreignCurrencyDp, '.', '');
+ $foreignAmount = app('steam')->bcround($transaction->foreign_amount, $foreignCurrencyDp);
}
$transactionArray = [
'currency_id' => (string) $transaction->transaction_currency_id,
diff --git a/app/Transformers/TransactionGroupTransformer.php b/app/Transformers/TransactionGroupTransformer.php
index 4baa7e8c95..adf222c03a 100644
--- a/app/Transformers/TransactionGroupTransformer.php
+++ b/app/Transformers/TransactionGroupTransformer.php
@@ -364,7 +364,7 @@ class TransactionGroupTransformer extends AbstractTransformer
$bill = $this->getBill($journal->bill);
if (null !== $foreignAmount && null !== $foreignCurrency) {
- $foreignAmount = number_format((float) $foreignAmount, $foreignCurrency['decimal_places'] ?? 0, '.', '');
+ $foreignAmount = app('steam')->bcround($foreignAmount, $foreignCurrency['decimal_places'] ?? 0);
}
$longitude = null;
@@ -394,7 +394,7 @@ class TransactionGroupTransformer extends AbstractTransformer
'foreign_currency_symbol' => $foreignCurrency['symbol'],
'foreign_currency_decimal_places' => $foreignCurrency['decimal_places'],
- 'amount' => number_format((float) $amount, $currency->decimal_places, '.', ''),
+ 'amount' => app('steam')->bcround($amount, $currency->decimal_places),
'foreign_amount' => $foreignAmount,
'description' => $journal->description,
@@ -462,7 +462,7 @@ class TransactionGroupTransformer extends AbstractTransformer
{
$result = $journal->transactions->first(
static function (Transaction $transaction) {
- return (float) $transaction->amount < 0;
+ return (float) $transaction->amount < 0; // lame but it works.
}
);
if (null === $result) {
@@ -482,7 +482,7 @@ class TransactionGroupTransformer extends AbstractTransformer
{
$result = $journal->transactions->first(
static function (Transaction $transaction) {
- return (float) $transaction->amount > 0;
+ return (float) $transaction->amount > 0; // lame but it works
}
);
if (null === $result) {