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:
1 parent
246f8465d7
commit
1448120941
48 files changed
+1094
-264
No files matched your search
+1
-1
@@ -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
@@ -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
|
||||||
|
```
|
||||||
@@ -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
@@ -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)
|
||||||
@@ -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
@@ -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
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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
@@ -130,6 +130,10 @@ overlord_directive.directive('keypress', [function () {
|
|||||||
});
|
});
|
||||||
})(k);
|
})(k);
|
||||||
}
|
}
|
||||||
|
element.on('$destroy', function() {
|
||||||
|
$interval.cancel(timeoutId);
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|||||||
+7
@@ -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'}, {
|
||||||
|
|||||||
@@ -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}).
|
||||||
|
|||||||
@@ -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});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}]
|
||||||
|
};
|
||||||
@@ -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')
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Reference in new issue
Block a user