feat: show more details about the order

This commit is contained in:
Vlad Stan 2023-03-07 12:00:43 +02:00
parent 68795d2db2
commit 76af65c148
7 changed files with 72 additions and 27 deletions

View file

@ -318,8 +318,8 @@ async def delete_product(user_id: str, product_id: str) -> None:
async def create_order(user_id: str, o: Order) -> Order: async def create_order(user_id: str, o: Order) -> Order:
await db.execute( await db.execute(
f""" f"""
INSERT INTO nostrmarket.orders (user_id, id, event_id, pubkey, address, contact_data, order_items, stall_id, invoice_id, total) INSERT INTO nostrmarket.orders (user_id, id, event_id, pubkey, address, contact_data, extra_data, order_items, stall_id, invoice_id, total)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
( (
user_id, user_id,
@ -328,6 +328,7 @@ async def create_order(user_id: str, o: Order) -> Order:
o.pubkey, o.pubkey,
o.address, o.address,
json.dumps(o.contact.dict() if o.contact else {}), json.dumps(o.contact.dict() if o.contact else {}),
json.dumps(o.extra.dict()),
json.dumps([i.dict() for i in o.items]), json.dumps([i.dict() for i in o.items]),
o.stall_id, o.stall_id,
o.invoice_id, o.invoice_id,

View file

@ -80,6 +80,7 @@ async def m001_initial(db):
event_id TEXT, event_id TEXT,
pubkey TEXT NOT NULL, pubkey TEXT NOT NULL,
contact_data TEXT NOT NULL DEFAULT '{empty_object}', contact_data TEXT NOT NULL DEFAULT '{empty_object}',
extra_data TEXT NOT NULL DEFAULT '{empty_object}',
order_items TEXT NOT NULL, order_items TEXT NOT NULL,
address TEXT, address TEXT,
total REAL NOT NULL, total REAL NOT NULL,

View file

@ -6,7 +6,7 @@ from typing import List, Optional
from pydantic import BaseModel from pydantic import BaseModel
from lnbits.utils.exchange_rates import fiat_amount_as_satoshis from lnbits.utils.exchange_rates import btc_price, fiat_amount_as_satoshis
from .helpers import ( from .helpers import (
decrypt_message, decrypt_message,
@ -244,6 +244,12 @@ class Product(PartialProduct, Nostrable):
return product return product
class ProductOverview(BaseModel):
id: str
name: str
price: float
######################################## ORDERS ######################################## ######################################## ORDERS ########################################
@ -258,6 +264,20 @@ class OrderContact(BaseModel):
email: Optional[str] email: Optional[str]
class OrderExtra(BaseModel):
products: List[ProductOverview]
currency: str
btc_price: str
@classmethod
async def from_products(cls, products: List[Product]):
currency = products[0].config.currency
exchange_rate = (
(await btc_price(currency)) if currency and currency != "sat" else 1
)
return OrderExtra(products=products, currency=currency, btc_price=exchange_rate)
class PartialOrder(BaseModel): class PartialOrder(BaseModel):
id: str id: str
event_id: Optional[str] event_id: Optional[str]
@ -311,13 +331,15 @@ class Order(PartialOrder):
total: float total: float
paid: bool = False paid: bool = False
shipped: bool = False shipped: bool = False
time: int time: Optional[int]
extra: OrderExtra
@classmethod @classmethod
def from_row(cls, row: Row) -> "Order": def from_row(cls, row: Row) -> "Order":
contact = OrderContact(**json.loads(row["contact_data"])) contact = OrderContact(**json.loads(row["contact_data"]))
extra = OrderExtra(**json.loads(row["extra_data"]))
items = [OrderItem(**z) for z in json.loads(row["order_items"])] items = [OrderItem(**z) for z in json.loads(row["order_items"])]
order = cls(**dict(row), contact=contact, items=items) order = cls(**dict(row), contact=contact, items=items, extra=extra)
return order return order

View file

@ -63,20 +63,7 @@
</div> </div>
<div class="col-3 col-sm-1"></div> <div class="col-3 col-sm-1"></div>
</div> </div>
<div class="row items-center no-wrap q-mb-md">
<div class="col-3 q-pr-lg">Customer Public Key:</div>
<div class="col-6 col-sm-8 q-pr-lg">
<q-input
filled
dense
readonly
disabled
v-model.trim="props.row.pubkey"
type="text"
></q-input>
</div>
<div class="col-3 col-sm-1"></div>
</div>
<div class="row items-center no-wrap q-mb-md"> <div class="row items-center no-wrap q-mb-md">
<div class="col-3 q-pr-lg">Address:</div> <div class="col-3 q-pr-lg">Address:</div>
<div class="col-6 col-sm-8 q-pr-lg"> <div class="col-6 col-sm-8 q-pr-lg">
@ -91,23 +78,48 @@
</div> </div>
<div class="col-3 col-sm-1"></div> <div class="col-3 col-sm-1"></div>
</div> </div>
<div <div class="row items-center no-wrap q-mb-md">
v-if="props.row.contact.nostr" <div class="col-3 q-pr-lg">Products:</div>
class="row items-center no-wrap q-mb-md" <div class="col-8">
> <div class="row items-center no-wrap q-mb-md">
<div class="col-3 q-pr-lg">Nostr Contact Pubkey:</div> <div class="col-1">Quantity</div>
<div class="col-1"></div>
<div class="col-10">Name</div>
</div>
</div>
<div class="col-1"></div>
</div>
<div class="row items-center no-wrap q-mb-md">
<div class="col-3 q-pr-lg"></div>
<div class="col-8">
<div
v-for="item in props.row.items"
class="row items-center no-wrap q-mb-md"
>
<div class="col-1">{{item.quantity}}</div>
<div class="col-1">x</div>
<div class="col-10">
{{productOverview(props.row, item.product_id)}}
</div>
</div>
</div>
<div class="col-1"></div>
</div>
<div class="row items-center no-wrap q-mb-md">
<div class="col-3 q-pr-lg">Customer Public Key:</div>
<div class="col-6 col-sm-8 q-pr-lg"> <div class="col-6 col-sm-8 q-pr-lg">
<q-input <q-input
filled filled
dense dense
readonly readonly
disabled disabled
v-model.trim="props.row.contact.nostr" v-model.trim="props.row.pubkey"
type="text" type="text"
></q-input> ></q-input>
</div> </div>
<div class="col-3 col-sm-1"></div> <div class="col-3 col-sm-1"></div>
</div> </div>
<div <div
v-if="props.row.contact.phone" v-if="props.row.contact.phone"
class="row items-center no-wrap q-mb-md" class="row items-center no-wrap q-mb-md"

View file

@ -71,6 +71,13 @@ async function orderList(path) {
'YYYY-MM-DD HH:mm' 'YYYY-MM-DD HH:mm'
) )
}, },
productOverview: function (order, productId) {
product = order.extra.products.find(p => p.id === productId)
if (product) {
return `${product.name} (${product.price} ${order.extra.currency})`
}
return ''
},
getOrders: async function () { getOrders: async function () {
try { try {
const ordersPath = this.stallId const ordersPath = this.stallId

View file

@ -36,7 +36,7 @@ async def on_invoice_paid(payment: Payment) -> None:
if payment.extra.get("tag") != "nostrmarket": if payment.extra.get("tag") != "nostrmarket":
return return
print("### on_invoice_paid") print("### on_invoice_paid", json.dumps(payment))
async def subscribe_to_nostr_client(recieve_event_queue: Queue, send_req_queue: Queue): async def subscribe_to_nostr_client(recieve_event_queue: Queue, send_req_queue: Queue):
@ -124,7 +124,7 @@ async def handle_dirrect_message(
async def handle_new_order(order: PartialOrder): async def handle_new_order(order: PartialOrder):
### check that event_id not parsed already ### todo: check that event_id not parsed already
order.validate_order() order.validate_order()

View file

@ -46,6 +46,7 @@ from .models import (
Merchant, Merchant,
Nostrable, Nostrable,
Order, Order,
OrderExtra,
PartialMerchant, PartialMerchant,
PartialOrder, PartialOrder,
PartialProduct, PartialProduct,
@ -487,6 +488,7 @@ async def api_create_order(
stall_id=products[0].stall_id, stall_id=products[0].stall_id,
invoice_id=payment_hash, invoice_id=payment_hash,
total=total_amount, total=total_amount,
extra=await OrderExtra.from_products(products),
) )
await create_order(wallet.wallet.user, order) await create_order(wallet.wallet.user, order)