feat: filter orders

This commit is contained in:
Vlad Stan 2023-03-29 16:22:05 +03:00
parent 21ecf6c3c7
commit 5b03c324f1
5 changed files with 138 additions and 26 deletions

31
crud.py
View file

@ -445,21 +445,34 @@ async def get_order_by_event_id(merchant_id: str, event_id: str) -> Optional[Ord
return Order.from_row(row) if row else None
async def get_orders(merchant_id: str) -> List[Order]:
async def get_orders(merchant_id: str, **kwargs) -> List[Order]:
q = " AND ".join(
[f"{field[0]} = ?" for field in kwargs.items() if field[1] != None]
)
values = ()
if q:
q = f"AND {q}"
values = (v for v in kwargs.values() if v != None)
rows = await db.fetchall(
"SELECT * FROM nostrmarket.orders WHERE merchant_id = ? ORDER BY time DESC",
(merchant_id,),
f"SELECT * FROM nostrmarket.orders WHERE merchant_id = ? {q} ORDER BY time DESC",
(merchant_id, *values),
)
return [Order.from_row(row) for row in rows]
async def get_orders_for_stall(merchant_id: str, stall_id: str) -> List[Order]:
async def get_orders_for_stall(
merchant_id: str, stall_id: str, **kwargs
) -> List[Order]:
q = " AND ".join(
[f"{field[0]} = ?" for field in kwargs.items() if field[1] != None]
)
values = ()
if q:
q = f"AND {q}"
values = (v for v in kwargs.values() if v != None)
rows = await db.fetchall(
"SELECT * FROM nostrmarket.orders WHERE merchant_id = ? AND stall_id = ? ORDER BY time DESC",
(
merchant_id,
stall_id,
),
f"SELECT * FROM nostrmarket.orders WHERE merchant_id = ? AND stall_id = ? {q} ORDER BY time DESC",
(merchant_id, stall_id, *values),
)
return [Order.from_row(row) for row in rows]

View file

@ -1,18 +1,45 @@
<div>
<div class="row q-mb-md">
<div class="col">
<div class="col-3 q-pr-lg">
<q-select
v-model="search.publicKey"
:options="customers.map(c => ({label: buildCustomerLabel(c), value: c.public_key}))"
label="Customer"
emit-value
class="text-wrap"
>
</q-select>
</div>
<div class="col-3 q-pr-lg">
<q-select
v-model="search.isPaid"
:options="ternaryOptions"
label="Paid"
emit-value
>
</q-select>
</div>
<div class="col-3 q-pr-lg">
<q-select
v-model="search.isShipped"
:options="ternaryOptions"
label="Shipped"
emit-value
>
</q-select>
</div>
<div class="col-3">
<q-btn
unelevated
color="secondary"
outline
icon="refresh"
icon="search"
@click="getOrders()"
class="float-left"
>Refresh Orders</q-btn
class="float-right"
>Search Orders</q-btn
>
</div>
</div>
<div class="row">
<div class="row q-mt-md">
<div class="col">
<q-table
flat

View file

@ -12,6 +12,26 @@ async function orderList(path) {
shippingMessage: '',
showShipDialog: false,
filter: '',
search: {
publicKey: '',
isPaid: null,
isShipped: null
},
customers: [],
ternaryOptions: [
{
label: 'All',
value: null
},
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
],
ordersTable: {
columns: [
{
@ -83,11 +103,22 @@ async function orderList(path) {
getOrders: async function () {
try {
const ordersPath = this.stallId
? `/stall/order/${this.stallId}`
: '/order'
? `stall/order/${this.stallId}`
: 'order'
const query = []
if (this.search.publicKey) {
query.push(`pubkey=${this.search.publicKey}`)
}
if (this.search.isPaid) {
query.push(`paid=${this.search.isPaid}`)
}
if (this.search.isShipped) {
query.push(`shipped=${this.search.isShipped}`)
}
const {data} = await LNbits.api.request(
'GET',
'/nostrmarket/api/v1' + ordersPath,
`/nostrmarket/api/v1/${ordersPath}?${query.join('&')}`,
this.inkey
)
this.orders = data.map(s => ({...s, expanded: false}))
@ -129,10 +160,35 @@ async function orderList(path) {
},
customerSelected: function (customerPubkey) {
this.$emit('customer-selected', customerPubkey)
},
getCustomers: async function () {
try {
const {data} = await LNbits.api.request(
'GET',
'/nostrmarket/api/v1/customers',
this.inkey
)
this.customers = data
} catch (error) {
LNbits.utils.notifyApiError(error)
}
},
buildCustomerLabel: function (c) {
let label = `${c.profile.name || 'unknown'} ${c.profile.about || ''}`
if (c.unread_messages) {
label += `[new: ${c.unread_messages}]`
}
label += ` (${c.public_key.slice(0, 16)}...${c.public_key.slice(
c.public_key.length - 16
)}`
return label
}
},
created: async function () {
if (this.stallId) {
await this.getOrders()
}
await this.getCustomers()
}
})
}

View file

@ -62,9 +62,13 @@
<q-card class="q-mt-lg">
<q-card-section>
<div class="row">
<div class="col-2"></div>
<div class="col-8"></div>
<div class="col-2"></div>
<div class="col-12">
<order-list
:adminkey="g.user.wallets[0].adminkey"
:inkey="g.user.wallets[0].inkey"
@customer-selected="customerSelectedForOrder"
></order-list>
</div>
</div>
</q-card-section>
</q-card>

View file

@ -1,6 +1,6 @@
import json
from http import HTTPStatus
from typing import List, Optional
from typing import List, Optional, Union
from fastapi import Depends
from fastapi.exceptions import HTTPException
@ -448,12 +448,17 @@ async def api_get_stall_products(
@nostrmarket_ext.get("/api/v1/stall/order/{stall_id}")
async def api_get_stall_orders(
stall_id: str,
paid: Optional[bool] = None,
shipped: Optional[bool] = None,
pubkey: Optional[str] = None,
wallet: WalletTypeInfo = Depends(require_invoice_key),
):
try:
merchant = await get_merchant_for_user(wallet.wallet.user)
assert merchant, "Merchant cannot be found"
orders = await get_orders_for_stall(merchant.id, stall_id)
orders = await get_orders_for_stall(
merchant.id, stall_id, paid=paid, shipped=shipped, public_key=pubkey
)
return orders
except AssertionError as ex:
raise HTTPException(
@ -673,12 +678,19 @@ async def api_get_order(order_id: str, wallet: WalletTypeInfo = Depends(get_key_
@nostrmarket_ext.get("/api/v1/order")
async def api_get_orders(wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_get_orders(
paid: Optional[bool] = None,
shipped: Optional[bool] = None,
pubkey: Optional[str] = None,
wallet: WalletTypeInfo = Depends(get_key_type),
):
try:
merchant = await get_merchant_for_user(wallet.wallet.user)
assert merchant, "Merchant cannot be found"
orders = await get_orders(merchant.id)
orders = await get_orders(
merchant_id=merchant.id, paid=paid, shipped=shipped, public_key=pubkey
)
return orders
except AssertionError as ex:
raise HTTPException(