mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-03 11:08:28 +00:00
Fix #10180
This commit is contained in:
@@ -43,6 +43,7 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
|||||||
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
|
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,10 +105,10 @@ class BasicController extends Controller
|
|||||||
$billData = $this->getSubscriptionInformation($start, $end);
|
$billData = $this->getSubscriptionInformation($start, $end);
|
||||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||||
$netWorthData = $this->getNetWorthInfo($end);
|
$netWorthData = $this->getNetWorthInfo($end);
|
||||||
// $balanceData = [];
|
// $balanceData = [];
|
||||||
// $billData = [];
|
// $billData = [];
|
||||||
// $spentData = [];
|
// $spentData = [];
|
||||||
// $netWorthData = [];
|
// $netWorthData = [];
|
||||||
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
||||||
|
|
||||||
// give new keys
|
// give new keys
|
||||||
@@ -539,26 +540,63 @@ class BasicController extends Controller
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
unset($leftToSpend);
|
||||||
if (0 === count($return)) {
|
if (0 === count($return)) {
|
||||||
$currency = $this->nativeCurrency;
|
// a small trick to get every expense in this period, regardless of budget.
|
||||||
$return[$currency->id] = [
|
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection());
|
||||||
'key' => sprintf('left-to-spend-in-%s', $currency->code),
|
foreach ($spent as $row) {
|
||||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
|
// either an amount was budgeted or 0 is available.
|
||||||
'monetary_value' => '0',
|
$currencyId = (int) $row['currency_id'];
|
||||||
'no_available_budgets' => true,
|
$spentInCurrency = $row['sum'];
|
||||||
'currency_id' => (string) $currency->id,
|
$perDay = '0';
|
||||||
'currency_code' => $currency->code,
|
if (0 !== $days && -1 === bccomp($spentInCurrency, '0')) {
|
||||||
'currency_symbol' => $currency->symbol,
|
$perDay = bcdiv($spentInCurrency, (string) $days);
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
}
|
||||||
'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false),
|
|
||||||
'local_icon' => 'money',
|
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
|
||||||
'sub_title' => app('amount')->formatFlat(
|
|
||||||
$currency->symbol,
|
$return[$currencyId] = [
|
||||||
$currency->decimal_places,
|
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||||
'0',
|
'title' => trans('firefly.spent'),
|
||||||
false
|
'no_available_budgets' => true,
|
||||||
),
|
'monetary_value' => $spentInCurrency,
|
||||||
];
|
'currency_id' => (string) $row['currency_id'],
|
||||||
|
'currency_code' => $row['currency_code'],
|
||||||
|
'currency_symbol' => $row['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $row['currency_decimal_places'],
|
||||||
|
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $spentInCurrency, false),
|
||||||
|
'local_icon' => 'money',
|
||||||
|
'sub_title' => app('amount')->formatFlat(
|
||||||
|
$row['currency_symbol'],
|
||||||
|
$row['currency_decimal_places'],
|
||||||
|
$perDay,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// $amount = '0';
|
||||||
|
// // $days
|
||||||
|
// // fill in by money spent, just count it.
|
||||||
|
// $currency = $this->nativeCurrency;
|
||||||
|
// $return[$currency->id] = [
|
||||||
|
// 'key' => sprintf('left-to-spend-in-%s', $currency->code),
|
||||||
|
// 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
|
||||||
|
// 'monetary_value' => '0',
|
||||||
|
// 'no_available_budgets' => true,
|
||||||
|
// 'currency_id' => (string) $currency->id,
|
||||||
|
// 'currency_code' => $currency->code,
|
||||||
|
// 'currency_symbol' => $currency->symbol,
|
||||||
|
// 'currency_decimal_places' => $currency->decimal_places,
|
||||||
|
// 'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false),
|
||||||
|
// 'local_icon' => 'money',
|
||||||
|
// 'sub_title' => app('amount')->formatFlat(
|
||||||
|
// $currency->symbol,
|
||||||
|
// $currency->decimal_places,
|
||||||
|
// '0',
|
||||||
|
// false
|
||||||
|
// ),
|
||||||
|
// ];
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values($return);
|
return array_values($return);
|
||||||
|
@@ -31,7 +31,6 @@ use FireflyIII\Models\Account;
|
|||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Support\Facades\Amount;
|
|
||||||
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
|
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
|
||||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
|
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
|
||||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||||
@@ -63,7 +62,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
++$count;
|
++$count;
|
||||||
app('log')->debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total));
|
app('log')->debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total));
|
||||||
}
|
}
|
||||||
$avg = $total;
|
$avg = $total;
|
||||||
if ($count > 0) {
|
if ($count > 0) {
|
||||||
$avg = bcdiv($total, (string) $count);
|
$avg = bcdiv($total, (string) $count);
|
||||||
}
|
}
|
||||||
@@ -85,21 +84,21 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
|
|
||||||
// get all transactions:
|
// get all transactions:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||||
$collector->setBudgets($budgets);
|
$collector->setBudgets($budgets);
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// loop transactions:
|
// loop transactions:
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
// prep data array for currency:
|
// prep data array for currency:
|
||||||
$budgetId = (int) $journal['budget_id'];
|
$budgetId = (int) $journal['budget_id'];
|
||||||
$budgetName = $journal['budget_name'];
|
$budgetName = $journal['budget_name'];
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$key = sprintf('%d-%d', $budgetId, $currencyId);
|
$key = sprintf('%d-%d', $budgetId, $currencyId);
|
||||||
|
|
||||||
$data[$key] ??= [
|
$data[$key] ??= [
|
||||||
'id' => $budgetId,
|
'id' => $budgetId,
|
||||||
'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']),
|
'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']),
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
@@ -137,13 +136,13 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
$collector->setBudgets($this->getBudgets());
|
$collector->setBudgets($this->getBudgets());
|
||||||
}
|
}
|
||||||
$collector->withBudgetInformation()->withAccountInformation()->withCategoryInformation();
|
$collector->withBudgetInformation()->withAccountInformation()->withCategoryInformation();
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$budgetId = (int) $journal['budget_id'];
|
$budgetId = (int) $journal['budget_id'];
|
||||||
$budgetName = (string) $journal['budget_name'];
|
$budgetName = (string) $journal['budget_name'];
|
||||||
|
|
||||||
// catch "no category" entries.
|
// catch "no category" entries.
|
||||||
if (0 === $budgetId) {
|
if (0 === $budgetId) {
|
||||||
@@ -151,7 +150,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// info about the currency:
|
// info about the currency:
|
||||||
$array[$currencyId] ??= [
|
$array[$currencyId] ??= [
|
||||||
'budgets' => [],
|
'budgets' => [],
|
||||||
'currency_id' => $currencyId,
|
'currency_id' => $currencyId,
|
||||||
'currency_name' => $journal['currency_name'],
|
'currency_name' => $journal['currency_name'],
|
||||||
@@ -203,8 +202,9 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
?Collection $accounts = null,
|
?Collection $accounts = null,
|
||||||
?Collection $budgets = null,
|
?Collection $budgets = null,
|
||||||
?TransactionCurrency $currency = null,
|
?TransactionCurrency $currency = null,
|
||||||
bool $convertToNative = false
|
bool $convertToNative = false
|
||||||
): array {
|
): array
|
||||||
|
{
|
||||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", "%s").', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", "%s").', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
||||||
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||||
// because those expenses only become expenses once they move from the liability to the friend.
|
// because those expenses only become expenses once they move from the liability to the friend.
|
||||||
@@ -212,8 +212,8 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
|
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$repository->setUser($this->user);
|
$repository->setUser($this->user);
|
||||||
$subset = $repository->getAccountsByType(config('firefly.valid_liabilities'));
|
$subset = $repository->getAccountsByType(config('firefly.valid_liabilities'));
|
||||||
$selection = new Collection();
|
$selection = new Collection();
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($subset as $account) {
|
foreach ($subset as $account) {
|
||||||
@@ -223,12 +223,11 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($this->user)
|
$collector->setUser($this->user)
|
||||||
->setRange($start, $end)
|
->setRange($start, $end)
|
||||||
// ->excludeDestinationAccounts($selection)
|
// ->excludeDestinationAccounts($selection)
|
||||||
->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
|
->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
||||||
;
|
|
||||||
|
|
||||||
if (null !== $accounts) {
|
if (null !== $accounts) {
|
||||||
$collector->setAccounts($accounts);
|
$collector->setAccounts($accounts);
|
||||||
@@ -240,8 +239,10 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
Log::debug(sprintf('Limit to normal currency %s', $currency->code));
|
Log::debug(sprintf('Limit to normal currency %s', $currency->code));
|
||||||
$collector->setNormalCurrency($currency);
|
$collector->setNormalCurrency($currency);
|
||||||
}
|
}
|
||||||
$collector->setBudgets($budgets);
|
if ($budgets->count() > 0) {
|
||||||
$journals = $collector->getExtractedJournals();
|
$collector->setBudgets($budgets);
|
||||||
|
}
|
||||||
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// same but for transactions in the foreign currency:
|
// same but for transactions in the foreign currency:
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
|
@@ -62,6 +62,7 @@ function drawChart() {
|
|||||||
// net worth
|
// net worth
|
||||||
var net_worth = [];
|
var net_worth = [];
|
||||||
var keepGreen = false;
|
var keepGreen = false;
|
||||||
|
var makeBlue = false;
|
||||||
|
|
||||||
for (key in data) {
|
for (key in data) {
|
||||||
// balance
|
// balance
|
||||||
@@ -80,17 +81,14 @@ function drawChart() {
|
|||||||
|
|
||||||
// left to spend
|
// left to spend
|
||||||
if (key.substring(0, 17) === 'left-to-spend-in-') {
|
if (key.substring(0, 17) === 'left-to-spend-in-') {
|
||||||
|
left_to_spend_top.push(data[key].value_parsed);
|
||||||
|
left_to_spend_bottom.push(data[key].sub_title);
|
||||||
if(true === data[key].no_available_budgets) {
|
if(true === data[key].no_available_budgets) {
|
||||||
left_to_spend_top.push('---');
|
makeBlue = true;
|
||||||
left_to_spend_bottom.push('---');
|
$('#box-left-to-spend-text').text(data[key].title);
|
||||||
keepGreen = true;
|
|
||||||
}
|
}
|
||||||
if(false === data[key].no_available_budgets) {
|
if(false === data[key].no_available_budgets && parseFloat(data[key].monetary_value) > 0) {
|
||||||
left_to_spend_top.push(data[key].value_parsed);
|
keepGreen = true;
|
||||||
left_to_spend_bottom.push(data[key].sub_title);
|
|
||||||
if (parseFloat(data[key].monetary_value) > 0) {
|
|
||||||
keepGreen = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +100,9 @@ function drawChart() {
|
|||||||
if(!keepGreen) {
|
if(!keepGreen) {
|
||||||
$('#box-left-to-spend-box').removeClass('bg-green-gradient').addClass('bg-red-gradient')
|
$('#box-left-to-spend-box').removeClass('bg-green-gradient').addClass('bg-red-gradient')
|
||||||
}
|
}
|
||||||
|
if(makeBlue) {
|
||||||
|
$('#box-left-to-spend-box').removeClass('bg-red-gradient').removeClass('bg-green-gradient').addClass('bg-blue-gradient')
|
||||||
|
}
|
||||||
|
|
||||||
// balance
|
// balance
|
||||||
$('#box-balance-sums').html(balance_top.join(', '));
|
$('#box-balance-sums').html(balance_top.join(', '));
|
||||||
|
Reference in New Issue
Block a user