diff --git a/crud.py b/crud.py
index 94c1d20..326352c 100644
--- a/crud.py
+++ b/crud.py
@@ -8,7 +8,7 @@ from lnbits.helpers import urlsafe_short_hash
from .models import (
CreateDcaClientData, DcaClient, UpdateDcaClientData,
- CreateDepositData, DcaDeposit, UpdateDepositStatusData,
+ CreateDepositData, DcaDeposit, UpdateDepositData, UpdateDepositStatusData,
CreateDcaPaymentData, DcaPayment,
ClientBalanceSummary,
CreateLamassuConfigData, LamassuConfig, UpdateLamassuConfigData,
@@ -153,6 +153,28 @@ async def update_deposit_status(deposit_id: str, data: UpdateDepositStatusData)
return await get_deposit(deposit_id)
+async def update_deposit(deposit_id: str, data: UpdateDepositData) -> Optional[DcaDeposit]:
+ update_data = {k: v for k, v in data.dict().items() if v is not None}
+ if not update_data:
+ return await get_deposit(deposit_id)
+
+ set_clause = ", ".join([f"{k} = :{k}" for k in update_data.keys()])
+ update_data["id"] = deposit_id
+
+ await db.execute(
+ f"UPDATE satoshimachine.dca_deposits SET {set_clause} WHERE id = :id",
+ update_data
+ )
+ return await get_deposit(deposit_id)
+
+
+async def delete_deposit(deposit_id: str) -> None:
+ await db.execute(
+ "DELETE FROM satoshimachine.dca_deposits WHERE id = :id",
+ {"id": deposit_id}
+ )
+
+
# DCA Payment CRUD Operations
async def create_dca_payment(data: CreateDcaPaymentData) -> DcaPayment:
payment_id = urlsafe_short_hash()
diff --git a/models.py b/models.py
index e4bf64d..2fb60a6 100644
--- a/models.py
+++ b/models.py
@@ -60,6 +60,18 @@ class DcaDeposit(BaseModel):
confirmed_at: Optional[datetime]
+class UpdateDepositData(BaseModel):
+ amount: Optional[float] = None
+ currency: Optional[str] = None
+ notes: Optional[str] = None
+
+ @validator('amount')
+ def round_amount_to_cents(cls, v):
+ if v is not None:
+ return round(float(v), 2)
+ return v
+
+
class UpdateDepositStatusData(BaseModel):
status: str
notes: Optional[str] = None
diff --git a/static/js/index.js b/static/js/index.js
index 610ec0a..50b0fce 100644
--- a/static/js/index.js
+++ b/static/js/index.js
@@ -389,12 +389,12 @@ window.app = Vue.createApp({
}
if (this.depositFormDialog.data.id) {
- // Update existing deposit (mainly for notes/status)
+ // Update existing pending deposit
const { data: updatedDeposit } = await LNbits.api.request(
'PUT',
`/satmachineadmin/api/v1/dca/deposits/${this.depositFormDialog.data.id}`,
null,
- { status: this.depositFormDialog.data.status, notes: data.notes }
+ { amount: data.amount, currency: data.currency, notes: data.notes }
)
const index = this.deposits.findIndex(d => d.id === updatedDeposit.id)
if (index !== -1) {
@@ -460,6 +460,28 @@ window.app = Vue.createApp({
this.depositFormDialog.show = true
},
+ async deleteDeposit(deposit) {
+ try {
+ await LNbits.utils
+ .confirmDialog('Are you sure you want to delete this pending deposit?')
+ .onOk(async () => {
+ await LNbits.api.request(
+ 'DELETE',
+ `/satmachineadmin/api/v1/dca/deposits/${deposit.id}`,
+ null
+ )
+ this.deposits = this.deposits.filter(d => d.id !== deposit.id)
+ this.$q.notify({
+ type: 'positive',
+ message: 'Deposit deleted successfully',
+ timeout: 5000
+ })
+ })
+ } catch (error) {
+ LNbits.utils.notifyApiError(error)
+ }
+ },
+
// Export Methods
async exportClientsCSV() {
await LNbits.utils.exportCSV(this.clientsTable.columns, this.dcaClients)
diff --git a/templates/satmachineadmin/index.html b/templates/satmachineadmin/index.html
index 83de8c7..9c0f3a9 100644
--- a/templates/satmachineadmin/index.html
+++ b/templates/satmachineadmin/index.html
@@ -192,12 +192,21 @@
Confirm Deposit
Edit Deposit
+
+ Delete Deposit
+
diff --git a/views_api.py b/views_api.py
index a4a8b94..eb38da8 100644
--- a/views_api.py
+++ b/views_api.py
@@ -19,7 +19,9 @@ from .crud import (
create_deposit,
get_all_deposits,
get_deposit,
+ update_deposit,
update_deposit_status,
+ delete_deposit,
get_client_balance_summary,
# Lamassu config CRUD operations
create_lamassu_config,
@@ -39,6 +41,7 @@ from .models import (
UpdateDcaClientData,
CreateDepositData,
DcaDeposit,
+ UpdateDepositData,
UpdateDepositStatusData,
ClientBalanceSummary,
CreateLamassuConfigData,
@@ -161,6 +164,56 @@ async def api_update_deposit_status(
return updated_deposit
+@satmachineadmin_api_router.put("/api/v1/dca/deposits/{deposit_id}")
+async def api_update_deposit(
+ deposit_id: str,
+ data: UpdateDepositData,
+ user: User = Depends(check_super_user),
+) -> DcaDeposit:
+ """Update deposit fields (amount, currency, notes). Only pending deposits can be edited."""
+ deposit = await get_deposit(deposit_id)
+ if not deposit:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Deposit not found."
+ )
+
+ if deposit.status != "pending":
+ raise HTTPException(
+ status_code=HTTPStatus.BAD_REQUEST,
+ detail="Only pending deposits can be edited.",
+ )
+
+ updated_deposit = await update_deposit(deposit_id, data)
+ if not updated_deposit:
+ raise HTTPException(
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
+ detail="Failed to update deposit.",
+ )
+ return updated_deposit
+
+
+@satmachineadmin_api_router.delete("/api/v1/dca/deposits/{deposit_id}")
+async def api_delete_deposit(
+ deposit_id: str,
+ user: User = Depends(check_super_user),
+):
+ """Delete a deposit. Only pending deposits (not yet inserted into the machine) can be deleted."""
+ deposit = await get_deposit(deposit_id)
+ if not deposit:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Deposit not found."
+ )
+
+ if deposit.status != "pending":
+ raise HTTPException(
+ status_code=HTTPStatus.BAD_REQUEST,
+ detail="Only pending deposits can be deleted. Confirmed deposits have already been inserted into the machine.",
+ )
+
+ await delete_deposit(deposit_id)
+ return {"message": "Deposit deleted successfully"}
+
+
# Transaction Polling Endpoints