Sync "convert to native"

This commit is contained in:
James Cole
2025-07-26 19:17:26 +02:00
parent 46395e350a
commit a16cc73c77
12 changed files with 109 additions and 57 deletions

View File

@@ -32,6 +32,7 @@ use FireflyIII\Models\UserGroup;
use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use NumberFormatter; use NumberFormatter;
/** /**
@@ -66,13 +67,13 @@ class Amount
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol); $fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces); $fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces); $fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
$result = (string) $fmt->format((float) $rounded); // intentional float $result = (string)$fmt->format((float)$rounded); // intentional float
if (true === $coloured) { if (true === $coloured) {
if (1 === bccomp((string) $rounded, '0')) { if (1 === bccomp((string)$rounded, '0')) {
return sprintf('<span class="text-success money-positive">%s</span>', $result); return sprintf('<span class="text-success money-positive">%s</span>', $result);
} }
if (-1 === bccomp((string) $rounded, '0')) { if (-1 === bccomp((string)$rounded, '0')) {
return sprintf('<span class="text-danger money-negative">%s</span>', $result); return sprintf('<span class="text-danger money-negative">%s</span>', $result);
} }
@@ -106,23 +107,22 @@ class Amount
$amount = $journal[$field] ?? '0'; $amount = $journal[$field] ?? '0';
// Log::debug(sprintf('Field is %s, amount is %s', $field, $amount)); // Log::debug(sprintf('Field is %s, amount is %s', $field, $amount));
// fallback, the transaction has a foreign amount in $currency. // fallback, the transaction has a foreign amount in $currency.
if ($convertToNative && null !== $journal['foreign_amount'] && $currency->id === (int) $journal['foreign_currency_id']) { if ($convertToNative && null !== $journal['foreign_amount'] && $currency->id === (int)$journal['foreign_currency_id']) {
$amount = $journal['foreign_amount']; $amount = $journal['foreign_amount'];
// Log::debug(sprintf('Overruled, amount is now %s', $amount)); // Log::debug(sprintf('Overruled, amount is now %s', $amount));
} }
return (string) $amount; return (string)$amount;
} }
public function convertToNative(?User $user = null): bool public function convertToNative(?User $user = null): bool
{ {
if (!$user instanceof User) { if (!$user instanceof User) {
return true === Preferences::get('convert_to_native', false)->data && true === config('cer.enabled'); return true === Preferences::get('convert_to_native', false)->data && true === config('cer.enabled');
// Log::debug(sprintf('convertToNative [a]: %s', var_export($result, true)));
} }
Log::debug('convertToNative setting', Preferences::getForUser($user, 'convert_to_native', false));
return true === Preferences::getForUser($user, 'convert_to_native', false)->data && true === config('cer.enabled'); return true === Preferences::getForUser($user, 'convert_to_native', false)->data && true === config('cer.enabled');
// Log::debug(sprintf('convertToNative [b]: %s', var_export($result, true)));
} }
public function getNativeCurrency(): TransactionCurrency public function getNativeCurrency(): TransactionCurrency
@@ -180,9 +180,9 @@ class Amount
return '0'; return '0';
} }
$amount = $sourceTransaction->{$field} ?? '0'; $amount = $sourceTransaction->{$field} ?? '0';
if ((int) $sourceTransaction->foreign_currency_id === $currency->id) { if ((int)$sourceTransaction->foreign_currency_id === $currency->id) {
// use foreign amount instead! // use foreign amount instead!
$amount = (string) $sourceTransaction->foreign_amount; // hard coded to be foreign amount. $amount = (string)$sourceTransaction->foreign_amount; // hard coded to be foreign amount.
} }
return $amount; return $amount;
@@ -336,9 +336,9 @@ class Amount
} }
if ($csPrecedes) { if ($csPrecedes) {
return $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE; return $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE;
} }
return $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE; return $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE;
} }
} }

View File

@@ -44,11 +44,22 @@ export default () => ({
chartOptions: null, chartOptions: null,
switchConvertToNative() { switchConvertToNative() {
this.convertToNative = !this.convertToNative; this.convertToNative = !this.convertToNative;
setVariable('convertToNative', this.convertToNative); setVariable('convert_to_native', this.convertToNative);
}, },
localCacheKey(type) { localCacheKey(type) {
return 'ds_accounts_' + type; return 'ds_accounts_' + type;
}, },
eventListeners: {
['@convert-to-native.window'](event){
console.log('I heard that! it is now ' + event.detail);
}
},
doSomeReload() {
console.log('doSomeReload');
},
getFreshData() { getFreshData() {
const start = new Date(window.store.get('start')); const start = new Date(window.store.get('start'));
const end = new Date(window.store.get('end')); const end = new Date(window.store.get('end'));
@@ -273,8 +284,11 @@ export default () => ({
init() { init() {
// console.log('accounts init'); // console.log('accounts init');
Promise.all([getVariable('viewRange', '1M'), getVariable('convertToNative', false), getVariable('language', 'en_US'), Promise.all([
getConfiguration('cer.enabled', false) getVariable('viewRange', '1M'), // 0
getVariable('convert_to_native', false), // 1
getVariable('language', 'en_US'), // 2
getConfiguration('cer.enabled', false) // 3
]).then((values) => { ]).then((values) => {
//console.log('accounts after promises'); //console.log('accounts after promises');
this.convertToNative = values[1] && values[3]; this.convertToNative = values[1] && values[3];
@@ -296,7 +310,7 @@ export default () => ({
this.loadChart(); this.loadChart();
this.loadAccounts(); this.loadAccounts();
}); });
window.store.observe('convertToNative', () => { window.store.observe('convert_to_native', () => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -153,7 +153,7 @@ export default () => ({
init() { init() {
// console.log('boxes init'); // console.log('boxes init');
// TODO can be replaced by "getVariables" // TODO can be replaced by "getVariables"
Promise.all([getVariable('viewRange'), getVariable('convertToNative', false)]).then((values) => { Promise.all([getVariable('viewRange'), getVariable('convert_to_native', false)]).then((values) => {
// console.log('boxes after promises'); // console.log('boxes after promises');
afterPromises = true; afterPromises = true;
this.convertToNative = values[1]; this.convertToNative = values[1];
@@ -167,7 +167,7 @@ export default () => ({
this.boxData = null; this.boxData = null;
this.loadBoxes(); this.loadBoxes();
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -123,8 +123,6 @@ export default () => ({
for (const i in data) { for (const i in data) {
if (data.hasOwnProperty(i)) { if (data.hasOwnProperty(i)) {
let current = data[i]; let current = data[i];
console.log('Now at');
console.log(current);
// // convert to EUR yes no? // // convert to EUR yes no?
let label = current.label + ' (' + current.currency_code + ')'; let label = current.label + ' (' + current.currency_code + ')';
options.data.labels.push(label); options.data.labels.push(label);
@@ -159,7 +157,7 @@ export default () => ({
init() { init() {
Promise.all([getVariable('convertToNative', false)]).then((values) => { Promise.all([getVariable('convert_to_native', false)]).then((values) => {
this.convertToNative = values[0]; this.convertToNative = values[0];
afterPromises = true; afterPromises = true;
if (false === this.loading) { if (false === this.loading) {
@@ -176,7 +174,7 @@ export default () => ({
this.loadChart(); this.loadChart();
} }
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -183,7 +183,7 @@ export default () => ({
}, },
init() { init() {
// console.log('categories init'); // console.log('categories init');
Promise.all([getVariable('convertToNative', false),]).then((values) => { Promise.all([getVariable('convert_to_native', false),]).then((values) => {
this.convertToNative = values[0]; this.convertToNative = values[0];
afterPromises = true; afterPromises = true;
this.loadChart(); this.loadChart();
@@ -195,7 +195,7 @@ export default () => ({
this.chartData = null; this.chartData = null;
this.loadChart(); this.loadChart();
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -46,7 +46,8 @@ import {
} from "chart.js"; } from "chart.js";
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import {showInternalsButton} from "../../support/page-settings/show-internals-button.js"; import {showInternalsButton} from "../../support/page-settings/show-internals-button.js";
import {showWizardButton} from "../../support/page-settings/show-wizard-button.js"; import {setVariable} from "../../store/set-variable.js";
import {getVariable} from "../../store/get-variable.js";
// register things // register things
Chart.register({ Chart.register({
@@ -66,7 +67,25 @@ Chart.register({
Legend Legend
}); });
let index = function () {
return {
convertToNative: false,
saveNativeSettings(event) {
setVariable('convert_to_native', event.currentTarget.checked);
this.$dispatch('convert-to-native', event.currentTarget.checked);
console.log('saveNativeSettings + dispatch.');
},
init() {
Promise.all([getVariable('convert_to_native', false)]).then((values) => {
this.convertToNative = values[0];
console.log('convert_to_native: ' + this.convertToNative);
});
}
}
};
const comps = { const comps = {
index,
dates, dates,
boxes, boxes,
accounts, accounts,

View File

@@ -129,7 +129,7 @@ export default () => ({
init() { init() {
// console.log('piggies init'); // console.log('piggies init');
apiData = []; apiData = [];
Promise.all([getVariable('convertToNative', false)]).then((values) => { Promise.all([getVariable('convert_to_native', false)]).then((values) => {
afterPromises = true; afterPromises = true;
this.convertToNative = values[0]; this.convertToNative = values[0];
@@ -144,7 +144,7 @@ export default () => ({
apiData = []; apiData = [];
this.loadPiggyBanks(); this.loadPiggyBanks();
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -94,6 +94,7 @@ function getObjectName(type, name, direction, code) {
if ('category' === type && null === name && 'out' === direction) { if ('category' === type && null === name && 'out' === direction) {
return translations.unknown_category + ' (' + translations.out + (convertToNative ? ', ' + code + ')' : ')'); return translations.unknown_category + ' (' + translations.out + (convertToNative ? ', ' + code + ')' : ')');
} }
// account 4x // account 4x
if ('account' === type && null === name && 'in' === direction) { if ('account' === type && null === name && 'in' === direction) {
return translations.unknown_source + (convertToNative ? ' (' + code + ')' : ''); return translations.unknown_source + (convertToNative ? ' (' + code + ')' : '');
@@ -348,9 +349,13 @@ export default () => ({
init() { init() {
// console.log('sankey init'); // console.log('sankey init');
transactions = []; transactions = [];
Promise.all([getVariable('convertToNative', false)]).then((values) => { Promise.all([getVariable('convert_to_native', false)]).then((values) => {
this.convertToNative = values[0]; this.convertToNative = values[0];
convertToNative = values[0]; convertToNative = values[0];
this.convertToNative = false;
convertToNative = false;
// some translations: // some translations:
translations.all_money = i18next.t('firefly.all_money'); translations.all_money = i18next.t('firefly.all_money');
translations.category = i18next.t('firefly.category'); translations.category = i18next.t('firefly.category');
@@ -378,7 +383,7 @@ export default () => ({
this.transactions = []; this.transactions = [];
this.loadChart(); this.loadChart();
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -305,7 +305,7 @@ export default () => ({
}, },
init() { init() {
Promise.all([getVariable('convertToNative', false)]).then((values) => { Promise.all([getVariable('convert_to_native', false)]).then((values) => {
this.convertToNative = values[0]; this.convertToNative = values[0];
afterPromises = true; afterPromises = true;
@@ -323,7 +323,7 @@ export default () => ({
this.startSubscriptions(); this.startSubscriptions();
} }
}); });
window.store.observe('convertToNative', (newValue) => { window.store.observe('convert_to_native', (newValue) => {
if (!afterPromises) { if (!afterPromises) {
return; return;
} }

View File

@@ -21,6 +21,14 @@
import {format} from "date-fns"; import {format} from "date-fns";
export default function (amount, currencyCode) { export default function (amount, currencyCode) {
if( (typeof amount !== 'number' && typeof amount !== 'string') || isNaN(amount)) {
console.warn('format-money: amount is not a number:', amount);
return '';
}
if(typeof currencyCode !== 'string' || currencyCode.length !== 3) {
console.warn('format-money: currencyCode is not a valid ISO 4217 code:', currencyCode);
return '';
}
let locale = window.__localeId__.replace('_', '-'); let locale = window.__localeId__.replace('_', '-');
return Intl.NumberFormat(locale, { return Intl.NumberFormat(locale, {

View File

@@ -7,7 +7,7 @@
@include('partials.dashboard.boxes') @include('partials.dashboard.boxes')
<!-- row with account, budget and category data --> <!-- row with account, budget and category data -->
<div class="row mb-2" x-data="accounts"> <div class="row mb-2" x-data="accounts" x-bind="eventListeners">
<!-- column with 3 charts --> <!-- column with 3 charts -->
<div class="col-xl-8 col-lg-12 col-sm-12 col-xs-12"> <div class="col-xl-8 col-lg-12 col-sm-12 col-xs-12">
<!-- row with account chart --> <!-- row with account chart -->
@@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div class="modal fade" id="internalsModal" tabindex="-1" aria-labelledby="internalsModalLabel" <div x-data="index" class="modal fade" id="internalsModal" tabindex="-1" aria-labelledby="internalsModalLabel"
aria-hidden="true"> aria-hidden="true">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@@ -58,9 +58,17 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p> <div class="row mb-3">
Buttons. <label class="col-sm-4 col-form-label">Convert to native</label>
</p> <div class="col-sm-8">
<div class="form-check form-switch form-check-inline">
<label>
<input class="form-check-input" x-model="convertToNative" type="checkbox" @change="saveNativeSettings"> <span
>Yes no</span>
</label>
</div>
</div>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ __('firefly.close') }}</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ __('firefly.close') }}</button>