mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-30 02:26:58 +00:00
Merge pull request #10716 from firefly-iii/release-1754505595
🤖 Automatically merge the PR into the develop branch.
This commit is contained in:
@@ -123,7 +123,7 @@ class ListController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
@@ -130,7 +130,7 @@ class ListController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
@@ -154,7 +154,7 @@ class ListController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEventEnrichment();
|
$enrichment = new PiggyBankEventEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$events = $enrichment->enrich($events);
|
$events = $enrichment->enrich($events);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
@@ -84,7 +84,7 @@ class ShowController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||||
@@ -115,7 +115,7 @@ class ShowController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||||
|
|
||||||
|
|
||||||
/** @var PiggyBankTransformer $transformer */
|
/** @var PiggyBankTransformer $transformer */
|
||||||
|
@@ -75,7 +75,7 @@ class StoreController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||||
|
|
||||||
/** @var PiggyBankTransformer $transformer */
|
/** @var PiggyBankTransformer $transformer */
|
||||||
$transformer = app(PiggyBankTransformer::class);
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
@@ -77,7 +77,7 @@ class UpdateController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||||
|
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
|
|
||||||
|
@@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
|
||||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@@ -79,14 +78,14 @@ class ShowController extends Controller
|
|||||||
// get list of budgets. Count it and split it.
|
// get list of budgets. Count it and split it.
|
||||||
$collection = $this->repository->get();
|
$collection = $this->repository->get();
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
$recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
// enrich
|
// enrich
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new RecurringEnrichment();
|
$enrichment = new RecurringEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$recurrences = $enrichment->enrich($recurrences);
|
$recurrences = $enrichment->enrich($recurrences);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
|
||||||
@@ -117,7 +116,7 @@ class ShowController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new RecurringEnrichment();
|
$enrichment = new RecurringEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||||
|
|
||||||
/** @var RecurrenceTransformer $transformer */
|
/** @var RecurrenceTransformer $transformer */
|
||||||
$transformer = app(RecurrenceTransformer::class);
|
$transformer = app(RecurrenceTransformer::class);
|
||||||
|
@@ -120,7 +120,7 @@ class ListController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEventEnrichment();
|
$enrichment = new PiggyBankEventEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$events = $enrichment->enrich($events);
|
$events = $enrichment->enrich($events);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
@@ -157,7 +157,8 @@ class DebugController extends Controller
|
|||||||
return view('debug', compact('table', 'now', 'logContent'));
|
return view('debug', compact('table', 'now', 'logContent'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function apiTest() {
|
public function apiTest()
|
||||||
|
{
|
||||||
return view('test.api-test');
|
return view('test.api-test');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -121,7 +121,7 @@ class IndexController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$collection = $enrichment->enrich($collection);
|
$collection = $enrichment->enrich($collection);
|
||||||
|
|
||||||
/** @var PiggyBank $piggy */
|
/** @var PiggyBank $piggy */
|
||||||
foreach ($collection as $piggy) {
|
foreach ($collection as $piggy) {
|
||||||
|
@@ -82,7 +82,7 @@ class ShowController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new PiggyBankEnrichment();
|
$enrichment = new PiggyBankEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||||
|
|
||||||
/** @var PiggyBankTransformer $transformer */
|
/** @var PiggyBankTransformer $transformer */
|
||||||
$transformer = app(PiggyBankTransformer::class);
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
@@ -142,9 +142,10 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectMetaData(): void
|
private function collectMetaData(): void
|
||||||
{
|
{
|
||||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||||
->whereIn('account_id', $this->ids)
|
->whereIn('account_id', $this->ids)
|
||||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray();
|
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
|
||||||
|
;
|
||||||
|
|
||||||
/** @var array $entry */
|
/** @var array $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
@@ -170,9 +171,10 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
private function collectNotes(): void
|
private function collectNotes(): void
|
||||||
{
|
{
|
||||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||||
->whereNotNull('notes.text')
|
->whereNotNull('notes.text')
|
||||||
->where('notes.text', '!=', '')
|
->where('notes.text', '!=', '')
|
||||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||||
|
;
|
||||||
foreach ($notes as $note) {
|
foreach ($notes as $note) {
|
||||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||||
}
|
}
|
||||||
@@ -182,14 +184,15 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
private function collectLocations(): void
|
private function collectLocations(): void
|
||||||
{
|
{
|
||||||
$locations = Location::query()->whereIn('locatable_id', $this->ids)
|
$locations = Location::query()->whereIn('locatable_id', $this->ids)
|
||||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
|
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||||
|
;
|
||||||
foreach ($locations as $location) {
|
foreach ($locations as $location) {
|
||||||
$this->locations[(int)$location['locatable_id']]
|
$this->locations[(int)$location['locatable_id']]
|
||||||
= [
|
= [
|
||||||
'latitude' => (float)$location['latitude'],
|
'latitude' => (float)$location['latitude'],
|
||||||
'longitude' => (float)$location['longitude'],
|
'longitude' => (float)$location['longitude'],
|
||||||
'zoom_level' => (int)$location['zoom_level'],
|
'zoom_level' => (int)$location['zoom_level'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||||
}
|
}
|
||||||
@@ -204,19 +207,20 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
->setUserGroup($this->userGroup)
|
->setUserGroup($this->userGroup)
|
||||||
->setAccounts($this->collection)
|
->setAccounts($this->collection)
|
||||||
->withAccountInformation()
|
->withAccountInformation()
|
||||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]);
|
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value])
|
||||||
$journals = $collector->getExtractedJournals();
|
;
|
||||||
|
$journals = $collector->getExtractedJournals();
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$this->openingBalances[(int)$journal['source_account_id']]
|
$this->openingBalances[(int)$journal['source_account_id']]
|
||||||
= [
|
= [
|
||||||
'amount' => Steam::negative($journal['amount']),
|
'amount' => Steam::negative($journal['amount']),
|
||||||
'date' => $journal['date'],
|
'date' => $journal['date'],
|
||||||
];
|
];
|
||||||
$this->openingBalances[(int)$journal['destination_account_id']]
|
$this->openingBalances[(int)$journal['destination_account_id']]
|
||||||
= [
|
= [
|
||||||
'amount' => Steam::positive($journal['amount']),
|
'amount' => Steam::positive($journal['amount']),
|
||||||
'date' => $journal['date'],
|
'date' => $journal['date'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,28 +276,28 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
// add balances
|
// add balances
|
||||||
// get currencies:
|
// get currencies:
|
||||||
$currency = $this->primaryCurrency; // assume primary currency
|
$currency = $this->primaryCurrency; // assume primary currency
|
||||||
if (null !== $meta['currency']) {
|
if (null !== $meta['currency']) {
|
||||||
$currency = $meta['currency'];
|
$currency = $meta['currency'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the current balance:
|
// get the current balance:
|
||||||
$date = $this->getDate();
|
$date = $this->getDate();
|
||||||
//$finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
// $finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$finalBalance = $this->balances[$id];
|
$finalBalance = $this->balances[$id];
|
||||||
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
|
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
|
||||||
|
|
||||||
// collect current balances:
|
// collect current balances:
|
||||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||||
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
|
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
|
||||||
$debtAmount = $meta['current_debt'] ?? null;
|
$debtAmount = $meta['current_debt'] ?? null;
|
||||||
|
|
||||||
// set some pc_ default values to NULL:
|
// set some pc_ default values to NULL:
|
||||||
$pcCurrentBalance = null;
|
$pcCurrentBalance = null;
|
||||||
$pcOpeningBalance = null;
|
$pcOpeningBalance = null;
|
||||||
$pcVirtualBalance = null;
|
$pcVirtualBalance = null;
|
||||||
$pcDebtAmount = null;
|
$pcDebtAmount = null;
|
||||||
|
|
||||||
// convert to primary currency if needed:
|
// convert to primary currency if needed:
|
||||||
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
|
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
|
||||||
@@ -316,7 +320,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
$openingBalance = null;
|
$openingBalance = null;
|
||||||
$pcOpeningBalance = null;
|
$pcOpeningBalance = null;
|
||||||
}
|
}
|
||||||
$meta['balances'] = [
|
$meta['balances'] = [
|
||||||
'current_balance' => $currentBalance,
|
'current_balance' => $currentBalance,
|
||||||
'pc_current_balance' => $pcCurrentBalance,
|
'pc_current_balance' => $pcCurrentBalance,
|
||||||
'opening_balance' => $openingBalance,
|
'opening_balance' => $openingBalance,
|
||||||
@@ -327,7 +331,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
'pc_debt_amount' => $pcDebtAmount,
|
'pc_debt_amount' => $pcDebtAmount,
|
||||||
];
|
];
|
||||||
// end add balances
|
// end add balances
|
||||||
$item->meta = $meta;
|
$item->meta = $meta;
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
@@ -57,8 +57,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
|||||||
private readonly BudgetRepositoryInterface $repository;
|
private readonly BudgetRepositoryInterface $repository;
|
||||||
|
|
||||||
|
|
||||||
private ?Carbon $start = null;
|
private ?Carbon $start = null;
|
||||||
private ?Carbon $end = null;
|
private ?Carbon $end = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -52,7 +54,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
return $this->collection;
|
return $this->collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrichSingle(Model|array $model): array|Model
|
public function enrichSingle(array|Model $model): array|Model
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$collection = new Collection([$model]);
|
$collection = new Collection([$model]);
|
||||||
@@ -80,7 +82,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
$this->ids[] = $id;
|
$this->ids[] = $id;
|
||||||
$this->currencyIds[$id] = (int)$piggy->transaction_currency_id;
|
$this->currencyIds[$id] = (int)$piggy->transaction_currency_id;
|
||||||
}
|
}
|
||||||
$this->ids = array_unique($this->ids);
|
$this->ids = array_unique($this->ids);
|
||||||
|
|
||||||
// collect currencies.
|
// collect currencies.
|
||||||
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
|
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
|
||||||
@@ -89,10 +91,10 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// collect accounts
|
// collect accounts
|
||||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get(['piggy_bank_id', 'account_id', 'current_amount', 'native_current_amount']);
|
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get(['piggy_bank_id', 'account_id', 'current_amount', 'native_current_amount']);
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$id = (int)$item->piggy_bank_id;
|
$id = (int)$item->piggy_bank_id;
|
||||||
$accountId = (int)$item->account_id;
|
$accountId = (int)$item->account_id;
|
||||||
$this->amounts[$id] ??= [];
|
$this->amounts[$id] ??= [];
|
||||||
if (!array_key_exists($id, $this->accountIds)) {
|
if (!array_key_exists($id, $this->accountIds)) {
|
||||||
$this->accountIds[$id] = (int)$item->account_id;
|
$this->accountIds[$id] = (int)$item->account_id;
|
||||||
@@ -108,11 +110,12 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get account currency preference for ALL.
|
// get account currency preference for ALL.
|
||||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||||
|
|
||||||
/** @var AccountMeta $item */
|
/** @var AccountMeta $item */
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$accountId = (int)$item->account_id;
|
$accountId = (int)$item->account_id;
|
||||||
$currencyId = (int)$item->data;
|
$currencyId = (int)$item->data;
|
||||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||||
}
|
}
|
||||||
@@ -120,7 +123,8 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get account info.
|
// get account info.
|
||||||
$set = Account::whereIn('id', array_values($this->accountIds))->get();
|
$set = Account::whereIn('id', array_values($this->accountIds))->get();
|
||||||
|
|
||||||
/** @var Account $item */
|
/** @var Account $item */
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$id = (int)$item->id;
|
$id = (int)$item->id;
|
||||||
@@ -134,14 +138,14 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
private function appendCollectedData(): void
|
private function appendCollectedData(): void
|
||||||
{
|
{
|
||||||
$this->collection = $this->collection->map(function (PiggyBank $item) {
|
$this->collection = $this->collection->map(function (PiggyBank $item) {
|
||||||
$id = (int)$item->id;
|
$id = (int)$item->id;
|
||||||
$currencyId = (int)$item->transaction_currency_id;
|
$currencyId = (int)$item->transaction_currency_id;
|
||||||
$currency = $this->currencies[$currencyId] ?? $this->primaryCurrency;
|
$currency = $this->currencies[$currencyId] ?? $this->primaryCurrency;
|
||||||
$targetAmount = null;
|
$targetAmount = null;
|
||||||
if (0 !== bccomp($item->target_amount, '0')) {
|
if (0 !== bccomp($item->target_amount, '0')) {
|
||||||
$targetAmount = $item->target_amount;
|
$targetAmount = $item->target_amount;
|
||||||
}
|
}
|
||||||
$meta = [
|
$meta = [
|
||||||
'notes' => $this->notes[$id] ?? null,
|
'notes' => $this->notes[$id] ?? null,
|
||||||
'currency' => $this->currencies[$currencyId] ?? null,
|
'currency' => $this->currencies[$currencyId] ?? null,
|
||||||
// 'auto_budget' => $this->autoBudgets[$id] ?? null,
|
// 'auto_budget' => $this->autoBudgets[$id] ?? null,
|
||||||
@@ -170,17 +174,17 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
// add current amount(s).
|
// add current amount(s).
|
||||||
foreach ($this->amounts[$id] as $accountId => $row) {
|
foreach ($this->amounts[$id] as $accountId => $row) {
|
||||||
$meta['accounts'][] = [
|
$meta['accounts'][] = [
|
||||||
'account_id' => (string)$accountId,
|
'account_id' => (string)$accountId,
|
||||||
'name' => $this->accounts[$accountId]['name'] ?? '',
|
'name' => $this->accounts[$accountId]['name'] ?? '',
|
||||||
'current_amount' => Steam::bcround($row['current_amount'], $currency->decimal_places),
|
'current_amount' => Steam::bcround($row['current_amount'], $currency->decimal_places),
|
||||||
'pc_current_amount' => Steam::bcround($row['pc_current_amount'], $this->primaryCurrency->decimal_places),
|
'pc_current_amount' => Steam::bcround($row['pc_current_amount'], $this->primaryCurrency->decimal_places),
|
||||||
];
|
];
|
||||||
$meta['current_amount'] = bcadd($meta['current_amount'], $row['current_amount']);
|
$meta['current_amount'] = bcadd($meta['current_amount'], $row['current_amount']);
|
||||||
// only add pc_current_amount when the pc_current_amount is set
|
// only add pc_current_amount when the pc_current_amount is set
|
||||||
$meta['pc_current_amount'] = null === $row['pc_current_amount'] ? null : bcadd($meta['pc_current_amount'], $row['pc_current_amount']);
|
$meta['pc_current_amount'] = null === $row['pc_current_amount'] ? null : bcadd($meta['pc_current_amount'], $row['pc_current_amount']);
|
||||||
}
|
}
|
||||||
$meta['current_amount'] = Steam::bcround($meta['current_amount'], $currency->decimal_places);
|
$meta['current_amount'] = Steam::bcround($meta['current_amount'], $currency->decimal_places);
|
||||||
// only round this number when pc_current_amount is set.
|
// only round this number when pc_current_amount is set.
|
||||||
$meta['pc_current_amount'] = null === $meta['pc_current_amount'] ? null : Steam::bcround($meta['pc_current_amount'], $this->primaryCurrency->decimal_places);
|
$meta['pc_current_amount'] = null === $meta['pc_current_amount'] ? null : Steam::bcround($meta['pc_current_amount'], $this->primaryCurrency->decimal_places);
|
||||||
|
|
||||||
@@ -194,7 +198,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
$meta['save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['target_amount'], $meta['current_amount']), $currency->decimal_places);
|
$meta['save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['target_amount'], $meta['current_amount']), $currency->decimal_places);
|
||||||
$meta['pc_save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['pc_target_amount'], $meta['pc_current_amount']), $currency->decimal_places);
|
$meta['pc_save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['pc_target_amount'], $meta['pc_current_amount']), $currency->decimal_places);
|
||||||
|
|
||||||
$item->meta = $meta;
|
$item->meta = $meta;
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
@@ -203,9 +207,10 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
private function collectNotes(): void
|
private function collectNotes(): void
|
||||||
{
|
{
|
||||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||||
->whereNotNull('notes.text')
|
->whereNotNull('notes.text')
|
||||||
->where('notes.text', '!=', '')
|
->where('notes.text', '!=', '')
|
||||||
->where('noteable_type', PiggyBank::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
->where('noteable_type', PiggyBank::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||||
|
;
|
||||||
foreach ($notes as $note) {
|
foreach ($notes as $note) {
|
||||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||||
}
|
}
|
||||||
@@ -214,12 +219,13 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectObjectGroups(): void
|
private function collectObjectGroups(): void
|
||||||
{
|
{
|
||||||
$set = DB::table('object_groupables')
|
$set = DB::table('object_groupables')
|
||||||
->whereIn('object_groupable_id', $this->ids)
|
->whereIn('object_groupable_id', $this->ids)
|
||||||
->where('object_groupable_type', PiggyBank::class)
|
->where('object_groupable_type', PiggyBank::class)
|
||||||
->get(['object_groupable_id', 'object_group_id']);
|
->get(['object_groupable_id', 'object_group_id'])
|
||||||
|
;
|
||||||
|
|
||||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||||
|
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||||
@@ -233,9 +239,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function collectCurrentAmounts(): void
|
private function collectCurrentAmounts(): void {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the suggested amount the user should save per month, or "".
|
* Returns the suggested amount the user should save per month, or "".
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||||
|
|
||||||
use FireflyIII\Models\AccountMeta;
|
use FireflyIII\Models\AccountMeta;
|
||||||
@@ -16,7 +18,6 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class PiggyBankEventEnrichment implements EnrichmentInterface
|
class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
private User $user;
|
private User $user;
|
||||||
private UserGroup $userGroup;
|
private UserGroup $userGroup;
|
||||||
private Collection $collection;
|
private Collection $collection;
|
||||||
@@ -27,13 +28,13 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
|||||||
private array $piggybankIds = [];
|
private array $piggybankIds = [];
|
||||||
private array $accountCurrencies = [];
|
private array $accountCurrencies = [];
|
||||||
private array $currencies = [];
|
private array $currencies = [];
|
||||||
//private bool $convertToPrimary = false;
|
// private bool $convertToPrimary = false;
|
||||||
//private TransactionCurrency $primaryCurrency;
|
// private TransactionCurrency $primaryCurrency;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
//$this->convertToPrimary = Amount::convertToPrimary();
|
// $this->convertToPrimary = Amount::convertToPrimary();
|
||||||
//$this->primaryCurrency = Amount::getPrimaryCurrency();
|
// $this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrich(Collection $collection): Collection
|
public function enrich(Collection $collection): Collection
|
||||||
@@ -45,7 +46,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
|||||||
return $this->collection;
|
return $this->collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrichSingle(Model|array $model): array|Model
|
public function enrichSingle(array|Model $model): array|Model
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$collection = new Collection([$model]);
|
$collection = new Collection([$model]);
|
||||||
@@ -75,14 +76,15 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
$this->ids = array_unique($this->ids);
|
$this->ids = array_unique($this->ids);
|
||||||
// collect groups with journal info.
|
// collect groups with journal info.
|
||||||
$set = TransactionJournal::whereIn('id', $this->journalIds)->get(['id', 'transaction_group_id']);
|
$set = TransactionJournal::whereIn('id', $this->journalIds)->get(['id', 'transaction_group_id']);
|
||||||
|
|
||||||
/** @var TransactionJournal $item */
|
/** @var TransactionJournal $item */
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$this->groupIds[(int)$item->id] = (int)$item->transaction_group_id;
|
$this->groupIds[(int)$item->id] = (int)$item->transaction_group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect account info.
|
// collect account info.
|
||||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->piggybankIds)->get(['piggy_bank_id', 'account_id']);
|
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->piggybankIds)->get(['piggy_bank_id', 'account_id']);
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$id = (int)$item->piggy_bank_id;
|
$id = (int)$item->piggy_bank_id;
|
||||||
if (!array_key_exists($id, $this->accountIds)) {
|
if (!array_key_exists($id, $this->accountIds)) {
|
||||||
@@ -92,11 +94,12 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
// get account currency preference for ALL.
|
// get account currency preference for ALL.
|
||||||
// TODO This method does a find in a loop.
|
// TODO This method does a find in a loop.
|
||||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||||
|
|
||||||
/** @var AccountMeta $item */
|
/** @var AccountMeta $item */
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$accountId = (int)$item->account_id;
|
$accountId = (int)$item->account_id;
|
||||||
$currencyId = (int)$item->data;
|
$currencyId = (int)$item->data;
|
||||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||||
}
|
}
|
||||||
@@ -107,10 +110,10 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
|||||||
private function appendCollectedData(): void
|
private function appendCollectedData(): void
|
||||||
{
|
{
|
||||||
$this->collection = $this->collection->map(function (PiggyBankEvent $item) {
|
$this->collection = $this->collection->map(function (PiggyBankEvent $item) {
|
||||||
$id = (int)$item->id;
|
$id = (int)$item->id;
|
||||||
$piggyId = (int)$item->piggy_bank_id;
|
$piggyId = (int)$item->piggy_bank_id;
|
||||||
$journalId = (int)$item->transaction_journal_id;
|
$journalId = (int)$item->transaction_journal_id;
|
||||||
$currency = null;
|
$currency = null;
|
||||||
if (array_key_exists($piggyId, $this->accountIds)) {
|
if (array_key_exists($piggyId, $this->accountIds)) {
|
||||||
$accountId = $this->accountIds[$piggyId];
|
$accountId = $this->accountIds[$piggyId];
|
||||||
if (array_key_exists($accountId, $this->accountCurrencies)) {
|
if (array_key_exists($accountId, $this->accountCurrencies)) {
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -75,7 +77,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
return $this->collection;
|
return $this->collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrichSingle(Model|array $model): array|Model
|
public function enrichSingle(array|Model $model): array|Model
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$collection = new Collection([$model]);
|
$collection = new Collection([$model]);
|
||||||
@@ -105,7 +107,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
$this->ids[] = $id;
|
$this->ids[] = $id;
|
||||||
$this->transactionTypeIds[$id] = $typeId;
|
$this->transactionTypeIds[$id] = $typeId;
|
||||||
}
|
}
|
||||||
$this->ids = array_unique($this->ids);
|
$this->ids = array_unique($this->ids);
|
||||||
|
|
||||||
// collect transaction types.
|
// collect transaction types.
|
||||||
$transactionTypes = TransactionType::whereIn('id', array_unique($this->transactionTypeIds))->get();
|
$transactionTypes = TransactionType::whereIn('id', array_unique($this->transactionTypeIds))->get();
|
||||||
@@ -120,20 +122,22 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
Log::debug('Start of enrichment: collectRepetitions()');
|
Log::debug('Start of enrichment: collectRepetitions()');
|
||||||
$repository = app(RecurringRepositoryInterface::class);
|
$repository = app(RecurringRepositoryInterface::class);
|
||||||
$repository->setUserGroup($this->userGroup);
|
$repository->setUserGroup($this->userGroup);
|
||||||
$set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get();
|
$set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get();
|
||||||
|
|
||||||
/** @var RecurrenceRepetition $repetition */
|
/** @var RecurrenceRepetition $repetition */
|
||||||
foreach ($set as $repetition) {
|
foreach ($set as $repetition) {
|
||||||
$recurrence = $this->collection->filter(function (Recurrence $item) use ($repetition) {
|
$recurrence = $this->collection->filter(function (Recurrence $item) use ($repetition) {
|
||||||
return (int)$item->id === (int)$repetition->recurrence_id;
|
return (int)$item->id === (int)$repetition->recurrence_id;
|
||||||
})->first();
|
})->first();
|
||||||
$fromDate = $recurrence->latest_date ?? $recurrence->first_date;
|
$fromDate = $recurrence->latest_date ?? $recurrence->first_date;
|
||||||
$id = (int)$repetition->recurrence_id;
|
$id = (int)$repetition->recurrence_id;
|
||||||
$repId = (int)$repetition->id;
|
$repId = (int)$repetition->id;
|
||||||
$this->repetitions[$id] ??= [];
|
$this->repetitions[$id] ??= [];
|
||||||
|
|
||||||
// get the (future) occurrences for this specific type of repetition:
|
// get the (future) occurrences for this specific type of repetition:
|
||||||
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
||||||
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
|
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
|
||||||
|
|
||||||
/** @var Carbon $carbon */
|
/** @var Carbon $carbon */
|
||||||
foreach ($set as $carbon) {
|
foreach ($set as $carbon) {
|
||||||
$occurrences[] = $carbon->toAtomString();
|
$occurrences[] = $carbon->toAtomString();
|
||||||
@@ -157,16 +161,17 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
private function collectTransactions(): void
|
private function collectTransactions(): void
|
||||||
{
|
{
|
||||||
$set = RecurrenceTransaction::whereIn('recurrence_id', $this->ids)->get();
|
$set = RecurrenceTransaction::whereIn('recurrence_id', $this->ids)->get();
|
||||||
|
|
||||||
/** @var RecurrenceTransaction $transaction */
|
/** @var RecurrenceTransaction $transaction */
|
||||||
foreach ($set as $transaction) {
|
foreach ($set as $transaction) {
|
||||||
$id = (int)$transaction->recurrence_id;
|
$id = (int)$transaction->recurrence_id;
|
||||||
$transactionId = (int)$transaction->id;
|
$transactionId = (int)$transaction->id;
|
||||||
$this->recurrenceIds[$transactionId] = $id;
|
$this->recurrenceIds[$transactionId] = $id;
|
||||||
$this->transactions[$id] ??= [];
|
$this->transactions[$id] ??= [];
|
||||||
$amount = $transaction->amount;
|
$amount = $transaction->amount;
|
||||||
$foreignAmount = $transaction->foreign_amount;
|
$foreignAmount = $transaction->foreign_amount;
|
||||||
|
|
||||||
$this->transactions[$id][$transactionId] = [
|
$this->transactions[$id][$transactionId] = [
|
||||||
'id' => (string)$transactionId,
|
'id' => (string)$transactionId,
|
||||||
'recurrence_id' => $id,
|
'recurrence_id' => $id,
|
||||||
'transaction_currency_id' => (int)$transaction->transaction_currency_id,
|
'transaction_currency_id' => (int)$transaction->transaction_currency_id,
|
||||||
@@ -203,8 +208,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
private function appendCollectedData(): void
|
private function appendCollectedData(): void
|
||||||
{
|
{
|
||||||
$this->collection = $this->collection->map(function (Recurrence $item) {
|
$this->collection = $this->collection->map(function (Recurrence $item) {
|
||||||
$id = (int)$item->id;
|
$id = (int)$item->id;
|
||||||
$meta = [
|
$meta = [
|
||||||
'notes' => $this->notes[$id] ?? null,
|
'notes' => $this->notes[$id] ?? null,
|
||||||
'repetitions' => array_values($this->repetitions[$id] ?? []),
|
'repetitions' => array_values($this->repetitions[$id] ?? []),
|
||||||
'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])),
|
'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])),
|
||||||
@@ -241,7 +246,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language);
|
return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language);
|
||||||
}
|
}
|
||||||
if ('ndom' === $repetition->repetition_type) {
|
if ('ndom' === $repetition->repetition_type) {
|
||||||
$parts = explode(',', $repetition->repetition_moment);
|
$parts = explode(',', $repetition->repetition_moment);
|
||||||
// first part is number of week, second is weekday.
|
// first part is number of week, second is weekday.
|
||||||
$dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language);
|
$dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language);
|
||||||
if ($repetition->repetition_skip > 0) {
|
if ($repetition->repetition_skip > 0) {
|
||||||
@@ -257,8 +262,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
$repDate = clone $today;
|
$repDate = clone $today;
|
||||||
}
|
}
|
||||||
// $diffInYears = (int)$today->diffInYears($repDate, true);
|
// $diffInYears = (int)$today->diffInYears($repDate, true);
|
||||||
//$repDate->addYears($diffInYears); // technically not necessary.
|
// $repDate->addYears($diffInYears); // technically not necessary.
|
||||||
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));
|
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));
|
||||||
|
|
||||||
return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language);
|
return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language);
|
||||||
}
|
}
|
||||||
@@ -269,8 +274,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
private function getLanguage(): void
|
private function getLanguage(): void
|
||||||
{
|
{
|
||||||
/** @var Preference $preference */
|
/** @var Preference $preference */
|
||||||
$preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US'));
|
$preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US'));
|
||||||
$language = $preference->data;
|
$language = $preference->data;
|
||||||
if (is_array($language)) {
|
if (is_array($language)) {
|
||||||
$language = 'en_US';
|
$language = 'en_US';
|
||||||
}
|
}
|
||||||
@@ -293,9 +298,9 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
$return = [];
|
$return = [];
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
foreach ($transactions as $transaction) {
|
foreach ($transactions as $transaction) {
|
||||||
$currencyId = $transaction['transaction_currency_id'];
|
$currencyId = $transaction['transaction_currency_id'];
|
||||||
$pcAmount = null;
|
$pcAmount = null;
|
||||||
$pcForeignAmount = null;
|
$pcForeignAmount = null;
|
||||||
// set the same amount in the primary currency, if both are the same anyway.
|
// set the same amount in the primary currency, if both are the same anyway.
|
||||||
if (true === $this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) {
|
if (true === $this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) {
|
||||||
$pcAmount = $transaction['amount'];
|
$pcAmount = $transaction['amount'];
|
||||||
@@ -311,26 +316,26 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction['pc_amount'] = $pcAmount;
|
$transaction['pc_amount'] = $pcAmount;
|
||||||
$transaction['pc_foreign_amount'] = $pcForeignAmount;
|
$transaction['pc_foreign_amount'] = $pcForeignAmount;
|
||||||
|
|
||||||
$sourceId = $transaction['source_id'];
|
$sourceId = $transaction['source_id'];
|
||||||
$transaction['source_name'] = $this->accounts[$sourceId]->name;
|
$transaction['source_name'] = $this->accounts[$sourceId]->name;
|
||||||
$transaction['source_iban'] = $this->accounts[$sourceId]->iban;
|
$transaction['source_iban'] = $this->accounts[$sourceId]->iban;
|
||||||
$transaction['source_type'] = $this->accounts[$sourceId]->accountType->type;
|
$transaction['source_type'] = $this->accounts[$sourceId]->accountType->type;
|
||||||
$transaction['source_id'] = (string)$transaction['source_id'];
|
$transaction['source_id'] = (string)$transaction['source_id'];
|
||||||
|
|
||||||
$destId = $transaction['destination_id'];
|
$destId = $transaction['destination_id'];
|
||||||
$transaction['destination_name'] = $this->accounts[$destId]->name;
|
$transaction['destination_name'] = $this->accounts[$destId]->name;
|
||||||
$transaction['destination_iban'] = $this->accounts[$destId]->iban;
|
$transaction['destination_iban'] = $this->accounts[$destId]->iban;
|
||||||
$transaction['destination_type'] = $this->accounts[$destId]->accountType->type;
|
$transaction['destination_type'] = $this->accounts[$destId]->accountType->type;
|
||||||
$transaction['destination_id'] = (string)$transaction['destination_id'];
|
$transaction['destination_id'] = (string)$transaction['destination_id'];
|
||||||
|
|
||||||
$transaction['currency_id'] = (string)$currencyId;
|
$transaction['currency_id'] = (string)$currencyId;
|
||||||
$transaction['currency_name'] = $this->currencies[$currencyId]->name;
|
$transaction['currency_name'] = $this->currencies[$currencyId]->name;
|
||||||
$transaction['currency_code'] = $this->currencies[$currencyId]->code;
|
$transaction['currency_code'] = $this->currencies[$currencyId]->code;
|
||||||
$transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
$transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
||||||
$transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
$transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||||
|
|
||||||
$transaction['primary_currency_id'] = (string)$this->primaryCurrency->id;
|
$transaction['primary_currency_id'] = (string)$this->primaryCurrency->id;
|
||||||
$transaction['primary_currency_name'] = $this->primaryCurrency->name;
|
$transaction['primary_currency_name'] = $this->primaryCurrency->name;
|
||||||
@@ -352,8 +357,9 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
$transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
$transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||||
}
|
}
|
||||||
unset($transaction['transaction_currency_id']);
|
unset($transaction['transaction_currency_id']);
|
||||||
$return[] = $transaction;
|
$return[] = $transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,6 +367,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
{
|
{
|
||||||
$all = array_merge(array_unique($this->sourceAccountIds), array_unique($this->destinationAccountIds));
|
$all = array_merge(array_unique($this->sourceAccountIds), array_unique($this->destinationAccountIds));
|
||||||
$accounts = Account::with(['accountType'])->whereIn('id', array_unique($all))->get();
|
$accounts = Account::with(['accountType'])->whereIn('id', array_unique($all))->get();
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$id = (int)$account->id;
|
$id = (int)$account->id;
|
||||||
@@ -370,8 +377,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectTransactionMetaData(): void
|
private function collectTransactionMetaData(): void
|
||||||
{
|
{
|
||||||
$ids = array_keys($this->transactions);
|
$ids = array_keys($this->transactions);
|
||||||
$meta = RecurrenceTransactionMeta::whereIn('rt_id', $ids)->get();
|
$meta = RecurrenceTransactionMeta::whereIn('rt_id', $ids)->get();
|
||||||
// other meta-data to be collected:
|
// other meta-data to be collected:
|
||||||
$billIds = [];
|
$billIds = [];
|
||||||
$piggyBankIds = [];
|
$piggyBankIds = [];
|
||||||
@@ -399,6 +406,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tags':
|
case 'tags':
|
||||||
@@ -417,6 +425,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_id':
|
case 'category_id':
|
||||||
@@ -430,6 +439,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_name':
|
case 'category_name':
|
||||||
@@ -443,6 +453,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'budget_id':
|
case 'budget_id':
|
||||||
@@ -456,6 +467,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,9 +574,10 @@ class RecurringEnrichment implements EnrichmentInterface
|
|||||||
private function collectNotes(): void
|
private function collectNotes(): void
|
||||||
{
|
{
|
||||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||||
->whereNotNull('notes.text')
|
->whereNotNull('notes.text')
|
||||||
->where('notes.text', '!=', '')
|
->where('notes.text', '!=', '')
|
||||||
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||||
|
;
|
||||||
foreach ($notes as $note) {
|
foreach ($notes as $note) {
|
||||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||||
}
|
}
|
||||||
|
@@ -80,7 +80,7 @@ trait CalculateXOccurrencesSince
|
|||||||
while ($total < $count) {
|
while ($total < $count) {
|
||||||
$domCorrected = min($dayOfMonth, $mutator->daysInMonth);
|
$domCorrected = min($dayOfMonth, $mutator->daysInMonth);
|
||||||
$mutator->day = $domCorrected;
|
$mutator->day = $domCorrected;
|
||||||
$mutator->setTime(0,0,0);
|
$mutator->setTime(0, 0, 0);
|
||||||
if (0 === $attempts % $skipMod && $mutator->gte($afterDate)) {
|
if (0 === $attempts % $skipMod && $mutator->gte($afterDate)) {
|
||||||
Log::debug(sprintf('Mutator is now %s and is added to the list.', $mutator->toAtomString()));
|
Log::debug(sprintf('Mutator is now %s and is added to the list.', $mutator->toAtomString()));
|
||||||
$return[] = clone $mutator;
|
$return[] = clone $mutator;
|
||||||
|
@@ -37,6 +37,7 @@ use Illuminate\Support\Facades\DB;
|
|||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use ValueError;
|
use ValueError;
|
||||||
|
|
||||||
use function Safe\parse_url;
|
use function Safe\parse_url;
|
||||||
use function Safe\preg_replace;
|
use function Safe\preg_replace;
|
||||||
|
|
||||||
@@ -64,10 +65,10 @@ class Steam
|
|||||||
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
|
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
|
||||||
if (str_contains($number, '.')) {
|
if (str_contains($number, '.')) {
|
||||||
if ('-' !== $number[0]) {
|
if ('-' !== $number[0]) {
|
||||||
return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
|
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
|
return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $number;
|
return $number;
|
||||||
@@ -203,7 +204,7 @@ class Steam
|
|||||||
Log::debug(sprintf('finalAccountBalanceInRange(#%d, %s, %s)', $account->id, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('finalAccountBalanceInRange(#%d, %s, %s)', $account->id, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
|
|
||||||
// set up cache
|
// set up cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
$cache->addProperty('final-balance-in-range');
|
$cache->addProperty('final-balance-in-range');
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
@@ -213,21 +214,21 @@ class Steam
|
|||||||
return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
$balances = [];
|
$balances = [];
|
||||||
$formatted = $start->format('Y-m-d');
|
$formatted = $start->format('Y-m-d');
|
||||||
/*
|
/*
|
||||||
* To make sure the start balance is correct, we need to get the balance at the exact end of the previous day.
|
* To make sure the start balance is correct, we need to get the balance at the exact end of the previous day.
|
||||||
* Since we just did "startOfDay" we can do subDay()->endOfDay() to get the correct moment.
|
* Since we just did "startOfDay" we can do subDay()->endOfDay() to get the correct moment.
|
||||||
* THAT will be the start balance.
|
* THAT will be the start balance.
|
||||||
*/
|
*/
|
||||||
$request = clone $start;
|
$request = clone $start;
|
||||||
$request->subDay()->endOfDay();
|
$request->subDay()->endOfDay();
|
||||||
Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $request->toIso8601String()));
|
Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $request->toIso8601String()));
|
||||||
$startBalance = $this->finalAccountBalance($account, $request);
|
$startBalance = $this->finalAccountBalance($account, $request);
|
||||||
$primaryCurrency = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
|
$primaryCurrency = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
|
||||||
$accountCurrency = $this->getAccountCurrency($account);
|
$accountCurrency = $this->getAccountCurrency($account);
|
||||||
$hasCurrency = $accountCurrency instanceof TransactionCurrency;
|
$hasCurrency = $accountCurrency instanceof TransactionCurrency;
|
||||||
$currency = $accountCurrency ?? $primaryCurrency;
|
$currency = $accountCurrency ?? $primaryCurrency;
|
||||||
Log::debug(sprintf('Currency is %s', $currency->code));
|
Log::debug(sprintf('Currency is %s', $currency->code));
|
||||||
|
|
||||||
|
|
||||||
@@ -240,7 +241,7 @@ class Steam
|
|||||||
Log::debug(sprintf('Also set start balance in %s', $primaryCurrency->code));
|
Log::debug(sprintf('Also set start balance in %s', $primaryCurrency->code));
|
||||||
$startBalance[$primaryCurrency->code] ??= '0';
|
$startBalance[$primaryCurrency->code] ??= '0';
|
||||||
}
|
}
|
||||||
$currencies = [
|
$currencies = [
|
||||||
$currency->id => $currency,
|
$currency->id => $currency,
|
||||||
$primaryCurrency->id => $primaryCurrency,
|
$primaryCurrency->id => $primaryCurrency,
|
||||||
];
|
];
|
||||||
@@ -250,47 +251,48 @@ class Steam
|
|||||||
|
|
||||||
// sums up the balance changes per day.
|
// sums up the balance changes per day.
|
||||||
Log::debug(sprintf('Date >= %s and <= %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('Date >= %s and <= %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
$set = $account->transactions()
|
$set = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s'))
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
||||||
->groupBy('transaction_journals.date')
|
->groupBy('transaction_journals.date')
|
||||||
->groupBy('transactions.transaction_currency_id')
|
->groupBy('transactions.transaction_currency_id')
|
||||||
->orderBy('transaction_journals.date', 'ASC')
|
->orderBy('transaction_journals.date', 'ASC')
|
||||||
->whereNull('transaction_journals.deleted_at')
|
->whereNull('transaction_journals.deleted_at')
|
||||||
->get(
|
->get(
|
||||||
[ // @phpstan-ignore-line
|
[ // @phpstan-ignore-line
|
||||||
'transaction_journals.date',
|
'transaction_journals.date',
|
||||||
'transactions.transaction_currency_id',
|
'transactions.transaction_currency_id',
|
||||||
DB::raw('SUM(transactions.amount) AS sum_of_day'),
|
DB::raw('SUM(transactions.amount) AS sum_of_day'),
|
||||||
]
|
]
|
||||||
);
|
)
|
||||||
|
;
|
||||||
|
|
||||||
$currentBalance = $startBalance;
|
$currentBalance = $startBalance;
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
|
|
||||||
|
|
||||||
/** @var Transaction $entry */
|
/** @var Transaction $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
// get date object
|
// get date object
|
||||||
$carbon = new Carbon($entry->date, $entry->date_tz);
|
$carbon = new Carbon($entry->date, $entry->date_tz);
|
||||||
$carbonKey = $carbon->format('Y-m-d');
|
$carbonKey = $carbon->format('Y-m-d');
|
||||||
// make sure sum is a string:
|
// make sure sum is a string:
|
||||||
$sumOfDay = (string)($entry->sum_of_day ?? '0');
|
$sumOfDay = (string)($entry->sum_of_day ?? '0');
|
||||||
// #10426 make sure sum is not in scientific notation.
|
// #10426 make sure sum is not in scientific notation.
|
||||||
$sumOfDay = $this->floatalize($sumOfDay);
|
$sumOfDay = $this->floatalize($sumOfDay);
|
||||||
|
|
||||||
// find currency of this entry, does not have to exist.
|
// find currency of this entry, does not have to exist.
|
||||||
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
||||||
|
|
||||||
// make sure this $entry has its own $entryCurrency
|
// make sure this $entry has its own $entryCurrency
|
||||||
/** @var TransactionCurrency $entryCurrency */
|
/** @var TransactionCurrency $entryCurrency */
|
||||||
$entryCurrency = $currencies[$entry->transaction_currency_id];
|
$entryCurrency = $currencies[$entry->transaction_currency_id];
|
||||||
|
|
||||||
Log::debug(sprintf('Processing transaction(s) on moment %s', $carbon->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('Processing transaction(s) on moment %s', $carbon->format('Y-m-d H:i:s')));
|
||||||
|
|
||||||
// add amount to current balance in currency code.
|
// add amount to current balance in currency code.
|
||||||
$currentBalance[$entryCurrency->code] ??= '0';
|
$currentBalance[$entryCurrency->code] ??= '0';
|
||||||
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, (string)$currentBalance[$entryCurrency->code]);
|
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, (string)$currentBalance[$entryCurrency->code]);
|
||||||
|
|
||||||
// if not requested to convert to primary currency, add the amount to "balance", do nothing else.
|
// if not requested to convert to primary currency, add the amount to "balance", do nothing else.
|
||||||
@@ -308,7 +310,7 @@ class Steam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add to final array.
|
// add to final array.
|
||||||
$balances[$carbonKey] = $currentBalance;
|
$balances[$carbonKey] = $currentBalance;
|
||||||
Log::debug(sprintf('Updated entry [%s]', $carbonKey), $currentBalance);
|
Log::debug(sprintf('Updated entry [%s]', $carbonKey), $currentBalance);
|
||||||
}
|
}
|
||||||
$cache->store($balances);
|
$cache->store($balances);
|
||||||
@@ -319,36 +321,37 @@ class Steam
|
|||||||
|
|
||||||
public function finalAccountsBalanceOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
public function finalAccountsBalanceOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
$convertToPrimary = $convertToPrimary ?? Amount::convertToPrimary();
|
$convertToPrimary ??= Amount::convertToPrimary();
|
||||||
$primary = $primary ?? Amount::getPrimaryCurrency();
|
$primary ??= Amount::getPrimaryCurrency();
|
||||||
$currencies = $this->getCurrencies($accounts);
|
$currencies = $this->getCurrencies($accounts);
|
||||||
|
|
||||||
// balance(s) in all currencies for ALL accounts.
|
// balance(s) in all currencies for ALL accounts.
|
||||||
$array = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
|
$array = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->get(['transactions.account_id', 'transaction_currencies.code', 'transactions.amount'])->toArray();
|
->get(['transactions.account_id', 'transaction_currencies.code', 'transactions.amount'])->toArray()
|
||||||
|
;
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
// filter array back to this account:
|
// filter array back to this account:
|
||||||
$filtered = array_filter($array, function ($item) use ($account) {
|
$filtered = array_filter($array, function ($item) use ($account) {
|
||||||
return (int)$item['account_id'] === $account->id;
|
return (int)$item['account_id'] === $account->id;
|
||||||
});
|
});
|
||||||
$currency = $currencies[$account->id];
|
$currency = $currencies[$account->id];
|
||||||
// this array is PER account, so we wait a bit before we change code here.
|
// this array is PER account, so we wait a bit before we change code here.
|
||||||
$return = [
|
$return = [
|
||||||
'pc_balance' => '0',
|
'pc_balance' => '0',
|
||||||
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
||||||
];
|
];
|
||||||
|
|
||||||
// balance(s) in all currencies.
|
// balance(s) in all currencies.
|
||||||
$others = $this->groupAndSumTransactions($filtered, 'code', 'amount');
|
$others = $this->groupAndSumTransactions($filtered, 'code', 'amount');
|
||||||
// Log::debug('All balances are (joined)', $others);
|
// Log::debug('All balances are (joined)', $others);
|
||||||
// if there is no request to convert, take this as "balance" and "pc_balance".
|
// if there is no request to convert, take this as "balance" and "pc_balance".
|
||||||
$return['balance'] = $others[$currency->code] ?? '0';
|
$return['balance'] = $others[$currency->code] ?? '0';
|
||||||
if (!$convertToPrimary) {
|
if (!$convertToPrimary) {
|
||||||
unset($return['pc_balance']);
|
unset($return['pc_balance']);
|
||||||
// Log::debug(sprintf('Set balance to %s, unset pc_balance', $return['balance']));
|
// Log::debug(sprintf('Set balance to %s, unset pc_balance', $return['balance']));
|
||||||
@@ -360,7 +363,7 @@ class Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// either way, the balance is always combined with the virtual balance:
|
// either way, the balance is always combined with the virtual balance:
|
||||||
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
||||||
|
|
||||||
if ($convertToPrimary) {
|
if ($convertToPrimary) {
|
||||||
// the primary currency balance is combined with a converted virtual_balance:
|
// the primary currency balance is combined with a converted virtual_balance:
|
||||||
@@ -378,6 +381,7 @@ class Steam
|
|||||||
$result[$account->id] = $final;
|
$result[$account->id] = $final;
|
||||||
// Log::debug('Final balance is', $final);
|
// Log::debug('Final balance is', $final);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,13 +401,13 @@ class Steam
|
|||||||
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
||||||
{
|
{
|
||||||
|
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
$cache->addProperty($date);
|
$cache->addProperty($date);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||||
|
|
||||||
//return $cache->get();
|
// return $cache->get();
|
||||||
}
|
}
|
||||||
// Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
// Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||||
if (null === $convertToPrimary) {
|
if (null === $convertToPrimary) {
|
||||||
@@ -413,7 +417,7 @@ class Steam
|
|||||||
$primary = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
|
$primary = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
|
||||||
}
|
}
|
||||||
// account balance thing.
|
// account balance thing.
|
||||||
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
||||||
if ($currencyPresent) {
|
if ($currencyPresent) {
|
||||||
$accountCurrency = $account->meta['currency'];
|
$accountCurrency = $account->meta['currency'];
|
||||||
}
|
}
|
||||||
@@ -421,19 +425,20 @@ class Steam
|
|||||||
|
|
||||||
$accountCurrency = $this->getAccountCurrency($account);
|
$accountCurrency = $this->getAccountCurrency($account);
|
||||||
}
|
}
|
||||||
$hasCurrency = null !== $accountCurrency;
|
$hasCurrency = null !== $accountCurrency;
|
||||||
$currency = $hasCurrency ? $accountCurrency : $primary;
|
$currency = $hasCurrency ? $accountCurrency : $primary;
|
||||||
$return = [
|
$return = [
|
||||||
'pc_balance' => '0',
|
'pc_balance' => '0',
|
||||||
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
||||||
];
|
];
|
||||||
// balance(s) in all currencies.
|
// balance(s) in all currencies.
|
||||||
$array = $account->transactions()
|
$array = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
|
->get(['transaction_currencies.code', 'transactions.amount'])->toArray()
|
||||||
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
;
|
||||||
|
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
||||||
// Log::debug('All balances are (joined)', $others);
|
// Log::debug('All balances are (joined)', $others);
|
||||||
// if there is no request to convert, take this as "balance" and "pc_balance".
|
// if there is no request to convert, take this as "balance" and "pc_balance".
|
||||||
$return['balance'] = $others[$currency->code] ?? '0';
|
$return['balance'] = $others[$currency->code] ?? '0';
|
||||||
@@ -448,7 +453,7 @@ class Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// either way, the balance is always combined with the virtual balance:
|
// either way, the balance is always combined with the virtual balance:
|
||||||
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
||||||
|
|
||||||
if ($convertToPrimary) {
|
if ($convertToPrimary) {
|
||||||
// the primary currency balance is combined with a converted virtual_balance:
|
// the primary currency balance is combined with a converted virtual_balance:
|
||||||
@@ -462,7 +467,7 @@ class Steam
|
|||||||
$return['balance'] = bcadd($return['balance'], $virtualBalance);
|
$return['balance'] = bcadd($return['balance'], $virtualBalance);
|
||||||
// Log::debug(sprintf('Virtual balance makes the (primary currency) total %s', $return['balance']));
|
// Log::debug(sprintf('Virtual balance makes the (primary currency) total %s', $return['balance']));
|
||||||
}
|
}
|
||||||
$final = array_merge($return, $others);
|
$final = array_merge($return, $others);
|
||||||
// Log::debug('Final balance is', $final);
|
// Log::debug('Final balance is', $final);
|
||||||
$cache->store($final);
|
$cache->store($final);
|
||||||
|
|
||||||
@@ -471,8 +476,8 @@ class Steam
|
|||||||
|
|
||||||
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
||||||
{
|
{
|
||||||
$type = $account->accountType->type;
|
$type = $account->accountType->type;
|
||||||
$list = config('firefly.valid_currency_account_types');
|
$list = config('firefly.valid_currency_account_types');
|
||||||
|
|
||||||
// return null if not in this list.
|
// return null if not in this list.
|
||||||
if (!in_array($type, $list, true)) {
|
if (!in_array($type, $list, true)) {
|
||||||
@@ -507,9 +512,9 @@ class Steam
|
|||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$current = $converter->convert($currency, $primary, $date, $amount);
|
$current = $converter->convert($currency, $primary, $date, $amount);
|
||||||
Log::debug(sprintf('Convert %s %s to %s %s', $currency->code, $amount, $primary->code, $current));
|
Log::debug(sprintf('Convert %s %s to %s %s', $currency->code, $amount, $primary->code, $current));
|
||||||
$total = bcadd($current, $total);
|
$total = bcadd($current, $total);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $total;
|
return $total;
|
||||||
@@ -551,15 +556,15 @@ class Steam
|
|||||||
{
|
{
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
$set = auth()->user()->transactions()
|
$set = auth()->user()->transactions()
|
||||||
->whereIn('transactions.account_id', $accounts)
|
->whereIn('transactions.account_id', $accounts)
|
||||||
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
||||||
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
||||||
;
|
;
|
||||||
|
|
||||||
/** @var Transaction $entry */
|
/** @var Transaction $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||||
$date->setTimezone(config('app.timezone'));
|
$date->setTimezone(config('app.timezone'));
|
||||||
$list[(int)$entry->account_id] = $date;
|
$list[(int)$entry->account_id] = $date;
|
||||||
}
|
}
|
||||||
@@ -634,9 +639,9 @@ class Steam
|
|||||||
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
|
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
|
||||||
{
|
{
|
||||||
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
|
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
|
||||||
$returnUrl = $safeUrl;
|
$returnUrl = $safeUrl;
|
||||||
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
||||||
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
||||||
|
|
||||||
if (null !== $unknownHost && $unknownHost === $safeHost) {
|
if (null !== $unknownHost && $unknownHost === $safeHost) {
|
||||||
$returnUrl = $unknownUrl;
|
$returnUrl = $unknownUrl;
|
||||||
@@ -673,7 +678,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function floatalize(string $value): string
|
public function floatalize(string $value): string
|
||||||
{
|
{
|
||||||
$value = strtoupper($value);
|
$value = strtoupper($value);
|
||||||
if (!str_contains($value, 'E')) {
|
if (!str_contains($value, 'E')) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
@@ -759,14 +764,15 @@ class Steam
|
|||||||
$accountPreferences = [];
|
$accountPreferences = [];
|
||||||
$primary = Amount::getPrimaryCurrency();
|
$primary = Amount::getPrimaryCurrency();
|
||||||
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
$result = AccountMeta::whereIn('account_id', $ids)->where('name', 'currency_id')->get();
|
$result = AccountMeta::whereIn('account_id', $ids)->where('name', 'currency_id')->get();
|
||||||
|
|
||||||
/** @var AccountMeta $item */
|
/** @var AccountMeta $item */
|
||||||
foreach ($result as $item) {
|
foreach ($result as $item) {
|
||||||
$accountPreferences[(int)$item->account_id] = (int)$item->data;
|
$accountPreferences[(int)$item->account_id] = (int)$item->data;
|
||||||
}
|
}
|
||||||
// collect those currencies.
|
// collect those currencies.
|
||||||
$set = TransactionCurrency::whereIn('id', $accountPreferences)->get();
|
$set = TransactionCurrency::whereIn('id', $accountPreferences)->get();
|
||||||
foreach ($set as $item) {
|
foreach ($set as $item) {
|
||||||
$currencies[$item->id] = $item;
|
$currencies[$item->id] = $item;
|
||||||
}
|
}
|
||||||
@@ -777,7 +783,7 @@ class Steam
|
|||||||
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
||||||
if ($currencyPresent) {
|
if ($currencyPresent) {
|
||||||
$currencyId = $account->meta['currency']->id;
|
$currencyId = $account->meta['currency']->id;
|
||||||
$currencies[$currencyId] ??= $account->meta['currency'];
|
$currencies[$currencyId] ??= $account->meta['currency'];
|
||||||
$accountCurrencies[$accountId] = $account->meta['currency'];
|
$accountCurrencies[$accountId] = $account->meta['currency'];
|
||||||
}
|
}
|
||||||
if (!$currencyPresent && !array_key_exists($account->id, $accountPreferences)) {
|
if (!$currencyPresent && !array_key_exists($account->id, $accountPreferences)) {
|
||||||
@@ -787,6 +793,7 @@ class Steam
|
|||||||
$accountCurrencies[$account->id] = $currencies[$accountPreferences[$account->id]];
|
$accountCurrencies[$account->id] = $currencies[$accountPreferences[$account->id]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $accountCurrencies;
|
return $accountCurrencies;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,7 +73,7 @@ class CategoryTransformer extends AbstractTransformer
|
|||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'rel' => 'self',
|
'rel' => 'self',
|
||||||
'uri' => '/categories/' . $category->id,
|
'uri' => '/categories/'.$category->id,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@@ -65,19 +65,19 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => (string)$event->id,
|
'id' => (string)$event->id,
|
||||||
'created_at' => $event->created_at?->toAtomString(),
|
'created_at' => $event->created_at?->toAtomString(),
|
||||||
'updated_at' => $event->updated_at?->toAtomString(),
|
'updated_at' => $event->updated_at?->toAtomString(),
|
||||||
'amount' => $amount,
|
'amount' => $amount,
|
||||||
'pc_amount' => $primaryAmount,
|
'pc_amount' => $primaryAmount,
|
||||||
|
|
||||||
// currencies according to 6.3.0
|
// currencies according to 6.3.0
|
||||||
'has_currency_setting' => true,
|
'has_currency_setting' => true,
|
||||||
'currency_id' => (string)$currency->id,
|
'currency_id' => (string)$currency->id,
|
||||||
'currency_name' => $currency->name,
|
'currency_name' => $currency->name,
|
||||||
'currency_code' => $currency->code,
|
'currency_code' => $currency->code,
|
||||||
'currency_symbol' => $currency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
|
|
||||||
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
||||||
'primary_currency_name' => $this->primaryCurrency->name,
|
'primary_currency_name' => $this->primaryCurrency->name,
|
||||||
@@ -85,9 +85,9 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
|||||||
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
||||||
'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places,
|
'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places,
|
||||||
|
|
||||||
'transaction_journal_id' => null !== $event->transaction_journal_id ? (string)$event->transaction_journal_id : null,
|
'transaction_journal_id' => null !== $event->transaction_journal_id ? (string)$event->transaction_journal_id : null,
|
||||||
'transaction_group_id' => $event->meta['transaction_group_id'],
|
'transaction_group_id' => $event->meta['transaction_group_id'],
|
||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'rel' => 'self',
|
'rel' => 'self',
|
||||||
'uri' => sprintf('/piggy-banks/%d/events/%s', $event->piggy_bank_id, $event->id),
|
'uri' => sprintf('/piggy-banks/%d/events/%s', $event->piggy_bank_id, $event->id),
|
||||||
|
@@ -25,13 +25,9 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Transformers;
|
namespace FireflyIII\Transformers;
|
||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\ObjectGroup;
|
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
|
||||||
use FireflyIII\Support\Facades\Amount;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PiggyBankTransformer
|
* Class PiggyBankTransformer
|
||||||
@@ -56,36 +52,36 @@ class PiggyBankTransformer extends AbstractTransformer
|
|||||||
public function transform(PiggyBank $piggyBank): array
|
public function transform(PiggyBank $piggyBank): array
|
||||||
{
|
{
|
||||||
// Amounts, depending on 0.0 state of target amount
|
// Amounts, depending on 0.0 state of target amount
|
||||||
$percentage = null;
|
$percentage = null;
|
||||||
if (null !== $piggyBank->meta['target_amount'] && 0 !== bccomp($piggyBank->meta['current_amount'], '0')) { // target amount is not 0.00
|
if (null !== $piggyBank->meta['target_amount'] && 0 !== bccomp($piggyBank->meta['current_amount'], '0')) { // target amount is not 0.00
|
||||||
$percentage = (int)bcmul(bcdiv($piggyBank->meta['current_amount'], $piggyBank->meta['target_amount']), '100');
|
$percentage = (int)bcmul(bcdiv($piggyBank->meta['current_amount'], $piggyBank->meta['target_amount']), '100');
|
||||||
}
|
}
|
||||||
$startDate = $piggyBank->start_date?->toAtomString();
|
$startDate = $piggyBank->start_date?->toAtomString();
|
||||||
$targetDate = $piggyBank->target_date?->toAtomString();
|
$targetDate = $piggyBank->target_date?->toAtomString();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => (string)$piggyBank->id,
|
'id' => (string)$piggyBank->id,
|
||||||
'created_at' => $piggyBank->created_at->toAtomString(),
|
'created_at' => $piggyBank->created_at->toAtomString(),
|
||||||
'updated_at' => $piggyBank->updated_at->toAtomString(),
|
'updated_at' => $piggyBank->updated_at->toAtomString(),
|
||||||
'name' => $piggyBank->name,
|
'name' => $piggyBank->name,
|
||||||
'percentage' => $percentage,
|
'percentage' => $percentage,
|
||||||
'start_date' => $startDate,
|
'start_date' => $startDate,
|
||||||
'target_date' => $targetDate,
|
'target_date' => $targetDate,
|
||||||
'order' => $piggyBank->order,
|
'order' => $piggyBank->order,
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'notes' => $piggyBank->meta['notes'],
|
'notes' => $piggyBank->meta['notes'],
|
||||||
'object_group_id' => $piggyBank->meta['object_group_id'],
|
'object_group_id' => $piggyBank->meta['object_group_id'],
|
||||||
'object_group_order' => $piggyBank->meta['object_group_order'],
|
'object_group_order' => $piggyBank->meta['object_group_order'],
|
||||||
'object_group_title' => $piggyBank->meta['object_group_title'],
|
'object_group_title' => $piggyBank->meta['object_group_title'],
|
||||||
'accounts' => $piggyBank->meta['accounts'],
|
'accounts' => $piggyBank->meta['accounts'],
|
||||||
|
|
||||||
// currency settings, 6.3.0.
|
// currency settings, 6.3.0.
|
||||||
'object_has_currency_setting' => true,
|
'object_has_currency_setting' => true,
|
||||||
'currency_id' => (string)$piggyBank->meta['currency']->id,
|
'currency_id' => (string)$piggyBank->meta['currency']->id,
|
||||||
'currency_name' => $piggyBank->meta['currency']->name,
|
'currency_name' => $piggyBank->meta['currency']->name,
|
||||||
'currency_code' => $piggyBank->meta['currency']->code,
|
'currency_code' => $piggyBank->meta['currency']->code,
|
||||||
'currency_symbol' => $piggyBank->meta['currency']->symbol,
|
'currency_symbol' => $piggyBank->meta['currency']->symbol,
|
||||||
'currency_decimal_places' => $piggyBank->meta['currency']->decimal_places,
|
'currency_decimal_places' => $piggyBank->meta['currency']->decimal_places,
|
||||||
|
|
||||||
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
||||||
'primary_currency_name' => $this->primaryCurrency->name,
|
'primary_currency_name' => $this->primaryCurrency->name,
|
||||||
@@ -94,16 +90,16 @@ class PiggyBankTransformer extends AbstractTransformer
|
|||||||
'primary_currency_decimal_places' => (int)$this->primaryCurrency->decimal_places,
|
'primary_currency_decimal_places' => (int)$this->primaryCurrency->decimal_places,
|
||||||
|
|
||||||
|
|
||||||
'target_amount' => $piggyBank->meta['target_amount'],
|
'target_amount' => $piggyBank->meta['target_amount'],
|
||||||
'pc_target_amount' => $piggyBank->meta['pc_target_amount'],
|
'pc_target_amount' => $piggyBank->meta['pc_target_amount'],
|
||||||
'current_amount' => $piggyBank->meta['current_amount'],
|
'current_amount' => $piggyBank->meta['current_amount'],
|
||||||
'pc_current_amount' => $piggyBank->meta['pc_current_amount'],
|
'pc_current_amount' => $piggyBank->meta['pc_current_amount'],
|
||||||
'left_to_save' => $piggyBank->meta['left_to_save'],
|
'left_to_save' => $piggyBank->meta['left_to_save'],
|
||||||
'pc_left_to_save' => $piggyBank->meta['pc_left_to_save'],
|
'pc_left_to_save' => $piggyBank->meta['pc_left_to_save'],
|
||||||
'save_per_month' => $piggyBank->meta['save_per_month'],
|
'save_per_month' => $piggyBank->meta['save_per_month'],
|
||||||
'pc_save_per_month' => $piggyBank->meta['pc_save_per_month'],
|
'pc_save_per_month' => $piggyBank->meta['pc_save_per_month'],
|
||||||
|
|
||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'rel' => 'self',
|
'rel' => 'self',
|
||||||
'uri' => sprintf('/piggy-banks/%d', $piggyBank->id),
|
'uri' => sprintf('/piggy-banks/%d', $piggyBank->id),
|
||||||
|
@@ -24,34 +24,19 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Transformers;
|
namespace FireflyIII\Transformers;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Factory\CategoryFactory;
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
use FireflyIII\Models\RecurrenceRepetition;
|
|
||||||
use FireflyIII\Models\RecurrenceTransaction;
|
|
||||||
use FireflyIII\Models\RecurrenceTransactionMeta;
|
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
|
||||||
use FireflyIII\Support\Facades\Steam;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use function Safe\json_decode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RecurringTransactionTransformer
|
* Class RecurringTransactionTransformer
|
||||||
*/
|
*/
|
||||||
class RecurrenceTransformer extends AbstractTransformer
|
class RecurrenceTransformer extends AbstractTransformer
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RecurrenceTransformer constructor.
|
* RecurrenceTransformer constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the recurring transaction.
|
* Transform the recurring transaction.
|
||||||
@@ -86,7 +71,7 @@ class RecurrenceTransformer extends AbstractTransformer
|
|||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'rel' => 'self',
|
'rel' => 'self',
|
||||||
'uri' => '/recurring/' . $recurrence->id,
|
'uri' => '/recurring/'.$recurrence->id,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
12
composer.lock
generated
12
composer.lock
generated
@@ -5101,16 +5101,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "predis/predis",
|
"name": "predis/predis",
|
||||||
"version": "v3.1.0",
|
"version": "v3.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/predis/predis.git",
|
"url": "https://github.com/predis/predis.git",
|
||||||
"reference": "202e0c5322b906ec4c761c0cefebad6d0959a699"
|
"reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/predis/predis/zipball/202e0c5322b906ec4c761c0cefebad6d0959a699",
|
"url": "https://api.github.com/repos/predis/predis/zipball/9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8",
|
||||||
"reference": "202e0c5322b906ec4c761c0cefebad6d0959a699",
|
"reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -5152,7 +5152,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/predis/predis/issues",
|
"issues": "https://github.com/predis/predis/issues",
|
||||||
"source": "https://github.com/predis/predis/tree/v3.1.0"
|
"source": "https://github.com/predis/predis/tree/v3.2.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -5160,7 +5160,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-07-22T15:37:44+00:00"
|
"time": "2025-08-06T06:41:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/cache",
|
"name": "psr/cache",
|
||||||
|
@@ -78,8 +78,8 @@ return [
|
|||||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||||
// see cer.php for exchange rates feature flag.
|
// see cer.php for exchange rates feature flag.
|
||||||
],
|
],
|
||||||
'version' => 'develop/2025-08-05',
|
'version' => 'develop/2025-08-06',
|
||||||
'build_time' => 1754394714,
|
'build_time' => 1754505490,
|
||||||
'api_version' => '2.1.0', // field is no longer used.
|
'api_version' => '2.1.0', // field is no longer used.
|
||||||
'db_version' => 26,
|
'db_version' => 26,
|
||||||
|
|
||||||
|
24
package-lock.json
generated
24
package-lock.json
generated
@@ -5700,9 +5700,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.195",
|
"version": "1.5.197",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.195.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.197.tgz",
|
||||||
"integrity": "sha512-URclP0iIaDUzqcAyV1v2PgduJ9N0IdXmWsnPzPfelvBmjmZzEy6xJcjb1cXj+TbYqXgtLrjHEoaSIdTYhw4ezg==",
|
"integrity": "sha512-m1xWB3g7vJ6asIFz+2pBUbq3uGmfmln1M9SSvBe4QIFWYrRHylP73zL/3nMjDmwz8V+1xAXQDfBd6+HPW0WvDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@@ -5757,9 +5757,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.2",
|
"version": "5.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||||
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
|
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10214,9 +10214,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/sass": {
|
"node_modules/sass": {
|
||||||
"version": "1.89.2",
|
"version": "1.90.0",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz",
|
||||||
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
|
"integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -12459,9 +12459,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.8.0",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
|
||||||
"integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
|
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@@ -1,154 +1,154 @@
|
|||||||
{
|
{
|
||||||
"firefly": {
|
"firefly": {
|
||||||
"administrations_page_title": "Financial administrations",
|
"administrations_page_title": "\u0627\u0644\u0625\u062f\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
|
||||||
"administrations_index_menu": "Financial administrations",
|
"administrations_index_menu": "\u0627\u0644\u0625\u062f\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
|
||||||
"expires_at": "Expires at",
|
"expires_at": "\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621",
|
||||||
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its primary currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
|
"temp_administrations_introduction": "\u0633\u064a\u062d\u0635\u0644 Firefly III \u0642\u0631\u064a\u0628\u0627\u064b \u0639\u0644\u0649 \u0625\u0645\u0643\u0627\u0646\u064a\u0629 \u0625\u062f\u0627\u0631\u0629 \u0639\u062f\u0629 \u0625\u062f\u0627\u0631\u0627\u062a \u0645\u0627\u0644\u064a\u0629. \u062d\u0627\u0644\u064a\u0627\u064b \u0644\u062f\u064a\u0643 \u0648\u0627\u062d\u062f\u0629 \u0641\u0642\u0637. \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u064a\u064a\u0646 \u0639\u0646\u0648\u0627\u0646 \u0647\u0630\u0647 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0648\u0639\u0645\u0644\u062a\u0647\u0627 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629. \u0647\u0630\u0627 \u064a\u0633\u062a\u0628\u062f\u0644 \u0627\u0644\u0625\u0639\u062f\u0627\u062f \u0627\u0644\u0633\u0627\u0628\u0642 \u062d\u064a\u062b \u0643\u0646\u062a \u062a\u0639\u064a\u0646 \"\u0627\u0644\u0639\u0645\u0644\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629\". \u0647\u0630\u0627 \u0627\u0644\u0625\u0639\u062f\u0627\u062f \u0623\u0635\u0628\u062d \u0627\u0644\u0622\u0646 \u0645\u0631\u062a\u0628\u0637\u0627\u064b \u0628\u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0627\u0644\u0645\u0627\u0644\u064a\u0629 \u0648\u064a\u0645\u0643\u0646 \u0623\u0646 \u064a\u062e\u062a\u0644\u0641 \u0644\u0643\u0644 \u0625\u062f\u0627\u0631\u0629.",
|
||||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.",
|
"administration_currency_form_help": "\u0642\u062f \u064a\u0633\u062a\u063a\u0631\u0642 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0635\u0641\u062d\u0629 \u0648\u0642\u062a\u0627\u064b \u0637\u0648\u064a\u0644\u0627\u064b \u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u062a\u063a\u064a\u064a\u0631 \u0627\u0644\u0639\u0645\u0644\u0629 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629 \u0644\u0623\u0646 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0642\u062f \u062a\u062d\u062a\u0627\u062c \u0625\u0644\u0649 \u0627\u0644\u062a\u062d\u0648\u064a\u0644 \u0625\u0644\u0649 \u0639\u0645\u0644\u062a\u0643 (\u0627\u0644\u062c\u062f\u064a\u062f\u0629) \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629.",
|
||||||
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
|
"administrations_page_edit_sub_title_js": "\u062a\u0639\u062f\u064a\u0644 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0627\u0644\u0645\u0627\u0644\u064a\u0629 \"{title}\"",
|
||||||
"table": "Table",
|
"table": "\u062c\u062f\u0648\u0644",
|
||||||
"welcome_back": "What's playing?",
|
"welcome_back": "\u0623\u0647\u0644\u0627\u064b \u0648\u0633\u0647\u0644\u0627\u064b!",
|
||||||
"flash_error": "Error!",
|
"flash_error": "\u062e\u0637\u0623!",
|
||||||
"flash_warning": "Warning!",
|
"flash_warning": "\u062a\u062d\u0630\u064a\u0631!",
|
||||||
"flash_success": "Success!",
|
"flash_success": "\u0646\u062c\u062d!",
|
||||||
"close": "Close",
|
"close": "\u0625\u063a\u0644\u0627\u0642",
|
||||||
"select_dest_account": "Please select or type a valid destination account name",
|
"select_dest_account": "\u064a\u0631\u062c\u0649 \u0627\u062e\u062a\u064a\u0627\u0631 \u0623\u0648 \u0643\u062a\u0627\u0628\u0629 \u0627\u0633\u0645 \u062d\u0633\u0627\u0628 \u0648\u062c\u0647\u0629 \u0635\u0627\u0644\u062d",
|
||||||
"select_source_account": "Please select or type a valid source account name",
|
"select_source_account": "\u064a\u0631\u062c\u0649 \u0627\u062e\u062a\u064a\u0627\u0631 \u0623\u0648 \u0643\u062a\u0627\u0628\u0629 \u0627\u0633\u0645 \u062d\u0633\u0627\u0628 \u0645\u0635\u062f\u0631 \u0635\u0627\u0644\u062d",
|
||||||
"split_transaction_title": "Description of the split transaction",
|
"split_transaction_title": "\u0648\u0635\u0641 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u0645\u0646\u0642\u0633\u0645\u0629",
|
||||||
"errors_submission": "There was something wrong with your submission. Please check out the errors below.",
|
"errors_submission": "\u0643\u0627\u0646 \u0647\u0646\u0627\u0643 \u062e\u0637\u0623 \u0645\u0627 \u0641\u064a \u062a\u0642\u062f\u064a\u0645\u0643. \u064a\u0631\u062c\u0649 \u0627\u0644\u062a\u062d\u0642\u0642 \u0645\u0646 \u0627\u0644\u0623\u062e\u0637\u0627\u0621 \u0623\u062f\u0646\u0627\u0647.",
|
||||||
"is_reconciled": "Is reconciled",
|
"is_reconciled": "\u062a\u0645\u062a \u0627\u0644\u062a\u0633\u0648\u064a\u0629",
|
||||||
"split": "Split",
|
"split": "\u062a\u0642\u0633\u064a\u0645",
|
||||||
"single_split": "Split",
|
"single_split": "\u062a\u0642\u0633\u064a\u0645",
|
||||||
"not_enough_currencies": "Not enough currencies",
|
"not_enough_currencies": "\u0639\u062f\u062f \u0627\u0644\u0639\u0645\u0644\u0627\u062a \u063a\u064a\u0631 \u0643\u0627\u0641\u064d",
|
||||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
"not_enough_currencies_enabled": "\u0625\u0630\u0627 \u0643\u0627\u0646 \u0644\u062f\u064a\u0643 \u0639\u0645\u0644\u0629 \u0648\u0627\u062d\u062f\u0629 \u0641\u0642\u0637 \u0645\u0641\u0639\u0644\u0629\u060c \u0641\u0644\u0627 \u062f\u0627\u0639\u064a \u0644\u0625\u0636\u0627\u0641\u0629 \u0623\u0633\u0639\u0627\u0631 \u0635\u0631\u0641.",
|
||||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> has been stored.",
|
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID} (\"{title}\")<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647\u0627.",
|
||||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> has been stored.",
|
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">\u0648\u064a\u0628 \u0647\u0648\u0643 #{ID} (\"{title}\")<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647.",
|
||||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") has been updated.",
|
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">\u0648\u064a\u0628 \u0647\u0648\u0643 #{ID}<\/a> (\"{title}\") \u062a\u0645 \u062a\u062d\u062f\u064a\u062b\u0647.",
|
||||||
"transaction_updated_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> (\"{title}\") has been updated.",
|
"transaction_updated_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID}<\/a> (\"{title}\") \u062a\u0645 \u062a\u062d\u062f\u064a\u062b\u0647\u0627.",
|
||||||
"transaction_new_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> has been stored.",
|
"transaction_new_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID}<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647\u0627.",
|
||||||
"transaction_journal_information": "Transaction information",
|
"transaction_journal_information": "\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"submission_options": "Submission options",
|
"submission_options": "\u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0625\u0631\u0633\u0627\u0644",
|
||||||
"apply_rules_checkbox": "Apply rules",
|
"apply_rules_checkbox": "\u062a\u0637\u0628\u064a\u0642 \u0627\u0644\u0642\u0648\u0627\u0639\u062f",
|
||||||
"fire_webhooks_checkbox": "Fire webhooks",
|
"fire_webhooks_checkbox": "\u062a\u0634\u063a\u064a\u0644 Webhooks",
|
||||||
"no_budget_pointer": "You seem to have no budgets yet. You should create some on the <a href=\"budgets\">budgets<\/a>-page. Budgets can help you keep track of expenses.",
|
"no_budget_pointer": "\u064a\u0628\u062f\u0648 \u0623\u0646\u0647 \u0644\u064a\u0633 \u0644\u062f\u064a\u0643 \u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a \u0628\u0639\u062f. \u064a\u062c\u0628 \u0623\u0646 \u062a\u0646\u0634\u0626 \u0628\u0639\u0636\u0647\u0627 \u0641\u064a <a href=\"budgets\">\u0635\u0641\u062d\u0629 \u0627\u0644\u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a<\/a>. \u0627\u0644\u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a \u064a\u0645\u0643\u0646 \u0623\u0646 \u062a\u0633\u0627\u0639\u062f\u0643 \u0641\u064a \u062a\u062a\u0628\u0639 \u0627\u0644\u0646\u0641\u0642\u0627\u062a.",
|
||||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
"no_bill_pointer": "\u064a\u0628\u062f\u0648 \u0623\u0646\u0647 \u0644\u064a\u0633 \u0644\u062f\u064a\u0643 \u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a \u0628\u0639\u062f. \u064a\u062c\u0628 \u0623\u0646 \u062a\u0646\u0634\u0626 \u0628\u0639\u0636\u0647\u0627 \u0641\u064a <a href=\"subscriptions\">\u0635\u0641\u062d\u0629 \u0627\u0644\u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a<\/a>. \u0627\u0644\u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a \u064a\u0645\u0643\u0646 \u0623\u0646 \u062a\u0633\u0627\u0639\u062f\u0643 \u0641\u064a \u062a\u062a\u0628\u0639 \u0627\u0644\u0646\u0641\u0642\u0627\u062a.",
|
||||||
"source_account": "Source account",
|
"source_account": "\u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631",
|
||||||
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
"hidden_fields_preferences": "\u064a\u0645\u0643\u0646\u0643 \u062a\u0645\u0643\u064a\u0646 \u0627\u0644\u0645\u0632\u064a\u062f \u0645\u0646 \u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0641\u064a <a href=\"preferences\">\u0627\u0644\u062a\u0641\u0636\u064a\u0644\u0627\u062a<\/a> \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0643.",
|
||||||
"destination_account": "Destination account",
|
"destination_account": "\u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629",
|
||||||
"add_another_split": "Add another split",
|
"add_another_split": "\u0625\u0636\u0627\u0641\u0629 \u062a\u0642\u0633\u064a\u0645 \u0622\u062e\u0631",
|
||||||
"submission": "Submission",
|
"submission": "\u0625\u0631\u0633\u0627\u0644",
|
||||||
"stored_journal": "Successfully created new transaction \":description\"",
|
"stored_journal": "\u062a\u0645 \u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u062c\u062f\u064a\u062f\u0629 \":description\"",
|
||||||
"create_another": "After storing, return here to create another one.",
|
"create_another": "\u0628\u0639\u062f \u0627\u0644\u062a\u062e\u0632\u064a\u0646\u060c \u0639\u062f \u0625\u0644\u0649 \u0647\u0646\u0627 \u0644\u0625\u0646\u0634\u0627\u0621 \u0648\u0627\u062d\u062f\u0629 \u0623\u062e\u0631\u0649.",
|
||||||
"reset_after": "Reset form after submission",
|
"reset_after": "\u0625\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0646\u0645\u0648\u0630\u062c \u0628\u0639\u062f \u0627\u0644\u0625\u0631\u0633\u0627\u0644",
|
||||||
"submit": "Submit",
|
"submit": "\u0625\u0631\u0633\u0627\u0644",
|
||||||
"amount": "Amount",
|
"amount": "\u0627\u0644\u0645\u0628\u0644\u063a",
|
||||||
"date": "Date",
|
"date": "\u0627\u0644\u062a\u0627\u0631\u064a\u062e",
|
||||||
"is_reconciled_fields_dropped": "Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.",
|
"is_reconciled_fields_dropped": "\u0644\u0623\u0646 \u0647\u0630\u0647 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u062a\u0645\u062a \u062a\u0633\u0648\u064a\u062a\u0647\u0627\u060c \u0644\u0646 \u062a\u062a\u0645\u0643\u0646 \u0645\u0646 \u062a\u062d\u062f\u064a\u062b \u0627\u0644\u062d\u0633\u0627\u0628\u0627\u062a \u0623\u0648 \u0627\u0644\u0645\u0628\u0627\u0644\u063a \u0625\u0644\u0627 \u0625\u0630\u0627 \u0623\u0632\u0644\u062a \u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||||
"tags": "Tags",
|
"tags": "\u0627\u0644\u0648\u0633\u0648\u0645",
|
||||||
"no_budget": "(no budget)",
|
"no_budget": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u0645\u064a\u0632\u0627\u0646\u064a\u0629)",
|
||||||
"no_bill": "(no subscription)",
|
"no_bill": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u0627\u0634\u062a\u0631\u0627\u0643)",
|
||||||
"category": "Category",
|
"category": "\u0641\u0626\u0629",
|
||||||
"attachments": "Attachments",
|
"attachments": "\u0627\u0644\u0645\u0631\u0641\u0642\u0627\u062a",
|
||||||
"notes": "Notes",
|
"notes": "\u0645\u0644\u0627\u062d\u0638\u0627\u062a",
|
||||||
"external_url": "External URL",
|
"external_url": "\u0631\u0627\u0628\u0637 \u062e\u0627\u0631\u062c\u064a",
|
||||||
"update_transaction": "Update transaction",
|
"update_transaction": "\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"after_update_create_another": "After updating, return here to continue editing.",
|
"after_update_create_another": "\u0628\u0639\u062f \u0627\u0644\u062a\u062d\u062f\u064a\u062b\u060c \u0639\u062f \u0625\u0644\u0649 \u0647\u0646\u0627 \u0644\u0645\u062a\u0627\u0628\u0639\u0629 \u0627\u0644\u062a\u062d\u0631\u064a\u0631.",
|
||||||
"store_as_new": "Store as a new transaction instead of updating.",
|
"store_as_new": "\u062a\u062e\u0632\u064a\u0646 \u0643\u0645\u0639\u0627\u0645\u0644\u0629 \u062c\u062f\u064a\u062f\u0629 \u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0627\u0644\u062a\u062d\u062f\u064a\u062b.",
|
||||||
"split_title_help": "If you create a split transaction, there must be a global description for all splits of the transaction.",
|
"split_title_help": "\u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u0645\u0646\u0642\u0633\u0645\u0629\u060c \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0647\u0646\u0627\u0643 \u0648\u0635\u0641 \u0639\u0627\u0644\u0645\u064a \u0644\u062c\u0645\u064a\u0639 \u0627\u0646\u0642\u0633\u0627\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||||
"none_in_select_list": "(none)",
|
"none_in_select_list": "(\u0644\u0627 \u064a\u0648\u062c\u062f)",
|
||||||
"no_piggy_bank": "(no piggy bank)",
|
"no_piggy_bank": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u062d\u0635\u0627\u0644\u0629)",
|
||||||
"description": "Description",
|
"description": "\u0627\u0644\u0648\u0635\u0641",
|
||||||
"split_transaction_title_help": "If you create a split transaction, there must be a global description for all splits of the transaction.",
|
"split_transaction_title_help": "\u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u0645\u0646\u0642\u0633\u0645\u0629\u060c \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0647\u0646\u0627\u0643 \u0648\u0635\u0641 \u0639\u0627\u0644\u0645\u064a \u0644\u062c\u0645\u064a\u0639 \u0627\u0646\u0642\u0633\u0627\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||||
"destination_account_reconciliation": "You can't edit the destination account of a reconciliation transaction.",
|
"destination_account_reconciliation": "\u0644\u0627 \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u062f\u064a\u0644 \u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629 \u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||||
"source_account_reconciliation": "You can't edit the source account of a reconciliation transaction.",
|
"source_account_reconciliation": "\u0644\u0627 \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u062f\u064a\u0644 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||||
"budget": "Budget",
|
"budget": "\u0645\u064a\u0632\u0627\u0646\u064a\u0629",
|
||||||
"bill": "Subscription",
|
"bill": "\u0627\u0634\u062a\u0631\u0627\u0643",
|
||||||
"you_create_withdrawal": "You're creating a withdrawal.",
|
"you_create_withdrawal": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0633\u062d\u0628.",
|
||||||
"you_create_transfer": "You're creating a transfer.",
|
"you_create_transfer": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u062a\u062d\u0648\u064a\u0644.",
|
||||||
"you_create_deposit": "You're creating a deposit.",
|
"you_create_deposit": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0625\u064a\u062f\u0627\u0639.",
|
||||||
"edit": "Edit",
|
"edit": "\u062a\u0639\u062f\u064a\u0644",
|
||||||
"delete": "Delete",
|
"delete": "\u062d\u0630\u0641",
|
||||||
"name": "Name",
|
"name": "\u0627\u0644\u0627\u0633\u0645",
|
||||||
"profile_whoops": "Whoops!",
|
"profile_whoops": "\u0639\u0630\u0631\u0627\u064b!",
|
||||||
"profile_something_wrong": "Something went wrong!",
|
"profile_something_wrong": "\u062d\u062f\u062b \u062e\u0637\u0623 \u0645\u0627!",
|
||||||
"profile_try_again": "Something went wrong. Please try again.",
|
"profile_try_again": "\u062d\u062f\u062b \u062e\u0637\u0623 \u0645\u0627. \u064a\u0631\u062c\u0649 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062e\u0631\u0649.",
|
||||||
"profile_oauth_clients": "OAuth Clients",
|
"profile_oauth_clients": "\u0639\u0645\u0644\u0627\u0621 OAuth",
|
||||||
"profile_oauth_no_clients": "You have not created any OAuth clients.",
|
"profile_oauth_no_clients": "\u0644\u0645 \u062a\u0642\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0623\u064a \u0639\u0645\u0644\u0627\u0621 OAuth.",
|
||||||
"profile_oauth_clients_header": "Clients",
|
"profile_oauth_clients_header": "\u0627\u0644\u0639\u0645\u0644\u0627\u0621",
|
||||||
"profile_oauth_client_id": "Client ID",
|
"profile_oauth_client_id": "\u0645\u0639\u0631\u0651\u0641 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||||
"profile_oauth_client_name": "Name",
|
"profile_oauth_client_name": "\u0627\u0644\u0627\u0633\u0645",
|
||||||
"profile_oauth_client_secret": "Secret",
|
"profile_oauth_client_secret": "\u0627\u0644\u0633\u0631",
|
||||||
"profile_oauth_create_new_client": "Create New Client",
|
"profile_oauth_create_new_client": "\u0625\u0646\u0634\u0627\u0621 \u0639\u0645\u064a\u0644 \u062c\u062f\u064a\u062f",
|
||||||
"profile_oauth_create_client": "Create Client",
|
"profile_oauth_create_client": "\u0625\u0646\u0634\u0627\u0621 \u0639\u0645\u064a\u0644",
|
||||||
"profile_oauth_edit_client": "Edit Client",
|
"profile_oauth_edit_client": "\u062a\u0639\u062f\u064a\u0644 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||||
"profile_oauth_name_help": "Something your users will recognize and trust.",
|
"profile_oauth_name_help": "\u0634\u064a\u0621 \u0633\u064a\u062a\u0639\u0631\u0641 \u0639\u0644\u064a\u0647 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u0648\u0646 \u0648\u064a\u062b\u0642\u0648\u0646 \u0628\u0647.",
|
||||||
"profile_oauth_redirect_url": "Redirect URL",
|
"profile_oauth_redirect_url": "\u0631\u0627\u0628\u0637 \u0625\u0639\u0627\u062f\u0629 \u0627\u0644\u062a\u0648\u062c\u064a\u0647",
|
||||||
"profile_oauth_clients_external_auth": "If you're using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.",
|
"profile_oauth_clients_external_auth": "\u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0633\u062a\u062e\u062f\u0645 \u0645\u0648\u0641\u0631 \u0645\u0635\u0627\u062f\u0642\u0629 \u062e\u0627\u0631\u062c\u064a \u0645\u062b\u0644 Authelia\u060c \u0641\u0644\u0646 \u062a\u0639\u0645\u0644 \u0639\u0645\u0644\u0627\u0621 OAuth. \u064a\u0645\u0643\u0646\u0643 \u0641\u0642\u0637 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0631\u0645\u0648\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a\u0629.",
|
||||||
"profile_oauth_redirect_url_help": "Your application's authorization callback URL.",
|
"profile_oauth_redirect_url_help": "\u0631\u0627\u0628\u0637 \u0625\u0639\u0627\u062f\u0629 \u0627\u0644\u062a\u0648\u062c\u064a\u0647 \u0644\u062a\u0637\u0628\u064a\u0642\u0643.",
|
||||||
"profile_authorized_apps": "Authorized applications",
|
"profile_authorized_apps": "\u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0645\u0635\u0631\u062d \u0628\u0647\u0627",
|
||||||
"profile_authorized_clients": "Authorized clients",
|
"profile_authorized_clients": "\u0627\u0644\u0639\u0645\u0644\u0627\u0621 \u0627\u0644\u0645\u0635\u0631\u062d \u0644\u0647\u0645",
|
||||||
"profile_scopes": "Scopes",
|
"profile_scopes": "\u0627\u0644\u0646\u0637\u0627\u0642\u0627\u062a",
|
||||||
"profile_revoke": "Revoke",
|
"profile_revoke": "\u0625\u0644\u063a\u0627\u0621",
|
||||||
"profile_personal_access_tokens": "Personal Access Tokens",
|
"profile_personal_access_tokens": "\u0631\u0645\u0648\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a\u0629",
|
||||||
"profile_personal_access_token": "Personal Access Token",
|
"profile_personal_access_token": "\u0631\u0645\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a",
|
||||||
"profile_personal_access_token_explanation": "Here is your new personal access token. This is the only time it will be shown so don't lose it! You may now use this token to make API requests.",
|
"profile_personal_access_token_explanation": "\u0647\u0630\u0627 \u0647\u0648 \u0631\u0645\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a \u0627\u0644\u062c\u062f\u064a\u062f \u0627\u0644\u062e\u0627\u0635 \u0628\u0643. \u0647\u0630\u0647 \u0647\u064a \u0627\u0644\u0645\u0631\u0629 \u0627\u0644\u0648\u062d\u064a\u062f\u0629 \u0627\u0644\u062a\u064a \u0633\u064a\u0638\u0647\u0631 \u0641\u064a\u0647\u0627 \u0641\u0644\u0627 \u062a\u0641\u0642\u062f\u0647! \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0622\u0646 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0631\u0645\u0632 \u0644\u0625\u062c\u0631\u0627\u0621 \u0637\u0644\u0628\u0627\u062a API.",
|
||||||
"profile_no_personal_access_token": "You have not created any personal access tokens.",
|
"profile_no_personal_access_token": "\u0644\u0645 \u062a\u0642\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0623\u064a \u0631\u0645\u0648\u0632 \u0648\u0635\u0648\u0644 \u0634\u062e\u0635\u064a\u0629.",
|
||||||
"profile_create_new_token": "Create new token",
|
"profile_create_new_token": "\u0625\u0646\u0634\u0627\u0621 \u0631\u0645\u0632 \u062c\u062f\u064a\u062f",
|
||||||
"profile_create_token": "Create token",
|
"profile_create_token": "\u0625\u0646\u0634\u0627\u0621 \u0631\u0645\u0632",
|
||||||
"profile_create": "Create",
|
"profile_create": "\u0625\u0646\u0634\u0627\u0621",
|
||||||
"profile_save_changes": "Save changes",
|
"profile_save_changes": "\u062d\u0641\u0638 \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u0627\u062a",
|
||||||
"default_group_title_name": "(ungrouped)",
|
"default_group_title_name": "(\u063a\u064a\u0631 \u0645\u062c\u0645\u0639)",
|
||||||
"piggy_bank": "Piggy bank",
|
"piggy_bank": "\u062d\u0635\u0627\u0644\u0629",
|
||||||
"profile_oauth_client_secret_title": "Client Secret",
|
"profile_oauth_client_secret_title": "\u0633\u0631 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||||
"profile_oauth_client_secret_expl": "Here is your new client secret. This is the only time it will be shown so don't lose it! You may now use this secret to make API requests.",
|
"profile_oauth_client_secret_expl": "\u0647\u0630\u0627 \u0647\u0648 \u0633\u0631 \u0627\u0644\u0639\u0645\u064a\u0644 \u0627\u0644\u062c\u062f\u064a\u062f \u0627\u0644\u062e\u0627\u0635 \u0628\u0643. \u0647\u0630\u0647 \u0647\u064a \u0627\u0644\u0645\u0631\u0629 \u0627\u0644\u0648\u062d\u064a\u062f\u0629 \u0627\u0644\u062a\u064a \u0633\u064a\u0638\u0647\u0631 \u0641\u064a\u0647\u0627 \u0641\u0644\u0627 \u062a\u0641\u0642\u062f\u0647! \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0622\u0646 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0633\u0631 \u0644\u0625\u062c\u0631\u0627\u0621 \u0637\u0644\u0628\u0627\u062a API.",
|
||||||
"profile_oauth_confidential": "Confidential",
|
"profile_oauth_confidential": "\u0633\u0631\u064a",
|
||||||
"profile_oauth_confidential_help": "Require the client to authenticate with a secret. Confidential clients can hold credentials in a secure way without exposing them to unauthorized parties. Public applications, such as primary desktop or JavaScript SPA applications, are unable to hold secrets securely.",
|
"profile_oauth_confidential_help": "\u064a\u062a\u0637\u0644\u0628 \u0645\u0646 \u0627\u0644\u0639\u0645\u064a\u0644 \u0627\u0644\u0645\u0635\u0627\u062f\u0642\u0629 \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0633\u0631. \u064a\u0645\u0643\u0646 \u0644\u0644\u0639\u0645\u0644\u0627\u0621 \u0627\u0644\u0633\u0631\u064a\u064a\u0646 \u0627\u0644\u0627\u062d\u062a\u0641\u0627\u0638 \u0628\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0627\u0639\u062a\u0645\u0627\u062f \u0628\u0637\u0631\u064a\u0642\u0629 \u0622\u0645\u0646\u0629 \u062f\u0648\u0646 \u0643\u0634\u0641\u0647\u0627 \u0644\u0623\u0637\u0631\u0627\u0641 \u063a\u064a\u0631 \u0645\u0635\u0631\u062d \u0644\u0647\u0627. \u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0639\u0627\u0645\u0629 \u0645\u062b\u0644 \u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0633\u0637\u062d \u0627\u0644\u0645\u0643\u062a\u0628 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629 \u0623\u0648 \u062a\u0637\u0628\u064a\u0642\u0627\u062a SPA JavaScript \u063a\u064a\u0631 \u0642\u0627\u062f\u0631\u0629 \u0639\u0644\u0649 \u0627\u0644\u0627\u062d\u062a\u0641\u0627\u0638 \u0628\u0627\u0644\u0623\u0633\u0631\u0627\u0631 \u0628\u0623\u0645\u0627\u0646.",
|
||||||
"multi_account_warning_unknown": "Depending on the type of transaction you create, the source and\/or destination account of subsequent splits may be overruled by whatever is defined in the first split of the transaction.",
|
"multi_account_warning_unknown": "\u0627\u0639\u062a\u0645\u0627\u062f\u0627\u064b \u0639\u0644\u0649 \u0646\u0648\u0639 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u064a \u062a\u0646\u0634\u0626\u0647\u0627\u060c \u0642\u062f \u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0648\/\u0623\u0648 \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||||
"multi_account_warning_withdrawal": "Keep in mind that the source account of subsequent splits will be overruled by whatever is defined in the first split of the withdrawal.",
|
"multi_account_warning_withdrawal": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0633\u062d\u0628.",
|
||||||
"multi_account_warning_deposit": "Keep in mind that the destination account of subsequent splits will be overruled by whatever is defined in the first split of the deposit.",
|
"multi_account_warning_deposit": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0625\u064a\u062f\u0627\u0639.",
|
||||||
"multi_account_warning_transfer": "Keep in mind that the source + destination account of subsequent splits will be overruled by whatever is defined in the first split of the transfer.",
|
"multi_account_warning_transfer": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 + \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647\u0645\u0627 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u062a\u062d\u0648\u064a\u0644.",
|
||||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
"webhook_trigger_STORE_TRANSACTION": "\u0628\u0639\u062f \u0625\u0646\u0634\u0627\u0621 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
"webhook_trigger_UPDATE_TRANSACTION": "\u0628\u0639\u062f \u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
"webhook_trigger_DESTROY_TRANSACTION": "\u0628\u0639\u062f \u062d\u0630\u0641 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
"webhook_response_TRANSACTIONS": "\u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||||
"webhook_response_ACCOUNTS": "Account details",
|
"webhook_response_ACCOUNTS": "\u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u062d\u0633\u0627\u0628",
|
||||||
"webhook_response_none_NONE": "No details",
|
"webhook_response_none_NONE": "\u0644\u0627 \u062a\u0648\u062c\u062f \u062a\u0641\u0627\u0635\u064a\u0644",
|
||||||
"webhook_delivery_JSON": "JSON",
|
"webhook_delivery_JSON": "JSON",
|
||||||
"actions": "Actions",
|
"actions": "\u0627\u0644\u0625\u062c\u0631\u0627\u0621\u0627\u062a",
|
||||||
"meta_data": "Meta data",
|
"meta_data": "\u0628\u064a\u0627\u0646\u0627\u062a \u0648\u0635\u0641\u064a\u0629",
|
||||||
"webhook_messages": "Webhook message",
|
"webhook_messages": "\u0631\u0633\u0627\u0644\u0629 \u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"inactive": "Inactive",
|
"inactive": "\u063a\u064a\u0631 \u0646\u0634\u0637",
|
||||||
"no_webhook_messages": "There are no webhook messages",
|
"no_webhook_messages": "\u0644\u0627 \u062a\u0648\u062c\u062f \u0631\u0633\u0627\u0626\u0644 \u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"inspect": "Inspect",
|
"inspect": "\u062a\u0641\u0642\u062f",
|
||||||
"create_new_webhook": "Create new webhook",
|
"create_new_webhook": "\u0625\u0646\u0634\u0627\u0621 \u0648\u064a\u0628 \u0647\u0648\u0643 \u062c\u062f\u064a\u062f",
|
||||||
"webhooks": "Webhooks",
|
"webhooks": "\u0648\u064a\u0628 \u0647\u0648\u0643\u0633",
|
||||||
"webhook_trigger_form_help": "Indicate on what event the webhook will trigger",
|
"webhook_trigger_form_help": "\u062d\u062f\u062f \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0630\u064a \u0633\u064a\u0634\u063a\u0644 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"webhook_response_form_help": "Indicate what the webhook must submit to the URL.",
|
"webhook_response_form_help": "\u062d\u062f\u062f \u0645\u0627 \u064a\u062c\u0628 \u0623\u0646 \u064a\u0631\u0633\u0644\u0647 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0625\u0644\u0649 \u0627\u0644\u0631\u0627\u0628\u0637.",
|
||||||
"webhook_delivery_form_help": "Which format the webhook must deliver data in.",
|
"webhook_delivery_form_help": "\u062d\u062f\u062f \u0623\u064a \u0635\u064a\u063a\u0629 \u064a\u062c\u0628 \u0623\u0646 \u064a\u0631\u0633\u0644 \u0628\u0647\u0627 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a.",
|
||||||
"webhook_active_form_help": "The webhook must be active or it won't be called.",
|
"webhook_active_form_help": "\u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0646\u0634\u0637\u0627\u064b \u0648\u0625\u0644\u0627 \u0644\u0646 \u064a\u062a\u0645 \u0627\u0633\u062a\u062f\u0639\u0627\u0624\u0647.",
|
||||||
"edit_webhook_js": "Edit webhook \"{title}\"",
|
"edit_webhook_js": "\u062a\u0639\u062f\u064a\u0644 \u0648\u064a\u0628 \u0647\u0648\u0643 \"{title}\"",
|
||||||
"webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.",
|
"webhook_was_triggered": "\u062a\u0645 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0639\u0644\u0649 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u0645\u062d\u062f\u062f\u0629. \u064a\u0631\u062c\u0649 \u0627\u0644\u0627\u0646\u062a\u0638\u0627\u0631 \u062d\u062a\u0649 \u062a\u0638\u0647\u0631 \u0627\u0644\u0646\u062a\u0627\u0626\u062c.",
|
||||||
"view_message": "View message",
|
"view_message": "\u0639\u0631\u0636 \u0627\u0644\u0631\u0633\u0627\u0644\u0629",
|
||||||
"view_attempts": "View failed attempts",
|
"view_attempts": "\u0639\u0631\u0636 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u0627\u0644\u0641\u0627\u0634\u0644\u0629",
|
||||||
"message_content_title": "Webhook message content",
|
"message_content_title": "\u0645\u062d\u062a\u0648\u0649 \u0631\u0633\u0627\u0644\u0629 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"message_content_help": "This is the content of the message that was sent (or tried) using this webhook.",
|
"message_content_help": "\u0647\u0630\u0627 \u0647\u0648 \u0645\u062d\u062a\u0648\u0649 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0627\u0644\u062a\u064a \u062a\u0645 \u0625\u0631\u0633\u0627\u0644\u0647\u0627 (\u0623\u0648 \u0645\u062d\u0627\u0648\u0644\u0629 \u0625\u0631\u0633\u0627\u0644\u0647\u0627) \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643.",
|
||||||
"attempt_content_title": "Webhook attempts",
|
"attempt_content_title": "\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"attempt_content_help": "These are all the unsuccessful attempts of this webhook message to submit to the configured URL. After some time, Firefly III will stop trying.",
|
"attempt_content_help": "\u0647\u0630\u0647 \u0647\u064a \u062c\u0645\u064a\u0639 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u063a\u064a\u0631 \u0627\u0644\u0646\u0627\u062c\u062d\u0629 \u0644\u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0644\u0625\u0631\u0633\u0627\u0644\u0647\u0627 \u0625\u0644\u0649 \u0627\u0644\u0631\u0627\u0628\u0637 \u0627\u0644\u0645\u062d\u062f\u062f. \u0628\u0639\u062f \u0641\u062a\u0631\u0629\u060c \u0633\u064a\u062a\u0648\u0642\u0641 Firefly III \u0639\u0646 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629.",
|
||||||
"no_attempts": "There are no unsuccessful attempts. That's a good thing!",
|
"no_attempts": "\u0644\u0627 \u062a\u0648\u062c\u062f \u0645\u062d\u0627\u0648\u0644\u0627\u062a \u063a\u064a\u0631 \u0646\u0627\u062c\u062d\u0629. \u0647\u0630\u0627 \u0623\u0645\u0631 \u062c\u064a\u062f!",
|
||||||
"webhook_attempt_at": "Attempt at {moment}",
|
"webhook_attempt_at": "\u0645\u062d\u0627\u0648\u0644\u0629 \u0641\u064a {moment}",
|
||||||
"logs": "Logs",
|
"logs": "\u0627\u0644\u0633\u062c\u0644\u0627\u062a",
|
||||||
"response": "Response",
|
"response": "\u0627\u0644\u0627\u0633\u062a\u062c\u0627\u0628\u0629",
|
||||||
"visit_webhook_url": "Visit webhook URL",
|
"visit_webhook_url": "\u0632\u064a\u0627\u0631\u0629 \u0631\u0627\u0628\u0637 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"reset_webhook_secret": "Reset webhook secret",
|
"reset_webhook_secret": "\u0625\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0633\u0631 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||||
"header_exchange_rates": "Exchange rates",
|
"header_exchange_rates": "\u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||||
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
|
"exchange_rates_intro": "\u064a\u062f\u0639\u0645 Firefly III \u062a\u0646\u0632\u064a\u0644 \u0648\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641. \u0627\u0642\u0631\u0623 \u0627\u0644\u0645\u0632\u064a\u062f \u0639\u0646 \u0630\u0644\u0643 \u0641\u064a <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">\u0627\u0644\u0648\u062b\u0627\u0626\u0642<\/a>.",
|
||||||
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
|
"exchange_rates_from_to": "\u0628\u064a\u0646 {from} \u0648{to} (\u0648\u0628\u0627\u0644\u0639\u0643\u0633)",
|
||||||
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
|
"exchange_rates_intro_rates": "\u064a\u0633\u062a\u062e\u062f\u0645 Firefly III \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641 \u0627\u0644\u062a\u0627\u0644\u064a\u0629. \u064a\u062a\u0645 \u062d\u0633\u0627\u0628 \u0627\u0644\u0639\u0643\u0633 \u062a\u0644\u0642\u0627\u0626\u064a\u0627\u064b \u0625\u0630\u0627 \u0644\u0645 \u064a\u062a\u0645 \u062a\u0648\u0641\u064a\u0631\u0647. \u0625\u0630\u0627 \u0644\u0645 \u064a\u0648\u062c\u062f \u0633\u0639\u0631 \u0635\u0631\u0641 \u0644\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629\u060c \u0633\u064a\u0639\u0648\u062f Firefly III \u0628\u0627\u0644\u0632\u0645\u0646 \u0644\u0644\u0639\u062b\u0648\u0631 \u0639\u0644\u0649 \u0648\u0627\u062d\u062f. \u0625\u0630\u0627 \u0644\u0645 \u064a\u0648\u062c\u062f \u0623\u064a \u0633\u0639\u0631\u060c \u0633\u064a\u062a\u0645 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0627\u0644\u0633\u0639\u0631 \"1\".",
|
||||||
"header_exchange_rates_rates": "Exchange rates",
|
"header_exchange_rates_rates": "\u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||||
"header_exchange_rates_table": "Table with exchange rates",
|
"header_exchange_rates_table": "\u062c\u062f\u0648\u0644 \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
"help_rate_form": "\u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u064a\u0648\u0645\u060c \u0643\u0645 {to} \u0633\u062a\u062d\u0635\u0644 \u0645\u0642\u0627\u0628\u0644 \u0648\u0627\u062d\u062f {from}\u061f",
|
||||||
"add_new_rate": "Add a new exchange rate",
|
"add_new_rate": "\u0625\u0636\u0627\u0641\u0629 \u0633\u0639\u0631 \u0635\u0631\u0641 \u062c\u062f\u064a\u062f",
|
||||||
"save_new_rate": "Save new rate"
|
"save_new_rate": "\u062d\u0641\u0638 \u0633\u0639\u0631 \u062c\u062f\u064a\u062f"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
|
@@ -183,6 +183,6 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"html_language": "sv",
|
"html_language": "sv",
|
||||||
"date_time_fns": "MMMM do, yyyy @ HH:mm:ss"
|
"date_time_fns": "D MMMM YYYY @ HH:mm:ss"
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user