diff --git a/app/Api/V1/Controllers/Summary/BasicController.php b/app/Api/V1/Controllers/Summary/BasicController.php index f5feb2fa2c..92e52cadb5 100644 --- a/app/Api/V1/Controllers/Summary/BasicController.php +++ b/app/Api/V1/Controllers/Summary/BasicController.php @@ -43,6 +43,7 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Report\Summarizer\TransactionSummarizer; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; /** @@ -104,10 +105,10 @@ class BasicController extends Controller $billData = $this->getSubscriptionInformation($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end); $netWorthData = $this->getNetWorthInfo($end); - // $balanceData = []; - // $billData = []; +// $balanceData = []; +// $billData = []; // $spentData = []; - // $netWorthData = []; +// $netWorthData = []; $total = array_merge($balanceData, $billData, $spentData, $netWorthData); // give new keys @@ -539,26 +540,63 @@ class BasicController extends Controller ), ]; } + unset($leftToSpend); if (0 === count($return)) { - $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 - ), - ]; + // a small trick to get every expense in this period, regardless of budget. + $spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection()); + foreach ($spent as $row) { + // either an amount was budgeted or 0 is available. + $currencyId = (int) $row['currency_id']; + $spentInCurrency = $row['sum']; + $perDay = '0'; + if (0 !== $days && -1 === bccomp($spentInCurrency, '0')) { + $perDay = bcdiv($spentInCurrency, (string) $days); + } + + Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum'])); + + $return[$currencyId] = [ + 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), + 'title' => trans('firefly.spent'), + '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); diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 4c25f32ffa..f0dadd8c70 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -31,7 +31,6 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Budget; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Report\Summarizer\TransactionSummarizer; use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; @@ -63,7 +62,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn ++$count; 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) { $avg = bcdiv($total, (string) $count); } @@ -85,21 +84,21 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn // get all transactions: /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setAccounts($accounts)->setRange($start, $end); $collector->setBudgets($budgets); - $journals = $collector->getExtractedJournals(); + $journals = $collector->getExtractedJournals(); // loop transactions: /** @var array $journal */ foreach ($journals as $journal) { // prep data array for currency: - $budgetId = (int) $journal['budget_id']; - $budgetName = $journal['budget_name']; - $currencyId = (int) $journal['currency_id']; - $key = sprintf('%d-%d', $budgetId, $currencyId); + $budgetId = (int) $journal['budget_id']; + $budgetName = $journal['budget_name']; + $currencyId = (int) $journal['currency_id']; + $key = sprintf('%d-%d', $budgetId, $currencyId); - $data[$key] ??= [ + $data[$key] ??= [ 'id' => $budgetId, 'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']), 'sum' => '0', @@ -137,13 +136,13 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn $collector->setBudgets($this->getBudgets()); } $collector->withBudgetInformation()->withAccountInformation()->withCategoryInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $budgetId = (int) $journal['budget_id']; - $budgetName = (string) $journal['budget_name']; + $currencyId = (int) $journal['currency_id']; + $budgetId = (int) $journal['budget_id']; + $budgetName = (string) $journal['budget_name']; // catch "no category" entries. if (0 === $budgetId) { @@ -151,7 +150,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'budgets' => [], 'currency_id' => $currencyId, 'currency_name' => $journal['currency_name'], @@ -203,8 +202,9 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null, - bool $convertToNative = false - ): array { + bool $convertToNative = false + ): array + { 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) // 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->setUser($this->user); - $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); - $selection = new Collection(); + $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); + $selection = new Collection(); /** @var Account $account */ foreach ($subset as $account) { @@ -223,12 +223,11 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn } /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user) - ->setRange($start, $end) + ->setRange($start, $end) // ->excludeDestinationAccounts($selection) - ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]) - ; + ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); if (null !== $accounts) { $collector->setAccounts($accounts); @@ -240,8 +239,10 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn Log::debug(sprintf('Limit to normal currency %s', $currency->code)); $collector->setNormalCurrency($currency); } - $collector->setBudgets($budgets); - $journals = $collector->getExtractedJournals(); + if ($budgets->count() > 0) { + $collector->setBudgets($budgets); + } + $journals = $collector->getExtractedJournals(); // same but for transactions in the foreign currency: if (null !== $currency) { diff --git a/public/v1/js/ff/index.js b/public/v1/js/ff/index.js index 496eb93270..c7bfc189bb 100644 --- a/public/v1/js/ff/index.js +++ b/public/v1/js/ff/index.js @@ -62,6 +62,7 @@ function drawChart() { // net worth var net_worth = []; var keepGreen = false; + var makeBlue = false; for (key in data) { // balance @@ -80,17 +81,14 @@ function drawChart() { // left to spend 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) { - left_to_spend_top.push('---'); - left_to_spend_bottom.push('---'); - keepGreen = true; + makeBlue = true; + $('#box-left-to-spend-text').text(data[key].title); } - if(false === data[key].no_available_budgets) { - left_to_spend_top.push(data[key].value_parsed); - left_to_spend_bottom.push(data[key].sub_title); - if (parseFloat(data[key].monetary_value) > 0) { - keepGreen = true; - } + if(false === data[key].no_available_budgets && parseFloat(data[key].monetary_value) > 0) { + keepGreen = true; } } @@ -102,6 +100,9 @@ function drawChart() { if(!keepGreen) { $('#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 $('#box-balance-sums').html(balance_top.join(', '));