Big update to properly support multi currencies.

This commit is contained in:
James Cole 2017-06-04 13:39:16 +02:00
parent 771ebde295
commit 82e74a2afd
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
34 changed files with 470 additions and 498 deletions

View File

@ -19,6 +19,7 @@ use FireflyIII\Http\Requests\MassDeleteJournalRequest;
use FireflyIII\Http\Requests\MassEditJournalRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
@ -126,8 +127,7 @@ class MassController extends Controller
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgets = $budgetRepository->getBudgets();
// skip transactions that have multiple destinations
// or multiple sources:
// skip transactions that have multiple destinations, multiple sources or are an opening balance.
$filtered = new Collection;
$messages = [];
/**
@ -146,6 +146,10 @@ class MassController extends Controller
$messages[] = trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]);
continue;
}
if ($journal->transactionType->type === TransactionType::OPENING_BALANCE) {
$messages[] = trans('firefly.cannot_edit_opening_balance');
continue;
}
$filtered->push($journal);
}
@ -158,13 +162,21 @@ class MassController extends Controller
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'mass-edit');
// set some values to be used in the edit routine:
// collect some useful meta data for the mass edit:
$filtered->each(
function (TransactionJournal $journal) {
$journal->amount = $journal->amountPositive();
$sources = $journal->sourceAccountList();
$destinations = $journal->destinationAccountList();
$journal->transaction_count = $journal->transactions()->count();
$transaction = $journal->positiveTransaction();
$currency = $transaction->transactionCurrency;
$journal->amount = floatval($transaction->amount);
$sources = $journal->sourceAccountList();
$destinations = $journal->destinationAccountList();
$journal->transaction_count = $journal->transactions()->count();
$journal->currency_symbol = $currency->symbol;
$journal->transaction_type_type = $journal->transactionType->type;
$journal->foreign_amount = floatval($transaction->foreign_amount);
$journal->foreign_currency = $transaction->foreignCurrency;
if (!is_null($sources->first())) {
$journal->source_account_id = $sources->first()->id;
$journal->source_account_name = $sources->first()->editname;
@ -195,6 +207,7 @@ class MassController extends Controller
{
$journalIds = $request->get('journals');
$count = 0;
if (is_array($journalIds)) {
foreach ($journalIds as $journalId) {
$journal = $repository->find(intval($journalId));
@ -208,6 +221,10 @@ class MassController extends Controller
$budgetId = $request->get('budget_id')[$journal->id] ?? 0;
$category = $request->get('category')[$journal->id];
$tags = $journal->tags->pluck('tag')->toArray();
$amount = round($request->get('amount')[$journal->id], 12);
$foreignAmount = isset($request->get('foreign_amount')[$journal->id]) ? round($request->get('foreign_amount')[$journal->id], 12) : null;
$foreignCurrencyId = isset($request->get('foreign_currency_id')[$journal->id]) ?
intval($request->get('foreign_currency_id')[$journal->id]) : null;
// build data array
$data = [
@ -218,16 +235,20 @@ class MassController extends Controller
'source_account_name' => $sourceAccountName,
'destination_account_id' => intval($destAccountId),
'destination_account_name' => $destAccountName,
'amount' => round($request->get('amount')[$journal->id], 12),
'currency_id' => $journal->transaction_currency_id,
'amount' => $foreignAmount,
'native_amount' => $amount,
'source_amount' => $amount,
'date' => new Carbon($request->get('date')[$journal->id]),
'interest_date' => $journal->interest_date,
'book_date' => $journal->book_date,
'process_date' => $journal->process_date,
'budget_id' => intval($budgetId),
'currency_id' => $foreignCurrencyId,
'foreign_amount' => $foreignAmount,
'destination_amount' => $foreignAmount,
//'foreign_currency_id' => $foreignCurrencyId,
'category' => $category,
'tags' => $tags,
];
// call repository update function.
$repository->update($journal, $data);
@ -235,6 +256,7 @@ class MassController extends Controller
$count++;
}
}
}
Preferences::mark();
Session::flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count]));

View File

@ -238,6 +238,7 @@ class SingleController extends Controller
$sourceAccounts = $journal->sourceAccountList();
$destinationAccounts = $journal->destinationAccountList();
$optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$pTransaction = $journal->positiveTransaction();
$preFilled = [
'date' => $journal->dateAsString(),
'interest_date' => $journal->dateAsString('interest_date'),
@ -250,8 +251,6 @@ class SingleController extends Controller
'source_account_name' => $sourceAccounts->first()->edit_name,
'destination_account_id' => $destinationAccounts->first()->id,
'destination_account_name' => $destinationAccounts->first()->edit_name,
'amount' => $journal->amountPositive(),
'currency' => $journal->transactionCurrency,
// new custom fields:
'due_date' => $journal->dateAsString('due_date'),
@ -260,26 +259,36 @@ class SingleController extends Controller
'interal_reference' => $journal->getMeta('internal_reference'),
'notes' => $journal->getMeta('notes'),
// exchange rate fields
'native_amount' => $journal->amountPositive(),
'native_currency' => $journal->transactionCurrency,
// amount fields
'amount' => $pTransaction->amount,
'source_amount' => $pTransaction->amount,
'native_amount' => $pTransaction->amount,
'destination_amount' => $pTransaction->foreign_amount,
'currency' => $pTransaction->transactionCurrency,
'source_currency' => $pTransaction->transactionCurrency,
'native_currency' => $pTransaction->transactionCurrency,
'foreign_currency' => !is_null($pTransaction->foreignCurrency) ? $pTransaction->foreignCurrency : $pTransaction->transactionCurrency,
'destination_currency' => !is_null($pTransaction->foreignCurrency) ? $pTransaction->foreignCurrency : $pTransaction->transactionCurrency,
];
// if user has entered a foreign currency, update some fields
$foreignCurrencyId = intval($journal->getMeta('foreign_currency_id'));
if ($foreignCurrencyId > 0) {
// update some fields in pre-filled.
// @codeCoverageIgnoreStart
$preFilled['amount'] = $journal->getMeta('foreign_amount');
$preFilled['currency'] = $this->currency->find(intval($journal->getMeta('foreign_currency_id')));
// @codeCoverageIgnoreEnd
// amounts for withdrawals and deposits:
// (amount, native_amount, source_amount, destination_amount)
if (($journal->isWithdrawal() || $journal->isDeposit()) && !is_null($pTransaction->foreign_amount)) {
$preFilled['amount'] = $pTransaction->foreign_amount;
$preFilled['currency'] = $pTransaction->foreignCurrency;
}
if ($journal->isWithdrawal() && $destinationAccounts->first()->accountType->type == AccountType::CASH) {
if ($journal->isTransfer() && !is_null($pTransaction->foreign_amount)) {
$preFilled['destination_amount'] = $pTransaction->foreign_amount;
$preFilled['destination_currency'] = $pTransaction->foreignCurrency;
}
// fixes for cash accounts:
if ($journal->isWithdrawal() && $destinationAccounts->first()->accountType->type === AccountType::CASH) {
$preFilled['destination_account_name'] = '';
}
if ($journal->isDeposit() && $sourceAccounts->first()->accountType->type == AccountType::CASH) {
if ($journal->isDeposit() && $sourceAccounts->first()->accountType->type === AccountType::CASH) {
$preFilled['source_account_name'] = '';
}
@ -319,6 +328,7 @@ class SingleController extends Controller
return redirect(route('transactions.create', [$request->input('what')]))->withInput();
}
/** @var array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
$this->attachments->saveAttachmentsForModel($journal, $files);

View File

@ -93,7 +93,7 @@ class SplitController extends Controller
}
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
$currencies = ExpandedForm::makeSelectList($this->currencies->get());
$currencies = $this->currencies->get();
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
$optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
@ -130,7 +130,6 @@ class SplitController extends Controller
*/
public function update(Request $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{
if ($this->isOpeningBalance($journal)) {
return $this->redirectToAccount($journal);
}
@ -179,7 +178,6 @@ class SplitController extends Controller
'journal_source_account_id' => $request->get('journal_source_account_id'),
'journal_source_account_name' => $request->get('journal_source_account_name'),
'journal_destination_account_id' => $request->get('journal_destination_account_id'),
'currency_id' => $request->get('currency_id'),
'what' => $request->get('what'),
'date' => $request->get('date'),
// all custom fields:
@ -218,7 +216,6 @@ class SplitController extends Controller
'journal_source_account_id' => $request->old('journal_source_account_id', $sourceAccounts->first()->id),
'journal_source_account_name' => $request->old('journal_source_account_name', $sourceAccounts->first()->name),
'journal_destination_account_id' => $request->old('journal_destination_account_id', $destinationAccounts->first()->id),
'currency_id' => $request->old('currency_id', $journal->transaction_currency_id),
'destinationAccounts' => $destinationAccounts,
'what' => strtolower($journal->transactionTypeStr()),
'date' => $request->old('date', $journal->date),
@ -253,14 +250,22 @@ class SplitController extends Controller
/** @var array $transaction */
foreach ($transactions as $index => $transaction) {
$set = [
'description' => $transaction['description'],
'source_account_id' => $transaction['source_account_id'],
'source_account_name' => $transaction['source_account_name'],
'destination_account_id' => $transaction['destination_account_id'],
'destination_account_name' => $transaction['destination_account_name'],
'amount' => round($transaction['destination_amount'], 12),
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
'category' => $transaction['category'],
'description' => $transaction['description'],
'source_account_id' => $transaction['source_account_id'],
'source_account_name' => $transaction['source_account_name'],
'destination_account_id' => $transaction['destination_account_id'],
'destination_account_name' => $transaction['destination_account_name'],
'amount' => round($transaction['destination_amount'], 12),
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
'category' => $transaction['category'],
'transaction_currency_id' => $transaction['transaction_currency_id'],
'transaction_currency_code' => $transaction['transaction_currency_code'],
'transaction_currency_symbol' => $transaction['transaction_currency_symbol'],
'foreign_amount' => round($transaction['foreign_destination_amount'], 12),
'foreign_currency_id' => $transaction['foreign_currency_id'],
'foreign_currency_code' => $transaction['foreign_currency_code'],
'foreign_currency_symbol' => $transaction['foreign_currency_symbol'],
];
// set initial category and/or budget:
@ -294,8 +299,12 @@ class SplitController extends Controller
'destination_account_id' => $transaction['destination_account_id'] ?? 0,
'destination_account_name' => $transaction['destination_account_name'] ?? '',
'amount' => round($transaction['amount'] ?? 0, 12),
'foreign_amount' => !isset($transaction['foreign_amount']) ? null : round($transaction['foreign_amount'] ?? 0, 12),
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
'category' => $transaction['category'] ?? '',
'transaction_currency_id' => intval($transaction['transaction_currency_id']),
'foreign_currency_id' => $transaction['foreign_currency_id'] ?? null,
];
}
Log::debug(sprintf('Found %d splits in request data.', count($return)));

View File

@ -183,17 +183,8 @@ class TransactionController extends Controller
$transactions = $tasker->getTransactionsOverview($journal);
$what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
$subTitle = trans('firefly.' . $what) . ' "' . e($journal->description) . '"';
$foreignCurrency = null;
if ($journal->hasMeta('foreign_currency_id')) {
// @codeCoverageIgnoreStart
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$foreignCurrency = $repository->find(intval($journal->getMeta('foreign_currency_id')));
// @codeCoverageIgnoreEnd
}
return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions', 'foreignCurrency'));
return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions'));
}

