Enables manual settlement with fiat currencies
Adds support for settling receivables with fiat currencies like EUR and USD, in addition to sats. Updates the settlement dialog to handle fiat amounts and exchange rates, defaulting to cash payment when a fiat balance exists. Modifies the API to accept currency and amount_sats parameters and adjust the journal entry accordingly, converting the fiat amount to minor units (e.g., cents) for accounting purposes.
This commit is contained in:
parent
49f21da55a
commit
70013d1c29
4 changed files with 120 additions and 20 deletions
|
|
@ -96,7 +96,9 @@ window.app = Vue.createApp({
|
|||
invoice: null,
|
||||
paymentHash: null,
|
||||
checkWalletKey: null,
|
||||
pollIntervalId: null
|
||||
pollIntervalId: null,
|
||||
exchangeRate: 3571.43, // sats per EUR (TODO: fetch from API)
|
||||
originalCurrency: 'BTC' // Track original receivable currency
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -114,6 +116,25 @@ window.app = Vue.createApp({
|
|||
clearInterval(this.settleReceivableDialog.pollIntervalId)
|
||||
this.settleReceivableDialog.pollIntervalId = null
|
||||
}
|
||||
},
|
||||
'settleReceivableDialog.payment_method': function(newVal, oldVal) {
|
||||
// Convert amount when payment method changes between cash and lightning
|
||||
if (!oldVal) return
|
||||
|
||||
const isOldCash = ['cash', 'bank_transfer', 'check'].includes(oldVal)
|
||||
const isNewCash = ['cash', 'bank_transfer', 'check'].includes(newVal)
|
||||
|
||||
// Only convert if switching between cash and lightning
|
||||
if (isOldCash === isNewCash) return
|
||||
|
||||
// Convert from fiat to sats (when switching from cash to lightning)
|
||||
if (isOldCash && !isNewCash) {
|
||||
this.settleReceivableDialog.amount = this.settleReceivableDialog.maxAmount
|
||||
}
|
||||
// Convert from sats to fiat (when switching from lightning to cash)
|
||||
else if (!isOldCash && isNewCash) {
|
||||
this.settleReceivableDialog.amount = this.settleReceivableDialog.maxAmountFiat || 0
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -135,6 +156,30 @@ window.app = Vue.createApp({
|
|||
}
|
||||
return 'Amount (sats) *'
|
||||
},
|
||||
settlementAmountLabel() {
|
||||
const isCashPayment = ['cash', 'bank_transfer', 'check'].includes(
|
||||
this.settleReceivableDialog.payment_method
|
||||
)
|
||||
if (isCashPayment && this.settleReceivableDialog.fiatCurrency) {
|
||||
return `Settlement Amount (${this.settleReceivableDialog.fiatCurrency}) *`
|
||||
}
|
||||
return 'Settlement Amount (sats) *'
|
||||
},
|
||||
settlementMaxAmount() {
|
||||
const isCashPayment = ['cash', 'bank_transfer', 'check'].includes(
|
||||
this.settleReceivableDialog.payment_method
|
||||
)
|
||||
if (isCashPayment && this.settleReceivableDialog.maxAmountFiat) {
|
||||
return this.settleReceivableDialog.maxAmountFiat
|
||||
}
|
||||
return this.settleReceivableDialog.maxAmount
|
||||
},
|
||||
settlementAmountStep() {
|
||||
const isCashPayment = ['cash', 'bank_transfer', 'check'].includes(
|
||||
this.settleReceivableDialog.payment_method
|
||||
)
|
||||
return isCashPayment ? '0.01' : '1'
|
||||
},
|
||||
currencyOptions() {
|
||||
const options = [{label: 'Satoshis (default)', value: null}]
|
||||
this.currencies.forEach(curr => {
|
||||
|
|
@ -883,20 +928,29 @@ window.app = Vue.createApp({
|
|||
clearInterval(this.settleReceivableDialog.pollIntervalId)
|
||||
}
|
||||
|
||||
// Extract fiat balances (e.g., EUR)
|
||||
const fiatBalances = userBalance.fiat_balances || {}
|
||||
const fiatCurrency = Object.keys(fiatBalances)[0] || null // Get first fiat currency (e.g., 'EUR')
|
||||
const fiatAmount = fiatCurrency ? Math.abs(fiatBalances[fiatCurrency]) : 0
|
||||
|
||||
this.settleReceivableDialog = {
|
||||
show: true,
|
||||
user_id: userBalance.user_id,
|
||||
username: userBalance.username,
|
||||
maxAmount: Math.abs(userBalance.balance), // Convert negative to positive
|
||||
amount: Math.abs(userBalance.balance), // Default to full amount
|
||||
payment_method: 'lightning',
|
||||
maxAmount: Math.abs(userBalance.balance), // Sats amount
|
||||
maxAmountFiat: fiatAmount, // EUR or other fiat amount
|
||||
fiatCurrency: fiatCurrency, // 'EUR', 'USD', etc.
|
||||
amount: fiatCurrency ? fiatAmount : Math.abs(userBalance.balance), // Default to fiat if available, otherwise sats
|
||||
payment_method: fiatCurrency ? 'cash' : 'lightning', // Default to cash if fiat balance exists
|
||||
description: `Payment from ${userBalance.username}`,
|
||||
reference: '',
|
||||
loading: false,
|
||||
invoice: null,
|
||||
paymentHash: null,
|
||||
checkWalletKey: null,
|
||||
pollIntervalId: null
|
||||
pollIntervalId: null,
|
||||
exchangeRate: fiatAmount > 0 ? Math.abs(userBalance.balance) / fiatAmount : 3571.43, // Calculate rate from actual amounts
|
||||
originalCurrency: fiatCurrency || 'BTC'
|
||||
}
|
||||
},
|
||||
async generateSettlementInvoice() {
|
||||
|
|
@ -1018,17 +1072,30 @@ window.app = Vue.createApp({
|
|||
async submitSettleReceivable() {
|
||||
this.settleReceivableDialog.loading = true
|
||||
try {
|
||||
// Determine if this is a fiat payment
|
||||
const isCashPayment = ['cash', 'bank_transfer', 'check'].includes(
|
||||
this.settleReceivableDialog.payment_method
|
||||
)
|
||||
|
||||
const payload = {
|
||||
user_id: this.settleReceivableDialog.user_id,
|
||||
amount: this.settleReceivableDialog.amount,
|
||||
payment_method: this.settleReceivableDialog.payment_method,
|
||||
description: this.settleReceivableDialog.description,
|
||||
reference: this.settleReceivableDialog.reference || null,
|
||||
}
|
||||
|
||||
// Add currency info for fiat payments
|
||||
if (isCashPayment && this.settleReceivableDialog.fiatCurrency) {
|
||||
payload.currency = this.settleReceivableDialog.fiatCurrency
|
||||
payload.amount_sats = this.settleReceivableDialog.maxAmount
|
||||
}
|
||||
|
||||
const response = await LNbits.api.request(
|
||||
'POST',
|
||||
'/castle/api/v1/receivables/settle',
|
||||
this.g.user.wallets[0].adminkey,
|
||||
{
|
||||
user_id: this.settleReceivableDialog.user_id,
|
||||
amount: this.settleReceivableDialog.amount,
|
||||
payment_method: this.settleReceivableDialog.payment_method,
|
||||
description: this.settleReceivableDialog.description,
|
||||
reference: this.settleReceivableDialog.reference || null
|
||||
}
|
||||
payload
|
||||
)
|
||||
|
||||
this.$q.notify({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue