Feature: The app checks if the database schema is not created and creates it automatially on first run.

Fix: While user login try to catch None password error.
Fix: Rename Yeild to the correct spelling Yield.
Fix: Wrong column type for IsReconciled in Voucher.
Fix: Redirect user on login to last page.
Fix: Validate input in save/update of employee and product
This commit is contained in:
Amritanshu 2014-03-12 22:49:29 +05:30
parent f4551c8b5a
commit 69071182a3
9 changed files with 284 additions and 56 deletions

View File

@ -8,14 +8,118 @@ from sqlalchemy.orm import sessionmaker
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False))
Base = declarative_base()
def initialize_sql(engine):
# from brewman.models.messaging import Tag, Thread, Subscriber, thread_tag, Post
# from brewman.models.voucher import Attendance, Batch, Fingerprint, Inventory, Journal, Product, SalaryDeduction, Voucher, VoucherType
# from brewman.models.master import Product, AttendanceType, CostCenter, Employee, Ledger, LedgerBase, LedgerType, ProductGroup
# from brewman.models.auth import Client, Group, Role, User, role_group, user_group
# from .master import DbSetting
DBSession.configure(bind=engine)
Base.metadata.bind = engine
# Base.metadata.create_all(engine)
if not schema_exists(engine):
fixtures(engine)
def schema_exists(engine):
from brewman.models.master import DbSetting
with engine.connect() as connection:
return engine.dialect.has_table(connection, DbSetting.__tablename__)
def fixtures(engine):
import transaction
import uuid
from brewman.models.messaging import Tag, Thread, Subscriber, thread_tag, Post
from brewman.models.voucher import Attendance, Batch, Fingerprint, Inventory, Journal, Product, SalaryDeduction, Voucher, VoucherType
from brewman.models.master import Product, AttendanceType, CostCenter, Employee, Ledger, LedgerBase, LedgerType, ProductGroup
from brewman.models.auth import Client, Group, Role, User, role_group, user_group
Base.metadata.create_all(engine)
user = User('Admin', '123456', False, uuid.UUID('8de98592-76d9-c74d-bb3f-d6184d388b5a'))
DBSession.add(user)
groups = [Group('Owner', uuid.UUID('52e08c0c-048a-784f-be10-6e129ad4b5d4')),
Group('Accountant', uuid.UUID('bc4c2d23-437a-984d-abd4-7d5fce677547')),
Group('Accounts Manager', uuid.UUID('cfc44fa7-3392-5b45-b311-5959333f568f'))]
for group in groups:
DBSession.add(group)
user.groups.append(group)
roles = [Role('Attendance', uuid.UUID('09d05434-a09a-fa45-963b-769a2e3fc667')),
Role('Trial Balance', uuid.UUID('3b099fec-ddc5-4243-b30e-afb78d9ca14a')),
Role('Cash Flow', uuid.UUID('c4d3ae29-420b-ea4c-ae90-00a356263fd9')),
Role('Cost Centers', uuid.UUID('6fcc1a20-6aec-e840-b334-1632b34aeab8')),
Role('Users', uuid.UUID('c5b7d9d7-f178-0e45-8ea4-bf4e08ec901b')),
Role('Daybook', uuid.UUID('c3edb554-a057-8942-8030-37b8e926d583')),
Role('Edit Posted Vouchers', uuid.UUID('d6675817-ddf5-bf40-9de6-fa223eb4aaa6')),
Role('Employees', uuid.UUID('e4edd0ac-7f5d-e64d-8611-73fdc4cd8ba2')),
Role('Fingerprints', uuid.UUID('d9c45323-f997-ba46-9407-8a7145f0828b')),
Role('Issue', uuid.UUID('03b602eb-f58a-b94f-af58-8cb47d7849d0')),
Role('Journal', uuid.UUID('7661388f-62ce-1c41-8e0d-0326ee5d4018')),
Role('Accounts', uuid.UUID('f438262f-72dd-2f4e-9186-5abc3af44fba')),
Role('Product Ledger', uuid.UUID('018a2408-e804-1446-90c5-b015829da6ba')),
Role('Backdated Vouchers', uuid.UUID('b67b2062-5ca7-134f-8258-5d284dd92426')),
Role('Payment', uuid.UUID('f85c0b52-c3fd-7141-8957-7a56cdc014a4')),
Role('Post Vouchers', uuid.UUID('36e741da-1a57-b047-a59e-dcd58fcf4338')),
Role('Products', uuid.UUID('74fa6d21-eebb-e14c-8153-bebc57190ab4')),
Role('Product Groups', uuid.UUID('08413a22-cf88-fd43-b2b7-365d2951d99f')),
Role('Profit & Loss', uuid.UUID('0492ebb3-76f3-204e-ab94-bbfe880f0691')),
Role('Purchase', uuid.UUID('12335acb-8630-2d41-a191-1517c8d172de')),
Role('Purchase Entries', uuid.UUID('78a6422b-aa11-174c-9dfa-412a99e87e02')),
Role('Purchase Return', uuid.UUID('ab33196e-d9e4-114c-ac8c-997954363756')),
Role('Receipt', uuid.UUID('1f1ce53e-76ff-a346-974a-65db6f606e5f')),
Role('Closing Stock', uuid.UUID('97515732-24e4-c94d-9585-d4bd7f6c7891')),
Role('Ledger', uuid.UUID('a2120944-243f-3f49-be57-0ad633ce4801')),
Role('Raw Material Cost', uuid.UUID('d462842b-baf1-2343-95e5-ffdba9bbc163')),
Role('Edit Other User\'s Vouchers', uuid.UUID('a8328891-7ce2-a943-8c29-2eabc1ffeea3')),
Role('Clients', uuid.UUID('cfad44f0-f2a9-7045-89d7-9019cf0f371a')),
Role('Salary Deduction', uuid.UUID('92d70e80-1c32-384d-959e-abf84b804696')),
Role('Messages', uuid.UUID('f586d128-b6d9-4090-a913-78fcbdb68e59')),
Role('Lock Date', uuid.UUID('d52de0be-9388-4b0b-a359-7e122ab6e53a')),
Role('Net Transactions', uuid.UUID('2c40f7cf-67fc-4efa-a670-8d16a2e7884d')),
Role('Balance Sheet', uuid.UUID('40deb018-b8f2-460a-88be-8972c9fcdf04')),
Role('Advanced Delete', uuid.UUID('197ebcd2-bc4a-4b65-a138-ce942ece32ea')),
Role('Rebase', uuid.UUID('de204a88-5f9d-4579-a2d6-aa2f25efde42')),
Role('Reset Stock', uuid.UUID('aecaf82f-aa41-4634-b754-0c1308b621b1')),
Role('Reconcile', uuid.UUID('a5cb51cb-e38e-4705-84a7-cc1e9a8b866b')),
Role('Stock Movement', uuid.UUID('20b707ee-2b59-41ad-be87-76d5fe1efca8')),
Role('Purchases', uuid.UUID('cf7019c8-3fd3-45b0-9a42-601029ce5b71')),
Role('Dashboard', uuid.UUID('53eecc09-bd06-4890-b6f5-6885dda762d4'))]
for role in roles:
DBSession.add(role)
groups[0].roles.append(role)
cost_centers = [CostCenter('Overall', uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), True),
CostCenter('Purchase', uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), True),
CostCenter('Kitchen', uuid.UUID('b2d398ce-e3cc-c542-9feb-5d7783e899df'), True)]
for cost_center in cost_centers:
DBSession.add(cost_center)
ledgers = [Ledger(1, 'All Purchases', 2, True, False, uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'),
uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), True),
Ledger(1, 'Local Purchase', 9, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('d2b75912-505f-2548-9093-466dfff6a0f9'), True),
Ledger(1, 'ESI/PF - Payable', 11, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('42277912-cc18-854b-b134-9f4b00dba419'), True),
Ledger(2, 'ESI/PF - Expense', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('d2a1a286-e900-764b-a1a5-9f4b00dbb940'), True),
Ledger(1, 'Cash in Hand', 1, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('ed2341bb-80b8-9649-90db-f9aaca183bb3'), True),
Ledger(1, 'Staff Salary', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('5c2b54d0-c174-004d-a0d5-92cdaadcefa7'), True),
Ledger(1, 'Suspense', 4, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'),
uuid.UUID('3854e317-6f3b-5142-ab26-9c44d4cddd08'), True)]
for ledger in ledgers:
DBSession.add(ledger)
product_group = ProductGroup('Suspense', uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), True)
DBSession.add(product_group)
product = Product(1, 'Suspense', '', 1, '', 1, False, uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'),
uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), 0, True,
uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15'), True)
DBSession.add(product)
transaction.commit()