View File

@ -291,6 +291,7 @@ class ImportStorage
'user_id' => $entry->user->id,
'transaction_type_id' => $entry->fields['transaction-type']->id,
'bill_id' => $billId,
// TODO update this transaction currency reference.
'transaction_currency_id' => $entry->fields['currency']->id,
'description' => $entry->fields['description'],
'date' => $entry->fields['date-transaction'],

View File

@ -74,6 +74,7 @@ class ImportValidator
$entry = $this->setOpposingAccount($entry);
$entry = $this->cleanDescription($entry);
$entry = $this->setTransactionType($entry);
// TODO update this transaction currency reference.
$entry = $this->setTransactionCurrency($entry);
$newCollection->put($index, $entry);
@ -383,6 +384,7 @@ class ImportValidator
*/
private function setTransactionCurrency(ImportEntry $entry): ImportEntry
{
// TODO update this transaction currency reference.
if (is_null($entry->fields['currency'])) {
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);

View File

@ -26,7 +26,6 @@ use Watson\Validating\ValidatingTrait;
*/
class Transaction extends Model
{
/**
* The attributes that should be casted to native types.
*
@ -42,16 +41,18 @@ class Transaction extends Model
'bill_name_encrypted' => 'boolean',
];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount', 'identifier'];
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount', 'identifier', 'transaction_currency_id', 'foreign_currency_id','foreign_amount'];
protected $hidden = ['encrypted'];
protected $rules
= [
'account_id' => 'required|exists:accounts,id',
'transaction_journal_id' => 'required|exists:transaction_journals,id',
'description' => 'between:0,1024',
'amount' => 'required|numeric',
'account_id' => 'required|exists:accounts,id',
'transaction_journal_id' => 'required|exists:transaction_journals,id',
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
//'foreign_currency_id' => 'exists:transaction_currencies,id',
'description' => 'between:0,1024',
'amount' => 'required|numeric',
//'foreign_amount' => 'numeric',
];
use SoftDeletes, ValidatingTrait;
/**
* @param Builder $query
@ -74,6 +75,8 @@ class Transaction extends Model
return false;
}
use SoftDeletes, ValidatingTrait;
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -160,6 +163,22 @@ class Transaction extends Model
$this->attributes['amount'] = strval(round($value, 12));
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionCurrency()
{
return $this->belongsTo('FireflyIII\Models\TransactionCurrency');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function foreignCurrency()
{
return $this->belongsTo('FireflyIII\Models\TransactionCurrency','foreign_currency_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@ -68,7 +68,6 @@ class TransactionJournal extends Model
= [
'user_id' => 'required|exists:users,id',
'transaction_type_id' => 'required|exists:transaction_types,id',
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
'description' => 'required|between:1,1024',
'completed' => 'required|boolean',
'date' => 'required|date',
@ -299,46 +298,6 @@ class TransactionJournal extends Model
return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00'));
}
/**
* @param EloquentBuilder $query
*/
public function scopeExpanded(EloquentBuilder $query)
{
// left join transaction type:
if (!self::isJoined($query, 'transaction_types')) {
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
}
// left join transaction currency:
$query->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id');
// extend group by:
$query->groupBy(
[
'transaction_journals.id',
'transaction_journals.created_at',
'transaction_journals.updated_at',
'transaction_journals.deleted_at',
'transaction_journals.user_id',
'transaction_journals.transaction_type_id',
'transaction_journals.bill_id',
'transaction_journals.transaction_currency_id',
'transaction_journals.description',
'transaction_journals.date',
'transaction_journals.interest_date',
'transaction_journals.book_date',
'transaction_journals.process_date',
'transaction_journals.order',
'transaction_journals.tag_count',
'transaction_journals.encrypted',
'transaction_journals.completed',
'transaction_types.type',
'transaction_currencies.code',
]
);
$query->with(['categories', 'budgets', 'attachments', 'bill', 'transactions']);
}
/**
* @param EloquentBuilder $query
*/

View File

@ -44,6 +44,7 @@ use FireflyIII\Support\Navigation;
use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam;
use FireflyIII\Support\Twig\Account;
use FireflyIII\Support\Twig\AmountFormat;
use FireflyIII\Support\Twig\General;
use FireflyIII\Support\Twig\Journal;
use FireflyIII\Support\Twig\PiggyBank;
@ -79,7 +80,7 @@ class FireflyServiceProvider extends ServiceProvider
Twig::addExtension(new Translation);
Twig::addExtension(new Transaction);
Twig::addExtension(new Rule);
Twig::addExtension(new Account);
Twig::addExtension(new AmountFormat);
}
/**

View File

@ -481,6 +481,7 @@ class AccountRepository implements AccountRepositoryInterface
[
'user_id' => $this->user->id,
'transaction_type_id' => $transactionType->id,
// TODO update this transaction currency reference.
'transaction_currency_id' => $currencyId,
'description' => 'Initial balance for "' . $account->name . '"',
'completed' => true,
@ -622,6 +623,7 @@ class AccountRepository implements AccountRepositoryInterface
// update date:
$journal->date = $date;
// TODO update this transaction currency reference.
$journal->transaction_currency_id = $currencyId;
$journal->save();
// update transactions:

View File

@ -39,7 +39,6 @@ class JournalRepository implements JournalRepositoryInterface
{
/** @var User */
private $user;
/** @var array */
private $validMetaFields
= ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', 'internal_reference', 'notes', 'foreign_amount',
@ -182,13 +181,12 @@ class JournalRepository implements JournalRepositoryInterface
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
$accounts = $this->storeAccounts($transactionType, $data);
$data = $this->verifyNativeAmount($data, $accounts);
$currencyId = $data['currency_id'];
$amount = strval($data['amount']);
$journal = new TransactionJournal(
[
'user_id' => $this->user->id,
'transaction_type_id' => $transactionType->id,
'transaction_currency_id' => $currencyId,
'transaction_currency_id' => $data['currency_id'], // no longer used.
'description' => $data['description'],
'completed' => 0,
'date' => $data['date'],
@ -200,27 +198,32 @@ class JournalRepository implements JournalRepositoryInterface
$this->storeCategoryWithJournal($journal, $data['category']);
$this->storeBudgetWithJournal($journal, $data['budget_id']);
// store two transactions:
$one = [
'journal' => $journal,
'account' => $accounts['source'],
'amount' => bcmul($amount, '-1'),
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
'journal' => $journal,
'account' => $accounts['source'],
'amount' => bcmul($amount, '-1'),
'transaction_currency_id' => $data['currency_id'],
'foreign_amount' => is_null($data['foreign_amount']) ? null : bcmul(strval($data['foreign_amount']), '-1'),
'foreign_currency_id' => $data['foreign_currency_id'],
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
];
$this->storeTransaction($one);
$two = [
'journal' => $journal,
'account' => $accounts['destination'],
'amount' => $amount,
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
'journal' => $journal,
'account' => $accounts['destination'],
'amount' => $amount,
'transaction_currency_id' => $data['currency_id'],
'foreign_amount' => $data['foreign_amount'],
'foreign_currency_id' => $data['foreign_currency_id'],
'description' => null,
'category' => null,
'budget' => null,
'identifier' => 0,
];
$this->storeTransaction($two);
@ -256,11 +259,14 @@ class JournalRepository implements JournalRepositoryInterface
{
// update actual journal:
$journal->description = $data['description'];
$journal->date = $data['date'];
$accounts = $this->storeAccounts($journal->transactionType, $data);
$data = $this->verifyNativeAmount($data, $accounts);
$amount = strval($data['amount']);
$journal->description = $data['description'];
$journal->date = $data['date'];
$accounts = $this->storeAccounts($journal->transactionType, $data);
$data = $this->verifyNativeAmount($data, $accounts);
$data['amount'] = strval($data['amount']);
$data['foreign_amount'] = is_null($data['foreign_amount']) ? null : strval($data['foreign_amount']);
var_dump($data);
// unlink all categories, recreate them:
$journal->categories()->detach();
@ -269,9 +275,11 @@ class JournalRepository implements JournalRepositoryInterface
$this->storeCategoryWithJournal($journal, $data['category']);
$this->storeBudgetWithJournal($journal, $data['budget_id']);
// negative because source loses money.
$this->updateSourceTransaction($journal, $accounts['source'], $data);
$this->updateSourceTransaction($journal, $accounts['source'], bcmul($amount, '-1')); // negative because source loses money.
$this->updateDestinationTransaction($journal, $accounts['destination'], $amount); // positive because destination gets money.
// positive because destination gets money.
$this->updateDestinationTransaction($journal, $accounts['destination'], $data);
$journal->save();
@ -308,9 +316,8 @@ class JournalRepository implements JournalRepositoryInterface
public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal
{
// update actual journal:
$journal->transaction_currency_id = $data['currency_id'];
$journal->description = $data['journal_description'];
$journal->date = $data['date'];
$journal->description = $data['journal_description'];
$journal->date = $data['date'];
$journal->save();
Log::debug(sprintf('Updated split journal #%d', $journal->id));
@ -342,6 +349,7 @@ class JournalRepository implements JournalRepositoryInterface
// store each transaction.
$identifier = 0;
Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions'])));
foreach ($data['transactions'] as $transaction) {
Log::debug(sprintf('Split journal update split transaction %d', $identifier));
$transaction = $this->appendTransactionData($transaction, $data);
@ -564,30 +572,40 @@ class JournalRepository implements JournalRepositoryInterface
$accounts = $this->storeAccounts($journal->transactionType, $transaction);
// store transaction one way:
$one = $this->storeTransaction(
$amount = bcmul(strval($transaction['amount']), '-1');
$foreignAmount = is_null($transaction['foreign_amount']) ? null : bcmul(strval($transaction['foreign_amount']), '-1');
$one = $this->storeTransaction(
[
'journal' => $journal,
'account' => $accounts['source'],
'amount' => bcmul(strval($transaction['amount']), '-1'),
'description' => $transaction['description'],
'category' => null,
'budget' => null,
'identifier' => $identifier,
'journal' => $journal,
'account' => $accounts['source'],
'amount' => $amount,
'transaction_currency_id' => $transaction['transaction_currency_id'],
'foreign_amount' => $foreignAmount,
'foreign_currency_id' => $transaction['foreign_currency_id'],
'description' => $transaction['description'],
'category' => null,
'budget' => null,
'identifier' => $identifier,
]
);
$this->storeCategoryWithTransaction($one, $transaction['category']);
$this->storeBudgetWithTransaction($one, $transaction['budget_id']);
// and the other way:
$two = $this->storeTransaction(
$amount = strval($transaction['amount']);
$foreignAmount = is_null($transaction['foreign_amount']) ? null : strval($transaction['foreign_amount']);
$two = $this->storeTransaction(
[
'journal' => $journal,
'account' => $accounts['destination'],
'amount' => strval($transaction['amount']),
'description' => $transaction['description'],
'category' => null,
'budget' => null,
'identifier' => $identifier,
'journal' => $journal,
'account' => $accounts['destination'],
'amount' => $amount,
'transaction_currency_id' => $transaction['transaction_currency_id'],
'foreign_amount' => $foreignAmount,
'foreign_currency_id' => $transaction['foreign_currency_id'],
'description' => $transaction['description'],
'category' => null,
'budget' => null,
'identifier' => $identifier,
]
);
$this->storeCategoryWithTransaction($two, $transaction['category']);
@ -603,16 +621,27 @@ class JournalRepository implements JournalRepositoryInterface
*/
private function storeTransaction(array $data): Transaction
{
$fields = [
'transaction_journal_id' => $data['journal']->id,
'account_id' => $data['account']->id,
'amount' => $data['amount'],
'foreign_amount' => $data['foreign_amount'],
'transaction_currency_id' => $data['transaction_currency_id'],
'foreign_currency_id' => $data['foreign_currency_id'],
'description' => $data['description'],
'identifier' => $data['identifier'],
];
if (is_null($data['foreign_currency_id'])) {
unset($fields['foreign_currency_id']);
}
if (is_null($data['foreign_amount'])) {
unset($fields['foreign_amount']);
}
/** @var Transaction $transaction */
$transaction = Transaction::create(
[
'transaction_journal_id' => $data['journal']->id,
'account_id' => $data['account']->id,
'amount' => $data['amount'],
'description' => $data['description'],
'identifier' => $data['identifier'],
]
);
$transaction = Transaction::create($fields);
Log::debug(sprintf('Transaction stored with ID: %s', $transaction->id));
@ -675,22 +704,23 @@ class JournalRepository implements JournalRepositoryInterface
/**
* @param TransactionJournal $journal
* @param Account $account
* @param string $amount
* @param array $data
*
* @throws FireflyException
*/
private function updateDestinationTransaction(TransactionJournal $journal, Account $account, string $amount)
private function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data)
{
// should be one:
$set = $journal->transactions()->where('amount', '>', 0)->get();
if ($set->count() != 1) {
throw new FireflyException(
sprintf('Journal #%d has an unexpected (%d) amount of transactions with an amount more than zero.', $journal->id, $set->count())
);
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
}
/** @var Transaction $transaction */
$transaction = $set->first();
$transaction->amount = $amount;
$transaction = $set->first();
$transaction->amount = app('steam')->positive($data['amount']);
$transaction->transaction_currency_id = $data['currency_id'];
$transaction->foreign_amount = is_null($data['foreign_amount']) ? null : app('steam')->positive($data['foreign_amount']);
$transaction->foreign_currency_id = $data['foreign_currency_id'];
$transaction->account_id = $account->id;
$transaction->save();
@ -699,26 +729,24 @@ class JournalRepository implements JournalRepositoryInterface
/**
* @param TransactionJournal $journal
* @param Account $account
* @param string $amount
* @param array $data
*
* @throws FireflyException
*/
private function updateSourceTransaction(TransactionJournal $journal, Account $account, string $amount)
private function updateSourceTransaction(TransactionJournal $journal, Account $account, array $data)
{
// should be one:
$set = $journal->transactions()->where('amount', '<', 0)->get();
if ($set->count() != 1) {
throw new FireflyException(
sprintf('Journal #%d has an unexpected (%d) amount of transactions with an amount less than zero.', $journal->id, $set->count())
);
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
}
/** @var Transaction $transaction */
$transaction = $set->first();
$transaction->amount = $amount;
$transaction->account_id = $account->id;
$transaction = $set->first();
$transaction->amount = bcmul(app('steam')->positive($data['amount']), '-1');
$transaction->transaction_currency_id = $data['currency_id'];
$transaction->foreign_amount = is_null($data['foreign_amount']) ? null : bcmul(app('steam')->positive($data['foreign_amount']), '-1');
$transaction->foreign_currency_id = $data['foreign_currency_id'];
$transaction->save();
}
/**
@ -777,8 +805,10 @@ class JournalRepository implements JournalRepositoryInterface
private function verifyNativeAmount(array $data, array $accounts): array
{
/** @var TransactionType $transactionType */
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
$submittedCurrencyId = $data['currency_id'];
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
$submittedCurrencyId = $data['currency_id'];
$data['foreign_amount'] = null;
$data['foreign_currency_id'] = null;
// which account to check for what the native currency is?
$check = 'source';
@ -803,11 +833,17 @@ class JournalRepository implements JournalRepositoryInterface
}
break;
case TransactionType::TRANSFER:
// source gets the original amount.
$data['amount'] = strval($data['source_amount']);
$data['currency_id'] = intval($accounts['source']->getMeta('currency_id'));
$data['foreign_amount'] = strval($data['destination_amount']);
$data['foreign_currency_id'] = intval($accounts['destination']->getMeta('currency_id'));
$sourceCurrencyId = intval($accounts['source']->getMeta('currency_id'));
$destinationCurrencyId = intval($accounts['destination']->getMeta('currency_id'));
$data['amount'] = strval($data['source_amount']);
$data['currency_id'] = intval($accounts['source']->getMeta('currency_id'));
if ($sourceCurrencyId !== $destinationCurrencyId) {
// accounts have different id's, save this info:
$data['foreign_amount'] = strval($data['destination_amount']);
$data['foreign_currency_id'] = $destinationCurrencyId;
}
break;
default:
throw new FireflyException(sprintf('Cannot handle %s in verifyNativeAmount()', $transactionType->type));

View File

@ -81,6 +81,8 @@ class JournalTasker implements JournalTaskerInterface
->leftJoin('account_types as source_account_types', 'source_accounts.account_type_id', '=', 'source_account_types.id')
->leftJoin('accounts as destination_accounts', 'destination.account_id', '=', 'destination_accounts.id')
->leftJoin('account_types as destination_account_types', 'destination_accounts.account_type_id', '=', 'destination_account_types.id')
->leftJoin('transaction_currencies as native_currencies', 'transactions.transaction_currency_id', '=', 'native_currencies.id')
->leftJoin('transaction_currencies as foreign_currencies', 'transactions.foreign_currency_id', '=', 'foreign_currencies.id')
->where('transactions.amount', '<', 0)
->whereNull('transactions.deleted_at')
->get(
@ -91,12 +93,21 @@ class JournalTasker implements JournalTaskerInterface
'source_accounts.encrypted as account_encrypted',
'source_account_types.type as account_type',
'transactions.amount',
'transactions.foreign_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',
'destination_account_types.type as destination_account_type',
'native_currencies.id as transaction_currency_id',
'native_currencies.code as transaction_currency_code',
'native_currencies.symbol as transaction_currency_symbol',
'foreign_currencies.id as foreign_currency_id',
'foreign_currencies.code as foreign_currency_code',
'foreign_currencies.symbol as foreign_currency_symbol',
]
);
@ -109,23 +120,31 @@ class JournalTasker implements JournalTaskerInterface
$budget = $entry->budgets->first();
$category = $entry->categories->first();
$transaction = [
'source_id' => $entry->id,
'source_amount' => $entry->amount,
'description' => $entry->description,
'source_account_id' => $entry->account_id,
'source_account_name' => Steam::decrypt(intval($entry->account_encrypted), $entry->account_name),
'source_account_type' => $entry->account_type,
'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_type' => $entry->destination_account_type,
'destination_account_name' => Steam::decrypt(intval($entry->destination_account_encrypted), $entry->destination_account_name),
'destination_account_before' => $destinationBalance,
'destination_account_after' => bcadd($destinationBalance, bcmul($entry->amount, '-1')),
'budget_id' => is_null($budget) ? 0 : $budget->id,
'category' => is_null($category) ? '' : $category->name,
'source_id' => $entry->id,
'source_amount' => $entry->amount,
'foreign_source_amount' => $entry->foreign_amount,
'description' => $entry->description,
'source_account_id' => $entry->account_id,
'source_account_name' => Steam::decrypt(intval($entry->account_encrypted), $entry->account_name),
'source_account_type' => $entry->account_type,
'source_account_before' => $sourceBalance,
'source_account_after' => bcadd($sourceBalance, $entry->amount),
'destination_id' => $entry->destination_id,
'destination_amount' => bcmul($entry->amount, '-1'),
'foreign_destination_amount' => is_null($entry->foreign_amount) ? null : bcmul($entry->foreign_amount, '-1'),
'destination_account_id' => $entry->destination_account_id,
'destination_account_type' => $entry->destination_account_type,
'destination_account_name' => Steam::decrypt(intval($entry->destination_account_encrypted), $entry->destination_account_name),
'destination_account_before' => $destinationBalance,
'destination_account_after' => bcadd($destinationBalance, bcmul($entry->amount, '-1')),
'budget_id' => is_null($budget) ? 0 : $budget->id,
'category' => is_null($category) ? '' : $category->name,
'transaction_currency_id' => $entry->transaction_currency_id,
'transaction_currency_code' => $entry->transaction_currency_code,
'transaction_currency_symbol' => $entry->transaction_currency_symbol,
'foreign_currency_id' => $entry->foreign_currency_id,
'foreign_currency_code' => $entry->foreign_currency_code,
'foreign_currency_symbol' => $entry->foreign_currency_symbol,
];
if ($entry->destination_account_type === AccountType::CASH) {
$transaction['destination_account_name'] = '';

View File

@ -17,6 +17,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Preferences as Prefs;
@ -101,17 +102,6 @@ class Amount
return $format;
}
/**
* @param string $amount
* @param bool $coloured
*
* @return string
*/
public function format(string $amount, bool $coloured = true): string
{
return $this->formatAnything($this->getDefaultCurrency(), $amount, $coloured);
}
/**
* This method will properly format the given number, in color or "black and white",
* as a currency, given two things: the currency required and the current locale.
@ -159,49 +149,6 @@ class Amount
return $result;
}
/**
* Used in many places (unfortunately).
*
* @param string $currencyCode
* @param string $amount
* @param bool $coloured
*
* @return string
*/
public function formatByCode(string $currencyCode, string $amount, bool $coloured = true): string
{
$currency = TransactionCurrency::where('code', $currencyCode)->first();
return $this->formatAnything($currency, $amount, $coloured);
}
/**
*
* @param \FireflyIII\Models\TransactionJournal $journal
* @param bool $coloured
*
* @return string
*/
public function formatJournal(TransactionJournal $journal, bool $coloured = true): string
{
$currency = $journal->transactionCurrency;
return $this->formatAnything($currency, $journal->amount(), $coloured);
}
/**
* @param Transaction $transaction
* @param bool $coloured
*
* @return string
*/
public function formatTransaction(Transaction $transaction, bool $coloured = true)
{
$currency = $transaction->transactionJournal->transactionCurrency;
return $this->formatAnything($currency, strval($transaction->amount), $coloured);
}
/**
* @return Collection
*/

View File

@ -37,15 +37,8 @@ class JournalList implements BinderInterface
$ids = explode(',', $value);
/** @var \Illuminate\Support\Collection $object */
$object = TransactionJournal::whereIn('transaction_journals.id', $ids)
->expanded()
->where('transaction_journals.user_id', auth()->user()->id)
->get(
[
'transaction_journals.*',
'transaction_types.type AS transaction_type_type',
'transaction_currencies.code AS transaction_currency_code',
]
);
->get(['transaction_journals.*',]);
if ($object->count() > 0) {
return $object;

View File

@ -213,6 +213,14 @@ trait TransactionJournalTrait
return 0;
}
/**
* @return Transaction
*/
public function positiveTransaction(): Transaction
{
return $this->transactions()->where('amount', '>', 0)->first();
}
/**
* @return Collection
*/

View File

@ -1,63 +0,0 @@
<?php
/**
* Account.php
* Copyright (c) 2017 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\Support\Twig;
use FireflyIII\Models\Account as AccountModel;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount as AmountFacade;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class Account
*
* @package FireflyIII\Support\Twig
*/
class Account extends Twig_Extension
{
/**
* {@inheritDoc}
*/
public function getFunctions(): array
{
return [
$this->formatAmountByAccount(),
];
}
/**
* Will return "active" when a part of the route matches the argument.
* ie. "accounts" will match "accounts.index".
*
* @return Twig_SimpleFunction
*/
protected function formatAmountByAccount(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatAmountByAccount', function (AccountModel $account, string $amount, bool $coloured = true): string {
$currencyId = intval($account->getMeta('currency_id'));
if ($currencyId === 0) {
// Format using default currency:
return AmountFacade::format($amount, $coloured);
}
$currency = TransactionCurrency::find($currencyId);
return AmountFacade::formatAnything($currency, $amount, $coloured);
}, ['is_safe' => ['html']]
);
}
}

View File

@ -0,0 +1,109 @@
<?php
/**
* AmountFormat.php
* Copyright (c) 2017 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\Support\Twig;
use FireflyIII\Models\Account as AccountModel;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Contains all amount formatting routines.
*
* @package FireflyIII\Support\Twig
*/
class AmountFormat extends Twig_Extension
{
/**
* {@inheritDoc}
*/
public function getFilters(): array
{
return [
$this->formatAmount(),
$this->formatAmountPlain(),
];
}
/**
* {@inheritDoc}
*/
public function getFunctions(): array
{
return [
$this->formatAmountByAccount(),
];
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName(): string
{
return 'FireflyIII\Support\Twig\AmountFormat';
}
/**
*
* @return Twig_SimpleFilter
*/
protected function formatAmount(): Twig_SimpleFilter
{
return new Twig_SimpleFilter(
'formatAmount', function (string $string): string {
return app('amount')->format($string);
}, ['is_safe' => ['html']]
);
}
/**
* Will format the amount by the currency related to the given account.
*
* @return Twig_SimpleFunction
*/
protected function formatAmountByAccount(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatAmountByAccount', function (AccountModel $account, string $amount, bool $coloured = true): string {
$currencyId = intval($account->getMeta('currency_id'));
if ($currencyId === 0) {
// Format using default currency:
return app('amount')->format($amount, $coloured);
}
$currency = TransactionCurrency::find($currencyId);
return app('amount')->formatAnything($currency, $amount, $coloured);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFilter
*/
protected function formatAmountPlain(): Twig_SimpleFilter
{
return new Twig_SimpleFilter(
'formatAmountPlain', function (string $string): string {
return app('amount')->format($string, false);
}, ['is_safe' => ['html']]
);
}
}

View File

@ -38,9 +38,6 @@ class General extends Twig_Extension
public function getFilters(): array
{
return [
$this->formatAmount(),
$this->formatAmountPlain(),
$this->formatJournal(),
$this->balance(),
$this->formatFilesize(),
$this->mimeIcon(),
@ -173,33 +170,6 @@ class General extends Twig_Extension
);
}
/**
*
* @return Twig_SimpleFilter
*/
protected function formatAmount(): Twig_SimpleFilter
{
return new Twig_SimpleFilter(
'formatAmount', function (string $string): string {
return app('amount')->format($string);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFilter
*/
protected function formatAmountPlain(): Twig_SimpleFilter
{
return new Twig_SimpleFilter(
'formatAmountPlain', function (string $string): string {
return app('amount')->format($string, false);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFilter
*/
@ -223,17 +193,6 @@ class General extends Twig_Extension
);
}
/**
* @return Twig_SimpleFilter
*/
protected function formatJournal(): Twig_SimpleFilter
{
return new Twig_SimpleFilter(
'formatJournal', function (TransactionJournal $journal): string {
return app('amount')->formatJournal($journal);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction

View File

@ -16,7 +16,6 @@ namespace FireflyIII\Support\Twig;
use Amount;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction as TransactionModel;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use Steam;
use Twig_Extension;
@ -30,49 +29,6 @@ use Twig_SimpleFunction;
*/
class Transaction extends Twig_Extension
{
/**
* @return Twig_SimpleFunction
*/
public function formatAnything(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatAnything', function (TransactionCurrency $currency, string $amount): string {
return Amount::formatAnything($currency, $amount, true);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/
public function formatAnythingPlain(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatAnythingPlain', function (TransactionCurrency $currency, string $amount): string {
return Amount::formatAnything($currency, $amount, false);
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/
public function formatByCode(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'formatByCode', function (string $currencyCode, string $amount): string {
return Amount::formatByCode($currencyCode, $amount, true);
}, ['is_safe' => ['html']]
);
}
/**
* @return array
*/
@ -91,17 +47,13 @@ class Transaction extends Twig_Extension
public function getFunctions(): array
{
$functions = [
$this->formatAnything(),
$this->formatAnythingPlain(),
$this->transactionSourceAccount(),
$this->transactionDestinationAccount(),
$this->optionalJournalAmount(),
$this->transactionBudgets(),
$this->transactionIdBudgets(),
$this->transactionCategories(),
$this->transactionIdCategories(),
$this->splitJournalIndicator(),
$this->formatByCode(),
];
return $functions;
@ -117,33 +69,6 @@ class Transaction extends Twig_Extension
return 'transaction';
}
/**
* @return Twig_SimpleFunction
*/
public function optionalJournalAmount(): Twig_SimpleFunction
{
return new Twig_SimpleFunction(
'optionalJournalAmount', function (int $journalId, string $transactionAmount, string $code, string $type): string {
// get amount of journal:
$amount = strval(TransactionModel::where('transaction_journal_id', $journalId)->whereNull('deleted_at')->where('amount', '<', 0)->sum('amount'));
// display deposit and transfer positive
if ($type === TransactionType::DEPOSIT || $type === TransactionType::TRANSFER) {
$amount = bcmul($amount, '-1');
}
// not equal to transaction amount?
if (bccomp($amount, $transactionAmount) !== 0 && bccomp($amount, bcmul($transactionAmount, '-1')) !== 0) {
//$currency =
return sprintf(' (%s)', Amount::formatByCode($code, $amount, true));
}
return '';
}, ['is_safe' => ['html']]
);
}
/**
* @return Twig_SimpleFunction
*/

View File

@ -89,6 +89,7 @@ $factory->define(
'user_id' => 1,
'transaction_type_id' => 1,
'bill_id' => null,
// TODO update this transaction currency reference.
'transaction_currency_id' => 1,
'description' => $faker->words(3, true),
'date' => '2017-01-01',

View File

@ -38,11 +38,12 @@ function updateInitialPage() {
$('#native_amount_holder').hide();
$('#amount_holder').hide();
if (journalData.native_currency.id === journalData.currency.id) {
if (journalData.native_currency.id === journalData.destination_currency.id) {
$('#exchange_rate_instruction_holder').hide();
$('#destination_amount_holder').hide();
}
if (journalData.native_currency.id !== journalData.currency.id) {
if (journalData.native_currency.id !== journalData.destination_currency.id) {
$('#exchange_rate_instruction_holder').show().find('p').text(getTransferExchangeInstructions());
}

View File

@ -166,11 +166,31 @@ function resetSplits() {
var input = $(v);
input.attr('name', 'transactions[' + i + '][amount]');
});
// ends with ][foreign_amount]
$.each($('input[name$="][foreign_amount]"]'), function (i, v) {
var input = $(v);
input.attr('name', 'transactions[' + i + '][foreign_amount]');
});
// ends with ][transaction_currency_id]
$.each($('input[name$="][transaction_currency_id]"]'), function (i, v) {
var input = $(v);
input.attr('name', 'transactions[' + i + '][transaction_currency_id]');
});
// ends with ][foreign_currency_id]
$.each($('input[name$="][foreign_currency_id]"]'), function (i, v) {
var input = $(v);
input.attr('name', 'transactions[' + i + '][foreign_currency_id]');
});
// ends with ][budget_id]
$.each($('select[name$="][budget_id]"]'), function (i, v) {
var input = $(v);
input.attr('name', 'transactions[' + i + '][budget_id]');
});
// ends with ][category]
$.each($('input[name$="][category]"]'), function (i, v) {
var input = $(v);

View File

@ -962,6 +962,7 @@ return [
'split_this_transfer' => 'Split this transfer',
'cannot_edit_multiple_source' => 'You cannot edit splitted transaction #:id with description ":description" because it contains multiple source accounts.',
'cannot_edit_multiple_dest' => 'You cannot edit splitted transaction #:id with description ":description" because it contains multiple destination accounts.',
'cannot_edit_opening_balance' => 'You cannot edit the opening balance of an account.',
'no_edit_multiple_left' => 'You have selected no valid transactions to edit.',
// import

View File

@ -14,10 +14,8 @@
{{ transaction.description }}
{% endif %}
<span class="pull-right small">
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{# TODO replace with new format code #}
XX.XX
</span>
</a>
{% endfor %}

View File

@ -64,14 +64,11 @@
<span style="margin-right:5px;">
{% if transaction.transaction_type_type == 'Transfer' %}
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, steam_positive(transaction.transaction_amount)) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{# TODO format amount of transaction. #}
{# TODO format: Amount of transaction (amount in foreign) / total (total foreign) #}
XX.XX
{% else %}
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
XX.XX
{% endif %}
</span>

View File

@ -45,10 +45,8 @@
</a>
</td>
<td>
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{# TODO replace with new format code #}
XX.XX
</td>
<td class="hidden-sm hidden-xs">
{{ transaction.date.formatLocalized(monthAndDayFormat) }}

View File

@ -59,10 +59,8 @@
</td>
<td class="hide-balance_before" style="text-align: right;">{{ transaction.before|formatAmount }}</td>
<td class="hide-amount" style="text-align: right;">
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{# TODO replace with new format code #}
XX.XX
</td>
<td class="hide-balance_after" style="text-align: right;">{{ transaction.after|formatAmount }}</td>

View File

@ -62,17 +62,8 @@
</td>
<td style="text-align: right;">
<span style="margin-right:5px;">
{% if transaction.transaction_type_type == 'Transfer' %}
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, steam_positive(transaction.transaction_amount)) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{% else %}
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{% endif %}
{# TODO replace with new format code #}
XX.XX
</span>
</td>

View File

@ -39,10 +39,8 @@
</td>
<td data-value="{{ transaction.transaction_amount }}">
<!-- format amount of transaction -->
{{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }}
<!-- and then amount of journal itself. -->
{{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }}
{# TODO replace with new format code #}
XX.XX
</td>

View File

@ -43,7 +43,8 @@
<a href="{{ route('transactions.show',journal.id) }}" title="{{ journal.description }}">{{ journal.description }}</a>
</td>
<td>
{{ journal|formatJournal }}
{# TODO fix amount display #}
XX.XX
</td>
<td>
{{ journal.date.formatLocalized(monthAndDayFormat) }}

View File

@ -47,11 +47,20 @@
</td>
<td>
<div class="input-group input-group-sm">
<span class="input-group-addon">{{ journal.transactionCurrency.symbol }}</span>
<span class="input-group-addon">{{ journal.currency_symbol }}</span>
<input name="amount[{{ journal.id }}]" class="form-control" autocomplete="off"
step="any" type="number" value="{{ journal.amount }}">
<input type="hidden" name="transaction_currency_id[{{ journal.id }}]" value="{{ journal.transaction_currency_id }}">
</div>
{% if journal.foreign_amount %}
{# insert foreign data #}
<div class="input-group input-group-sm">
<span class="input-group-addon">{{ journal.foreign_currency.symbol }}</span>
<input name="foreign_amount[{{ journal.id }}]" class="form-control" autocomplete="off"
step="any" type="number" value="{{ journal.foreign_amount }}">
<input type="hidden" name="foreign_currency_id[{{ journal.id }}]" value="{{ journal.foreign_currency.id }}">
</div>
{% endif %}
</td>
<td>
{# DATE #}

View File

@ -36,14 +36,9 @@
<!-- total amount -->
<tr>
<td>{{ 'total_amount'|_ }}</td>
<td>{{ journal|formatJournal }}
{% if journal.hasMeta('foreign_amount') %}
{% if journal.transactiontype.type == 'Withdrawal' %}
({{ formatAnything(foreignCurrency, journal.getMeta('foreign_amount')*-1) }})
{% else %}
({{ formatAnything(foreignCurrency, journal.getMeta('foreign_amount')) }})
{% endif %}
{% endif %}
<td>
{# TODO fix amount display #}
XX.XX
</td>
</tr>
<tr>
@ -304,9 +299,8 @@
</td>
<td>
{{ formatAnything(journal.transactionCurrency, transaction.source_account_before) }}
&longrightarrow; {{ formatAnything(journal.transactionCurrency, transaction.source_account_after) }}
{# TODO replace with new display: #}
XX.XX
</td>
<td>
{% if transaction.destination_account_type == 'Cash account' %}
@ -317,25 +311,27 @@
</td>
<td>
{{ formatAnything(journal.transactionCurrency, transaction.destination_account_before) }}
&longrightarrow; {{ formatAnything(journal.transactionCurrency, transaction.destination_account_after) }}
{# TODO replace with new format code #}
XX.XX
</td>
<td>
{% if journal.transactiontype.type == 'Deposit' %}
<!-- deposit, positive amount with correct currency -->
{{ formatAnything(journal.transactionCurrency, transaction.destination_amount) }}
{# TODO replace with new format code #}
XX.XX
{% endif %}
{% if journal.transactiontype.type == 'Withdrawal' %}
<!-- withdrawal, negative amount with correct currency -->
{{ formatAnything(journal.transactionCurrency, transaction.source_amount) }}
{# TODO replace with new format code #}
XX.XX
{% endif %}
{% if journal.transactiontype.type == 'Transfer' %}
<!-- transfer, positive amount in blue -->
<span class="text-info">
{{ formatAnythingPlain(journal.transactionCurrency, transaction.destination_amount) }}
{# TODO replace with new format code #}
XX.XX
</span>
{% endif %}
</td>

View File

@ -64,9 +64,9 @@
{{ ExpandedForm.nonSelectableAmount('native_amount', data.native_amount, {currency: data.native_currency}) }}
{{ ExpandedForm.nonSelectableAmount('source_amount', data.native_amount, {currency: data.native_currency }) }}
{{ ExpandedForm.nonSelectableAmount('source_amount', data.source_amount, {currency: data.source_currency }) }}
{{ ExpandedForm.nonSelectableAmount('destination_amount', data.amount, {currency: data.currency }) }}
{{ ExpandedForm.nonSelectableAmount('destination_amount', data.destination_amount, {currency: data.destination_currency }) }}
{# ALWAYS SHOW DATE #}
{{ ExpandedForm.date('date',data['date']) }}

View File

@ -40,9 +40,6 @@
{# DESCRIPTION IS ALWAYS AVAILABLE #}
{{ ExpandedForm.text('journal_description', journal.description) }}
{# CURRENCY IS NEW FOR SPLIT JOURNALS #}
{{ ExpandedForm.select('currency_id', currencies, preFilled.currency_id) }}
{# show source if withdrawal or transfer #}
{% if preFilled.what == 'withdrawal' or preFilled.what == 'transfer' %}
{{ ExpandedForm.select('journal_source_account_id', assetAccounts, preFilled.journal_source_account_id) }}
@ -59,6 +56,7 @@
{% endif %}
{# TOTAL AMOUNT IS STATIC TEXT #}
{# TODO this does not reflect the actual currency (currencies) #}
{{ ExpandedForm.staticText('journal_amount', preFilled.journal_amount|formatAmount ) }}
<input type="hidden" name="journal_amount" value="{{ preFilled.journal_amount }}"/>
@ -204,7 +202,7 @@
<th>{{ trans('list.source') }}</th>
{% endif %}
<th>{{ trans('list.amount') }}</th>
<th colspan="2">{{ trans('list.amount') }}</th>
{# only withdrawal has budget #}
{% if preFilled.what == 'withdrawal' %}
@ -234,7 +232,7 @@
</td>
{% endif %}
<!-- deposit has several source names -->
{# deposit has several source names #}
{% if preFilled.what == 'deposit' %}
<td>
<input type="text" name="transactions[{{ loop.index0 }}][source_account_name]"
@ -243,10 +241,26 @@
</td>
{% endif %}
{# two fields for amount #}
<td style="width:10%;">
<input type="number" name="transactions[{{ loop.index0 }}][amount]" value="{{ transaction.amount }}"
class="form-control" autocomplete="off" step="any" min="0.01">
<div class="input-group">
<div class="input-group-addon">{{ transaction.transaction_currency_symbol }}</div>
<input type="number" name="transactions[{{ loop.index0 }}][amount]" value="{{ transaction.amount }}"
class="form-control" autocomplete="off" step="any" min="0.01">
</div>
<input type="hidden" name="transactions[{{ loop.index0 }}][transaction_currency_id]" value="{{ transaction.transaction_currency_id }}">
</td>
{# foreign amount #}
<td style="width:10%;">
{% if transaction.foreign_amount != null %}
<div class="input-group">
<div class="input-group-addon">{{ transaction.foreign_currency_symbol }}</div>
<input type="number" name="transactions[{{ loop.index0 }}][foreign_amount]"
value="{{ transaction.foreign_amount }}"
class="form-control" autocomplete="off" step="any" min="0.01">
</div>
<input type="hidden" name="transactions[{{ loop.index0 }}][foreign_currency_id]" value="{{ transaction.foreign_currency_id }}">
{% endif %}
</td>
{% if preFilled.what == 'withdrawal' %}