diff --git a/app/Api/V1/Controllers/Chart/AccountController.php b/app/Api/V1/Controllers/Chart/AccountController.php index e6ceb7d015..44f809cbad 100644 --- a/app/Api/V1/Controllers/Chart/AccountController.php +++ b/app/Api/V1/Controllers/Chart/AccountController.php @@ -27,13 +27,16 @@ namespace FireflyIII\Api\V1\Controllers\Chart; use Carbon\Carbon; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Data\DateRequest; +use FireflyIII\Api\V1\Requests\Chart\ChartRequest; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\Preference; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Chart\ChartData; use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Http\Api\ApiSupport; +use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -43,8 +46,10 @@ use Illuminate\Http\JsonResponse; class AccountController extends Controller { use ApiSupport; + use CollectsAccountsFromFilter; private AccountRepositoryInterface $repository; + private ChartData $chartData; /** * AccountController constructor. @@ -56,6 +61,7 @@ class AccountController extends Controller function ($request, $next) { /** @var User $user */ $user = auth()->user(); + $this->chartData = new ChartData(); $this->repository = app(AccountRepositoryInterface::class); $this->repository->setUser($user); @@ -64,6 +70,30 @@ class AccountController extends Controller ); } + + /** + * TODO fix documentation + * + * @throws FireflyException + */ + public function dashboard(ChartRequest $request): JsonResponse + { + $queryParameters = $request->getParameters(); + $accounts = $this->getAccountList($queryParameters); + + // move date to end of day + $queryParameters['start']->startOfDay(); + $queryParameters['end']->endOfDay(); + + // loop each account, and collect info: + /** @var Account $account */ + foreach ($accounts as $account) { + $this->renderAccountData($queryParameters, $account); + } + + return response()->json($this->chartData->render()); + } + /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview @@ -133,4 +163,46 @@ class AccountController extends Controller return response()->json($chartData); } + + + /** + * @throws FireflyException + */ + private function renderAccountData(array $params, Account $account): void + { + $currency = $this->repository->getAccountCurrency($account); + if (null === $currency) { + $currency = $this->default; + } + $currentSet = [ + 'label' => $account->name, + + // the currency that belongs to the account. + 'currency_id' => (string) $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + + // the default currency of the user (could be the same!) + 'date' => $params['start']->toAtomString(), + 'start' => $params['start']->toAtomString(), + 'end' => $params['end']->toAtomString(), + 'period' => '1D', + 'entries' => [], + ]; + $currentStart = clone $params['start']; + $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); + + $previous = array_values($range)[0]['balance']; + while ($currentStart <= $params['end']) { + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->toAtomString(); + $balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; + $previous = $balance; + + $currentStart->addDay(); + $currentSet['entries'][$label] = $balance; + } + $this->chartData->add($currentSet); + } } diff --git a/app/Api/V1/Controllers/Chart/BudgetController.php b/app/Api/V1/Controllers/Chart/BudgetController.php new file mode 100644 index 0000000000..385d4e1f38 --- /dev/null +++ b/app/Api/V1/Controllers/Chart/BudgetController.php @@ -0,0 +1,260 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers\Chart; + +use Carbon\Carbon; +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Api\V1\Requests\Generic\DateRequest; +use FireflyIII\Enums\UserRoleEnum; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Budget; +use FireflyIII\Models\BudgetLimit; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; +use FireflyIII\Support\Http\Api\CleansChartData; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; +use Illuminate\Http\JsonResponse; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; + +/** + * Class BudgetController + */ +class BudgetController extends Controller +{ + use CleansChartData; + use ValidatesUserGroupTrait; + + protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; + + protected OperationsRepositoryInterface $opsRepository; + private BudgetLimitRepositoryInterface $blRepository; + private array $currencies = []; + private TransactionCurrency $currency; + private BudgetRepositoryInterface $repository; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->repository = app(BudgetRepositoryInterface::class); + $this->blRepository = app(BudgetLimitRepositoryInterface::class); + $this->opsRepository = app(OperationsRepositoryInterface::class); + $userGroup = $this->validateUserGroup($request); + $this->repository->setUserGroup($userGroup); + $this->opsRepository->setUserGroup($userGroup); + $this->blRepository->setUserGroup($userGroup); + + return $next($request); + } + ); + } + + /** + * TODO see autocomplete/accountcontroller + */ + public function dashboard(DateRequest $request): JsonResponse + { + $params = $request->getAll(); + + /** @var Carbon $start */ + $start = $params['start']; + + /** @var Carbon $end */ + $end = $params['end']; + + // code from FrontpageChartGenerator, but not in separate class + $budgets = $this->repository->getActiveBudgets(); + $data = []; + + /** @var Budget $budget */ + foreach ($budgets as $budget) { + // could return multiple arrays, so merge. + $data = array_merge($data, $this->processBudget($budget, $start, $end)); + } + + return response()->json($this->clean($data)); + } + + /** + * @throws FireflyException + */ + private function processBudget(Budget $budget, Carbon $start, Carbon $end): array + { + // get all limits: + $limits = $this->blRepository->getBudgetLimits($budget, $start, $end); + $rows = []; + + // if no limits + if (0 === $limits->count()) { + // return as a single item in an array + $rows = $this->noBudgetLimits($budget, $start, $end); + } + if ($limits->count() > 0) { + $rows = $this->budgetLimits($budget, $limits); + } + // is always an array + $return = []; + foreach ($rows as $row) { + $current = [ + 'label' => $budget->name, + 'currency_id' => (string) $row['currency_id'], + 'currency_code' => $row['currency_code'], + 'currency_name' => $row['currency_name'], + 'currency_decimal_places' => $row['currency_decimal_places'], + 'period' => null, + 'start' => $row['start'], + 'end' => $row['end'], + 'entries' => [ + 'spent' => $row['spent'], + 'left' => $row['left'], + 'overspent' => $row['overspent'], + ], + ]; + $return[] = $current; + } + + return $return; + } + + /** + * When no budget limits are present, the expenses of the whole period are collected and grouped. + * This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty. + * + * @throws FireflyException + */ + private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array + { + $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget])); + + return $this->processExpenses($budget->id, $spent, $start, $end); + } + + /** + * Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return + * its info. + * + * @param array> $array + * + * @throws FireflyException + */ + private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array + { + $return = []; + + /** + * This array contains the expenses in this budget. Grouped per currency. + * The grouping is on the main currency only. + * + * @var int $currencyId + * @var array $block + */ + foreach ($array as $currencyId => $block) { + $this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId); + $return[$currencyId] ??= [ + 'currency_id' => (string) $currencyId, + 'currency_code' => $block['currency_code'], + 'currency_name' => $block['currency_name'], + 'currency_symbol' => $block['currency_symbol'], + 'currency_decimal_places' => (int) $block['currency_decimal_places'], + 'start' => $start->toAtomString(), + 'end' => $end->toAtomString(), + 'spent' => '0', + 'left' => '0', + 'overspent' => '0', + ]; + $currentBudgetArray = $block['budgets'][$budgetId]; + + // var_dump($return); + /** @var array $journal */ + foreach ($currentBudgetArray['transaction_journals'] as $journal) { + $return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], $journal['amount']); + } + } + + return $return; + } + + /** + * Function that processes each budget limit (per budget). + * + * If you have a budget limit in EUR, only transactions in EUR will be considered. + * If you have a budget limit in GBP, only transactions in GBP will be considered. + * + * If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit. + * + * @throws FireflyException + */ + private function budgetLimits(Budget $budget, Collection $limits): array + { + app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id)); + $data = []; + + /** @var BudgetLimit $limit */ + foreach ($limits as $limit) { + $data = array_merge($data, $this->processLimit($budget, $limit)); + } + + return $data; + } + + /** + * @throws FireflyException + */ + private function processLimit(Budget $budget, BudgetLimit $limit): array + { + Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); + $end = clone $limit->end_date; + $end->endOfDay(); + $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget])); + $limitCurrencyId = $limit->transaction_currency_id; + $filtered = []; + + /** @var array $entry */ + foreach ($spent as $currencyId => $entry) { + // only spent the entry where the entry's currency matches the budget limit's currency + // so $filtered will only have 1 or 0 entries + if ($entry['currency_id'] === $limitCurrencyId) { + $filtered[$currencyId] = $entry; + } + } + $result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end); + if (1 === count($result)) { + $compare = bccomp($limit->amount, app('steam')->positive($result[$limitCurrencyId]['spent'])); + if (1 === $compare) { + // convert this amount into the native currency: + $result[$limitCurrencyId]['left'] = bcadd($limit->amount, $result[$limitCurrencyId]['spent']); + } + if ($compare <= 0) { + $result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, $result[$limitCurrencyId]['spent'])); + } + } + + return $result; + } +} diff --git a/app/Api/V1/Controllers/Chart/CategoryController.php b/app/Api/V1/Controllers/Chart/CategoryController.php new file mode 100644 index 0000000000..7dac060685 --- /dev/null +++ b/app/Api/V1/Controllers/Chart/CategoryController.php @@ -0,0 +1,128 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers\Chart; + +use Carbon\Carbon; +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Enums\AccountTypeEnum; +use FireflyIII\Enums\TransactionTypeEnum; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\Http\Api\CleansChartData; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; +use Illuminate\Http\JsonResponse; + +/** + * Class BudgetController + */ +class CategoryController extends Controller +{ + use CleansChartData; + use ValidatesUserGroupTrait; + + 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); + $userGroup = $this->validateUserGroup($request); + $this->accountRepos->setUserGroup($userGroup); + $this->currencyRepos->setUserGroup($userGroup); + + return $next($request); + } + ); + } + + /** + * TODO may be worth to move to a handler but the data is simple enough. + * TODO see autoComplete/account controller + * + * @throws FireflyException + * + * @SuppressWarnings("PHPMD.UnusedFormalParameter") + */ + public function dashboard(DateRequest $request): JsonResponse + { + /** @var Carbon $start */ + $start = $this->parameters->get('start'); + + /** @var Carbon $end */ + $end = $this->parameters->get('end'); + $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]); + $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([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]); + $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']); + $key = sprintf('%s-%s', $categoryName, $currency->code); + // create arrays + $return[$key] ??= [ + 'label' => $categoryName, + 'currency_id' => (string) $currency->id, + 'currency_code' => $currency->code, + 'currency_name' => $currency->name, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + 'period' => null, + 'start' => $start->toAtomString(), + 'end' => $end->toAtomString(), + 'amount' => '0', + ]; + + // add monies + $return[$key]['amount'] = bcadd($return[$key]['amount'], $amount); + } + $return = array_values($return); + + // order by amount + usort($return, static function (array $a, array $b) { + return (float) $a['amount'] < (float) $b['amount'] ? 1 : -1; + }); + + return response()->json($this->clean($return)); + } +} diff --git a/app/Api/V1/Controllers/Summary/BasicController.php b/app/Api/V1/Controllers/Summary/BasicController.php index 89e94cad78..c3e9553955 100644 --- a/app/Api/V1/Controllers/Summary/BasicController.php +++ b/app/Api/V1/Controllers/Summary/BasicController.php @@ -39,6 +39,8 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Facades\Amount; +use FireflyIII\Support\Http\Api\ExchangeRateConverter; +use FireflyIII\Support\Report\Summarizer\TransactionSummarizer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; @@ -93,24 +95,24 @@ class BasicController extends Controller public function basic(DateRequest $request): JsonResponse { // parameters for boxes: - $dates = $request->getAll(); - $start = $dates['start']; - $end = $dates['end']; - $code = $request->get('currency_code'); + $dates = $request->getAll(); + $start = $dates['start']; + $end = $dates['end']; + $code = $request->get('currency_code'); // balance information: $balanceData = $this->getBalanceInformation($start, $end); - $billData = $this->getBillInformation($start, $end); + $billData = $this->getSubscriptionInformation($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end); $netWorthData = $this->getNetWorthInfo($end); // $balanceData = []; // $billData = []; // $spentData = []; // $netWorthData = []; - $total = array_merge($balanceData, $billData, $spentData, $netWorthData); + $total = array_merge($balanceData, $billData, $spentData, $netWorthData); // give new keys - $return = []; + $return = []; foreach ($total as $entry) { if (null === $code || ($code === $entry['currency_code'])) { $return[$entry['key']] = $entry; @@ -122,55 +124,119 @@ class BasicController extends Controller private function getBalanceInformation(Carbon $start, Carbon $end): array { + Log::debug('getBalanceInformation'); // some config settings $convertToNative = Amount::convertToNative(); $default = Amount::getNativeCurrency(); // prep some arrays: - $incomes = []; - $expenses = []; - $sums = []; - $return = []; + $incomes = []; + $expenses = []; + $sums = []; + $return = []; + $currencies = [ + $default->id => $default, + ]; // collect income of user using the new group collector. /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]); + $collector = app(GroupCollectorInterface::class); + $summarizer = new TransactionSummarizer(); + $set = $collector->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value])->getExtractedJournals(); + $incomes = $summarizer->groupByCurrencyId($set, 'positive', false); - $set = $collector->getExtractedJournals(); - /** @var array $journal */ - foreach ($set as $journal) { - $currencyId = $convertToNative ? $default->id : (int) $journal['currency_id']; - $amount = Amount::getAmountFromJournal($journal); - $incomes[$currencyId] ??= '0'; - $incomes[$currencyId] = bcadd( - $incomes[$currencyId], - bcmul($amount, '-1') - ); - $sums[$currencyId] ??= '0'; - $sums[$currencyId] = bcadd($sums[$currencyId], bcmul($amount, '-1')); - } - - // collect expenses of user using the new group collector. + // collect expenses of user. +// collect expenses of user using the new group collector. /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); - $set = $collector->getExtractedJournals(); + $collector = app(GroupCollectorInterface::class); + $set = $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->getExtractedJournals(); + $expenses = $summarizer->groupByCurrencyId($set, 'negative', false); - /** @var array $journal */ - foreach ($set as $journal) { - $currencyId = $convertToNative ? $default->id : (int) $journal['currency_id']; - $amount = Amount::getAmountFromJournal($journal); - $expenses[$currencyId] ??= '0'; - $expenses[$currencyId] = bcadd($expenses[$currencyId], $amount); - $sums[$currencyId] ??= '0'; - $sums[$currencyId] = bcadd($sums[$currencyId], $amount); + // if convert to native, do so right now. + if ($convertToNative) { + $newExpenses = [ + $default->id => [ + 'currency_id' => $default->id, + 'currency_code' => $default->code, + 'currency_symbol' => $default->symbol, + 'currency_decimal_places' => $default->decimal_places, + 'sum' => '0', + ], + ]; + $newIncomes = [ + $default->id => [ + 'currency_id' => $default->id, + 'currency_code' => $default->code, + 'currency_symbol' => $default->symbol, + 'currency_decimal_places' => $default->decimal_places, + 'sum' => '0', + ], + ]; + $sums = [ + $default->id => [ + 'currency_id' => $default->id, + 'currency_code' => $default->code, + 'currency_symbol' => $default->symbol, + 'currency_decimal_places' => $default->decimal_places, + 'sum' => '0', + ], + ]; + + $converter = new ExchangeRateConverter(); + // loop over income and expenses + foreach ([$expenses, $incomes] as $index => $array) { + + // loop over either one. + foreach ($array as $entry) { + + // if it is the native currency already. + if ($entry['currency_id'] === $default->id) { + $sums[$default->id]['sum'] = bcadd($entry['sum'], $sums[$default->id]['sum']); + + // don't forget to add it to newExpenses and newIncome + if (0 === $index) { + $newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $entry['sum']); + } + if (1 === $index) { + $newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $entry['sum']); + } + + continue; + } + + $currencies[$entry['currency_id']] ??= $this->currencyRepos->find($entry['currency_id']); + $convertedSum = $converter->convert($currencies[$entry['currency_id']], $default, $start, $entry['sum']); + $sums[$default->id]['sum'] = bcadd($sums[$default->id]['sum'], $convertedSum); + if (0 === $index) { + $newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $convertedSum); + } + if (1 === $index) { + $newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $convertedSum); + } + } + } + $incomes = $newIncomes; + $expenses = $newExpenses; + } + if (!$convertToNative) { + foreach ([$expenses, $incomes] as $array) { + foreach ($array as $entry) { + $currencyId = $entry['currency_id']; + $sums[$currencyId] ??= [ + 'currency_id' => $entry['currency_id'], + 'currency_code' => $entry['currency_code'], + 'currency_symbol' => $entry['currency_symbol'], + 'currency_decimal_places' => $entry['currency_decimal_places'], + 'sum' => '0', + ]; + $sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], $entry['sum']); + } + } } - // format amounts: - $keys = array_keys($sums); + $keys = array_keys($sums); foreach ($keys as $currencyId) { - $currency = $this->currencyRepos->find($currencyId); + $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); if (null === $currency) { continue; } @@ -178,37 +244,37 @@ class BasicController extends Controller $return[] = [ 'key' => sprintf('balance-in-%s', $currency->code), 'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]), - 'monetary_value' => $sums[$currencyId] ?? '0', + 'monetary_value' => $sums[$currencyId]['sum'] ?? '0', 'currency_id' => (string) $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, - 'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false), + 'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false), 'local_icon' => 'balance-scale', - 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) - .' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), + 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false) + . ' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false), ]; $return[] = [ 'key' => sprintf('spent-in-%s', $currency->code), 'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]), - 'monetary_value' => $expenses[$currencyId] ?? '0', + 'monetary_value' => $expenses[$currencyId]['sum'] ?? '0', 'currency_id' => (string) $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, - 'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false), + 'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false), 'local_icon' => 'balance-scale', 'sub_title' => '', ]; $return[] = [ 'key' => sprintf('earned-in-%s', $currency->code), 'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]), - 'monetary_value' => $incomes[$currencyId] ?? '0', + 'monetary_value' => $incomes[$currencyId]['sum'] ?? '0', 'currency_id' => (string) $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, - 'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), + 'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false), 'local_icon' => 'balance-scale', 'sub_title' => '', ]; @@ -227,7 +293,7 @@ class BasicController extends Controller 'value_parsed' => app('amount')->formatAnything($currency, '0', false), 'local_icon' => 'balance-scale', 'sub_title' => app('amount')->formatAnything($currency, '0', false) - .' + '.app('amount')->formatAnything($currency, '0', false), + . ' + ' . app('amount')->formatAnything($currency, '0', false), ]; $return[] = [ 'key' => sprintf('spent-in-%s', $currency->code), @@ -258,17 +324,71 @@ class BasicController extends Controller return $return; } - private function getBillInformation(Carbon $start, Carbon $end): array + private function getSubscriptionInformation(Carbon $start, Carbon $end): array { - app('log')->debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-'))); + Log::debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-'))); /* * Since both this method and the chart use the exact same data, we can suffice * with calling the one method in the bill repository that will get this amount. */ $paidAmount = $this->billRepository->sumPaidInRange($start, $end); $unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end); + $currencies = [ + $this->nativeCurrency->id => $this->nativeCurrency, + ]; - $return = []; + if ($this->convertToNative) { + $converter = new ExchangeRateConverter(); + $newPaidAmount = [[ + 'id' => $this->nativeCurrency->id, + 'name' => $this->nativeCurrency->name, + 'symbol' => $this->nativeCurrency->symbol, + 'code' => $this->nativeCurrency->code, + 'decimal_places' => $this->nativeCurrency->decimal_places, + 'sum' => '0', + ]]; + + $newUnpaidAmount = [[ + 'id' => $this->nativeCurrency->id, + 'name' => $this->nativeCurrency->name, + 'symbol' => $this->nativeCurrency->symbol, + 'code' => $this->nativeCurrency->code, + 'decimal_places' => $this->nativeCurrency->decimal_places, + 'sum' => '0', + ]]; + foreach ([$paidAmount, $unpaidAmount] as $index => $array) { + foreach ($array as $item) { + $currencyId = (int) $item['id']; + if (0 === $index) { + // paid amount + if ($currencyId === $this->nativeCurrency->id) { + $newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $item['sum']); + continue; + } + $currencies[$currencyId] ??= $this->currencyRepos->find($currencyId); + $convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']); + $newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $convertedAmount); + continue; + } + // unpaid amount + if ($currencyId === $this->nativeCurrency->id) { + $newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $item['sum']); + continue; + } + $currencies[$currencyId] ??= $this->currencyRepos->find($currencyId); + $convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']); + $newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $convertedAmount); + } + } + $paidAmount = $newPaidAmount; + $unpaidAmount = $newUnpaidAmount; + } + +// var_dump($paidAmount); +// var_dump($unpaidAmount); +// exit; + + $return = []; /** * @var array $info @@ -307,7 +427,7 @@ class BasicController extends Controller 'sub_title' => '', ]; } - app('log')->debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-'))); + Log::debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-'))); if (0 === count($return)) { $currency = $this->nativeCurrency; @@ -369,7 +489,7 @@ class BasicController extends Controller Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum'])); - $return[] = [ + $return[] = [ 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]), 'monetary_value' => $leftToSpend, @@ -416,16 +536,16 @@ class BasicController extends Controller $end->endOfDay(); /** @var User $user */ - $user = auth()->user(); + $user = auth()->user(); Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s'))); /** @var NetWorthInterface $netWorthHelper */ $netWorthHelper = app(NetWorthInterface::class); $netWorthHelper->setUser($user); - $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]); + $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]); // filter list on preference of being included. - $filtered = $allAccounts->filter( + $filtered = $allAccounts->filter( function (Account $account) { $includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth'); @@ -433,13 +553,13 @@ class BasicController extends Controller } ); - $netWorthSet = $netWorthHelper->byAccounts($filtered, $end); - $return = []; + $netWorthSet = $netWorthHelper->byAccounts($filtered, $end); + $return = []; foreach ($netWorthSet as $key => $data) { if ('native' === $key) { continue; } - $amount = $data['balance']; + $amount = $data['balance']; if (0 === bccomp($amount, '0')) { continue; } diff --git a/app/Api/V1/Requests/Chart/ChartRequest.php b/app/Api/V1/Requests/Chart/ChartRequest.php new file mode 100644 index 0000000000..a52c2e8245 --- /dev/null +++ b/app/Api/V1/Requests/Chart/ChartRequest.php @@ -0,0 +1,91 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests\Chart; + +use FireflyIII\Enums\UserRoleEnum; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Support\Facades\Log; +use Illuminate\Validation\Validator; + +/** + * Class ChartRequest + */ +class ChartRequest extends FormRequest +{ + use ChecksLogin; + use ConvertsDataTypes; + use ValidatesUserGroupTrait; + + protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; + + public function getParameters(): array + { + return [ + 'start' => $this->convertDateTime('start')?->startOfDay(), + 'end' => $this->convertDateTime('end')?->endOfDay(), + 'preselected' => $this->convertString('preselected', 'empty'), + 'period' => $this->convertString('period', '1M'), + 'accounts' => $this->arrayFromValue($this->get('accounts')), + ]; + } + + /** + * The rules that the incoming request must be matched against. + */ + public function rules(): array + { + return [ + 'start' => 'required|date|after:1900-01-01|before:2099-12-31|before_or_equal:end', + 'end' => 'required|date|after:1900-01-01|before:2099-12-31|after_or_equal:start', + 'preselected' => sprintf('nullable|in:%s', implode(',', config('firefly.preselected_accounts'))), + 'period' => sprintf('nullable|in:%s', implode(',', config('firefly.valid_view_ranges'))), + 'accounts.*' => 'exists:accounts,id', + ]; + + } + + public function withValidator(Validator $validator): void + { + $validator->after( + static function (Validator $validator): void { + // validate transaction query data. + $data = $validator->getData(); + if (!array_key_exists('accounts', $data)) { + // $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); + return; + } + if (!is_array($data['accounts'])) { + $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); + } + } + ); + if ($validator->fails()) { + Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); + } + } +} diff --git a/app/Api/V1/Requests/Generic/DateRequest.php b/app/Api/V1/Requests/Generic/DateRequest.php new file mode 100644 index 0000000000..c3840ac76b --- /dev/null +++ b/app/Api/V1/Requests/Generic/DateRequest.php @@ -0,0 +1,62 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests\Generic; + +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Request class for end points that require date parameters. + * + * Class DateRequest + */ +class DateRequest extends FormRequest +{ + use ChecksLogin; + use ConvertsDataTypes; + + /** + * Get all data from the request. + */ + public function getAll(): array + { + return [ + 'start' => $this->getCarbonDate('start')->startOfDay(), + 'end' => $this->getCarbonDate('end')->endOfDay(), + ]; + } + + /** + * The rules that the incoming request must be matched against. + */ + public function rules(): array + { + return [ + 'start' => 'required|date|after:1900-01-01|before:2099-12-31', + 'end' => 'required|date|after_or_equal:start|before:2099-12-31|after:1900-01-01', + ]; + } +} diff --git a/app/Api/V1/Requests/Generic/SingleDateRequest.php b/app/Api/V1/Requests/Generic/SingleDateRequest.php new file mode 100644 index 0000000000..2e4842433b --- /dev/null +++ b/app/Api/V1/Requests/Generic/SingleDateRequest.php @@ -0,0 +1,59 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests\Generic; + +use Carbon\Carbon; +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Request class for end points that require a date parameter. + * + * Class SingleDateRequest + */ +class SingleDateRequest extends FormRequest +{ + use ChecksLogin; + use ConvertsDataTypes; + + /** + * Get all data from the request. + */ + public function getDate(): Carbon + { + return $this->getCarbonDate('date'); + } + + /** + * The rules that the incoming request must be matched against. + */ + public function rules(): array + { + return [ + 'date' => 'required|date|after:1900-01-01|before:2099-12-31', + ]; + } +} diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index fddb77e0ec..500d651b43 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -138,7 +138,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U ->where('end_date', $end->format('Y-m-d'))->get() ; - Log::debug(sprintf('Found %d available budgets', $availableBudgets->count())); + Log::debug(sprintf('Found %d available budgets (already converted)', $availableBudgets->count())); // use native amount if necessary? $convertToNative = Amount::convertToNative($this->user); diff --git a/app/Support/Chart/ChartData.php b/app/Support/Chart/ChartData.php index 66585c415f..93a825415d 100644 --- a/app/Support/Chart/ChartData.php +++ b/app/Support/Chart/ChartData.php @@ -46,7 +46,7 @@ class ChartData if (array_key_exists('native_currency_id', $data)) { $data['native_currency_id'] = (string) $data['native_currency_id']; } - $required = ['start', 'date', 'end', 'entries', 'native_entries']; + $required = ['start', 'date', 'end', 'entries']; foreach ($required as $field) { if (!array_key_exists($field, $data)) { throw new FireflyException(sprintf('Data-set is missing the "%s"-variable.', $field)); diff --git a/app/Support/Report/Summarizer/TransactionSummarizer.php b/app/Support/Report/Summarizer/TransactionSummarizer.php index 6c3a22fd6a..27f5bc1cda 100644 --- a/app/Support/Report/Summarizer/TransactionSummarizer.php +++ b/app/Support/Report/Summarizer/TransactionSummarizer.php @@ -49,7 +49,7 @@ class TransactionSummarizer $this->convertToNative = Amount::convertToNative($user); } - public function groupByCurrencyId(array $journals, string $method = 'negative'): array + public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array { Log::debug(sprintf('Now in groupByCurrencyId(array, "%s")', $method)); $array = []; @@ -94,10 +94,10 @@ class TransactionSummarizer } } if (!$this->convertToNative) { - Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code'])); // use foreign amount? $foreignCurrencyId = (int) $journal['foreign_currency_id']; if (0 !== $foreignCurrencyId) { + Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is "%s")', $journal['transaction_journal_id'], $journal['foreign_currency_code'])); $foreignCurrencyName = $journal['foreign_currency_name']; $foreignCurrencySymbol = $journal['foreign_currency_symbol']; $foreignCurrencyCode = $journal['foreign_currency_code']; @@ -124,7 +124,7 @@ class TransactionSummarizer } // then process foreign amount, if it exists. - if (0 !== $foreignCurrencyId) { + if (0 !== $foreignCurrencyId && true === $includeForeign) { $amount = (string) ($journal['foreign_amount'] ?? '0'); $array[$foreignCurrencyId] ??= [ 'sum' => '0', diff --git a/config/firefly.php b/config/firefly.php index 0eb32abc8e..e0595eba79 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -184,6 +184,7 @@ return [ 'currencyPreference' => 'EUR', 'language' => 'en_US', 'locale' => 'equal', + 'convertToNative' => false, ], 'default_currency' => 'EUR', 'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'), diff --git a/package-lock.json b/package-lock.json index dab4933374..f6a74a6815 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,42 +13,6 @@ "postcss": "^8.4.47" } }, - "node_modules/@ag-grid-community/client-side-row-model": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/@ag-grid-community/client-side-row-model/-/client-side-row-model-32.3.4.tgz", - "integrity": "sha512-AZyLSemPyaCJi8wPJ/wvwow6v4MZKMkg9152TameKvaEf+m+N+gWJNKb1dQoqjgWCgEByqvM6SO8dJtYRrdr/A==", - "license": "MIT", - "dependencies": { - "@ag-grid-community/core": "32.3.4", - "tslib": "^2.3.0" - } - }, - "node_modules/@ag-grid-community/core": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/@ag-grid-community/core/-/core-32.3.4.tgz", - "integrity": "sha512-g1CJOQuA4uRx1U3VP9SZLnTJBYdMwCTM348FsubdI6anaqxnHv3X0kridq9v1v26qXbl7yytm5X3v1hPcV8wVA==", - "license": "MIT", - "dependencies": { - "ag-charts-types": "10.3.4", - "tslib": "^2.3.0" - } - }, - "node_modules/@ag-grid-community/infinite-row-model": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/@ag-grid-community/infinite-row-model/-/infinite-row-model-32.3.4.tgz", - "integrity": "sha512-GWlUoU9UPGp0ZYdBCiV8R+A/mwdYweoB3HsVOEeQiNZYDC1TQJxiCSKBCCg9qk3KDY+VbJ/6ebV/BUN7cLwIuQ==", - "license": "MIT", - "dependencies": { - "@ag-grid-community/core": "32.3.4", - "tslib": "^2.3.0" - } - }, - "node_modules/@ag-grid-community/styles": { - "version": "33.0.3", - "resolved": "https://registry.npmjs.org/@ag-grid-community/styles/-/styles-33.0.3.tgz", - "integrity": "sha512-1bXrYoVj5TIpLvyjgXHvKnYrC0/JvrdGDdJ3mYfT58GulDt1iNQqhjxMnZB+sxMdQoOc681jmKTGcWzOEDE1Dw==", - "license": "MIT" - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -3657,12 +3621,6 @@ "integrity": "sha512-q2VoAOu1DtZ7z41M2gQ05VMNYkFCAMxFU+j/HUMwCOlr/e3VhO+qww2SGJw4OxBw5nZQ7YV78+wK2RiB7ConzQ==", "license": "MIT" }, - "node_modules/ag-charts-types": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-10.3.4.tgz", - "integrity": "sha512-MU+3gvKn1jEyLlMHS0Vu0nHmIQxiVJAnA6ftUatLZvV0c7hOWap4VWghqZ0cVZUJsCdMI59Iuq1u3xquKv4LOQ==", - "license": "MIT" - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -11109,6 +11067,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/tty-browserify": { @@ -12291,18 +12250,14 @@ "resources/assets/v2": { "hasInstallScript": true, "dependencies": { - "@ag-grid-community/client-side-row-model": "^32.0.2", - "@ag-grid-community/core": "^32.0.2", - "@ag-grid-community/infinite-row-model": "^32.0.2", - "@ag-grid-community/styles": "^33.0.2", "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "admin-lte": "^4.0.0-alpha3", + "admin-lte": "^4.0.0-beta3", "alpinejs": "^3.13.7", - "bootstrap": "^5.3.0", - "bootstrap5-autocomplete": "^1.1.22", - "bootstrap5-tags": "^1.7", - "chart.js": "^4.4.0", + "bootstrap": "^5", + "bootstrap5-autocomplete": "^1", + "bootstrap5-tags": "^1", + "chart.js": "^4", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.14.0", "date-fns": "^4.0.0", @@ -12314,10 +12269,10 @@ "store": "^2.0.12" }, "devDependencies": { - "axios": "^1.8.2", - "laravel-vite-plugin": "^1.0.5", - "patch-package": "^8.0.0", - "sass": "^1.78.0", + "axios": "^1", + "laravel-vite-plugin": "^1", + "patch-package": "^8", + "sass": "^1", "vite": "^6", "vite-plugin-manifest-sri": "^0.2.0" } diff --git a/resources/assets/v2/package.json b/resources/assets/v2/package.json index 1c1018dcf9..b7eca8bc55 100644 --- a/resources/assets/v2/package.json +++ b/resources/assets/v2/package.json @@ -8,26 +8,22 @@ "postinstall": "patch-package --error-on-fail" }, "devDependencies": { - "axios": "^1.8.2", - "laravel-vite-plugin": "^1.0.5", - "patch-package": "^8.0.0", - "sass": "^1.78.0", + "axios": "^1", + "laravel-vite-plugin": "^1", + "patch-package": "^8", + "sass": "^1", "vite": "^6", "vite-plugin-manifest-sri": "^0.2.0" }, "dependencies": { - "@ag-grid-community/client-side-row-model": "^32.0.2", - "@ag-grid-community/core": "^32.0.2", - "@ag-grid-community/infinite-row-model": "^32.0.2", - "@ag-grid-community/styles": "^33.0.2", "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "admin-lte": "^4.0.0-alpha3", + "admin-lte": "^4.0.0-beta3", "alpinejs": "^3.13.7", - "bootstrap": "^5.3.0", - "bootstrap5-autocomplete": "^1.1.22", - "bootstrap5-tags": "^1.7", - "chart.js": "^4.4.0", + "bootstrap": "^5", + "bootstrap5-autocomplete": "^1", + "bootstrap5-tags": "^1", + "chart.js": "^4", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.14.0", "date-fns": "^4.0.0", diff --git a/resources/assets/v2/src/api/v1/chart/account/dashboard.js b/resources/assets/v2/src/api/v1/chart/account/dashboard.js new file mode 100644 index 0000000000..f5c1870393 --- /dev/null +++ b/resources/assets/v2/src/api/v1/chart/account/dashboard.js @@ -0,0 +1,36 @@ +/* + * overview.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "../../../../boot/axios"; +import {format} from "date-fns"; + +export default class Dashboard { + dashboard(start, end) { + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get('/api/v1/chart/account/dashboard', {params: {fix: true, start: startStr, end: endStr}}); + } + + expense(start, end) { + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get('/api/v1/chart/account/expense-dashboard', {params: {start: startStr, end: endStr}}); + } +} diff --git a/resources/assets/v2/src/api/v1/chart/budget/dashboard.js b/resources/assets/v2/src/api/v1/chart/budget/dashboard.js new file mode 100644 index 0000000000..6e94a2cc7c --- /dev/null +++ b/resources/assets/v2/src/api/v1/chart/budget/dashboard.js @@ -0,0 +1,30 @@ +/* + * overview.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "../../../../boot/axios"; +import {format} from "date-fns"; + +export default class Dashboard { + dashboard(start, end) { + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get('/api/v1/chart/budget/dashboard', {params: {start: startStr, end: endStr}}); + } +} diff --git a/resources/assets/v2/src/api/v1/chart/category/dashboard.js b/resources/assets/v2/src/api/v1/chart/category/dashboard.js new file mode 100644 index 0000000000..46afdc01b0 --- /dev/null +++ b/resources/assets/v2/src/api/v1/chart/category/dashboard.js @@ -0,0 +1,30 @@ +/* + * overview.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "../../../../boot/axios"; +import {format} from "date-fns"; + +export default class Dashboard { + dashboard(start, end) { + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get('/api/v1/chart/category/dashboard', {params: {start: startStr, end: endStr}}); + } +} diff --git a/resources/assets/v2/src/api/v1/accounts/get.js b/resources/assets/v2/src/api/v1/model/account/get.js similarity index 84% rename from resources/assets/v2/src/api/v1/accounts/get.js rename to resources/assets/v2/src/api/v1/model/account/get.js index ce6fc50d57..a8d014a42c 100644 --- a/resources/assets/v2/src/api/v1/accounts/get.js +++ b/resources/assets/v2/src/api/v1/model/account/get.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -import {api} from "../../../boot/axios"; +import {api} from "../../../../boot/axios"; import format from "date-fns/format"; export default class Get { @@ -37,6 +37,18 @@ export default class Get { return api.get('/api/v1/accounts/' + identifier, {params: params}); } + + /** + * + * @param identifier + * @param params + * @returns {Promise>} + */ + show(identifier, params) { + return api.get('/api/v1/accounts/' + identifier, {params: params}); + } + + /** * * @param identifier diff --git a/resources/assets/v2/src/api/v1/attachments/post.js b/resources/assets/v2/src/api/v1/model/attachment/post.js similarity index 100% rename from resources/assets/v2/src/api/v1/attachments/post.js rename to resources/assets/v2/src/api/v1/model/attachment/post.js diff --git a/resources/assets/v2/src/api/v1/model/piggy-bank/get.js b/resources/assets/v2/src/api/v1/model/piggy-bank/get.js new file mode 100644 index 0000000000..512120b50a --- /dev/null +++ b/resources/assets/v2/src/api/v1/model/piggy-bank/get.js @@ -0,0 +1,35 @@ +/* + * get.js + * Copyright (c) 2023 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +import {api} from "../../../../boot/axios"; + +export default class Get { + + /** + * + * @param params + * @returns {Promise>} + */ + list(params) { + return api.get('/api/v1/piggy-banks', {params: params}); + } + +} diff --git a/resources/assets/v2/src/api/v1/model/subscription/get.js b/resources/assets/v2/src/api/v1/model/subscription/get.js new file mode 100644 index 0000000000..a1ba57460d --- /dev/null +++ b/resources/assets/v2/src/api/v1/model/subscription/get.js @@ -0,0 +1,42 @@ +/* + * get.js + * Copyright (c) 2023 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +import {api} from "../../../../boot/axios"; + +export default class Get { + + /** + * + * @param params + * @returns {Promise>} + */ + list(params) { + return api.get('/api/v1/subscriptions', {params: params}); + } + + paid(params) { + return api.get('/api/v1/subscriptions/sum/paid', {params: params}); + } + + unpaid(params) { + return api.get('/api/v1/subscriptions/sum/unpaid', {params: params}); + } +} diff --git a/resources/assets/v2/src/api/v1/model/transaction/get.js b/resources/assets/v2/src/api/v1/model/transaction/get.js new file mode 100644 index 0000000000..a00b59064a --- /dev/null +++ b/resources/assets/v2/src/api/v1/model/transaction/get.js @@ -0,0 +1,37 @@ +/* + * get.js + * Copyright (c) 2023 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +import {api} from "../../../../boot/axios"; + +export default class Get { + + /** + * + * @param params + * @returns {Promise>} + */ + list(params) { + return api.get('/api/v1/transactions', {params: params}); + } + show(id, params){ + return api.get('/api/v1/transactions/' + id, {params: params}); + } +} diff --git a/resources/assets/v2/src/api/v1/model/transaction/post.js b/resources/assets/v2/src/api/v1/model/transaction/post.js new file mode 100644 index 0000000000..59b97de988 --- /dev/null +++ b/resources/assets/v2/src/api/v1/model/transaction/post.js @@ -0,0 +1,28 @@ +/* + * post.js + * Copyright (c) 2023 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "../../../../boot/axios"; + +export default class Post { + post(submission) { + let url = '/api/v1/transactions'; + return api.post(url, submission); + } +} diff --git a/resources/assets/v2/src/api/v1/model/transaction/put.js b/resources/assets/v2/src/api/v1/model/transaction/put.js new file mode 100644 index 0000000000..ad38c699e7 --- /dev/null +++ b/resources/assets/v2/src/api/v1/model/transaction/put.js @@ -0,0 +1,28 @@ +/* + * post.js + * Copyright (c) 2023 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "../../../../boot/axios"; + +export default class Put { + put(submission, params) { + let url = '/api/v1/transactions/' + parseInt(params.id); + return api.put(url, submission); + } +} diff --git a/resources/assets/v2/src/api/v2/chart/account/dashboard.js b/resources/assets/v2/src/api/v2/chart/account/dashboard.js index eb0c336ea0..521bf7405b 100644 --- a/resources/assets/v2/src/api/v2/chart/account/dashboard.js +++ b/resources/assets/v2/src/api/v2/chart/account/dashboard.js @@ -25,7 +25,7 @@ export default class Dashboard { dashboard(start, end) { let startStr = format(start, 'y-MM-dd'); let endStr = format(end, 'y-MM-dd'); - return api.get('/api/v2/chart/account/dashboard', {params: {filter: {start: startStr, end: endStr}}}); + return api.get('/api/v2/chart/account/dashboard', {params: {start: startStr, end: endStr}}); } expense(start, end) { diff --git a/resources/assets/v2/src/pages/accounts/index.js b/resources/assets/v2/src/pages/accounts/index.js index 422202ee24..80f4b34649 100644 --- a/resources/assets/v2/src/pages/accounts/index.js +++ b/resources/assets/v2/src/pages/accounts/index.js @@ -24,8 +24,8 @@ import i18next from "i18next"; import {format} from "date-fns"; import formatMoney from "../../util/format-money.js"; -import Get from "../../api/v2/model/account/get.js"; -import Put from "../../api/v2/model/account/put.js"; +import Get from "../../api/v1/model/account/get.js"; +import Put from "../../api/v1/model/account/put.js"; import AccountRenderer from "../../support/renderers/AccountRenderer.js"; import {showInternalsButton} from "../../support/page-settings/show-internals-button.js"; import {showWizardButton} from "../../support/page-settings/show-wizard-button.js"; diff --git a/resources/assets/v2/src/pages/administrations/create.js b/resources/assets/v2/src/pages/administrations/create.js index 0def2cdce6..ef0ccd6231 100644 --- a/resources/assets/v2/src/pages/administrations/create.js +++ b/resources/assets/v2/src/pages/administrations/create.js @@ -20,7 +20,7 @@ import '../../boot/bootstrap.js'; import dates from "../shared/dates.js"; -import Post from "../../api/v2/model/user-group/post.js"; +import Post from "../../api/v1/model/user-group/post.js"; import i18next from "i18next"; diff --git a/resources/assets/v2/src/pages/administrations/edit.js b/resources/assets/v2/src/pages/administrations/edit.js index 1cca799b6f..5237b770cd 100644 --- a/resources/assets/v2/src/pages/administrations/edit.js +++ b/resources/assets/v2/src/pages/administrations/edit.js @@ -20,10 +20,10 @@ import '../../boot/bootstrap.js'; import dates from "../shared/dates.js"; -import Post from "../../api/v2/model/user-group/post.js"; +import Post from "../../api/v1/model/user-group/post.js"; import i18next from "i18next"; -import Get from "../../api/v2/model/user-group/get.js"; -import Put from "../../api/v2/model/user-group/put.js"; +import Get from "../../api/v1/model/user-group/get.js"; +import Put from "../../api/v1/model/user-group/put.js"; let administrations = function () { diff --git a/resources/assets/v2/src/pages/administrations/index.js b/resources/assets/v2/src/pages/administrations/index.js index 40fe046ceb..bae286d55a 100644 --- a/resources/assets/v2/src/pages/administrations/index.js +++ b/resources/assets/v2/src/pages/administrations/index.js @@ -23,11 +23,9 @@ import dates from "../shared/dates.js"; import i18next from "i18next"; import {format} from "date-fns"; -import '@ag-grid-community/styles/ag-grid.css'; -import '@ag-grid-community/styles/ag-theme-alpine.css'; import '../../css/grid-ff3-theme.css'; -import Get from "../../api/v2/model/user-group/get.js"; -import Post from "../../api/v2/model/user-group/post.js"; +import Get from "../../api/v1/model/user-group/get.js"; +import Post from "../../api/v1/model/user-group/post.js"; let index = function () { return { diff --git a/resources/assets/v2/src/pages/dashboard/accounts.js b/resources/assets/v2/src/pages/dashboard/accounts.js index e22da6a86c..83567dbae4 100644 --- a/resources/assets/v2/src/pages/dashboard/accounts.js +++ b/resources/assets/v2/src/pages/dashboard/accounts.js @@ -20,9 +20,9 @@ import {getVariable} from "../../store/get-variable.js"; import {setVariable} from "../../store/set-variable.js"; -import Dashboard from "../../api/v2/chart/account/dashboard.js"; +import Dashboard from "../../api/v1/chart/account/dashboard.js"; import formatMoney from "../../util/format-money.js"; -import Get from "../../api/v2/model/account/get.js"; +import Get from "../../api/v1/model/account/get.js"; import {Chart} from 'chart.js'; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; import {getCacheKey} from "../../support/get-cache-key.js"; @@ -39,12 +39,12 @@ export default () => ({ loading: false, loadingAccounts: false, accountList: [], - autoConversion: false, - autoConversionAvailable: false, + convertToNative: false, + convertToNativeAvailable: false, chartOptions: null, - switchAutoConversion() { - this.autoConversion = !this.autoConversion; - setVariable('autoConversion', this.autoConversion); + switchConvertToNative() { + this.convertToNative = !this.convertToNative; + setVariable('convertToNative', this.convertToNative); }, localCacheKey(type) { return 'ds_accounts_' + type; @@ -90,18 +90,18 @@ export default () => ({ dataset.label = current.label; // use the "native" currency code and use the "native_entries" as array - if (this.autoConversion) { - currencies.push(current.native_currency_code); - dataset.currency_code = current.native_currency_code; - collection = Object.values(current.native_entries); - yAxis = 'y' + current.native_currency_code; - } - if (!this.autoConversion) { + // if (this.convertToNative) { + // currencies.push(current.native_currency_code); + // dataset.currency_code = current.native_currency_code; + // collection = Object.values(current.native_entries); + // yAxis = 'y' + current.native_currency_code; + // } + // if (!this.convertToNative) { yAxis = 'y' + current.currency_code; dataset.currency_code = current.currency_code; currencies.push(current.currency_code); collection = Object.values(current.entries); - } + // } dataset.yAxisID = yAxis; dataset.data = collection; @@ -217,12 +217,12 @@ export default () => ({ for (let iii = 0; iii < current.attributes.transactions.length; iii++) { let currentTransaction = current.attributes.transactions[iii]; //console.log(currentTransaction); - let nativeAmountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.native_amount) * -1 : parseFloat(currentTransaction.native_amount); + //let nativeAmountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.native_amount) * -1 : parseFloat(currentTransaction.native_amount); let amountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.amount) * -1 : parseFloat(currentTransaction.amount); // if transfer and source is this account, multiply again if('transfer' === currentTransaction.type && parseInt(currentTransaction.source_id) === accountId) { // - nativeAmountRaw = nativeAmountRaw * -1; + // nativeAmountRaw = nativeAmountRaw * -1; amountRaw = amountRaw * -1; } @@ -232,8 +232,8 @@ export default () => ({ type: currentTransaction.type, amount_raw: amountRaw, amount: formatMoney(amountRaw, currentTransaction.currency_code), - native_amount_raw: nativeAmountRaw, - native_amount: formatMoney(nativeAmountRaw, currentTransaction.native_currency_code), + // native_amount_raw: nativeAmountRaw, + // native_amount: formatMoney(nativeAmountRaw, currentTransaction.native_currency_code), }); } groups.push(group); @@ -244,7 +244,7 @@ export default () => ({ order: parent.attributes.order, id: parent.id, balance: parent.attributes.balance, - native_balance: parent.attributes.native_balance, + //native_balance: parent.attributes.native_balance, groups: groups, }); // console.log(parent.attributes); @@ -266,12 +266,12 @@ export default () => ({ init() { // console.log('accounts init'); - Promise.all([getVariable('viewRange', '1M'), getVariable('autoConversion', false), getVariable('language', 'en_US'), + Promise.all([getVariable('viewRange', '1M'), getVariable('convertToNative', false), getVariable('language', 'en_US'), getConfiguration('cer.enabled', false) ]).then((values) => { //console.log('accounts after promises'); - this.autoConversion = values[1] && values[3]; - this.autoConversionAvailable = values[3]; + this.convertToNative = values[1] && values[3]; + this.convertToNativeAvailable = values[3]; afterPromises = true; // main dashboard chart: @@ -289,11 +289,11 @@ export default () => ({ this.loadChart(); this.loadAccounts(); }); - window.store.observe('autoConversion', () => { + window.store.observe('convertToNative', () => { if (!afterPromises) { return; } - // console.log('accounts observe autoconversion'); + // console.log('accounts observe convertToNative'); this.loadChart(); this.loadAccounts(); }); diff --git a/resources/assets/v2/src/pages/dashboard/boxes.js b/resources/assets/v2/src/pages/dashboard/boxes.js index 1bcc66497a..911233af94 100644 --- a/resources/assets/v2/src/pages/dashboard/boxes.js +++ b/resources/assets/v2/src/pages/dashboard/boxes.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -import Summary from "../../api/v2/summary/index.js"; +import Summary from "../../api/v1/summary/index.js"; import {format} from "date-fns"; import {getVariable} from "../../store/get-variable.js"; import formatMoney from "../../util/format-money.js"; @@ -31,7 +31,7 @@ export default () => ({ billBox: {paid: [], unpaid: []}, leftBox: {left: [], perDay: []}, netBox: {net: []}, - autoConversion: false, + convertToNative: false, loading: false, boxData: null, boxOptions: null, @@ -42,8 +42,9 @@ export default () => ({ const boxesCacheKey = getCacheKey('ds_boxes_data', {start: start, end: end}); cleanupCache(); - const cacheValid = window.store.get('cacheValid'); + //const cacheValid = window.store.get('cacheValid'); let cachedData = window.store.get(boxesCacheKey); + const cacheValid = false; // force refresh if (cacheValid && typeof cachedData !== 'undefined') { this.boxData = cachedData; @@ -75,114 +76,56 @@ export default () => ({ continue; } let key = current.key; - // native (auto conversion): - if (this.autoConversion) { - if (key.startsWith('balance-in-native')) { - this.balanceBox.amounts.push(formatMoney(current.value, current.currency_code)); - // prep subtitles (for later) - if (!subtitles.hasOwnProperty(current.currency_code)) { - subtitles[current.currency_code] = ''; - } - continue; - } - // spent info is used in subtitle: - if (key.startsWith('spent-in-native')) { - // prep subtitles (for later) - if (!subtitles.hasOwnProperty(current.currency_code)) { - subtitles[current.currency_code] = ''; - } - // append the amount spent. - subtitles[current.currency_code] = - subtitles[current.currency_code] + - formatMoney(current.value, current.currency_code); - continue; - } - // earned info is used in subtitle: - if (key.startsWith('earned-in-native')) { - // prep subtitles (for later) - if (!subtitles.hasOwnProperty(current.currency_code)) { - subtitles[current.currency_code] = ''; - } - // prepend the amount earned. - subtitles[current.currency_code] = - formatMoney(current.value, current.currency_code) + ' + ' + - subtitles[current.currency_code]; - continue; - } - - if (key.startsWith('bills-unpaid-in-native')) { - this.billBox.unpaid.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('bills-paid-in-native')) { - this.billBox.paid.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('left-to-spend-in-native')) { - this.leftBox.left.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('left-per-day-to-spend-in-native')) { // per day - this.leftBox.perDay.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('net-worth-in-native')) { - this.netBox.net.push(formatMoney(current.value, current.currency_code)); - continue; - } + console.log('NOT NATIVE'); + if (key.startsWith('balance-in-')) { + this.balanceBox.amounts.push(formatMoney(current.monetary_value, current.currency_code)); + continue; } - // not native - if (!this.autoConversion && !key.endsWith('native')) { - if (key.startsWith('balance-in-')) { - this.balanceBox.amounts.push(formatMoney(current.value, current.currency_code)); - continue; + // spent info is used in subtitle: + if (key.startsWith('spent-in-')) { + // prep subtitles (for later) + if (!subtitles.hasOwnProperty(current.currency_code)) { + subtitles[current.currency_code] = ''; } - // spent info is used in subtitle: - if (key.startsWith('spent-in-')) { - // prep subtitles (for later) - if (!subtitles.hasOwnProperty(current.currency_code)) { - subtitles[current.currency_code] = ''; - } - // append the amount spent. - subtitles[current.currency_code] = - subtitles[current.currency_code] + - formatMoney(current.value, current.currency_code); - continue; - } - // earned info is used in subtitle: - if (key.startsWith('earned-in-')) { - // prep subtitles (for later) - if (!subtitles.hasOwnProperty(current.currency_code)) { - subtitles[current.currency_code] = ''; - } - // prepend the amount earned. - subtitles[current.currency_code] = - formatMoney(current.value, current.currency_code) + ' + ' + - subtitles[current.currency_code]; - continue; + // append the amount spent. + subtitles[current.currency_code] = + subtitles[current.currency_code] + + formatMoney(current.monetary_value, current.currency_code); + continue; + } + // earned info is used in subtitle: + if (key.startsWith('earned-in-')) { + // prep subtitles (for later) + if (!subtitles.hasOwnProperty(current.currency_code)) { + subtitles[current.currency_code] = ''; } + // prepend the amount earned. + subtitles[current.currency_code] = + formatMoney(current.monetary_value, current.currency_code) + ' + ' + + subtitles[current.currency_code]; + continue; + } - if (key.startsWith('bills-unpaid-in-')) { - this.billBox.unpaid.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('bills-paid-in-')) { - this.billBox.paid.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('left-to-spend-in-')) { - this.leftBox.left.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('left-per-day-to-spend-in-')) { - this.leftBox.perDay.push(formatMoney(current.value, current.currency_code)); - continue; - } - if (key.startsWith('net-worth-in-')) { - this.netBox.net.push(formatMoney(current.value, current.currency_code)); + if (key.startsWith('bills-unpaid-in-')) { + this.billBox.unpaid.push(formatMoney(current.monetary_value, current.currency_code)); + continue; + } + if (key.startsWith('bills-paid-in-')) { + this.billBox.paid.push(formatMoney(current.monetary_value, current.currency_code)); + continue; + } + if (key.startsWith('left-to-spend-in-')) { + this.leftBox.left.push(formatMoney(current.monetary_value, current.currency_code)); + continue; + } + if (key.startsWith('left-per-day-to-spend-in-')) { + this.leftBox.perDay.push(formatMoney(current.monetary_value, current.currency_code)); + continue; + } + if (key.startsWith('net-worth-in-')) { + this.netBox.net.push(formatMoney(current.monetary_value, current.currency_code)); - } } } } @@ -210,10 +153,10 @@ export default () => ({ init() { // console.log('boxes init'); // TODO can be replaced by "getVariables" - Promise.all([getVariable('viewRange'), getVariable('autoConversion', false)]).then((values) => { + Promise.all([getVariable('viewRange'), getVariable('convertToNative', false)]).then((values) => { // console.log('boxes after promises'); afterPromises = true; - this.autoConversion = values[1]; + this.convertToNative = values[1]; this.loadBoxes(); }); window.store.observe('end', () => { @@ -224,12 +167,12 @@ export default () => ({ this.boxData = null; this.loadBoxes(); }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - // console.log('boxes observe autoConversion'); - this.autoConversion = newValue; + // console.log('boxes observe convertToNative'); + this.convertToNative = newValue; this.loadBoxes(); }); }, diff --git a/resources/assets/v2/src/pages/dashboard/budgets.js b/resources/assets/v2/src/pages/dashboard/budgets.js index fe7dc039af..5f8a4d800a 100644 --- a/resources/assets/v2/src/pages/dashboard/budgets.js +++ b/resources/assets/v2/src/pages/dashboard/budgets.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ import {getVariable} from "../../store/get-variable.js"; -import Dashboard from "../../api/v2/chart/budget/dashboard.js"; +import Dashboard from "../../api/v1/chart/budget/dashboard.js"; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; import formatMoney from "../../util/format-money.js"; import {Chart} from 'chart.js'; @@ -34,7 +34,7 @@ let afterPromises = false; export default () => ({ loading: false, - autoConversion: false, + convertToNative: false, loadChart() { if (true === this.loading) { return; @@ -134,7 +134,7 @@ export default () => ({ // // convert to EUR yes no? let label = current.label + ' (' + current.currency_code + ')'; options.data.labels.push(label); - if (this.autoConversion) { + if (this.convertToNative) { currencies.push(current.native_currency_code); // series 0: spent options.data.datasets[0].data.push(parseFloat(current.native_entries.spent) * -1); @@ -143,7 +143,7 @@ export default () => ({ // series 2: overspent options.data.datasets[2].data.push(parseFloat(current.native_entries.overspent)); } - if (!this.autoConversion) { + if (!this.convertToNative) { currencies.push(current.currency_code); // series 0: spent options.data.datasets[0].data.push(parseFloat(current.entries.spent) * -1); @@ -172,8 +172,8 @@ export default () => ({ init() { - Promise.all([getVariable('autoConversion', false)]).then((values) => { - this.autoConversion = values[0]; + Promise.all([getVariable('convertToNative', false)]).then((values) => { + this.convertToNative = values[0]; afterPromises = true; if (false === this.loading) { this.loadChart(); @@ -189,12 +189,12 @@ export default () => ({ this.loadChart(); } }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - // console.log('boxes observe autoConversion'); - this.autoConversion = newValue; + // console.log('boxes observe convertToNative'); + this.convertToNative = newValue; if (false === this.loading) { this.loadChart(); } diff --git a/resources/assets/v2/src/pages/dashboard/categories.js b/resources/assets/v2/src/pages/dashboard/categories.js index 8f68e28b38..b655947c0b 100644 --- a/resources/assets/v2/src/pages/dashboard/categories.js +++ b/resources/assets/v2/src/pages/dashboard/categories.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ import {getVariable} from "../../store/get-variable.js"; -import Dashboard from "../../api/v2/chart/category/dashboard.js"; +import Dashboard from "../../api/v1/chart/category/dashboard.js"; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; import {Chart} from "chart.js"; import formatMoney from "../../util/format-money.js"; @@ -32,7 +32,7 @@ let afterPromises = false; export default () => ({ loading: false, - autoConversion: false, + convertToNative: false, generateOptions(data) { currencies = []; let options = getDefaultChartSettings('column'); @@ -44,7 +44,7 @@ export default () => ({ let current = data[i]; let code = current.currency_code; // only use native code when doing auto conversion. - if (this.autoConversion) { + if (this.convertToNative) { code = current.native_currency_code; } @@ -65,7 +65,7 @@ export default () => ({ let yAxis = 'y'; let current = data[i]; let code = current.currency_code; - if (this.autoConversion) { + if (this.convertToNative) { code = current.native_currency_code; } @@ -77,7 +77,7 @@ export default () => ({ // this series' currency matches this column's currency. amount = parseFloat(current.amount); yAxis = 'y' + current.currency_code; - if (this.autoConversion) { + if (this.convertToNative) { amount = parseFloat(current.native_amount); yAxis = 'y' + current.native_currency_code; } @@ -183,8 +183,8 @@ export default () => ({ }, init() { // console.log('categories init'); - Promise.all([getVariable('autoConversion', false),]).then((values) => { - this.autoConversion = values[0]; + Promise.all([getVariable('convertToNative', false),]).then((values) => { + this.convertToNative = values[0]; afterPromises = true; this.loadChart(); }); @@ -195,11 +195,11 @@ export default () => ({ this.chartData = null; this.loadChart(); }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - this.autoConversion = newValue; + this.convertToNative = newValue; this.loadChart(); }); }, diff --git a/resources/assets/v2/src/pages/dashboard/piggies.js b/resources/assets/v2/src/pages/dashboard/piggies.js index 037932f9f2..a23bd4e63e 100644 --- a/resources/assets/v2/src/pages/dashboard/piggies.js +++ b/resources/assets/v2/src/pages/dashboard/piggies.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ import {getVariable} from "../../store/get-variable.js"; -import Get from "../../api/v2/model/piggy-bank/get.js"; +import Get from "../../api/v1/model/piggy-bank/get.js"; import {getCacheKey} from "../../support/get-cache-key.js"; import {format} from "date-fns"; import i18next from "i18next"; @@ -29,7 +29,7 @@ const PIGGY_CACHE_KEY = 'ds_pg_data'; export default () => ({ loading: false, - autoConversion: false, + convertToNative: false, sankeyGrouping: 'account', piggies: [], getFreshData() { @@ -96,14 +96,14 @@ export default () => ({ id: current.id, name: current.attributes.name, percentage: parseInt(current.attributes.percentage), - amount: this.autoConversion ? current.attributes.native_current_amount : current.attributes.current_amount, + amount: this.convertToNative ? current.attributes.native_current_amount : current.attributes.current_amount, // left to save - left_to_save: this.autoConversion ? current.attributes.native_left_to_save : current.attributes.left_to_save, + left_to_save: this.convertToNative ? current.attributes.native_left_to_save : current.attributes.left_to_save, // target amount - target_amount: this.autoConversion ? current.attributes.native_target_amount : current.attributes.target_amount, + target_amount: this.convertToNative ? current.attributes.native_target_amount : current.attributes.target_amount, // save per month - save_per_month: this.autoConversion ? current.attributes.native_save_per_month : current.attributes.save_per_month, - currency_code: this.autoConversion ? current.attributes.native_currency_code : current.attributes.currency_code, + save_per_month: this.convertToNative ? current.attributes.native_save_per_month : current.attributes.save_per_month, + currency_code: this.convertToNative ? current.attributes.native_currency_code : current.attributes.currency_code, }; dataSet[groupName].piggies.push(piggy); @@ -129,10 +129,10 @@ export default () => ({ init() { // console.log('piggies init'); apiData = []; - Promise.all([getVariable('autoConversion', false)]).then((values) => { + Promise.all([getVariable('convertToNative', false)]).then((values) => { afterPromises = true; - this.autoConversion = values[0]; + this.convertToNative = values[0]; this.loadPiggyBanks(); }); @@ -144,12 +144,12 @@ export default () => ({ apiData = []; this.loadPiggyBanks(); }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - // console.log('piggies observe autoConversion'); - this.autoConversion = newValue; + // console.log('piggies observe convertToNative'); + this.convertToNative = newValue; this.loadPiggyBanks(); }); }, diff --git a/resources/assets/v2/src/pages/dashboard/sankey.js b/resources/assets/v2/src/pages/dashboard/sankey.js index 40a73e5aaa..6705883ad2 100644 --- a/resources/assets/v2/src/pages/dashboard/sankey.js +++ b/resources/assets/v2/src/pages/dashboard/sankey.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ import {getVariable} from "../../store/get-variable.js"; -import Get from "../../api/v2/model/transaction/get.js"; +import Get from "../../api/v1/model/transaction/get.js"; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; import {Chart} from 'chart.js'; import {Flow, SankeyController} from 'chartjs-chart-sankey'; @@ -33,7 +33,7 @@ let currencies = []; let afterPromises = false; let chart = null; let transactions = []; -let autoConversion = false; +let convertToNative = false; let translations = { category: null, unknown_category: null, @@ -83,37 +83,37 @@ function getObjectName(type, name, direction, code) { // category 4x if ('category' === type && null !== name && 'in' === direction) { - return translations.category + ' "' + name + '" (' + translations.in + (autoConversion ? ', ' + code + ')' : ')'); + return translations.category + ' "' + name + '" (' + translations.in + (convertToNative ? ', ' + code + ')' : ')'); } if ('category' === type && null === name && 'in' === direction) { - return translations.unknown_category + ' (' + translations.in + (autoConversion ? ', ' + code + ')' : ')'); + return translations.unknown_category + ' (' + translations.in + (convertToNative ? ', ' + code + ')' : ')'); } if ('category' === type && null !== name && 'out' === direction) { - return translations.category + ' "' + name + '" (' + translations.out + (autoConversion ? ', ' + code + ')' : ')'); + return translations.category + ' "' + name + '" (' + translations.out + (convertToNative ? ', ' + code + ')' : ')'); } if ('category' === type && null === name && 'out' === direction) { - return translations.unknown_category + ' (' + translations.out + (autoConversion ? ', ' + code + ')' : ')'); + return translations.unknown_category + ' (' + translations.out + (convertToNative ? ', ' + code + ')' : ')'); } // account 4x if ('account' === type && null === name && 'in' === direction) { - return translations.unknown_source + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_source + (convertToNative ? ' (' + code + ')' : ''); } if ('account' === type && null !== name && 'in' === direction) { - return translations.revenue_account + '"' + name + '"' + (autoConversion ? ' (' + code + ')' : ''); + return translations.revenue_account + '"' + name + '"' + (convertToNative ? ' (' + code + ')' : ''); } if ('account' === type && null === name && 'out' === direction) { - return translations.unknown_dest + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_dest + (convertToNative ? ' (' + code + ')' : ''); } if ('account' === type && null !== name && 'out' === direction) { - return translations.expense_account + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : ''); + return translations.expense_account + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : ''); } // budget 2x if ('budget' === type && null !== name) { - return translations.budget + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : ''); + return translations.budget + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : ''); } if ('budget' === type && null === name) { - return translations.unknown_budget + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_budget + (convertToNative ? ' (' + code + ')' : ''); } console.error('Cannot handle: type:"' + type + '", dir: "' + direction + '"'); } @@ -121,25 +121,25 @@ function getObjectName(type, name, direction, code) { function getLabelName(type, name, code) { // category if ('category' === type && null !== name) { - return translations.category + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : ''); + return translations.category + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : ''); } if ('category' === type && null === name) { - return translations.unknown_category + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_category + (convertToNative ? ' (' + code + ')' : ''); } // account if ('account' === type && null === name) { - return translations.unknown_account + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_account + (convertToNative ? ' (' + code + ')' : ''); } if ('account' === type && null !== name) { - return name + (autoConversion ? ' (' + code + ')' : ''); + return name + (convertToNative ? ' (' + code + ')' : ''); } // budget 2x if ('budget' === type && null !== name) { - return translations.budget + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : ''); + return translations.budget + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : ''); } if ('budget' === type && null === name) { - return translations.unknown_budget + (autoConversion ? ' (' + code + ')' : ''); + return translations.unknown_budget + (convertToNative ? ' (' + code + ')' : ''); } console.error('Cannot handle: type:"' + type + '"'); } @@ -147,7 +147,7 @@ function getLabelName(type, name, code) { export default () => ({ loading: false, - autoConversion: false, + convertToNative: false, generateOptions() { let options = getDefaultChartSettings('sankey'); @@ -164,8 +164,8 @@ export default () => ({ if (group.attributes.transactions.hasOwnProperty(ii)) { // properties of the transaction, used in the generation of the chart: let transaction = group.attributes.transactions[ii]; - let currencyCode = this.autoConversion ? transaction.native_currency_code : transaction.currency_code; - let amount = this.autoConversion ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount); + let currencyCode = this.convertToNative ? transaction.native_currency_code : transaction.currency_code; + let amount = this.convertToNative ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount); let flowKey; /* @@ -194,7 +194,7 @@ export default () => ({ if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { from: category, - to: translations.all_money + (this.autoConversion ? ' (' + currencyCode + ')' : ''), + to: translations.all_money + (this.convertToNative ? ' (' + currencyCode + ')' : ''), amount: 0 }; } @@ -214,7 +214,7 @@ export default () => ({ if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { - from: translations.all_money + (this.autoConversion ? ' (' + currencyCode + ')' : ''), + from: translations.all_money + (this.convertToNative ? ' (' + currencyCode + ')' : ''), to: budget, amount: 0 }; @@ -348,9 +348,9 @@ export default () => ({ init() { // console.log('sankey init'); transactions = []; - Promise.all([getVariable('autoConversion', false)]).then((values) => { - this.autoConversion = values[0]; - autoConversion = values[0]; + Promise.all([getVariable('convertToNative', false)]).then((values) => { + this.convertToNative = values[0]; + convertToNative = values[0]; // some translations: translations.all_money = i18next.t('firefly.all_money'); translations.category = i18next.t('firefly.category'); @@ -378,12 +378,12 @@ export default () => ({ this.transactions = []; this.loadChart(); }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - // console.log('sankey observe autoConversion'); - this.autoConversion = newValue; + // console.log('sankey observe convertToNative'); + this.convertToNative = newValue; this.loadChart(); }); }, diff --git a/resources/assets/v2/src/pages/dashboard/subscriptions.js b/resources/assets/v2/src/pages/dashboard/subscriptions.js index 9cca5c9c7e..6b1f35da7a 100644 --- a/resources/assets/v2/src/pages/dashboard/subscriptions.js +++ b/resources/assets/v2/src/pages/dashboard/subscriptions.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ import {getVariable} from "../../store/get-variable.js"; -import Get from "../../api/v2/model/subscription/get.js"; +import Get from "../../api/v1/model/subscription/get.js"; import {format} from "date-fns"; import {getCacheKey} from "../../support/get-cache-key.js"; import {Chart} from "chart.js"; @@ -66,10 +66,10 @@ function downloadSubscriptions(params) { currency_code: current.attributes.currency_code, // native amount - native_amount_min: current.attributes.native_amount_min, - native_amount_max: current.attributes.native_amount_max, - native_amount: (parseFloat(current.attributes.native_amount_max) + parseFloat(current.attributes.native_amount_min)) / 2, - native_currency_code: current.attributes.native_currency_code, + // native_amount_min: current.attributes.native_amount_min, + // native_amount_max: current.attributes.native_amount_max, + // native_amount: (parseFloat(current.attributes.native_amount_max) + parseFloat(current.attributes.native_amount_min)) / 2, + // native_currency_code: current.attributes.native_currency_code, // paid transactions: transactions: [], @@ -79,8 +79,7 @@ function downloadSubscriptions(params) { paid: current.attributes.paid_dates.length > 0, }; // set variables - bill.expected_amount = params.autoConversion ? formatMoney(bill.native_amount, bill.native_currency_code) : - formatMoney(bill.amount, bill.currency_code); + bill.expected_amount = formatMoney(bill.amount, bill.currency_code); bill.expected_times = i18next.t('firefly.subscr_expected_x_times', { times: current.attributes.pay_dates.length, amount: bill.expected_amount @@ -92,22 +91,25 @@ function downloadSubscriptions(params) { const currentPayment = current.attributes.paid_dates[iii]; let percentage = 100; // math: -100+(paid/expected)*100 - if (params.autoConversion) { + if (params.convertToNative) { percentage = Math.round(-100 + ((parseFloat(currentPayment.native_amount) * -1) / parseFloat(bill.native_amount)) * 100); } - if (!params.autoConversion) { + if (!params.convertToNative) { percentage = Math.round(-100 + ((parseFloat(currentPayment.amount) * -1) / parseFloat(bill.amount)) * 100); } - + // TODO fix me + currentPayment.currency_code = 'EUR'; + console.log('Currency code: "'+currentPayment+'"'); + console.log(currentPayment); let currentTransaction = { - amount: params.autoConversion ? formatMoney(currentPayment.native_amount, currentPayment.native_currency_code) : formatMoney(currentPayment.amount, currentPayment.currency_code), + amount: formatMoney(currentPayment.amount, currentPayment.currency_code), percentage: percentage, date: format(new Date(currentPayment.date), 'PP'), foreign_amount: null, }; if (null !== currentPayment.foreign_currency_code) { - currentTransaction.foreign_amount = params.autoConversion ? currentPayment.foreign_native_amount : currentPayment.foreign_amount; - currentTransaction.foreign_currency_code = params.autoConversion ? currentPayment.native_currency_code : currentPayment.foreign_currency_code; + currentTransaction.foreign_amount = currentPayment.foreign_amount; + currentTransaction.foreign_currency_code = currentPayment.foreign_currency_code; } bill.transactions.push(currentTransaction); @@ -119,7 +121,7 @@ function downloadSubscriptions(params) { // bill is unpaid, count the "pay_dates" and multiply with the "amount". // since bill is unpaid, this can only be in currency amount and native currency amount. const totalAmount = current.attributes.pay_dates.length * bill.amount; - const totalNativeAmount = current.attributes.pay_dates.length * bill.native_amount; + // const totalNativeAmount = current.attributes.pay_dates.length * bill.native_amount; // for bill's currency if (!subscriptionData[objectGroupId].payment_info.hasOwnProperty(bill.currency_code)) { subscriptionData[objectGroupId].payment_info[bill.currency_code] = { @@ -128,11 +130,11 @@ function downloadSubscriptions(params) { unpaid: 0, native_currency_code: bill.native_currency_code, native_paid: 0, - native_unpaid: 0, + //native_unpaid: 0, }; } subscriptionData[objectGroupId].payment_info[bill.currency_code].unpaid += totalAmount; - subscriptionData[objectGroupId].payment_info[bill.currency_code].native_unpaid += totalNativeAmount; + //subscriptionData[objectGroupId].payment_info[bill.currency_code].native_unpaid += totalNativeAmount; } if (current.attributes.paid_dates.length > 0) { @@ -149,15 +151,15 @@ function downloadSubscriptions(params) { currency_code: bill.currency_code, paid: 0, unpaid: 0, - native_currency_code: bill.native_currency_code, - native_paid: 0, - native_unpaid: 0, + // native_currency_code: bill.native_currency_code, + // native_paid: 0, + //native_unpaid: 0, }; } const amount = parseFloat(currentJournal.amount) * -1; - const nativeAmount = parseFloat(currentJournal.native_amount) * -1; + // const nativeAmount = parseFloat(currentJournal.native_amount) * -1; subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].paid += amount; - subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].native_paid += nativeAmount; + // subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].native_paid += nativeAmount; } } } @@ -178,7 +180,7 @@ function downloadSubscriptions(params) { export default () => ({ loading: false, - autoConversion: false, + convertToNative: false, subscriptions: [], startSubscriptions() { this.loading = true; @@ -198,7 +200,7 @@ export default () => ({ let params = { start: format(start, 'y-MM-dd'), end: format(end, 'y-MM-dd'), - autoConversion: this.autoConversion, + // convertToNative: this.convertToNative, page: 1 }; downloadSubscriptions(params).then(() => { @@ -226,9 +228,9 @@ export default () => ({ drawPieChart(groupId, groupTitle, data) { let id = '#pie_' + groupId + '_' + data.currency_code; //console.log(data); - const unpaidAmount = this.autoConversion ? data.native_unpaid : data.unpaid; - const paidAmount = this.autoConversion ? data.native_paid : data.paid; - const currencyCode = this.autoConversion ? data.native_currency_code : data.currency_code; + const unpaidAmount = data.unpaid; + const paidAmount = data.paid; + const currencyCode = data.currency_code; const chartData = { labels: [ i18next.t('firefly.paid'), @@ -267,8 +269,8 @@ export default () => ({ }, init() { - Promise.all([getVariable('autoConversion', false)]).then((values) => { - this.autoConversion = values[0]; + Promise.all([getVariable('convertToNative', false)]).then((values) => { + this.convertToNative = values[0]; afterPromises = true; if (false === this.loading) { @@ -285,11 +287,11 @@ export default () => ({ this.startSubscriptions(); } }); - window.store.observe('autoConversion', (newValue) => { + window.store.observe('convertToNative', (newValue) => { if (!afterPromises) { return; } - this.autoConversion = newValue; + this.convertToNative = newValue; if (false === this.loading) { this.startSubscriptions(); } diff --git a/resources/assets/v2/src/pages/transactions/create.js b/resources/assets/v2/src/pages/transactions/create.js index 18682d0e98..a876f78e88 100644 --- a/resources/assets/v2/src/pages/transactions/create.js +++ b/resources/assets/v2/src/pages/transactions/create.js @@ -23,7 +23,7 @@ import dates from '../../pages/shared/dates.js'; import {createEmptySplit, defaultErrorSet} from "./shared/create-empty-split.js"; import {parseFromEntries} from "./shared/parse-from-entries.js"; import formatMoney from "../../util/format-money.js"; -import Post from "../../api/v2/model/transaction/post.js"; +import Post from "../../api/v1/model/transaction/post.js"; import {loadCurrencies} from "./shared/load-currencies.js"; import {loadBudgets} from "./shared/load-budgets.js"; import {loadPiggyBanks} from "./shared/load-piggy-banks.js"; diff --git a/resources/assets/v2/src/pages/transactions/edit.js b/resources/assets/v2/src/pages/transactions/edit.js index 9d3fcc38d7..7698a1b131 100644 --- a/resources/assets/v2/src/pages/transactions/edit.js +++ b/resources/assets/v2/src/pages/transactions/edit.js @@ -21,7 +21,7 @@ import '../../boot/bootstrap.js'; import dates from '../../pages/shared/dates.js'; import formatMoney from "../../util/format-money.js"; -import Get from "../../api/v2/model/transaction/get.js"; +import Get from "../../api/v1/model/transaction/get.js"; import {parseDownloadedSplits} from "./shared/parse-downloaded-splits.js"; import {addAutocomplete, getUrls} from "./shared/add-autocomplete.js"; import { @@ -40,7 +40,7 @@ import Tags from "bootstrap5-tags"; import i18next from "i18next"; import {defaultErrorSet} from "./shared/create-empty-split.js"; import {parseFromEntries} from "./shared/parse-from-entries.js"; -import Put from "../../api/v2/model/transaction/put.js"; +import Put from "../../api/v1/model/transaction/put.js"; import {processAttachments} from "./shared/process-attachments.js"; import {spliceErrorsIntoTransactions} from "./shared/splice-errors-into-transactions.js"; diff --git a/resources/assets/v2/src/pages/transactions/index.js b/resources/assets/v2/src/pages/transactions/index.js index 7b8d3c759d..e9f587b624 100644 --- a/resources/assets/v2/src/pages/transactions/index.js +++ b/resources/assets/v2/src/pages/transactions/index.js @@ -24,10 +24,8 @@ import i18next from "i18next"; import {format} from "date-fns"; import formatMoney from "../../util/format-money.js"; -import '@ag-grid-community/styles/ag-grid.css'; -import '@ag-grid-community/styles/ag-theme-alpine.css'; import '../../css/grid-ff3-theme.css'; -import Get from "../../api/v2/model/transaction/get.js"; +import Get from "../../api/v1/model/transaction/get.js"; let index = function () { return { diff --git a/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js b/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js index d037448707..c648579df0 100644 --- a/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js +++ b/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js @@ -22,10 +22,10 @@ import Autocomplete from "bootstrap5-autocomplete"; export function getUrls() { return { - description: '/api/v2/autocomplete/transaction-descriptions', - account: '/api/v2/autocomplete/accounts', - category: '/api/v2/autocomplete/categories', - tag: '/api/v2/autocomplete/tags', + description: '/api/v1/autocomplete/transaction-descriptions', + account: '/api/v1/autocomplete/accounts', + category: '/api/v1/autocomplete/categories', + tag: '/api/v1/autocomplete/tags', } } diff --git a/resources/assets/v2/src/pages/transactions/shared/load-budgets.js b/resources/assets/v2/src/pages/transactions/shared/load-budgets.js index 27ba98b582..8416953fc3 100644 --- a/resources/assets/v2/src/pages/transactions/shared/load-budgets.js +++ b/resources/assets/v2/src/pages/transactions/shared/load-budgets.js @@ -19,7 +19,7 @@ */ -import Get from "../../../api/v2/model/budget/get.js"; +import Get from "../../../api/v1/model/budget/get.js"; export function loadBudgets() { let params = { diff --git a/resources/assets/v2/src/pages/transactions/shared/load-currencies.js b/resources/assets/v2/src/pages/transactions/shared/load-currencies.js index 048baa5701..02497d5a3a 100644 --- a/resources/assets/v2/src/pages/transactions/shared/load-currencies.js +++ b/resources/assets/v2/src/pages/transactions/shared/load-currencies.js @@ -19,7 +19,7 @@ */ -import Get from "../../../api/v2/model/currency/get.js"; +import Get from "../../../api/v1/model/currency/get.js"; export function loadCurrencies() { let params = { diff --git a/resources/assets/v2/src/pages/transactions/shared/load-piggy-banks.js b/resources/assets/v2/src/pages/transactions/shared/load-piggy-banks.js index 3e32d8afb6..c014345539 100644 --- a/resources/assets/v2/src/pages/transactions/shared/load-piggy-banks.js +++ b/resources/assets/v2/src/pages/transactions/shared/load-piggy-banks.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -import Get from "../../../api/v2/model/piggy-bank/get.js"; +import Get from "../../../api/v1/model/piggy-bank/get.js"; export function loadPiggyBanks() { let params = { diff --git a/resources/assets/v2/src/pages/transactions/shared/load-subscriptions.js b/resources/assets/v2/src/pages/transactions/shared/load-subscriptions.js index 29dea7b13b..a3ecb8b657 100644 --- a/resources/assets/v2/src/pages/transactions/shared/load-subscriptions.js +++ b/resources/assets/v2/src/pages/transactions/shared/load-subscriptions.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -import SubscriptionGet from "../../../api/v2/model/subscription/get.js"; +import SubscriptionGet from "../../../api/v1/model/subscription/get.js"; export function loadSubscriptions() { let params = { diff --git a/resources/assets/v2/src/pages/transactions/show.js b/resources/assets/v2/src/pages/transactions/show.js index 5b24c388c8..ad5a3f55ab 100644 --- a/resources/assets/v2/src/pages/transactions/show.js +++ b/resources/assets/v2/src/pages/transactions/show.js @@ -21,7 +21,7 @@ import '../../boot/bootstrap.js'; import dates from "../shared/dates.js"; import i18next from "i18next"; -import Get from "../../api/v2/model/transaction/get.js"; +import Get from "../../api/v1/model/transaction/get.js"; import {parseDownloadedSplits} from "./shared/parse-downloaded-splits.js"; import {format} from "date-fns"; import formatMoney from "../../util/format-money.js"; diff --git a/resources/assets/v2/vite.config.js b/resources/assets/v2/vite.config.js index 74c6bde199..f3f18671bb 100644 --- a/resources/assets/v2/vite.config.js +++ b/resources/assets/v2/vite.config.js @@ -36,8 +36,8 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => { let https = null; if (command === 'serve') { https = { - key: fs.readFileSync(`/sites/vm/tls-certificates/wildcard.sd.internal.key`), - cert: fs.readFileSync(`/sites/vm/tls-certificates/wildcard.sd.internal.crt`), + key: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.key`), + cert: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.crt`), }; } @@ -82,11 +82,13 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => { server: { - origin: 'http://127.0.0.1:8000', + cors: true, + origin: 'https://firefly.sd.internal:5173', watch: { usePolling: true, }, - host: '10.0.0.15', + port: 5173, + host: true, // hmr: { // protocol: 'wss', // }, diff --git a/resources/views/v2/partials/dashboard/account-chart.blade.php b/resources/views/v2/partials/dashboard/account-chart.blade.php index 40a4fc9db1..3e173575ec 100644 --- a/resources/views/v2/partials/dashboard/account-chart.blade.php +++ b/resources/views/v2/partials/dashboard/account-chart.blade.php @@ -9,17 +9,17 @@
-