James Cole
2024-09-28 17:17:29 +02:00
parent e7526ac5e3
commit b45aa85853
4 changed files with 117 additions and 81 deletions

View File

@@ -312,6 +312,12 @@ PUSHER_ID=
DEMO_USERNAME= DEMO_USERNAME=
DEMO_PASSWORD= DEMO_PASSWORD=
#
# Disable or enable the running balance column data
# Please disable this. It's a very experimental feature.
#
USE_RUNNING_BALANCE=false
# #
# The v2 layout is very experimental. If it breaks you get to keep both parts. # The v2 layout is very experimental. If it breaks you get to keep both parts.
# Be wary of data loss. # Be wary of data loss.

View File

@@ -68,7 +68,7 @@ class AccountBalanceCalculator
public static function recalculateForJournal(TransactionJournal $transactionJournal): void public static function recalculateForJournal(TransactionJournal $transactionJournal): void
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
$object = new self(); $object = new self();
// recalculate the involved accounts: // recalculate the involved accounts:
$accounts = new Collection(); $accounts = new Collection();
@@ -78,11 +78,38 @@ class AccountBalanceCalculator
$object->optimizedCalculation($accounts, $transactionJournal->date); $object->optimizedCalculation($accounts, $transactionJournal->date);
} }
private function getLatestBalance(int $accountId, int $currencyId, ?Carbon $notBefore): string
{
if (null === $notBefore) {
Log::debug('getLatestBalance: no notBefore date, returning 0');
return '0';
}
Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d')));
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNull('transactions.deleted_at')
->where('transaction_journals.transaction_currency_id', $currencyId)
->whereNull('transaction_journals.deleted_at')
// this order is the same as GroupCollector, but in the exact reverse.
->orderBy('transaction_journals.date', 'asc')
->orderBy('transaction_journals.order', 'desc')
->orderBy('transaction_journals.id', 'asc')
->orderBy('transaction_journals.description', 'asc')
->orderBy('transactions.amount', 'asc')
->where('transactions.account_id', $accountId);
$notBefore->startOfDay();
$query->where('transaction_journals.date', '<', $notBefore);
$first = $query->first(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount','transactions.balance_after']);
$balance = $first->balance_after ?? '0';
Log::debug(sprintf('getLatestBalance: found balance: %s in transaction #%d', $balance, $first->id ?? 0));
return $balance;
}
private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
{ {
$query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency); $query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency);
$entry = $query->first(); $entry = $query->first();
if (null !== $entry) { if (null !== $entry) {
// Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance)); // Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
@@ -102,6 +129,11 @@ class AccountBalanceCalculator
private function optimizedCalculation(Collection $accounts, ?Carbon $notBefore = null): void private function optimizedCalculation(Collection $accounts, ?Carbon $notBefore = null): void
{ {
Log::debug('start of optimizedCalculation'); Log::debug('start of optimizedCalculation');
if(false === config('firefly.feature_flags.running_balance_column')) {
Log::debug('optimizedCalculation is disabled, return.');
return;
}
if ($accounts->count() > 0) { if ($accounts->count() > 0) {
Log::debug(sprintf('Limited to %d account(s)', $accounts->count())); Log::debug(sprintf('Limited to %d account(s)', $accounts->count()));
} }
@@ -109,15 +141,14 @@ class AccountBalanceCalculator
$balances = []; $balances = [];
$count = 0; $count = 0;
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') $query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNull('transactions.deleted_at') ->whereNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at') ->whereNull('transaction_journals.deleted_at')
// this order is the same as GroupCollector, but in the exact reverse. // this order is the same as GroupCollector, but in the exact reverse.
->orderBy('transaction_journals.date', 'asc') ->orderBy('transaction_journals.date', 'asc')
->orderBy('transaction_journals.order', 'desc') ->orderBy('transaction_journals.order', 'desc')
->orderBy('transaction_journals.id', 'asc') ->orderBy('transaction_journals.id', 'asc')
->orderBy('transaction_journals.description', 'asc') ->orderBy('transaction_journals.description', 'asc')
->orderBy('transactions.amount', 'asc') ->orderBy('transactions.amount', 'asc');
;
if ($accounts->count() > 0) { if ($accounts->count() > 0) {
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray()); $query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
} }
@@ -126,17 +157,17 @@ class AccountBalanceCalculator
$query->where('transaction_journals.date', '>=', $notBefore); $query->where('transaction_journals.date', '>=', $notBefore);
} }
$set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']); $set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']);
/** @var Transaction $entry */ /** @var Transaction $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
// start with empty array: // start with empty array:
$balances[$entry->account_id] ??= []; $balances[$entry->account_id] ??= [];
$balances[$entry->account_id][$entry->transaction_currency_id] ??= '0'; $balances[$entry->account_id][$entry->transaction_currency_id] ??= $this->getLatestBalance($entry->account_id, $entry->transaction_currency_id, $notBefore);
// before and after are easy: // before and after are easy:
$before = $balances[$entry->account_id][$entry->transaction_currency_id]; $before = $balances[$entry->account_id][$entry->transaction_currency_id];
$after = bcadd($before, $entry->amount); $after = bcadd($before, $entry->amount);
if (true === $entry->balance_dirty || $accounts->count() > 0) { if (true === $entry->balance_dirty || $accounts->count() > 0) {
// update the transaction: // update the transaction:
$entry->balance_before = $before; $entry->balance_before = $before;
@@ -157,9 +188,9 @@ class AccountBalanceCalculator
private function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance private function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance
{ {
$query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency); $query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency);
$entry = $query->first(); $entry = $query->first();
if (null !== $entry) { if (null !== $entry) {
return $entry; return $entry;
} }
@@ -176,7 +207,7 @@ class AccountBalanceCalculator
private function recalculateLatest(?Account $account): void private function recalculateLatest(?Account $account): void
{ {
$query = Transaction::groupBy(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); $query = Transaction::groupBy(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']);
if (null !== $account) { if (null !== $account) {
$query->where('transactions.account_id', $account->id); $query->where('transactions.account_id', $account->id);
@@ -197,11 +228,11 @@ class AccountBalanceCalculator
$sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount; $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount;
// at this point SQLite may return scientific notation because why not. Terrible. // at this point SQLite may return scientific notation because why not. Terrible.
$sumAmount = app('steam')->floatalize($sumAmount); $sumAmount = app('steam')->floatalize($sumAmount);
$sumForeignAmount = app('steam')->floatalize($sumForeignAmount); $sumForeignAmount = app('steam')->floatalize($sumForeignAmount);
// first create for normal currency: // first create for normal currency:
$entry = $this->getAccountBalanceByAccount($account, $transactionCurrency); $entry = $this->getAccountBalanceByAccount($account, $transactionCurrency);
try { try {
$entry->balance = bcadd((string) $entry->balance, $sumAmount); $entry->balance = bcadd((string) $entry->balance, $sumAmount);
@@ -256,7 +287,7 @@ class AccountBalanceCalculator
*/ */
private function recalculateJournals(?Account $account, ?TransactionJournal $transactionJournal): void private function recalculateJournals(?Account $account, ?TransactionJournal $transactionJournal): void
{ {
$query = Transaction::groupBy(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); $query = Transaction::groupBy(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']);
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'); $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
$query->orderBy('transaction_journals.date', 'asc'); $query->orderBy('transaction_journals.date', 'asc');
$amounts = []; $amounts = [];
@@ -267,28 +298,28 @@ class AccountBalanceCalculator
$query->where('transaction_journals.date', '>=', $transactionJournal->date); $query->where('transaction_journals.date', '>=', $transactionJournal->date);
$amounts = $this->getStartAmounts($account, $transactionJournal); $amounts = $this->getStartAmounts($account, $transactionJournal);
} }
$result = $query->get(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]); $result = $query->get(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]);
/** @var \stdClass $row */ /** @var \stdClass $row */
foreach ($result as $row) { foreach ($result as $row) {
$account = (int) $row->account_id; $account = (int) $row->account_id;
$transactionCurrency = (int) $row->transaction_currency_id; $transactionCurrency = (int) $row->transaction_currency_id;
$foreignCurrency = (int) $row->foreign_currency_id; $foreignCurrency = (int) $row->foreign_currency_id;
$sumAmount = (string) $row->sum_amount; $sumAmount = (string) $row->sum_amount;
$sumForeignAmount = (string) $row->sum_foreign_amount; $sumForeignAmount = (string) $row->sum_foreign_amount;
$journalId = (int) $row->id; $journalId = (int) $row->id;
// check for empty strings // check for empty strings
$sumAmount = '' === $sumAmount ? '0' : $sumAmount; $sumAmount = '' === $sumAmount ? '0' : $sumAmount;
$sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount; $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount;
// new amounts: // new amounts:
$amounts[$account][$transactionCurrency] = bcadd($amounts[$account][$transactionCurrency] ?? '0', $sumAmount); $amounts[$account][$transactionCurrency] = bcadd($amounts[$account][$transactionCurrency] ?? '0', $sumAmount);
$amounts[$account][$foreignCurrency] = bcadd($amounts[$account][$foreignCurrency] ?? '0', $sumForeignAmount); $amounts[$account][$foreignCurrency] = bcadd($amounts[$account][$foreignCurrency] ?? '0', $sumForeignAmount);
// first create for normal currency: // first create for normal currency:
$entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency); $entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency);
$entry->balance = $amounts[$account][$transactionCurrency]; $entry->balance = $amounts[$account][$transactionCurrency];
$entry->save(); $entry->save();
// then do foreign amount, if present: // then do foreign amount, if present:

View File

@@ -29,7 +29,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Search\OperatorQuerySearch; use FireflyIII\Support\Search\OperatorQuerySearch;
use League\CommonMark\GithubFlavoredMarkdownConverter; use League\CommonMark\GithubFlavoredMarkdownConverter;
use Route;
use Twig\Extension\AbstractExtension; use Twig\Extension\AbstractExtension;
use Twig\TwigFilter; use Twig\TwigFilter;
use Twig\TwigFunction; use Twig\TwigFunction;
@@ -63,8 +62,15 @@ class General extends AbstractExtension
} }
/** @var Carbon $date */ /** @var Carbon $date */
$date = session('end', today(config('app.timezone'))->endOfMonth()); $date = session('end', today(config('app.timezone'))->endOfMonth());
$info = app('steam')->balanceByTransactions($account, $date, null); $runningBalance = config('firefly.feature_flags.running_balance_column');
$info = [];
if (true === $runningBalance) {
$info = app('steam')->balanceByTransactions($account, $date, null);
}
if (false === $runningBalance) {
$info[] = app('steam')->balance($account, $date);
}
$strings = []; $strings = [];
foreach ($info as $currencyId => $balance) { foreach ($info as $currencyId => $balance) {
@@ -87,15 +93,15 @@ class General extends AbstractExtension
static function (int $size): string { static function (int $size): string {
// less than one GB, more than one MB // less than one GB, more than one MB
if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) { if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) {
return round($size / (1024 * 1024), 2).' MB'; return round($size / (1024 * 1024), 2) . ' MB';
} }
// less than one MB // less than one MB
if ($size < (1024 * 1024)) { if ($size < (1024 * 1024)) {
return round($size / 1024, 2).' KB'; return round($size / 1024, 2) . ' KB';
} }
return $size.' bytes'; return $size . ' bytes';
} }
); );
} }
@@ -117,7 +123,7 @@ class General extends AbstractExtension
case 'application/pdf': case 'application/pdf':
return 'fa-file-pdf-o'; return 'fa-file-pdf-o';
// image // image
case 'image/png': case 'image/png':
case 'image/jpeg': case 'image/jpeg':
case 'image/svg+xml': case 'image/svg+xml':
@@ -126,7 +132,7 @@ class General extends AbstractExtension
case 'application/vnd.oasis.opendocument.image': case 'application/vnd.oasis.opendocument.image':
return 'fa-file-image-o'; return 'fa-file-image-o';
// MS word // MS word
case 'application/msword': case 'application/msword':
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
@@ -142,7 +148,7 @@ class General extends AbstractExtension
case 'application/vnd.oasis.opendocument.text-master': case 'application/vnd.oasis.opendocument.text-master':
return 'fa-file-word-o'; return 'fa-file-word-o';
// MS excel // MS excel
case 'application/vnd.ms-excel': case 'application/vnd.ms-excel':
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
@@ -153,7 +159,7 @@ class General extends AbstractExtension
case 'application/vnd.oasis.opendocument.spreadsheet-template': case 'application/vnd.oasis.opendocument.spreadsheet-template':
return 'fa-file-excel-o'; return 'fa-file-excel-o';
// MS powerpoint // MS powerpoint
case 'application/vnd.ms-powerpoint': case 'application/vnd.ms-powerpoint':
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
case 'application/vnd.openxmlformats-officedocument.presentationml.template': case 'application/vnd.openxmlformats-officedocument.presentationml.template':
@@ -165,7 +171,7 @@ class General extends AbstractExtension
case 'application/vnd.oasis.opendocument.presentation-template': case 'application/vnd.oasis.opendocument.presentation-template':
return 'fa-file-powerpoint-o'; return 'fa-file-powerpoint-o';
// calc // calc
case 'application/vnd.sun.xml.draw': case 'application/vnd.sun.xml.draw':
case 'application/vnd.sun.xml.draw.template': case 'application/vnd.sun.xml.draw.template':
case 'application/vnd.stardivision.draw': case 'application/vnd.stardivision.draw':
@@ -198,7 +204,7 @@ class General extends AbstractExtension
] ]
); );
return (string)$converter->convert($text); return (string) $converter->convert($text);
}, },
['is_safe' => ['html']] ['is_safe' => ['html']]
); );
@@ -212,8 +218,8 @@ class General extends AbstractExtension
return new TwigFilter( return new TwigFilter(
'phphost', 'phphost',
static function (string $string): string { static function (string $string): string {
$proto = (string)parse_url($string, PHP_URL_SCHEME); $proto = (string) parse_url($string, PHP_URL_SCHEME);
$host = (string)parse_url($string, PHP_URL_HOST); $host = (string) parse_url($string, PHP_URL_HOST);
return e(sprintf('%s://%s', $proto, $host)); return e(sprintf('%s://%s', $proto, $host));
} }
@@ -301,7 +307,7 @@ class General extends AbstractExtension
'activeRoutePartialObjectType', 'activeRoutePartialObjectType',
static function ($context): string { static function ($context): string {
[, $route, $objectType] = func_get_args(); [, $route, $objectType] = func_get_args();
$activeObjectType = $context['objectType'] ?? false; $activeObjectType = $context['objectType'] ?? false;
if ($objectType === $activeObjectType if ($objectType === $activeObjectType
&& false !== stripos( && false !== stripos(

View File

@@ -65,10 +65,6 @@ use FireflyIII\Support\Binder\UserGroupAccount;
use FireflyIII\Support\Binder\UserGroupBill; use FireflyIII\Support\Binder\UserGroupBill;
use FireflyIII\Support\Binder\UserGroupTransaction; use FireflyIII\Support\Binder\UserGroupTransaction;
use FireflyIII\TransactionRules\Actions\AddTag; use FireflyIII\TransactionRules\Actions\AddTag;
use FireflyIII\TransactionRules\Actions\AppendDescription;
use FireflyIII\TransactionRules\Actions\AppendDescriptionToNotes;
use FireflyIII\TransactionRules\Actions\AppendNotes;
use FireflyIII\TransactionRules\Actions\AppendNotesToDescription;
use FireflyIII\TransactionRules\Actions\ClearBudget; use FireflyIII\TransactionRules\Actions\ClearBudget;
use FireflyIII\TransactionRules\Actions\ClearCategory; use FireflyIII\TransactionRules\Actions\ClearCategory;
use FireflyIII\TransactionRules\Actions\ClearNotes; use FireflyIII\TransactionRules\Actions\ClearNotes;
@@ -77,10 +73,6 @@ use FireflyIII\TransactionRules\Actions\ConvertToTransfer;
use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal; use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal;
use FireflyIII\TransactionRules\Actions\DeleteTransaction; use FireflyIII\TransactionRules\Actions\DeleteTransaction;
use FireflyIII\TransactionRules\Actions\LinkToBill; use FireflyIII\TransactionRules\Actions\LinkToBill;
use FireflyIII\TransactionRules\Actions\MoveDescriptionToNotes;
use FireflyIII\TransactionRules\Actions\MoveNotesToDescription;
use FireflyIII\TransactionRules\Actions\PrependDescription;
use FireflyIII\TransactionRules\Actions\PrependNotes;
use FireflyIII\TransactionRules\Actions\RemoveAllTags; use FireflyIII\TransactionRules\Actions\RemoveAllTags;
use FireflyIII\TransactionRules\Actions\RemoveTag; use FireflyIII\TransactionRules\Actions\RemoveTag;
use FireflyIII\TransactionRules\Actions\SetAmount; use FireflyIII\TransactionRules\Actions\SetAmount;
@@ -110,11 +102,12 @@ return [
], ],
// some feature flags: // some feature flags:
'feature_flags' => [ 'feature_flags' => [
'export' => true, 'export' => true,
'telemetry' => false, 'telemetry' => false,
'webhooks' => true, 'webhooks' => true,
'handle_debts' => true, 'handle_debts' => true,
'expression_engine' => true, 'expression_engine' => true,
'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/2024-09-28', 'version' => 'develop/2024-09-28',
@@ -436,7 +429,7 @@ return [
'transfers' => 'fa-exchange', 'transfers' => 'fa-exchange',
], ],
'bindables' => [ 'bindables' => [
// models // models
'account' => Account::class, 'account' => Account::class,
'attachment' => Attachment::class, 'attachment' => Attachment::class,
@@ -494,7 +487,7 @@ return [
'userGroupBill' => UserGroupBill::class, 'userGroupBill' => UserGroupBill::class,
'userGroup' => UserGroup::class, 'userGroup' => UserGroup::class,
], ],
'rule-actions' => [ 'rule-actions' => [
'set_category' => SetCategory::class, 'set_category' => SetCategory::class,
'clear_category' => ClearCategory::class, 'clear_category' => ClearCategory::class,
'set_budget' => SetBudget::class, 'set_budget' => SetBudget::class,
@@ -528,7 +521,7 @@ return [
// 'set_foreign_amount' => SetForeignAmount::class, // 'set_foreign_amount' => SetForeignAmount::class,
// 'set_foreign_currency' => SetForeignCurrency::class, // 'set_foreign_currency' => SetForeignCurrency::class,
], ],
'context-rule-actions' => [ 'context-rule-actions' => [
'set_category', 'set_category',
'set_budget', 'set_budget',
'add_tag', 'add_tag',
@@ -547,13 +540,13 @@ return [
'convert_transfer', 'convert_transfer',
], ],
'test-triggers' => [ 'test-triggers' => [
'limit' => 10, 'limit' => 10,
'range' => 200, 'range' => 200,
], ],
// expected source types for each transaction type, in order of preference. // expected source types for each transaction type, in order of preference.
'expected_source_types' => [ 'expected_source_types' => [
'source' => [ 'source' => [
TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeEnum::DEPOSIT->value => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::REVENUE, AccountType::CASH], TransactionTypeEnum::DEPOSIT->value => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::REVENUE, AccountType::CASH],
@@ -598,7 +591,7 @@ return [
TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
], ],
], ],
'allowed_opposing_types' => [ 'allowed_opposing_types' => [
'source' => [ 'source' => [
AccountType::ASSET => [ AccountType::ASSET => [
AccountType::ASSET, AccountType::ASSET,
@@ -688,7 +681,7 @@ return [
], ],
], ],
// depending on the account type, return the allowed transaction types: // depending on the account type, return the allowed transaction types:
'allowed_transaction_types' => [ 'allowed_transaction_types' => [
'source' => [ 'source' => [
AccountType::ASSET => [ AccountType::ASSET => [
TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::WITHDRAWAL,
@@ -757,7 +750,7 @@ return [
], ],
// having the source + dest will tell you the transaction type. // having the source + dest will tell you the transaction type.
'account_to_transaction' => [ 'account_to_transaction' => [
AccountType::ASSET => [ AccountType::ASSET => [
AccountType::ASSET => TransactionTypeModel::TRANSFER, AccountType::ASSET => TransactionTypeModel::TRANSFER,
AccountType::CASH => TransactionTypeModel::WITHDRAWAL, AccountType::CASH => TransactionTypeModel::WITHDRAWAL,
@@ -822,7 +815,7 @@ return [
], ],
// allowed source -> destination accounts. // allowed source -> destination accounts.
'source_dests' => [ 'source_dests' => [
TransactionTypeModel::WITHDRAWAL => [ TransactionTypeModel::WITHDRAWAL => [
AccountType::ASSET => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::CASH], AccountType::ASSET => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::CASH],
AccountType::LOAN => [AccountType::EXPENSE, AccountType::CASH], AccountType::LOAN => [AccountType::EXPENSE, AccountType::CASH],
@@ -861,7 +854,7 @@ return [
], ],
], ],
// if you add fields to this array, don't forget to update the export routine (ExportDataGenerator). // if you add fields to this array, don't forget to update the export routine (ExportDataGenerator).
'journal_meta_fields' => [ 'journal_meta_fields' => [
// sepa // sepa
'sepa_cc', 'sepa_cc',
'sepa_ct_op', 'sepa_ct_op',
@@ -895,28 +888,28 @@ return [
'recurrence_count', 'recurrence_count',
'recurrence_date', 'recurrence_date',
], ],
'webhooks' => [ 'webhooks' => [
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3), 'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
], ],
'can_have_virtual_amounts' => [AccountType::ASSET], 'can_have_virtual_amounts' => [AccountType::ASSET],
'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], 'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
'dynamic_creation_allowed' => [ 'dynamic_creation_allowed' => [
AccountType::EXPENSE, AccountType::EXPENSE,
AccountType::REVENUE, AccountType::REVENUE,
AccountType::INITIAL_BALANCE, AccountType::INITIAL_BALANCE,
AccountType::RECONCILIATION, AccountType::RECONCILIATION,
AccountType::LIABILITY_CREDIT, AccountType::LIABILITY_CREDIT,
], ],
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'], 'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
// dynamic date ranges are as follows: // dynamic date ranges are as follows:
'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'], 'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'],
// only used in v1 // only used in v1
'allowed_sort_parameters' => ['order', 'name', 'iban'], 'allowed_sort_parameters' => ['order', 'name', 'iban'],
// preselected account lists possibilities: // preselected account lists possibilities:
'preselected_accounts' => ['all', 'assets', 'liabilities'], 'preselected_accounts' => ['all', 'assets', 'liabilities'],
]; ];