View File

@ -1,17 +1,17 @@
import random
import string
import uuid
from sqlalchemy.schema import ForeignKey, Table
from brewman.models.guidtype import GUID
from hashlib import md5
from sqlalchemy.schema import ForeignKey, Table
from sqlalchemy import Column, Boolean, Unicode, Integer
from sqlalchemy.orm import synonym, relationship
from brewman.models.guidtype import GUID
from brewman.models import Base
from brewman.models import DBSession
def encrypt(val):
return md5(val.encode('utf-8') + "Salt".encode('utf-8')).hexdigest()
@ -68,7 +68,6 @@ user_group = Table(
Column('GroupID', GUID(), ForeignKey('auth_groups.GroupID'))
)
role_group = Table(
'auth_rolegroups', Base.metadata,
Column('RoleGroupID', GUID(), primary_key=True, default=uuid.uuid4),
@ -101,10 +100,11 @@ class User(Base):
def __name__(self):
return self.name
def __init__(self, name=None, password=None, locked_out=None):
def __init__(self, name=None, password=None, locked_out=None, id=None):
self.name = name
self.password = password
self.locked_out = locked_out
self.id = id
@classmethod
def by_name(cls, name):
@ -120,6 +120,8 @@ class User(Base):
@classmethod
def auth(cls, name, password):
if password is None:
return False, None
user = cls.by_name(name)
if not user:
return False, None
@ -150,8 +152,10 @@ class Group(Base):
id = Column('GroupID', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('Name', Unicode(255), unique=True)
def __init__(self, name=None):
def __init__(self, name=None, id=None):
self.name = name
self.id = id
@classmethod
def by_id(cls, id):
@ -170,8 +174,9 @@ class Role(Base):
groups = relationship("Group", secondary=role_group, backref="roles")
def __init__(self, name=None):
def __init__(self, name=None, id=None):
self.name = name
self.id = id
@classmethod
def list(cls):

View File

@ -17,7 +17,7 @@ class Product(Base):
units = Column('Units', Unicode(255), nullable=False)
fraction = Column('Fraction', Numeric, nullable=False)
fraction_units = Column('FractionUnits', Unicode(255), nullable=False)
yeild = Column('Yeild', Numeric, nullable=False)
product_yield = Column('ProductYield', Numeric, nullable=False)
show_for_purchase = Column('ShowForPurchase', Boolean, nullable=False)
product_group_id = Column('ProductGroupID', GUID(), ForeignKey('entities_productgroups.ProductGroupID'),
nullable=False)
@ -31,20 +31,21 @@ class Product(Base):
ledger = relationship('Ledger', primaryjoin="Ledger.id==Product.ledger_id", backref='products')
def __init__(self, code=None, name=None, units=None, fraction=None, fraction_units=None, yeild=None,
def __init__(self, code=None, name=None, units=None, fraction=None, fraction_units=None, product_yield=None,
show_for_purchase=None, product_group_id=None, ledger_id=None, price=None, discontinued=None,
is_fixture=False):
id=None,is_fixture=False):
self.code = code
self.name = name
self.units = units
self.fraction = fraction
self.fraction_units = fraction_units
self.yeild = yeild
self.product_yield = product_yield
self.show_for_purchase = show_for_purchase
self.product_group_id = product_group_id
self.ledger_id = ledger_id
self.price = price
self.discontinued = discontinued
self.id = id
self.is_fixture = is_fixture
@property
@ -108,8 +109,9 @@ class ProductGroup(Base):
products = relationship('Product', backref='product_group')
def __init__(self, name=None, is_fixture=False):
def __init__(self, name=None, id=None, is_fixture=False):
self.name = name
self.id = id
self.is_fixture = is_fixture
@classmethod
@ -135,8 +137,9 @@ class CostCenter(Base):
def __name__(self):
return self.name
def __init__(self, name=None, is_fixture=False):
def __init__(self, name=None, id=None, is_fixture=False):
self.name = name
self.id = id
self.is_fixture = is_fixture
@classmethod
@ -190,13 +193,14 @@ class LedgerBase(Base):
return LedgerType.by_id(self.type)
def __init__(self, code=None, name=None, type=None, is_active=None, is_reconcilable=False, costcenter_id=None,
is_fixture=False):
id=None, is_fixture=False):
self.code = code
self.name = name
self.type = type
self.is_active = is_active
self.is_reconcilable = is_reconcilable
self.costcenter_id = costcenter_id
self.id = id
self.is_fixture = is_fixture
@classmethod

View File

@ -54,7 +54,7 @@ class Voucher(Base):
id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4)
date = Column('Date', DateTime, nullable=False)
reconcile_date = Column('ReconcileDate', DateTime, nullable=False)
is_reconciled = Column('IsReconciled', DateTime, nullable=False)
is_reconciled = Column('IsReconciled', Boolean, nullable=False)
narration = Column('Narration', Unicode(1000), nullable=False)
posted = Column('Posted', Boolean, nullable=False)
creation_date = Column('CreationDate', DateTime(timezone=True), nullable=False)

View File

@ -37,17 +37,17 @@
</div>
</div>
<div class="form-group">
<label for="txtFractionUnits" class="col-md-2 control-label">FractionUnits</label>
<label for="txtFractionUnits" class="col-md-2 control-label">Fraction Units</label>
<div class="col-md-10">
<input type="text" id="txtFractionUnits" class="form-control" ng-model="product.FractionUnits"/>
</div>
</div>
<div class="form-group">
<label for="txtYeild" class="col-md-2 control-label">Yeild</label>
<label for="txtYield" class="col-md-2 control-label">Yield</label>
<div class="col-md-10">
<input type="text" id="txtYeild" class="form-control" ng-model="product.Yeild"/>
<input type="text" id="txtYield" class="form-control" ng-model="product.ProductYield"/>
</div>
</div>

View File

@ -1,3 +1,4 @@
from decimal import Decimal
from datetime import date, datetime, timedelta, time
import uuid
import re
@ -23,7 +24,7 @@ def forbidden(request):
response.status_int = 401
return response
else:
return HTTPFound(location=request.route_url('login'))
return HTTPFound(location=request.route_url('login', _query={'came_from': request.path}))
@view_config(route_name='favicon')
@ -58,3 +59,20 @@ def get_lock_info():
def to_uuid(value):
p = re.compile('^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$')
return uuid.UUID(value) if p.match(value) else None
def to_decimal(value, default=0):
import re
_parser = re.compile(r""" # A numeric string consists of:
(?P<sign>[-+])? # an optional sign, followed by either...
(
(?=\d|\.\d) # ...a number (with at least one digit)
(?P<int>\d*) # having a (possibly empty) integer part
(\.(?P<frac>\d*))? # followed by an optional fractional part
|
(?P<signal>s)? # ...an (optionally signaling)
NaN # NaN
(?P<diag>\d*) # with (possibly empty) diagnostic info.
)
\Z
""", re.VERBOSE | re.IGNORECASE).match
return Decimal(value) if _parser(value.strip()) is not None else default

