diff --git a/lnbits/extensions/shop/crud.py b/lnbits/extensions/shop/crud.py
index 1986829e2..dceaa203b 100644
--- a/lnbits/extensions/shop/crud.py
+++ b/lnbits/extensions/shop/crud.py
@@ -148,16 +148,18 @@ async def create_shop_stall(data: createStalls) -> Stalls:
id,
wallet,
name,
+ currency,
publickey,
relays,
shippingzones
)
- VALUES (?, ?, ?, ?, ?, ?)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
stall_id,
data.wallet,
data.name,
+ data.currency,
data.publickey,
data.relays,
data.shippingzones,
@@ -447,17 +449,31 @@ async def get_shop_chat_by_merchant(ids: List[str]) -> List[ChatMessage]:
async def get_shop_settings(user) -> Optional[ShopSettings]:
- row = await db.fetchone("SELECT * FROM shop.settings WHERE 'user = ?", (user,))
+ row = await db.fetchone("""SELECT * FROM shop.settings WHERE "user" = ?""", (user,))
return ShopSettings(**row) if row else None
-async def set_shop_settings(user: str, data) -> Optional[ShopSettings]:
+async def create_shop_settings(user: str, data):
await db.execute(
- f"""
+ """
+ INSERT INTO shop.settings ("user", currency, fiat_base_multiplier)
+ VALUES (?, ?, ?)
+ """,
+ (
+ user,
+ data.currency,
+ data.fiat_base_multiplier,
+ ),
+ )
+
+
+async def set_shop_settings(user: str, data):
+ await db.execute(
+ """
UPDATE shop.settings
SET currency = ?, fiat_base_multiplier = ?
- WHERE 'user' = ?;
+ WHERE "user" = ?;
""",
(
data.currency,
diff --git a/lnbits/extensions/shop/migrations.py b/lnbits/extensions/shop/migrations.py
index 2936695eb..e6592dffb 100644
--- a/lnbits/extensions/shop/migrations.py
+++ b/lnbits/extensions/shop/migrations.py
@@ -21,6 +21,7 @@ async def m001_initial(db):
id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
name TEXT NOT NULL,
+ currency TEXT,
publickey TEXT,
relays TEXT,
shippingzones TEXT NOT NULL,
diff --git a/lnbits/extensions/shop/models.py b/lnbits/extensions/shop/models.py
index 2282cef0f..ed6342f0b 100644
--- a/lnbits/extensions/shop/models.py
+++ b/lnbits/extensions/shop/models.py
@@ -19,6 +19,7 @@ class Stalls(BaseModel):
id: str
wallet: str
name: str
+ currency: str
publickey: Optional[str]
relays: Optional[str]
shippingzones: str
@@ -27,6 +28,7 @@ class Stalls(BaseModel):
class createStalls(BaseModel):
wallet: str = Query(...)
name: str = Query(...)
+ currency: str = Query("sat")
publickey: str = Query(None)
relays: str = Query(None)
shippingzones: str = Query(...)
@@ -38,7 +40,7 @@ class createProduct(BaseModel):
categories: str = Query(None)
description: str = Query(None)
image: str = Query(None)
- price: int = Query(0, ge=0)
+ price: float = Query(0, ge=0)
quantity: int = Query(0, ge=0)
@@ -49,19 +51,19 @@ class Products(BaseModel):
categories: Optional[str]
description: Optional[str]
image: Optional[str]
- price: int
+ price: float
quantity: int
class createZones(BaseModel):
- cost: int = Query(0, ge=0)
+ cost: float = Query(0, ge=0)
countries: str = Query(...)
class Zones(BaseModel):
id: str
user: str
- cost: int
+ cost: float
countries: str
diff --git a/lnbits/extensions/shop/templates/shop/_dialogs.html b/lnbits/extensions/shop/templates/shop/_dialogs.html
index a55d76144..3718f38ca 100644
--- a/lnbits/extensions/shop/templates/shop/_dialogs.html
+++ b/lnbits/extensions/shop/templates/shop/_dialogs.html
@@ -84,7 +84,11 @@
dense
v-model.number="productDialog.data.price"
type="number"
- label="Price"
+ :label="'Price (' + currencies.unit + ') *'"
+ :mask="currencies.unit != 'sat' ? '#.##' : '#'"
+ fill-mask="0"
+ reverse-fill-mask
+ :step="currencies.unit != 'sat' ? '0.01' : '1'"
>
{
obj._data = _.clone(obj)
+ if ('{{ currency }}' != 'sat') {
+ obj.price /= 100
+ }
return obj
}
const mapZone = obj => {
@@ -545,7 +548,7 @@
LNbits.api
.request(
'PUT',
- '/shop/api/v1/settings',
+ '/shop/api/v1/settings/' + this.g.user.id,
this.g.user.wallets[0].adminkey,
data
)
@@ -680,6 +683,7 @@
name: this.stallDialog.data.name,
wallet: this.stallDialog.data.wallet,
publickey: this.stallDialog.data.publickey || this.keys.pubkey,
+ currency: this.currencies.unit,
relays: this.stallDialog.data.relays,
shippingzones: this.stallDialog.data.shippingzones
.map(z => z.split('-')[0].trim())
@@ -1376,6 +1380,8 @@
this.onboarding.showAgain = showOnboard || false
this.diagonAlley =
this.$q.localStorage.getItem('lnbits.DAmode') || false
+ this.currencies.unit = '{{ currency }}'
+ console.log(this.currencies.unit, '{{currency}}')
await this.getCurrencies()
this.getStalls()
this.getProducts()
diff --git a/lnbits/extensions/shop/templates/shop/stall.html b/lnbits/extensions/shop/templates/shop/stall.html
index 6e776e86e..18b89f37e 100644
--- a/lnbits/extensions/shop/templates/shop/stall.html
+++ b/lnbits/extensions/shop/templates/shop/stall.html
@@ -48,7 +48,10 @@
- {{p.price}} sats
+
+ {{unit != 'sat' ? getAmountFormated(p.price) : p.price +
+ 'sats'}}
{% endraw %}
@@ -112,13 +115,18 @@
-
- {{ item.price }} satsBTC {{ (item.price / 1e8).toFixed(8) }}
+
+ {{ item.price }} satsBTC {{ (item.price / 1e8).toFixed(8) }}
+
+
+ {{ getAmountFormated(item.price) }}
+ ({{ getValueInSats(item.price) }} sats)
+
{{item.quantity}} left
- {% raw %} Total: {{ finalCost }} {% endraw %}
+ {% raw %} Total: {{ unit != 'sat' ? getAmountFormated(finalCost) :
+ finalCost + 'sats' }}
+ ({{ getValueInSats(finalCost) }} sats)
+ {% endraw %}
{
return {product_id: p[0], quantity: p[1].quantity}
})
@@ -448,9 +488,12 @@
})
}
},
- created() {
+ async created() {
this.stall = JSON.parse('{{ stall | tojson }}')
this.products = JSON.parse('{{ products | tojson }}')
+ this.unit = this.stall.currency
+ await this.getRates()
+ setInterval(this.getRates, 300000)
}
})
diff --git a/lnbits/extensions/shop/views.py b/lnbits/extensions/shop/views.py
index d9fbe64b4..50d6357c3 100644
--- a/lnbits/extensions/shop/views.py
+++ b/lnbits/extensions/shop/views.py
@@ -12,7 +12,7 @@ from starlette.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_user_exists # type: ignore
from lnbits.extensions.shop import shop_ext, shop_renderer
-from lnbits.extensions.shop.models import CreateChatMessage
+from lnbits.extensions.shop.models import CreateChatMessage, SetSettings
from lnbits.extensions.shop.notifier import Notifier
from .crud import (
@@ -26,6 +26,8 @@ from .crud import (
get_shop_zone,
get_shop_zones,
update_shop_product_stock,
+ get_shop_settings,
+ create_shop_settings,
)
templates = Jinja2Templates(directory="templates")
@@ -33,8 +35,16 @@ templates = Jinja2Templates(directory="templates")
@shop_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
+ settings = await get_shop_settings(user=user.id)
+
+ if not settings:
+ await create_shop_settings(
+ user=user.id, data=SetSettings(currency="sat", fiat_base_multiplier=1)
+ )
+ settings = await get_shop_settings(user.id)
return shop_renderer().TemplateResponse(
- "shop/index.html", {"request": request, "user": user.dict()}
+ "shop/index.html",
+ {"request": request, "user": user.dict(), "currency": settings.currency},
)
diff --git a/lnbits/extensions/shop/views_api.py b/lnbits/extensions/shop/views_api.py
index 86f0a8f56..398fc0b5b 100644
--- a/lnbits/extensions/shop/views_api.py
+++ b/lnbits/extensions/shop/views_api.py
@@ -33,6 +33,7 @@ from .crud import (
create_shop_product,
create_shop_stall,
create_shop_zone,
+ create_shop_settings,
delete_shop_order,
delete_shop_product,
delete_shop_stall,
@@ -102,15 +103,21 @@ async def api_shop_product_create(
product_id=None,
wallet: WalletTypeInfo = Depends(require_invoice_key),
):
+ # For fiat currencies,
+ # we multiply by data.fiat_base_multiplier (usually 100) to save the value in cents.
+ settings = await get_shop_settings(user=wallet.wallet.user)
+ stall = await get_shop_stall(stall_id=data.stall)
+ if stall.currency != "sat":
+ data.price *= settings.fiat_base_multiplier
if product_id:
product = await get_shop_product(product_id)
if not product:
- return {"message": "Withdraw product does not exist."}
+ return {"message": "Product does not exist."}
- stall = await get_shop_stall(stall_id=product.stall)
+ # stall = await get_shop_stall(stall_id=product.stall)
if stall.wallet != wallet.wallet.id:
- return {"message": "Not your withdraw product."}
+ return {"message": "Not your product."}
product = await update_shop_product(product_id, **data.dict())
else:
@@ -250,6 +257,8 @@ async def api_shop_orders(
wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids
orders = await get_shop_orders(wallet_ids)
+ if not orders:
+ return
orders_with_details = []
for order in orders:
order = order.dict()
@@ -472,9 +481,24 @@ async def api_get_settings(wallet: WalletTypeInfo = Depends(require_admin_key)):
return settings
-@shop_ext.put("/api/v1/settings")
+@shop_ext.post("/api/v1/settings")
+@shop_ext.put("/api/v1/settings/{usr}")
async def api_set_settings(
- data: SetSettings, wallet: WalletTypeInfo = Depends(require_admin_key)
+ data: SetSettings,
+ usr: str = None,
+ wallet: WalletTypeInfo = Depends(require_admin_key),
):
+ if usr:
+ if usr != wallet.wallet.user:
+ return {"message": "Not your Shop."}
+
+ settings = await get_shop_settings(user=usr)
+
+ if settings.user != wallet.wallet.user:
+ return {"message": "Not your Shop."}
+
+ return await set_shop_settings(usr, data)
+
user = wallet.wallet.user
- return await set_shop_settings(user, data)
+
+ return await create_shop_settings(user, data)