Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,14 @@ async def m017_add_inventory_omit_tags(db: Database):
ALTER TABLE tpos.pos ADD inventory_omit_tags TEXT NULL;
"""
)


async def m018_add_stripe_reader_id(db: Database):
"""
Add Stripe reader id column
"""
await db.execute(
"""
ALTER TABLE tpos.pos ADD stripe_reader_id TEXT NULL;
"""
)
2 changes: 2 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class CreateTposData(BaseModel):
business_vat_id: str | None
fiat_provider: str | None = Field(None)
stripe_card_payments: bool = False
stripe_reader_id: str | None = None

@validator("tax_default", pre=True, always=True)
def default_tax_when_none(cls, v):
Expand Down Expand Up @@ -97,6 +98,7 @@ class TposClean(BaseModel):
business_vat_id: str | None = None
fiat_provider: str | None = None
stripe_card_payments: bool = False
stripe_reader_id: str | None = None

@property
def withdraw_maximum(self) -> int:
Expand Down
6 changes: 4 additions & 2 deletions static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ window.app = Vue.createApp({
lnaddress_cut: 2,
enable_receipt_print: false,
fiat: false,
stripe_card_payments: false
stripe_card_payments: false,
stripe_reader_id: ''
},
advanced: {
tips: false,
Expand Down Expand Up @@ -241,7 +242,8 @@ window.app = Vue.createApp({
lnaddress_cut: 2,
enable_receipt_print: false,
fiat: false,
stripe_card_payments: false
stripe_card_payments: false,
stripe_reader_id: ''
}
this.formDialog.advanced = {tips: false, otc: false}
},
Expand Down
57 changes: 54 additions & 3 deletions static/js/tpos.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ window.app = Vue.createApp({
}
quantity = Math.min(quantity, item.quantity_in_stock - inCart)
}
const existing = this.cart.get(item.id)
const priceSource = existing || item
if (this.cart.has(item.id)) {
this.cart.set(item.id, {
...this.cart.get(item.id),
Expand All @@ -305,11 +307,12 @@ window.app = Vue.createApp({
quantity: quantity
})
}
this.total = this.total + this.calculateItemPrice(item, quantity)
this.total = this.total + this.calculateItemPrice(priceSource, quantity)
this.cartTaxTotal()
},
removeFromCart(item, quantity = 1) {
let item_quantity = this.cart.get(item.id).quantity
const existing = this.cart.get(item.id)
let item_quantity = existing.quantity
if (item_quantity == 1 || item_quantity == quantity) {
this.cart.delete(item.id)
} else {
Expand All @@ -318,7 +321,55 @@ window.app = Vue.createApp({
quantity: this.cart.get(item.id).quantity - quantity
})
}
this.total = this.total - this.calculateItemPrice(item, quantity)
const priceSource = existing || item
this.total = this.total - this.calculateItemPrice(priceSource, quantity)
this.cartTaxTotal()
},
promptItemPrice(item) {
const cartItem = this.cart.get(item.id)
if (!cartItem) return
this.$q
.dialog({
title: 'Set price',
message: 'Update item price for this cart line',
prompt: {
model:
this.currency === 'sats'
? String(cartItem.price)
: cartItem.price.toFixed(2),
type: 'number'
},
cancel: true
})
.onOk(val => {
const newPrice = parseFloat(val)
if (isNaN(newPrice) || newPrice < 0) {
Quasar.Notify.create({
type: 'warning',
message: 'Please enter a valid price.'
})
return
}
this.updateCartItemPrice(cartItem, newPrice)
})
},
updateCartItemPrice(cartItem, newPrice) {
const roundedPrice =
this.currency === 'sats' ? Math.ceil(newPrice) : +newPrice.toFixed(2)
const existing = this.cart.get(cartItem.id)
if (!existing) return
const oldItemTotal = this.calculateItemPrice(existing, existing.quantity)
const updatedItem = {
...existing,
price: roundedPrice,
formattedPrice: this.formatAmount(roundedPrice, this.currency)
}
this.cart.set(cartItem.id, updatedItem)
const newItemTotal = this.calculateItemPrice(
updatedItem,
updatedItem.quantity
)
this.total = +(this.total - oldItemTotal + newItemTotal).toFixed(2)
this.cartTaxTotal()
},
calculateItemPrice(item, qty) {
Expand Down
6 changes: 5 additions & 1 deletion templates/tpos/_cart.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ <h5 v-show="!denomIsSats" class="q-mt-none q-mb-sm">
</td>
<td>
<div class="text-center">
<span v-text="item.formattedPrice"></span>
<span
class="cursor-pointer text-secondary"
@click="promptItemPrice(item)"
v-text="item.formattedPrice"
></span>
</div>
</td>
<td>
Expand Down
17 changes: 17 additions & 0 deletions templates/tpos/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,23 @@ <h6 class="text-subtitle1 q-my-none">{{SITE_TITLE}} TPoS extension</h6>
</small>
</div>
</div>
<div
v-if="
(formDialog.data.fiat_provider || []).includes('stripe') &&
formDialog.data.stripe_card_payments
"
class="row q-mt-sm"
>
<div class="col">
<q-input
filled
dense
v-model.trim="formDialog.data.stripe_reader_id"
label="Stripe reader ID"
hint="If you are using a Stripe reader (rather than a generic device) add it here"
></q-input>
</div>
</div>
<div class="row">
<div class="col">
<q-checkbox
Expand Down
2 changes: 2 additions & 0 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ async def api_tpos_create_invoice(tpos_id: str, data: CreateTposInvoice) -> Paym
extra["inventory"] = inventory_payload.dict()
if data.pay_in_fiat and tpos.fiat_provider:
extra["fiat_method"] = data.fiat_method if data.fiat_method else "checkout"
if tpos.stripe_reader_id:
extra["terminal"] = {"reader_id": tpos.stripe_reader_id}
invoice_data = CreateInvoice(
unit=currency,
out=False,
Expand Down