From 49f21da55ab5de889dd185629ad16c4ded553eb0 Mon Sep 17 00:00:00 2001 From: padreug Date: Thu, 23 Oct 2025 04:10:06 +0200 Subject: [PATCH] Refactors lightning account naming Standardizes lightning account name to "Assets:Bitcoin:Lightning" for consistency. Updates the database and code to reflect this change, ensuring that payment processing and account management use the new name. Prevents polling of receivable dialog after settlement. --- migrations.py | 16 +++++++++++++++- static/js/index.js | 36 +++++++++++++++++++++++------------- views_api.py | 40 +++++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/migrations.py b/migrations.py index 611848c..468057e 100644 --- a/migrations.py +++ b/migrations.py @@ -217,7 +217,7 @@ async def m006_hierarchical_account_names(db): # Assets "cash": "Assets:Cash", "bank": "Assets:Bank", - "lightning": "Assets:Lightning:Balance", + "lightning": "Assets:Bitcoin:Lightning", "accounts_receivable": "Assets:Receivable", # Liabilities @@ -318,3 +318,17 @@ async def m007_balance_assertions(db): CREATE INDEX idx_balance_assertions_date ON balance_assertions (date); """ ) + + +async def m008_rename_lightning_account(db): + """ + Rename Lightning account from Assets:Lightning:Balance to Assets:Bitcoin:Lightning + for better naming consistency. + """ + await db.execute( + """ + UPDATE accounts + SET name = 'Assets:Bitcoin:Lightning' + WHERE name = 'Assets:Lightning:Balance' + """ + ) diff --git a/static/js/index.js b/static/js/index.js index ff91f69..82272a0 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -958,10 +958,14 @@ window.app = Vue.createApp({ ) if (response.data && response.data.paid) { + // Stop polling immediately + clearInterval(this.settleReceivableDialog.pollIntervalId) + this.settleReceivableDialog.pollIntervalId = null + // Record payment in accounting - this creates the journal entry // that settles the receivable try { - await LNbits.api.request( + const recordResponse = await LNbits.api.request( 'POST', '/castle/api/v1/record-payment', this.g.user.wallets[0].adminkey, @@ -969,21 +973,27 @@ window.app = Vue.createApp({ payment_hash: paymentHash } ) + console.log('Settlement payment recorded:', recordResponse.data) + + this.$q.notify({ + type: 'positive', + message: 'Payment received! Receivable has been settled.', + timeout: 3000 + }) + + // Close dialog and refresh + this.settleReceivableDialog.show = false + await this.loadBalance() + await this.loadTransactions() + await this.loadAllUserBalances() } catch (error) { console.error('Error recording settlement payment:', error) + this.$q.notify({ + type: 'negative', + message: 'Payment detected but failed to record: ' + (error.response?.data?.detail || error.message), + timeout: 5000 + }) } - - this.$q.notify({ - type: 'positive', - message: 'Payment received! Receivable has been settled.', - timeout: 3000 - }) - - // Close dialog and refresh - this.settleReceivableDialog.show = false - await this.loadBalance() - await this.loadTransactions() - await this.loadAllUserBalances() return true } return false diff --git a/views_api.py b/views_api.py index b134e29..e256320 100644 --- a/views_api.py +++ b/views_api.py @@ -623,25 +623,31 @@ async def api_record_payment( """ from lnbits.core.crud.payments import get_standalone_payment - # Get the payment details - payment = await get_standalone_payment(data.payment_hash) + # Get the payment details (incoming=True to get the invoice, not the payment) + payment = await get_standalone_payment(data.payment_hash, incoming=True) if not payment: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Payment not found" ) - if not payment.paid: + if payment.pending: raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, detail="Payment not yet paid" + status_code=HTTPStatus.BAD_REQUEST, detail="Payment not yet settled" ) # Get user_id from payment metadata (set during invoice generation) - # This allows admins to record payments on behalf of users - target_user_id = wallet.wallet.user # Default to wallet user + target_user_id = None if payment.extra and isinstance(payment.extra, dict): - metadata_user_id = payment.extra.get("user_id") - if metadata_user_id: - target_user_id = metadata_user_id + target_user_id = payment.extra.get("user_id") + + if not target_user_id: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail="Payment metadata missing user_id. Cannot determine which user to credit.", + ) + + # Convert amount from millisatoshis to satoshis + amount_sats = payment.amount // 1000 # Get user's receivable account (what user owes) user_receivable = await get_or_create_user_account( @@ -649,14 +655,14 @@ async def api_record_payment( ) # Get lightning account - lightning_account = await get_account_by_name("Lightning Balance") + lightning_account = await get_account_by_name("Assets:Bitcoin:Lightning") if not lightning_account: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Lightning account not found" ) # Create journal entry to record payment - # DR Lightning Balance, CR Accounts Receivable (User) + # DR Assets:Bitcoin:Lightning, CR Assets:Receivable (User) # This reduces what the user owes # Add meta information for audit trail @@ -675,14 +681,14 @@ async def api_record_payment( lines=[ CreateEntryLine( account_id=lightning_account.id, - debit=payment.amount, + debit=amount_sats, credit=0, description="Lightning payment received", ), CreateEntryLine( account_id=user_receivable.id, debit=0, - credit=payment.amount, + credit=amount_sats, description="Payment applied to balance", ), ], @@ -716,14 +722,14 @@ async def api_pay_user( ) # Get lightning account - lightning_account = await get_account_by_name("Lightning Balance") + lightning_account = await get_account_by_name("Assets:Bitcoin:Lightning") if not lightning_account: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Lightning account not found" ) # Create journal entry - # DR Accounts Payable (User), CR Lightning Balance + # DR Liabilities:Payable (User), CR Assets:Bitcoin:Lightning entry_data = CreateJournalEntry( description=f"Payment to user {user_id[:8]}", lines=[ @@ -1044,11 +1050,11 @@ async def api_approve_manual_payment_request( ) # Get the Lightning asset account - lightning_account = await get_account_by_name("Lightning Balance") + lightning_account = await get_account_by_name("Assets:Bitcoin:Lightning") if not lightning_account: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, - detail="Lightning Balance account not found", + detail="Lightning account not found", ) # Create journal entry: Debit Lightning (asset decreased), Credit Accounts Payable (liability increased)