feat: allow invoice re-issue
This commit is contained in:
parent
4539e3a515
commit
b5aed1224a
4 changed files with 110 additions and 10 deletions
12
services.py
12
services.py
|
|
@ -407,7 +407,9 @@ async def _handle_incoming_dms(
|
||||||
merchant, new_dm, json_data
|
merchant, new_dm, json_data
|
||||||
)
|
)
|
||||||
if dm_reply:
|
if dm_reply:
|
||||||
await _reply_to_structured_dm(merchant, event, reply_type.value, dm_reply)
|
await reply_to_structured_dm(
|
||||||
|
merchant, event.pubkey, reply_type.value, dm_reply
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _handle_outgoing_dms(
|
async def _handle_outgoing_dms(
|
||||||
|
|
@ -474,15 +476,15 @@ async def _persist_dm(
|
||||||
return new_dm
|
return new_dm
|
||||||
|
|
||||||
|
|
||||||
async def _reply_to_structured_dm(
|
async def reply_to_structured_dm(
|
||||||
merchant: Merchant, event: NostrEvent, dm_type: int, dm_reply: str
|
merchant: Merchant, customer_pubkey: str, dm_type: int, dm_reply: str
|
||||||
):
|
):
|
||||||
dm_event = merchant.build_dm_event(dm_reply, event.pubkey)
|
dm_event = merchant.build_dm_event(dm_reply, customer_pubkey)
|
||||||
dm = PartialDirectMessage(
|
dm = PartialDirectMessage(
|
||||||
event_id=dm_event.id,
|
event_id=dm_event.id,
|
||||||
event_created_at=dm_event.created_at,
|
event_created_at=dm_event.created_at,
|
||||||
message=dm_reply,
|
message=dm_reply,
|
||||||
public_key=event.pubkey,
|
public_key=customer_pubkey,
|
||||||
type=dm_type,
|
type=dm_type,
|
||||||
)
|
)
|
||||||
await create_direct_message(merchant.id, dm)
|
await create_direct_message(merchant.id, dm)
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,16 @@
|
||||||
<div class="col-6 col-sm-8 q-pr-lg">
|
<div class="col-6 col-sm-8 q-pr-lg">
|
||||||
<q-input filled dense readonly disabled v-model.trim="props.row.invoice_id" type="text"></q-input>
|
<q-input filled dense readonly disabled v-model.trim="props.row.invoice_id" type="text"></q-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 col-sm-1"></div>
|
<div class="col-3">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col-3 q-pr-lg"></div>
|
||||||
|
|
||||||
|
<div class="col-9">
|
||||||
|
<q-btn @click="reissueOrderInvoice(props.row.id)" unelevated color="primary" type="submit" class="float-left" label="Reissue Invoice"></q-btn>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,27 @@ async function orderList(path) {
|
||||||
this.search.restoring = false
|
this.search.restoring = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
reissueOrderInvoice: async function (orderId) {
|
||||||
|
try {
|
||||||
|
const { data } = await LNbits.api.request(
|
||||||
|
'PUT',
|
||||||
|
`/nostrmarket/api/v1/order/${orderId}/reissue`,
|
||||||
|
this.adminkey
|
||||||
|
)
|
||||||
|
this.$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Order invoice reissued!'
|
||||||
|
})
|
||||||
|
|
||||||
|
const i = this.orders.map(o => o.id).indexOf(orderId)
|
||||||
|
console.log('### order', i)
|
||||||
|
if (i !== -1) {
|
||||||
|
this.orders[i] = { ...this.orders[i], ...data}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
LNbits.utils.notifyApiError(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
updateOrderShipped: async function () {
|
updateOrderShipped: async function () {
|
||||||
this.selectedOrder.shipped = !this.selectedOrder.shipped
|
this.selectedOrder.shipped = !this.selectedOrder.shipped
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
76
views_api.py
76
views_api.py
|
|
@ -53,6 +53,7 @@ from .crud import (
|
||||||
touch_merchant,
|
touch_merchant,
|
||||||
update_customer_no_unread_messages,
|
update_customer_no_unread_messages,
|
||||||
update_merchant,
|
update_merchant,
|
||||||
|
update_order,
|
||||||
update_order_shipped_status,
|
update_order_shipped_status,
|
||||||
update_product,
|
update_product,
|
||||||
update_stall,
|
update_stall,
|
||||||
|
|
@ -68,14 +69,19 @@ from .models import (
|
||||||
OrderStatusUpdate,
|
OrderStatusUpdate,
|
||||||
PartialDirectMessage,
|
PartialDirectMessage,
|
||||||
PartialMerchant,
|
PartialMerchant,
|
||||||
|
PartialOrder,
|
||||||
PartialProduct,
|
PartialProduct,
|
||||||
PartialStall,
|
PartialStall,
|
||||||
PartialZone,
|
PartialZone,
|
||||||
|
PaymentOption,
|
||||||
|
PaymentRequest,
|
||||||
Product,
|
Product,
|
||||||
Stall,
|
Stall,
|
||||||
Zone,
|
Zone,
|
||||||
)
|
)
|
||||||
from .services import (
|
from .services import (
|
||||||
|
reply_to_structured_dm,
|
||||||
|
build_order_with_payment,
|
||||||
create_or_update_order_from_dm,
|
create_or_update_order_from_dm,
|
||||||
sign_and_send_to_nostr,
|
sign_and_send_to_nostr,
|
||||||
update_merchant_to_nostr,
|
update_merchant_to_nostr,
|
||||||
|
|
@ -102,7 +108,7 @@ async def api_create_merchant(
|
||||||
await create_zone(
|
await create_zone(
|
||||||
merchant.id,
|
merchant.id,
|
||||||
PartialZone(
|
PartialZone(
|
||||||
id=f"online-{merchant.id}",
|
id=f"online-{merchant.public_key}",
|
||||||
name="Online",
|
name="Online",
|
||||||
currency="sat",
|
currency="sat",
|
||||||
cost=0,
|
cost=0,
|
||||||
|
|
@ -137,7 +143,7 @@ async def api_get_merchant(
|
||||||
merchant = await get_merchant_for_user(wallet.wallet.user)
|
merchant = await get_merchant_for_user(wallet.wallet.user)
|
||||||
if not merchant:
|
if not merchant:
|
||||||
return
|
return
|
||||||
|
|
||||||
merchant = await touch_merchant(wallet.wallet.user, merchant.id)
|
merchant = await touch_merchant(wallet.wallet.user, merchant.id)
|
||||||
last_dm_time = await get_last_direct_messages_time(merchant.id)
|
last_dm_time = await get_last_direct_messages_time(merchant.id)
|
||||||
|
|
||||||
|
|
@ -210,6 +216,7 @@ async def api_republish_merchant(
|
||||||
detail="Cannot get merchant",
|
detail="Cannot get merchant",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@nostrmarket_ext.put("/api/v1/merchant/{merchant_id}/toggle")
|
@nostrmarket_ext.put("/api/v1/merchant/{merchant_id}/toggle")
|
||||||
async def api_republish_merchant(
|
async def api_republish_merchant(
|
||||||
merchant_id: str,
|
merchant_id: str,
|
||||||
|
|
@ -237,7 +244,6 @@ async def api_republish_merchant(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@nostrmarket_ext.delete("/api/v1/merchant/{merchant_id}/nostr")
|
@nostrmarket_ext.delete("/api/v1/merchant/{merchant_id}/nostr")
|
||||||
async def api_delete_merchant(
|
async def api_delete_merchant(
|
||||||
merchant_id: str,
|
merchant_id: str,
|
||||||
|
|
@ -802,7 +808,13 @@ async def api_update_order_status(
|
||||||
await nostr_client.publish_nostr_event(dm_event)
|
await nostr_client.publish_nostr_event(dm_event)
|
||||||
await websocketUpdater(
|
await websocketUpdater(
|
||||||
merchant.id,
|
merchant.id,
|
||||||
json.dumps({ "type": f"dm:{dm.type}", "customerPubkey": order.public_key, "dm": dm.dict() }),
|
json.dumps(
|
||||||
|
{
|
||||||
|
"type": f"dm:{dm.type}",
|
||||||
|
"customerPubkey": order.public_key,
|
||||||
|
"dm": dm.dict(),
|
||||||
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return order
|
return order
|
||||||
|
|
@ -852,6 +864,62 @@ async def api_restore_orders(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@nostrmarket_ext.put("/api/v1/order/{order_id}/reissue")
|
||||||
|
async def api_reissue_order_invoice(
|
||||||
|
order_id: str,
|
||||||
|
wallet: WalletTypeInfo = Depends(require_admin_key),
|
||||||
|
) -> Order:
|
||||||
|
try:
|
||||||
|
merchant = await get_merchant_for_user(wallet.wallet.user)
|
||||||
|
assert merchant, "Merchant cannot be found"
|
||||||
|
|
||||||
|
data = await get_order(merchant.id, order_id)
|
||||||
|
assert data, "Order cannot be found"
|
||||||
|
|
||||||
|
order, invoice = await build_order_with_payment(
|
||||||
|
merchant.id, merchant.public_key, PartialOrder(**data.dict())
|
||||||
|
)
|
||||||
|
|
||||||
|
await update_order(
|
||||||
|
merchant.id,
|
||||||
|
order.id,
|
||||||
|
**{
|
||||||
|
"stall_id": order.stall_id,
|
||||||
|
"total": order.total,
|
||||||
|
"invoice_id": order.invoice_id,
|
||||||
|
"extra_data": json.dumps(order.extra.dict()),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
payment_req = PaymentRequest(
|
||||||
|
id=data.id, payment_options=[PaymentOption(type="ln", link=invoice)]
|
||||||
|
)
|
||||||
|
response = {
|
||||||
|
"type": DirectMessageType.PAYMENT_REQUEST.value,
|
||||||
|
**payment_req.dict(),
|
||||||
|
}
|
||||||
|
dm_reply = json.dumps(response, separators=(",", ":"), ensure_ascii=False)
|
||||||
|
|
||||||
|
await reply_to_structured_dm(
|
||||||
|
merchant,
|
||||||
|
order.public_key,
|
||||||
|
DirectMessageType.PAYMENT_REQUEST.value,
|
||||||
|
dm_reply,
|
||||||
|
)
|
||||||
|
|
||||||
|
return order
|
||||||
|
except AssertionError as ex:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
|
detail=str(ex),
|
||||||
|
)
|
||||||
|
except Exception as ex:
|
||||||
|
logger.warning(ex)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Cannot restore orders",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
######################################## DIRECT MESSAGES ########################################
|
######################################## DIRECT MESSAGES ########################################
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue