diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index 285a73f3e9..b0205f36af 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -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])); diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index eef9bd7ab4..89de28d7d2 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -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); diff --git a/app/Http/Controllers/Transaction/SplitController.php b/app/Http/Controllers/Transaction/SplitController.php index c587129811..e6668bc43e 100644 --- a/app/Http/Controllers/Transaction/SplitController.php +++ b/app/Http/Controllers/Transaction/SplitController.php @@ -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))); diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 1e838c5dec..5f6f12de2e 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -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')); } diff --git a/app/Import/ImportStorage.php b/app/Import/ImportStorage.php index 2d5524fcec..4f39086965 100644 --- a/app/Import/ImportStorage.php +++ b/app/Import/ImportStorage.php @@ -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'], diff --git a/app/Import/ImportValidator.php b/app/Import/ImportValidator.php index 3a3a373b2b..fd9981ec47 100644 --- a/app/Import/ImportValidator.php +++ b/app/Import/ImportValidator.php @@ -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); diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index ef5deeadcd..0e9ade0b30 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -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 */ diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index 53506bc61d..cc0c00ef45 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -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 */ diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index ef4890bb7f..c9740f4bcf 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -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); } /** diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 122e8f7d5c..7b594555b8 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -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: diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index ef4820ac2e..9a28be284b 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -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)); diff --git a/app/Repositories/Journal/JournalTasker.php b/app/Repositories/Journal/JournalTasker.php index b56abe0db8..bb0c8bcdd2 100644 --- a/app/Repositories/Journal/JournalTasker.php +++ b/app/Repositories/Journal/JournalTasker.php @@ -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'] = ''; diff --git a/app/Support/Amount.php b/app/Support/Amount.php index 32e42cf3bb..7d11d68b7d 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -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 */ diff --git a/app/Support/Binder/JournalList.php b/app/Support/Binder/JournalList.php index cc31681323..3b5678f886 100644 --- a/app/Support/Binder/JournalList.php +++ b/app/Support/Binder/JournalList.php @@ -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; diff --git a/app/Support/Models/TransactionJournalTrait.php b/app/Support/Models/TransactionJournalTrait.php index c9cea3ec49..0961fafbb4 100644 --- a/app/Support/Models/TransactionJournalTrait.php +++ b/app/Support/Models/TransactionJournalTrait.php @@ -213,6 +213,14 @@ trait TransactionJournalTrait return 0; } + /** + * @return Transaction + */ + public function positiveTransaction(): Transaction + { + return $this->transactions()->where('amount', '>', 0)->first(); + } + /** * @return Collection */ diff --git a/app/Support/Twig/Account.php b/app/Support/Twig/Account.php deleted file mode 100644 index d2a5520505..0000000000 --- a/app/Support/Twig/Account.php +++ /dev/null @@ -1,63 +0,0 @@ -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']] - ); - } - - -} \ No newline at end of file diff --git a/app/Support/Twig/AmountFormat.php b/app/Support/Twig/AmountFormat.php new file mode 100644 index 0000000000..eb06a98ebf --- /dev/null +++ b/app/Support/Twig/AmountFormat.php @@ -0,0 +1,109 @@ +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']] + ); + } +} \ No newline at end of file diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index 5db0ba95f6..9603e54e44 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -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 diff --git a/app/Support/Twig/Transaction.php b/app/Support/Twig/Transaction.php index d4b8e84850..a8d97c97f8 100644 --- a/app/Support/Twig/Transaction.php +++ b/app/Support/Twig/Transaction.php @@ -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 */ diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 283a342b20..bd8d30b2a9 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -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', diff --git a/public/js/ff/transactions/single/edit.js b/public/js/ff/transactions/single/edit.js index 17f2d0a5c0..d608568c65 100644 --- a/public/js/ff/transactions/single/edit.js +++ b/public/js/ff/transactions/single/edit.js @@ -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()); } diff --git a/public/js/ff/transactions/split/edit.js b/public/js/ff/transactions/split/edit.js index a91c0a3422..a97739b122 100644 --- a/public/js/ff/transactions/split/edit.js +++ b/public/js/ff/transactions/split/edit.js @@ -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); diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index da1c9bcb43..54f7cbc4ae 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -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 diff --git a/resources/views/list/journals-tiny.twig b/resources/views/list/journals-tiny.twig index 190d28cf37..63306fa102 100644 --- a/resources/views/list/journals-tiny.twig +++ b/resources/views/list/journals-tiny.twig @@ -14,10 +14,8 @@ {{ transaction.description }} {% endif %} - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} + {# TODO replace with new format code #} + XX.XX {% endfor %} diff --git a/resources/views/list/journals.twig b/resources/views/list/journals.twig index db348d7acb..acd95000bb 100644 --- a/resources/views/list/journals.twig +++ b/resources/views/list/journals.twig @@ -64,14 +64,11 @@ {% if transaction.transaction_type_type == 'Transfer' %} - {{ formatByCode(transaction.transaction_currency_code, steam_positive(transaction.transaction_amount)) }} - - {{ 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 %} - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} + XX.XX {% endif %} diff --git a/resources/views/popup/list/journals.twig b/resources/views/popup/list/journals.twig index d6f97dcc59..1177cce1f5 100644 --- a/resources/views/popup/list/journals.twig +++ b/resources/views/popup/list/journals.twig @@ -45,10 +45,8 @@ - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} + {# TODO replace with new format code #} + XX.XX {{ transaction.date.formatLocalized(monthAndDayFormat) }} diff --git a/resources/views/reports/partials/journals-audit.twig b/resources/views/reports/partials/journals-audit.twig index 0c9fd25adc..48c5430658 100644 --- a/resources/views/reports/partials/journals-audit.twig +++ b/resources/views/reports/partials/journals-audit.twig @@ -59,10 +59,8 @@ {{ transaction.before|formatAmount }} - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} + {# TODO replace with new format code #} + XX.XX {{ transaction.after|formatAmount }} diff --git a/resources/views/search/partials/transactions-large.twig b/resources/views/search/partials/transactions-large.twig index 7502719e27..ca8c06ac92 100644 --- a/resources/views/search/partials/transactions-large.twig +++ b/resources/views/search/partials/transactions-large.twig @@ -62,17 +62,8 @@ - {% if transaction.transaction_type_type == 'Transfer' %} - - {{ formatByCode(transaction.transaction_currency_code, steam_positive(transaction.transaction_amount)) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} - {% else %} - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} - {% endif %} + {# TODO replace with new format code #} + XX.XX diff --git a/resources/views/search/partials/transactions.twig b/resources/views/search/partials/transactions.twig index 587c9b432d..387b5ec07b 100644 --- a/resources/views/search/partials/transactions.twig +++ b/resources/views/search/partials/transactions.twig @@ -39,10 +39,8 @@ - - {{ formatByCode(transaction.transaction_currency_code, transaction.transaction_amount) }} - - {{ optionalJournalAmount(transaction.journal_id, transaction.transaction_amount, transaction.transaction_currency_code, transaction.transaction_type_type) }} + {# TODO replace with new format code #} + XX.XX diff --git a/resources/views/transactions/mass-delete.twig b/resources/views/transactions/mass-delete.twig index f3525c1d6c..2049df92f8 100644 --- a/resources/views/transactions/mass-delete.twig +++ b/resources/views/transactions/mass-delete.twig @@ -43,7 +43,8 @@ {{ journal.description }} - {{ journal|formatJournal }} + {# TODO fix amount display #} + XX.XX {{ journal.date.formatLocalized(monthAndDayFormat) }} diff --git a/resources/views/transactions/mass/edit.twig b/resources/views/transactions/mass/edit.twig index c0c2ccc123..a8bab41a7d 100644 --- a/resources/views/transactions/mass/edit.twig +++ b/resources/views/transactions/mass/edit.twig @@ -47,11 +47,20 @@
- {{ journal.transactionCurrency.symbol }} + {{ journal.currency_symbol }} +
- + {% if journal.foreign_amount %} + {# insert foreign data #} +
+ {{ journal.foreign_currency.symbol }} + + +
+ {% endif %} {# DATE #} diff --git a/resources/views/transactions/show.twig b/resources/views/transactions/show.twig index 3c086d1899..b115ca16c8 100644 --- a/resources/views/transactions/show.twig +++ b/resources/views/transactions/show.twig @@ -36,14 +36,9 @@ {{ 'total_amount'|_ }} - {{ 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 %} + + {# TODO fix amount display #} + XX.XX @@ -304,9 +299,8 @@ - - {{ formatAnything(journal.transactionCurrency, transaction.source_account_before) }} - ⟶ {{ formatAnything(journal.transactionCurrency, transaction.source_account_after) }} + {# TODO replace with new display: #} + XX.XX {% if transaction.destination_account_type == 'Cash account' %} @@ -317,25 +311,27 @@ - - {{ formatAnything(journal.transactionCurrency, transaction.destination_account_before) }} - ⟶ {{ formatAnything(journal.transactionCurrency, transaction.destination_account_after) }} + {# TODO replace with new format code #} + XX.XX {% if journal.transactiontype.type == 'Deposit' %} - {{ formatAnything(journal.transactionCurrency, transaction.destination_amount) }} + {# TODO replace with new format code #} + XX.XX {% endif %} {% if journal.transactiontype.type == 'Withdrawal' %} - {{ formatAnything(journal.transactionCurrency, transaction.source_amount) }} + {# TODO replace with new format code #} + XX.XX {% endif %} {% if journal.transactiontype.type == 'Transfer' %} - {{ formatAnythingPlain(journal.transactionCurrency, transaction.destination_amount) }} + {# TODO replace with new format code #} + XX.XX {% endif %} diff --git a/resources/views/transactions/single/edit.twig b/resources/views/transactions/single/edit.twig index 4ef0d2ceaa..fc09562117 100644 --- a/resources/views/transactions/single/edit.twig +++ b/resources/views/transactions/single/edit.twig @@ -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']) }} diff --git a/resources/views/transactions/split/edit.twig b/resources/views/transactions/split/edit.twig index e78dffb4ab..a0420fe4c8 100644 --- a/resources/views/transactions/split/edit.twig +++ b/resources/views/transactions/split/edit.twig @@ -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 ) }} @@ -204,7 +202,7 @@ {{ trans('list.source') }} {% endif %} - {{ trans('list.amount') }} + {{ trans('list.amount') }} {# only withdrawal has budget #} {% if preFilled.what == 'withdrawal' %} @@ -234,7 +232,7 @@ {% endif %} - + {# deposit has several source names #} {% if preFilled.what == 'deposit' %} {% endif %} - + {# two fields for amount #} - +
+
{{ transaction.transaction_currency_symbol }}
+ +
+ + + {# foreign amount #} + + {% if transaction.foreign_amount != null %} +
+
{{ transaction.foreign_currency_symbol }}
+ +
+ + {% endif %} {% if preFilled.what == 'withdrawal' %}