diff --git a/app/Console/Commands/UpgradeDatabase.php b/app/Console/Commands/UpgradeDatabase.php index d5de734e37..b2a6fc171c 100644 --- a/app/Console/Commands/UpgradeDatabase.php +++ b/app/Console/Commands/UpgradeDatabase.php @@ -25,7 +25,9 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use Illuminate\Console\Command; +use Illuminate\Database\Query\JoinClause; use Illuminate\Database\QueryException; use Log; use Preferences; @@ -69,6 +71,7 @@ class UpgradeDatabase extends Command $this->migrateRepetitions(); $this->repairPiggyBanks(); $this->updateAccountCurrencies(); + $this->updateJournalCurrencies(); $this->info('Firefly III database is up to date.'); } @@ -252,4 +255,49 @@ class UpgradeDatabase extends Command $identifier++; } } + + /** + * Makes sure that withdrawals, deposits and transfers have + * a currency setting matching their respective accounts + */ + private function updateJournalCurrencies() + { + $types = [ + TransactionType::WITHDRAWAL => '<', + TransactionType::DEPOSIT => '>', + ]; + $repository = app(CurrencyRepositoryInterface::class); + + foreach ($types as $type => $operator) { + $set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')->leftJoin( + 'transactions', function (JoinClause $join) use ($operator) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', $operator, '0'); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id') + ->where('transaction_types.type', $type) + ->where('account_meta.name', 'currency_id') + ->where('transaction_journals.transaction_currency_id', '!=', DB::raw('account_meta.data')) + ->get( + ['transaction_journals.*', 'account_meta.data as expected_currency_id', 'transactions.amount as transaction_amount'] + ); + /** @var TransactionJournal $journal */ + foreach ($set as $journal) { + $expectedCurrency = $repository->find(intval($journal->expected_currency_id)); + $this->line( + sprintf( + '%s #%d uses %s but should use %s. It has been updated to do so, please verify the amounts.', $type, $journal->id, + $journal->transactionCurrency->code, $expectedCurrency->code + ) + ); + + $journal->setMeta('foreign_amount', $journal->transaction_amount); + $journal->setMeta('foreign_currency_id', $journal->transaction_currency_id); + $journal->transaction_currency_id = $expectedCurrency->id; + $journal->save(); + + } + } + } } diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 82b078fc9f..02599350c6 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -249,14 +249,17 @@ class AccountController extends Controller if ($account->accountType->type === AccountType::INITIAL_BALANCE) { return $this->redirectToOriginalAccount($account); } - $range = Preferences::get('viewRange', '1M')->data; - $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type); - $page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page')); - $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); - $chartUri = route('chart.account.single', [$account->id]); - $start = null; - $end = null; - $periods = new Collection; + /** @var CurrencyRepositoryInterface $currencyRepos */ + $currencyRepos = app(CurrencyRepositoryInterface::class); + $range = Preferences::get('viewRange', '1M')->data; + $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type); + $page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page')); + $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); + $chartUri = route('chart.account.single', [$account->id]); + $start = null; + $end = null; + $periods = new Collection; + $currency = $currencyRepos->find(intval($account->getMeta('currency_id'))); // prep for "all" view. if ($moment === 'all') { @@ -323,7 +326,7 @@ class AccountController extends Controller return view( - 'accounts.show', compact('account', 'moment', 'accountType', 'periods', 'subTitleIcon', 'journals', 'subTitle', 'start', 'end', 'chartUri') + 'accounts.show', compact('account','currency', 'moment', 'accountType', 'periods', 'subTitleIcon', 'journals', 'subTitle', 'start', 'end', 'chartUri') ); } diff --git a/public/js/ff/firefly.js b/public/js/ff/firefly.js index 8fb15909dd..c0a223edf0 100644 --- a/public/js/ff/firefly.js +++ b/public/js/ff/firefly.js @@ -13,6 +13,8 @@ $(function () { "use strict"; + configAccounting(currencySymbol); + $.ajaxSetup({ headers: { 'X-CSRF-Token': $('meta[name="_token"]').attr('content') @@ -108,22 +110,24 @@ function currencySelect(e) { return false; } -// Settings object that controls default parameters for library methods: -accounting.settings = { - currency: { - symbol: currencySymbol, // default currency symbol is '$' - format: accountingConfig, // controls output: %s = symbol, %v = value/number (can be object: see below) - decimal: mon_decimal_point, // decimal point separator - thousand: mon_thousands_sep, // thousands separator - precision: frac_digits // decimal places - }, - number: { - precision: 0, // default precision on numbers is 0 - thousand: ",", - decimal: "." - } -}; +function configAccounting(customCurrency) { +// Settings object that controls default parameters for library methods: + accounting.settings = { + currency: { + symbol: customCurrency, // default currency symbol is '$' + format: accountingConfig, // controls output: %s = symbol, %v = value/number (can be object: see below) + decimal: mon_decimal_point, // decimal point separator + thousand: mon_thousands_sep, // thousands separator + precision: frac_digits // decimal places + }, + number: { + precision: 0, // default precision on numbers is 0 + thousand: ",", + decimal: "." + } + }; +} function listLengthInitial() { "use strict"; diff --git a/public/js/ff/transactions/single/create.js b/public/js/ff/transactions/single/create.js index ed48eb28a3..61806b786f 100644 --- a/public/js/ff/transactions/single/create.js +++ b/public/js/ff/transactions/single/create.js @@ -26,7 +26,6 @@ $(document).ready(function () { updateNativeCurrency(); - // when user changes source account or destination, native currency may be different. $('select[name="source_account_id"]').on('change', updateNativeCurrency); $('select[name="destination_account_id"]').on('change', updateNativeCurrency); @@ -101,85 +100,83 @@ function updateForm() { "use strict"; $('input[name="what"]').val(what); + + var destName = $('#ffInput_destination_account_name'); + var srcName = $('#ffInput_source_account_name'); + switch (what) { case 'withdrawal': // show source_id and dest_name - $('#source_account_id_holder').show(); - $('#destination_account_name_holder').show(); + document.getElementById('source_account_id_holder').style.display = 'block'; + document.getElementById('destination_account_name_holder').style.display = 'block'; // hide others: - $('#source_account_name_holder').hide(); - $('#destination_account_id_holder').hide(); - - // - $('#budget_id_holder').show(); + document.getElementById('source_account_name_holder').style.display = 'none'; + document.getElementById('destination_account_id_holder').style.display = 'none'; + document.getElementById('budget_id_holder').style.display = 'block'; // hide piggy bank: - $('#piggy_bank_id_holder').hide(); + document.getElementById('piggy_bank_id_holder').style.display = 'none'; - // copy destination account name to - // source account name: - if ($('#ffInput_destination_account_name').val().length > 0) { - $('#ffInput_source_account_name').val($('#ffInput_destination_account_name').val()); + // copy destination account name to source account name: + if (destName.val().length > 0) { + srcName.val(destName.val()); } // exchange / foreign currencies: - // hide explanation, hide source and destination amounts: - $('#exchange_rate_instruction_holder').hide(); - $('#source_amount_holder').hide(); - $('#destination_amount_holder').hide(); - // show normal amount: - $('#amount_holder').show(); + // hide explanation, hide source and destination amounts, show normal amount + document.getElementById('exchange_rate_instruction_holder').style.display = 'none'; + document.getElementById('source_amount_holder').style.display = 'none'; + document.getElementById('destination_amount_holder').style.display = 'none'; + document.getElementById('amount_holder').style.display = 'block'; break; case 'deposit': // show source_name and dest_id: - $('#source_account_name_holder').show(); - $('#destination_account_id_holder').show(); + document.getElementById('source_account_name_holder').style.display = 'block'; + document.getElementById('destination_account_id_holder').style.display = 'block'; // hide others: - $('#source_account_id_holder').hide(); - $('#destination_account_name_holder').hide(); + document.getElementById('source_account_id_holder').style.display = 'none'; + document.getElementById('destination_account_name_holder').style.display = 'none'; // hide budget - $('#budget_id_holder').hide(); + document.getElementById('budget_id_holder').style.display = 'none'; // hide piggy bank - $('#piggy_bank_id_holder').hide(); + document.getElementById('piggy_bank_id_holder').style.display = 'none'; - if ($('#ffInput_source_account_name').val().length > 0) { - $('#ffInput_destination_account_name').val($('#ffInput_source_account_name').val()); + // copy name + if (srcName.val().length > 0) { + destName.val(srcName.val()); } // exchange / foreign currencies: - // hide explanation, hide source and destination amounts: - $('#exchange_rate_instruction_holder').hide(); - $('#source_amount_holder').hide(); - $('#destination_amount_holder').hide(); - // show normal amount: - $('#amount_holder').show(); + // hide explanation, hide source and destination amounts, show amount + document.getElementById('exchange_rate_instruction_holder').style.display = 'none'; + document.getElementById('source_amount_holder').style.display = 'none'; + document.getElementById('destination_amount_holder').style.display = 'none'; + document.getElementById('amount_holder').style.display = 'block'; break; case 'transfer': // show source_id and dest_id: - $('#source_account_id_holder').show(); - $('#destination_account_id_holder').show(); + document.getElementById('source_account_id_holder').style.display = 'block'; + document.getElementById('destination_account_id_holder').style.display = 'block'; // hide others: - $('#source_account_name_holder').hide(); - $('#destination_account_name_holder').hide(); + document.getElementById('source_account_name_holder').style.display = 'none'; + document.getElementById('destination_account_name_holder').style.display = 'none'; // hide budget - $('#budget_id_holder').hide(); + document.getElementById('budget_id_holder').style.display = 'none'; + + // optional piggies + var showPiggies = 'block'; if (piggiesLength === 0) { - $('#piggy_bank_id_holder').hide(); - } else { - $('#piggy_bank_id_holder').show(); + showPiggies = 'none'; } - break; - default: - // no action. + document.getElementById('piggy_bank_id_holder').style.display = showPiggies; break; } - // update the amount thing: updateNativeCurrency(); } diff --git a/public/js/ff/transactions/single/edit.js b/public/js/ff/transactions/single/edit.js index 62e0380e30..17f2d0a5c0 100644 --- a/public/js/ff/transactions/single/edit.js +++ b/public/js/ff/transactions/single/edit.js @@ -49,6 +49,8 @@ function updateInitialPage() { return; } + $('#source_amount_holder').hide(); + $('#destination_amount_holder').hide(); if (journalData.native_currency.id === journalData.currency.id) { diff --git a/resources/views/accounts/show.twig b/resources/views/accounts/show.twig index a29f420fa8..d7aff66784 100644 --- a/resources/views/accounts/show.twig +++ b/resources/views/accounts/show.twig @@ -140,6 +140,7 @@ {% block scripts %} + + +