mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-14 16:13:54 +00:00
Clean up balance methods.
This commit is contained in:
@@ -64,7 +64,7 @@ class AccountBalanceGrouped
|
||||
/** @var array $currency */
|
||||
foreach ($this->data as $currency) {
|
||||
// income and expense array prepped:
|
||||
$income = [
|
||||
$income = [
|
||||
'label' => 'earned',
|
||||
'currency_id' => (string) $currency['currency_id'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
@@ -81,7 +81,7 @@ class AccountBalanceGrouped
|
||||
'entries' => [],
|
||||
'native_entries' => [],
|
||||
];
|
||||
$expense = [
|
||||
$expense = [
|
||||
'label' => 'spent',
|
||||
'currency_id' => (string) $currency['currency_id'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
@@ -101,22 +101,22 @@ class AccountBalanceGrouped
|
||||
// loop all possible periods between $start and $end, and add them to the correct dataset.
|
||||
$currentStart = clone $this->start;
|
||||
while ($currentStart <= $this->end) {
|
||||
$key = $currentStart->format($this->carbonFormat);
|
||||
$label = $currentStart->toAtomString();
|
||||
$key = $currentStart->format($this->carbonFormat);
|
||||
$label = $currentStart->toAtomString();
|
||||
// normal entries
|
||||
$income['entries'][$label] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
|
||||
$expense['entries'][$label] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
|
||||
$income['entries'][$label] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
|
||||
$expense['entries'][$label] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
|
||||
|
||||
// converted entries
|
||||
$income['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_earned'] ?? '0', $currency['native_currency_decimal_places']);
|
||||
$expense['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_spent'] ?? '0', $currency['native_currency_decimal_places']);
|
||||
|
||||
// next loop
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
||||
}
|
||||
|
||||
$chartData[] = $income;
|
||||
$chartData[] = $expense;
|
||||
$chartData[] = $income;
|
||||
$chartData[] = $expense;
|
||||
}
|
||||
|
||||
return $chartData;
|
||||
@@ -142,9 +142,9 @@ class AccountBalanceGrouped
|
||||
private function processJournal(array $journal): void
|
||||
{
|
||||
// format the date according to the period
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currency = $this->findCurrency($currencyId);
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currency = $this->findCurrency($currencyId);
|
||||
|
||||
// set the array with monetary info, if it does not exist.
|
||||
$this->createDefaultDataEntry($journal);
|
||||
@@ -152,12 +152,12 @@ class AccountBalanceGrouped
|
||||
$this->createDefaultPeriodEntry($journal);
|
||||
|
||||
// is this journal's amount in- our outgoing?
|
||||
$key = $this->getDataKey($journal);
|
||||
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
||||
$key = $this->getDataKey($journal);
|
||||
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
||||
|
||||
// get conversion rate
|
||||
$rate = $this->getRate($currency, $journal['date']);
|
||||
$amountConverted = bcmul($amount, $rate);
|
||||
$rate = $this->getRate($currency, $journal['date']);
|
||||
$amountConverted = bcmul($amount, $rate);
|
||||
|
||||
// perhaps transaction already has the foreign amount in the native currency.
|
||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||
@@ -166,7 +166,7 @@ class AccountBalanceGrouped
|
||||
}
|
||||
|
||||
// add normal entry
|
||||
$this->data[$currencyId][$period][$key] = bcadd($this->data[$currencyId][$period][$key], $amount);
|
||||
$this->data[$currencyId][$period][$key] = bcadd($this->data[$currencyId][$period][$key], $amount);
|
||||
|
||||
// add converted entry
|
||||
$convertedKey = sprintf('native_%s', $key);
|
||||
@@ -185,7 +185,7 @@ class AccountBalanceGrouped
|
||||
|
||||
private function createDefaultDataEntry(array $journal): void
|
||||
{
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$this->data[$currencyId] ??= [
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_symbol' => $journal['currency_symbol'],
|
||||
@@ -202,8 +202,8 @@ class AccountBalanceGrouped
|
||||
|
||||
private function createDefaultPeriodEntry(array $journal): void
|
||||
{
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$this->data[$currencyId][$period] ??= [
|
||||
'period' => $period,
|
||||
'spent' => '0',
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\Http\Api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateTimeInterface;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,7 @@ trait ConvertsExchangeRates
|
||||
|
||||
// if not enabled, return the same array but without conversion:
|
||||
return $set;
|
||||
$this->enabled = false;
|
||||
$this->enabled = false;
|
||||
if (false === $this->enabled) {
|
||||
$set['converted'] = false;
|
||||
|
||||
@@ -55,8 +56,8 @@ trait ConvertsExchangeRates
|
||||
$set['converted'] = true;
|
||||
|
||||
/** @var TransactionCurrency $native */
|
||||
$native = app('amount')->getDefaultCurrency();
|
||||
$currency = $this->getCurrency((int) $set['currency_id']);
|
||||
$native = app('amount')->getDefaultCurrency();
|
||||
$currency = $this->getCurrency((int) $set['currency_id']);
|
||||
if ($native->id === $currency->id) {
|
||||
$set['native_currency_id'] = (string) $currency->id;
|
||||
$set['native_currency_code'] = $currency->code;
|
||||
@@ -66,9 +67,9 @@ trait ConvertsExchangeRates
|
||||
return $set;
|
||||
}
|
||||
foreach ($set['entries'] as $date => $entry) {
|
||||
$carbon = Carbon::createFromFormat(\DateTimeInterface::ATOM, $date);
|
||||
$rate = $this->getRate($currency, $native, $carbon);
|
||||
$rate = '0' === $rate ? '1' : $rate;
|
||||
$carbon = Carbon::createFromFormat(DateTimeInterface::ATOM, $date);
|
||||
$rate = $this->getRate($currency, $native, $carbon);
|
||||
$rate = '0' === $rate ? '1' : $rate;
|
||||
app('log')->debug(sprintf('bcmul("%s", "%s")', (string) $entry, $rate));
|
||||
$set['entries'][$date] = (float) bcmul((string) $entry, $rate);
|
||||
}
|
||||
|
@@ -85,8 +85,8 @@ class ExchangeRateConverter
|
||||
*/
|
||||
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||
{
|
||||
$key = $this->getCacheKey($from, $to, $date);
|
||||
$res = Cache::get($key, null);
|
||||
$key = $this->getCacheKey($from, $to, $date);
|
||||
$res = Cache::get($key, null);
|
||||
|
||||
// find in cache
|
||||
if (null !== $res) {
|
||||
@@ -96,7 +96,7 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
// find in database
|
||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
Cache::forever($key, $rate);
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
@@ -105,7 +105,7 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
// find reverse in database
|
||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
$rate = bcdiv('1', $rate);
|
||||
Cache::forever($key, $rate);
|
||||
@@ -143,7 +143,7 @@ class ExchangeRateConverter
|
||||
if ($from === $to) {
|
||||
return '1';
|
||||
}
|
||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||
|
||||
// perhaps the rate has been cached during this particular run
|
||||
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
||||
@@ -153,7 +153,7 @@ class ExchangeRateConverter
|
||||
return $preparedRate;
|
||||
}
|
||||
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
$rate = $cache->get();
|
||||
@@ -166,16 +166,15 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
/** @var null|CurrencyExchangeRate $result */
|
||||
$result = auth()->user()
|
||||
?->currencyExchangeRates()
|
||||
->where('from_currency_id', $from)
|
||||
->where('to_currency_id', $to)
|
||||
->where('date', '<=', $date)
|
||||
->orderBy('date', 'DESC')
|
||||
->first()
|
||||
;
|
||||
$result = auth()->user()
|
||||
?->currencyExchangeRates()
|
||||
->where('from_currency_id', $from)
|
||||
->where('to_currency_id', $to)
|
||||
->where('date', '<=', $date)
|
||||
->orderBy('date', 'DESC')
|
||||
->first();
|
||||
++$this->queryCount;
|
||||
$rate = (string) $result?->rate;
|
||||
$rate = (string) $result?->rate;
|
||||
|
||||
if ('' === $rate) {
|
||||
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
||||
@@ -215,13 +214,13 @@ class ExchangeRateConverter
|
||||
if ($euroId === $currency->id) {
|
||||
return '1';
|
||||
}
|
||||
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
||||
|
||||
if (null !== $rate) {
|
||||
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
||||
return $rate;
|
||||
}
|
||||
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
return bcdiv('1', $rate);
|
||||
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
|
||||
@@ -250,7 +249,7 @@ class ExchangeRateConverter
|
||||
if ($cache->has()) {
|
||||
return (int) $cache->get();
|
||||
}
|
||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||
++$this->queryCount;
|
||||
if (null === $euro) {
|
||||
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
||||
@@ -272,14 +271,13 @@ class ExchangeRateConverter
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$set = auth()->user()
|
||||
->currencyExchangeRates()
|
||||
->where('from_currency_id', $from->id)
|
||||
->where('to_currency_id', $to->id)
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->where('date', '>=', $start->format('Y-m-d'))
|
||||
->orderBy('date', 'DESC')->get()
|
||||
;
|
||||
$set = auth()->user()
|
||||
->currencyExchangeRates()
|
||||
->where('from_currency_id', $from->id)
|
||||
->where('to_currency_id', $to->id)
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->where('date', '>=', $start->format('Y-m-d'))
|
||||
->orderBy('date', 'DESC')->get();
|
||||
++$this->queryCount;
|
||||
if (0 === $set->count()) {
|
||||
Log::debug('No prepared rates found in this period, use the fallback');
|
||||
@@ -293,10 +291,10 @@ class ExchangeRateConverter
|
||||
$this->isPrepared = true;
|
||||
|
||||
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
||||
$temp = [];
|
||||
$count = 0;
|
||||
$temp = [];
|
||||
$count = 0;
|
||||
foreach ($set as $rate) {
|
||||
$date = $rate->date->format('Y-m-d');
|
||||
$date = $rate->date->format('Y-m-d');
|
||||
$temp[$date] ??= [
|
||||
$from->id => [
|
||||
$to->id => $rate->rate,
|
||||
@@ -305,11 +303,11 @@ class ExchangeRateConverter
|
||||
++$count;
|
||||
}
|
||||
Log::debug(sprintf('Found %d rates in this period.', $count));
|
||||
$currentStart = clone $start;
|
||||
$currentStart = clone $start;
|
||||
while ($currentStart->lte($end)) {
|
||||
$currentDate = $currentStart->format('Y-m-d');
|
||||
$currentDate = $currentStart->format('Y-m-d');
|
||||
$this->prepared[$currentDate] ??= [];
|
||||
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
||||
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
||||
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
|
||||
// fill from temp or fallback or from temp (see before)
|
||||
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
||||
|
@@ -40,7 +40,7 @@ trait ParsesQueryFilters
|
||||
|
||||
private function dateOrToday(QueryParameters $parameters, string $field): Carbon
|
||||
{
|
||||
$date = today();
|
||||
$date = today();
|
||||
|
||||
$value = $parameters->filter()?->value($field, date('Y-m-d'));
|
||||
|
||||
|
@@ -30,7 +30,7 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SummaryBalanceGrouped
|
||||
{
|
||||
private const string SUM = 'sum';
|
||||
private const string SUM = 'sum';
|
||||
private array $amounts = [];
|
||||
private array $currencies;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
@@ -47,9 +47,9 @@ class SummaryBalanceGrouped
|
||||
public function groupData(): array
|
||||
{
|
||||
Log::debug('Now going to group data.');
|
||||
$return = [];
|
||||
$return = [];
|
||||
foreach ($this->keys as $key) {
|
||||
$title = match ($key) {
|
||||
$title = match ($key) {
|
||||
'sum' => 'balance',
|
||||
'expense' => 'spent',
|
||||
'income' => 'earned',
|
||||
@@ -108,11 +108,11 @@ class SummaryBalanceGrouped
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
// transaction info:
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$amount = bcmul($journal['amount'], $multiplier);
|
||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = $currency;
|
||||
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$amount = bcmul($journal['amount'], $multiplier);
|
||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = $currency;
|
||||
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||
// use foreign amount instead
|
||||
$nativeAmount = $journal['foreign_amount'];
|
||||
|
@@ -56,8 +56,8 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$groupId = 0;
|
||||
$user = auth()->user();
|
||||
$groupId = 0;
|
||||
if (!$request->has('user_group_id')) {
|
||||
$groupId = $user->user_group_id;
|
||||
Log::debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
|
||||
@@ -68,7 +68,7 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
/** @var UserGroupRepositoryInterface $repository */
|
||||
$repository = app(UserGroupRepositoryInterface::class);
|
||||
$repository = app(UserGroupRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
$memberships = $repository->getMembershipsFromGroupId($groupId);
|
||||
|
||||
@@ -79,14 +79,14 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
// need to get the group from the membership:
|
||||
$group = $repository->getById($groupId);
|
||||
$group = $repository->getById($groupId);
|
||||
if (null === $group) {
|
||||
Log::debug(sprintf('validateUserGroup: group #%d does not exist.', $groupId));
|
||||
|
||||
throw new AuthorizationException((string) trans('validation.belongs_user_or_user_group'));
|
||||
}
|
||||
Log::debug(sprintf('validateUserGroup: validate access of user to group #%d ("%s").', $groupId, $group->title));
|
||||
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : []; // @phpstan-ignore-line
|
||||
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : []; // @phpstan-ignore-line
|
||||
if (0 === count($roles)) {
|
||||
Log::debug('validateUserGroup: no roles defined, so no access.');
|
||||
|
||||
|
Reference in New Issue
Block a user