Adds receivable entry functionality
Implements the ability to record receivables (user owes the castle). Adds API endpoint for creating receivable entries, which includes currency conversion to satoshis if fiat currency is provided. Integrates a UI component (receivable dialog) for superusers to record debts owed by users, enhancing financial tracking capabilities.
This commit is contained in:
parent
b7e4e05469
commit
2a14dd2e62
4 changed files with 250 additions and 3 deletions
|
|
@ -12,6 +12,7 @@ window.app = Vue.createApp({
|
|||
transactions: [],
|
||||
accounts: [],
|
||||
currencies: [],
|
||||
users: [],
|
||||
settings: null,
|
||||
userWalletSettings: null,
|
||||
isAdmin: false,
|
||||
|
|
@ -42,6 +43,16 @@ window.app = Vue.createApp({
|
|||
show: false,
|
||||
userWalletId: '',
|
||||
loading: false
|
||||
},
|
||||
receivableDialog: {
|
||||
show: false,
|
||||
selectedUser: '',
|
||||
description: '',
|
||||
amount: null,
|
||||
revenueAccount: '',
|
||||
reference: '',
|
||||
currency: null,
|
||||
loading: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -49,18 +60,37 @@ window.app = Vue.createApp({
|
|||
expenseAccounts() {
|
||||
return this.accounts.filter(a => a.account_type === 'expense')
|
||||
},
|
||||
revenueAccounts() {
|
||||
return this.accounts.filter(a => a.account_type === 'revenue')
|
||||
},
|
||||
amountLabel() {
|
||||
if (this.expenseDialog.currency) {
|
||||
return `Amount (${this.expenseDialog.currency}) *`
|
||||
}
|
||||
return 'Amount (sats) *'
|
||||
},
|
||||
receivableAmountLabel() {
|
||||
if (this.receivableDialog.currency) {
|
||||
return `Amount (${this.receivableDialog.currency}) *`
|
||||
}
|
||||
return 'Amount (sats) *'
|
||||
},
|
||||
currencyOptions() {
|
||||
const options = [{label: 'Satoshis (default)', value: null}]
|
||||
this.currencies.forEach(curr => {
|
||||
options.push({label: curr, value: curr})
|
||||
})
|
||||
return options
|
||||
},
|
||||
userOptions() {
|
||||
const options = []
|
||||
this.users.forEach(user => {
|
||||
options.push({
|
||||
label: user.username,
|
||||
value: user.user_wallet_id
|
||||
})
|
||||
})
|
||||
return options
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -129,6 +159,18 @@ window.app = Vue.createApp({
|
|||
LNbits.utils.notifyApiError(error)
|
||||
}
|
||||
},
|
||||
async loadUsers() {
|
||||
try {
|
||||
const response = await LNbits.api.request(
|
||||
'GET',
|
||||
'/castle/api/v1/users',
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
this.users = response.data
|
||||
} catch (error) {
|
||||
console.error('Error loading users:', error)
|
||||
}
|
||||
},
|
||||
async loadSettings() {
|
||||
try {
|
||||
// Try with admin key first to check settings
|
||||
|
|
@ -304,6 +346,43 @@ window.app = Vue.createApp({
|
|||
this.payDialog.amount = Math.abs(this.balance.balance)
|
||||
this.payDialog.show = true
|
||||
},
|
||||
async showReceivableDialog() {
|
||||
// Load users if not already loaded
|
||||
if (this.users.length === 0 && this.isSuperUser) {
|
||||
await this.loadUsers()
|
||||
}
|
||||
this.receivableDialog.show = true
|
||||
},
|
||||
async submitReceivable() {
|
||||
this.receivableDialog.loading = true
|
||||
try {
|
||||
await LNbits.api.request(
|
||||
'POST',
|
||||
'/castle/api/v1/entries/receivable',
|
||||
this.g.user.wallets[0].adminkey,
|
||||
{
|
||||
description: this.receivableDialog.description,
|
||||
amount: this.receivableDialog.amount,
|
||||
revenue_account: this.receivableDialog.revenueAccount,
|
||||
user_wallet: this.receivableDialog.selectedUser,
|
||||
reference: this.receivableDialog.reference || null,
|
||||
currency: this.receivableDialog.currency || null
|
||||
}
|
||||
)
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Receivable added successfully'
|
||||
})
|
||||
this.receivableDialog.show = false
|
||||
this.resetReceivableDialog()
|
||||
await this.loadBalance()
|
||||
await this.loadTransactions()
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
} finally {
|
||||
this.receivableDialog.loading = false
|
||||
}
|
||||
},
|
||||
resetExpenseDialog() {
|
||||
this.expenseDialog.description = ''
|
||||
this.expenseDialog.amount = null
|
||||
|
|
@ -312,6 +391,14 @@ window.app = Vue.createApp({
|
|||
this.expenseDialog.reference = ''
|
||||
this.expenseDialog.currency = null
|
||||
},
|
||||
resetReceivableDialog() {
|
||||
this.receivableDialog.selectedUser = ''
|
||||
this.receivableDialog.description = ''
|
||||
this.receivableDialog.amount = null
|
||||
this.receivableDialog.revenueAccount = ''
|
||||
this.receivableDialog.reference = ''
|
||||
this.receivableDialog.currency = null
|
||||
},
|
||||
formatSats(amount) {
|
||||
return new Intl.NumberFormat().format(amount)
|
||||
},
|
||||
|
|
@ -330,5 +417,9 @@ window.app = Vue.createApp({
|
|||
await this.loadCurrencies()
|
||||
await this.loadSettings()
|
||||
await this.loadUserWallet()
|
||||
// Load users if super user (for receivable dialog)
|
||||
if (this.isSuperUser) {
|
||||
await this.loadUsers()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue