Tax done
This commit is contained in:
@ -53,7 +53,7 @@ class FoodTable(Base):
|
||||
def __name__(self):
|
||||
return self.name
|
||||
|
||||
def __init__(self, name=None, location=None, is_active=None, sort_order=None, id=None):
|
||||
def __init__(self, name=None, location=None, is_active=None, sort_order=0, id=None):
|
||||
self.name = name
|
||||
self.location = location
|
||||
self.is_active = is_active
|
||||
@ -67,10 +67,12 @@ class Tax(Base):
|
||||
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
|
||||
name = Column('name', Unicode(255), nullable=False, unique=True)
|
||||
rate = Column('rate', Numeric, nullable=False)
|
||||
is_fixture = Column("is_fixture", Boolean, nullable=False)
|
||||
|
||||
def __init__(self, name=None, rate=None, id=None):
|
||||
def __init__(self, name=None, rate=None, is_fixture=False, id=None):
|
||||
self.name = name
|
||||
self.rate = rate
|
||||
self.is_fixture = is_fixture
|
||||
self.id = id
|
||||
|
||||
|
||||
@ -84,6 +86,7 @@ class ProductGroup(Base):
|
||||
group_type = Column('group_type', Unicode(255), nullable=False)
|
||||
|
||||
is_active = Column('is_active', Boolean, nullable=False)
|
||||
is_fixture = Column('is_fixture', Boolean, nullable=False)
|
||||
sort_order = Column('sort_order', Numeric, nullable=False)
|
||||
|
||||
def __init__(self, name, discount_limit, is_modifier_compulsory, group_type, is_active, sort_order, id=None):
|
||||
@ -104,8 +107,7 @@ class Product(Base):
|
||||
name = Column('name', Unicode(255), nullable=False)
|
||||
units = Column('units', Unicode(255), nullable=False)
|
||||
product_group_id = Column('product_group_id', GUID(), ForeignKey('product_groups.id'), nullable=False)
|
||||
vat_id = Column('vat_id', GUID(), ForeignKey('taxes.id'), nullable=False)
|
||||
service_tax_id = Column('service_tax_id', GUID(), ForeignKey('taxes.id'), nullable=False)
|
||||
tax_id = Column('tax_id', GUID(), ForeignKey('taxes.id'), nullable=False)
|
||||
price = Column('price', Numeric, nullable=False)
|
||||
has_happy_hour = Column('has_happy_hour', Boolean, nullable=False)
|
||||
is_not_available = Column('is_not_available', Boolean, nullable=False)
|
||||
@ -115,16 +117,14 @@ class Product(Base):
|
||||
sort_order = Column('sort_order', Numeric, nullable=False)
|
||||
|
||||
product_group = relationship('ProductGroup', backref='products')
|
||||
vat = relationship('Tax', foreign_keys=vat_id)
|
||||
service_tax = relationship('Tax', foreign_keys=service_tax_id)
|
||||
tax = relationship('Tax', foreign_keys=tax_id)
|
||||
|
||||
def __init__(self, name=None, units=None, product_group_id=None, vat_id=None, service_tax_id=None, price=None,
|
||||
def __init__(self, name=None, units=None, product_group_id=None, tax_id=None, price=None,
|
||||
has_happy_hour=None, is_not_available=None, quantity=None, is_active=None, sort_order=None, id=None):
|
||||
self.name = name
|
||||
self.units = units
|
||||
self.product_group_id = product_group_id
|
||||
self.vat_id = vat_id
|
||||
self.service_tax_id = service_tax_id
|
||||
self.tax_id = tax_id
|
||||
self.price = price
|
||||
self.has_happy_hour = has_happy_hour
|
||||
self.is_not_available = is_not_available
|
||||
|
||||
11
barker/models/validation_exception.py
Normal file
11
barker/models/validation_exception.py
Normal file
@ -0,0 +1,11 @@
|
||||
class ValidationError(Exception):
|
||||
def __init__(self, message, errors=None):
|
||||
self.message = message
|
||||
# Call the base class constructor with the parameters it needs
|
||||
Exception.__init__(self, message)
|
||||
|
||||
# Now for your custom code...
|
||||
self.errors = errors
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
@ -40,6 +40,20 @@ def includeme(config):
|
||||
config.add_route('print_location_list', '/PrintLocations.json')
|
||||
config.add_route('print_location_id', '/PrintLocation/{id}.json')
|
||||
|
||||
config.add_route("products_new", "/products/new")
|
||||
config.add_route("products_id", "/products/{id}")
|
||||
config.add_route("products_list", "/products")
|
||||
config.add_route("v1_products_new", "/v1/products/new")
|
||||
config.add_route("v1_products_id", "/v1/products/{id}")
|
||||
config.add_route("v1_products_list", "/v1/products")
|
||||
|
||||
config.add_route("product_groups_new", "/product-groups/new")
|
||||
config.add_route("product_groups_id", "/product-groups/{id}")
|
||||
config.add_route("product_groups_list", "/product-groups")
|
||||
config.add_route("v1_product_groups_new", "/v1/product-groups/new")
|
||||
config.add_route("v1_product_groups_id", "/v1/product-groups/{id}")
|
||||
config.add_route("v1_product_groups_list", "/v1/product-groups")
|
||||
|
||||
config.add_route('product', '/Product.json')
|
||||
config.add_route('product_list', '/Products.json')
|
||||
config.add_route('product_id', '/Product/{id}.json')
|
||||
@ -64,9 +78,12 @@ def includeme(config):
|
||||
config.add_route('sa_st', '/SaleAnalysis/ServiceTax.json')
|
||||
config.add_route('sa_vat', '/SaleAnalysis/Vat.json')
|
||||
|
||||
config.add_route('tax', '/Tax.json')
|
||||
config.add_route('tax_list', '/Taxes.json')
|
||||
config.add_route('tax_id', '/Tax/{id}.json')
|
||||
config.add_route("taxes_new", "/taxes/new")
|
||||
config.add_route("taxes_id", "/taxes/{id}")
|
||||
config.add_route("taxes_list", "/taxes")
|
||||
config.add_route("v1_taxes_new", "/v1/taxes/new")
|
||||
config.add_route("v1_taxes_id", "/v1/taxes/{id}")
|
||||
config.add_route("v1_taxes_list", "/v1/taxes")
|
||||
|
||||
config.add_route('v1_users_new', '/v1/users/new')
|
||||
config.add_route('v1_users_list', '/v1/users/list')
|
||||
|
||||
@ -14,6 +14,7 @@ from barker.models import (
|
||||
DbSetting,
|
||||
Permission,
|
||||
User,
|
||||
FoodTable,
|
||||
get_engine,
|
||||
get_session_factory,
|
||||
get_tm_session,
|
||||
@ -108,6 +109,9 @@ def main(argv=sys.argv):
|
||||
admin.roles.append(roles[0])
|
||||
dbsession.add(admin)
|
||||
|
||||
for name in range(1,20):
|
||||
dbsession.add(FoodTable(str(name), "", True))
|
||||
|
||||
options = [
|
||||
SettleOption('Unsettled', False, 1, True, 1),
|
||||
SettleOption('Cash', True, 2, False, 2),
|
||||
|
||||
@ -1,45 +1,103 @@
|
||||
import uuid
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
import transaction
|
||||
from pyramid.response import Response
|
||||
from pyramid.view import view_config
|
||||
|
||||
from barker.models import Product
|
||||
from barker.models.validation_exception import ValidationError
|
||||
|
||||
|
||||
@view_config(request_method='PUT', route_name='product', renderer='json', permission='Products', trans=True)
|
||||
@view_config(request_method='PUT', route_name='v1_products_new', renderer='json', permission='Products', trans=True)
|
||||
def save(request):
|
||||
json = request.json_body
|
||||
item = Product(json['Name'], json['Units'], json['ProductGroupID'], json['VatID'], json['ServiceTaxID'],
|
||||
json['Price'], json['HasHappyHour'], json['IsNotAvailable'], json['Quantity'], json['IsActive'],
|
||||
json['SortOrder'])
|
||||
|
||||
name = json.get("name", "").strip()
|
||||
if name == "":
|
||||
raise ValidationError("Name cannot be blank")
|
||||
|
||||
units = json.get("units", "").strip()
|
||||
|
||||
product_group = json.get("productGroup", None)
|
||||
if product_group is None:
|
||||
raise ValidationError("please choose a product group")
|
||||
product_group_id = uuid.UUID(product_group["id"])
|
||||
|
||||
tax = json.get("tax", None)
|
||||
if product_group is None:
|
||||
raise ValidationError("please choose a product group")
|
||||
tax_id = uuid.UUID(tax["id"])
|
||||
|
||||
try:
|
||||
price = Decimal(json.get("price", 0))
|
||||
if price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
|
||||
has_happy_hour = json.get("hasHappyHour", True)
|
||||
is_not_available = json.get("isNotAvailable", True)
|
||||
|
||||
try:
|
||||
quantity = Decimal(json.get("quantity", 0))
|
||||
if quantity < 0:
|
||||
raise ValidationError("Quantity must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Quantity must be a decimal >= 0")
|
||||
|
||||
is_active = json.get("isActive", True)
|
||||
|
||||
item = Product(
|
||||
name,
|
||||
units,
|
||||
product_group_id,
|
||||
tax_id,
|
||||
price,
|
||||
has_happy_hour,
|
||||
is_not_available,
|
||||
quantity,
|
||||
is_active
|
||||
)
|
||||
request.dbsession.add(item)
|
||||
transaction.commit()
|
||||
item = request.dbsession.query(Product).filter(Product.id == item.id).first()
|
||||
return product_info(item)
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='product_id', renderer='json', permission='Products', trans=True)
|
||||
@view_config(request_method='POST', route_name='v1_products_id', renderer='json', permission='Products', trans=True)
|
||||
def update(request):
|
||||
item = request.dbsession.query(Product).filter(Product.id == uuid.UUID(request.matchdict['id'])).first()
|
||||
item = (
|
||||
request.dbsession.query(Product)
|
||||
.filter(Product.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
json = request.json_body
|
||||
item.name = json['Name']
|
||||
item.units = json['Units']
|
||||
item.product_group_id = json['ProductGroupID']
|
||||
item.vat_id = json['VatID']
|
||||
item.service_tax_id = json['ServiceTaxID']
|
||||
item.price = json['Price']
|
||||
item.has_happy_hour = json['HasHappyHour']
|
||||
item.is_not_available = json['IsNotAvailable']
|
||||
item.quantity = json['Quantity']
|
||||
item.is_active = json['IsActive']
|
||||
item.sort_order = json['SortOrder']
|
||||
item.name = json["name"].strip()
|
||||
item.units = json["units"].strip()
|
||||
item.product_group_id = uuid.UUID(json["productGroup"]["id"])
|
||||
item.vat_id = uuid.UUID(json["tax"]["id"])
|
||||
try:
|
||||
item.price = Decimal(json["price"])
|
||||
if item.price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
item.has_happy_hour = json['hasHappyHour']
|
||||
item.is_not_available = json['isNotAvailable']
|
||||
try:
|
||||
item.quantity = Decimal(json["quantity"])
|
||||
if item.price < 0:
|
||||
raise ValidationError("Quantity must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Quantity must be a decimal >= 0")
|
||||
item.is_active = json['isActive']
|
||||
transaction.commit()
|
||||
item = request.dbsession.query(Product).filter(Product.id == item.id).first()
|
||||
return product_info(item)
|
||||
|
||||
|
||||
@view_config(request_method='DELETE', route_name='product_id', renderer='json', permission='Products', trans=True)
|
||||
@view_config(request_method='DELETE', route_name='v1_products_id', renderer='json', permission='Products', trans=True)
|
||||
def delete(request):
|
||||
item = request.dbsession.query(Product).filter(Product.id == uuid.UUID(request.matchdict['id'])).first()
|
||||
if item is None:
|
||||
@ -52,32 +110,32 @@ def delete(request):
|
||||
return response
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='product_id', renderer='json', permission='Authenticated')
|
||||
@view_config(request_method='GET', route_name='v1_products_id', renderer='json', permission='Authenticated')
|
||||
def show_id(request):
|
||||
id = uuid.UUID(request.matchdict['id'])
|
||||
item = request.dbsession.query(Product).filter(Product.id == id).first()
|
||||
id_ = uuid.UUID(request.matchdict['id'])
|
||||
item = request.dbsession.query(Product).filter(Product.id == id_).first()
|
||||
return product_info(item)
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='product_list', renderer='json', permission='Authenticated')
|
||||
@view_config(request_method='GET', route_name='v1_products_list', renderer='json', permission='Authenticated')
|
||||
def show_list(request):
|
||||
active = request.GET.get('a', None)
|
||||
list = request.dbsession.query(Product)
|
||||
list_ = request.dbsession.query(Product)
|
||||
if active is not None:
|
||||
list = list.filter(Product.is_active == active)
|
||||
list = list.order_by(Product.product_group_id, Product.sort_order).order_by(Product.name).all()
|
||||
list_ = list_.filter(Product.is_active == active)
|
||||
list_ = list_.order_by(Product.product_group_id, Product.sort_order).order_by(Product.name).all()
|
||||
products = []
|
||||
for item in list:
|
||||
for item in list_:
|
||||
products.append(product_info(item))
|
||||
return products
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='product_list', renderer='json', permission='Products', trans=True)
|
||||
@view_config(request_method='POST', route_name='v1_products_list', renderer='json', permission='Products', trans=True)
|
||||
def sort_order(request):
|
||||
json = request.json_body
|
||||
index, last_group = 0, None
|
||||
for item in json:
|
||||
product_id = uuid.UUID(item['ProductID'])
|
||||
product_id = uuid.UUID(item['id'])
|
||||
product_group_id = uuid.UUID(item['ProductGroupID'])
|
||||
if last_group != product_group_id:
|
||||
index = 0
|
||||
@ -94,16 +152,14 @@ def sort_order(request):
|
||||
|
||||
def product_info(item):
|
||||
return {
|
||||
'ProductID': item.id,
|
||||
'Name': item.name,
|
||||
'Units': item.units,
|
||||
'ProductGroup': {'ProductGroupID': item.product_group_id, 'Name': item.product_group.name},
|
||||
'Vat': {'TaxID': item.vat_id, 'Name': item.vat.name, 'Rate': item.vat.rate},
|
||||
'ServiceTax': {'TaxID': item.service_tax_id, 'Name': item.service_tax.name, 'Rate': item.service_tax.rate},
|
||||
'Price': item.price,
|
||||
'HasHappyHour': item.has_happy_hour,
|
||||
'IsNotAvailable': item.is_not_available,
|
||||
|
||||
'IsActive': item.is_active,
|
||||
'SortOrder': item.sort_order
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'units': item.units,
|
||||
'productGroup': {'id': item.product_group_id, 'name': item.product_group.name},
|
||||
'tax': {'id': item.vat_id, 'name': item.vat.name, 'rate': item.vat.rate},
|
||||
'price': item.price,
|
||||
'hasHappyHour': item.has_happy_hour,
|
||||
'isNotAvailable': item.is_not_available,
|
||||
'isActive': item.is_active,
|
||||
'sortOrder': item.sort_order
|
||||
}
|
||||
|
||||
@ -1,63 +1,109 @@
|
||||
import uuid
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
import transaction
|
||||
from pyramid.view import view_config
|
||||
|
||||
from barker.models import Tax
|
||||
from barker.models.validation_exception import ValidationError
|
||||
|
||||
|
||||
@view_config(request_method='PUT', route_name='tax', renderer='json', permission='Taxes', trans=True)
|
||||
@view_config(request_method='POST', route_name='v1_taxes_new', renderer='json', permission='Taxes', trans=True)
|
||||
def save(request):
|
||||
json = request.json_body
|
||||
item = Tax(json['Name'], json['Rate'])
|
||||
name = json.get("name", "").strip()
|
||||
if name == "":
|
||||
raise ValidationError("Name cannot be blank")
|
||||
try:
|
||||
rate = Decimal(json["rate"]) / 100
|
||||
if rate < 0:
|
||||
raise ValidationError("Tax Rate must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Tax Rate must be a decimal >= 0")
|
||||
item = Tax(name, rate)
|
||||
request.dbsession.add(item)
|
||||
transaction.commit()
|
||||
item = request.dbsession.query(Tax).filter(Tax.id == item.id).first()
|
||||
return tax_info(item)
|
||||
return tax_info(item.id, request.dbsession)
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='tax_id', renderer='json', permission='Taxes', trans=True)
|
||||
@view_config(request_method='PUT', route_name='v1_taxes_id', renderer='json', permission='Taxes', trans=True)
|
||||
def update(request):
|
||||
json = request.json_body
|
||||
item = request.dbsession.query(Tax).filter(Tax.id == uuid.UUID(request.matchdict['id'])).first()
|
||||
item.name = json['Name']
|
||||
item.rate = json['Rate']
|
||||
item = (
|
||||
request.dbsession.query(Tax)
|
||||
.filter(Tax.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
if item.is_fixture:
|
||||
raise ValidationError(
|
||||
"{0} is a fixture and cannot be edited or deleted.".format(item.full_name)
|
||||
)
|
||||
item.name = json['name'].strip()
|
||||
try:
|
||||
item.rate = Decimal(json["rate"]) / 100
|
||||
if item.rate <= 0:
|
||||
raise ValidationError("Tax Rate must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Tax Rate must be a decimal >= 0")
|
||||
item.rate = json['rate']
|
||||
transaction.commit()
|
||||
item = request.dbsession.query(Tax).filter(Tax.id == item.id).first()
|
||||
return tax_info(item)
|
||||
return tax_info(item.id, request.dbsession)
|
||||
|
||||
|
||||
@view_config(request_method='DELETE', route_name='tax_id', renderer='json', permission='Taxes', trans=True)
|
||||
@view_config(request_method='DELETE', route_name='v1_taxes_id', renderer='json', permission='Taxes', trans=True)
|
||||
def delete(request):
|
||||
item = request.dbsession.query(Tax).filter(Tax.id == uuid.UUID(request.matchdict['id'])).first()
|
||||
item = (
|
||||
request.dbsession.query(Tax)
|
||||
.filter(Tax.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
if item.is_fixture:
|
||||
raise ValidationError(
|
||||
"{0} is a fixture and cannot be edited or deleted.".format(item.full_name)
|
||||
)
|
||||
request.dbsession.delete(item)
|
||||
transaction.commit()
|
||||
return {}
|
||||
return tax_info(None, request.dbsession)
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='tax_id', renderer='json', permission='Authenticated')
|
||||
@view_config(request_method='GET', route_name='v1_taxes_new', renderer='json', permission='Authenticated')
|
||||
def show_blank(request):
|
||||
return tax_info(None, request.dbsession)
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='v1_taxes_id', renderer='json', permission='Authenticated')
|
||||
def show_id(request):
|
||||
id = uuid.UUID(request.matchdict['id'])
|
||||
item = request.dbsession.query(Tax).filter(Tax.id == id).first()
|
||||
return tax_info(item)
|
||||
return tax_info(uuid.UUID(request.matchdict["id"]), request.dbsession)
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='tax_list', renderer='json', permission='Authenticated')
|
||||
@view_config(request_method='GET', route_name='v1_taxes_list', renderer='json', permission='Authenticated')
|
||||
def show_list(request):
|
||||
list = request.dbsession.query(Tax).order_by(Tax.name).all()
|
||||
list_ = request.dbsession.query(Tax).order_by(Tax.name).all()
|
||||
taxes = []
|
||||
for item in list:
|
||||
for item in list_:
|
||||
taxes.append({
|
||||
'TaxID': item.id,
|
||||
'Name': item.name,
|
||||
'Rate': item.rate,
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'rate': item.rate,
|
||||
'isFixture': item.is_fixture
|
||||
})
|
||||
return taxes
|
||||
|
||||
|
||||
def tax_info(item):
|
||||
return {
|
||||
'TaxID': item.id,
|
||||
'Name': item.name,
|
||||
'Rate': item.rate
|
||||
}
|
||||
def tax_info(id_, dbsession):
|
||||
if id_ is None:
|
||||
tax = {
|
||||
"name": "",
|
||||
"rate": 0,
|
||||
"isFixture": False
|
||||
}
|
||||
else:
|
||||
item = dbsession.query(Tax).filter(Tax.id == id_).first()
|
||||
tax = {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'rate': item.rate * 100,
|
||||
'isFixture': item.is_fixture
|
||||
}
|
||||
return tax
|
||||
|
||||
Reference in New Issue
Block a user