mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-11-04 05:15:39 +00:00 
			
		
		
		
	This commit is contained in:
		@@ -312,6 +312,12 @@ PUSHER_ID=
 | 
			
		||||
DEMO_USERNAME=
 | 
			
		||||
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.
 | 
			
		||||
# Be wary of data loss.
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ class AccountBalanceCalculator
 | 
			
		||||
    public static function recalculateForJournal(TransactionJournal $transactionJournal): void
 | 
			
		||||
    {
 | 
			
		||||
        Log::debug(__METHOD__);
 | 
			
		||||
        $object   = new self();
 | 
			
		||||
        $object = new self();
 | 
			
		||||
 | 
			
		||||
        // recalculate the involved accounts:
 | 
			
		||||
        $accounts = new Collection();
 | 
			
		||||
@@ -78,11 +78,38 @@ class AccountBalanceCalculator
 | 
			
		||||
        $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
 | 
			
		||||
    {
 | 
			
		||||
        $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) {
 | 
			
		||||
            // 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
 | 
			
		||||
    {
 | 
			
		||||
        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) {
 | 
			
		||||
            Log::debug(sprintf('Limited to %d account(s)', $accounts->count()));
 | 
			
		||||
        }
 | 
			
		||||
@@ -109,15 +141,14 @@ class AccountBalanceCalculator
 | 
			
		||||
        $balances = [];
 | 
			
		||||
        $count    = 0;
 | 
			
		||||
        $query    = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
 | 
			
		||||
            ->whereNull('transactions.deleted_at')
 | 
			
		||||
            ->whereNull('transaction_journals.deleted_at')
 | 
			
		||||
                               ->whereNull('transactions.deleted_at')
 | 
			
		||||
                               ->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')
 | 
			
		||||
        ;
 | 
			
		||||
                               ->orderBy('transaction_journals.date', 'asc')
 | 
			
		||||
                               ->orderBy('transaction_journals.order', 'desc')
 | 
			
		||||
                               ->orderBy('transaction_journals.id', 'asc')
 | 
			
		||||
                               ->orderBy('transaction_journals.description', 'asc')
 | 
			
		||||
                               ->orderBy('transactions.amount', 'asc');
 | 
			
		||||
        if ($accounts->count() > 0) {
 | 
			
		||||
            $query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
 | 
			
		||||
        }
 | 
			
		||||
@@ -126,17 +157,17 @@ class AccountBalanceCalculator
 | 
			
		||||
            $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 */
 | 
			
		||||
        foreach ($set as $entry) {
 | 
			
		||||
            // start with empty array:
 | 
			
		||||
            $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                                                        = $balances[$entry->account_id][$entry->transaction_currency_id];
 | 
			
		||||
            $after                                                         = bcadd($before, $entry->amount);
 | 
			
		||||
            $before = $balances[$entry->account_id][$entry->transaction_currency_id];
 | 
			
		||||
            $after  = bcadd($before, $entry->amount);
 | 
			
		||||
            if (true === $entry->balance_dirty || $accounts->count() > 0) {
 | 
			
		||||
                // update the transaction:
 | 
			
		||||
                $entry->balance_before = $before;
 | 
			
		||||
@@ -157,9 +188,9 @@ class AccountBalanceCalculator
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
            return $entry;
 | 
			
		||||
        }
 | 
			
		||||
@@ -176,7 +207,7 @@ class AccountBalanceCalculator
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
            $query->where('transactions.account_id', $account->id);
 | 
			
		||||
@@ -197,11 +228,11 @@ class AccountBalanceCalculator
 | 
			
		||||
            $sumForeignAmount    = '' === $sumForeignAmount ? '0' : $sumForeignAmount;
 | 
			
		||||
 | 
			
		||||
            // at this point SQLite may return scientific notation because why not. Terrible.
 | 
			
		||||
            $sumAmount           = app('steam')->floatalize($sumAmount);
 | 
			
		||||
            $sumForeignAmount    = app('steam')->floatalize($sumForeignAmount);
 | 
			
		||||
            $sumAmount        = app('steam')->floatalize($sumAmount);
 | 
			
		||||
            $sumForeignAmount = app('steam')->floatalize($sumForeignAmount);
 | 
			
		||||
 | 
			
		||||
            // first create for normal currency:
 | 
			
		||||
            $entry               = $this->getAccountBalanceByAccount($account, $transactionCurrency);
 | 
			
		||||
            $entry = $this->getAccountBalanceByAccount($account, $transactionCurrency);
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                $entry->balance = bcadd((string) $entry->balance, $sumAmount);
 | 
			
		||||
@@ -256,7 +287,7 @@ class AccountBalanceCalculator
 | 
			
		||||
     */
 | 
			
		||||
    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->orderBy('transaction_journals.date', 'asc');
 | 
			
		||||
        $amounts = [];
 | 
			
		||||
@@ -267,28 +298,28 @@ class AccountBalanceCalculator
 | 
			
		||||
            $query->where('transaction_journals.date', '>=', $transactionJournal->date);
 | 
			
		||||
            $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 */
 | 
			
		||||
        foreach ($result as $row) {
 | 
			
		||||
            $account                                 = (int) $row->account_id;
 | 
			
		||||
            $transactionCurrency                     = (int) $row->transaction_currency_id;
 | 
			
		||||
            $foreignCurrency                         = (int) $row->foreign_currency_id;
 | 
			
		||||
            $sumAmount                               = (string) $row->sum_amount;
 | 
			
		||||
            $sumForeignAmount                        = (string) $row->sum_foreign_amount;
 | 
			
		||||
            $journalId                               = (int) $row->id;
 | 
			
		||||
            $account             = (int) $row->account_id;
 | 
			
		||||
            $transactionCurrency = (int) $row->transaction_currency_id;
 | 
			
		||||
            $foreignCurrency     = (int) $row->foreign_currency_id;
 | 
			
		||||
            $sumAmount           = (string) $row->sum_amount;
 | 
			
		||||
            $sumForeignAmount    = (string) $row->sum_foreign_amount;
 | 
			
		||||
            $journalId           = (int) $row->id;
 | 
			
		||||
 | 
			
		||||
            // check for empty strings
 | 
			
		||||
            $sumAmount                               = '' === $sumAmount ? '0' : $sumAmount;
 | 
			
		||||
            $sumForeignAmount                        = '' === $sumForeignAmount ? '0' : $sumForeignAmount;
 | 
			
		||||
            $sumAmount        = '' === $sumAmount ? '0' : $sumAmount;
 | 
			
		||||
            $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount;
 | 
			
		||||
 | 
			
		||||
            // new amounts:
 | 
			
		||||
            $amounts[$account][$transactionCurrency] = bcadd($amounts[$account][$transactionCurrency] ?? '0', $sumAmount);
 | 
			
		||||
            $amounts[$account][$foreignCurrency]     = bcadd($amounts[$account][$foreignCurrency] ?? '0', $sumForeignAmount);
 | 
			
		||||
 | 
			
		||||
            // first create for normal currency:
 | 
			
		||||
            $entry                                   = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency);
 | 
			
		||||
            $entry->balance                          = $amounts[$account][$transactionCurrency];
 | 
			
		||||
            $entry          = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency);
 | 
			
		||||
            $entry->balance = $amounts[$account][$transactionCurrency];
 | 
			
		||||
            $entry->save();
 | 
			
		||||
 | 
			
		||||
            // then do foreign amount, if present:
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Search\OperatorQuerySearch;
 | 
			
		||||
use League\CommonMark\GithubFlavoredMarkdownConverter;
 | 
			
		||||
use Route;
 | 
			
		||||
use Twig\Extension\AbstractExtension;
 | 
			
		||||
use Twig\TwigFilter;
 | 
			
		||||
use Twig\TwigFunction;
 | 
			
		||||
@@ -63,8 +62,15 @@ class General extends AbstractExtension
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /** @var Carbon $date */
 | 
			
		||||
                $date    = session('end', today(config('app.timezone'))->endOfMonth());
 | 
			
		||||
                $info    = app('steam')->balanceByTransactions($account, $date, null);
 | 
			
		||||
                $date           = session('end', today(config('app.timezone'))->endOfMonth());
 | 
			
		||||
                $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 = [];
 | 
			
		||||
                foreach ($info as $currencyId => $balance) {
 | 
			
		||||
@@ -87,15 +93,15 @@ class General extends AbstractExtension
 | 
			
		||||
            static function (int $size): string {
 | 
			
		||||
                // less than one GB, more than one MB
 | 
			
		||||
                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
 | 
			
		||||
                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':
 | 
			
		||||
                        return 'fa-file-pdf-o';
 | 
			
		||||
 | 
			
		||||
                        // image
 | 
			
		||||
                    // image
 | 
			
		||||
                    case 'image/png':
 | 
			
		||||
                    case 'image/jpeg':
 | 
			
		||||
                    case 'image/svg+xml':
 | 
			
		||||
@@ -126,7 +132,7 @@ class General extends AbstractExtension
 | 
			
		||||
                    case 'application/vnd.oasis.opendocument.image':
 | 
			
		||||
                        return 'fa-file-image-o';
 | 
			
		||||
 | 
			
		||||
                        // MS word
 | 
			
		||||
                    // MS word
 | 
			
		||||
                    case 'application/msword':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
 | 
			
		||||
@@ -142,7 +148,7 @@ class General extends AbstractExtension
 | 
			
		||||
                    case 'application/vnd.oasis.opendocument.text-master':
 | 
			
		||||
                        return 'fa-file-word-o';
 | 
			
		||||
 | 
			
		||||
                        // MS excel
 | 
			
		||||
                    // MS excel
 | 
			
		||||
                    case 'application/vnd.ms-excel':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
 | 
			
		||||
@@ -153,7 +159,7 @@ class General extends AbstractExtension
 | 
			
		||||
                    case 'application/vnd.oasis.opendocument.spreadsheet-template':
 | 
			
		||||
                        return 'fa-file-excel-o';
 | 
			
		||||
 | 
			
		||||
                        // MS powerpoint
 | 
			
		||||
                    // MS powerpoint
 | 
			
		||||
                    case 'application/vnd.ms-powerpoint':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
 | 
			
		||||
                    case 'application/vnd.openxmlformats-officedocument.presentationml.template':
 | 
			
		||||
@@ -165,7 +171,7 @@ class General extends AbstractExtension
 | 
			
		||||
                    case 'application/vnd.oasis.opendocument.presentation-template':
 | 
			
		||||
                        return 'fa-file-powerpoint-o';
 | 
			
		||||
 | 
			
		||||
                        // calc
 | 
			
		||||
                    // calc
 | 
			
		||||
                    case 'application/vnd.sun.xml.draw':
 | 
			
		||||
                    case 'application/vnd.sun.xml.draw.template':
 | 
			
		||||
                    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']]
 | 
			
		||||
        );
 | 
			
		||||
@@ -212,8 +218,8 @@ class General extends AbstractExtension
 | 
			
		||||
        return new TwigFilter(
 | 
			
		||||
            'phphost',
 | 
			
		||||
            static function (string $string): string {
 | 
			
		||||
                $proto = (string)parse_url($string, PHP_URL_SCHEME);
 | 
			
		||||
                $host  = (string)parse_url($string, PHP_URL_HOST);
 | 
			
		||||
                $proto = (string) parse_url($string, PHP_URL_SCHEME);
 | 
			
		||||
                $host  = (string) parse_url($string, PHP_URL_HOST);
 | 
			
		||||
 | 
			
		||||
                return e(sprintf('%s://%s', $proto, $host));
 | 
			
		||||
            }
 | 
			
		||||
@@ -301,7 +307,7 @@ class General extends AbstractExtension
 | 
			
		||||
            'activeRoutePartialObjectType',
 | 
			
		||||
            static function ($context): string {
 | 
			
		||||
                [, $route, $objectType] = func_get_args();
 | 
			
		||||
                $activeObjectType       = $context['objectType'] ?? false;
 | 
			
		||||
                $activeObjectType = $context['objectType'] ?? false;
 | 
			
		||||
 | 
			
		||||
                if ($objectType === $activeObjectType
 | 
			
		||||
                    && false !== stripos(
 | 
			
		||||
 
 | 
			
		||||
@@ -65,10 +65,6 @@ use FireflyIII\Support\Binder\UserGroupAccount;
 | 
			
		||||
use FireflyIII\Support\Binder\UserGroupBill;
 | 
			
		||||
use FireflyIII\Support\Binder\UserGroupTransaction;
 | 
			
		||||
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\ClearCategory;
 | 
			
		||||
use FireflyIII\TransactionRules\Actions\ClearNotes;
 | 
			
		||||
@@ -77,10 +73,6 @@ use FireflyIII\TransactionRules\Actions\ConvertToTransfer;
 | 
			
		||||
use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal;
 | 
			
		||||
use FireflyIII\TransactionRules\Actions\DeleteTransaction;
 | 
			
		||||
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\RemoveTag;
 | 
			
		||||
use FireflyIII\TransactionRules\Actions\SetAmount;
 | 
			
		||||
@@ -110,11 +102,12 @@ return [
 | 
			
		||||
    ],
 | 
			
		||||
    // some feature flags:
 | 
			
		||||
    'feature_flags'                => [
 | 
			
		||||
        'export'            => true,
 | 
			
		||||
        'telemetry'         => false,
 | 
			
		||||
        'webhooks'          => true,
 | 
			
		||||
        'handle_debts'      => true,
 | 
			
		||||
        'expression_engine' => true,
 | 
			
		||||
        'export'                 => true,
 | 
			
		||||
        'telemetry'              => false,
 | 
			
		||||
        'webhooks'               => true,
 | 
			
		||||
        'handle_debts'           => true,
 | 
			
		||||
        'expression_engine'      => true,
 | 
			
		||||
        'running_balance_column' => env('USE_RUNNING_BALANCE', false),
 | 
			
		||||
        // see cer.php for exchange rates feature flag.
 | 
			
		||||
    ],
 | 
			
		||||
    'version'                      => 'develop/2024-09-28',
 | 
			
		||||
@@ -436,7 +429,7 @@ return [
 | 
			
		||||
        'transfers'  => 'fa-exchange',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    'bindables'                    => [
 | 
			
		||||
    'bindables'            => [
 | 
			
		||||
        // models
 | 
			
		||||
        'account'              => Account::class,
 | 
			
		||||
        'attachment'           => Attachment::class,
 | 
			
		||||
@@ -494,7 +487,7 @@ return [
 | 
			
		||||
        'userGroupBill'        => UserGroupBill::class,
 | 
			
		||||
        'userGroup'            => UserGroup::class,
 | 
			
		||||
    ],
 | 
			
		||||
    'rule-actions'                 => [
 | 
			
		||||
    'rule-actions'         => [
 | 
			
		||||
        'set_category'            => SetCategory::class,
 | 
			
		||||
        'clear_category'          => ClearCategory::class,
 | 
			
		||||
        'set_budget'              => SetBudget::class,
 | 
			
		||||
@@ -528,7 +521,7 @@ return [
 | 
			
		||||
        // 'set_foreign_amount' => SetForeignAmount::class,
 | 
			
		||||
        // 'set_foreign_currency' => SetForeignCurrency::class,
 | 
			
		||||
    ],
 | 
			
		||||
    'context-rule-actions'         => [
 | 
			
		||||
    'context-rule-actions' => [
 | 
			
		||||
        'set_category',
 | 
			
		||||
        'set_budget',
 | 
			
		||||
        'add_tag',
 | 
			
		||||
@@ -547,13 +540,13 @@ return [
 | 
			
		||||
        'convert_transfer',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    'test-triggers'                => [
 | 
			
		||||
    'test-triggers'             => [
 | 
			
		||||
        'limit' => 10,
 | 
			
		||||
        'range' => 200,
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // expected source types for each transaction type, in order of preference.
 | 
			
		||||
    'expected_source_types'        => [
 | 
			
		||||
    'expected_source_types'     => [
 | 
			
		||||
        'source'      => [
 | 
			
		||||
            TransactionTypeModel::WITHDRAWAL       => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
 | 
			
		||||
            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],
 | 
			
		||||
        ],
 | 
			
		||||
    ],
 | 
			
		||||
    'allowed_opposing_types'       => [
 | 
			
		||||
    'allowed_opposing_types'    => [
 | 
			
		||||
        'source'      => [
 | 
			
		||||
            AccountType::ASSET            => [
 | 
			
		||||
                AccountType::ASSET,
 | 
			
		||||
@@ -688,7 +681,7 @@ return [
 | 
			
		||||
        ],
 | 
			
		||||
    ],
 | 
			
		||||
    // depending on the account type, return the allowed transaction types:
 | 
			
		||||
    'allowed_transaction_types'    => [
 | 
			
		||||
    'allowed_transaction_types' => [
 | 
			
		||||
        'source'      => [
 | 
			
		||||
            AccountType::ASSET            => [
 | 
			
		||||
                TransactionTypeModel::WITHDRAWAL,
 | 
			
		||||
@@ -757,7 +750,7 @@ return [
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // having the source + dest will tell you the transaction type.
 | 
			
		||||
    'account_to_transaction'       => [
 | 
			
		||||
    'account_to_transaction'    => [
 | 
			
		||||
        AccountType::ASSET            => [
 | 
			
		||||
            AccountType::ASSET           => TransactionTypeModel::TRANSFER,
 | 
			
		||||
            AccountType::CASH            => TransactionTypeModel::WITHDRAWAL,
 | 
			
		||||
@@ -822,7 +815,7 @@ return [
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // allowed source -> destination accounts.
 | 
			
		||||
    'source_dests'                 => [
 | 
			
		||||
    'source_dests'              => [
 | 
			
		||||
        TransactionTypeModel::WITHDRAWAL       => [
 | 
			
		||||
            AccountType::ASSET    => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, 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).
 | 
			
		||||
    'journal_meta_fields'          => [
 | 
			
		||||
    'journal_meta_fields'       => [
 | 
			
		||||
        // sepa
 | 
			
		||||
        'sepa_cc',
 | 
			
		||||
        'sepa_ct_op',
 | 
			
		||||
@@ -895,28 +888,28 @@ return [
 | 
			
		||||
        'recurrence_count',
 | 
			
		||||
        'recurrence_date',
 | 
			
		||||
    ],
 | 
			
		||||
    'webhooks'                     => [
 | 
			
		||||
    'webhooks'                  => [
 | 
			
		||||
        'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
 | 
			
		||||
    ],
 | 
			
		||||
    'can_have_virtual_amounts'     => [AccountType::ASSET],
 | 
			
		||||
    'can_have_opening_balance'     => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
 | 
			
		||||
    'dynamic_creation_allowed'     => [
 | 
			
		||||
    'can_have_virtual_amounts'  => [AccountType::ASSET],
 | 
			
		||||
    'can_have_opening_balance'  => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
 | 
			
		||||
    'dynamic_creation_allowed'  => [
 | 
			
		||||
        AccountType::EXPENSE,
 | 
			
		||||
        AccountType::REVENUE,
 | 
			
		||||
        AccountType::INITIAL_BALANCE,
 | 
			
		||||
        AccountType::RECONCILIATION,
 | 
			
		||||
        AccountType::LIABILITY_CREDIT,
 | 
			
		||||
    ],
 | 
			
		||||
    '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_account_fields'         => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
 | 
			
		||||
    '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_account_fields'      => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
    'allowed_sort_parameters'      => ['order', 'name', 'iban'],
 | 
			
		||||
    'allowed_sort_parameters'   => ['order', 'name', 'iban'],
 | 
			
		||||
 | 
			
		||||
    // preselected account lists possibilities:
 | 
			
		||||
    'preselected_accounts'         => ['all', 'assets', 'liabilities'],
 | 
			
		||||
    'preselected_accounts'      => ['all', 'assets', 'liabilities'],
 | 
			
		||||
];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user