View File

@ -29,16 +29,45 @@ def html(request):
@view_config(request_method='POST', route_name='api_employee', renderer='json', permission='Employees')
@TryCatchFunction
def save(request):
is_active = request.json_body['IsActive']
joining_date = datetime.datetime.strptime(request.json_body['JoiningDate'], '%d-%b-%Y')
leaving_date = None if is_active else datetime.datetime.strptime(request.json_body['LeavingDate'],
'%d-%b-%Y')
name = request.json_body.get('Name', '').strip()
if name == '':
raise ValidationError('Name cannot be blank')
item = Employee(0, request.json_body['Name'], is_active,
uuid.UUID(request.json_body['CostCenter']['CostCenterID']),
request.json_body['Designation'], int(request.json_body['Salary']),
int(request.json_body['ServicePoints']),
joining_date, leaving_date).create()
cost_center_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
designation = request.json_body.get('Designation', '').strip()
try:
salary = int(request.json_body['Salary'])
if salary < 0:
raise ValidationError("Salary must be an integer >= 0")
except (ValueError, KeyError):
raise ValidationError("Salary must be an integer >= 0")
try:
service_points = int(request.json_body['ServicePoints'])
if service_points < 0:
raise ValidationError("Service Points must be an integer >= 0")
except (ValueError, KeyError):
raise ValidationError("Service Points must be an integer >= 0")
try:
joining_date = datetime.datetime.strptime(request.json_body['JoiningDate'], '%d-%b-%Y')
except (ValueError, KeyError, TypeError):
raise ValidationError("Joining Date is not a valid date")
is_active = request.json_body['IsActive']
try:
if is_active:
leaving_date = None
else:
leaving_date = datetime.datetime.strptime(request.json_body['LeavingDate'], '%d-%b-%Y')
if leaving_date < joining_date:
raise ValidationError("Leaving Date cannot be less than Joining Date")
except (ValueError, KeyError, TypeError):
raise ValidationError("Leaving Date is not a valid date")
item = Employee(0, name, is_active, cost_center_id, designation, salary, service_points, joining_date,
leaving_date).create()
transaction.commit()
return employee_info(item.id)
@ -49,15 +78,44 @@ def update(request):
item = Employee.by_id(uuid.UUID(request.matchdict['id']))
if item.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
item.name = request.json_body['Name']
item.name = request.json_body.get('Name', '').strip()
if item.name == '':
raise ValidationError('Name cannot be blank')
item.cost_center_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
item.designation = request.json_body.get('Designation', '').strip()
try:
item.salary = int(request.json_body['Salary'])
if item.salary < 0:
raise ValidationError("Salary must be an integer >= 0")
except (ValueError, KeyError):
raise ValidationError("Salary must be an integer >= 0")
try:
item.service_points = int(request.json_body['ServicePoints'])
if item.service_points < 0:
raise ValidationError("Service Points must be an integer >= 0")
except (ValueError, KeyError):
raise ValidationError("Service Points must be an integer >= 0")
try:
item.joining_date = datetime.datetime.strptime(request.json_body['JoiningDate'], '%d-%b-%Y')
except (ValueError, KeyError, TypeError):
raise ValidationError("Joining Date is not a valid date")
item.is_active = request.json_body['IsActive']
item.costcenter_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
item.designation = request.json_body['Designation']
item.salary = int(request.json_body['Salary'])
item.service_points = int(request.json_body['ServicePoints'])
item.joining_date = datetime.datetime.strptime(request.json_body['JoiningDate'], '%d-%b-%Y')
item.leaving_date = None if item.is_active else datetime.datetime.strptime(request.json_body['LeavingDate'],
'%d-%b-%Y')
try:
if item.is_active:
item.leaving_date = None
else:
item.leaving_date = datetime.datetime.strptime(request.json_body['LeavingDate'], '%d-%b-%Y')
if item.leaving_date < item.joining_date:
raise ValidationError("Leaving Date cannot be less than Joining Date")
except (ValueError, KeyError, TypeError):
raise ValidationError("Leaving Date is not a valid date")
transaction.commit()
return employee_info(item.id)
@ -141,8 +199,8 @@ def employee_info(id):
def delete_with_data(employee):
suspense_ledger = Ledger.by_id(Ledger.suspense())
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True))\
.filter(Voucher.journals.any(Journal.ledger_id == employee.id))\
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
.filter(Voucher.journals.any(Journal.ledger_id == employee.id)) \
.all()
for voucher in query:

