Restucturing some code.

This commit is contained in:
James Cole
2016-10-15 12:39:34 +02:00
parent 2f9a4bb79a
commit 8e48e53f17
9 changed files with 708 additions and 280 deletions

View File

@@ -24,6 +24,7 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
use Illuminate\Http\Request;
use Preferences;
use Response;
@@ -270,17 +271,13 @@ class TransactionController extends Controller
*
* @return View
*/
public function show(TransactionJournal $journal, JournalRepositoryInterface $repository)
public function show(TransactionJournal $journal, JournalRepositoryInterface $repository, JournalTaskerInterface $tasker)
{
$events = $repository->getPiggyBankEvents($journal);
$transactions = $repository->getTransactions($journal);
$transactions = $tasker->getTransactionsOverview($journal);
$what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
$subTitle = trans('firefly.' . $what) . ' "' . e($journal->description) . '"';
if ($transactions->count() > 2) {
return view('split.journals.show', compact('journal', 'events', 'subTitle', 'what', 'transactions'));
}
return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions'));

View File

@@ -41,6 +41,12 @@ class JournalServiceProvider extends ServiceProvider
* @return void
*/
public function register()
{
$this->registerRepository();
$this->registerTasker();
}
private function registerRepository()
{
$this->app->bind(
'FireflyIII\Repositories\Journal\JournalRepositoryInterface',
@@ -56,4 +62,21 @@ class JournalServiceProvider extends ServiceProvider
}
);
}
private function registerTasker()
{
$this->app->bind(
'FireflyIII\Repositories\Journal\JournalTaskerInterface',
function (Application $app, array $arguments) {
if (!isset($arguments[0]) && $app->auth->check()) {
return app('FireflyIII\Repositories\Journal\JournalTasker', [auth()->user()]);
}
if (!isset($arguments[0]) && !$app->auth->check()) {
throw new FireflyException('There is no user present.');
}
return app('FireflyIII\Repositories\Journal\JournalTasker', $arguments);
}
);
}
}

View File

