Skip to content

Commit

Permalink
Make taxes work (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
talvasconcelos authored Aug 1, 2024
1 parent 019bb92 commit e4156c1
Show file tree
Hide file tree
Showing 13 changed files with 1,267 additions and 975 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,12 @@ On the regular TPoS you can also add value to a total. Enter a value and click t
![atm withdraw](https://i.imgur.com/rYXtn93.png)
6. After successful withdraw, the green check will show and TPOS exists ATM mode\
![atm success](https://i.imgur.com/FaHltvW.png)

## Tax settings

For tax settings, by default tax is included in the price. You'll need to set a default tax rate in percentage (ex: 13). If items have a tax value, as some products may have different tax (VAT usually), it overides the default value.

- **Tax Exclusive means tax is applied on top of the unit price.**
- **Tax Inclusive means the unit price includes tax.**

When using the normal keypad PoS, the default tax value is used, and tax value is always included in the value.
5 changes: 3 additions & 2 deletions crud.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import List, Optional, Union

from loguru import logger

from lnbits.helpers import urlsafe_short_hash

from . import db
from .models import CreateTposData, TPoS, TPoSClean, LNURLCharge
from loguru import logger
from .models import CreateTposData, LNURLCharge, TPoS, TPoSClean


async def get_current_timestamp():
Expand Down
21 changes: 17 additions & 4 deletions migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async def m005_initial(db):
Initial withdraws table.
"""
await db.execute(
f"""
"""
CREATE TABLE tpos.withdraws (
id TEXT PRIMARY KEY,
tpos_id TEXT NOT NULL,
Expand Down Expand Up @@ -108,10 +108,23 @@ async def m007_atm_premium(db):
await db.execute("ALTER TABLE tpos.pos ADD COLUMN withdrawpremium FLOAT;")



async def m008_atm_time_option_and_pin_toggle(db):
"""
Add a time mins/sec and pin toggle
"""
await db.execute("ALTER TABLE tpos.pos ADD COLUMN withdrawtimeopt TEXT DEFAULT 'mins';")
await db.execute("ALTER TABLE tpos.pos ADD COLUMN withdrawpindisabled BOOL NOT NULL DEFAULT false;")
await db.execute(
"ALTER TABLE tpos.pos ADD COLUMN withdrawtimeopt TEXT DEFAULT 'mins';"
)
await db.execute(
"ALTER TABLE tpos.pos ADD COLUMN withdrawpindisabled BOOL NOT NULL DEFAULT false;"
)


async def m009_tax_inclusive(db):
"""
Add tax_inclusive column
"""
await db.execute(
"ALTER TABLE tpos.pos ADD COLUMN tax_inclusive BOOL NOT NULL DEFAULT true;"
)
await db.execute("ALTER TABLE tpos.pos ADD COLUMN tax_default FLOAT DEFAULT 0;")
48 changes: 18 additions & 30 deletions models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from sqlite3 import Row
from typing import Optional, Any, List
from typing import List, Optional

from fastapi import Request
from lnurl import Lnurl, LnurlWithdrawResponse
from lnurl import encode as lnurl_encode
from lnurl.models import ClearnetUrl, MilliSatoshi
from pydantic import BaseModel, Field
from lnurl.types import ClearnetUrl, MilliSatoshi
from pydantic import BaseModel, Field, validator


class CreateTposData(BaseModel):
Expand All @@ -22,32 +22,8 @@ class CreateTposData(BaseModel):
withdrawbtwn: int = Field(10, ge=1)
withdrawpremium: float = Field(None)
withdrawpindisabled: bool = Field(False)


class TPoS(BaseModel):
id: str
wallet: str
name: str
currency: str
tip_options: Optional[str]
tip_wallet: Optional[str]
withdrawlimit: Optional[int]
withdrawpin: Optional[int]
withdrawamt: int
withdrawtime: int
withdrawtimeopt: Optional[str]
withdrawbtwn: int
withdrawpremium: Optional[float]
withdrawpindisabled: Optional[bool]
items: Optional[str]

@classmethod
def from_row(cls, row: Row) -> "TPoS":
return cls(**dict(row))

@property
def withdrawamtposs(self) -> int:
return self.withdrawlimit - self.withdrawamt if self.withdrawlimit else 0
tax_inclusive: bool = Field(True)
tax_default: float = Field(None)


class TPoSClean(BaseModel):
Expand All @@ -63,6 +39,8 @@ class TPoSClean(BaseModel):
withdrawpremium: Optional[float]
withdrawpindisabled: Optional[bool]
items: Optional[str]
tax_inclusive: bool
tax_default: Optional[float]

@classmethod
def from_row(cls, row: Row) -> "TPoSClean":
Expand All @@ -73,6 +51,12 @@ def withdrawamtposs(self) -> int:
return self.withdrawlimit - self.withdrawamt if self.withdrawlimit else 0


class TPoS(TPoSClean, BaseModel):
wallet: str
tip_wallet: Optional[str]
withdrawpin: Optional[int]


class LNURLCharge(BaseModel):
id: str
tpos_id: str
Expand Down Expand Up @@ -120,10 +104,14 @@ class Item(BaseModel):
price: float
title: str
description: Optional[str]
tax: Optional[float] = 0.0
tax: Optional[float] = Field(0, ge=0.0)
disabled: bool = False
categories: Optional[List[str]] = []

@validator("tax", pre=True, always=True)
def set_default_tax(cls, v):
return v or 0


class CreateUpdateItemData(BaseModel):
items: List[Item]
53 changes: 53 additions & 0 deletions static/components/item-list/item-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<div style="margin-bottom: 200px">
<q-separator></q-separator>
<q-list separator padding>
<q-item v-for="item in items" :key="item.id" class="q-py-md">
<q-item-section avatar top>
<q-avatar>
<img v-if="item.image" class="responsive-img" :src="item.image" />
<q-icon v-else color="primary" name="sell"></q-icon>
</q-avatar>
</q-item-section>

<q-item-section class="col-4">
<q-item-label class="ellipsis"
><span
class="text-body text-weight-bold text-uppercase"
v-text="item.title"
></span
></q-item-label>
<q-item-label lines="1">
<span
class="text-weight-medium ellipsis"
v-text="item.description"
></span>
</q-item-label>
</q-item-section>

<q-item-section top>
<q-item-label lines="1">
<span class="text-weight-bold" v-text="item.formattedPrice"></span>
</q-item-label>
<q-item-label caption lines="1">
<i
><span
v-text="`tax ${inclusive ? 'incl.' : 'excl.'} ${item.tax ? item.tax + '%' : ''}`"
></span
></i>
</q-item-label>
<q-item-label v-if="!inclusive" lines="1" class="q-mt-xs">
<span
v-text="`Price w/ tax: ${format(item.price * (1 + item.tax * 0.01), currency)}`"
></span>
</q-item-label>
</q-item-section>

<q-item-section side>
<div class="text-grey-8 q-gutter-sm">
<q-btn round color="green" icon="add" @click="addToCart(item)" />
</div>
</q-item-section>
</q-item>
</q-list>
<q-separator></q-separator>
</div>
20 changes: 20 additions & 0 deletions static/components/item-list/item-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
async function itemList(path) {
const template = await loadTemplateAsync(path)

Vue.component('item-list', {
name: 'item-list',
props: ['items', 'inclusive', 'format', 'currency', 'add-product'],
template,

data: function () {
return {}
},
computed: {},
methods: {
addToCart(item) {
this.$emit('add-product', item)
}
},
created() {}
})
}
Loading

0 comments on commit e4156c1

Please sign in to comment.