View File

@ -1,4 +1,4 @@
from decimal import Decimal
from decimal import Decimal, InvalidOperation
import uuid
from pyramid.response import Response
from pyramid.security import authenticated_userid
@ -27,21 +27,42 @@ def html(request):
@TryCatchFunction
def save(request):
json = request.json_body
name = json.get('Name', '').strip()
if name == '':
raise ValidationError('Name cannot be blank')
units = json.get('Units', '').strip()
fraction = Decimal(json.get('Fraction', 0))
try:
fraction = Decimal(json.get('Fraction', 0))
if fraction <= 0 or fraction > 1:
raise ValidationError("Fraction must be a decimal > 0 and <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal > 0 and <= 1")
fraction_units = json.get('FractionUnits', '').strip()
yeild = Decimal(json.get('Yeild', 1))
try:
product_yield = Decimal(json.get('ProductYield', 1))
if product_yield < 0 or product_yield > 1:
raise ValidationError("Yield must be a decimal >= 0 <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Yield must be a decimal >= 0 <= 1")
show_for_purchase = json.get('ShowForPurchase', True)
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['ProductGroupID'])
price = Decimal(json.get('Price', 0))
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")
discontinued = json.get('Discontinued', False)
item = Product(0, name, units, fraction, fraction_units, yeild, show_for_purchase, product_group_id,
item = Product(0, name, units, fraction, fraction_units, product_yield, show_for_purchase, product_group_id,
Ledger.all_purchases(), price, discontinued).create()
transaction.commit()
return product_info(item.id)
@ -55,13 +76,30 @@ def update(request):
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.full_name))
item.name = request.json_body['Name'].strip()
item.units = request.json_body['Units'].strip()
item.fraction = Decimal(request.json_body['Fraction'])
try:
item.fraction = Decimal(request.json_body['Fraction'])
if item.fraction <= 0 or item.fraction > 1:
raise ValidationError("Fraction must be a decimal > 0 and <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal > 0 and <= 1")
item.fraction_units = request.json_body['FractionUnits']
item.yeild = Decimal(request.json_body['Yeild'])
try:
item.product_yield = Decimal(request.json_body['ProductYield'])
if item.product_yield < 0 or item.product_yield > 1:
raise ValidationError("Yield must be a decimal >= 0 <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Yield must be a decimal >= 0 <= 1")
item.show_for_purchase = request.json_body['ShowForPurchase']
item.product_group_id = uuid.UUID(request.json_body['ProductGroup']['ProductGroupID'])
item.ledger_id = Ledger.all_purchases()
item.price = Decimal(request.json_body['Price'])
try:
item.price = Decimal(request.json_body['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.discontinued = request.json_body['Discontinued']
transaction.commit()
return product_info(item.id)
@ -131,9 +169,10 @@ def product_info(id):
else:
product = Product.by_id(id)
product = {'ProductID': product.id, 'Code': product.code, 'Name': product.name, 'Units': product.units,
'Fraction': product.fraction, 'FractionUnits': product.fraction_units, 'Yeild': product.yeild,
'ShowForPurchase': product.show_for_purchase, 'Discontinued': product.discontinued,
'IsFixture': product.is_fixture, 'ProductGroup': {'ProductGroupID': product.product_group_id},
'Fraction': product.fraction, 'FractionUnits': product.fraction_units,
'ProductYield': product.product_yield, 'ShowForPurchase': product.show_for_purchase,
'Discontinued': product.discontinued, 'IsFixture': product.is_fixture,
'ProductGroup': {'ProductGroupID': product.product_group_id},
'Ledger': {'LedgerID': product.ledger_id}, 'Price': product.price}
return product

View File

@ -6,7 +6,7 @@ from brewman.models.voucher import Batch
@view_config(request_method='GET', route_name='api_batch', renderer='json', permission='Authenticated')
def batch_term(request):
filter = request.GET.get('term', None)
filter = filter if filter is not None and filter is not '' else None
filter = filter if filter is not None and filter.strip() is not '' else None
count = request.GET.get('count', None)
count = None if count is None or count == '' else int(count)
date = request.GET.get('date', None)