Removed: Pyramid Debug Toolbar dependency removed.

Recipe: Recipe list and Add / Delete recipe created.
Breaking: Major updates to old databases needed as structure has changed significantly
Product table is not a inherited table similar to ledger table
table prefixes for entities removed
renamed a few tables
removed file types not used from the manifest
README.txt now contains the installation procedure on an Ubuntu 14.04 machine
Product.ShowForPurchase column removed
Product.Discountinued renamed to !Product.IsActive
This commit is contained in:
Amritanshu committed 2014-04-29 15:38:44 +05:30
1 parent 246f8465d7
commit 1448120941
48 files changed
+1094 -264

No files matched your search

+1 -1
View File
@@ -1,2 +1,2 @@
include *.txt *.ini *.cfg *.rst include *.txt *.ini *.cfg *.rst
recursive-include brewman *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.map *.eot *.svg *.ttf *.woff recursive-include brewman *.ico *.png *.css *.gif *.jpg *.txt *.js *.html *.map *.eot *.svg *.ttf *.woff
+41 -1
View File
@@ -1 +1,41 @@
brewman README # Installation on Ubuntu 14.04
## Prepare the system
1. Install system-wide pip
**Currently the ensurepip is broken in Python 3.4 / Ubuntu 14.04, therefore we need to install system-wide pip**
```bash
sudo apt-get install python3-pip
```
2. Install postgresql
```bash
sudo apt-get install postgresql postgresql-client pgadmin3
```
[Full Guide](https://help.ubuntu.com/community/PostgreSQL)
3. Configure the server and set password
```bash
sudo -u postgresql psql postgres
\password postgres
```
4. Install components to build psycopg2
```bash
sudo apt-get install libpq-dev python3-dev
```
## Setup the virutal environment
1. Create the virtual environment
**Currently the ensurepip is broken in Python 3.4 / Ubuntu 14.04, therefore --without-pip is needed.**
```bash
pyvenv-3.4 env --without-pip --system-site-packages
```
2. Activate the virtual environment
```bash
source env/bin/activate
```
3. Install pyramid, sqlachemy, psycopg2 and other dependencies:
```bash
python3 -m pip install pyramid waitress sqlalchemy zope.sqlalchemy psycopg2
```
+1
View File
@@ -67,6 +67,7 @@ def main(global_config, **settings):
add_route(config, 'group', '/Group') add_route(config, 'group', '/Group')
add_route(config, 'client', '/Client') add_route(config, 'client', '/Client')
add_route(config, 'product', '/Product') add_route(config, 'product', '/Product')
add_route(config, 'recipe', '/Recipe')
add_route(config, 'product_group', '/ProductGroup') add_route(config, 'product_group', '/ProductGroup')
config.add_route('journal_id', '/Journal/{id}') config.add_route('journal_id', '/Journal/{id}')
+14 -1
View File
@@ -18,11 +18,24 @@ class RootFactory(object):
pass pass
def pluralize(word, num=None):
if num is None or num != 1:
if word.endswith('y'):
return word[:-1] + 'ies'
elif word[-1] in 'sx' or word[-2:] in ['sh', 'ch']:
return word + 'es'
elif word.endswith('an'):
return word[:-2] + 'en'
else:
return word + 's'
return word
def add_route(config, name, url, has_list=True, variable='id'): def add_route(config, name, url, has_list=True, variable='id'):
config.add_route(name + '_' + variable, url + '/{' + variable + '}') config.add_route(name + '_' + variable, url + '/{' + variable + '}')
config.add_route(name, url) config.add_route(name, url)
if has_list: if has_list:
config.add_route(name + '_list', url + 's') config.add_route(name + '_list', pluralize(url))
config.add_route('api_' + name + '_' + variable, '/api' + url + '/{' + variable + '}') config.add_route('api_' + name + '_' + variable, '/api' + url + '/{' + variable + '}')
config.add_route('api_' + name, '/api' + url) config.add_route('api_' + name, '/api' + url)
+7 -3
View File
@@ -27,7 +27,7 @@ def fixtures(engine):
import uuid import uuid
from brewman.models.messaging import Tag, Thread, Subscriber, thread_tag, Post 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.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.master import Product, AttendanceType, CostCenter, Employee, Ledger, LedgerBase, LedgerType, ProductGroup, MenuItem, Recipe, RecipeItem
from brewman.models.auth import Client, Group, Role, User, role_group, user_group from brewman.models.auth import Client, Group, Role, User, role_group, user_group
Base.metadata.create_all(engine) Base.metadata.create_all(engine)
@@ -66,6 +66,7 @@ def fixtures(engine):
Role('Purchase Entries', uuid.UUID('78a6422b-aa11-174c-9dfa-412a99e87e02')), Role('Purchase Entries', uuid.UUID('78a6422b-aa11-174c-9dfa-412a99e87e02')),
Role('Purchase Return', uuid.UUID('ab33196e-d9e4-114c-ac8c-997954363756')), Role('Purchase Return', uuid.UUID('ab33196e-d9e4-114c-ac8c-997954363756')),
Role('Receipt', uuid.UUID('1f1ce53e-76ff-a346-974a-65db6f606e5f')), Role('Receipt', uuid.UUID('1f1ce53e-76ff-a346-974a-65db6f606e5f')),
Role('Recipes', uuid.UUID('ffb7fb65-d42c-424d-9ff1-45069e3b4a29')),
Role('Closing Stock', uuid.UUID('97515732-24e4-c94d-9585-d4bd7f6c7891')), Role('Closing Stock', uuid.UUID('97515732-24e4-c94d-9585-d4bd7f6c7891')),
Role('Ledger', uuid.UUID('a2120944-243f-3f49-be57-0ad633ce4801')), Role('Ledger', uuid.UUID('a2120944-243f-3f49-be57-0ad633ce4801')),
Role('Raw Material Cost', uuid.UUID('d462842b-baf1-2343-95e5-ffdba9bbc163')), Role('Raw Material Cost', uuid.UUID('d462842b-baf1-2343-95e5-ffdba9bbc163')),
@@ -116,8 +117,11 @@ def fixtures(engine):
product_group = ProductGroup('Suspense', uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), True) product_group = ProductGroup('Suspense', uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), True)
DBSession.add(product_group) DBSession.add(product_group)
product = Product(1, 'Suspense', '', 1, '', 1, False, uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), DBSession.add(ProductGroup('Semi', uuid.UUID('e6bf81b9-1e9b-499f-81d5-ab5662e9d9b1'), True))
uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), 0, True, DBSession.add(ProductGroup('Menu Items', uuid.UUID('dad46805-f577-4e5b-8073-9b788e0173fc'), True))
product = Product(1, 'Suspense', '', 1, '', 1, uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'),
uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), 0, False,
uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15'), True) uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15'), True)
DBSession.add(product) DBSession.add(product)
+94 -20
View File
@@ -1,15 +1,19 @@
import uuid import uuid
from sqlalchemy import UniqueConstraint, Column, Integer, Unicode, Numeric, Boolean, ForeignKey, func, DateTime, desc, PickleType
from sqlalchemy import UniqueConstraint, Column, Integer, Unicode, Numeric, Boolean, ForeignKey, func, DateTime, desc, \
PickleType
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from brewman.models import Base, DBSession from brewman.models import Base, DBSession
from brewman.models.guidtype import GUID from brewman.models.guidtype import GUID
__author__ = 'tanshu' __author__ = 'tanshu'
class Product(Base): class ProductBase(Base):
__tablename__ = 'entities_products' __tablename__ = 'products'
__tableagrs__ = (UniqueConstraint('Name', 'Units')) __table_args__ = (UniqueConstraint('Name', 'Units'), )
id = Column('ProductID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('ProductID', GUID(), primary_key=True, default=uuid.uuid4)
code = Column('Code', Integer, unique=True) code = Column('Code', Integer, unique=True)
@@ -18,33 +22,32 @@ class Product(Base):
fraction = Column('Fraction', Numeric, nullable=False) fraction = Column('Fraction', Numeric, nullable=False)
fraction_units = Column('FractionUnits', Unicode(255), nullable=False) fraction_units = Column('FractionUnits', Unicode(255), nullable=False)
product_yield = Column('ProductYield', 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('product_groups.ProductGroupID'),
product_group_id = Column('ProductGroupID', GUID(), ForeignKey('entities_productgroups.ProductGroupID'),
nullable=False) nullable=False)
ledger_id = Column('LedgerID', GUID(), ForeignKey('entities_ledgers.LedgerID'), nullable=False) ledger_id = Column('LedgerID', GUID(), ForeignKey('ledgers.LedgerID'), nullable=False)
price = Column('Price', Numeric, nullable=False) price = Column('Price', Numeric, nullable=False)
discontinued = Column('Discontinued', Boolean, nullable=False) is_active = Column('IsActive', Boolean, nullable=False)
is_fixture = Column('IsFixture', Boolean, nullable=False) is_fixture = Column('IsFixture', Boolean, nullable=False)
product_type = Column('product_type', Unicode(50), nullable=False)
__mapper_args__ = {'polymorphic_on': product_type}
batches = relationship('Batch', backref='product') batches = relationship('Batch', backref='product')
inventories = relationship('Inventory', backref='product') inventories = relationship('Inventory', backref='product')
ledger = relationship('Ledger', primaryjoin="Ledger.id==Product.ledger_id", backref='products') 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, product_yield=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, product_group_id=None, ledger_id=None, price=None, is_active=None, id=None, is_fixture=False):
id=None,is_fixture=False):
self.code = code self.code = code
self.name = name self.name = name
self.units = units self.units = units
self.fraction = fraction self.fraction = fraction
self.fraction_units = fraction_units self.fraction_units = fraction_units
self.product_yield = product_yield self.product_yield = product_yield
self.show_for_purchase = show_for_purchase
self.product_group_id = product_group_id self.product_group_id = product_group_id
self.ledger_id = ledger_id self.ledger_id = ledger_id
self.price = price self.price = price
self.discontinued = discontinued self.is_active = is_active
self.id = id self.id = id
self.is_fixture = is_fixture self.is_fixture = is_fixture
@@ -56,7 +59,7 @@ class Product(Base):
def list(cls, name, active): def list(cls, name, active):
query = DBSession.query(cls) query = DBSession.query(cls)
if active is not None: if active is not None:
query = query.filter(cls.discontinued != active) query = query.filter(cls.is_active == active)
for item in name.split(): for item in name.split():
query = query.filter(cls.name.ilike('%' + item + '%')) query = query.filter(cls.name.ilike('%' + item + '%'))
return query.order_by(cls.name) return query.order_by(cls.name)
@@ -78,7 +81,7 @@ class Product(Base):
return DBSession.query(cls) return DBSession.query(cls)
def create(self): def create(self):
code = DBSession.query(func.max(Product.code)).one()[0] code = DBSession.query(func.max(ProductBase.code)).one()[0]
if code is None: if code is None:
self.code = 1 self.code = 1
else: else:
@@ -89,7 +92,7 @@ class Product(Base):
def can_delete(self, advanced_delete): def can_delete(self, advanced_delete):
if self.is_fixture: if self.is_fixture:
return False, "{0} is a fixture and cannot be edited or deleted.".format(self.name) return False, "{0} is a fixture and cannot be edited or deleted.".format(self.name)
if not self.discontinued: if self.is_active:
return False, 'Product is active' return False, 'Product is active'
if len(self.inventories) > 0 and not advanced_delete: if len(self.inventories) > 0 and not advanced_delete:
return False, 'Product has entries' return False, 'Product has entries'
@@ -100,8 +103,71 @@ class Product(Base):
return uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15') return uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15')
class Product(ProductBase):
__mapper_args__ = {'polymorphic_identity': ''}
class MenuItem(ProductBase):
__tablename__ = 'menu_items'
__mapper_args__ = {'polymorphic_identity': 'menu_items'}
id = Column('ProductID', GUID(), ForeignKey(ProductBase.id), primary_key=True)
is_semi = Column('is_semi', Boolean, nullable=False)
recipes = relationship('Recipe', backref='product')
def __init__(self, code=None, name=None, units=None, is_semi=None, fraction=None, fraction_units=None,
product_group_id=None, ledger_id=None, price=None, is_active=None, id=None):
self.is_semi = is_semi
super().__init__(code=code, name=name, units=units, fraction=fraction, fraction_units=fraction_units,
product_yield=1, product_group_id=product_group_id, ledger_id=ledger_id, price=price,
is_active=is_active, id=id, is_fixture=False)
class Recipe(Base):
__tablename__ = 'recipes'
__table_args__ = (UniqueConstraint('date', 'product_id'), )
id = Column('recipe_id', GUID(), primary_key=True, default=uuid.uuid4)
date = Column('date', DateTime, nullable=False)
product_id = Column('product_id', GUID(), ForeignKey(MenuItem.id), nullable=False)
quantity = Column('quantity', Numeric, nullable=False)
sale_price = Column('sale_price', Numeric, nullable=True)
notes = Column('notes', Unicode(255))
recipe_items = relationship('RecipeItem', backref='recipe')
def __init__(self, date=None, product_id=None, quantity=None, sale_price=None, notes=None, id=None):
self.date = date
self.product_id = product_id
self.quantity = quantity
self.sale_price = sale_price
self.notes = notes
self.id = id
class RecipeItem(Base):
__tablename__ = 'recipe_items'
__table_args__ = (UniqueConstraint('recipe_id', 'ingredient_id'), )
id = Column('recipe_item_id', GUID(), primary_key=True, default=uuid.uuid4)
recipe_id = Column('recipe_id', GUID(), ForeignKey('recipes.recipe_id'), nullable=False)
ingredient_id = Column('ingredient_id', GUID(), ForeignKey('products.ProductID'), nullable=False)
quantity = Column('quantity', Integer, nullable=False)
price = Column('price', Integer, nullable=False)
product = relationship('ProductBase')
def __init__(self, recipe_id=None, ingredient_id=None, quantity=None, price=None, id=None):
self.recipe_id = recipe_id
self.ingredient_id = ingredient_id
self.quantity = quantity
self.price = price
self.id = id
class ProductGroup(Base): class ProductGroup(Base):
__tablename__ = 'entities_productgroups' __tablename__ = 'product_groups'
id = Column('ProductGroupID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('ProductGroupID', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('Name', Unicode(255), unique=True) name = Column('Name', Unicode(255), unique=True)
@@ -122,9 +188,17 @@ class ProductGroup(Base):
def by_id(cls, id): def by_id(cls, id):
return DBSession.query(cls).filter(cls.id == id).first() return DBSession.query(cls).filter(cls.id == id).first()
@classmethod
def menu_item(cls):
return uuid.UUID('dad46805-f577-4e5b-8073-9b788e0173fc')
@classmethod
def semi(cls):
return uuid.UUID('e6bf81b9-1e9b-499f-81d5-ab5662e9d9b1')
class CostCenter(Base): class CostCenter(Base):
__tablename__ = 'entities_costcenters' __tablename__ = 'cost_centers'
id = Column('CostCenterID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('CostCenterID', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('Name', Unicode(255), unique=True) name = Column('Name', Unicode(255), unique=True)
@@ -168,7 +242,7 @@ class CostCenter(Base):
class LedgerBase(Base): class LedgerBase(Base):
__tablename__ = 'entities_ledgers' __tablename__ = 'ledgers'
id = Column('LedgerID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('LedgerID', GUID(), primary_key=True, default=uuid.uuid4)
code = Column('Code', Integer) code = Column('Code', Integer)
@@ -177,7 +251,7 @@ class LedgerBase(Base):
ledger_type = Column('ledger_type', Unicode(50), nullable=False) ledger_type = Column('ledger_type', Unicode(50), nullable=False)
is_active = Column('IsActive', Boolean) is_active = Column('IsActive', Boolean)
is_reconcilable = Column('IsReconcilable', Boolean) is_reconcilable = Column('IsReconcilable', Boolean)
costcenter_id = Column('CostCenterID', GUID(), ForeignKey('entities_costcenters.CostCenterID')) costcenter_id = Column('CostCenterID', GUID(), ForeignKey('cost_centers.CostCenterID'))
is_fixture = Column('IsFixture', Boolean, nullable=False) is_fixture = Column('IsFixture', Boolean, nullable=False)
__mapper_args__ = {'polymorphic_on': ledger_type} __mapper_args__ = {'polymorphic_on': ledger_type}
@@ -287,7 +361,7 @@ class LedgerBase(Base):
class Employee(LedgerBase): class Employee(LedgerBase):
__tablename__ = 'entities_employees' __tablename__ = 'employees'
__mapper_args__ = {'polymorphic_identity': 'employees'} __mapper_args__ = {'polymorphic_identity': 'employees'}
id = Column('LedgerID', GUID(), ForeignKey(LedgerBase.id), primary_key=True) id = Column('LedgerID', GUID(), ForeignKey(LedgerBase.id), primary_key=True)
+20 -20
View File
@@ -2,7 +2,7 @@ from datetime import datetime
import uuid import uuid
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy import Column, Integer, Boolean, Unicode, DateTime, Numeric, ForeignKey from sqlalchemy import Column, Integer, Boolean, Unicode, DateTime, Numeric, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship, synonym, backref from sqlalchemy.orm import relationship, synonym, backref
from brewman.models.guidtype import GUID from brewman.models.guidtype import GUID
@@ -49,7 +49,7 @@ class VoucherType:
class Voucher(Base): class Voucher(Base):
__tablename__ = 'entities_vouchers' __tablename__ = 'vouchers'
id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4)
date = Column('Date', DateTime, nullable=False) date = Column('Date', DateTime, nullable=False)
@@ -117,14 +117,14 @@ class Voucher(Base):
class Journal(Base): class Journal(Base):
__tablename__ = 'entities_journals' __tablename__ = 'journals'
id = Column('JournalID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('JournalID', GUID(), primary_key=True, default=uuid.uuid4)
debit = Column('Debit', Integer) debit = Column('Debit', Integer)
amount = Column('Amount', Numeric) amount = Column('Amount', Numeric)
voucher_id = Column('VoucherID', GUID(), ForeignKey('entities_vouchers.VoucherID'), nullable=False) voucher_id = Column('VoucherID', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False)
ledger_id = Column('LedgerID', GUID(), ForeignKey('entities_ledgers.LedgerID'), nullable=False) ledger_id = Column('LedgerID', GUID(), ForeignKey('ledgers.LedgerID'), nullable=False)
cost_center_id = Column('CostCenterID', GUID(), ForeignKey('entities_costcenters.CostCenterID'), nullable=False) cost_center_id = Column('CostCenterID', GUID(), ForeignKey('cost_centers.CostCenterID'), nullable=False)
@hybrid_property @hybrid_property
def signed_amount(self): def signed_amount(self):
@@ -156,10 +156,10 @@ class Journal(Base):
class SalaryDeduction(Base): class SalaryDeduction(Base):
__tablename__ = 'entities_salarydeductions' __tablename__ = 'salary_deductions'
id = Column('SalaryDeductionID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('SalaryDeductionID', GUID(), primary_key=True, default=uuid.uuid4)
voucher_id = Column('VoucherID', GUID(), ForeignKey('entities_vouchers.VoucherID'), nullable=False) voucher_id = Column('VoucherID', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False)
journal_id = Column('JournalID', GUID(), ForeignKey('entities_journals.JournalID'), nullable=False) journal_id = Column('JournalID', GUID(), ForeignKey('journals.JournalID'), nullable=False)
gross_salary = Column('GrossSalary', Integer) gross_salary = Column('GrossSalary', Integer)
days_worked = Column('DaysWorked', Integer) days_worked = Column('DaysWorked', Integer)
esi_ee = Column('EsiEmployee', Integer) esi_ee = Column('EsiEmployee', Integer)
@@ -186,12 +186,12 @@ class SalaryDeduction(Base):
class Inventory(Base): class Inventory(Base):
__tablename__ = 'entities_inventories' __tablename__ = 'inventories'
# __tableagrs__ = (UniqueConstraint('VoucherID', 'ProductID')) __table_args__ = (UniqueConstraint('VoucherID', 'BatchID'), )
id = Column('InventoryID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('InventoryID', GUID(), primary_key=True, default=uuid.uuid4)
voucher_id = Column('VoucherID', GUID(), ForeignKey('entities_vouchers.VoucherID'), nullable=False) voucher_id = Column('VoucherID', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False)
product_id = Column('ProductID', GUID(), ForeignKey('entities_products.ProductID'), nullable=False) product_id = Column('ProductID', GUID(), ForeignKey('products.ProductID'), nullable=False)
batch_id = Column('BatchID', GUID(), ForeignKey('entities_batches.BatchID'), nullable=False) batch_id = Column('BatchID', GUID(), ForeignKey('batches.BatchID'), nullable=False)
quantity = Column('Quantity', Numeric) quantity = Column('Quantity', Numeric)
rate = Column('Rate', Numeric) rate = Column('Rate', Numeric)
tax = Column('Tax', Numeric) tax = Column('Tax', Numeric)
@@ -216,11 +216,11 @@ class Inventory(Base):
class Batch(Base): class Batch(Base):
__tablename__ = 'entities_batches' __tablename__ = 'batches'
id = Column('BatchID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('BatchID', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('Name', DateTime) name = Column('Name', DateTime)
product_id = Column('ProductID', GUID(), ForeignKey('entities_products.ProductID'), nullable=False) product_id = Column('ProductID', GUID(), ForeignKey('products.ProductID'), nullable=False)
quantity_remaining = Column('QuantityRemaining', Numeric) quantity_remaining = Column('QuantityRemaining', Numeric)
rate = Column('Rate', Numeric) rate = Column('Rate', Numeric)
tax = Column('Tax', Numeric) tax = Column('Tax', Numeric)
@@ -262,10 +262,10 @@ class Batch(Base):
class Attendance(Base): class Attendance(Base):
__tablename__ = 'entities_attendances' __tablename__ = 'attendances'
id = Column('AttendanceID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('AttendanceID', GUID(), primary_key=True, default=uuid.uuid4)
employee_id = Column('EmployeeID', GUID(), ForeignKey('entities_employees.LedgerID')) employee_id = Column('EmployeeID', GUID(), ForeignKey('employees.LedgerID'))
date = Column('Date', DateTime) date = Column('Date', DateTime)
attendance_type = Column('AttendanceType', Integer) attendance_type = Column('AttendanceType', Integer)
amount = Column('Amount', Numeric) amount = Column('Amount', Numeric)
@@ -305,10 +305,10 @@ class Attendance(Base):
class Fingerprint(Base): class Fingerprint(Base):
__tablename__ = 'entities_fingerprints' __tablename__ = 'fingerprints'
id = Column('FingerprintID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('FingerprintID', GUID(), primary_key=True, default=uuid.uuid4)
employee_id = Column('EmployeeID', GUID(), ForeignKey('entities_employees.LedgerID')) employee_id = Column('EmployeeID', GUID(), ForeignKey('employees.LedgerID'))
date = Column('Date', DateTime) date = Column('Date', DateTime)
def __init__(self, id=None, employee_id=None, date=None): def __init__(self, id=None, employee_id=None, date=None):
@@ -8,11 +8,11 @@
<meta name="author" content="Tanshu"> <meta name="author" content="Tanshu">
<!-- Le styles --> <!-- Le styles -->
## <link rel="stylesheet" type="text/css" media="screen" href="/css/style.css"/> <!-- <link rel="stylesheet" type="text/css" media="screen" href="/css/style.css"/> -->
<link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap.min.css"/> <link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="/css/hack.css"/> <link rel="stylesheet" type="text/css" media="screen" href="/css/hack.css"/>
## <link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap-theme.min.css"/> <!-- <link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap-theme.min.css"/> -->
<link rel="stylesheet" type="text/css" media="screen" href="/css/table.css"/> <link rel="stylesheet" type="text/css" media="screen" href="/css/table.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="/css/chosen.min.css"/> <link rel="stylesheet" type="text/css" media="screen" href="/css/chosen.min.css"/>
@@ -25,7 +25,7 @@
} }
</style> </style>
## <script src="/js/mousetrap.min.js"></script> <!-- <script src="/js/mousetrap.min.js"></script> -->
<script src="/js/jquery-2.1.0.min.js"></script> <script src="/js/jquery-2.1.0.min.js"></script>
<script src="/js/lodash.min.js"></script> <script src="/js/lodash.min.js"></script>
<script src="/js/bootstrap.min.js"></script> <script src="/js/bootstrap.min.js"></script>
@@ -69,6 +69,7 @@
<script src="/script/purchases.js"></script> <script src="/script/purchases.js"></script>
<script src="/script/ledger.js"></script> <script src="/script/ledger.js"></script>
<script src="/script/reconcile.js"></script> <script src="/script/reconcile.js"></script>
<script src="/script/recipe.js"></script>
<script src="/script/product-ledger.js"></script> <script src="/script/product-ledger.js"></script>
<script src="/script/trial-balance.js"></script> <script src="/script/trial-balance.js"></script>
<script src="/script/net-transactions.js"></script> <script src="/script/net-transactions.js"></script>
@@ -183,6 +184,7 @@
<li><a href="/Accounts">Accounts</a></li> <li><a href="/Accounts">Accounts</a></li>
<li><a href="/CostCenters">Cost Centers</a></li> <li><a href="/CostCenters">Cost Centers</a></li>
<li><a href="/Products">Products</a></li> <li><a href="/Products">Products</a></li>
<li><a href="/Recipes">Recipes</a></li>
<li><a href="/ProductGroups">Product Groups</a></li> <li><a href="/ProductGroups">Product Groups</a></li>
</ul> </ul>
</li> </li>
+1 -4
View File
@@ -54,10 +54,7 @@
<div class="form-group"> <div class="form-group">
<div class="col-md-offset-2 col-md-10"> <div class="col-md-offset-2 col-md-10">
<label class="checkbox-inline"> <label class="checkbox-inline">
<input type="checkbox" ng-model="product.ShowForPurchase"> Show for Purchase <input type="checkbox" ng-model="product.IsActive"> Is Active?
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="product.Discontinued"> Discontinued
</label> </label>
</div> </div>
</div> </div>
+2 -2
View File
@@ -16,7 +16,7 @@
<th>Name</th> <th>Name</th>
<th>Price</th> <th>Price</th>
<th>Type</th> <th>Type</th>
<th>Discontinued</th> <th>Is Active?</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -25,7 +25,7 @@
<td><a href="{{item.Url}}">{{item.Name}} ({{item.Units}})</a></td> <td><a href="{{item.Url}}">{{item.Name}} ({{item.Units}})</a></td>
<td>₹ {{item.Price}}</td> <td>₹ {{item.Price}}</td>
<td>{{item.ProductGroup}}</td> <td>{{item.ProductGroup}}</td>
<td>{{item.Discontinued}}</td> <td>{{item.IsActive}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+109
View File
@@ -0,0 +1,109 @@
<form class="form-horizontal" role=form>
<h2>Recipe Detail</h2>
<div class="form-group">
<label for="txtName" class="col-md-2 control-label">Name</label>
<div class="col-md-4">
<input type="text" id="txtName" class="form-control" ng-model="recipe.Name"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control" ng-model="recipe.Quantity" placeholder="Quantity"/>
</div>
<div class="col-md-2">
<div class="input-group">
<input class="form-control" id="txtDate" type="text" datepicker-popup="dd-MMM-yyyy" placeholder="Date"
ng-model="recipe.Date"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<div class="col-md-2">
<p class="form-control-static">{{cost_price | currency}} / {{cost_price * 100 / recipe.SalePrice | number:2 }}%</p>
</div>
</div>
<div class="form-group">
<div class="col-md-2">
<label class="checkbox-inline control-label pull-right">
<input type="checkbox" ng-model="recipe.IsSemi"> Is Semi?
</label>
</div>
<div class="col-md-2" ng-show="recipe.IsSemi">
<input type="text" class="form-control" ng-model="recipe.Units" placeholder="Units"/>
</div>
<div class="col-md-2" ng-show="recipe.IsSemi">
<input type="text" class="form-control" ng-model="recipe.Fraction" placeholder="Fraction"/>
</div>
<div class="col-md-2" ng-show="recipe.IsSemi">
<input type="text" class="form-control" ng-model="recipe.FractionUnits" placeholder="Fraction Units"/>
</div>
<div class="col-md-2" ng-hide="recipe.IsSemi">
<div class="input-group">
<span class="input-group-addon">₹</span>
<input type="text" id="txtPrice" class="form-control" ng-model="recipe.SalePrice"
placeholder="Sale Price"/>
</div>
</div>
<div class="col-md-4" ng-hide="recipe.IsSemi">
<select id="ddlType" class="form-control" ng-model="recipe.ProductGroup.ProductGroupID"
ng-options="l.ProductGroupID as l.Name for l in product_groups"> </select>
</div>
</div>
<div class="form-group">
<label for="txtAccount" class="col-md-2 control-label">Ingredient</label>
<div class="col-md-5">
<input type="text" id="txtProduct" class="form-control" ng-model="product"
typeahead="product as product.Name for product in products($viewValue)"
typeahead-editable="false" on-return="add()"/>
</div>
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" placeholder="Qty" ng-model="quantity" on-return="add()"/>
<span class="input-group-addon">{{product.FractionUnits}}</span>
</div>
</div>
<div class="col-md-3">
<div class="input-group">
<span class="input-group-addon">₹</span>
<input type="text" class="form-control" placeholder="Price" ng-model="product.Price" on-return="add()"/>
<span class="input-group-addon">/{{product.Units}}</span>
<span class="input-group-btn">
<button class="btn btn-info" ng-click="add()">Add <i
class="glyphicon glyphicon-plus-sign"></i>
</button>
</span>
</div>
</div>
<table id="gvGrid" class="table table-condensed table-striped">
<thead>
<tr>
<th>Ingredient</th>
<th>Unit</th>
<th class="text-right">Quantity</th>
<th class="text-right">Rate</th>
<th class="text-right">Amount</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in recipe.RecipeItems">
<td>{{item.Product.Name}}</td>
<td>{{item.Product.FractionUnits}}</td>
<td class="text-right">{{item.Quantity | number:2}}</td>
<td class="text-right">{{item.Price / (item.Product.Fraction * item.Product.ProductYield) | currency}}</td>
<td class="text-right">{{item.Quantity * (item.Price / (item.Product.Fraction * item.Product.ProductYield)) | currency}}</td>
<td>
<button type="button" class="close" ng-click="removeItem(item)">×</button>
</td>
</tr>
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-danger" ng-show="recipe.RecipeID" ng-click="confirm()">Delete</button>
</div>
</div>
</form>
+81
View File
@@ -0,0 +1,81 @@
<form class="form-horizontal" role=form>
<h2>Recipes
<div class="form-group col-md-9 pull-right">
<div class="col-md-10">
<input type="text" class="form-control" placeholder="Search" ng-model="search">
</div>
<div class="col-md-2">
<a href="/Recipe" class="btn btn-success btn-block">Add <i
class="glyphicon glyphicon-plus"></i></a>
</div>
</div>
</h2>
<div class="form-group">
<div class="col-md-offset-2 col-md-2">
<select class="form-control" ng-model="product_type_selected">
<option value="semi">Semi Products</option>
<option value="menu">Menu Items</option>
<option value="all">All</option>
</select>
</div>
<div class="col-md-3">
<select class="form-control" ng-model="show_latest">
<option value="latest">Only Latest Recipes</option>
<option value="all">All Recipes</option>
</select>
</div>
<div class="col-md-3">
<select class="form-control" ng-model="show_summary">
<option value="no">Brief</option>
<option value="yes">With Recipes</option>
</select>
</div>
</div>
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th ng-if="show_summary === 'no'">Date</th>
<th class="text-right">Sale Price</th>
<th class="text-right">Original Cost</th>
<th class="text-right" ng-if="show_summary === 'no'">Current Cost</th>
<th class="text-right">Original Costing</th>
<th class="text-right" ng-if="show_summary === 'no'">Current Costing</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="item in display">
<td><a ng-if="item.IsLatest" href="{{item.Url}}">{{item.Name}} ({{item.Units}})</a></td>
<td ng-if="show_summary === 'no'">{{item.Date}}</td>
<td class="text-right">{{item.IsSemi ? '' : (item.SalePrice | currency)}}</td>
<td class="text-right">{{item.CostPrice | currency}}</td>
<td class="text-right" ng-if="show_summary === 'no'">{{item.CurrentCostPrice | currency}}</td>
<td class="text-right">{{item.IsSemi ? '' : (item.Costing | percent)}}</td>
<td class="text-right" ng-if="show_summary === 'no'">{{item.IsSemi ? '' : (item.CurrentCosting | percent)}}</td>
</tr>
<tr ng-repeat-end ng-if="show_summary === 'yes'">
<td colspan="7">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>Ingredient</th>
<th class="text-right">Quantity</th>
<th class="text-right">Rate</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="sub_item in item.RecipeItems">
<td>{{sub_item.Name}}</td>
<td class="text-right">{{sub_item.Quantity | number:2}} {{sub_item.FractionUnits}}</td>
<td class="text-right">{{sub_item.Price | currency}}</td>
<td class="text-right">{{sub_item.Quantity * sub_item.Price | currency}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</form>
+4
View File
@@ -130,6 +130,10 @@ overlord_directive.directive('keypress', [function () {
}); });
})(k); })(k);
} }
element.on('$destroy', function() {
$interval.cancel(timeoutId);
});
}; };
}]); }]);
+7
View File
@@ -21,6 +21,13 @@ overlord_service.factory('Account', ['$resource', function ($resource) {
}); });
}]); }]);
overlord_service.factory('Recipe', ['$resource', function ($resource) {
return $resource('/api/Recipe/:id',
{id: '@RecipeID'}, {
query: {method: 'GET', params: {list: true}, isArray: true}
});
}]);
overlord_service.factory('Employee', ['$resource', function ($resource) { overlord_service.factory('Employee', ['$resource', function ($resource) {
return $resource('/api/Employee/:id', return $resource('/api/Employee/:id',
{id: '@LedgerID'}, { {id: '@LedgerID'}, {
+4
View File
@@ -83,6 +83,10 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/Product', {templateUrl: '/partial/product-detail.html', controller: ProductCtrl, resolve: ProductCtrl.resolve}). when('/Product', {templateUrl: '/partial/product-detail.html', controller: ProductCtrl, resolve: ProductCtrl.resolve}).
when('/Product/:id', {templateUrl: '/partial/product-detail.html', controller: ProductCtrl, resolve: ProductCtrl.resolve}). when('/Product/:id', {templateUrl: '/partial/product-detail.html', controller: ProductCtrl, resolve: ProductCtrl.resolve}).
when('/Recipes', {templateUrl: '/partial/recipe-list.html', controller: RecipeListCtrl, resolve: RecipeListCtrl.resolve, reloadOnSearch:false}).
when('/Recipe', {templateUrl: '/partial/recipe-detail.html', controller: RecipeCtrl, resolve: RecipeCtrl.resolve}).
when('/Recipe/:id', {templateUrl: '/partial/recipe-detail.html', controller: RecipeCtrl, resolve: RecipeCtrl.resolve}).
when('/ProductGroups', {templateUrl: '/partial/product-group-list.html', controller: ProductGroupListCtrl, resolve: ProductGroupListCtrl.resolve}). when('/ProductGroups', {templateUrl: '/partial/product-group-list.html', controller: ProductGroupListCtrl, resolve: ProductGroupListCtrl.resolve}).
when('/ProductGroup', {templateUrl: '/partial/product-group-detail.html', controller: ProductGroupCtrl, resolve: ProductGroupCtrl.resolve}). when('/ProductGroup', {templateUrl: '/partial/product-group-detail.html', controller: ProductGroupCtrl, resolve: ProductGroupCtrl.resolve}).
when('/ProductGroup/:id', {templateUrl: '/partial/product-group-detail.html', controller: ProductGroupCtrl, resolve: ProductGroupCtrl.resolve}). when('/ProductGroup/:id', {templateUrl: '/partial/product-group-detail.html', controller: ProductGroupCtrl, resolve: ProductGroupCtrl.resolve}).
+6 -6
View File
@@ -45,7 +45,7 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi
if (value.indexOf("'") === 0 || value.indexOf('"') === 0) { if (value.indexOf("'") === 0 || value.indexOf('"') === 0) {
value = value.substring(1, value.length - 2); value = value.substring(1, value.length - 2);
} }
if (key !== '' && value !== '' && _.any(['w', 'u', 'g'], function (item) { if (key !== '' && value !== '' && _.any(['a', 'u', 'g'], function (item) {
return item === key; return item === key;
})) { })) {
matches.push({'key': key, 'value': value}); matches.push({'key': key, 'value': value});
@@ -60,8 +60,8 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi
if (item.Name.toLowerCase().indexOf(match.value) === -1) { if (item.Name.toLowerCase().indexOf(match.value) === -1) {
return false; return false;
} }
} else if (match.key === 'w') { } else if (match.key === 'a') {
if (item.Discontinued === $scope.isTrue(match.value)) { if (item.IsActive === $scope.isTrue(match.value)) {
return false; return false;
} }
} else if (match.key === 'u') { } else if (match.key === 'u') {
@@ -85,14 +85,14 @@ ProductListCtrl.resolve = {
}] }]
}; };
var ProductCtrl = ['$scope', '$location', '$modal', 'product', 'product_groups', function ($scope, $location, $modal, product, product_groups) { var ProductCtrl = ['$scope', '$location', '$window', '$modal', 'product', 'product_groups', function ($scope, $location, $window, $modal, product, product_groups) {
$scope.product = product; $scope.product = product;
$scope.product_groups = product_groups; $scope.product_groups = product_groups;
$scope.save = function () { $scope.save = function () {
$scope.product.$save(function (u, putResponseHeaders) { $scope.product.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: u.Code}); $scope.toasts.push({Type: 'Success', Message: u.Code});
$location.path('/Products'); $window.history.back();
}, function (data, status) { }, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data}); $scope.toasts.push({Type: 'Danger', Message: data.data});
}); });
@@ -101,7 +101,7 @@ var ProductCtrl = ['$scope', '$location', '$modal', 'product', 'product_groups',
$scope.delete = function () { $scope.delete = function () {
$scope.product.$delete(function (u, putResponseHeaders) { $scope.product.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''}); $scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/Products'); $window.history.back();
}, function (data, status) { }, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data}); $scope.toasts.push({Type: 'Danger', Message: data.data});
}); });
+177
View File
@@ -0,0 +1,177 @@
'use strict';
var RecipeListCtrl = ['$scope', 'recipes', function ($scope, recipes) {
$scope.info = recipes;
$scope.display = $scope.info;
$scope.product_type_selected = 'all';
$scope.show_latest = 'latest';
$scope.show_summary = 'no';
$scope.$watch('product_type_selected', function (value) {
$scope.display = $scope.doFilter();
}, true);
$scope.$watch('show_latest', function (value) {
$scope.display = $scope.doFilter();
}, true);
$scope.doFilter = function (q) {
return _.filter($scope.info, function (item) {
if ($scope.product_type_selected === 'menu') {
if (item.IsSemi) {
return false;
}
} else if ($scope.product_type_selected === 'semi') {
if (!item.IsSemi) {
return false;
}
}
if ($scope.show_latest === 'latest' && !item.IsLatest) {
return false;
}
return true;
});
};
}];
RecipeListCtrl.resolve = {
recipes: ['Recipe', function (Recipe) {
return Recipe.query({}).$promise;
}]
};
var RecipeCtrl = ['$scope', '$location', '$window', '$modal', 'dateFilter', 'Product', 'recipe', 'product_groups', function ($scope, $location, $window, $modal, dateFilter, Product, recipe, product_groups) {
$scope.recipe = recipe;
$scope.original = {};
angular.copy($scope.recipe, $scope.original);
$scope.product_groups = product_groups;
$scope.cost_price = 0;
function getOld(productID, recipe_items) {
return _.find(recipe_items, function (recipe_item) {
return recipe_item.Product.ProductID === productID;
});
}
$scope.add = function () {
if (!$scope.product || !$scope.product.ProductID || !$scope.quantity || Number(!$scope.quantity)) {
return;
}
var oldItem = getOld($scope.product.ProductID, this.recipe.RecipeItems);
if (typeof oldItem === 'undefined') {
var quantity = Number($scope.quantity);
var price = Number($scope.product.Price);
this.recipe.RecipeItems.push({
Product: $scope.product,
Quantity: quantity,
Price: price
});
} else {
$scope.toasts.push({Type: 'Danger', Message: 'Ingredient already in the list'});
}
delete $scope.quantity;
delete $scope.product;
$('#txtProduct').focus();
};
$scope.removeItem = function (item) {
var index = this.recipe.RecipeItems.indexOf(item);
this.recipe.RecipeItems.splice(index, 1);
};
$scope.$watch('recipe.RecipeItems', function (recipe_items, oldValue) {
if (!angular.isArray(recipe_items)) {
return;
}
$scope.cost_price = recipe_items.reduce(function (sum, item, index, array) {
var rate = item.Price / (item.Product.Fraction * item.Product.ProductYield)
return sum + (item.Quantity * rate);
}, 0);
}, true);
$scope.save = function () {
if (angular.isDate($scope.recipe.Date)) {
$scope.recipe.Date = dateFilter($scope.recipe.Date, 'dd-MMM-yyyy');
}
if (angular.isUndefined($scope.recipe.Date) || $scope.recipe.Date === '') {
$scope.toasts.push({Type: 'Danger', Message: 'Please Choose a date'});
return;
}
if ($scope.recipe.Date === $scope.original.Date) {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.title = "Update Recipe?";
$scope.body = "Are you sure? This will overwrite the original recipe.";
$scope.isDelete = false;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
$scope.doSave();
});
} else {
$scope.doSave();
}
};
$scope.doSave = function () {
$scope.recipe.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$window.history.back();
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.recipe.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$window.history.back();
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.confirm = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.title = "Delete Recipe";
$scope.body = "Are you sure? This cannot be undone.";
$scope.isDelete = true;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
$scope.delete();
});
};
$('#txtName').focus();
$scope.products = function ($viewValue) {
return Product.autocomplete({term: $viewValue, count: 20, a: true, e: true, t: 'S'}).$promise;
};
}];
RecipeCtrl.resolve = {
recipe: ['$route', 'Recipe', function ($route, Recipe) {
var id = $route.current.params.id;
return Recipe.get({id: id}).$promise;
}],
product_groups: ['ProductGroup', function (ProductGroup) {
return ProductGroup.query({}).$promise;
}]
};
+6 -2
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
@@ -8,9 +10,11 @@ from brewman.models.master import DbSetting
from brewman.models.validation_exception import TryCatchFunction from brewman.models.validation_exception import TryCatchFunction
@view_config(route_name='settings', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='settings', permission='Authenticated')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_lock_info', renderer='json', permission='Lock Date') @view_config(request_method='POST', route_name='api_lock_info', renderer='json', permission='Lock Date')
+6 -4
View File
@@ -11,13 +11,15 @@ from pyramid.view import view_config
from brewman.models.master import DbSetting from brewman.models.master import DbSetting
@view_config(route_name='home', renderer='brewman:templates/angular_base.mako') @view_config(route_name='home')
@view_config(request_method='GET', route_name='login', renderer='brewman:templates/angular_base.mako') @view_config(request_method='GET', route_name='login')
def home(request): def home(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(context=HTTPForbidden, renderer='brewman:templates/angular_base.mako') @view_config(context=HTTPForbidden)
def forbidden(request): def forbidden(request):
if 'X-Requested-With' in request.headers and request.headers['X-Requested-With'] == 'XMLHttpRequest': if 'X-Requested-With' in request.headers and request.headers['X-Requested-With'] == 'XMLHttpRequest':
response = Response("Forbidden") response = Response("Forbidden")
+8 -7
View File
@@ -1,5 +1,6 @@
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
@@ -13,13 +14,13 @@ from brewman.models.validation_exception import ValidationError, TryCatchFunctio
from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.models.voucher import Voucher, Journal, VoucherType
@view_config(route_name='account_list', renderer='brewman:templates/angular_base.mako', permission='Accounts') @view_config(route_name='account_list', permission='Accounts')
@view_config(request_method='GET', route_name='account_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='account_id', permission='Accounts')
permission='Accounts') @view_config(request_method='GET', route_name='account', permission='Accounts')
@view_config(request_method='GET', route_name='account', renderer='brewman:templates/angular_base.mako',
permission='Accounts')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_account', renderer='json', permission='Accounts') @view_config(request_method='POST', route_name='api_account', renderer='json', permission='Accounts')
+9 -9
View File
@@ -1,5 +1,7 @@
import datetime import datetime
import uuid import uuid
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
from sqlalchemy import or_ from sqlalchemy import or_
@@ -13,16 +15,14 @@ from brewman.views.services.session import session_period_start, session_period_
__author__ = 'tanshu' __author__ = 'tanshu'
@view_config(request_method='GET', route_name='attendance_date', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='attendance_date', permission='Attendance')
permission='Attendance') @view_config(request_method='GET', route_name='attendance', permission='Attendance')
@view_config(request_method='GET', route_name='attendance', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='employee_attendance_id', permission='Attendance')
permission='Attendance') @view_config(request_method='GET', route_name='employee_attendance', permission='Attendance')
@view_config(request_method='GET', route_name='employee_attendance_id', renderer='brewman:templates/angular_base.mako',
permission='Attendance')
@view_config(request_method='GET', route_name='employee_attendance', renderer='brewman:templates/angular_base.mako',
permission='Attendance')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_attendance_types', renderer='json', permission='Authenticated') @view_config(request_method='GET', route_name='api_attendance_types', renderer='json', permission='Authenticated')
+7 -6
View File
@@ -1,5 +1,6 @@
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
@@ -9,12 +10,12 @@ from brewman.models.auth import Client
from brewman.models.validation_exception import TryCatchFunction from brewman.models.validation_exception import TryCatchFunction
@view_config(request_method='GET', route_name='client_list', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='client_list', permission='Clients')
permission='Clients') @view_config(request_method='GET', route_name='client_id', permission='Clients')
@view_config(request_method='GET', route_name='client_id', renderer='brewman:templates/angular_base.mako',
permission='Clients')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_client_id', renderer='json', permission='Clients') @view_config(request_method='POST', route_name='api_client_id', renderer='json', permission='Clients')
+8 -7
View File
@@ -1,19 +1,20 @@
import uuid import uuid
import pkg_resources
from pyramid.response import Response from pyramid.response import Response, FileResponse
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.auth import Group, Role from brewman.models.auth import Group, Role
from brewman.models.validation_exception import ValidationError, TryCatchFunction from brewman.models.validation_exception import ValidationError, TryCatchFunction
@view_config(route_name='group_list', renderer='brewman:templates/angular_base.mako', permission='Users') @view_config(route_name='group_list', permission='Users')
@view_config(request_method='GET', route_name='group_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='group_id', permission='Users')
permission='Users') @view_config(request_method='GET', route_name='group', permission='Users')
@view_config(request_method='GET', route_name='group', renderer='brewman:templates/angular_base.mako',
permission='Users')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_group', renderer='json', permission='Users') @view_config(request_method='POST', route_name='api_group', renderer='json', permission='Users')
+8 -7
View File
@@ -1,6 +1,7 @@
import re import re
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
@@ -22,13 +23,13 @@ class UserView(object):
self.user = User.by_id(self.user) self.user = User.by_id(self.user)
self.has_permission = 'Users' in groupfinder(self.user.id, request) self.has_permission = 'Users' in groupfinder(self.user.id, request)
@view_config(route_name='user_list', renderer='brewman:templates/angular_base.mako', permission='Users') @view_config(route_name='user_list', permission='Users')
@view_config(request_method='GET', route_name='user_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='user_id', permission='Authenticated')
permission='Authenticated') @view_config(request_method='GET', route_name='user', permission='Users')
@view_config(request_method='GET', route_name='user', renderer='brewman:templates/angular_base.mako',
permission='Users')
def html(self): def html(self):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=self.request)
@view_config(request_method='POST', route_name='api_user', renderer='json', permission='Users') @view_config(request_method='POST', route_name='api_user', renderer='json', permission='Users')
+8 -7
View File
@@ -1,5 +1,6 @@
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
@@ -9,13 +10,13 @@ from brewman.models.master import CostCenter
from brewman.models.validation_exception import ValidationError, TryCatchFunction from brewman.models.validation_exception import ValidationError, TryCatchFunction
@view_config(route_name='cost_center_list', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='cost_center_list', permission='Authenticated')
@view_config(request_method='GET', route_name='cost_center_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='cost_center_id', permission='Cost Centers')
permission='Cost Centers') @view_config(request_method='GET', route_name='cost_center', permission='Cost Centers')
@view_config(request_method='GET', route_name='cost_center', renderer='brewman:templates/angular_base.mako',
permission='Cost Centers')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_cost_center', renderer='json', permission='Cost Centers') @view_config(request_method='POST', route_name='api_cost_center', renderer='json', permission='Cost Centers')
+6 -2
View File
@@ -1,3 +1,5 @@
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
from sqlalchemy import func from sqlalchemy import func
@@ -10,9 +12,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish, session_period_start, session_current_date from brewman.views.services.session import session_period_finish, session_period_start, session_current_date
@view_config(route_name='dashboard', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='dashboard', permission='Authenticated')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(route_name='api_dashboard', renderer='json') @view_config(route_name='api_dashboard', renderer='json')
+9 -9
View File
@@ -1,6 +1,7 @@
import datetime import datetime
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
@@ -15,15 +16,14 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views import to_uuid from brewman.views import to_uuid
@view_config(route_name='employee_list', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='employee_list', permission='Authenticated')
@view_config(request_method='GET', route_name='employee_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='employee_id', permission='Employees')
permission='Employees') @view_config(request_method='GET', route_name='employee', permission='Employees')
@view_config(request_method='GET', route_name='employee', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='employee_functions', permission='Employees')
permission='Employees')
@view_config(request_method='GET', route_name='employee_functions', renderer='brewman:templates/angular_base.mako',
permission='Employees')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_employee', renderer='json', permission='Employees') @view_config(request_method='POST', route_name='api_employee', renderer='json', permission='Employees')
+7 -3
View File
@@ -1,5 +1,7 @@
import datetime import datetime
import uuid import uuid
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
@@ -14,10 +16,12 @@ from brewman.models.tzinfoutc import get_age
from brewman.models.validation_exception import TryCatchFunction, ValidationError from brewman.models.validation_exception import TryCatchFunction, ValidationError
@view_config(request_method='GET', route_name='message_id', renderer='brewman:templates/angular_base.mako') @view_config(request_method='GET', route_name='message_id')
@view_config(request_method='GET', route_name='message', renderer='brewman:templates/angular_base.mako') @view_config(request_method='GET', route_name='message')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_message', renderer='json', permission='Authenticated') @view_config(request_method='POST', route_name='api_message', renderer='json', permission='Authenticated')
+73 -40
View File
@@ -1,26 +1,28 @@
from decimal import Decimal, InvalidOperation from decimal import Decimal, InvalidOperation
import uuid import uuid
from pyramid.response import Response
from pyramid.security import authenticated_userid
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
from sqlalchemy import desc
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
import transaction import transaction
from brewman import groupfinder from brewman import groupfinder
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import Product, Ledger, MenuItem
from brewman.models.master import Product, CostCenter, LedgerType, Ledger
from brewman.models.validation_exception import TryCatchFunction, ValidationError from brewman.models.validation_exception import TryCatchFunction, ValidationError
from brewman.models.voucher import Voucher, Batch, Inventory, VoucherType from brewman.models.voucher import Voucher, Batch, Inventory, VoucherType
@view_config(route_name='product_list', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='product_list', permission='Authenticated')
@view_config(request_method='GET', route_name='product_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_id', permission='Products')
permission='Products') @view_config(request_method='GET', route_name='product', permission='Products')
@view_config(request_method='GET', route_name='product', renderer='brewman:templates/angular_base.mako',
permission='Products')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_product', renderer='json', permission='Products') @view_config(request_method='POST', route_name='api_product', renderer='json', permission='Products')
@@ -36,10 +38,10 @@ def save(request):
try: try:
fraction = Decimal(json.get('Fraction', 0)) fraction = Decimal(json.get('Fraction', 0))
if fraction <= 0 or fraction > 1: if fraction <= 0:
raise ValidationError("Fraction must be a decimal > 0 and <= 1") raise ValidationError("Fraction must be a decimal > 0")
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal > 0 and <= 1") raise ValidationError("Fraction must be a decimal > 0")
fraction_units = json.get('FractionUnits', '').strip() fraction_units = json.get('FractionUnits', '').strip()
@@ -50,7 +52,6 @@ def save(request):
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Yield must be a decimal >= 0 <= 1") raise ValidationError("Yield must be a decimal >= 0 <= 1")
show_for_purchase = json.get('ShowForPurchase', True)
product_group = json.get('ProductGroup', None) product_group = json.get('ProductGroup', None)
if product_group is None: if product_group is None:
raise ValidationError('Please choose a product group') raise ValidationError('Please choose a product group')
@@ -58,12 +59,12 @@ def save(request):
try: try:
price = Decimal(json.get('Price', 0)) price = Decimal(json.get('Price', 0))
if price < 0: if price < 0:
raise ValidationError("Price must be a decimal > 0") raise ValidationError("Price must be a decimal >= 0")
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Price must be a decimal > 0") raise ValidationError("Price must be a decimal >= 0")
discontinued = json.get('Discontinued', False) is_active = json.get('IsActive', True)
item = Product(0, name, units, fraction, fraction_units, product_yield, show_for_purchase, product_group_id, item = Product(0, name, units, fraction, fraction_units, product_yield, product_group_id, Ledger.all_purchases(),
Ledger.all_purchases(), price, discontinued).create() price, is_active).create()
transaction.commit() transaction.commit()
return product_info(item.id) return product_info(item.id)
@@ -78,10 +79,10 @@ def update(request):
item.units = request.json_body['Units'].strip() item.units = request.json_body['Units'].strip()
try: try:
item.fraction = Decimal(request.json_body['Fraction']) item.fraction = Decimal(request.json_body['Fraction'])
if item.fraction <= 0 or item.fraction > 1: if item.fraction <= 0:
raise ValidationError("Fraction must be a decimal > 0 and <= 1") raise ValidationError("Fraction must be a decimal > 0")
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal > 0 and <= 1") raise ValidationError("Fraction must be a decimal > 0")
item.fraction_units = request.json_body['FractionUnits'] item.fraction_units = request.json_body['FractionUnits']
try: try:
@@ -91,16 +92,15 @@ def update(request):
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Yield must be a decimal >= 0 <= 1") 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.product_group_id = uuid.UUID(request.json_body['ProductGroup']['ProductGroupID'])
item.ledger_id = Ledger.all_purchases() item.ledger_id = Ledger.all_purchases()
try: try:
item.price = Decimal(request.json_body['Price']) item.price = Decimal(request.json_body['Price'])
if item.price < 0: if item.price < 0:
raise ValidationError("Price must be a decimal > 0") raise ValidationError("Price must be a decimal >= 0")
except (ValueError, InvalidOperation): except (ValueError, InvalidOperation):
raise ValidationError("Price must be a decimal > 0") raise ValidationError("Price must be a decimal >= 0")
item.discontinued = request.json_body['Discontinued'] item.is_active = request.json_body['IsActive']
transaction.commit() transaction.commit()
return product_info(item.id) return product_info(item.id)
@@ -135,12 +135,12 @@ def show_blank(request):
@view_config(request_method='GET', route_name='api_product', request_param='list', renderer='json', @view_config(request_method='GET', route_name='api_product', request_param='list', renderer='json',
permission='Authenticated') permission='Authenticated')
def show_list(request): def show_list(request):
list = Product.query().order_by(Product.discontinued).order_by(Product.product_group_id).order_by( list = Product.query().order_by(desc(Product.is_active)).order_by(Product.product_group_id).order_by(
Product.name).all() Product.name).all()
products = [] products = []
for item in list: for item in list:
products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'Price': item.price, products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'Price': item.price,
'ProductGroup': item.product_group.name, 'Discontinued': item.discontinued, 'ProductGroup': item.product_group.name, 'IsActive': item.is_active,
'IsFixture': item.is_fixture, 'Url': request.route_url('product_id', id=item.id)}) 'IsFixture': item.is_fixture, 'Url': request.route_url('product_id', id=item.id)})
return products return products
@@ -149,30 +149,63 @@ def show_list(request):
permission='Authenticated') permission='Authenticated')
def show_term(request): def show_term(request):
term = request.GET.get('term', None) term = request.GET.get('term', None)
term = term if term is not None and term is not '' else None term = term.strip() if term is not None and term.strip() is not '' else None
active = request.GET.get('a', None) active = request.GET.get('a', None)
active = active if active is not None else None active = active if active is not None else None
count = request.GET.get('count', None) count = request.GET.get('count', None)
count = None if count is None or count == '' else int(count) count = None if count is None or count == '' else int(count)
list = [] extended = request.GET.get('e', False)
for index, item in enumerate(Product.list(term, active)): products_type = request.GET.get('t', 'P') # P = Products / S = + Semi / M = + Menu Items
list.append({'ProductID': item.id, 'Name': item.full_name, 'Price': item.price})
if count is not None and index == count - 1: if products_type not in ('P', 'S', 'M'):
break products_type = 'P'
return list
def add_list(query):
local_results = []
for index, item in enumerate(query):
if extended:
product = {'ProductID': item.id, 'Name': item.full_name, 'Price': item.price, 'Units': item.units,
'Fraction': item.fraction, 'FractionUnits': item.fraction_units,
'ProductYield': item.product_yield}
else:
product = {'ProductID': item.id, 'Name': item.full_name, 'Price': item.price}
local_results.append(product)
if count is not None and index == count - 1:
break
return local_results
result_list = []
if products_type == 'S' or products_type == 'M':
query = DBSession.query(MenuItem)
if active is not None:
query = query.filter(MenuItem.is_active == active)
if products_type == 'S':
query = query.filter(MenuItem.is_semi == True)
for item in term.split():
if item.strip() != '':
query = query.filter(MenuItem.name.ilike('%' + item + '%'))
result_list += add_list(query)
query = DBSession.query(Product)
if active is not None:
query = query.filter(Product.is_active == active)
for item in term.split():
if item.strip() != '':
query = query.filter(Product.name.ilike('%' + item + '%'))
result_list += add_list(query)
return sorted(result_list, key=lambda k: k['Name'])
def product_info(id): def product_info(id):
if id is None: if id is None:
product = {'Code': '(Auto)', 'Type': LedgerType.by_name('Creditors').id, 'IsActive': True, product = {'Code': '(Auto)', 'IsActive': True}
'CostCenter': CostCenter.overall(), 'ShowForPurchase': True, 'Discontinued': False}
else: else:
product = Product.by_id(id) product = Product.by_id(id)
product = {'ProductID': product.id, 'Code': product.code, 'Name': product.name, 'Units': product.units, product = {'ProductID': product.id, 'Code': product.code, 'Name': product.name, 'Units': product.units,
'Fraction': product.fraction, 'FractionUnits': product.fraction_units, 'Fraction': product.fraction, 'FractionUnits': product.fraction_units,
'ProductYield': product.product_yield, 'ShowForPurchase': product.show_for_purchase, 'ProductYield': product.product_yield, 'IsActive': product.is_active,
'Discontinued': product.discontinued, 'IsFixture': product.is_fixture, 'IsFixture': product.is_fixture, 'ProductGroup': {'ProductGroupID': product.product_group_id},
'ProductGroup': {'ProductGroupID': product.product_group_id},
'Ledger': {'LedgerID': product.ledger_id}, 'Price': product.price} 'Ledger': {'LedgerID': product.ledger_id}, 'Price': product.price}
return product return product
+8 -8
View File
@@ -1,5 +1,6 @@
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
@@ -9,14 +10,13 @@ from brewman.models.master import ProductGroup
from brewman.models.validation_exception import ValidationError, TryCatchFunction from brewman.models.validation_exception import ValidationError, TryCatchFunction
@view_config(route_name='product_group_list', renderer='brewman:templates/angular_base.mako', @view_config(route_name='product_group_list', permission='Authenticated')
permission='Authenticated') @view_config(request_method='GET', route_name='product_group_id', permission='Product Groups')
@view_config(request_method='GET', route_name='product_group_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_group', permission='Product Groups')
permission='Product Groups')
@view_config(request_method='GET', route_name='product_group', renderer='brewman:templates/angular_base.mako',
permission='Product Groups')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_product_group', renderer='json', permission='Product Groups') @view_config(request_method='POST', route_name='api_product_group', renderer='json', permission='Product Groups')
+240
View File
@@ -0,0 +1,240 @@
import uuid
import datetime
from decimal import Decimal, InvalidOperation
import pkg_resources
from pyramid.response import FileResponse
from pyramid.view import view_config
from sqlalchemy import desc
import transaction
from brewman.models import DBSession
from brewman.models.master import Ledger, Recipe, ProductGroup, MenuItem, ProductBase, RecipeItem
from brewman.models.validation_exception import TryCatchFunction, ValidationError
@view_config(route_name='recipe_list', permission='Recipes')
@view_config(request_method='GET', route_name='recipe_id', permission='Recipes')
@view_config(request_method='GET', route_name='recipe', permission='Recipes')
def html(request):
package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_recipe', renderer='json', permission='Recipes')
@TryCatchFunction
def save(request):
json = request.json_body
name = json.get('Name', '').strip()
if name == '':
raise ValidationError('Name cannot be blank')
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")
try:
date = datetime.datetime.strptime(request.json_body['Date'], '%d-%b-%Y')
except (ValueError, KeyError, TypeError):
raise ValidationError("Date is not a valid date")
is_semi = json.get('IsSemi', False)
if not is_semi:
try:
sale_price = Decimal(json.get('SalePrice', 0))
if sale_price < 0:
raise ValidationError("Sale Price must be a decimal >= 0")
except (ValueError, InvalidOperation):
raise ValidationError("Sale Price must be a decimal >= 0")
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'])
units = 'Portion'
fraction = 1
fraction_units = 'Portion'
else:
sale_price = 0
product_group_id = ProductGroup.semi()
units = json.get('Units', '').strip()
try:
fraction = Decimal(json.get('Fraction', 0))
if fraction <= 0:
raise ValidationError("Fraction must be a decimal > 0")
except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal > 0")
fraction_units = json.get('FractionUnits', '').strip()
recipe_cost = 0
if len(json['RecipeItems']) == 0:
raise ValidationError("Recipe has no ingredients")
recipe_items = []
for item in json['RecipeItems']:
product = ProductBase.by_id(uuid.UUID(item['Product']['ProductID']))
quantity = round(Decimal(item['Quantity']), 2)
ingredient_price = round(Decimal(item['Price']), 2)
rate = ingredient_price / (product.fraction * product.product_yield)
recipe_cost += rate * quantity
recipe_items.append(RecipeItem(None, product.id, quantity, ingredient_price))
menu_item = MenuItem(0, name, units=units, is_semi=is_semi, fraction=fraction, fraction_units=fraction_units,
product_group_id=product_group_id, ledger_id=Ledger.all_purchases(),
price=recipe_cost, is_active=True).create()
recipe = Recipe(date=date, product_id=menu_item.id, quantity=quantity, sale_price=sale_price, notes='')
recipe.product = menu_item
DBSession.add(recipe)
for item in recipe_items:
item.recipe_id = recipe.id
recipe.recipe_items.append(item)
DBSession.add(item)
transaction.commit()
return recipe_info(recipe.id)
@view_config(request_method='POST', route_name='api_recipe_id', renderer='json', permission='Recipes')
@TryCatchFunction
def update(request):
json = request.json_body
recipe = DBSession.query(Recipe).filter(Recipe.id == uuid.UUID(request.matchdict['id'])).first()
name = json.get('Name', '').strip()
if name == '':
raise ValidationError('Name cannot be blank')
if recipe.product.name != name and recipe.product.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(recipe.product.name))
try:
date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
except (ValueError, KeyError, TypeError):
raise ValidationError("Date is not a valid date")
if len(json['RecipeItems']) == 0:
raise ValidationError("Recipe has no ingredients")
if date == recipe.date:
recipe.date = date
recipe_cost = 0
try:
recipe.sale_price = Decimal(json.get('SalePrice', 0))
if recipe.sale_price < 0:
raise ValidationError("Sale Price must be a decimal >= 0")
except (ValueError, InvalidOperation):
raise ValidationError("Sale Price must be a decimal >= 0")
recipe_items = []
for item in json['RecipeItems']:
product = ProductBase.by_id(uuid.UUID(item['Product']['ProductID']))
quantity = round(Decimal(item['Quantity']), 2)
ingredient_price = round(Decimal(item['Price']), 2)
rate = ingredient_price / (product.fraction * product.product_yield)
recipe_cost += rate * quantity
recipe_items.append(RecipeItem(None, product.id, quantity, ingredient_price))
recipe.product.price = recipe_cost
recipe.recipe_items = []
for recipe_item in recipe_items:
recipe_item.recipe_id = recipe.id
recipe.recipe_items.append(recipe_item)
DBSession.add(recipe_item)
else:
recipe_cost = 0
try:
sale_price = Decimal(json.get('SalePrice', 0))
if sale_price < 0:
raise ValidationError("Sale Price must be a decimal >= 0")
except (ValueError, InvalidOperation):
raise ValidationError("Sale Price must be a decimal >= 0")
recipe_items = []
for item in json['RecipeItems']:
product = ProductBase.by_id(uuid.UUID(item['Product']['ProductID']))
quantity = round(Decimal(item['Quantity']), 2)
ingredient_price = round(Decimal(item['Price']), 2)
rate = ingredient_price / (product.fraction * product.product_yield)
recipe_cost += rate * quantity
recipe_items.append(RecipeItem(None, product.id, quantity, ingredient_price))
menu_item = recipe.product
print(menu_item.id)
recipe = Recipe(date=date, product_id=menu_item.id, quantity=1, sale_price=sale_price, notes='')
recipe.product = menu_item
DBSession.add(recipe)
for item in recipe_items:
item.recipe_id = recipe.id
recipe.recipe_items.append(item)
DBSession.add(item)
print('One')
transaction.commit()
return recipe_info(recipe.id)
@view_config(request_method='DELETE', route_name='api_recipe_id', renderer='json', permission='Recipes')
def delete(request):
recipe = DBSession.query(Recipe).filter(Recipe.id == uuid.UUID(request.matchdict['id'])).first()
if len(recipe.product.recipes) > 1:
DBSession.delete(recipe)
else:
DBSession.delete(recipe)
DBSession.delete(recipe.product)
transaction.commit()
return recipe_info(None)
@view_config(request_method='GET', route_name='api_recipe_id', renderer='json', permission='Recipes')
def show_id(request):
return recipe_info(uuid.UUID(request.matchdict['id']))
@view_config(request_method='GET', route_name='api_recipe', renderer='json', permission='Recipes')
def show_blank(request):
return recipe_info(None)
@view_config(request_method='GET', route_name='api_recipe', renderer='json', request_param='list',
permission='Authenticated')
def show_list(request):
list = DBSession.query(Recipe).order_by(Recipe.product_id).order_by(desc(Recipe.date)).all()
recipes = []
previous_product_id = None
for item in list:
cost_price = 0
current_cost_price = 0
recipe_items = []
for recipe_item in item.recipe_items:
product = recipe_item.product
cost_rate = (recipe_item.price / product.product_yield) / product.fraction
cost_price += recipe_item.quantity * cost_rate
current_cost_price += (product.price / product.product_yield) * recipe_item.quantity / product.fraction
recipe_items.append({'Name': recipe_item.product.name, 'FractionUnits': recipe_item.product.fraction_units,
'Price': cost_rate, 'Quantity': recipe_item.quantity})
costing = 0 if item.sale_price == 0 else cost_price / item.sale_price
current_costing = 0 if item.sale_price == 0 else current_cost_price / item.sale_price
recipe = {'Name': item.product.name, 'Date': item.date.strftime('%d-%b-%Y'), 'SalePrice': item.sale_price,
'CostPrice': cost_price, 'CurrentCostPrice': current_cost_price, 'Costing': costing,
'CurrentCosting': current_costing, 'IsSemi': item.product.is_semi, 'RecipeItems': recipe_items,
'IsLatest': previous_product_id != item.product.id, 'Url': request.route_url('recipe_id', id=item.id)}
recipes.append(recipe)
previous_product_id = item.product.id
return recipes
def recipe_info(id):
if id is None:
info = {'Quantity': 1, 'IsSemi': False, 'Units': 'Portion', 'Fraction': 1, 'FractionUnits': 'Portion',
'RecipeItems': []}
else:
recipe = DBSession.query(Recipe).filter(Recipe.id == id).first()
info = {'RecipeID': recipe.id, 'Name': recipe.product.name, 'Quantity': recipe.quantity,
'Date': recipe.date.strftime('%d-%b-%Y'), 'IsSemi': recipe.product.is_semi,
'Units': recipe.product.units, 'Fraction': recipe.product.fraction,
'FractionUnits': recipe.product.fraction_units, 'SalePrice': recipe.sale_price,
'ProductGroup': {'ProductGroupID': recipe.product.product_group_id},
'RecipeItems': []}
for item in recipe.recipe_items:
info['RecipeItems'].append({
'Product': {'ProductID': item.product.id, 'Name': item.product.name,
'FractionUnits': item.product.fraction_units, 'Fraction': item.product.fraction,
'ProductYield': item.product.product_yield},
'Quantity': item.quantity, 'Price': item.price})
pass
return info
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
@@ -12,12 +14,12 @@ from brewman.views.reports.profit_loss import get_accumulated_profit
from brewman.views.services.session import session_period_finish from brewman.views.services.session import session_period_finish
@view_config(request_method='GET', route_name='balance_sheet', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='balance_sheet', permission='Balance Sheet')
permission='Balance Sheet') @view_config(request_method='GET', route_name='balance_sheet_date', permission='Balance Sheet')
@view_config(request_method='GET', route_name='balance_sheet_date', renderer='brewman:templates/angular_base.mako',
permission='Balance Sheet')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_balance_sheet', renderer='json', permission='Balance Sheet') @view_config(request_method='GET', route_name='api_balance_sheet', renderer='json', permission='Balance Sheet')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm.util import aliased from sqlalchemy.orm.util import aliased
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
@@ -10,12 +12,12 @@ from brewman.models.master import LedgerBase, LedgerType
from brewman.models.voucher import Voucher, Journal from brewman.models.voucher import Voucher, Journal
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='cash_flow', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='cash_flow', permission='Cash Flow')
permission='Cash Flow') @view_config(request_method='GET', route_name='cash_flow_id', permission='Cash Flow')
@view_config(request_method='GET', route_name='cash_flow_id', renderer='brewman:templates/angular_base.mako',
permission='Cash Flow')
def get_html(request): def get_html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_cash_flow', renderer='json', permission='Cash Flow') @view_config(request_method='GET', route_name='api_cash_flow', renderer='json', permission='Cash Flow')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from pyramid.view import view_config from pyramid.view import view_config
@@ -10,12 +12,12 @@ from brewman.models.voucher import Voucher, Journal, Inventory
from brewman.views.services.session import session_period_finish from brewman.views.services.session import session_period_finish
@view_config(request_method='GET', route_name='closing_stock', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='closing_stock', permission='Closing Stock')
permission='Closing Stock') @view_config(request_method='GET', route_name='closing_stock_date', permission='Closing Stock')
@view_config(request_method='GET', route_name='closing_stock_date', renderer='brewman:templates/angular_base.mako',
permission='Closing Stock')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_closing_stock', renderer='json', permission='Closing Stock') @view_config(request_method='GET', route_name='api_closing_stock', renderer='json', permission='Closing Stock')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from pyramid.view import view_config from pyramid.view import view_config
@@ -8,10 +10,11 @@ from brewman.views.services.session import session_period_finish, session_period
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='daybook', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='daybook', permission='Daybook')
permission='Daybook')
def daybook_get(request): def daybook_get(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_daybook', renderer='json', permission='Daybook') @view_config(request_method='GET', route_name='api_daybook', renderer='json', permission='Daybook')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
import uuid import uuid
@@ -14,12 +16,12 @@ from brewman.views.services.session import session_period_start, session_period_
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='ledger_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='ledger_id', permission='Ledger')
permission='Ledger') @view_config(request_method='GET', route_name='ledger', permission='Ledger')
@view_config(request_method='GET', route_name='ledger', renderer='brewman:templates/angular_base.mako',
permission='Ledger')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_ledger', renderer='json', permission='Ledger') @view_config(request_method='GET', route_name='api_ledger', renderer='json', permission='Ledger')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
@@ -10,10 +12,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish, session_period_start from brewman.views.services.session import session_period_finish, session_period_start
@view_config(request_method='GET', route_name='net_transactions', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='net_transactions', permission='Net Transactions')
permission='Net Transactions')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_net_transactions', renderer='json', permission='Net Transactions') @view_config(request_method='GET', route_name='api_net_transactions', renderer='json', permission='Net Transactions')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
import uuid import uuid
@@ -15,12 +17,12 @@ from brewman.views.services.session import session_period_start, session_period_
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='product_ledger_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_ledger_id', permission='Product Ledger')
permission='Product Ledger') @view_config(request_method='GET', route_name='product_ledger', permission='Product Ledger')
@view_config(request_method='GET', route_name='product_ledger', renderer='brewman:templates/angular_base.mako',
permission='Product Ledger')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_product_ledger', renderer='json', permission='Product Ledger') @view_config(request_method='GET', route_name='api_product_ledger', renderer='json', permission='Product Ledger')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
@@ -11,10 +13,11 @@ from brewman.views.reports.closing_stock import get_opening_stock, get_closing_s
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='profit_loss', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='profit_loss', permission='Profit & Loss')
permission='Profit & Loss')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_profit_loss', renderer='json', permission='Profit & Loss') @view_config(request_method='GET', route_name='api_profit_loss', renderer='json', permission='Profit & Loss')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
@@ -10,10 +12,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='purchase_entries', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='purchase_entries', permission='Purchase Entries')
permission='Purchase Entries')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_purchase_entries', renderer='json', permission='Purchase Entries') @view_config(request_method='GET', route_name='api_purchase_entries', renderer='json', permission='Purchase Entries')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, desc from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
@@ -10,10 +12,11 @@ from brewman.models.voucher import Voucher, Journal, Inventory, VoucherType
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='purchases', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='purchases', permission='Purchases')
permission='Purchases')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_purchases', renderer='json', permission='Purchases') @view_config(request_method='GET', route_name='api_purchases', renderer='json', permission='Purchases')
+7 -5
View File
@@ -1,5 +1,7 @@
import datetime import datetime
import uuid import uuid
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func, case from sqlalchemy.sql.expression import func, case
from pyramid.view import view_config from pyramid.view import view_config
@@ -11,12 +13,12 @@ from brewman.models.voucher import Voucher, Journal, Inventory
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='raw_material_cost', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='raw_material_cost', permission='Raw Material Cost')
permission='Raw Material Cost') @view_config(request_method='GET', route_name='raw_material_cost_id', permission='Raw Material Cost')
@view_config(request_method='GET', route_name='raw_material_cost_id', renderer='brewman:templates/angular_base.mako',
permission='Raw Material Cost')
def get_html(request): def get_html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_raw_material_cost', renderer='json', permission='Raw Material Cost') @view_config(request_method='GET', route_name='api_raw_material_cost', renderer='json', permission='Raw Material Cost')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
import uuid import uuid
@@ -15,12 +17,12 @@ from brewman.views.services.session import session_period_start, session_period_
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='reconcile_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='reconcile_id', permission='Reconcile')
permission='Reconcile') @view_config(request_method='GET', route_name='reconcile', permission='Reconcile')
@view_config(request_method='GET', route_name='reconcile', renderer='brewman:templates/angular_base.mako',
permission='Reconcile')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_reconcile', renderer='json', permission='Reconcile') @view_config(request_method='GET', route_name='api_reconcile', renderer='json', permission='Reconcile')
+6 -3
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from pyramid.view import view_config from pyramid.view import view_config
@@ -10,10 +12,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='stock_movement', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='stock_movement', permission='Stock Movement')
permission='Stock Movement')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_stock_movement', renderer='json', permission='Stock Movement') @view_config(request_method='GET', route_name='api_stock_movement', renderer='json', permission='Stock Movement')
+7 -5
View File
@@ -1,4 +1,6 @@
import datetime import datetime
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from pyramid.view import view_config from pyramid.view import view_config
@@ -9,12 +11,12 @@ from brewman.models.master import LedgerBase
from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish from brewman.views.services.session import session_period_finish
@view_config(request_method='GET', route_name='trial_balance', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='trial_balance', permission='Trial Balance')
permission='Trial Balance') @view_config(request_method='GET', route_name='trial_balance_date', permission='Trial Balance')
@view_config(request_method='GET', route_name='trial_balance_date', renderer='brewman:templates/angular_base.mako',
permission='Trial Balance')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_trial_balance', renderer='json', permission='Trial Balance') @view_config(request_method='GET', route_name='api_trial_balance', renderer='json', permission='Trial Balance')
def report_blank(request): def report_blank(request):
+6 -3
View File
@@ -1,3 +1,5 @@
import pkg_resources
from pyramid.response import FileResponse
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from pyramid.view import view_config from pyramid.view import view_config
@@ -5,10 +7,11 @@ from pyramid.view import view_config
from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='unposted', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='unposted', permission='Post Vouchers')
permission='Post Vouchers')
def html(request): def html(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='GET', route_name='api_unposted', renderer='json', permission='Post Vouchers') @view_config(request_method='GET', route_name='api_unposted', renderer='json', permission='Post Vouchers')
+19 -30
View File
@@ -1,5 +1,6 @@
import uuid import uuid
from pyramid.response import Response import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid from pyramid.security import authenticated_userid
from pyramid.view import view_config from pyramid.view import view_config
from sqlalchemy import func from sqlalchemy import func
@@ -18,36 +19,24 @@ from .purchase import purchase_create_voucher, purchase_update_voucher
__author__ = 'tanshu' __author__ = 'tanshu'
@view_config(request_method='GET', route_name='journal_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='journal_id', permission='Journal')
permission='Journal') @view_config(request_method='GET', route_name='journal', permission='Journal')
@view_config(request_method='GET', route_name='journal', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='payment_id', permission='Payment')
permission='Journal') @view_config(request_method='GET', route_name='payment', permission='Payment')
@view_config(request_method='GET', route_name='payment_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='receipt_id', permission='Receipt')
permission='Payment') @view_config(request_method='GET', route_name='receipt', permission='Receipt')
@view_config(request_method='GET', route_name='payment', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='purchase_id', permission='Purchase')
permission='Payment') @view_config(request_method='GET', route_name='purchase', permission='Purchase')
@view_config(request_method='GET', route_name='receipt_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='purchase_return_id', permission='Purchase Return')
permission='Receipt') @view_config(request_method='GET', route_name='purchase_return', permission='Purchase Return')
@view_config(request_method='GET', route_name='receipt', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='issue_id', permission='Issue')
permission='Receipt') @view_config(request_method='GET', route_name='issue', permission='Issue')
@view_config(request_method='GET', route_name='purchase_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='salary_deduction_id', permission='Issue')
permission='Purchase') @view_config(request_method='GET', route_name='salary_deduction', permission='Issue')
@view_config(request_method='GET', route_name='purchase', renderer='brewman:templates/angular_base.mako',
permission='Purchase')
@view_config(request_method='GET', route_name='purchase_return_id', renderer='brewman:templates/angular_base.mako',
permission='Purchase Return')
@view_config(request_method='GET', route_name='purchase_return', renderer='brewman:templates/angular_base.mako',
permission='Purchase Return')
@view_config(request_method='GET', route_name='issue_id', renderer='brewman:templates/angular_base.mako',
permission='Issue')
@view_config(request_method='GET', route_name='issue', renderer='brewman:templates/angular_base.mako',
permission='Issue')
@view_config(request_method='GET', route_name='salary_deduction_id', renderer='brewman:templates/angular_base.mako',
permission='Issue')
@view_config(request_method='GET', route_name='salary_deduction', renderer='brewman:templates/angular_base.mako',
permission='Issue')
def journal_get(request): def journal_get(request):
return {} package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_voucher_id', request_param='post', renderer='json', @view_config(request_method='POST', route_name='api_voucher_id', request_param='post', renderer='json',
-1
View File
@@ -8,7 +8,6 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [ requires = [
'pyramid', 'pyramid',
'pyramid_debugtoolbar',
'waitress', 'waitress',
'transaction', 'transaction',
'zope.sqlalchemy', 'zope.sqlalchemy',