@@ -26,6 +26,7 @@ use Illuminate\Support\Collection;
*/
interface JournalRepositoryInterface
{
/**
* Returns the amount in the account before the specified transaction took place.
*

View File

@@ -0,0 +1,231 @@
<?php
/**
* JournalTasker.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Repositories\Journal;
use Crypt;
use DB;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
/**
* Class JournalTasker
*
* @package FireflyIII\Repositories\Journal
*/
class JournalTasker implements JournalTaskerInterface
{
/** @var User */
private $user;
/**
* JournalRepository constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get an overview of the transactions of a journal, tailored to the view
* that shows a transaction (transaction/show/xx).
*
* @param TransactionJournal $journal
*
* @return array
*/
public function getTransactionsOverview(TransactionJournal $journal): array
{
// get all transaction data + the opposite site in one list.
/**
* select
*
* source.id,
* source.account_id,
* source_accounts.name as account_name,
* source_accounts.encrypted as account_encrypted,
* source.amount,
* source.description,
*
* destination.id as destination_id,
* destination.account_id as destination_account_id,
* destination_accounts.name as destination_account_name,
* destination_accounts.encrypted as destination_account_encrypted
*
*
* from transactions as source
*
* left join transactions as destination ON source.transaction_journal_id = destination.transaction_journal_id AND source.amount = destination.amount * -1 AND source.identifier = destination.identifier
* -- left join source account name:
* left join accounts as source_accounts ON source.account_id = source_accounts.id
* left join accounts as destination_accounts ON destination.account_id = destination_accounts.id
*
* where source.transaction_journal_id = 6600
* and source.amount < 0
* and source.deleted_at is null
*/
$set = $journal
->transactions()// "source"
->leftJoin(
'transactions as destination', function (JoinClause $join) {
$join
->on('transactions.transaction_journal_id', '=', 'destination.transaction_journal_id')
->where('transactions.amount', '=', DB::raw('destination.amount * -1'))
->where('transactions.identifier', '=', DB::raw('destination.identifier'));
}
)
->leftJoin('accounts as source_accounts', 'transactions.account_id', '=', 'source_accounts.id')
->leftJoin('accounts as destination_accounts', 'destination.account_id', '=', 'destination_accounts.id')
->where('transactions.amount', '<', 0)
->get(
[
'transactions.id',
'transactions.account_id',
'source_accounts.name as account_name',
'source_accounts.encrypted as account_encrypted',
'transactions.amount',
'transactions.description',
'destination.id as destination_id',
'destination.account_id as destination_account_id',
'destination_accounts.name as destination_account_name',
'destination_accounts.encrypted as destination_account_encrypted',
]
);
$transactions = [];
/** @var Transaction $entry */
foreach ($set as $entry) {
$sourceBalance = $this->getBalance($entry->id);
$destinationBalance = $this->getBalance($entry->destination_id);
$transaction = [
'source_id' => $entry->id,
'source_amount' => $entry->amount,
'description' => $entry->description,
'source_account_id' => $entry->account_id,
'source_account_name' => intval($entry->account_encrypted) === 1 ? Crypt::decrypt($entry->account_name) : $entry->account_name,
'source_account_before' => $sourceBalance,
'source_account_after' => bcadd($sourceBalance, $entry->amount),
'destination_id' => $entry->destination_id,
'destination_amount' => bcmul($entry->amount, '-1'),
'destination_account_id' => $entry->destination_account_id,
'destination_account_name' =>
intval($entry->destination_account_encrypted) === 1 ? Crypt::decrypt($entry->destination_account_name) : $entry->destination_account_name,
'destination_account_before' => $destinationBalance,
'destination_account_after' => bcadd($destinationBalance, bcmul($entry->amount, '-1')),
];
$transactions[] = $transaction;
}
return $transactions;
}
/**
* Collect the balance of an account before the given transaction has hit. This is tricky, because
* the balance does not depend on the transaction itself but the journal it's part of. And of course
* the order of transactions within the journal. So the query is pretty complex:
*
* @param int $transactionId
*
* @return string
*/
private function getBalance(int $transactionId): string
{
/*
select
-- transactions.*, transaction_journals.date, transaction_journals.order, transaction_journals.id, transactions.identifier
sum(transactions.amount)
from transactions
and (
-- first things first: remove all transaction journals that are newer by selecting only those that are earlier:
or
-- date is 03 but sorted lower: (fucntion 1)
(
transaction_journals.date = "2016-09-20"
and transaction_journals.order > 2)
or
-- date is 03 and sort is the same but id is higher (func 2)
(transaction_journals.date = "2016-09-20"
and transaction_journals.order = 2
and transaction_journals.id < 6966
)
-- date is 03 and sort is the same, and id is the same but identifier is 1 and not 0.(func 3)
or
(transaction_journals.date = "2016-09-20"
and transaction_journals.order = 2
and transaction_journals.id = 6966
and transactions.identifier > 1
)
) -- 14048
and transactions.id != 14048 -- just in case
order by transaction_journals.date DESC, transaction_journals.order ASC, transaction_journals.id DESC, transactions.identifier ASC
*/
// find the transaction first:
$transaction = Transaction::find($transactionId);
$date = $transaction->transactionJournal->date->format('Y-m-d');
$order = intval($transaction->transactionJournal->order);
$journalId = intval($transaction->transaction_journal_id);
$identifier = intval($transaction->identifier);
// go!
$sum
= Transaction
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('account_id', $transaction->account_id)
->whereNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at')
->where('transactions.id', '!=', $transactionId)
->where(
function (Builder $q1) use ($date, $order, $journalId, $identifier) {
$q1->where('transaction_journals.date', '<', $date); // date
$q1->orWhere(
function (Builder $q2) use ($date, $order) { // function 1
$q2->where('transaction_journals.date', $date);
$q2->where('transaction_journals.order', '>', $order);
}
);
$q1->orWhere(
function (Builder $q3) use ($date, $order, $journalId) { // function 2
$q3->where('transaction_journals.date', $date);
$q3->where('transaction_journals.order', $order);
$q3->where('transaction_journals.id', '<', $journalId);
}
);
$q1->orWhere(
function (Builder $q4) use ($date, $order, $journalId, $identifier) { // function 3
$q4->where('transaction_journals.date', $date);
$q4->where('transaction_journals.order', $order);
$q4->where('transaction_journals.id', $journalId);
$q4->where('transactions.identifier', '>', $identifier);
}
);
}
)->sum('transactions.amount');
return strval($sum);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* JournalTaskerInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Repositories\Journal;
use FireflyIII\Models\TransactionJournal;
/**
* Interface JournalTaskerInterface
*
* @package FireflyIII\Repositories\Journal
*/
interface JournalTaskerInterface
{
/**
* Get an overview of the transactions of a journal, tailored to the view
* that shows a transaction (transaction/show/xx).
*
* @param TransactionJournal $journal
*
* @return array
*/
public function getTransactionsOverview(TransactionJournal $journal): array;
}

View File

@@ -29,6 +29,20 @@ use Twig_SimpleFunction;
*/
class Transaction extends Twig_Extension
{
/**
* @return Twig_SimpleFunction
*/
public function formatAmountPlainWithCode(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatAmountPlainWithCode', function (string $amount, string $code): string {
return Amount::formatWithCode($code, $amount, false);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/
@@ -62,11 +76,14 @@ class Transaction extends Twig_Extension
{
$functions = [
$this->formatAmountWithCode(),
$this->formatAmountPlainWithCode(),
$this->transactionSourceAccount(),
$this->transactionDestinationAccount(),
$this->optionalJournalAmount(),
$this->transactionBudgets(),
$this->transactionIdBudgets(),
$this->transactionCategories(),
$this->transactionIdCategories(),
$this->splitJournalIndicator(),
];
@@ -144,22 +161,7 @@ class Transaction extends Twig_Extension
{
return new Twig_SimpleFunction(
'transactionBudgets', function (TransactionModel $transaction): string {
// see if the transaction has a budget:
$budgets = $transaction->budgets()->get();
if ($budgets->count() === 0) {
$budgets = $transaction->transactionJournal()->first()->budgets()->get();
}
if ($budgets->count() > 0) {
$str = [];
foreach ($budgets as $budget) {
$str[] = sprintf('<a href="%s" title="%s">%s</a>', route('budgets.show', [$budget->id]), $budget->name, $budget->name);
}
return join(', ', $str);
}
return '';
return $this->getTransactionBudgets($transaction);
}, ['is_safe' => ['html']]
);
}
@@ -171,21 +173,7 @@ class Transaction extends Twig_Extension
{
return new Twig_SimpleFunction(
'transactionCategories', function (TransactionModel $transaction): string {
// see if the transaction has a category:
$categories = $transaction->categories()->get();
if ($categories->count() === 0) {
$categories = $transaction->transactionJournal()->first()->categories()->get();
}
if ($categories->count() > 0) {
$str = [];
foreach ($categories as $category) {
$str[] = sprintf('<a href="%s" title="%s">%s</a>', route('categories.show', [$category->id]), $category->name, $category->name);
}
return join(', ', $str);
}
return '';
return $this->getTransactionCategories($transaction);
}, ['is_safe' => ['html']]
);
}
@@ -228,6 +216,34 @@ class Transaction extends Twig_Extension
);
}
/**
* @return Twig_SimpleFunction
*/
public function transactionIdBudgets(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'transactionIdBudgets', function (int $transactionId): string {
$transaction = TransactionModel::find($transactionId);
return $this->getTransactionBudgets($transaction);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/
public function transactionIdCategories(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'transactionIdCategories', function (int $transactionId): string {
$transaction = TransactionModel::find($transactionId);
return $this->getTransactionCategories($transaction);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/
@@ -298,4 +314,53 @@ class Transaction extends Twig_Extension
}, ['is_safe' => ['html']]
);
}
/**
* @param TransactionModel $transaction
*
* @return string
*/
private function getTransactionBudgets(TransactionModel $transaction): string
{
// see if the transaction has a budget:
$budgets = $transaction->budgets()->get();
if ($budgets->count() === 0) {
$budgets = $transaction->transactionJournal()->first()->budgets()->get();
}
if ($budgets->count() > 0) {
$str = [];
foreach ($budgets as $budget) {
$str[] = sprintf('<a href="%s" title="%s">%s</a>', route('budgets.show', [$budget->id]), $budget->name, $budget->name);
}
return join(', ', $str);
}
return '';
}
/**
* @param TransactionModel $transaction
*
* @return string
*/
private function getTransactionCategories(TransactionModel $transaction): string
{
// see if the transaction has a category:
$categories = $transaction->categories()->get();
if ($categories->count() === 0) {
$categories = $transaction->transactionJournal()->first()->categories()->get();
}
if ($categories->count() > 0) {
$str = [];
foreach ($categories as $category) {
$str[] = sprintf('<a href="%s" title="%s">%s</a>', route('categories.show', [$category->id]), $category->name, $category->name);
}
return join(', ', $str);
}
return '';
}
}

View File

@@ -712,6 +712,8 @@ return [
'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
'transaction_journal_information' => 'Transaction information',
'transaction_journal_meta' => 'Meta information',
// administration
'administration' => 'Administration',

View File

@@ -72,6 +72,8 @@ return [
'blocked_code' => 'Block code',
'domain' => 'Domain',
'registration_attempts' => 'Registration attempts',
'source_account' => 'Source account',
'destination_account' => 'Destination account',
'accounts_count' => 'Number of accounts',
'journals_count' => 'Number of journals',

View File

@@ -9,86 +9,134 @@
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Metadata</h3>
<h3 class="box-title">{{ 'transaction_journal_information'|_ }}</h3>
</div>
<div class="box-body table-responsive no-padding">
<table class="table table-hover sortable">
<tr>
<td>{{ trans('list.amount') }}</td>
<td>{{ journal|formatJournal }}</td>
</tr>
<tr>
<td>{{ trans('list.date') }}</td>
<td>{{ journal.date.formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% if journal.getMeta('interest_date') %}
<tr>
<td>{{ trans('list.interest_date') }}</td>
<td>{{ journal.getMeta('interest_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.getMeta('book_date') %}
<tr>
<td>{{ trans('list.book_date') }}</td>
<td>{{ journal.getMeta('book_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.getMeta('process_date') %}
<tr>
<td>{{ trans('list.process_date') }}</td>
<td>{{ journal.getMeta('process_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.getMeta('due_date') %}
<tr>
<td>{{ trans('list.due_date') }}</td>
<td>{{ journal.getMeta('due_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.getMeta('payment_date') %}
<tr>
<td>{{ trans('list.payment_date') }}</td>
<td>{{ journal.getMeta('payment_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.getMeta('invoice_date') %}
<tr>
<td>{{ trans('list.invoice_date') }}</td>
<td>{{ journal.getMeta('invoice_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
<table class="table table-hover">
<tbody>
<tr>
<td>{{ trans('list.type') }}</td>
<td>{{ journal.transactiontype.type|_ }}</td>
</tr>
<tr>
<td>{{ trans('list.completed') }}</td>
<td>
{% if journal.completed %}
<span class="text-success">{{ 'yes'|_ }}</span>
{% else %}
<span class="text-danger">{{ 'no'|_ }}</span>
<td>{{ trans('list.description') }}</td>
<td>{{ journal.description }}</td>
</tr>
<!-- source(s) -->
<tr>
<td>{{ 'source_accounts'|_ }}</td>
<td>{{ sourceAccount(journal)|raw }}</td>
</tr>
<!-- destination(s) -->
<tr>
<td>{{ 'destination_accounts'|_ }}</td>
<td>{{ destinationAccount(journal)|raw }}</td>
</tr>
<!-- total amount -->
<tr>
<td>{{ 'total_amount'|_ }}</td>
<td>{{ journal|formatJournal }}</td>
</tr>
<tr>
<td style="width:30%;">{{ trans('list.date') }}</td>
<td>{{ journal.date.formatLocalized(monthAndDayFormat) }}</td>
</tr>
</tbody>
</table>
</div>
<div class="box-footer">
<div class="pull-right">
<a class="btn btn-default" href="{{ route('transactions.edit',journal.id) }}"> {{ 'edit'|_ }}</a>
<a href="{{ route('transactions.delete',journal.id) }}" class="btn btn-danger"> {{ 'delete'|_ }}</a>
</div>
</div>
</div>
<!-- events, if present -->
{% if journal.piggyBankEvents|length > 0 %}
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">{{ 'piggyBanks'|_ }}</h3>
</div>
<div class="box-body table-responsive no-padding">
{% include 'list/piggy-bank-events' with {'events': events, 'showPiggyBank':true} %}
</div>
</div>
{% endif %}
</td>
</tr>
{% for budget in journal.budgets %}
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">{{ 'transaction_journal_meta'|_ }}</h3>
</div>
<div class="box-body table-responsive no-padding">
<table class="table table-hover">
<tbody>
<tr>
<td>{{ 'budget'|_ }}</td>
<td><a href="{{ route('budgets.show',budget.id) }}">{{ budget.name }}</a></td>
<td>{{ 'categories'|_ }}</td>
<td>{{ journalCategories(journal)|raw }}</td>
</tr>
{% endfor %}
{% for category in journal.categories %}
<tr>
<td>{{ 'category'|_ }}</td>
<td><a href="{{ route('categories.show',category.id) }}">{{ category.name }}</a></td>
<td>{{ 'budgets'|_ }}</td>
<td>{{ journalBudgets(journal)|raw }}</td>
</tr>
{% endfor %}
{% if journal.hasMeta('book_date') %}
<tr>
<td>{{ trans('list.book_date') }}</td>
<td>{{ journal.getMeta('book_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('process_date') %}
<tr>
<td>{{ trans('list.process_date') }}</td>
<td>{{ journal.getMeta('process_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('interest_date') %}
<tr>
<td>{{ trans('list.interest_date') }}</td>
<td>{{ journal.getMeta('interest_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('due_date') %}
<tr>
<td>{{ trans('list.due_date') }}</td>
<td>{{ journal.getMeta('due_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('payment_date') %}
<tr>
<td>{{ trans('list.payment_date') }}</td>
<td>{{ journal.getMeta('payment_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('invoice_date') %}
<tr>
<td>{{ trans('list.invoice_date') }}</td>
<td>{{ journal.getMeta('invoice_date').formatLocalized(monthAndDayFormat) }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('internal_reference') %}
<tr>
<td>{{ trans('list.internal_reference') }}</td>
<td>{{ journal.getMeta('internal_reference') }}</td>
</tr>
{% endif %}
{% if journal.hasMeta('notes') %}
<tr>
<td>{{ trans('list.notes') }}</td>
<td>{{ journal.getMeta('notes')|nl2br }}</td>
</tr>
{% endif %}
{% if journal.bill %}
<tr>
<td>{{ 'bill'|_ }}</td>
@@ -117,32 +165,12 @@
</td>
</tr>
{% endif %}
{% if journal.getMeta('internal_reference') %}
<tr>
<td>{{ trans('list.interal_reference') }}</td>
<td>{{ journal.getMeta('internal_reference') }}</td>
</tr>
{% endif %}
{% if journal.getMeta('notes') %}
<tr>
<td>{{ trans('list.notes') }}</td>
<td>{{ journal.getMeta('notes')|nl2br }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="box-footer">
<div class="pull-right">
<a class="btn btn-default" href="{{ route('transactions.edit',journal.id) }}">{{ 'edit'|_ }}</a>
<a href="{{ route('transactions.delete',journal.id) }}" class="btn btn-danger">{{ 'delete'|_ }}</a>
</div>
</div>
</div>
<!-- attachments for unsplitted journals -->
{% if journal.attachments|length > 0 %}
<div class="box">
<div class="box-header with-border">
@@ -182,60 +210,103 @@
</div>
</div>
{% endif %}
</div>
</div>
<!-- more than two transactions-->
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<!-- events, if present -->
{% if journal.piggyBankEvents|length > 0 %}
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">{{ 'piggyBanks'|_ }}</h3>
</div>
<div class="box-body">
{% include 'list/piggy-bank-events' with {'events': events, 'showPiggyBank':true} %}
</div>
</div>
{% endif %}
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
{% for t in transactions %}
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">{{ t.account.name }}</h3>
<h3 class="box-title">Transactions</h3>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<td style="width:30%;">{{ 'account'|_ }}</td>
<td><a href="{{ route('accounts.show',t.account.id) }}">{{ t.account.name }}</a></td>
<th>{{ trans('list.description') }}</th>
<th>{{ trans('list.source_account') }}</th>
<th>&#916;</th>
<th>{{ trans('list.destination_account') }}</th>
<th>&#916;</th>
<th>{{ trans('list.amount') }}</th>
<th>{{ trans('list.budget') }}</th>
<th>{{ trans('list.category') }}</th>
</tr>
</thead>
<tbody>
{% for transaction in transactions %}
<tr>
<td>{{ 'account_type'|_ }}</td>
<td>{{ t.account.accounttype.type|_ }}</td>
</tr>
<tr>
<td>{{ 'balance'|_ }}</td>
<td>{{ t.before|formatAmount }} &rarr; {{ (t.before+t.amount)|formatAmount }}</td>
</tr>
{% if t.description %}
<tr>
<td>{{ trans('form.description') }}</td>
<td>{{ t.description }}</td>
</tr>
<td>#{{ transaction.source_id }}
{% if transaction.description == "" %}
{{ journal.description }}
{% else %}
{{ transaction.description }}
{% endif %}
<tr>
<td>{{ 'category'|_ }}</td>
</td>
<td>
{{ transactionCategories(t)|raw }}
<a href="{{ route('accounts.show', transaction.source_account_id) }}">{{ transaction.source_account_name }}</a>
</td>
<td>
{{ formatAmountWithCode(transaction.source_account_before,journal.transactionCurrency.code) }}
&longrightarrow; {{ formatAmountWithCode(transaction.source_account_after,journal.transactionCurrency.code) }}
</td>
<td>
<a href="{{ route('accounts.show', transaction.destination_account_id) }}">{{ transaction.destination_account_name }}</a>
</td>
<td>
{{ formatAmountWithCode(transaction.destination_account_before,journal.transactionCurrency.code) }}
&longrightarrow; {{ formatAmountWithCode(transaction.destination_account_after,journal.transactionCurrency.code) }}
</td>
<td>
{% if journal.transactiontype.type == 'Deposit' %}
<!-- deposit, positive amount with correct currency -->
{{ formatAmountWithCode(transaction.destination_amount, journal.transactionCurrency.code) }}
{% endif %}
{% if journal.transactiontype.type == 'Withdrawal' %}
<!-- withdrawal, negative amount with correct currency -->
{{ formatAmountWithCode(transaction.source_amount, journal.transactionCurrency.code) }}
{% endif %}
{% if journal.transactiontype.type == 'Transfer' %}
<!-- transfer, positive amount in blue -->
<span class="text-info">{{ formatAmountPlainWithCode(transaction.destination_amount, journal.transactionCurrency.code) }}</span>
{% endif %}
</td>
<td>
{{ transactionIdBudgets(transaction.source_id) }}
</td>
<td>
{{ transactionIdCategories(transaction.source_id) }}
</td>
</tr>
{#
<tr>
<td>{{ 'budget'|_ }}</td>
<td>
{% if (index+1) != transactions|length or what == 'transfer' %}
{{ t.description }}
{% endif %}
</td>
<td><a href="{{ route('accounts.show',t.account.id) }}">{{ t.account.name }}</a> ({{ t.account.accounttype.type|_ }})</td>
<td>{{ t.sum|formatAmount }}</td>
<td>{{ t.before|formatAmount }} &rarr; {{ (t.sum+t.before)|formatAmount }}</td>
<td>
{% if (index+1) != transactions|length or what == 'transfer' %}
{{ transactionBudgets(t)|raw }}
{% endif %}
</td>
</tr>
<td>
{% if (index+1) != transactions|length or what == 'transfer' %}
{{ transactionCategories(t)|raw }}
{% endif %}
</td>
#}
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
</div>
<!-- end -->
{% endblock %}