setTransactionIdentifier(); } /** * This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird. */ private function setTransactionIdentifier() { $subQuery = TransactionJournal ::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->whereNull('transaction_journals.deleted_at') ->whereNull('transactions.deleted_at') ->groupBy(['transaction_journals.id']) ->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]); $result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived')) ->mergeBindings($subQuery->getQuery()) ->where('t_count', '>', 2) ->select(['id', 't_count']); $journalIds = array_unique($result->pluck('id')->toArray()); foreach ($journalIds as $journalId) { // grab all positive transactiosn from this journal that are not deleted. // for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier. $identifier = 0; $processed = []; $transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get(); /** @var Transaction $transaction */ foreach ($transactions as $transaction) { // find opposing: $amount = bcmul(strval($transaction->amount), '-1'); try { /** @var Transaction $opposing */ $opposing = Transaction ::where('transaction_journal_id', $journalId) ->where('amount', $amount)->where('identifier', '=', 0) ->whereNotIn('id', $processed) ->first(); } catch (QueryException $e) { Log::error($e->getMessage()); $this->error('Firefly III could not find the "identifier" field in the "transactions" table.'); $this->error('This field is required for Firefly III version ' . config('firefly.version') . ' to run.'); $this->error('Please run "php artisan migrate" to add this field to the table.'); $this->info('Then, run "php artisan firefly:upgrade-database" to try again.'); break 2; } if (!is_null($opposing)) { // give both a new identifier: $transaction->identifier = $identifier; $transaction->save(); $opposing->identifier = $identifier; $opposing->save(); $processed[] = $transaction->id; $processed[] = $opposing->id; $this->line(sprintf('Database upgrade for journal #%d, transactions #%d and #%d', $journalId, $transaction->id, $opposing->id)); } $identifier++; } } } }