mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 06:57:35 +08:00
account edit page displays the debt amount instead of the balance for credit card and debt accounts
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Дата выписки",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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 '';
|
||||
|
||||
Reference in New Issue
Block a user