diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php index 4101cf5d72..dbfd1fa160 100644 --- a/app/Api/V2/Controllers/Chart/AccountController.php +++ b/app/Api/V2/Controllers/Chart/AccountController.php @@ -56,7 +56,7 @@ class AccountController extends Controller $this->middleware( function ($request, $next) { $this->repository = app(AccountRepositoryInterface::class); - + $this->repository->setAdministrationId(auth()->user()->user_group_id); return $next($request); } ); @@ -90,10 +90,6 @@ class AccountController extends Controller /** @var User $user */ $user = auth()->user(); - // group ID - $administrationId = $user->getAdministrationId(); - $this->repository->setAdministrationId($administrationId); - // user's preferences $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray(); $frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); @@ -155,4 +151,5 @@ class AccountController extends Controller return response()->json($this->clean($chartData)); } + } diff --git a/app/Api/V2/Controllers/Chart/BudgetController.php b/app/Api/V2/Controllers/Chart/BudgetController.php index 12886cd4a5..236ccf9de1 100644 --- a/app/Api/V2/Controllers/Chart/BudgetController.php +++ b/app/Api/V2/Controllers/Chart/BudgetController.php @@ -33,6 +33,7 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Administration\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Administration\Budget\OperationsRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; +use FireflyIII\Support\Http\Api\CleansChartData; use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -43,6 +44,8 @@ use Illuminate\Support\Collection; */ class BudgetController extends Controller { + use CleansChartData; + protected OperationsRepositoryInterface $opsRepository; private BudgetLimitRepositoryInterface $blRepository; private array $currencies = []; @@ -93,7 +96,7 @@ class BudgetController extends Controller // could return multiple arrays, so merge. $data = array_merge($data, $this->processBudget($budget, $start, $end)); } - return response()->json($data); + return response()->json($this->clean($data)); } /** diff --git a/app/Api/V2/Controllers/Chart/CategoryController.php b/app/Api/V2/Controllers/Chart/CategoryController.php new file mode 100644 index 0000000000..bf167b3bad --- /dev/null +++ b/app/Api/V2/Controllers/Chart/CategoryController.php @@ -0,0 +1,138 @@ +. + */ + +namespace FireflyIII\Api\V2\Controllers\Chart; + +use Carbon\Carbon; +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\Http\Api\CleansChartData; +use FireflyIII\Support\Http\Api\ExchangeRateConverter; +use Illuminate\Http\JsonResponse; + +/** + * Class BudgetController + */ +class CategoryController extends Controller +{ + use CleansChartData; + + private AccountRepositoryInterface $accountRepos; + private CurrencyRepositoryInterface $currencyRepos; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->accountRepos = app(AccountRepositoryInterface::class); + $this->currencyRepos = app(CurrencyRepositoryInterface::class); + $this->accountRepos->setAdministrationId(auth()->user()->user_group_id); + return $next($request); + } + ); + } + + /** + * TODO may be worth to move to a handler but the data is simple enough. + * + * @param DateRequest $request + * + * @return JsonResponse + * @throws FireflyException + */ + public function dashboard(DateRequest $request): JsonResponse + { + $params = $request->getAll(); + /** @var Carbon $start */ + $start = $params['start']; + /** @var Carbon $end */ + $end = $params['end']; + $accounts = $this->accountRepos->getAccountsByType([AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]); + $default = app('amount')->getDefaultCurrency(); + $converter = new ExchangeRateConverter(); + $currencies = []; + $return = []; + + // get journals for entire period: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setRange($start, $end)->withAccountInformation(); + $collector->setXorAccounts($accounts)->withCategoryInformation(); + $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::RECONCILIATION]); + $journals = $collector->getExtractedJournals(); + + /** @var array $journal */ + foreach ($journals as $journal) { + $currencyId = (int)$journal['currency_id']; + $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); + $currencies[$currencyId] = $currency; + $categoryName = null === $journal['category_name'] ? (string)trans('firefly.no_category') : $journal['category_name']; + $amount = app('steam')->positive($journal['amount']); + $nativeAmount = $converter->convert($default, $currency, $journal['date'], $amount); + $key = sprintf('%s-%s', $categoryName, $currency->code); + if ((int)$journal['foreign_currency_id'] === (int)$default->id) { + $nativeAmount = app('steam')->positive($journal['foreign_amount']); + } + // create arrays + $return[$key] = $return[$key] ?? [ + 'label' => $categoryName, + 'currency_id' => (int)$currency->id, + 'currency_code' => $currency->code, + 'currency_name' => $currency->name, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => (int)$currency->decimal_places, + 'native_id' => (int)$default->id, + 'native_code' => $default->code, + 'native_name' => $default->name, + 'native_symbol' => $default->symbol, + 'native_decimal_places' => (int)$default->decimal_places, + 'period' => null, + 'start' => $start->toAtomString(), + 'end' => $end->toAtomString(), + 'amount' => '0', + 'native_amount' => '0', + ]; + + + // add monies + $return[$key]['amount'] = bcadd($return[$key]['amount'], $amount); + $return[$key]['native_amount'] = bcadd($return[$key]['native_amount'], $nativeAmount); + } + $return = array_values($return); + + // order by native amount + usort($return, function (array $a, array $b) { + return (float)$a['native_amount'] < (float)$b['native_amount'] ? 1 : -1; + }); + return response()->json($this->clean($return)); + } + + +} diff --git a/app/Support/Http/Api/CleansChartData.php b/app/Support/Http/Api/CleansChartData.php index 220bcfdd82..90cdba8c6a 100644 --- a/app/Support/Http/Api/CleansChartData.php +++ b/app/Support/Http/Api/CleansChartData.php @@ -54,12 +54,12 @@ trait CleansChartData if (array_key_exists('native_id', $array)) { $array['native_id'] = (string)$array['native_id']; } - if (!array_key_exists('end', $array)) { - throw new FireflyException(sprintf('Data-set "%s" is missing the "end"-variable.', $index)); - } if (!array_key_exists('start', $array)) { throw new FireflyException(sprintf('Data-set "%s" is missing the "start"-variable.', $index)); } + if (!array_key_exists('end', $array)) { + throw new FireflyException(sprintf('Data-set "%s" is missing the "end"-variable.', $index)); + } if (!array_key_exists('period', $array)) { throw new FireflyException(sprintf('Data-set "%s" is missing the "period"-variable.', $index)); } diff --git a/routes/api.php b/routes/api.php index 65cc115820..683603d8ab 100644 --- a/routes/api.php +++ b/routes/api.php @@ -103,6 +103,7 @@ Route::group( static function () { Route::get('account/dashboard', ['uses' => 'AccountController@dashboard', 'as' => 'account.dashboard']); Route::get('budget/dashboard', ['uses' => 'BudgetController@dashboard', 'as' => 'budget.dashboard']); + Route::get('category/dashboard', ['uses' => 'CategoryController@dashboard', 'as' => 'category.dashboard']); Route::get('balance/balance', ['uses' => 'BalanceController@balance', 'as' => 'balance.balance']); } );