account edit page displays the debt amount instead of the balance for credit card and debt accounts

This commit is contained in:
MaysWind
2025-02-11 00:45:23 +08:00
parent 18a6d25ed6
commit ab58109e5e
12 changed files with 133 additions and 28 deletions
+30 -3
View File
@@ -53,6 +53,7 @@ const props = defineProps<{
readonly?: boolean;
hide?: boolean;
enableRules?: boolean;
flipNegative?: boolean;
modelValue: number;
}>();
@@ -90,7 +91,7 @@ const rules = [
}
];
const currentValue = ref<string>(getFormattedValue(props.modelValue));
const currentValue = ref<string>(getInitedFormattedValue(props.modelValue, props.flipNegative));
const prependText = computed<string | undefined>(() => {
if (!props.currency || !props.showCurrency) {
@@ -292,6 +293,14 @@ function getValidFormattedValue(value: number, textualValue: string, hasDecimalS
return textualValue;
}
function getInitedFormattedValue(value: number, flipNegative?: boolean): string {
if (flipNegative) {
value = -value;
}
return getFormattedValue(value);
}
function getFormattedValue(value: number): string {
if (!Number.isNaN(value) && Number.isFinite(value)) {
const digitGroupingSymbol = getCurrentDigitGroupingSymbol();
@@ -309,7 +318,15 @@ function getDisplayCurrencyPrependAndAppendText(): CurrencyPrependAndAppendText
}
watch(() => props.currency, () => {
const newStringValue = getFormattedValue(props.modelValue);
const newStringValue = getInitedFormattedValue(props.modelValue, props.flipNegative);
if (!(newStringValue === '0' && currentValue.value === '')) {
currentValue.value = newStringValue;
}
});
watch(() => props.flipNegative, (newValue) => {
const newStringValue = getInitedFormattedValue(props.modelValue, newValue);
if (!(newStringValue === '0' && currentValue.value === '')) {
currentValue.value = newStringValue;
@@ -317,6 +334,10 @@ watch(() => props.currency, () => {
});
watch(() => props.modelValue, (newValue) => {
if (props.flipNegative) {
newValue = -newValue;
}
const numericCurrentValue = parseAmount(currentValue.value);
if (newValue !== numericCurrentValue) {
@@ -346,7 +367,13 @@ watch(currentValue, (newValue) => {
if (finalValue !== newValue) {
currentValue.value = finalValue;
} else {
emit('update:modelValue', parseAmount(finalValue));
let value: number = parseAmount(finalValue);
if (props.flipNegative) {
value = -value;
}
emit('update:modelValue', value);
}
});
</script>
+22 -5
View File
@@ -66,7 +66,7 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { ref, computed, watch } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { useI18nUIComponents } from '@/lib/ui/mobile.ts';
@@ -75,10 +75,11 @@ import { ALL_CURRENCIES } from '@/consts/currency.ts';
import { isString, isNumber, removeAll } from '@/lib/common.ts';
const props = defineProps<{
modelValue: number | string;
modelValue: number;
minValue?: number;
maxValue?: number;
currency?: string;
flipNegative?: boolean;
show: boolean;
}>();
@@ -99,7 +100,7 @@ const { showToast } = useI18nUIComponents();
const previousValue = ref<string>('');
const currentSymbol = ref<string>('');
const currentValue = ref<string>(getStringValue(props.modelValue));
const currentValue = ref<string>(getInitedStringValue(props.modelValue, props.flipNegative));
const decimalSeparator = computed<string>(() => getCurrentDecimalSeparator());
@@ -140,6 +141,14 @@ const confirmText = computed<string>(() => {
}
});
function getInitedStringValue(value: number, flipNegative?: boolean): string {
if (flipNegative) {
value = -value;
}
return getStringValue(value);
}
function getStringValue(value: number | string): string {
if (!isNumber(value) && !isString(value)) {
return '';
@@ -333,7 +342,11 @@ function confirm(): boolean {
return true;
} else {
const value = parseAmount(currentValue.value);
let value: number = parseAmount(currentValue.value);
if (props.flipNegative) {
value = -value;
}
emit('update:modelValue', value);
close();
@@ -347,12 +360,16 @@ function close(): void {
}
function onSheetOpen(): void {
currentValue.value = getStringValue(props.modelValue);
currentValue.value = getInitedStringValue(props.modelValue, props.flipNegative);
}
function onSheetClosed(): void {
close();
}
watch(() => props.flipNegative, (newValue) => {
currentValue.value = getInitedStringValue(props.modelValue, newValue);
});
</script>
<style>
+14 -10
View File
@@ -25,27 +25,31 @@ export class AccountCategory implements TypeAndName {
private static readonly allInstances: AccountCategory[] = [];
private static readonly allInstancesByType: Record<number, AccountCategory> = {};
public static readonly Cash = new AccountCategory(1, 1, 'Cash', '1');
public static readonly CheckingAccount = new AccountCategory(2, 2, 'Checking Account', '100');
public static readonly SavingsAccount = new AccountCategory(8, 3, 'Savings Account', '100');
public static readonly CreditCard = new AccountCategory(3, 4, 'Credit Card', '100');
public static readonly VirtualAccount = new AccountCategory(4, 5, 'Virtual Account', '500');
public static readonly DebtAccount = new AccountCategory(5, 6, 'Debt Account', '600');
public static readonly Receivables = new AccountCategory(6, 7, 'Receivables', '700');
public static readonly CertificateOfDeposit = new AccountCategory(9, 8, 'Certificate of Deposit', '110');
public static readonly InvestmentAccount = new AccountCategory(7, 9, 'Investment Account', '800');
public static readonly Cash = new AccountCategory(1, 1, 'Cash', true, false, '1');
public static readonly CheckingAccount = new AccountCategory(2, 2, 'Checking Account', true, false, '100');
public static readonly SavingsAccount = new AccountCategory(8, 3, 'Savings Account', true, false, '100');
public static readonly CreditCard = new AccountCategory(3, 4, 'Credit Card', false, true, '100');
public static readonly VirtualAccount = new AccountCategory(4, 5, 'Virtual Account', true, false, '500');
public static readonly DebtAccount = new AccountCategory(5, 6, 'Debt Account', false, true, '600');
public static readonly Receivables = new AccountCategory(6, 7, 'Receivables', true, false, '700');
public static readonly CertificateOfDeposit = new AccountCategory(9, 8, 'Certificate of Deposit', true, false, '110');
public static readonly InvestmentAccount = new AccountCategory(7, 9, 'Investment Account', true, false, '800');
public static readonly Default = AccountCategory.Cash;
public readonly type: number;
public readonly displayOrder: number;
public readonly name: string;
public readonly isAsset: boolean;
public readonly isLiability: boolean
public readonly defaultAccountIconId: string;
private constructor(type: number, displayOrder: number, name: string, defaultAccountIconId: string) {
private constructor(type: number, displayOrder: number, name: string, isAsset: boolean, isLiability: boolean, defaultAccountIconId: string) {
this.type = type;
this.displayOrder = displayOrder;
this.name = name;
this.isAsset = isAsset;
this.isLiability = isLiability;
this.defaultAccountIconId = defaultAccountIconId;
AccountCategory.allInstances.push(this);
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "Teilkontofarbe",
"Currency": "Währung",
"Account Balance": "Kontostand",
"Account Outstanding Balance": "Account Outstanding Balance",
"Sub-account Balance": "Teilkontostand",
"Sub-account Outstanding Balance": "Sub-account Outstanding Balance",
"Balance Time": "Saldozeit",
"Sub-account Balance Time": "Teilkontosaldozeit",
"Statement Date": "Abrechnungsdatum",
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "Sub-account Color",
"Currency": "Currency",
"Account Balance": "Account Balance",
"Account Outstanding Balance": "Account Outstanding Balance",
"Sub-account Balance": "Sub-account Balance",
"Sub-account Outstanding Balance": "Sub-account Outstanding Balance",
"Balance Time": "Balance Time",
"Sub-account Balance Time": "Sub-account Balance Time",
"Statement Date": "Statement Date",
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "Color de subcuenta",
"Currency": "Divisa",
"Account Balance": "Balance de cuenta",
"Account Outstanding Balance": "Account Outstanding Balance",
"Sub-account Balance": "Balance de subcuenta",
"Sub-account Outstanding Balance": "Sub-account Outstanding Balance",
"Balance Time": "Fecha del balance",
"Sub-account Balance Time": "Fecha del balance de la subcuenta",
"Statement Date": "Fecha de declaración",
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "Цвет субсчета",
"Currency": "Валюта",
"Account Balance": "Баланс счета",
"Account Outstanding Balance": "Account Outstanding Balance",
"Sub-account Balance": "Баланс субсчета",
"Sub-account Outstanding Balance": "Sub-account Outstanding Balance",
"Balance Time": "Время баланса",
"Sub-account Balance Time": "Время баланса субсчета",
"Statement Date": "Дата выписки",
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "Màu sắc tài khoản phụ",
"Currency": "Tiền tệ",
"Account Balance": "Số dư tài khoản",
"Account Outstanding Balance": "Account Outstanding Balance",
"Sub-account Balance": "Số dư tài khoản phụ",
"Sub-account Outstanding Balance": "Sub-account Outstanding Balance",
"Balance Time": "Thời gian số dư",
"Sub-account Balance Time": "Thời gian số dư tài khoản phụ",
"Statement Date": "Statement Date",
+2
View File
@@ -1475,7 +1475,9 @@
"Sub-account Color": "子账户颜色",
"Currency": "货币",
"Account Balance": "账户余额",
"Account Outstanding Balance": "账户未清余额",
"Sub-account Balance": "子账户余额",
"Sub-account Outstanding Balance": "子账户未清余额",
"Balance Time": "余额时间",
"Sub-account Balance Time": "子账户余额时间",
"Statement Date": "账单日",
+33 -4
View File
@@ -18,11 +18,12 @@ export class Account implements AccountInfoResponse {
public comment: string;
public creditCardStatementDate?: number;
public displayOrder: number;
public isAsset?: boolean;
public isLiability?: boolean;
public visible: boolean;
public subAccounts?: Account[];
private readonly _isAsset?: boolean;
private readonly _isLiability?: boolean;
protected constructor(id: string, name: string, parentId: string, category: number, type: number, icon: string, color: string, currency: string, balance: number, comment: string, displayOrder: number, visible: boolean, balanceTime?: number, creditCardStatementDate?: number, isAsset?: boolean, isLiability?: boolean, subAccounts?: Account[]) {
this.id = id;
this.name = name;
@@ -38,8 +39,8 @@ export class Account implements AccountInfoResponse {
this.displayOrder = displayOrder;
this.visible = visible;
this.creditCardStatementDate = creditCardStatementDate;
this.isAsset = isAsset;
this.isLiability = isLiability;
this._isAsset = isAsset;
this._isLiability = isLiability;
if (typeof(subAccounts) !== 'undefined') {
this.subAccounts = subAccounts;
@@ -48,6 +49,34 @@ export class Account implements AccountInfoResponse {
}
}
public get isAsset(): boolean {
if (typeof(this._isAsset) !== 'undefined') {
return this._isAsset;
}
const accountCategory = AccountCategory.valueOf(this.category);
if (accountCategory) {
return accountCategory.isAsset;
}
return false;
}
public get isLiability(): boolean {
if (typeof(this._isLiability) !== 'undefined') {
return this._isLiability;
}
const accountCategory = AccountCategory.valueOf(this.category);
if (accountCategory) {
return accountCategory.isLiability;
}
return false;
}
public get hidden(): boolean {
return !this.visible;
}
@@ -146,8 +146,9 @@
:persistent-placeholder="true"
:currency="selectedAccount.currency"
:show-currency="true"
:label="currentAccountIndex < 0 ? tt('Account Balance') : tt('Sub-account Balance')"
:placeholder="currentAccountIndex < 0 ? tt('Account Balance') : tt('Sub-account Balance')"
:flip-negative="account.isLiability"
:label="accountAmountTitle"
:placeholder="accountAmountTitle"
v-model="selectedAccount.balance"/>
</v-col>
<v-col cols="12" md="6" v-show="selectedAccount.balance"
@@ -274,6 +275,14 @@ const selectedAccount = computed<Account>(() => {
return subAccounts.value[currentAccountIndex.value];
});
const accountAmountTitle = computed<string>(() => {
if (currentAccountIndex.value < 0) {
return account.value.isLiability ? tt('Account Outstanding Balance') : tt('Account Balance');
} else {
return account.value.isLiability ? tt('Sub-account Outstanding Balance') : tt('Sub-account Balance');
}
});
let resolveFunc: ((value: AccountEditResponse) => void) | null = null;
let rejectFunc: ((reason?: unknown) => void) | null = null;
+11 -4
View File
@@ -191,13 +191,14 @@
link="#" no-chevron
class="list-item-with-header-and-title"
:class="{ 'disabled': editAccountId }"
:header="tt('Account Balance')"
:title="formatAmountWithCurrency(account.balance, account.currency)"
:header="account.isLiability ? tt('Account Outstanding Balance') : tt('Account Balance')"
:title="formatAccountDisplayBalance(account)"
@click="accountContext.showBalanceSheet = true"
>
<number-pad-sheet :min-value="TRANSACTION_MIN_AMOUNT"
:max-value="TRANSACTION_MAX_AMOUNT"
:currency="account.currency"
:flip-negative="account.isLiability"
v-model:show="accountContext.showBalanceSheet"
v-model="account.balance"
></number-pad-sheet>
@@ -419,13 +420,14 @@
link="#" no-chevron
class="list-item-with-header-and-title"
:class="{ 'disabled': editAccountId }"
:header="tt('Sub-account Balance')"
:title="formatAmountWithCurrency(subAccount.balance, subAccount.currency)"
:header="account.isLiability ? tt('Sub-account Outstanding Balance') : tt('Sub-account Balance')"
:title="formatAccountDisplayBalance(subAccount)"
@click="subAccountContexts[idx].showBalanceSheet = true"
>
<number-pad-sheet :min-value="TRANSACTION_MIN_AMOUNT"
:max-value="TRANSACTION_MAX_AMOUNT"
:currency="subAccount.currency"
:flip-negative="account.isLiability"
v-model:show="subAccountContexts[idx].showBalanceSheet"
v-model="subAccount.balance"
></number-pad-sheet>
@@ -566,6 +568,11 @@ const showAccountTypeSheet = ref<boolean>(false);
const showMoreActionSheet = ref<boolean>(false);
const showDeleteActionSheet = ref<boolean>(false);
function formatAccountDisplayBalance(selectedAccount: Account): string {
const balance = account.value.isLiability ? -selectedAccount.balance : selectedAccount.balance;
return formatAmountWithCurrency(balance, selectedAccount.currency);
}
function formatAccountBalanceDate(account: Account): string {
if (!isDefined(account.balanceTime)) {
return '';