diff --git a/brewman/__init__.py b/brewman/__init__.py index e2c5f991..82802754 100644 --- a/brewman/__init__.py +++ b/brewman/__init__.py @@ -1,13 +1,8 @@ import os from pyramid.config import Configurator -from sqlalchemy import engine_from_config -from pyramid.authentication import AuthTktAuthenticationPolicy -from pyramid.authorization import ACLAuthorizationPolicy from pyramid.session import SignedCookieSessionFactory -from brewman.models import initialize_sql from brewman.renderers import json_renderer, CSVRenderer -from brewman.security import groupfinder from brewman.transactional_view_deriver import transactional_view @@ -21,24 +16,18 @@ def main(global_config, **settings): DB_URI = 'postgresql://{0}:{1}@postgres:5432/{2}'.format( DB_USER, DB_PASS, DB_NAME ) - settings['sqlalchemy.url']= DB_URI - engine = engine_from_config(settings, 'sqlalchemy.') - initialize_sql(engine) SECRET_KEY = os.environ.get('SECRET_KEY', settings.get('secret_key', '')) session_factory = SignedCookieSessionFactory(SECRET_KEY) - authentication_policy = AuthTktAuthenticationPolicy('brewman', timeout=900, reissue_time=90, callback=groupfinder) - authorization_policy = ACLAuthorizationPolicy() config = Configurator( settings=settings, - root_factory='brewman.factories.RootFactory', - authentication_policy=authentication_policy, - authorization_policy=authorization_policy, session_factory=session_factory ) + config.include('.security') + config.include('.models') config.include('.routes') config.add_view_deriver(transactional_view) config.add_renderer(name='json', factory=json_renderer) diff --git a/brewman/factories.py b/brewman/factories.py deleted file mode 100644 index 5aca57b6..00000000 --- a/brewman/factories.py +++ /dev/null @@ -1,31 +0,0 @@ -from pyramid.security import Everyone -from pyramid.security import Authenticated -from pyramid.security import Allow -from brewman.models.auth import Role - - -class RootFactory(object): - @property - def __acl__(self): - acl = [ - (Allow, Everyone, 'view'), - (Allow, Authenticated, 'Authenticated')] - for permission in Role.list(): - acl.append((Allow, permission.name, permission.name)) - return acl - - def __init__(self, request): - 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 \ No newline at end of file diff --git a/brewman/models/__init__.py b/brewman/models/__init__.py index 85391d39..d526f7ae 100644 --- a/brewman/models/__init__.py +++ b/brewman/models/__init__.py @@ -1,132 +1,84 @@ -from zope.sqlalchemy import ZopeTransactionExtension - -from sqlalchemy.ext.declarative import declarative_base - -from sqlalchemy.orm import scoped_session +from sqlalchemy import engine_from_config from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import configure_mappers +import zope.sqlalchemy -DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False)) -Base = declarative_base() +# import or define all models here to ensure they are attached to the +# Base.metadata prior to any initialization routines +from .voucher import Attendance, Batch, Fingerprint, Inventory, Journal, Product, SalaryDeduction, Voucher, VoucherType +from .master import (Product, + AttendanceType, + CostCentre, Employee, + Ledger, + LedgerBase, + LedgerType, + ProductGroup, + Recipe, + RecipeItem + ) +from .auth import Client, Group, Role, User, role_group, user_group, LoginHistory + +# run configure_mappers after defining all of the models to ensure +# all relationships can be setup +configure_mappers() -def initialize_sql(engine): - DBSession.configure(bind=engine) - Base.metadata.bind = engine - if not schema_exists(engine): - fixtures(engine) +def get_engine(settings, prefix='sqlalchemy.'): + return engine_from_config(settings, prefix) -def schema_exists(engine): - from brewman.models.master import DbSetting - with engine.connect() as connection: - return engine.dialect.has_table(connection, DbSetting.__tablename__) +def get_session_factory(engine): + factory = sessionmaker(expire_on_commit=False) + factory.configure(bind=engine) + return factory -def fixtures(engine): - import transaction - import uuid - from brewman.models.voucher import Attendance, Batch, Fingerprint, Inventory, Journal, Product, SalaryDeduction, Voucher, VoucherType - from brewman.models.master import Product, AttendanceType, CostCentre, Employee, Ledger, LedgerBase, LedgerType, ProductGroup, Recipe, RecipeItem - from brewman.models.auth import Client, Group, Role, User, role_group, user_group, LoginHistory +def get_tm_session(session_factory, transaction_manager): + """ + Get a ``sqlalchemy.orm.Session`` instance backed by a transaction. - Base.metadata.create_all(engine) + This function will hook the session to the transaction manager which + will take care of committing any changes. - user = User('Admin', '123456', False, uuid.UUID('8de98592-76d9-c74d-bb3f-d6184d388b5a')) - DBSession.add(user) + - When using pyramid_tm it will automatically be committed or aborted + depending on whether an exception is raised. - groups = [Group('Owner', uuid.UUID('52e08c0c-048a-784f-be10-6e129ad4b5d4')), - Group('Accountant', uuid.UUID('bc4c2d23-437a-984d-abd4-7d5fce677547')), - Group('Accounts Manager', uuid.UUID('cfc44fa7-3392-5b45-b311-5959333f568f'))] + - When using scripts you should wrap the session in a manager yourself. + For example:: - for group in groups: - DBSession.add(group) - user.groups.append(group) + import transaction - roles = [Role('Attendance', uuid.UUID('09d05434-a09a-fa45-963b-769a2e3fc667')), - Role('Trial Balance', uuid.UUID('3b099fec-ddc5-4243-b30e-afb78d9ca14a')), - Role('Cash Flow', uuid.UUID('c4d3ae29-420b-ea4c-ae90-00a356263fd9')), - Role('Cost Centres', uuid.UUID('6fcc1a20-6aec-e840-b334-1632b34aeab8')), - Role('Users', uuid.UUID('c5b7d9d7-f178-0e45-8ea4-bf4e08ec901b')), - Role('Daybook', uuid.UUID('c3edb554-a057-8942-8030-37b8e926d583')), - Role('Edit Posted Vouchers', uuid.UUID('d6675817-ddf5-bf40-9de6-fa223eb4aaa6')), - Role('Employees', uuid.UUID('e4edd0ac-7f5d-e64d-8611-73fdc4cd8ba2')), - Role('Fingerprints', uuid.UUID('d9c45323-f997-ba46-9407-8a7145f0828b')), - Role('Issue', uuid.UUID('03b602eb-f58a-b94f-af58-8cb47d7849d0')), - Role('Journal', uuid.UUID('7661388f-62ce-1c41-8e0d-0326ee5d4018')), - Role('Accounts', uuid.UUID('f438262f-72dd-2f4e-9186-5abc3af44fba')), - Role('Product Ledger', uuid.UUID('018a2408-e804-1446-90c5-b015829da6ba')), - Role('Backdated Vouchers', uuid.UUID('b67b2062-5ca7-134f-8258-5d284dd92426')), - Role('Payment', uuid.UUID('f85c0b52-c3fd-7141-8957-7a56cdc014a4')), - Role('Post Vouchers', uuid.UUID('36e741da-1a57-b047-a59e-dcd58fcf4338')), - Role('Products', uuid.UUID('74fa6d21-eebb-e14c-8153-bebc57190ab4')), - Role('Product Groups', uuid.UUID('08413a22-cf88-fd43-b2b7-365d2951d99f')), - Role('Profit & Loss', uuid.UUID('0492ebb3-76f3-204e-ab94-bbfe880f0691')), - Role('Purchase', uuid.UUID('12335acb-8630-2d41-a191-1517c8d172de')), - Role('Purchase Entries', uuid.UUID('78a6422b-aa11-174c-9dfa-412a99e87e02')), - Role('Purchase Return', uuid.UUID('ab33196e-d9e4-114c-ac8c-997954363756')), - Role('Receipt', uuid.UUID('1f1ce53e-76ff-a346-974a-65db6f606e5f')), - Role('Recipes', uuid.UUID('ffb7fb65-d42c-424d-9ff1-45069e3b4a29')), - Role('Closing Stock', uuid.UUID('97515732-24e4-c94d-9585-d4bd7f6c7891')), - Role('Ledger', uuid.UUID('a2120944-243f-3f49-be57-0ad633ce4801')), - Role('Raw Material Cost', uuid.UUID('d462842b-baf1-2343-95e5-ffdba9bbc163')), - Role('Edit Other User\'s Vouchers', uuid.UUID('a8328891-7ce2-a943-8c29-2eabc1ffeea3')), - Role('Clients', uuid.UUID('cfad44f0-f2a9-7045-89d7-9019cf0f371a')), - Role('Salary Deduction', uuid.UUID('92d70e80-1c32-384d-959e-abf84b804696')), - Role('Messages', uuid.UUID('f586d128-b6d9-4090-a913-78fcbdb68e59')), - Role('Lock Date', uuid.UUID('d52de0be-9388-4b0b-a359-7e122ab6e53a')), - Role('Net Transactions', uuid.UUID('2c40f7cf-67fc-4efa-a670-8d16a2e7884d')), - Role('Balance Sheet', uuid.UUID('40deb018-b8f2-460a-88be-8972c9fcdf04')), - Role('Advanced Delete', uuid.UUID('197ebcd2-bc4a-4b65-a138-ce942ece32ea')), - Role('Rebase', uuid.UUID('de204a88-5f9d-4579-a2d6-aa2f25efde42')), - Role('Reset Stock', uuid.UUID('aecaf82f-aa41-4634-b754-0c1308b621b1')), - Role('Reconcile', uuid.UUID('a5cb51cb-e38e-4705-84a7-cc1e9a8b866b')), - Role('Stock Movement', uuid.UUID('20b707ee-2b59-41ad-be87-76d5fe1efca8')), - Role('Purchases', uuid.UUID('cf7019c8-3fd3-45b0-9a42-601029ce5b71')), - Role('Dashboard', uuid.UUID('53eecc09-bd06-4890-b6f5-6885dda762d4')), - Role('Service Charge', uuid.UUID('99b56390-96c2-4f3d-8b0f-5ae3c868594f')), - Role('Maintenance', uuid.UUID('770532e4-21de-4712-8a6b-4ff9fd63a503'))] + engine = get_engine(settings) + session_factory = get_session_factory(engine) + with transaction.manager: + dbsession = get_tm_session(session_factory, transaction.manager) - for role in roles: - DBSession.add(role) - groups[0].roles.append(role) + """ + dbsession = session_factory() + zope.sqlalchemy.register( + dbsession, transaction_manager=transaction_manager) + return dbsession - cost_centres = [CostCentre('Overall', uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), True), - CostCentre('Purchase', uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), True), - CostCentre('Kitchen', uuid.UUID('b2d398ce-e3cc-c542-9feb-5d7783e899df'), True)] - for cost_centre in cost_centres: - DBSession.add(cost_centre) +def includeme(config): + """ + Initialize the model for a Pyramid app. - ledgers = [Ledger(1, 'All Purchases', 2, True, False, uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), - uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), True), - Ledger(1, 'Local Purchase', 9, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('d2b75912-505f-2548-9093-466dfff6a0f9'), True), - Ledger(1, 'ESI/PF - Payable', 11, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('42277912-cc18-854b-b134-9f4b00dba419'), True), - Ledger(2, 'ESI/PF - Expense', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('d2a1a286-e900-764b-a1a5-9f4b00dbb940'), True), - Ledger(1, 'Cash in Hand', 1, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('ed2341bb-80b8-9649-90db-f9aaca183bb3'), True), - Ledger(1, 'Staff Salary', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('5c2b54d0-c174-004d-a0d5-92cdaadcefa7'), True), - Ledger(2, 'Service Charges', 11, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('b7eff754-e8ba-e047-ab06-9132c15c7640'), True), - Ledger(1, 'Suspense', 4, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), - uuid.UUID('3854e317-6f3b-5142-ab26-9c44d4cddd08'), True)] + Activate this setup using ``config.include('.models')``. - for ledger in ledgers: - DBSession.add(ledger) + """ + settings = config.get_settings() - product_group = ProductGroup('Suspense', uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), True) - DBSession.add(product_group) + # use pyramid_tm to hook the transaction lifecycle to the request + config.include('pyramid_tm') - DBSession.add(ProductGroup('Semi', uuid.UUID('e6bf81b9-1e9b-499f-81d5-ab5662e9d9b1'), 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, 0, False, False, False, - uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15'), True) - DBSession.add(product) - - transaction.commit() + session_factory = get_session_factory(get_engine(settings)) + config.registry['dbsession_factory'] = session_factory + # make request.dbsession available for use in Pyramid + config.add_request_method( + # r.tm is the transaction manager used by pyramid_tm + lambda r: get_tm_session(session_factory, r.tm), + 'dbsession', + reify=True + ) diff --git a/brewman/models/auth.py b/brewman/models/auth.py index dfba95e0..64fe40be 100644 --- a/brewman/models/auth.py +++ b/brewman/models/auth.py @@ -9,8 +9,7 @@ from sqlalchemy import Column, Boolean, Unicode, Integer, DateTime, UniqueConstr from sqlalchemy.orm import synonym, relationship from brewman.models.guidtype import GUID -from brewman.models import Base -from brewman.models import DBSession +from .meta import Base def encrypt(val): @@ -38,34 +37,20 @@ class Client(Base): self.id = id @classmethod - def by_id(cls, id): - if not isinstance(id, uuid.UUID): - id = uuid.UUID(id) - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def by_code(cls, code): + def by_code(cls, code, dbsession): if code is None: return None if not isinstance(code, int): code = int(code) - return DBSession.query(cls).filter(cls.code == code).first() + return dbsession.query(cls).filter(cls.code == code).first() @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name).all() - - @classmethod - def enabled_list(cls): - return DBSession.query(cls).filter(cls.enabled == True).order_by(cls.name).all() - - @classmethod - def create(cls): + def create(cls, dbsession): client_code = random.randint(1000, 9999) otp = random.randint(1000, 9999) name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6)) client = Client(client_code, name, False, otp) - DBSession.add(client) + dbsession.add(client) return client @@ -104,7 +89,6 @@ class User(Base): password = property(_get_password, _set_password) password = synonym('_password', descriptor=password) - @property def __name__(self): return self.name @@ -116,22 +100,10 @@ class User(Base): self.id = id @classmethod - def by_name(cls, name): - if not name: - return None - return DBSession.query(cls).filter(cls.name.ilike(name)).first() - - @classmethod - def by_id(cls, id): - if not isinstance(id, uuid.UUID): - id = uuid.UUID(id) - return DBSession.query(cls).filter(cls.id == id).one() - - @classmethod - def auth(cls, name, password): + def auth(cls, name, password, dbsession): if password is None: return False, None - user = cls.by_name(name) + user = dbsession.query(User).filter(User.name.ilike(name)).first() if not user: return False, None if user.password != encrypt(password) or user.locked_out: @@ -139,25 +111,10 @@ class User(Base): else: return True, user - @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name).all() - - @classmethod - def query(cls): - return DBSession.query(cls) - - @classmethod - def filtered_list(cls, name): - query = DBSession.query(cls) - for item in name.split(): - query = query.filter(cls.name.ilike('%' + item + '%')) - return query.order_by(cls.name) - class LoginHistory(Base): __tablename__ = 'auth_login_history' - __table_args__ = (UniqueConstraint('user_id', 'client_id', 'date'), ) + __table_args__ = (UniqueConstraint('user_id', 'client_id', 'date'),) id = Column('login_history_id', GUID(), primary_key=True, default=uuid.uuid4) user_id = Column('user_id', GUID(), ForeignKey('auth_users.UserID'), nullable=False) client_id = Column('client_id', GUID(), ForeignKey('auth_clients.client_id'), nullable=False) @@ -176,15 +133,10 @@ class Group(Base): id = Column('GroupID', GUID(), primary_key=True, default=uuid.uuid4) name = Column('Name', Unicode(255), unique=True) - def __init__(self, name=None, id=None): self.name = name self.id = id - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).one() - class Role(Base): __tablename__ = 'auth_roles' @@ -197,12 +149,3 @@ class Role(Base): def __init__(self, name=None, id=None): self.name = name self.id = id - - @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name).all() - - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).one() - diff --git a/brewman/models/guidtype.py b/brewman/models/guidtype.py index cdc2e8af..73aebbcd 100644 --- a/brewman/models/guidtype.py +++ b/brewman/models/guidtype.py @@ -1,7 +1,8 @@ -from sqlalchemy.types import TypeDecorator, CHAR, Binary +import uuid from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.sqlite import BLOB -import uuid +from sqlalchemy.types import TypeDecorator, CHAR, Binary + class GUID(TypeDecorator): """Platform-independent GUID type. @@ -13,13 +14,13 @@ class GUID(TypeDecorator): impl = Binary # if dialect.value == 'postgresql': - # impl = CHAR + # impl = CHAR # elif dialect.value == 'mysql': - # impl = MSBinary + # impl = MSBinary # elif dialect.valie == 'sqlite': - # impl = Binary + # impl = Binary # else: - # impl = Binary + # impl = Binary def load_dialect_impl(self, dialect): if dialect.name == 'postgresql': @@ -34,17 +35,17 @@ class GUID(TypeDecorator): return None elif dialect.name == 'postgresql': return str(value) - elif not isinstance(value,uuid.UUID): + elif not isinstance(value, uuid.UUID): raise ValueError('value %s is not a valid uuid.UUID' % value) else: return value.bytes # if not isinstance(value, uuid.UUID): - # return "%.32x" % uuid.UUID(value) + # return "%.32x" % uuid.UUID(value) # else: - # # hexstring - # return "%.32x" % value + # # hexstring + # return "%.32x" % value - def process_result_value(self,value,dialect=None): + def process_result_value(self, value, dialect=None): if value is None: return None elif isinstance(value, bytes): @@ -53,4 +54,4 @@ class GUID(TypeDecorator): return uuid.UUID(value) def is_mutable(self): - return False \ No newline at end of file + return False diff --git a/brewman/models/master.py b/brewman/models/master.py index ddd01304..5de193fa 100644 --- a/brewman/models/master.py +++ b/brewman/models/master.py @@ -1,15 +1,24 @@ -from datetime import datetime, date +from datetime import date import uuid -from sqlalchemy import UniqueConstraint, Column, Integer, Unicode, Numeric, Boolean, ForeignKey, func, DateTime, desc, \ - PickleType, Date +from sqlalchemy import ( + UniqueConstraint, + Column, + Integer, + Unicode, + Numeric, + Boolean, + ForeignKey, + func, + DateTime, + PickleType, + Date +) from sqlalchemy.orm import relationship -from brewman.models import Base, DBSession +from .meta import Base from brewman.models.guidtype import GUID -__author__ = 'tanshu' - class Product(Base): __tablename__ = 'products' @@ -60,38 +69,13 @@ class Product(Base): def full_name(self): return "{0} ({1})".format(self.name, self.units) - @classmethod - def list(cls, name, active): - query = DBSession.query(cls) - if active is not None: - query = query.filter(cls.is_active == active) - for item in name.split(): - query = query.filter(cls.name.ilike('%' + item + '%')) - return query.order_by(cls.name) - - @classmethod - def by_name(cls, name): - return DBSession.query(cls).filter(cls.name == name).first() - - @classmethod - def by_full_name(cls, full_name): - return DBSession.query(cls).filter(cls.name + ' (' + cls.units + ')' == full_name).first() - - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def query(cls): - return DBSession.query(cls) - - def create(self): - code = DBSession.query(func.max(Product.code)).one()[0] + def create(self, dbsession): + code = dbsession.query(func.max(Product.code)).one()[0] if code is None: self.code = 1 else: self.code = code + 1 - DBSession.add(self) + dbsession.add(self) return self def can_delete(self, advanced_delete): @@ -175,14 +159,6 @@ class ProductGroup(Base): self.id = id self.is_fixture = is_fixture - @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name) - - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - @classmethod def menu_item(cls): return uuid.UUID('dad46805-f577-4e5b-8073-9b788e0173fc') @@ -211,14 +187,6 @@ class CostCentre(Base): self.id = id self.is_fixture = is_fixture - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name).all() - @classmethod def cost_centre_purchase(cls): return uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3') @@ -273,22 +241,8 @@ class LedgerBase(Base): self.is_fixture = is_fixture @classmethod - def by_id(cls, id): - if not isinstance(id, uuid.UUID): - id = uuid.UUID(id) - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def by_name(cls, name): - return DBSession.query(cls).filter(cls.name == name).first() - - @classmethod - def list(cls): - return DBSession.query(cls).all() - - @classmethod - def list(cls, type, name, reconcilable=None, active=None): - query = DBSession.query(cls) + def list(cls, type, name, reconcilable=None, active=None, dbsession=None): + query = dbsession.query(cls) if type is not None: if not isinstance(type, int): type = int(type) @@ -302,13 +256,13 @@ class LedgerBase(Base): query = query.filter(cls.name.ilike('%' + item + '%')) return query.order_by(cls.name) - def create(self): - code = DBSession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0] + def create(self, dbsession): + code = dbsession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0] if code is None: self.code = 1 else: self.code = code + 1 - DBSession.add(self) + dbsession.add(self) return self def can_delete(self, advanced_delete): @@ -320,11 +274,6 @@ class LedgerBase(Base): return False, 'Account has journal entries' return True, '' - @classmethod - def get_code(cls, type): - code = DBSession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == type).one()[0] - return 1 if code is None else code + 1 - @classmethod def all_purchases(cls): return uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490') @@ -386,28 +335,19 @@ class Employee(LedgerBase): super().__init__(code=code, name=name, type=10, is_active=is_active, is_reconcilable=False, cost_centre_id=cost_centre_id) - def create(self): - code = DBSession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0] + def create(self, dbsession): + code = dbsession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0] if code is None: self.code = 1 else: self.code = code + 1 self.name += ' (' + str(self.code) + ')' - DBSession.add(self) + dbsession.add(self) return self def can_delete(self, advanced_delete): return super(Employee, self).can_delete(advanced_delete) - @classmethod - def list(cls): - return DBSession.query(Employee).order_by(desc(Employee.is_active)).order_by(Ledger.cost_centre_id).order_by( - Employee.designation).order_by(Employee.name).all() - - @classmethod - def by_code(cls, code): - return DBSession.query(cls).filter(cls.code == code).first() - class Ledger(LedgerBase): __mapper_args__ = {'polymorphic_identity': ''} @@ -417,10 +357,6 @@ class Ledger(LedgerBase): return False, 'Account has products' return super(Ledger, self).can_delete(advanced_delete) - @classmethod - def list(cls): - return DBSession.query(Ledger).order_by(Ledger.type).order_by(Ledger.name).order_by(Ledger.code).all() - class AttendanceType: def __init__(self, id, name, value=None): @@ -430,19 +366,11 @@ class AttendanceType: @classmethod def list(cls): - list = [] - list.append(AttendanceType(0, 'Not Set', 0)) - list.append(AttendanceType(1, 'Present', 1)) - list.append(AttendanceType(2, 'Off Day', 1)) - list.append(AttendanceType(3, 'On Leave', 0)) - list.append(AttendanceType(4, 'Absent', 0)) - list.append(AttendanceType(5, 'Half Day', .5)) - list.append(AttendanceType(6, 'Double Duty', 2)) - list.append(AttendanceType(7, 'Paid Leave Availed', 1)) - list.append(AttendanceType(8, 'Casual Leave Availed', 1)) - list.append(AttendanceType(9, 'Compensatory Off', 1)) - list.append(AttendanceType(10, 'Half Day + PL', 1)) - list.append(AttendanceType(11, 'Half Day + CL', 1)) + list = [AttendanceType(0, 'Not Set', 0), AttendanceType(1, 'Present', 1), AttendanceType(2, 'Off Day', 1), + AttendanceType(3, 'On Leave', 0), AttendanceType(4, 'Absent', 0), AttendanceType(5, 'Half Day', .5), + AttendanceType(6, 'Double Duty', 2), AttendanceType(7, 'Paid Leave Availed', 1), + AttendanceType(8, 'Casual Leave Availed', 1), AttendanceType(9, 'Compensatory Off', 1), + AttendanceType(10, 'Half Day + PL', 1), AttendanceType(11, 'Half Day + CL', 1)] return list @classmethod @@ -472,19 +400,18 @@ class LedgerType: @classmethod def list(cls): - list = [] - list.append(LedgerType(1, 'Cash', True, True, True, 10, True)) - list.append(LedgerType(2, 'Purchase', False, True, True, 20, True)) - list.append(LedgerType(3, 'Sale', False, False, True, 10, True)) - list.append(LedgerType(4, 'Assets', True, True, False, 20, True)) - list.append(LedgerType(5, 'Capital', True, False, False, 70, True)) - list.append(LedgerType(6, 'Debtors', True, True, True, 30, True)) - list.append(LedgerType(7, 'Expenses', False, True, True, 40, True)) + list = [LedgerType(1, 'Cash', True, True, True, 10, True), + LedgerType(2, 'Purchase', False, True, True, 20, True), + LedgerType(3, 'Sale', False, False, True, 10, True), + LedgerType(4, 'Assets', True, True, False, 20, True), + LedgerType(5, 'Capital', True, False, False, 70, True), + LedgerType(6, 'Debtors', True, True, True, 30, True), + LedgerType(7, 'Expenses', False, True, True, 40, True), + LedgerType(9, 'Creditors', True, False, True, 60, True), + LedgerType(10, 'Salary', True, True, True, 40, False), + LedgerType(11, 'Liabilities', True, False, True, 50, True), + LedgerType(12, 'Revenue', False, False, True, 30, True)] # list.append(LedgerType(8, 'Discount', False, False, True, 30, True)) - list.append(LedgerType(9, 'Creditors', True, False, True, 60, True)) - list.append(LedgerType(10, 'Salary', True, True, True, 40, False)) - list.append(LedgerType(11, 'Liabilities', True, False, True, 50, True)) - list.append(LedgerType(12, 'Revenue', False, False, True, 30, True)) # list.append(LedgerType(13, 'Tax', True, False, True, 80, True)) # list.append(LedgerType(14, 'Total', False, False, False, 900, False)) # list.append(LedgerType(15, 'Net', False, False, False, 1000, False)) @@ -516,17 +443,3 @@ class DbSetting(Base): self.id = id self.name = name self.data = data - - @classmethod - def by_id(cls, id): - if not isinstance(id, uuid.UUID): - id = uuid.UUID(id) - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def by_name(cls, name): - return DBSession.query(cls).filter(cls.name == name).first() - - @classmethod - def list(cls): - return DBSession.query(cls).order_by(cls.name).all() diff --git a/brewman/models/meta.py b/brewman/models/meta.py new file mode 100644 index 00000000..0682247b --- /dev/null +++ b/brewman/models/meta.py @@ -0,0 +1,16 @@ +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.schema import MetaData + +# Recommended naming convention used by Alembic, as various different database +# providers will autogenerate vastly different names making migrations more +# difficult. See: http://alembic.zzzcomputing.com/en/latest/naming.html +NAMING_CONVENTION = { + "ix": 'ix_%(column_0_label)s', + "uq": "uq_%(table_name)s_%(column_0_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "pk": "pk_%(table_name)s" +} + +metadata = MetaData(naming_convention=NAMING_CONVENTION) +Base = declarative_base(metadata=metadata) diff --git a/brewman/models/operations.py b/brewman/models/operations.py index 27b6ba8a..213936a7 100644 --- a/brewman/models/operations.py +++ b/brewman/models/operations.py @@ -1,7 +1,6 @@ from brewman.models.master import CostCentre from brewman.models.validation_exception import ValidationError -__author__ = 'tanshu' def validate(voucher): journals_valid(voucher) @@ -31,14 +30,14 @@ def check_batch_insert(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) if voucher.type == 3: # Issue purchase = None for item in voucher.journals: if item.cost_centre_id == CostCentre.cost_centre_purchase(): purchase = item - if purchase == None: + if purchase is None: return if purchase.debit == 1: return @@ -47,7 +46,7 @@ def check_batch_insert(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) if voucher.type == 2: # Purchase pass @@ -70,7 +69,7 @@ def issue_new(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) def issue_update(voucher): @@ -90,7 +89,7 @@ def issue_update(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) def purchase_return_new(voucher): @@ -99,7 +98,7 @@ def purchase_return_new(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) def purchase_return_update(voucher): @@ -108,7 +107,7 @@ def purchase_return_update(voucher): if batch.quantity_remaining < item.quantity: raise ValidationError( "Quantity of {0} ({1}) cannot be more than {2}".format(item.product.name, item.product.units, - batch.quantity_remaining)) + batch.quantity_remaining)) def inventory_valid(voucher): @@ -121,11 +120,11 @@ def inventory_valid(voucher): def is_distinct_inventory(inventories): found = set() for item in inventories: - itemHash = hash(item.product_id) - if itemHash in found: + item_hash = hash(item.product_id) + if item_hash in found: raise ValidationError("Duplicate inventories") else: - found.add(itemHash) + found.add(item_hash) def batch_valid(voucher): @@ -139,12 +138,12 @@ def is_date_allowed(voucher): def journals_valid(voucher): if len(voucher.journals) < 2: raise ValidationError("Not enough journals") - signedAmount = 0 + signed_amount = 0 for item in voucher.journals: if item.amount < 0: raise ValidationError("Amounts cannot be negative") - signedAmount += item.signed_amount - if not signedAmount == 0: + signed_amount += item.signed_amount + if not signed_amount == 0: raise ValidationError("Journal amounts do no match") is_distinct_journal(voucher.journals) @@ -152,9 +151,8 @@ def journals_valid(voucher): def is_distinct_journal(journals): found = set() for item in journals: - itemHash = hash(item.ledger_id) ^ hash(item.cost_centre_id) - if itemHash in found: + item_hash = hash(item.ledger_id) ^ hash(item.cost_centre_id) + if item_hash in found: raise ValidationError("Duplicate journals") else: - found.add(itemHash) - + found.add(item_hash) diff --git a/brewman/models/tzinfoutc.py b/brewman/models/tzinfoutc.py index b9445a67..ae863175 100644 --- a/brewman/models/tzinfoutc.py +++ b/brewman/models/tzinfoutc.py @@ -1,11 +1,9 @@ from datetime import timedelta, tzinfo, datetime -__author__ = 'tanshu' - - ZERO = timedelta(0) HOUR = timedelta(hours=1) + # A UTC class. class UTC(tzinfo): @@ -20,17 +18,19 @@ class UTC(tzinfo): def dst(self, dt): return ZERO + utc = UTC() -def get_age(old_date, now = None): - def isNaive(date): +def get_age(old_date, now=None): + def is_naive(date): return date.tzinfo is None or date.tzinfo.utcoffset(date) is None + if now is None: now = datetime.utcnow().replace(tzinfo=utc) - if isNaive(old_date) == isNaive(now): + if is_naive(old_date) == is_naive(now): pass - elif isNaive(old_date): + elif is_naive(old_date): old_date = old_date.replace(tzinfo=utc) else: now = now.replace(tzinfo=utc) diff --git a/brewman/models/validation_exception.py b/brewman/models/validation_exception.py index d9005aeb..2e80b403 100644 --- a/brewman/models/validation_exception.py +++ b/brewman/models/validation_exception.py @@ -1,11 +1,11 @@ class ValidationError(Exception): - def __init__(self, message, Errors=None): + def __init__(self, message, errors=None): self.message = message # Call the base class constructor with the parameters it needs Exception.__init__(self, message) # Now for your custom code... - self.Errors = Errors + self.errors = errors def __str__(self): return self.message diff --git a/brewman/models/voucher.py b/brewman/models/voucher.py index f67b2e01..20bec998 100644 --- a/brewman/models/voucher.py +++ b/brewman/models/voucher.py @@ -7,7 +7,7 @@ from sqlalchemy import Column, Integer, Boolean, Unicode, DateTime, Numeric, For from sqlalchemy.orm import relationship, synonym, backref from brewman.models.guidtype import GUID -from brewman.models import Base, DBSession +from .meta import Base from brewman.models.master import Product @@ -18,20 +18,11 @@ class VoucherType: @classmethod def list(cls): - list = [] - list.append(VoucherType(1, 'Journal')) - list.append(VoucherType(2, 'Purchase')) - list.append(VoucherType(3, 'Issue')) - list.append(VoucherType(4, 'Payment')) - list.append(VoucherType(5, 'Receipt')) - list.append(VoucherType(6, 'Purchase Return')) - list.append(VoucherType(7, 'Opening Ledgers')) - list.append(VoucherType(8, 'Opening Batches')) - list.append(VoucherType(9, 'Verification')) - list.append(VoucherType(10, 'Opening Balance')) - list.append(VoucherType(11, 'Closing Balance')) - list.append(VoucherType(12, 'Salary Deduction')) - list.append(VoucherType(13, 'Service Charge')) + list = [VoucherType(1, 'Journal'), VoucherType(2, 'Purchase'), VoucherType(3, 'Issue'), + VoucherType(4, 'Payment'), VoucherType(5, 'Receipt'), VoucherType(6, 'Purchase Return'), + VoucherType(7, 'Opening Ledgers'), VoucherType(8, 'Opening Batches'), VoucherType(9, 'Verification'), + VoucherType(10, 'Opening Balance'), VoucherType(11, 'Closing Balance'), + VoucherType(12, 'Salary Deduction'), VoucherType(13, 'Service Charge')] return list @classmethod @@ -41,7 +32,6 @@ class VoucherType: if item.name == name: return item - @classmethod def by_id(cls, id): list = cls.list() @@ -75,7 +65,6 @@ class Voucher(Base): service_charges = relationship('ServiceCharge', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False) - def _get_type(self): return self._type # for item in VoucherType.list(): @@ -108,18 +97,6 @@ class Voucher(Base): self.poster_id = poster_id self.is_reconciled = is_reconciled - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def list(cls): - return DBSession.query(cls).all() - - @classmethod - def query(cls): - return DBSession.query(cls) - class Journal(Base): __tablename__ = 'journals' @@ -147,18 +124,6 @@ class Journal(Base): self.ledger_id = ledger_id self.cost_centre_id = cost_centre_id - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def list(cls, voucher_id): - return DBSession.query(cls).filter(cls.voucher_id == voucher_id).all() - - @classmethod - def query(cls): - return DBSession.query(cls) - class SalaryDeduction(Base): __tablename__ = 'salary_deductions' @@ -213,7 +178,7 @@ class ServiceCharge(Base): class Inventory(Base): __tablename__ = 'inventories' - __table_args__ = (UniqueConstraint('VoucherID', 'BatchID'), ) + __table_args__ = (UniqueConstraint('VoucherID', 'BatchID'),) id = Column('InventoryID', GUID(), primary_key=True, default=uuid.uuid4) voucher_id = Column('VoucherID', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False, index=True) product_id = Column('ProductID', GUID(), ForeignKey('products.ProductID'), nullable=False) @@ -267,8 +232,8 @@ class Batch(Base): return self.quantity_remaining * self.rate * (1 + self.tax) * (1 - self.discount) @classmethod - def list(cls, name, include_nil, date): - query = DBSession.query(Batch).join(Batch.product) + def list(cls, name, include_nil, date, dbsession): + query = dbsession.query(Batch).join(Batch.product) if not include_nil: query = query.filter(cls.quantity_remaining > 0) if date is not None: @@ -277,11 +242,6 @@ class Batch(Base): query = query.filter(Product.name.ilike('%' + item + '%')) return query.order_by(Product.name).order_by(cls.name).all() - - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - @classmethod def suspense(cls): return uuid.UUID('a955790e-93cf-493c-a816-c7d92b127383') @@ -312,22 +272,14 @@ class Attendance(Base): self.user_id = user_id self.is_valid = is_valid if is_valid is not None else True - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def query(cls): - return DBSession.query(cls) - - def create(self): - old = DBSession.query(Attendance).filter(Attendance.date == self.date) \ + def create(self, dbsession): + old = dbsession.query(Attendance).filter(Attendance.date == self.date) \ .filter(Attendance.employee_id == self.employee_id) \ .filter(Attendance.is_valid == True).first() if old is None or old.attendance_type != self.attendance_type: if old is not None: old.is_valid = False - DBSession.add(self) + dbsession.add(self) class Fingerprint(Base): @@ -343,14 +295,6 @@ class Fingerprint(Base): self.date = date self.fingerprint_type = 0 - @classmethod - def by_id(cls, id): - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def query(cls): - return DBSession.query(cls) - class DbImage(Base): __tablename__ = 'images' @@ -368,13 +312,4 @@ class DbImage(Base): self.image = image self.thumbnail = thumbnail self.creation_date = datetime.utcnow() if creation_date is None else creation_date - - @classmethod - def by_id(cls, id): - if not isinstance(id, uuid.UUID): - id = uuid.UUID(id) - return DBSession.query(cls).filter(cls.id == id).first() - - @classmethod - def by_resource_id(cls, id, type): - return DBSession.query(cls).filter(cls.resource_id == id, cls.resource_type == type).all() + self.id = id diff --git a/brewman/renderers.py b/brewman/renderers.py index bb1537aa..3491e54d 100644 --- a/brewman/renderers.py +++ b/brewman/renderers.py @@ -6,7 +6,6 @@ import uuid from pyramid.renderers import JSON -__author__ = 'tanshu' class CSVRenderer(object): diff --git a/brewman/routes.py b/brewman/routes.py index 4c2272c1..83bdcd7a 100644 --- a/brewman/routes.py +++ b/brewman/routes.py @@ -1,5 +1,4 @@ import datetime -from brewman.factories import pluralize def includeme(config): @@ -128,5 +127,18 @@ def add_route(config, name, url, has_list=True, variable='id'): config.add_route('api_' + name, '/api' + url) +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 get_age(days): return datetime.timedelta(days=days).total_seconds() diff --git a/brewman/scripts/initializedb.py b/brewman/scripts/initializedb.py new file mode 100644 index 00000000..da699797 --- /dev/null +++ b/brewman/scripts/initializedb.py @@ -0,0 +1,171 @@ +import os +import sys +import transaction +import uuid + +from pyramid.paster import ( + get_appsettings, + setup_logging, +) + +from pyramid.scripts.common import parse_vars + +from ..models.meta import Base +from ..models import ( + get_engine, + get_session_factory, + get_tm_session, +) +from brewman.models.auth import ( + Client, + Group, + Role, + User, + role_group, + user_group, + LoginHistory +) +from brewman.models.master import ( + Product, + CostCentre, + Employee, + Ledger, + LedgerBase, + ProductGroup, + Recipe, + RecipeItem, + DbSetting +) +from brewman.models.voucher import ( + Attendance, + Batch, + Fingerprint, + Inventory, + Journal, + Product, + SalaryDeduction, + Voucher, + ServiceCharge, + DbImage +) + + +def usage(argv): + cmd = os.path.basename(argv[0]) + print('usage: %s [var=value]\n' + '(example: "%s development.ini")' % (cmd, cmd)) + sys.exit(1) + + +def main(argv=sys.argv): + if len(argv) < 2: + usage(argv) + config_uri = argv[1] + options = parse_vars(argv[2:]) + setup_logging(config_uri) + settings = get_appsettings(config_uri, options=options) + + engine = get_engine(settings) + Base.metadata.create_all(engine) + + session_factory = get_session_factory(engine) + + with transaction.manager: + dbsession = get_tm_session(session_factory, transaction.manager) + + user = User('Admin', '123456', False, uuid.UUID('8de98592-76d9-c74d-bb3f-d6184d388b5a')) + dbsession.add(user) + + groups = [Group('Owner', uuid.UUID('52e08c0c-048a-784f-be10-6e129ad4b5d4')), + Group('Accountant', uuid.UUID('bc4c2d23-437a-984d-abd4-7d5fce677547')), + Group('Accounts Manager', uuid.UUID('cfc44fa7-3392-5b45-b311-5959333f568f'))] + + for group in groups: + dbsession.add(group) + user.groups.append(group) + + roles = [Role('Attendance', uuid.UUID('09d05434-a09a-fa45-963b-769a2e3fc667')), + Role('Trial Balance', uuid.UUID('3b099fec-ddc5-4243-b30e-afb78d9ca14a')), + Role('Cash Flow', uuid.UUID('c4d3ae29-420b-ea4c-ae90-00a356263fd9')), + Role('Cost Centres', uuid.UUID('6fcc1a20-6aec-e840-b334-1632b34aeab8')), + Role('Users', uuid.UUID('c5b7d9d7-f178-0e45-8ea4-bf4e08ec901b')), + Role('Daybook', uuid.UUID('c3edb554-a057-8942-8030-37b8e926d583')), + Role('Edit Posted Vouchers', uuid.UUID('d6675817-ddf5-bf40-9de6-fa223eb4aaa6')), + Role('Employees', uuid.UUID('e4edd0ac-7f5d-e64d-8611-73fdc4cd8ba2')), + Role('Fingerprints', uuid.UUID('d9c45323-f997-ba46-9407-8a7145f0828b')), + Role('Issue', uuid.UUID('03b602eb-f58a-b94f-af58-8cb47d7849d0')), + Role('Journal', uuid.UUID('7661388f-62ce-1c41-8e0d-0326ee5d4018')), + Role('Accounts', uuid.UUID('f438262f-72dd-2f4e-9186-5abc3af44fba')), + Role('Product Ledger', uuid.UUID('018a2408-e804-1446-90c5-b015829da6ba')), + Role('Backdated Vouchers', uuid.UUID('b67b2062-5ca7-134f-8258-5d284dd92426')), + Role('Payment', uuid.UUID('f85c0b52-c3fd-7141-8957-7a56cdc014a4')), + Role('Post Vouchers', uuid.UUID('36e741da-1a57-b047-a59e-dcd58fcf4338')), + Role('Products', uuid.UUID('74fa6d21-eebb-e14c-8153-bebc57190ab4')), + Role('Product Groups', uuid.UUID('08413a22-cf88-fd43-b2b7-365d2951d99f')), + Role('Profit & Loss', uuid.UUID('0492ebb3-76f3-204e-ab94-bbfe880f0691')), + Role('Purchase', uuid.UUID('12335acb-8630-2d41-a191-1517c8d172de')), + Role('Purchase Entries', uuid.UUID('78a6422b-aa11-174c-9dfa-412a99e87e02')), + Role('Purchase Return', uuid.UUID('ab33196e-d9e4-114c-ac8c-997954363756')), + Role('Receipt', uuid.UUID('1f1ce53e-76ff-a346-974a-65db6f606e5f')), + Role('Recipes', uuid.UUID('ffb7fb65-d42c-424d-9ff1-45069e3b4a29')), + Role('Closing Stock', uuid.UUID('97515732-24e4-c94d-9585-d4bd7f6c7891')), + Role('Ledger', uuid.UUID('a2120944-243f-3f49-be57-0ad633ce4801')), + Role('Raw Material Cost', uuid.UUID('d462842b-baf1-2343-95e5-ffdba9bbc163')), + Role('Edit Other User\'s Vouchers', uuid.UUID('a8328891-7ce2-a943-8c29-2eabc1ffeea3')), + Role('Clients', uuid.UUID('cfad44f0-f2a9-7045-89d7-9019cf0f371a')), + Role('Salary Deduction', uuid.UUID('92d70e80-1c32-384d-959e-abf84b804696')), + Role('Messages', uuid.UUID('f586d128-b6d9-4090-a913-78fcbdb68e59')), + Role('Lock Date', uuid.UUID('d52de0be-9388-4b0b-a359-7e122ab6e53a')), + Role('Net Transactions', uuid.UUID('2c40f7cf-67fc-4efa-a670-8d16a2e7884d')), + Role('Balance Sheet', uuid.UUID('40deb018-b8f2-460a-88be-8972c9fcdf04')), + Role('Advanced Delete', uuid.UUID('197ebcd2-bc4a-4b65-a138-ce942ece32ea')), + Role('Rebase', uuid.UUID('de204a88-5f9d-4579-a2d6-aa2f25efde42')), + Role('Reset Stock', uuid.UUID('aecaf82f-aa41-4634-b754-0c1308b621b1')), + Role('Reconcile', uuid.UUID('a5cb51cb-e38e-4705-84a7-cc1e9a8b866b')), + Role('Stock Movement', uuid.UUID('20b707ee-2b59-41ad-be87-76d5fe1efca8')), + Role('Purchases', uuid.UUID('cf7019c8-3fd3-45b0-9a42-601029ce5b71')), + Role('Dashboard', uuid.UUID('53eecc09-bd06-4890-b6f5-6885dda762d4')), + Role('Service Charge', uuid.UUID('99b56390-96c2-4f3d-8b0f-5ae3c868594f')), + Role('Maintenance', uuid.UUID('770532e4-21de-4712-8a6b-4ff9fd63a503'))] + + for role in roles: + dbsession.add(role) + groups[0].roles.append(role) + + cost_centres = [CostCentre('Overall', uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), True), + CostCentre('Purchase', uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), True), + CostCentre('Kitchen', uuid.UUID('b2d398ce-e3cc-c542-9feb-5d7783e899df'), True)] + + for cost_centre in cost_centres: + dbsession.add(cost_centre) + + ledgers = [Ledger(1, 'All Purchases', 2, True, False, uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), + uuid.UUID('240dd899-c413-854c-a7eb-67a29d154490'), True), + Ledger(1, 'Local Purchase', 9, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('d2b75912-505f-2548-9093-466dfff6a0f9'), True), + Ledger(1, 'ESI/PF - Payable', 11, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('42277912-cc18-854b-b134-9f4b00dba419'), True), + Ledger(2, 'ESI/PF - Expense', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('d2a1a286-e900-764b-a1a5-9f4b00dbb940'), True), + Ledger(1, 'Cash in Hand', 1, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('ed2341bb-80b8-9649-90db-f9aaca183bb3'), True), + Ledger(1, 'Staff Salary', 7, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('5c2b54d0-c174-004d-a0d5-92cdaadcefa7'), True), + Ledger(2, 'Service Charges', 11, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('b7eff754-e8ba-e047-ab06-9132c15c7640'), True), + Ledger(1, 'Suspense', 4, True, False, uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), + uuid.UUID('3854e317-6f3b-5142-ab26-9c44d4cddd08'), True)] + + for ledger in ledgers: + dbsession.add(ledger) + + product_group = ProductGroup('Suspense', uuid.UUID('ae59a20c-87bb-444a-8abb-915ad5e58b83'), True) + dbsession.add(product_group) + + dbsession.add(ProductGroup('Semi', uuid.UUID('e6bf81b9-1e9b-499f-81d5-ab5662e9d9b1'), 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, 0, False, False, False, + uuid.UUID('aa79a643-9ddc-4790-ac7f-a41f9efb4c15'), True) + dbsession.add(product) diff --git a/brewman/scripts/populate.py b/brewman/scripts/populate.py deleted file mode 100644 index b3d53d39..00000000 --- a/brewman/scripts/populate.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -import sys -import transaction - -from sqlalchemy import engine_from_config - -from pyramid.paster import ( - get_appsettings, - setup_logging, - ) - -from ..models import ( - DBSession, - Base, - ) - -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) - -def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - settings = get_appsettings(config_uri) - engine = engine_from_config(settings, 'sqlalchemy.') - DBSession.configure(bind=engine) - Base.metadata.create_all(engine) diff --git a/brewman/security.py b/brewman/security.py deleted file mode 100644 index 1cf7f444..00000000 --- a/brewman/security.py +++ /dev/null @@ -1,24 +0,0 @@ -import uuid -from brewman.models.auth import User - -def groupfinder(user_id, request): - if request is not None and 'perms' in request.session: - perms = request.session['perms'] - else: - if type(user_id) == str: - user_id = uuid.UUID(user_id) - perms = [] - user = User.by_id(user_id) - for item in user.groups: - for perm in item.roles: - perms.append(perm.name) - perms = f7(perms) - if request is not None: - request.session['perms'] = perms - return perms - - -def f7(seq): - seen = set() - seen_add = seen.add - return [x for x in seq if x not in seen and not seen_add(x)] \ No newline at end of file diff --git a/brewman/security/__init__.py b/brewman/security/__init__.py new file mode 100644 index 00000000..b948155d --- /dev/null +++ b/brewman/security/__init__.py @@ -0,0 +1,39 @@ +import uuid +from pyramid.authentication import AuthTktAuthenticationPolicy +from brewman.security.permission_authorization_policy import PermissionAuthorizationPolicy +from ..models.auth import User + + +def get_user(request): + user_id = request.unauthenticated_userid + if user_id is not None: + user = request.dbsession.query(User).get(user_id) + return user + + +def groupfinder(user_id, request): + if 'perms' in request.session: + perms = request.session['perms'] + else: + perms = [] + user = request.dbsession.query(User).filter(User.id == uuid.UUID(user_id)).one() + for item in user.groups: + for perm in item.roles: + perms.append(perm.name) + perms = sorted(f7(perms)) + request.session['perms'] = perms + return perms + + +def f7(seq): + seen = set() + seen_add = seen.add + return [x for x in seq if x not in seen and not seen_add(x)] + + +def includeme(config): + authn_policy = AuthTktAuthenticationPolicy('brewman', timeout=900, reissue_time=90, callback=groupfinder) + config.set_authentication_policy(authn_policy) + config.set_authorization_policy(PermissionAuthorizationPolicy()) + config.add_request_method(get_user, 'user', reify=True) + diff --git a/brewman/security/permission_authorization_policy.py b/brewman/security/permission_authorization_policy.py new file mode 100644 index 00000000..252897b8 --- /dev/null +++ b/brewman/security/permission_authorization_policy.py @@ -0,0 +1,19 @@ +from zope.interface import implementer + +from pyramid.interfaces import IAuthorizationPolicy + + +@implementer(IAuthorizationPolicy) +class PermissionAuthorizationPolicy(object): + def permits(self, context, principals, permission): + if permission == 'Authenticated': + permission = 'system.Authenticated' + if permission == 'Everyone': + permission = 'system.Everyone' + allowed = permission in principals + return allowed + + def principals_allowed_by_permission(self, context, permission): + allowed = set() + allowed.add(permission) + return allowed diff --git a/brewman/subscribers.py b/brewman/subscribers.py index 0af8538e..b5cb2826 100644 --- a/brewman/subscribers.py +++ b/brewman/subscribers.py @@ -5,6 +5,6 @@ from brewman.models.master import DbSetting @subscriber(NewRequest) def maintenance_mode(event): - maintenance = DbSetting.by_name('Maintenance') + maintenance = event.request.dbsession.query(DbSetting).filter(DbSetting.name == 'Maintenance').first() if maintenance is not None and maintenance.data != event.request.authenticated_userid: raise HTTPServiceUnavailable diff --git a/brewman/transactional_view_deriver.py b/brewman/transactional_view_deriver.py index 75da8fc1..a976ffbd 100644 --- a/brewman/transactional_view_deriver.py +++ b/brewman/transactional_view_deriver.py @@ -3,8 +3,6 @@ from sqlalchemy.exc import OperationalError, IntegrityError, DBAPIError import transaction from brewman.models.validation_exception import ValidationError -__author__ = 'tanshu' - def transactional_view(view, info): if info.options.get('trans'): diff --git a/brewman/views/Management/__init__.py b/brewman/views/Management/__init__.py index 5e84a522..e69de29b 100644 --- a/brewman/views/Management/__init__.py +++ b/brewman/views/Management/__init__.py @@ -1 +0,0 @@ -__author__ = 'tanshu' diff --git a/brewman/views/Management/db_integrity.py b/brewman/views/Management/db_integrity.py index 5cb1e1b0..19ef62ec 100644 --- a/brewman/views/Management/db_integrity.py +++ b/brewman/views/Management/db_integrity.py @@ -1,7 +1,6 @@ from pyramid.view import view_config from sqlalchemy import func, distinct, over, desc import transaction -from brewman.models import DBSession from brewman.models.voucher import Attendance @@ -10,26 +9,26 @@ from brewman.models.voucher import Attendance def post_check_db(request): info = {} - duplicate_attendances = get_duplicate_attendances() + duplicate_attendances = get_duplicate_attendances(request.dbsession) if duplicate_attendances > 0: - fix_duplicate_attendances(duplicate_attendances) + fix_duplicate_attendances(request.dbsession) info['Duplicate Attendances Fixed'] = duplicate_attendances transaction.commit() return info -def get_duplicate_attendances(): - sub_query = DBSession.query( +def get_duplicate_attendances(dbsession): + sub_query = dbsession.query( over(distinct(func.first_value(Attendance.id)), partition_by=[Attendance.employee_id, Attendance.date]) ).filter(Attendance.is_valid == True).subquery() - query = DBSession.query(func.count(Attendance.id)). \ + query = dbsession.query(func.count(Attendance.id)). \ filter(~Attendance.id.in_(sub_query)). \ filter(Attendance.is_valid == True) return query.scalar() -def fix_duplicate_attendances(): - sub = DBSession.query(over(distinct(func.first_value(Attendance.id)), +def fix_duplicate_attendances(dbsession): + sub = dbsession.query(over(distinct(func.first_value(Attendance.id)), partition_by=[Attendance.employee_id, Attendance.date], order_by=desc(Attendance.creation_date))).filter(Attendance.is_valid == True).subquery() - DBSession.query(Attendance).filter(~Attendance.id.in_(sub)).filter(Attendance.is_valid == True).delete(False) + dbsession.query(Attendance).filter(~Attendance.id.in_(sub)).filter(Attendance.is_valid == True).delete(False) diff --git a/brewman/views/Management/rebase.py b/brewman/views/Management/rebase.py index da45b687..ee704af0 100644 --- a/brewman/views/Management/rebase.py +++ b/brewman/views/Management/rebase.py @@ -7,42 +7,39 @@ from sqlalchemy import func, and_, distinct from sqlalchemy.orm import aliased import transaction -from brewman.models import DBSession from brewman.models.master import LedgerBase, CostCentre, Ledger, Employee from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, \ Attendance, DbImage, ServiceCharge -__author__ = 'tanshu' - @view_config(request_method='POST', route_name='api_rebase', renderer='json', permission='Rebase', trans=True) def rebase(request): - # DBSession.execute('SET statement_timeout TO 300000;') # 5 minutes + # request.dbsession.execute('SET statement_timeout TO 300000;') # 5 minutes date = request.matchdict.get('date', None) date = datetime.datetime.strptime(date, '%d-%b-%Y') user_id = uuid.UUID(request.authenticated_userid) - voucher_l, accounts = opening_ledgers(date, user_id) - voucher_b, batches = opening_batches(date, user_id) - delete_data(date) - DBSession.add(voucher_l) + voucher_l, accounts = opening_ledgers(date, user_id, request.dbsession) + voucher_b, batches = opening_batches(date, user_id, request.dbsession) + delete_data(date, request.dbsession) + request.dbsession.add(voucher_l) for j in voucher_l.journals: - DBSession.add(j) - DBSession.add(voucher_b) + request.dbsession.add(j) + request.dbsession.add(voucher_b) for j in voucher_b.journals: - DBSession.add(j) + request.dbsession.add(j) for i in voucher_b.inventories: - DBSession.add(i) - cleanup_lint(date, accounts, batches) - # DBSession.execute('RESET statement_timeout;') + request.dbsession.add(i) + cleanup_lint(date, accounts, batches, request.dbsession) + # request.dbsession.execute('RESET statement_timeout;') transaction.commit() return {} -def opening_ledgers(date, user_id): +def opening_ledgers(date, user_id, dbsession): running_total = 0 accounts = [] sum_func = func.sum(Journal.signed_amount) - query = DBSession.query(LedgerBase, sum_func) \ + query = dbsession.query(LedgerBase, sum_func) \ .join(Journal, Voucher.journals).join(LedgerBase, Journal.ledger) \ .filter(Voucher.date < date).filter(Voucher.type != VoucherType.by_name('Issue').id) \ .having(sum_func != 0) \ @@ -66,11 +63,11 @@ def opening_ledgers(date, user_id): return voucher, accounts -def opening_batches(date, user_id): +def opening_batches(date, user_id, dbsession): total = 0 batches = [] sum_func = func.sum(Journal.debit * Inventory.quantity) - query = DBSession.query(Batch, sum_func) \ + query = dbsession.query(Batch, sum_func) \ .join(Journal, Voucher.journals).join(Inventory, Voucher.inventories).join(Batch, Inventory.batch) \ .filter(Voucher.date < date) \ .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ @@ -95,57 +92,76 @@ def opening_batches(date, user_id): return voucher, batches -def delete_data(date): +def delete_data(date, dbsession): sub_voucher = aliased(Voucher) - sub_query = DBSession.query(sub_voucher.id).filter(sub_voucher.date < date).subquery() + sub_query = dbsession.query(sub_voucher.id).filter(sub_voucher.date < date).subquery() - Inventory.__table__.delete(Inventory.voucher_id.in_(sub_query)).execute() - SalaryDeduction.__table__.delete(SalaryDeduction.voucher_id.in_(sub_query)).execute() - ServiceCharge.__table__.delete(ServiceCharge.voucher_id.in_(sub_query)).execute() - Journal.__table__.delete(Journal.voucher_id.in_(sub_query)).execute() - DbImage.__table__.delete(and_(DbImage.resource_type == 'voucher', DbImage.resource_id.in_(sub_query))).execute() - Voucher.__table__.delete(Voucher.date < date).execute() + dbsession.execute( + Inventory.__table__.delete(Inventory.voucher_id.in_(sub_query)) + ) + dbsession.execute( + SalaryDeduction.__table__.delete(SalaryDeduction.voucher_id.in_(sub_query)) + ) + dbsession.execute( + ServiceCharge.__table__.delete(ServiceCharge.voucher_id.in_(sub_query)) + ) + dbsession.execute( + Journal.__table__.delete(Journal.voucher_id.in_(sub_query)) + ) + dbsession.execute( + DbImage.__table__.delete(and_(DbImage.resource_type == 'voucher', DbImage.resource_id.in_(sub_query))) + ) + dbsession.execute( + Voucher.__table__.delete(Voucher.date < date) + ) -def cleanup_lint(date, accounts, batches): +def cleanup_lint(date, accounts, batches, dbsession): # Insert executes on the end so keep list of batches and journals - - Batch.__table__.delete( - and_( - ~Batch.id.in_(DBSession.query(distinct(Inventory.batch_id)).subquery()), - ~Batch.id.in_(batches) + dbsession.execute( + Batch.__table__.delete( + and_( + ~Batch.id.in_(dbsession.query(distinct(Inventory.batch_id)).subquery()), + ~Batch.id.in_(batches) + ) ) - ).execute() - - Fingerprint.__table__.delete(Fingerprint.date < date).execute() - Attendance.__table__.delete(Attendance.date < date).execute() - - Employee.__table__.delete( - and_( - ~Employee.id.in_(DBSession.query(distinct(Journal.ledger_id)).subquery()), - ~Employee.id.in_(accounts), - Employee.id.in_( - DBSession.query(LedgerBase.id).filter( - LedgerBase.is_fixture == False - ).filter( - LedgerBase.is_active == False - ).subquery()), - Employee.leaving_date < date + ) + dbsession.execute( + Fingerprint.__table__.delete(Fingerprint.date < date) + ) + dbsession.execute( + Attendance.__table__.delete(Attendance.date < date) + ) + dbsession.execute( + Employee.__table__.delete( + and_( + ~Employee.id.in_(dbsession.query(distinct(Journal.ledger_id)).subquery()), + ~Employee.id.in_(accounts), + Employee.id.in_( + dbsession.query(LedgerBase.id).filter( + LedgerBase.is_fixture == False + ).filter( + LedgerBase.is_active == False + ).subquery()), + Employee.leaving_date < date + ) ) - ).execute() - - LedgerBase.__table__.delete( - and_( - ~LedgerBase.id.in_(DBSession.query(Employee.id).subquery()), - LedgerBase.ledger_type == Employee.__mapper_args__['polymorphic_identity'] + ) + dbsession.execute( + LedgerBase.__table__.delete( + and_( + ~LedgerBase.id.in_(dbsession.query(Employee.id).subquery()), + LedgerBase.ledger_type == Employee.__mapper_args__['polymorphic_identity'] + ) ) - ).execute() - - Ledger.__table__.delete( - and_( - ~Ledger.id.in_(DBSession.query(distinct(Journal.ledger_id)).subquery()), - ~Ledger.id.in_(accounts), - Ledger.is_fixture == False, - Ledger.ledger_type == Ledger.__mapper_args__['polymorphic_identity'] + ) + dbsession.execute( + Ledger.__table__.delete( + and_( + ~Ledger.id.in_(dbsession.query(distinct(Journal.ledger_id)).subquery()), + ~Ledger.id.in_(accounts), + Ledger.is_fixture == False, + Ledger.ledger_type == Ledger.__mapper_args__['polymorphic_identity'] + ) ) - ).execute() + ) diff --git a/brewman/views/Management/settings.py b/brewman/views/Management/settings.py index ecda987b..1c05e8cd 100644 --- a/brewman/views/Management/settings.py +++ b/brewman/views/Management/settings.py @@ -5,7 +5,6 @@ from pyramid.response import FileResponse from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.auth import User from brewman.models.master import DbSetting @@ -38,19 +37,19 @@ def set_lock_info(request): else: data['Finish']['Date'] = datetime.datetime.strptime(request.json_body['Finish']['Date'], '%d-%b-%Y') - lock_date = DbSetting.by_name('Lock Info') + lock_date = request.dbsession.query(DbSetting).filter(DbSetting.name == 'Lock Info').first() if lock_date is not None: lock_date.data = data else: lock_date = DbSetting(name='Lock Info', data=data) - DBSession.add(lock_date) + request.dbsession.add(lock_date) transaction.commit() return get_lock_info(request) @view_config(request_method='DELETE', route_name='api_lock_info', renderer='json', permission='Lock Date', trans=True) def clear_lock_info(request): - lock_date = DbSetting.by_name('Lock Info') + lock_date = request.dbsession.query(DbSetting).filter(DbSetting.name == 'Lock Info').first() if lock_date is not None and lock_date.data is not None: lock_date.data = None transaction.commit() @@ -59,7 +58,7 @@ def clear_lock_info(request): @view_config(request_method='GET', route_name='api_lock_info', renderer='json', permission='Authenticated') def get_lock_info(request): - data = DbSetting.by_name('Lock Info') + data = request.dbsession.query(DbSetting).filter(DbSetting.name == 'Lock Info').first() if data is None: return {'Start': {'Locked': False}, 'Finish': {'Locked': False}} data = data.data @@ -82,22 +81,22 @@ def get_lock_info(request): @view_config(request_method='GET', route_name='api_maintenance', renderer='json', permission='Authenticated') def get_maintenance(request): - data = DbSetting.by_name('Maintenance') + data = request.dbsession.query(DbSetting).filter(DbSetting.name == 'Maintenance').first() if data is None: return {'Enabled': False, 'User': ''} - user = User.by_id(data.data) + user = request.dbsession.query(User).filter(User.id == data.data).one() return {'Enabled': True, 'User': user.name} @view_config(request_method='POST', route_name='api_maintenance', renderer='json', permission='Maintenance', trans=True) def set_maintenance(request): status = request.json_body['Enabled'] - maintenance = DbSetting.by_name('Maintenance') + maintenance = request.dbsession.query(DbSetting).filter(DbSetting.name == 'Maintenance').first() if status is False and maintenance is not None: - DBSession.delete(maintenance) + request.dbsession.delete(maintenance) elif status is True and maintenance is None: maintenance = DbSetting(name='Maintenance', data=request.authenticated_userid) - DBSession.add(maintenance) + request.dbsession.add(maintenance) elif status is True and maintenance.data != request.authenticated_userid: maintenance.data = request.authenticated_userid transaction.commit() diff --git a/brewman/views/Management/stock.py b/brewman/views/Management/stock.py index bfdd620a..f3cd632e 100644 --- a/brewman/views/Management/stock.py +++ b/brewman/views/Management/stock.py @@ -6,19 +6,15 @@ from pyramid.view import view_config from sqlalchemy import func import transaction -from brewman.models import DBSession from brewman.models.master import LedgerBase, CostCentre, Product from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory -__author__ = 'tanshu' - - @view_config(request_method='POST', route_name='api_reset_stock', renderer='json', permission='Reset Stock', trans=True) def rebase(request): user_id = uuid.UUID(request.authenticated_userid) - product = Product.by_id(uuid.UUID(request.matchdict['id'])) + product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(request.matchdict['id'])).first() quantity = round(Decimal(request.GET['Quantity']), 2) stock_date = datetime.datetime.strptime(request.GET['StockDate'], '%d-%b-%Y') @@ -27,23 +23,23 @@ def rebase(request): if reset_date > stock_date: raise ValidationError('Reset cannot be after the stock date') - change = quantity - get_closing_stock(product, stock_date) + change = quantity - get_closing_stock(product, stock_date, dbsession=request.dbsession) if change == 0: return {'No Change Needed'} - final = get_closing_stock(product) + final = get_closing_stock(product, dbsession=request.dbsession) if final + change < 0: raise ValidationError('Current Quantity will get negative. Cannot proceed') - batch = get_last_batch(product) - set_batches(batch, final + change) + batch = get_last_batch(product, request.dbsession) + set_batches(batch, final + change, request.dbsession) - create_voucher(batch, change, reset_date, user_id) + create_voucher(batch, change, reset_date, user_id, request.dbsession) transaction.commit() return {} -def get_closing_stock(product, finish_date=None): - query = DBSession.query(func.sum(Inventory.quantity * Journal.debit)) \ +def get_closing_stock(product, finish_date=None, dbsession=None): + query = dbsession.query(func.sum(Inventory.quantity * Journal.debit)) \ .join(Voucher) \ .filter(Voucher.id == Inventory.voucher_id) \ .filter(Voucher.id == Journal.voucher_id) \ @@ -55,24 +51,24 @@ def get_closing_stock(product, finish_date=None): return 0 if query is None else query[0] -def get_last_batch(product): - batch = DBSession.query(Batch).filter(Batch.product_id == product.id).order_by(Batch.name.desc()).first() +def get_last_batch(product, dbsession): + batch = dbsession.query(Batch).filter(Batch.product_id == product.id).order_by(Batch.name.desc()).first() if batch is None: raise ValidationError('Details for the product exist. Just add a purchase entry') return batch -def set_batches(batch, quantity): +def set_batches(batch, quantity, dbsession): batch.quantity_remaining = quantity - batches = DBSession.query(Batch).filter(Batch.id != batch.id).filter(Batch.product_id == batch.product_id) + batches = dbsession.query(Batch).filter(Batch.id != batch.id).filter(Batch.product_id == batch.product_id) for item in batches: item.quantity_remaining = 0 pass -def create_voucher(batch, quantity, date, user_id): +def create_voucher(batch, quantity, date, user_id, dbsession): voucher = Voucher(date=date, narration='Product Reset', user_id=user_id, type=VoucherType.by_name('Issue')) - DBSession.add(voucher) + dbsession.add(voucher) if quantity > 0: source = CostCentre.cost_centre_overall() @@ -84,12 +80,12 @@ def create_voucher(batch, quantity, date, user_id): inventory = Inventory(product_id=batch.product.id, quantity=abs(quantity), rate=batch.rate, tax=batch.tax, discount=batch.discount, batch=batch) voucher.inventories.append(inventory) - DBSession.add(inventory) + dbsession.add(inventory) amount = round(inventory.amount, 2) source = Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_centre_id=source) voucher.journals.append(source) - DBSession.add(source) + dbsession.add(source) destination = Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_centre_id=destination) voucher.journals.append(destination) - DBSession.add(destination) + dbsession.add(destination) diff --git a/brewman/views/__init__.py b/brewman/views/__init__.py index 5d7ff43c..6bb77e0c 100644 --- a/brewman/views/__init__.py +++ b/brewman/views/__init__.py @@ -40,7 +40,7 @@ def favicon(request): @view_config(route_name='db_image') def db_image(request): - item = DbImage.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(DbImage).filter(DbImage.id == uuid.UUID(request.matchdict['id'])).first() if request.matchdict['type'] == 'thumbnail': item = BytesIO(item.thumbnail) else: @@ -50,8 +50,8 @@ def db_image(request): return response -def get_lock_info(): - data = DbSetting.by_name('Lock Info') +def get_lock_info(dbsession): + data = dbsession.query(DbSetting).filter(DbSetting.name == 'Lock Info').first() if data is None: return None, None @@ -76,6 +76,7 @@ def to_uuid(value): p = re.compile('^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$') return uuid.UUID(value) if p.match(value) else None + def to_decimal(value, default=0): import re _parser = re.compile(r""" # A numeric string consists of: diff --git a/brewman/views/account.py b/brewman/views/account.py index 90cefb9b..6dedea48 100644 --- a/brewman/views/account.py +++ b/brewman/views/account.py @@ -8,8 +8,6 @@ from pyramid.response import Response, FileResponse from pyramid.view import view_config from sqlalchemy.orm import joinedload_all -from brewman import groupfinder -from brewman.models import DBSession from brewman.models.master import CostCentre, Ledger, LedgerType, LedgerBase from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, Journal, VoucherType @@ -28,14 +26,14 @@ def html(request): def save(request): item = Ledger(code=0, name=request.json_body['Name'], type=int(request.json_body['Type']), is_active=request.json_body['IsActive'], is_reconcilable=request.json_body['IsReconcilable'], - cost_centre_id=uuid.UUID(request.json_body['CostCentre']['CostCentreID'])).create() + cost_centre_id=uuid.UUID(request.json_body['CostCentre']['CostCentreID'])).create(request.dbsession) transaction.commit() - return account_info(item.id) + return account_info(item.id, request.dbsession) @view_config(request_method='POST', route_name='api_account_id', renderer='json', permission='Accounts', trans=True) def update(request): - item = Ledger.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(Ledger).filter(Ledger.id == uuid.UUID(request.matchdict['id'])).first() if item.is_fixture: raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name)) new_type = int(request.json_body['Type']) @@ -47,17 +45,17 @@ def update(request): item.is_reconcilable = request.json_body['IsReconcilable'] item.cost_centre_id = uuid.UUID(request.json_body['CostCentre']['CostCentreID']) transaction.commit() - return account_info(item.id) + return account_info(item.id, request.dbsession) @view_config(request_method='DELETE', route_name='api_account_id', renderer='json', permission='Accounts') def delete(request): - account = Ledger.by_id(uuid.UUID(request.matchdict['id'])) - can_delete, reason = account.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request)) + account = request.dbsession.query(Ledger).filter(Ledger.id == uuid.UUID(request.matchdict['id'])).first() + can_delete, reason = account.can_delete(request.has_permission('Advanced Delete')) if can_delete: - delete_with_data(account) + delete_with_data(account, request.dbsession) transaction.commit() - return account_info(None) + return account_info(None, request.dbsession) else: transaction.abort() response = Response("Cannot delete account because {0}".format(reason)) @@ -71,11 +69,11 @@ def show_balance(request): date = request.GET.get('d', None) date = None if date is None or date == '' else datetime.datetime.strptime(date, '%d-%b-%Y') id = uuid.UUID(request.matchdict['id']) - return {'Date': balance(id, date), 'Total': balance(id, None)} + return {'Date': balance(id, date, request), 'Total': balance(id, None, request)} -def balance(ledger_id, date): - bal = DBSession.query(func.sum(Journal.amount * Journal.debit)).join(Journal.voucher) +def balance(ledger_id, date, request): + bal = request.dbsession.query(func.sum(Journal.amount * Journal.debit)).join(Journal.voucher) if date is not None: bal = bal.filter(Voucher.date <= date) @@ -87,18 +85,18 @@ def balance(ledger_id, date): @view_config(request_method='GET', route_name='api_account_id', renderer='json', permission='Accounts') def show_id(request): - return account_info(uuid.UUID(request.matchdict.get('id', None))) + return account_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession) @view_config(request_method='GET', route_name='api_account', renderer='json', permission='Accounts') def show_blank(request): - return account_info(None) + return account_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_account', renderer='json', request_param='list', permission='Authenticated') def show_list(request): - list = Ledger.list() + list = request.dbsession.query(Ledger).order_by(Ledger.type).order_by(Ledger.name).order_by(Ledger.code).all() ledgers = [] for item in list: ledgers.append({'Name': item.name, 'Type': item.type_object.name, 'IsActive': 'Yes' if item.is_active else 'No', @@ -122,7 +120,7 @@ def show_term(request): count = None if count is None or count == '' else int(count) list = [] - for index, item in enumerate(LedgerBase.list(type, filter, reconcilable, active)): + for index, item in enumerate(LedgerBase.list(type, filter, reconcilable, active, request.dbsession)): list.append({'LedgerID': item.id, 'Name': item.name}) if count is not None and index == count - 1: break @@ -137,12 +135,12 @@ def account_type_list(request): return account_types -def account_info(id): +def account_info(id, dbsession): if id is None: account = {'Code': '(Auto)', 'Type': LedgerType.by_name('Creditors').id, 'IsActive': True, 'IsReconcilable': False, 'CostCentre': CostCentre.overall()} else: - account = Ledger.by_id(id) + account = dbsession.query(Ledger).filter(Ledger.id == id).first() account = {'LedgerID': account.id, 'Code': account.code, 'Name': account.name, 'Type': account.type, 'IsActive': account.is_active, 'IsReconcilable': account.is_reconcilable, 'IsFixture': account.is_fixture, @@ -150,9 +148,9 @@ def account_info(id): return account -def delete_with_data(account): - suspense_ledger = Ledger.by_id(Ledger.suspense()) - query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ +def delete_with_data(account, dbsession): + suspense_ledger = dbsession.query(Ledger).filter(Ledger.id == Ledger.suspense()).first() + query = dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ .filter(Voucher.journals.any(Journal.ledger_id == account.id)) \ .all() @@ -166,16 +164,16 @@ def delete_with_data(account): else: others = True if not others: - DBSession.delete(voucher) + dbsession.delete(voucher) else: if sus_jnl is None: acc_jnl.ledger = suspense_ledger voucher.narration += '\nSuspense \u20B9{0:,.2f} is {1}'.format(acc_jnl.amount, account.name) else: amount = (sus_jnl.debit * sus_jnl.amount) + (acc_jnl.debit * acc_jnl.amount) - DBSession.delete(acc_jnl) + dbsession.delete(acc_jnl) if amount == 0: - DBSession.delete(sus_jnl) + dbsession.delete(sus_jnl) else: sus_jnl.amount = abs(amount) sus_jnl.debit = -1 if amount < 0 else 1 @@ -183,4 +181,4 @@ def delete_with_data(account): account.name) if voucher.type in (VoucherType.by_name('Payment').id, VoucherType.by_name('Receipt').id): voucher.type = VoucherType.by_name('Journal') - DBSession.delete(account) + dbsession.delete(account) diff --git a/brewman/views/attendance.py b/brewman/views/attendance.py index f4c8fec7..ea6b6461 100644 --- a/brewman/views/attendance.py +++ b/brewman/views/attendance.py @@ -7,7 +7,6 @@ from pyramid.view import view_config from sqlalchemy import or_ import transaction -from brewman.models import DBSession from brewman.models.master import AttendanceType, Employee from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Attendance @@ -15,9 +14,6 @@ from brewman.views.fingerprint import get_prints from brewman.views.services.session import session_period_start, session_period_finish, session_current_date -__author__ = 'tanshu' - - @view_config(request_method='GET', route_name='attendance_date', permission='Attendance') @view_config(request_method='GET', route_name='attendance', permission='Attendance') @view_config(request_method='GET', route_name='employee_attendance_id', permission='Attendance') @@ -45,29 +41,30 @@ def attendance_blank(request): @view_config(request_method='GET', route_name='api_attendance_date', renderer='json', permission='Attendance') def attendance_date(request): date = request.matchdict.get('date', None) - return attendance_date_report(date) + return attendance_date_report(date, request.dbsession) -def attendance_date_report(date): +def attendance_date_report(date, dbsession): report = {'Date': date, 'Body': []} date = datetime.datetime.strptime(date, '%d-%b-%Y') - employees = DBSession().query(Employee) \ + employees = dbsession.query(Employee) \ .filter(Employee.joining_date <= date) \ .filter(or_(Employee.is_active, Employee.leaving_date >= date)) \ .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() for item in employees: - att = DBSession().query(Attendance).filter(Attendance.employee_id == item.id).filter( + att = dbsession.query(Attendance).filter(Attendance.employee_id == item.id).filter( Attendance.date == date).filter(Attendance.is_valid == True).first() att = 0 if att is None else att.attendance_type - prints, hours, worked = get_prints(item.id, date) + prints, hours, worked = get_prints(item.id, date, dbsession) report['Body'].append({'id': item.id, 'Code': item.code, 'Name': item.name, 'Designation': item.designation, 'Department': item.cost_centre.name, 'AttendanceTypeID': att, 'Prints': prints, 'Hours': hours, 'Worked': worked}) return report -@view_config(request_method='POST', route_name='api_attendance_date', renderer='json', permission='Attendance', trans=True) +@view_config(request_method='POST', route_name='api_attendance_date', renderer='json', permission='Attendance', + trans=True) def save(request): user_id = uuid.UUID(request.authenticated_userid) date = request.matchdict.get('date', None) @@ -79,9 +76,9 @@ def save(request): if attendance_type != 0: attendance = Attendance(employee_id=employee_id, date=date_object, attendance_type=attendance_type, user_id=user_id) - attendance.create() + attendance.create(request.dbsession) transaction.commit() - return attendance_date_report(date) + return attendance_date_report(date, request.dbsession) @view_config(request_method='GET', route_name='api_employee_attendance', renderer='json', permission='Attendance') @@ -92,7 +89,7 @@ def employee_attendance_blank(request): @view_config(request_method='GET', route_name='api_employee_attendance_id', renderer='json', permission='Attendance') def employee_attendance_report(request): - employee = Employee.by_id(uuid.UUID(request.matchdict['id'])) + employee = request.dbsession.query(Employee).filter(Employee.id == uuid.UUID(request.matchdict['id'])).first() if employee is None: raise ValidationError('Employee id is wrong') start_date = request.GET.get('StartDate', session_period_start(request)) @@ -103,35 +100,36 @@ def employee_attendance_report(request): finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') start_date = employee.joining_date if employee.joining_date > start_date else start_date finish_date = employee.leaving_date if not employee.is_active and employee.leaving_date < finish_date else finish_date - info['Body'] = employee_attendance(employee, start_date, finish_date) + info['Body'] = employee_attendance(employee, start_date, finish_date, request.dbsession) return info -def employee_attendance(employee, start_date, finish_date): +def employee_attendance(employee, start_date, finish_date, dbsession): if not isinstance(start_date, datetime.datetime): start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') if not isinstance(finish_date, datetime.datetime): finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') list = [] for item in daterange(start_date, finish_date, inclusive=True): - att = DBSession.query(Attendance) \ + att = dbsession.query(Attendance) \ .filter(Attendance.employee_id == employee.id) \ .filter(Attendance.date == item) \ .filter(Attendance.is_valid == True) \ .first() att = 0 if att is None else att.attendance_type - prints, hours, worked = get_prints(employee.id, item) + prints, hours, worked = get_prints(employee.id, item, dbsession) list.append({'Date': item.strftime('%d-%b-%Y'), 'AttendanceTypeID': att, 'Prints': prints, 'Hours': hours, 'Worked': worked}) return list -@view_config(request_method='POST', route_name='api_employee_attendance_id', renderer='json', permission='Attendance', trans=True) +@view_config(request_method='POST', route_name='api_employee_attendance_id', renderer='json', permission='Attendance', + trans=True) def save_employee_attendance(request): start_date = None finish_date = None user_id = uuid.UUID(request.authenticated_userid) - employee = Employee.by_id(uuid.UUID(request.matchdict['id'])) + employee = request.dbsession.query(Employee).filter(Employee.id == uuid.UUID(request.matchdict['id'])).first() for item in request.json_body['Body']: if start_date is None: start_date = item['Date'] @@ -142,11 +140,11 @@ def save_employee_attendance(request): date = datetime.datetime.strptime(item['Date'], '%d-%b-%Y') attendance = Attendance(employee_id=employee.id, date=date, attendance_type=attendance_type, user_id=user_id) - attendance.create() + attendance.create(request.dbsession) transaction.commit() return {'StartDate': start_date, 'FinishDate': finish_date, 'Employee': {'LedgerID': employee.id, 'Name': employee.name}, - 'Body': employee_attendance(employee, start_date, finish_date)} + 'Body': employee_attendance(employee, start_date, finish_date, request.dbsession)} def daterange(start, stop, step=datetime.timedelta(days=1), inclusive=False): @@ -163,4 +161,4 @@ def daterange(start, stop, step=datetime.timedelta(days=1), inclusive=False): yield start start = start + step if inclusive and start == stop: - yield start \ No newline at end of file + yield start diff --git a/brewman/views/attendance_report.py b/brewman/views/attendance_report.py index f4876b83..83c0bf0a 100644 --- a/brewman/views/attendance_report.py +++ b/brewman/views/attendance_report.py @@ -1,13 +1,11 @@ import datetime from pyramid.view import view_config from sqlalchemy import or_ -from ..models import DBSession from ..models.master import AttendanceType, Employee from ..models.voucher import Attendance from .attendance import daterange -from .services.session import session_period_start, session_period_finish +from .services.session import session_period_start, session_period_finish -__author__ = 'tanshu' @view_config(route_name='attendance_report', renderer='csv', permission='Attendance') def get_report(request): @@ -15,33 +13,33 @@ def get_report(request): finish_date = request.GET.get('FinishDate', session_period_finish(request)) start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') - header, report = attendance_record(start_date, finish_date) + header, report = attendance_record(start_date, finish_date, request.dbsession) return {'header': header, 'rows': report, 'filename': 'Attendance Record.csv'} -def attendance_record(start_date, finish_date): +def attendance_record(start_date, finish_date, dbsession): report = [] header = ["Code", "Name", "Designation", "Department", "Salary", "SC Points"] for date in daterange(start_date, finish_date, inclusive=True): header.append(date.strftime('%d-%b')) not_set = AttendanceType.by_id(0) - employees = DBSession().query(Employee)\ - .filter(Employee.joining_date <= finish_date)\ - .filter(or_(Employee.is_active, Employee.leaving_date >= start_date))\ - .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() + employees = dbsession.query(Employee) \ + .filter(Employee.joining_date <= finish_date) \ + .filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \ + .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() for employee in employees: row_display = [employee.code, employee.name, employee.designation, employee.cost_centre.name, employee.salary, employee.service_points] row_value = ['', '', '', '', employee.salary, employee.service_points] for date in daterange(start_date, finish_date, inclusive=True): - att = DBSession.query(Attendance)\ - .filter(Attendance.employee_id == employee.id)\ - .filter(Attendance.date == date)\ - .filter(Attendance.is_valid == True)\ - .first() + att = dbsession.query(Attendance) \ + .filter(Attendance.employee_id == employee.id) \ + .filter(Attendance.date == date) \ + .filter(Attendance.is_valid == True) \ + .first() att = not_set if att is None else AttendanceType.by_id(att.attendance_type) row_display.append(att.name) row_value.append(att.value) report.extend([tuple(row_display), tuple(row_value)]) - return header, report \ No newline at end of file + return header, report diff --git a/brewman/views/auth/__init__.py b/brewman/views/auth/__init__.py index 5e84a522..e69de29b 100644 --- a/brewman/views/auth/__init__.py +++ b/brewman/views/auth/__init__.py @@ -1 +0,0 @@ -__author__ = 'tanshu' diff --git a/brewman/views/auth/client.py b/brewman/views/auth/client.py index 885c794e..8781c1ec 100644 --- a/brewman/views/auth/client.py +++ b/brewman/views/auth/client.py @@ -6,7 +6,6 @@ from pyramid.view import view_config from sqlalchemy import desc import transaction -from brewman.models import DBSession from brewman.models.auth import Client, LoginHistory @@ -20,7 +19,7 @@ def html(request): @view_config(request_method='POST', route_name='api_client_id', renderer='json', permission='Clients', trans=True) def update(request): - item = Client.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(Client).filter(Client.id == uuid.UUID(request.matchdict['id'])).first() item.enabled = request.json_body['Enabled'] if item.enabled: item.otp = None @@ -37,19 +36,19 @@ def delete(request): response.status_int = 500 return response - client = Client.by_id(id) - LoginHistory.__table__.delete(LoginHistory.client_id == client.id).execute() - DBSession.delete(client) + client = request.dbsession.query(Client).filter(Client.id == uuid.UUID(id)).first() + request.dbsession.execute(LoginHistory.__table__.delete(LoginHistory.client_id == client.id)) + request.dbsession.delete(client) transaction.commit() return {} @view_config(request_method='GET', route_name='api_client', request_param='list', renderer='json', permission='Clients') def show_list(request): - list = Client.list() + list = request.dbsession.query(Client).order_by(Client.name).all() clients = [] for item in list: - last_login = DBSession.query(LoginHistory) \ + last_login = request.dbsession.query(LoginHistory) \ .filter(LoginHistory.client_id == item.id).order_by(desc(LoginHistory.date)).first() last_login = 'Never' if last_login is None else last_login.date.strftime('%d-%b-%Y %H:%M') clients.append( @@ -61,7 +60,5 @@ def show_list(request): @view_config(request_method='GET', route_name='api_client_id', renderer='json', permission='Clients') def show_id(request): - item = Client.by_id(request.matchdict['id']) + item = request.dbsession.query(Client).filter(Client.id == uuid.UUID(request.matchdict['id'])).first() return {'ClientID': item.id, 'Code': item.code, 'Name': item.name, 'Enabled': item.enabled, 'OTP': item.otp} - - diff --git a/brewman/views/auth/group.py b/brewman/views/auth/group.py index 86319c14..e3ff48a8 100644 --- a/brewman/views/auth/group.py +++ b/brewman/views/auth/group.py @@ -4,9 +4,9 @@ import pkg_resources from pyramid.response import Response, FileResponse from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.auth import Group, Role + @view_config(route_name='group_list', permission='Users') @view_config(request_method='GET', route_name='group_id', permission='Users') @view_config(request_method='GET', route_name='group', permission='Users') @@ -19,29 +19,29 @@ def html(request): @view_config(request_method='POST', route_name='api_group', renderer='json', permission='Users', trans=True) def save(request): group = Group(request.json_body['Name']) - DBSession.add(group) - add_permissions(group, request.json_body['Permissions']) + request.dbsession.add(group) + add_permissions(group, request.json_body['Permissions'], request.dbsession) transaction.commit() - return group_info(group.id) + return group_info(group.id, request.dbsession) @view_config(request_method='POST', route_name='api_group_id', renderer='json', permission='Users', trans=True) def update(request): id = request.matchdict.get('id', None) - group = Group.by_id(uuid.UUID(id)) + group = request.dbsession.query(Group).filter(Group.id == uuid.UUID(id)).one() group.name = request.json_body['Name'] - add_permissions(group, request.json_body['Permissions']) + add_permissions(group, request.json_body['Permissions'], request.dbsession) transaction.commit() - return group_info(group.id) + return group_info(group.id, request.dbsession) -def add_permissions(group, permissions): +def add_permissions(group, permissions, dbsession): for permission in permissions: id = uuid.UUID(permission['PermissionID']) gp = [p for p in group.roles if p.id == id] gp = None if len(gp) == 0 else gp[0] if permission['Enabled'] and gp is None: - group.roles.append(Role.by_id(id)) + group.roles.append(dbsession.query(Role).filter(Role.id == id).one()) elif not permission['Enabled'] and gp: group.roles.remove(gp) @@ -61,38 +61,36 @@ def delete(request): @view_config(request_method='GET', route_name='api_group_id', renderer='json', permission='Users') def show_id(request): - return group_info(uuid.UUID(request.matchdict.get('id', None))) + return group_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession) @view_config(request_method='GET', route_name='api_group', renderer='json', permission='Users') def show_blank(request): - return group_info(None) + return group_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_group', renderer='json', request_param='list', permission='Users') def show_list(request): - list = DBSession.query(Group).order_by(Group.name).all() + list = request.dbsession.query(Group).order_by(Group.name).all() groups = [] for item in list: group = {'Name': item.name, 'Permissions': [], 'Url': request.route_url('group_id', id=item.id)} - for permission in sorted(item.roles, key=lambda p:p.name): + for permission in sorted(item.roles, key=lambda p: p.name): group['Permissions'].append(permission.name) groups.append(group) return groups -def group_info(id): +def group_info(id, dbsession): if id is None: group = {'Name': '', 'Permissions': []} - for item in Role.list(): + for item in dbsession.query(Role).order_by(Role.name).all(): group['Permissions'].append({'PermissionID': item.id, 'Name': item.name, 'Enabled': False}) else: - group_object = Group.by_id(id) + group_object = dbsession.query(Group).filter(Group.id == id).one() group = {'GroupID': group_object.id, 'Name': group_object.name, 'Permissions': []} - for item in Role.list(): + for item in dbsession.query(Role).order_by(Role.name).all(): group['Permissions'].append( {'PermissionID': item.id, 'Name': item.name, 'Enabled': True if item in group_object.roles else False}) return group - - diff --git a/brewman/views/auth/user.py b/brewman/views/auth/user.py index 07ef6ff3..49427fc9 100644 --- a/brewman/views/auth/user.py +++ b/brewman/views/auth/user.py @@ -1,13 +1,11 @@ +import pkg_resources import re +import transaction import uuid -import pkg_resources from pyramid.response import Response, FileResponse from pyramid.view import view_config -import transaction -from brewman import groupfinder -from brewman.models import DBSession from brewman.models.auth import User, Group from brewman.models.validation_exception import ValidationError @@ -17,10 +15,8 @@ class UserView(object): self.request = request self.user = request.authenticated_userid self.permissions = None - self.has_permission = False if self.user is not None: - self.user = User.by_id(self.user) - self.has_permission = 'Users' in groupfinder(self.user.id, request) + self.user = request.dbsession.query(User).filter(User.id == request.authenticated_userid).one() @view_config(route_name='user_list', permission='Users') @view_config(request_method='GET', route_name='user_id', permission='Authenticated') @@ -37,7 +33,7 @@ class UserView(object): def save_user(self): user = User(self.request.json_body['Name'], self.request.json_body['Password'], self.request.json_body['LockedOut']) - DBSession.add(user) + self.request.dbsession.add(user) self.add_groups(user, self.request.json_body['Groups']) transaction.commit() return self.user_info(user.id) @@ -48,15 +44,15 @@ class UserView(object): id = self.request.matchdict['id'] p = re.compile('^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$') if p.match(id): - user = User.by_id(uuid.UUID(id)) + user = self.request.dbsession.query(User).filter(User.id == uuid.UUID(id)).one() else: - user = User.by_name(id) + user = self.request.dbsession.query(User).filter(User.name.ilike(id)).first() return self.update_user(user) def update_user(self, user): if user is None: raise ValidationError('User name / id not found') - if self.has_permission: + if self.request.has_permission('Users'): user.name = self.request.json_body['Name'] user.locked_out = self.request.json_body['LockedOut'] self.add_groups(user, self.request.json_body['Groups']) @@ -92,7 +88,7 @@ class UserView(object): @view_config(request_method='GET', route_name='api_user', renderer='json', request_param='list', permission='Users') def show_list(self): - list = User.list() + list = self.request.dbsession.query(User).order_by(User.name).all() users = [] for item in list: user = {'Name': item.name, 'LockedOut': item.locked_out, @@ -105,25 +101,25 @@ class UserView(object): @view_config(request_method='GET', route_name='api_user', renderer='json', request_param='names', permission='Authenticated') def show_name(self): - list = User.query().filter(User.locked_out == False).order_by(User.name).all() + list = self.request.dbsession.query(User).filter(User.locked_out == False).order_by(User.name).all() users = [{'Name': item.name} for item in list] return users def user_info(self, id): if id is None: account = {'Name': '', 'LockedOut': False, 'Groups': []} - for item in DBSession.query(Group).order_by(Group.name).all(): + for item in self.request.dbsession.query(Group).order_by(Group.name).all(): account['Groups'].append({'GroupID': item.id, 'Name': item.name, 'Enabled': False}) return account if isinstance(id, uuid.UUID): - user = User.by_id(id) + user = self.request.dbsession.query(User).filter(User.id == id).one() else: - user = User.by_name(id) + user = self.request.dbsession.query(User).filter(User.name.ilike(id)).first() - if self.has_permission: + if self.request.has_permission('Users'): account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []} - for item in DBSession.query(Group).order_by(Group.name).all(): + for item in self.request.dbsession.query(Group).order_by(Group.name).all(): account['Groups'].append( {'GroupID': item.id, 'Name': item.name, 'Enabled': True if item in user.groups else False}) elif self.user.id == user.id: @@ -140,6 +136,7 @@ class UserView(object): ug = [g for g in user.groups if g.id == id] ug = None if len(ug) == 0 else ug[0] if group['Enabled'] and ug is None: - user.groups.append(Group.by_id(id)) + group_object = self.request.dbsessioin.query(Group).filter(Group.id == id).one() + user.groups.append(group_object) elif not group['Enabled'] and ug: user.groups.remove(ug) diff --git a/brewman/views/cost_centre.py b/brewman/views/cost_centre.py index a6fa4557..c710ec4e 100644 --- a/brewman/views/cost_centre.py +++ b/brewman/views/cost_centre.py @@ -4,7 +4,6 @@ from pyramid.response import Response, FileResponse from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.master import CostCentre from brewman.models.validation_exception import ValidationError @@ -19,28 +18,29 @@ def html(request): return FileResponse(file, request=request) -@view_config(request_method='POST', route_name='api_cost_centre', renderer='json', permission='Cost Centres', trans=True) +@view_config(request_method='POST', route_name='api_cost_centre', renderer='json', permission='Cost Centres', + trans=True) def save(request): item = CostCentre(request.json_body['Name']) - DBSession.add(item) + request.dbsession.add(item) transaction.commit() - return cost_centre_info(item.id) + return cost_centre_info(item.id, request.dbsession) -@view_config(request_method='POST', route_name='api_cost_centre_id', renderer='json', permission='Cost Centres', trans=True) +@view_config(request_method='POST', route_name='api_cost_centre_id', renderer='json', permission='Cost Centres', + trans=True) def update(request): - item = CostCentre.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(CostCentre).filter(CostCentre.id == uuid.UUID(request.matchdict['id'])).first() if item.is_fixture: raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name)) item.name = request.json_body['Name'] transaction.commit() - return cost_centre_info(item.id) + return cost_centre_info(item.id, request.dbsession) @view_config(request_method='DELETE', route_name='api_cost_centre_id', renderer='json', permission='Cost Centres') def delete(request): - item = request.matchdict.get('id', None) - item = None if item is None else CostCentre.by_id(uuid.UUID(item)) + item = request.dbsession.query(CostCentre).filter(CostCentre.id == uuid.UUID(request.matchdict['id'])).first() if item is None: response = Response("Cost Centre not found") @@ -56,18 +56,18 @@ def delete(request): @view_config(request_method='GET', route_name='api_cost_centre_id', renderer='json', permission='Cost Centres') def show_id(request): - return cost_centre_info(uuid.UUID(request.matchdict.get('id', None))) + return cost_centre_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession) @view_config(request_method='GET', route_name='api_cost_centre', renderer='json', permission='Cost Centres') def show_blank(request): - return cost_centre_info(None) + return cost_centre_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_cost_centre', request_param='list', renderer='json', permission='Authenticated') def show_list(request): - list = CostCentre.list() + list = request.dbsession.query(CostCentre).order_by(CostCentre.name).all() cost_centres = [] for item in list: cost_centres.append({'CostCentreID': item.id, 'Name': item.name, 'IsFixture': item.is_fixture, @@ -75,11 +75,9 @@ def show_list(request): return cost_centres -def cost_centre_info(id): +def cost_centre_info(id, dbsession): if id is None: return {} else: - cost_centre = CostCentre.by_id(id) + cost_centre = dbsession.query(CostCentre).filter(CostCentre.id == id).first() return {'CostCentreID': cost_centre.id, 'Name': cost_centre.name, 'IsFixture': cost_centre.is_fixture} - - diff --git a/brewman/views/employee.py b/brewman/views/employee.py index 3191563b..2e75484f 100644 --- a/brewman/views/employee.py +++ b/brewman/views/employee.py @@ -1,15 +1,14 @@ import datetime -import uuid -from decimal import Decimal - import pkg_resources +import transaction +import uuid + +from decimal import Decimal from pyramid.response import Response, FileResponse from pyramid.view import view_config +from sqlalchemy import desc from sqlalchemy.orm import joinedload_all -import transaction -from brewman import groupfinder -from brewman.models import DBSession from brewman.models.master import CostCentre, Employee, LedgerBase, Ledger from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, Journal, VoucherType @@ -66,14 +65,14 @@ def save(request): raise ValidationError("Leaving Date is not a valid date") item = Employee(0, name, is_active, cost_centre_id, designation, salary, service_points, joining_date, - leaving_date).create() + leaving_date).create(request.dbsession) transaction.commit() - return employee_info(item.id) + return employee_info(item.id, request.dbsession) @view_config(request_method='POST', route_name='api_employee_id', renderer='json', permission='Employees', trans=True) def update(request): - item = Employee.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(Employee).filter(Employee.id == uuid.UUID(request.matchdict['id'])).first() if item.is_fixture: raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name)) @@ -115,17 +114,17 @@ def update(request): raise ValidationError("Leaving Date is not a valid date") transaction.commit() - return employee_info(item.id) + return employee_info(item.id, request.dbsession) @view_config(request_method='DELETE', route_name='api_employee_id', renderer='json', permission='Employees', trans=True) def delete(request): - employee = Employee.by_id(uuid.UUID(request.matchdict['id'])) - can_delete, reason = employee.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request)) + employee = request.dbsession.query(Employee).filter(Employee.id == uuid.UUID(request.matchdict['id'])).first() + can_delete, reason = employee.can_delete(request.has_permission('Advanced Delete')) if can_delete: - delete_with_data(employee) + delete_with_data(employee, request.dbsession) transaction.commit() - return employee_info(None) + return employee_info(None, request.dbsession) else: transaction.abort() response = Response("Cannot delete account because {0}".format(reason)) @@ -138,18 +137,19 @@ def show_id(request): id = to_uuid(request.matchdict['id']) if id is None: raise ValidationError("Invalid Employee") - return employee_info(id) + return employee_info(id, request.dbsession) @view_config(request_method='GET', route_name='api_employee', renderer='json', permission='Employees') def show_blank(request): - return employee_info(None) + return employee_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_employee', request_param='list', renderer='json', permission='Authenticated') def show_list(request): - list = Employee.list() + list = request.dbsession.query(Employee).order_by(desc(Employee.is_active)).order_by( + Ledger.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() ledgers = [] for item in list: ledgers.append( @@ -170,7 +170,7 @@ def show_term(request): count = None if count is None or count == '' else int(count) list = [] - for index, item in enumerate(LedgerBase.list(10, filter)): + for index, item in enumerate(LedgerBase.list(10, filter, dbsession=request.dbsession)): list.append({'LedgerID': item.id, 'Name': item.name, 'Designation': item.designation, 'CostCentre': {'CostCentreID': item.cost_centre.id, 'Name': item.cost_centre.name}}) if count is not None and index == count - 1: @@ -178,11 +178,11 @@ def show_term(request): return list -def employee_info(id): +def employee_info(id, dbsession): if id is None: employee = {'Code': '(Auto)', 'IsActive': True, 'CostCentre': CostCentre.overall()} else: - employee = Employee.by_id(id) + employee = dbsession.query(Employee).filter(Employee.id == id).first() if employee is None: raise ValidationError("Invalid Employee") employee = {'LedgerID': employee.id, 'Code': employee.code, 'Name': employee.name, @@ -193,9 +193,9 @@ def employee_info(id): return employee -def delete_with_data(employee): - suspense_ledger = Ledger.by_id(Ledger.suspense()) - query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ +def delete_with_data(employee, dbsession): + suspense_ledger = dbsession.query(Ledger).filter(Ledger.id == Ledger.suspense()).first() + query = dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ .filter(Voucher.journals.any(Journal.ledger_id == employee.id)) \ .all() @@ -209,7 +209,7 @@ def delete_with_data(employee): else: others = True if not others: - DBSession.delete(voucher) + dbsession.delete(voucher) else: if sus_jnl is None: acc_jnl.ledger = suspense_ledger @@ -217,10 +217,10 @@ def delete_with_data(employee): else: amount = (sus_jnl.debit * sus_jnl.amount) + (acc_jnl.debit * acc_jnl.amount) if acc_jnl.salary_deduction is not None: - DBSession.delete(acc_jnl.salary_deduction) - DBSession.delete(acc_jnl) + dbsession.delete(acc_jnl.salary_deduction) + dbsession.delete(acc_jnl) if amount == 0: - DBSession.delete(sus_jnl) + dbsession.delete(sus_jnl) else: sus_jnl.amount = abs(amount) sus_jnl.debit = -1 if amount < 0 else 1 @@ -229,7 +229,7 @@ def delete_with_data(employee): if voucher.type in (VoucherType.by_name('Payment').id, VoucherType.by_name('Receipt').id): voucher.type = VoucherType.by_name('Journal') for fingerprint in employee.fingerprints: - DBSession.delete(fingerprint) + dbsession.delete(fingerprint) for attendance in employee.attendances: - DBSession.delete(attendance) - DBSession.delete(employee) + dbsession.delete(attendance) + dbsession.delete(employee) diff --git a/brewman/views/fingerprint.py b/brewman/views/fingerprint.py index 6aafbd7c..69c6abf2 100644 --- a/brewman/views/fingerprint.py +++ b/brewman/views/fingerprint.py @@ -3,19 +3,18 @@ import datetime from io import StringIO from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.master import Employee from brewman.models.voucher import Fingerprint -__author__ = 'tanshu' -@view_config(request_method='POST', route_name='api_fingerprint', renderer='json', permission='Authenticated', trans=True) +@view_config(request_method='POST', route_name='api_fingerprint', renderer='json', permission='Authenticated', + trans=True) def show_list(request): filename = request.POST['uploadedFile'].filename input_file = request.POST['uploadedFile'].file reader = csv.reader(read_file(input_file), delimiter="\t") for row in reader: - add_fingerprint(row) + add_fingerprint(row, request.dbsession) transaction.commit() return filename @@ -31,27 +30,26 @@ def read_file(input_file): return StringIO(output) -def add_fingerprint(row): +def add_fingerprint(row, dbsession): try: employee_code = int(row[2]) date = datetime.datetime.strptime(row[6], '%Y/%m/%d %H:%M:%S') except ValueError: return - employee = Employee.by_code(employee_code) + employee = dbsession.query(Employee).filter(Employee.code == employee_code).first() if employee is not None: fp = Fingerprint(employee_id=employee.id, date=date) - old = DBSession.query(Fingerprint).filter(Fingerprint.date == date) \ + old = dbsession.query(Fingerprint).filter(Fingerprint.date == date) \ .filter(Fingerprint.employee_id == employee.id).first() if old is None: - DBSession.add(fp) + dbsession.add(fp) - -def get_prints(employee_id, date): +def get_prints(employee_id, date, dbsession): start_fp = date + datetime.timedelta(hours=7) finish_fp = date + datetime.timedelta(hours=7, days=1) - prints = DBSession.query(Fingerprint).filter(Fingerprint.employee_id == employee_id)\ - .filter(Fingerprint.date >= start_fp).filter(Fingerprint.date < finish_fp).order_by(Fingerprint.date).all() + prints = dbsession.query(Fingerprint).filter(Fingerprint.employee_id == employee_id) \ + .filter(Fingerprint.date >= start_fp).filter(Fingerprint.date < finish_fp).order_by(Fingerprint.date).all() last = None for i in range(len(prints), 0, -1): @@ -79,4 +77,4 @@ def working_hours(delta): minutes = int(5 * round(float(minutes) / 5)) hours = delta.seconds // 3600 worked = str(hours).zfill(2) + ':' + str(minutes).zfill(2) - return worked, delta.seconds >= 60 * 60 * 9 # 9hrs \ No newline at end of file + return worked, delta.seconds >= 60 * 60 * 9 # 9hrs diff --git a/brewman/views/product.py b/brewman/views/product.py index 6bd5c968..f81d77a5 100644 --- a/brewman/views/product.py +++ b/brewman/views/product.py @@ -1,15 +1,13 @@ -from decimal import Decimal, InvalidOperation +import pkg_resources +import transaction import uuid -import pkg_resources +from decimal import Decimal, InvalidOperation from pyramid.response import Response, FileResponse from pyramid.view import view_config from sqlalchemy import desc from sqlalchemy.orm import joinedload_all -import transaction -from brewman import groupfinder -from brewman.models import DBSession from brewman.models.master import Product, Ledger from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, Batch, Inventory, VoucherType @@ -70,14 +68,14 @@ def save(request): is_purchased = json.get('IsPurchased', True) is_sold = json.get('IsSold', True) item = Product(0, name, units, fraction, fraction_units, product_yield, product_group_id, Ledger.all_purchases(), - price, sale_price, is_active, is_purchased, is_sold).create() + price, sale_price, is_active, is_purchased, is_sold).create(request.dbsession) transaction.commit() - return product_info(item.id) + return product_info(item.id, request.dbsession) @view_config(request_method='POST', route_name='api_product_id', renderer='json', permission='Products', trans=True) def update(request): - item = Product.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(Product).filter(Product.id == uuid.UUID(request.matchdict['id'])).first() if item.is_fixture: raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.full_name)) item.name = request.json_body['Name'].strip() @@ -116,18 +114,18 @@ def update(request): item.is_purchased = request.json_body['IsPurchased'] item.is_sold = request.json_body['IsSold'] transaction.commit() - return product_info(item.id) + return product_info(item.id, request.dbsession) @view_config(request_method='DELETE', route_name='api_product_id', renderer='json', permission='Products', trans=True) def delete(request): - product = Product.by_id(uuid.UUID(request.matchdict['id'])) - can_delete, reason = product.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request)) + product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(request.matchdict['id'])).first() + can_delete, reason = product.can_delete(request.has_permission('Advanced Delete')) if can_delete: - delete_with_data(product) + delete_with_data(product, request) transaction.commit() - return product_info(None) + return product_info(None, request.dbsession) else: transaction.abort() response = Response("Cannot delete product because {0}".format(reason)) @@ -137,19 +135,19 @@ def delete(request): @view_config(request_method='GET', route_name='api_product_id', renderer='json', permission='Products') def show_id(request): - return product_info(uuid.UUID(request.matchdict.get('id', None))) + return product_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession) @view_config(request_method='GET', route_name='api_product', renderer='json', permission='Products') def show_blank(request): - return product_info(None) + return product_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_product', request_param='list', renderer='json', permission='Authenticated') def show_list(request): - list = Product.query().order_by(desc(Product.is_active)).order_by(Product.product_group_id).order_by( - Product.name).all() + list = request.dbsession.query(Product).order_by(desc(Product.is_active)).order_by( + Product.product_group_id).order_by(Product.name).all() products = [] for item in list: products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'CostPrice': item.price, @@ -189,7 +187,7 @@ def show_term(request): result_list = [] - query = DBSession.query(Product) + query = request.dbsession.query(Product) if active is not None: query = query.filter(Product.is_active == active) if is_purchased is not None: @@ -202,11 +200,11 @@ def show_term(request): return sorted(result_list, key=lambda k: k['Name']) -def product_info(id): +def product_info(id, dbsession): if id is None: product = {'Code': '(Auto)', 'IsActive': True, 'IsPurchased': True, 'IsSold': False} else: - product = Product.by_id(id) + product = dbsession.query(Product).filter(Product.id == id).first() product = {'ProductID': product.id, 'Code': product.code, 'Name': product.name, 'Units': product.units, 'Fraction': product.fraction, 'FractionUnits': product.fraction_units, 'ProductYield': product.product_yield, 'Price': product.price, 'SalePrice': product.sale_price, @@ -217,12 +215,12 @@ def product_info(id): return product -def delete_with_data(product): - suspense_product = Product.by_id(Product.suspense()) - suspense_batch = Batch.by_id(Batch.suspense()) - query = Voucher.query().options(joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True)) \ - .filter(Voucher.inventories.any(Inventory.product_id == product.id)) \ - .all() +def delete_with_data(product, request): + suspense_product = request.dbsession.query(Product).filter(Product.id == Product.suspense()).first() + suspense_batch = request.dbsession.query(Batch).filter(Batch.id == Batch.suspense()).first() + query = request.dbsession.query(Voucher).options( + joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True)).filter( + Voucher.inventories.any(Inventory.product_id == product.id)).all() for voucher in query: others, sus_inv, prod_inv = False, None, None @@ -234,7 +232,7 @@ def delete_with_data(product): else: others = True if not others and voucher.type == VoucherType.by_id('Issue'): - DBSession.delete(voucher) + request.dbsession.delete(voucher) else: if sus_inv is None: prod_inv.product = suspense_product @@ -246,8 +244,8 @@ def delete_with_data(product): voucher.narration += '\nSuspense \u20B9{0:,.2f} is {1}'.format(prod_inv.amount, product.name) else: sus_inv.quantity += prod_inv.amount - DBSession.delete(prod_inv) + request.dbsession.delete(prod_inv) voucher.narration += '\nDeleted \u20B9{0:,.2f} of {1}'.format(prod_inv.amount, product.name) for batch in product.batches: - DBSession.delete(batch) - DBSession.delete(product) + request.dbsession.delete(batch) + request.dbsession.delete(product) diff --git a/brewman/views/product_group.py b/brewman/views/product_group.py index faabfebd..925450de 100644 --- a/brewman/views/product_group.py +++ b/brewman/views/product_group.py @@ -4,7 +4,6 @@ from pyramid.response import Response, FileResponse from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.master import ProductGroup from brewman.models.validation_exception import ValidationError @@ -23,26 +22,25 @@ def html(request): trans=True) def save(request): item = ProductGroup(request.json_body['Name']) - DBSession.add(item) + request.dbsession.add(item) transaction.commit() - return product_group_info(item.id) + return product_group_info(item.id, request.dbsession) @view_config(request_method='POST', route_name='api_product_group_id', renderer='json', permission='Product Groups', trans=True) def update(request): - item = ProductGroup.by_id(uuid.UUID(request.matchdict['id'])) + item = request.dbsession.query(ProductGroup).filter(ProductGroup.id == uuid.UUID(request.matchdict['id'])).first() if item.is_fixture: raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name)) item.name = request.json_body['Name'] transaction.commit() - return product_group_info(item.id) + return product_group_info(item.id, request.dbsession) @view_config(request_method='DELETE', route_name='api_product_group_id', renderer='json', permission='Product Groups') def delete(request): - item = request.matchdict.get('id', None) - item = None if item is None else ProductGroup.by_id(uuid.UUID(item)) + item = request.dbsession.query(ProductGroup).filter(ProductGroup.id == uuid.UUID(request.matchdict['id'])).first() if item is None: response = Response("Product Group not Found") @@ -58,18 +56,18 @@ def delete(request): @view_config(request_method='GET', route_name='api_product_group_id', renderer='json', permission='Product Groups') def show_id(request): - return product_group_info(uuid.UUID(request.matchdict.get('id', None))) + return product_group_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession) @view_config(request_method='GET', route_name='api_product_group', renderer='json', permission='Product Groups') def show_blank(request): - return product_group_info(None) + return product_group_info(None, request.dbsession) @view_config(request_method='GET', route_name='api_product_group', request_param='list', renderer='json', permission='Authenticated') def show_list(request): - list = ProductGroup.list() + list = request.dbsession.query(ProductGroup).order_by(ProductGroup.name).all() product_groups = [] for item in list: product_groups.append({'ProductGroupID': item.id, 'Name': item.name, 'IsFixture': item.is_fixture, @@ -77,9 +75,9 @@ def show_list(request): return product_groups -def product_group_info(id): +def product_group_info(id, dbsession): if id is None: return {} else: - product_group = ProductGroup.by_id(id) + product_group = dbsession.query(ProductGroup).filter(ProductGroup.id == id).first() return {'ProductGroupID': product_group.id, 'Name': product_group.name, 'IsFixture': product_group.is_fixture} diff --git a/brewman/views/recipe.py b/brewman/views/recipe.py index 7e149aa4..12e39d8b 100644 --- a/brewman/views/recipe.py +++ b/brewman/views/recipe.py @@ -10,7 +10,6 @@ from pyramid.view import view_config from sqlalchemy import desc, or_, func import transaction -from brewman.models import DBSession from brewman.models.master import Recipe, Product, RecipeItem, CostCentre from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, Inventory, VoucherType, Journal @@ -30,7 +29,8 @@ def html(request): @view_config(request_method='POST', route_name='api_recipe_id', renderer='json', permission='Recipes', trans=True) def save(request): json = request.json_body - recipe_product = Product.by_id(uuid.UUID(json['Product']['ProductID'])) + recipe_product = request.dbsession.query(Product).filter( + Product.id == uuid.UUID(json['Product']['ProductID'])).first() try: valid_from = datetime.date(*(time.strptime(request.json_body['ValidFrom'], '%d-%b-%Y')[0:3])) @@ -65,12 +65,12 @@ def save(request): recipe = Recipe(product_id=recipe_product.id, quantity=recipe_quantity, sale_price=sale_price, valid_from=valid_from, valid_to=valid_to) for item in json['RecipeItems']: - product = Product.by_id(uuid.UUID(item['Product']['ProductID'])) + product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(item['Product']['ProductID'])).first() quantity = round(Decimal(item['Quantity']), 2) if product.is_purchased: - ingredient_cost = get_purchased_product_cost(product.id, valid_from, valid_to) + ingredient_cost = get_purchased_product_cost(product.id, valid_from, valid_to, request.dbsession) else: - ingredient_cost = get_sub_product_cost(product.id, valid_from, valid_to) + ingredient_cost = get_sub_product_cost(product.id, valid_from, valid_to, request.dbsession) cost_per_unit = ingredient_cost / (product.fraction * product.product_yield) recipe_cost += cost_per_unit * quantity recipe.recipe_items.append(RecipeItem(None, product.id, quantity, ingredient_cost)) @@ -79,28 +79,28 @@ def save(request): if recipe_product.is_sold: recipe_product.sale_price = sale_price - save_recipe(recipe) + save_recipe(recipe, request.dbsession) transaction.commit() session_period_set(request, valid_from, valid_to) return recipe_info(recipe.id, request) -def save_recipe(recipe): - product = Product.by_id(recipe.product_id) +def save_recipe(recipe, dbsession): + product = dbsession.query(Product).filter(Product.id == recipe.product_id).first() product.price = recipe.cost_price - update_old_rows(recipe.product_id, recipe.valid_from, recipe.valid_to, recipe.effective_from) - DBSession.add(recipe) + update_old_rows(recipe.product_id, recipe.valid_from, recipe.valid_to, recipe.effective_from, dbsession) + dbsession.add(recipe) for item in recipe.recipe_items: item.recipe_id = recipe.id - DBSession.add(item) + dbsession.add(item) -def get_purchased_product_cost(product_id, start_date, finish_date): +def get_purchased_product_cost(product_id, start_date, finish_date, dbsession): quantity_sum = func.sum(Journal.debit * Inventory.quantity).label('quantity') amount_sum = func.sum( Journal.debit * Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * (1 - Inventory.discount)).label( 'amount') - costing = DBSession.query(quantity_sum, amount_sum) \ + costing = dbsession.query(quantity_sum, amount_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Inventory.product_id == product_id) \ .filter(Voucher.date >= start_date) \ @@ -109,16 +109,16 @@ def get_purchased_product_cost(product_id, start_date, finish_date): .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ .group_by(Product).first() if costing is None: - product = Product.by_id(product_id) + product = dbsession.query(Product).filter(Product.id == product_id).first() return product.price else: quantity, amount = costing return amount / quantity -def get_sub_product_cost(product_id, start_date, finish_date): - product = Product.by_id(product_id) - old_recipe = DBSession.query(Recipe).filter(Recipe.product_id == product_id) \ +def get_sub_product_cost(product_id, start_date, finish_date, dbsession): + product = dbsession.query(Product).filter(Product.id == product_id).first() + old_recipe = dbsession.query(Recipe).filter(Recipe.product_id == product_id) \ .filter(Recipe.effective_to == None) \ .filter(Recipe.valid_from == start_date) \ .filter(Recipe.valid_to == finish_date) \ @@ -127,7 +127,7 @@ def get_sub_product_cost(product_id, start_date, finish_date): if old_recipe is not None: return old_recipe.cost_price - old_recipe = DBSession.query(Recipe).filter(Recipe.product_id == product_id) \ + old_recipe = dbsession.query(Recipe).filter(Recipe.product_id == product_id) \ .filter(Recipe.effective_to == None) \ .order_by(desc(Recipe.valid_to)) \ .first() @@ -140,21 +140,21 @@ def get_sub_product_cost(product_id, start_date, finish_date): valid_from=start_date, valid_to=finish_date) for item in old_recipe.recipe_items: if item.product.is_purchased: - ingredient_cost = get_purchased_product_cost(item.product_id, start_date, finish_date) + ingredient_cost = get_purchased_product_cost(item.product_id, start_date, finish_date, dbsession) else: - ingredient_cost = get_sub_product_cost(item.product_id, start_date, finish_date) + ingredient_cost = get_sub_product_cost(item.product_id, start_date, finish_date, dbsession) cost_per_unit = ingredient_cost / (item.product.fraction * item.product.product_yield) recipe_cost += cost_per_unit * item.quantity recipe.recipe_items.append(RecipeItem(None, item.product_id, item.quantity, ingredient_cost)) recipe.cost_price = round(recipe_cost / old_recipe.quantity, 2) - save_recipe(recipe) + save_recipe(recipe, dbsession) return recipe_cost -def update_old_rows(product_id, valid_from, valid_to, effective_date): - old = DBSession.query(Recipe).filter(Recipe.product_id == product_id) \ +def update_old_rows(product_id, valid_from, valid_to, effective_date, dbsession): + old = dbsession.query(Recipe).filter(Recipe.product_id == product_id) \ .filter(Recipe.valid_from < valid_to).filter(Recipe.valid_to > valid_from) \ .filter(or_(Recipe.effective_to == None, Recipe.effective_to >= effective_date)) \ .order_by(Recipe.effective_from).all() @@ -179,26 +179,26 @@ def update_old_rows(product_id, valid_from, valid_to, effective_date): if item.effective_from == effective_date and item.effective_to is None: for ri in item.recipe_items: - DBSession.delete(ri) - DBSession.delete(item) + dbsession.delete(ri) + dbsession.delete(item) else: item.effective_to = effective_date for recipe in new_recipes: - DBSession.add(recipe) + dbsession.add(recipe) for item in recipe.recipe_items: item.recipe_id = recipe.id - DBSession.add(item) + dbsession.add(item) @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() + recipe = request.dbsession.query(Recipe).filter(Recipe.id == uuid.UUID(request.matchdict['id'])).first() if len(recipe.product.recipes) > 1: - DBSession.delete(recipe) + request.dbsession.delete(recipe) else: - DBSession.delete(recipe) - DBSession.delete(recipe.product) + request.dbsession.delete(recipe) + request.dbsession.delete(recipe.product) transaction.commit() return recipe_info(None, request) @@ -216,7 +216,7 @@ def show_blank(request): @view_config(request_method='GET', route_name='api_recipe', renderer='json', request_param='list', permission='Authenticated') def show_list(request): - list = DBSession.query(Recipe).join(Recipe.product) \ + list = request.dbsession.query(Recipe).join(Recipe.product) \ .filter(Recipe.effective_to == None) \ .order_by(Recipe.product_id) \ .order_by(desc(Recipe.valid_to)) \ @@ -244,7 +244,7 @@ def recipe_info(id, request): info = {'Quantity': 1, 'ValidFrom': session_period_start(request), 'ValidTo': session_period_finish(request), 'RecipeItems': []} else: - recipe = DBSession.query(Recipe).filter(Recipe.id == id).one() + recipe = request.dbsession.query(Recipe).filter(Recipe.id == id).one() info = {'RecipeID': recipe.id, 'Product': {'ProductID': recipe.product_id, 'Name': recipe.product.name, 'Units': recipe.product.units, 'SalePrice': recipe.product.sale_price, 'IsSold': recipe.product.is_sold}, diff --git a/brewman/views/reports/balance_sheet.py b/brewman/views/reports/balance_sheet.py index 40f93672..e059d32c 100644 --- a/brewman/views/reports/balance_sheet.py +++ b/brewman/views/reports/balance_sheet.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func, desc from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerType, LedgerBase from brewman.models.voucher import Voucher, Journal, VoucherType @@ -30,19 +29,19 @@ def report_blank(request): @view_config(request_method='GET', route_name='api_balance_sheet_date', renderer='json', permission='Balance Sheet') def report_data(request): date = request.matchdict.get('date', None) - body, footer = build_balance_sheet(date) + body, footer = build_balance_sheet(date, request.dbsession) return {'Date': date, 'Body': body, 'Footer': footer} -def build_balance_sheet(finish_date): +def build_balance_sheet(finish_date, dbsession): if not isinstance(finish_date, datetime.datetime): finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') type_list = [i.id for i in LedgerType.list() if i.balance_sheet == True] report = [] groups = dict() # Add Net Profit / Loss - closing_stock = get_closing_stock(finish_date) - net_profit = get_accumulated_profit(finish_date) - closing_stock + closing_stock = get_closing_stock(finish_date, dbsession) + net_profit = get_accumulated_profit(finish_date, dbsession) - closing_stock total_amount = net_profit report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit', 'SubAmount': net_profit, 'Order': 79}) @@ -56,7 +55,7 @@ def build_balance_sheet(finish_date): groups[asset_group.id] = {'Group': asset_group.name, 'Amount': closing_stock, 'Order': asset_group.order} amount_sum = func.sum(Journal.amount * Journal.debit) - query = DBSession.query(LedgerBase, amount_sum) \ + query = dbsession.query(LedgerBase, amount_sum) \ .join(Journal.voucher).join(Journal.ledger) \ .filter(Voucher.date <= finish_date) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ diff --git a/brewman/views/reports/cash_flow.py b/brewman/views/reports/cash_flow.py index bc05db3f..fc9a0703 100644 --- a/brewman/views/reports/cash_flow.py +++ b/brewman/views/reports/cash_flow.py @@ -6,12 +6,12 @@ from sqlalchemy.sql.expression import func, desc from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerBase, LedgerType from brewman.models.voucher import Voucher, Journal from brewman.views.services.session import session_period_start, session_period_finish + @view_config(request_method='GET', route_name='cash_flow', permission='Cash Flow') @view_config(request_method='GET', route_name='cash_flow_id', permission='Cash Flow') def get_html(request): @@ -45,20 +45,20 @@ def build_report(request, start_date, finish_date): sub_journal = aliased(Journal) sub_ledger = aliased(LedgerBase) - sub_query = DBSession.query(sub_voucher.id)\ - .join(sub_journal, sub_voucher.journals)\ - .join(sub_ledger, sub_journal.ledger)\ - .filter(sub_ledger.type == LedgerType.by_name('Cash').id)\ - .filter(sub_voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ - .filter(sub_voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')).subquery() + sub_query = request.dbsession.query(sub_voucher.id) \ + .join(sub_journal, sub_voucher.journals) \ + .join(sub_ledger, sub_journal.ledger) \ + .filter(sub_ledger.type == LedgerType.by_name('Cash').id) \ + .filter(sub_voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ + .filter(sub_voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')).subquery() - query = DBSession.query(LedgerBase.type, func.sum(Journal.signed_amount))\ - .join(Journal, Voucher.journals)\ - .join(LedgerBase, Journal.ledger)\ - .filter(Voucher.id.in_(sub_query))\ - .filter(LedgerBase.type != LedgerType.by_name('Cash').id)\ - .group_by(LedgerBase.type)\ - .order_by(func.sum(Journal.signed_amount)).all() + query = request.dbsession.query(LedgerBase.type, func.sum(Journal.signed_amount)) \ + .join(Journal, Voucher.journals) \ + .join(LedgerBase, Journal.ledger) \ + .filter(Voucher.id.in_(sub_query)) \ + .filter(LedgerBase.type != LedgerType.by_name('Cash').id) \ + .group_by(LedgerBase.type) \ + .order_by(func.sum(Journal.signed_amount)).all() total_inflow = 0 total_outflow = 0 @@ -69,7 +69,9 @@ def build_report(request, start_date, finish_date): total_inflow += (amount * -1) if amount < 0 else 0 total_outflow += amount if amount >= 0 else 0 report['Body'].append({'Name': lt.name, 'Url': request.route_url('cash_flow_id', id=str(lt.id), - _query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow}) + _query={'StartDate': start_date, + 'FinishDate': finish_date}), + 'Inflow': inflow, 'Outflow': outflow}) report['Footer'].append({'Name': 'Total', 'Inflow': total_inflow, 'Outflow': total_outflow}) @@ -85,30 +87,32 @@ def build_report_id(request, ledger_type, start_date, finish_date): sub_journal = aliased(Journal) sub_ledger = aliased(LedgerBase) - sub_query = DBSession.query(sub_voucher.id)\ - .join(sub_journal, sub_voucher.journals)\ - .join(sub_ledger, sub_journal.ledger)\ - .filter(sub_ledger.type == LedgerType.by_name('Cash').id)\ - .filter(sub_voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ - .filter(sub_voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')).subquery() + sub_query = request.dbsession.query(sub_voucher.id) \ + .join(sub_journal, sub_voucher.journals) \ + .join(sub_ledger, sub_journal.ledger) \ + .filter(sub_ledger.type == LedgerType.by_name('Cash').id) \ + .filter(sub_voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ + .filter(sub_voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')).subquery() - query = DBSession.query(LedgerBase, func.sum(Journal.signed_amount))\ - .join(Journal, Voucher.journals)\ - .join(LedgerBase, Journal.ledger)\ - .filter(Voucher.id.in_(sub_query))\ - .filter(LedgerBase.type == ledger_type)\ - .group_by(LedgerBase)\ - .order_by(desc(func.sum(Journal.amount))).all() + query = request.dbsession.query(LedgerBase, func.sum(Journal.signed_amount)) \ + .join(Journal, Voucher.journals) \ + .join(LedgerBase, Journal.ledger) \ + .filter(Voucher.id.in_(sub_query)) \ + .filter(LedgerBase.type == ledger_type) \ + .group_by(LedgerBase) \ + .order_by(desc(func.sum(Journal.amount))).all() - totalInflow = 0 - totalOutflow = 0 + total_inflow = 0 + total_outflow = 0 for ledger, amount in query: inflow = amount * -1 if amount < 0 else 0 outflow = amount if amount >= 0 else 0 - totalInflow += (amount * -1) if amount < 0 else 0 - totalOutflow += amount if amount >= 0 else 0 + total_inflow += (amount * -1) if amount < 0 else 0 + total_outflow += amount if amount >= 0 else 0 report['Body'].append({'Name': ledger.name, 'Url': request.route_url('ledger_id', id=ledger.id, - _query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow}) + _query={'StartDate': start_date, + 'FinishDate': finish_date}), + 'Inflow': inflow, 'Outflow': outflow}) - report['Footer'].append({'Name': 'Total', 'Inflow': totalInflow, 'Outflow': totalOutflow}) + report['Footer'].append({'Name': 'Total', 'Inflow': total_inflow, 'Outflow': total_outflow}) return report diff --git a/brewman/views/reports/closing_stock.py b/brewman/views/reports/closing_stock.py index 81502694..b264f8e5 100644 --- a/brewman/views/reports/closing_stock.py +++ b/brewman/views/reports/closing_stock.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import Product, CostCentre from brewman.models.voucher import Voucher, Journal, Inventory @@ -28,14 +27,14 @@ def report_blank(request): @view_config(request_method='GET', route_name='api_closing_stock_date', renderer='json', permission='Closing Stock') def report_data(request): date = request.matchdict.get('date', None) - return {'Date': date, 'Body': build_report(date)} + return {'Date': date, 'Body': build_report(date, request.dbsession)} -def build_report(date): +def build_report(date, dbsession): date = datetime.datetime.strptime(date, '%d-%b-%Y') amount_sum = func.sum(Journal.debit * Inventory.quantity * Inventory.rate * (1 + Inventory.tax)).label('amount') quantity_sum = func.sum(Journal.debit * Inventory.quantity).label('quantity') - query = DBSession.query(Product, quantity_sum, amount_sum) \ + query = dbsession.query(Product, quantity_sum, amount_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Voucher.date <= date) \ .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ @@ -50,19 +49,35 @@ def build_report(date): return body -def get_opening_stock(startDate): - opening_stock = DBSession.query(func.sum(Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit)) \ - .join(Journal.voucher).join(Journal.ledger).join(Voucher.inventories) \ - .filter(Voucher.date < startDate) \ - .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ - .scalar() +def get_opening_stock(start_date, dbsession): + opening_stock = dbsession.query( + func.sum(Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit) + ).join( + Journal.voucher + ).join( + Journal.ledger + ).join( + Voucher.inventories + ).filter( + Voucher.date < start_date + ).filter( + Journal.cost_centre_id == CostCentre.cost_centre_purchase() + ).scalar() return 0 if opening_stock is None else opening_stock -def get_closing_stock(finishDate): - closing_stock = DBSession.query(func.sum(Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit)) \ - .join(Journal.voucher).join(Journal.ledger).join(Voucher.inventories) \ - .filter(Voucher.date <= finishDate) \ - .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ - .scalar() +def get_closing_stock(finish_date, dbsession): + closing_stock = dbsession.query( + func.sum(Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit) + ).join( + Journal.voucher + ).join( + Journal.ledger + ).join( + Voucher.inventories + ).filter( + Voucher.date <= finish_date + ).filter( + Journal.cost_centre_id == CostCentre.cost_centre_purchase() + ).scalar() return 0 if closing_stock is None else closing_stock diff --git a/brewman/views/reports/daybook.py b/brewman/views/reports/daybook.py index ccdc2ebb..33417457 100644 --- a/brewman/views/reports/daybook.py +++ b/brewman/views/reports/daybook.py @@ -31,7 +31,7 @@ def daybook_report(request): def build_report(request, start_date, finish_date): report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': []} - query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ + query = request.dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ @@ -40,20 +40,20 @@ def build_report(request, start_date, finish_date): for voucher in query: debit = 0 credit = 0 - nameDebit = "" - nameCredit = "" + name_debit = "" + name_credit = "" for journal in voucher.journals: if journal.debit == 1: debit += journal.amount - nameDebit += "{0} / ".format(journal.ledger.name) + name_debit += "{0} / ".format(journal.ledger.name) else: credit += journal.amount - nameCredit += "{0} / ".format(journal.ledger.name) - nameDebit = nameDebit[:-3] - nameCredit = nameCredit[:-3] + name_credit += "{0} / ".format(journal.ledger.name) + name_debit = name_debit[:-3] + name_credit = name_credit[:-3] report['Body'].append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher), 'Type': VoucherType.by_id(voucher.type).name, 'Narration': voucher.narration, 'Posted': voucher.posted, - 'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit, 'CreditA': credit}) + 'DebitN': name_debit, 'DebitA': debit, 'CreditN': name_credit, 'CreditA': credit}) return report diff --git a/brewman/views/reports/ledger.py b/brewman/views/reports/ledger.py index 033126a8..12d7d1c6 100644 --- a/brewman/views/reports/ledger.py +++ b/brewman/views/reports/ledger.py @@ -7,7 +7,6 @@ from sqlalchemy.orm import joinedload_all from sqlalchemy.sql.expression import func from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerBase from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.views.services.session import session_period_start, session_period_finish @@ -30,8 +29,7 @@ def show_blank(request): @view_config(request_method='GET', route_name='api_ledger_id', renderer='json', permission='Ledger', trans=True) def show_data(request): - ledger_id = request.matchdict['id'] - ledger = LedgerBase.by_id(uuid.UUID(ledger_id)) + ledger = request.dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(request.matchdict['id'])).first() start_date = request.GET.get('StartDate', session_period_start(request)) finish_date = request.GET.get('FinishDate', session_period_finish(request)) info = {'StartDate': start_date, 'FinishDate': finish_date, @@ -45,10 +43,10 @@ def build_report(request, info): ledger_id = info['Ledger']['LedgerID'] start_date = info['StartDate'] finish_date = info['FinishDate'] - opening = opening_balance(ledger_id, start_date) + opening = opening_balance(ledger_id, start_date, request.dbsession) info['Body'].append(opening) - query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ + query = request.dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ .filter(Voucher.journals.any(Journal.ledger_id == ledger_id)) \ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \ @@ -79,8 +77,8 @@ def build_report(request, info): 'Narration': voucher.narration, 'Debit': debit, 'Credit': credit, 'Posted': voucher.posted}) -def opening_balance(ledger_id, start_date): - opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \ +def opening_balance(ledger_id, start_date, dbsession): + opening = dbsession.query(func.sum(Journal.amount * Journal.debit)) \ .join(Journal.voucher) \ .filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ diff --git a/brewman/views/reports/net_transactions.py b/brewman/views/reports/net_transactions.py index bc82dc4a..6c5ac8d9 100644 --- a/brewman/views/reports/net_transactions.py +++ b/brewman/views/reports/net_transactions.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func, desc from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerBase from brewman.models.voucher import Voucher, Journal, VoucherType @@ -24,20 +23,21 @@ def report(request): start_date = request.GET.get('StartDate', None) finish_date = request.GET.get('FinishDate', None) if start_date and finish_date: - return {'StartDate': start_date, 'FinishDate': finish_date, 'Body': build_report(start_date, finish_date)} + return {'StartDate': start_date, 'FinishDate': finish_date, + 'Body': build_report(start_date, finish_date, request.dbsession)} else: return {'StartDate': session_period_start(request), 'FinishDate': session_period_finish(request), 'Body': []} -def build_report(start_date, finish_date): +def build_report(start_date, finish_date, dbsession): if not isinstance(start_date, datetime.datetime): start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') if not isinstance(finish_date, datetime.datetime): finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') amount_sum = func.sum(Journal.amount * Journal.debit).label('amount') - query = DBSession.query(LedgerBase, amount_sum) \ + query = dbsession.query(LedgerBase, amount_sum) \ .join(Journal.voucher).join(Journal.ledger) \ .filter(Voucher.date >= start_date) \ .filter(Voucher.date <= finish_date) \ diff --git a/brewman/views/reports/product_ledger.py b/brewman/views/reports/product_ledger.py index 17c87733..68177b74 100644 --- a/brewman/views/reports/product_ledger.py +++ b/brewman/views/reports/product_ledger.py @@ -6,7 +6,6 @@ from sqlalchemy.sql.expression import func from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import Product, CostCentre from brewman.models.validation_exception import ValidationError @@ -36,30 +35,30 @@ def show_data(request): id = to_uuid(request.matchdict['id']) if id is None: raise ValidationError("Invalid Product") - product = Product.by_id(id) + product = request.dbsession.query(Product).filter(Product.id == id).first() start_date = request.GET.get('StartDate', session_period_start(request)) finish_date = request.GET.get('FinishDate', session_period_finish(request)) info = {'StartDate': start_date, 'FinishDate': finish_date, 'Product': {'ProductID': product.id, 'Name': product.name}, 'Body': [], 'Footer': {}} - build_report(request, info) + build_report(request, info, request.dbsession) return info -def build_report(request, info): +def build_report(request, info, dbsession): product_id = info['Product']['ProductID'] start_date = info['StartDate'] finish_date = info['FinishDate'] - runningTotalQ, runningTotalA, opening = opening_balance(product_id, start_date) - totalDebitQ = runningTotalQ - totalDebitA = runningTotalA - totalCreditQ = 0 - totalCreditA = 0 + running_total_q, running_total_a, opening = opening_balance(product_id, start_date, dbsession) + total_debit_q = running_total_q + total_debit_a = running_total_a + total_credit_q = 0 + total_credit_a = 0 info['Body'].append(opening) - query = DBSession.query(Voucher, Inventory, Journal).options( + query = request.dbsession.query(Voucher, Inventory, Journal).options( joinedload(Journal.ledger, innerjoin=True), joinedload(Journal.cost_centre, innerjoin=True)) \ .filter(Voucher.id == Inventory.voucher_id) \ @@ -71,56 +70,65 @@ def build_report(request, info): .order_by(Voucher.date).order_by(Voucher.last_edit_date).all() for row in query: - journalDebit = row.Journal.debit * -1 + journal_debit = row.Journal.debit * -1 name = row.Journal.cost_centre.name if row.Voucher.type == VoucherType.by_name( 'Issue').id else row.Journal.ledger.name - debitQ = row.Inventory.quantity if journalDebit == 1 else 0 - debitA = row.Inventory.amount if journalDebit == 1 else 0 - creditQ = row.Inventory.quantity if journalDebit != 1 else 0 - creditA = row.Inventory.amount if journalDebit != 1 else 0 + debit_q = row.Inventory.quantity if journal_debit == 1 else 0 + debit_a = row.Inventory.amount if journal_debit == 1 else 0 + credit_q = row.Inventory.quantity if journal_debit != 1 else 0 + credit_a = row.Inventory.amount if journal_debit != 1 else 0 - runningTotalQ += (row.Inventory.quantity * journalDebit) - runningTotalA += (row.Inventory.amount * journalDebit) + running_total_q += (row.Inventory.quantity * journal_debit) + running_total_a += (row.Inventory.amount * journal_debit) - if journalDebit == 1: - totalDebitQ += row.Inventory.quantity - totalDebitA += row.Inventory.amount + if journal_debit == 1: + total_debit_q += row.Inventory.quantity + total_debit_a += row.Inventory.amount else: - totalCreditQ += row.Inventory.quantity - totalCreditA += row.Inventory.amount + total_credit_q += row.Inventory.quantity + total_credit_a += row.Inventory.amount info['Body'].append( {'Date': row.Voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, row.Voucher), - 'Type': VoucherType.by_id(row.Voucher.type).name, 'Narration': row.Voucher.narration, 'DebitQ': debitQ, - 'DebitA': debitA, 'CreditQ': creditQ, 'CreditA': creditA, 'RunningQ': runningTotalQ, - 'RunningA': runningTotalA}) + 'Type': VoucherType.by_id(row.Voucher.type).name, 'Narration': row.Voucher.narration, 'DebitQ': debit_q, + 'DebitA': debit_a, 'CreditQ': credit_q, 'CreditA': credit_a, 'RunningQ': running_total_q, + 'RunningA': running_total_a}) - info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', 'Narration': '', - 'DebitQ': totalDebitQ, 'DebitA': totalDebitA, 'CreditQ': totalCreditQ, 'CreditA': totalCreditA, - 'RunningQ': runningTotalQ, 'RunningA': runningTotalA} + info['Footer'] = { + 'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', 'Narration': '', + 'DebitQ': total_debit_q, 'DebitA': total_debit_a, 'CreditQ': total_credit_q, 'CreditA': total_credit_a, + 'RunningQ': running_total_q, 'RunningA': running_total_a + } -def opening_balance(product_id, start_date): - quantity, amount = DBSession.query(func.sum(Inventory.quantity * Journal.debit), - func.sum(Inventory.amount * Journal.debit)) \ - .join(Voucher) \ - .filter(Voucher.id == Inventory.voucher_id) \ - .filter(Voucher.id == Journal.voucher_id) \ - .filter(Inventory.product_id == product_id) \ - .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ - .filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ - .one() +def opening_balance(product_id, start_date, dbsession): + quantity, amount = dbsession.query( + func.sum(Inventory.quantity * Journal.debit), func.sum(Inventory.amount * Journal.debit) + ).join( + Voucher + ).filter( + Voucher.id == Inventory.voucher_id + ).filter( + Voucher.id == Journal.voucher_id + ).filter( + Inventory.product_id == product_id + ).filter( + Journal.cost_centre_id == CostCentre.cost_centre_purchase() + ).filter( + Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y') + ).one() if quantity and quantity > 0: - debitQuantity = quantity - debitAmount = amount + debit_quantity = quantity + debit_amount = amount else: - debitQuantity = '' - debitAmount = '' + debit_quantity = '' + debit_amount = '' if quantity is None: quantity = 0 amount = 0 return quantity, amount, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance', 'Narration': '', - 'DebitQ': debitQuantity, 'DebitA': debitAmount, 'RunningQ': quantity, 'RunningA': amount} + 'DebitQ': debit_quantity, 'DebitA': debit_amount, 'RunningQ': quantity, + 'RunningA': amount} diff --git a/brewman/views/reports/profit_loss.py b/brewman/views/reports/profit_loss.py index 85f19ffd..22b1fded 100644 --- a/brewman/views/reports/profit_loss.py +++ b/brewman/views/reports/profit_loss.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func, desc from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerType, LedgerBase from brewman.models.voucher import Voucher, Journal, VoucherType @@ -28,20 +27,20 @@ def get_profit_loss(request): report = {'StartDate': start_date, 'FinishDate': finish_date} start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') - report['Body'], report['Footer'] = build_profit_loss(start_date, finish_date) + report['Body'], report['Footer'] = build_profit_loss(start_date, finish_date, request.dbsession) return report else: return {'StartDate': session_period_start(request), 'FinishDate': session_period_finish(request), 'Body': [], 'Footer': {}} -def build_profit_loss(start_date, finish_date): +def build_profit_loss(start_date, finish_date, dbsession): profit_type_list = [i.id for i in LedgerType.list() if i.balance_sheet == False] report = [] groups = dict() amount_sum = func.sum(Journal.amount * Journal.debit) - query = DBSession.query(LedgerBase, amount_sum) \ + query = dbsession.query(LedgerBase, amount_sum) \ .join(Journal.voucher).join(Journal.ledger) \ .filter(Voucher.date >= start_date) \ .filter(Voucher.date <= finish_date) \ @@ -50,8 +49,8 @@ def build_profit_loss(start_date, finish_date): .group_by(LedgerBase).order_by(LedgerBase.type).order_by(desc(func.abs(amount_sum))).all() # Get opening / closing stock - opening_stock = get_opening_stock(start_date) - closing_stock = get_closing_stock(finish_date) + opening_stock = get_opening_stock(start_date, dbsession) + closing_stock = get_closing_stock(finish_date, dbsession) total_amount = (opening_stock - closing_stock) * -1 report.append({'Name': 'Opening Stock', 'SubAmount': opening_stock * -1, 'Order': 20.0001}) @@ -88,14 +87,13 @@ def build_profit_loss(start_date, finish_date): return sorted(report, key=lambda d: d['Order']), footer -def get_accumulated_profit(finish_date): - type_list = [i.id for i in LedgerType.list() if i.balance_sheet == False] +def get_accumulated_profit(finish_date, dbsession): + type_list = [i.id for i in LedgerType.list() if i.balance_sheet is False] - accumulated_profit = DBSession.query(func.sum(Journal.amount * Journal.debit))\ - .join(Journal.voucher).join(Journal.ledger)\ - .filter(Voucher.date <= finish_date)\ - .filter(Voucher.type != VoucherType.by_name('Issue').id)\ - .filter(LedgerBase.type.in_(type_list))\ - .scalar() + accumulated_profit = dbsession.query(func.sum(Journal.amount * Journal.debit)) \ + .join(Journal.voucher).join(Journal.ledger) \ + .filter(Voucher.date <= finish_date) \ + .filter(Voucher.type != VoucherType.by_name('Issue').id) \ + .filter(LedgerBase.type.in_(type_list)) \ + .scalar() return 0 if accumulated_profit is None else accumulated_profit - diff --git a/brewman/views/reports/purchase_entries.py b/brewman/views/reports/purchase_entries.py index 32ba0930..5ac35255 100644 --- a/brewman/views/reports/purchase_entries.py +++ b/brewman/views/reports/purchase_entries.py @@ -1,17 +1,14 @@ import datetime import pkg_resources -from pyramid.response import FileResponse -from sqlalchemy.sql.expression import func, desc +from pyramid.response import FileResponse from pyramid.view import view_config -from brewman.models import DBSession -from brewman.models.master import CostCentre, LedgerType, LedgerBase - -from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory +from brewman.models.voucher import Voucher, VoucherType from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.voucher import get_edit_url + @view_config(request_method='GET', route_name='purchase_entries', permission='Purchase Entries') def html(request): package, resource = 'brewman:static/base.html'.split(':', 1) @@ -26,7 +23,7 @@ def report_blank(request): @view_config(request_method='GET', route_name='api_purchase_entries', request_param='StartDate', renderer='json', - permission='Purchase Entries') + permission='Purchase Entries') def report_data(request): start_date = request.GET.get('StartDate', None) finish_date = request.GET.get('FinishDate', None) @@ -38,22 +35,20 @@ def build_report(request, start_date, finish_date): start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') - query = DBSession.query(Voucher)\ - .filter(Voucher.date >= start_date)\ - .filter(Voucher.date <= finish_date)\ - .filter(Voucher.type == VoucherType.by_name('Purchase').id)\ - .order_by(Voucher.date).all() + query = request.dbsession.query(Voucher) \ + .filter(Voucher.date >= start_date) \ + .filter(Voucher.date <= finish_date) \ + .filter(Voucher.type == VoucherType.by_name('Purchase').id) \ + .order_by(Voucher.date).all() for voucher in query: journal = [j for j in voucher.journals if j.debit == -1] journal = journal[0] row = {'Date': voucher.date.strftime('%d-%b-%Y'), 'Supplier': journal.ledger.name, - 'Url': get_edit_url(request, voucher), 'Products': []} + 'Url': get_edit_url(request, voucher), 'Products': []} for item in voucher.inventories: row['Products'].append( {'Product': item.product.full_name, 'Quantity': item.quantity, 'Rate': item.rate, 'Tax': item.tax, 'Amount': item.amount}) report['Body'].append(row) return report - - diff --git a/brewman/views/reports/purchases.py b/brewman/views/reports/purchases.py index 1c3be6ff..cb671ad1 100644 --- a/brewman/views/reports/purchases.py +++ b/brewman/views/reports/purchases.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func, desc from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import CostCentre, Product from brewman.models.voucher import Voucher, Journal, Inventory, VoucherType @@ -37,7 +36,7 @@ def build_report(request, start_date, finish_date): quantity_sum = func.sum(Journal.debit * Inventory.quantity).label('quantity') amount_sum = func.sum(Journal.debit * Inventory.quantity * Inventory.rate * (1 + Inventory.tax)).label('amount') - query = DBSession.query(Product, quantity_sum, amount_sum) \ + query = request.dbsession.query(Product, quantity_sum, amount_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \ diff --git a/brewman/views/reports/raw_material_cost.py b/brewman/views/reports/raw_material_cost.py index 9b122819..e5ccad73 100644 --- a/brewman/views/reports/raw_material_cost.py +++ b/brewman/views/reports/raw_material_cost.py @@ -5,7 +5,6 @@ from pyramid.response import FileResponse from sqlalchemy.sql.expression import func, case from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerBase, CostCentre, Product, ProductGroup @@ -48,9 +47,9 @@ def build_report(request, start_date, finish_date): report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': [], 'Footer': []} sum_issue = func.sum(case([(LedgerBase.type == 2, Journal.signed_amount)], else_=0)).label('issue') - sum_sale = (func.sum(case([(LedgerBase.type == 3, Journal.signed_amount)], else_=0)) * -1).label('sale') + sum_sale = func.sum(case([(LedgerBase.type == 3, Journal.signed_amount * -1)], else_=0)).label('sale') - query = DBSession.query(CostCentre, sum_issue, sum_sale) \ + query = request.dbsession.query(CostCentre, sum_issue, sum_sale) \ .join(CostCentre.journals).join(Journal.voucher).join(Journal.ledger) \ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \ @@ -83,7 +82,7 @@ def build_report_id(request, cost_centre_id, start_date, finish_date): sum_net = func.sum(Inventory.rate * Inventory.quantity * Journal.debit).label('net') sum_gross = func.sum(Inventory.amount * Journal.debit).label('gross') - query = DBSession.query(Product, sum_quantity, sum_net, sum_gross) \ + query = request.dbsession.query(Product, sum_quantity, sum_net, sum_gross) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals).join(Product.product_group) \ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \ diff --git a/brewman/views/reports/reconcile.py b/brewman/views/reports/reconcile.py index f060ffbe..04045ad3 100644 --- a/brewman/views/reports/reconcile.py +++ b/brewman/views/reports/reconcile.py @@ -8,7 +8,6 @@ import uuid from pyramid.view import view_config import transaction -from brewman.models import DBSession from brewman.models.master import LedgerBase from brewman.models.voucher import Voucher, Journal, VoucherType @@ -32,24 +31,23 @@ def show_blank(request): @view_config(request_method='GET', route_name='api_reconcile_id', renderer='json', permission='Reconcile', trans=True) def show_data(request): - id = request.matchdict['id'] - account = LedgerBase.by_id(uuid.UUID(id)) + account = request.dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(request.matchdict['id'])).first() start_date = request.GET.get('StartDate', session_period_start(request)) finish_date = request.GET.get('FinishDate', session_period_finish(request)) info = {'StartDate': start_date, 'FinishDate': finish_date, 'Account': {'LedgerID': account.id, 'Name': account.name}, 'Body': []} - build_report(request, info) + build_report(request, info, request.dbsession) return info -def build_report(request, info): +def build_report(request, info, dbsession): ledger_id = info['Account']['LedgerID'] start_date = info['StartDate'] finish_date = info['FinishDate'] - opening = opening_balance(ledger_id, start_date) + opening = opening_balance(ledger_id, start_date, dbsession) info['Body'].append(opening) - query = Voucher.query().options( + query = request.dbsession.query(Voucher).options( joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True) ).filter( Voucher.journals.any(Journal.ledger_id == ledger_id) @@ -90,13 +88,13 @@ def build_report(request, info): 'ReconcileDate': voucher.reconcile_date.strftime('%d-%b-%Y')}) -def opening_balance(ledgerID, start_date): - opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \ +def opening_balance(ledger_id, start_date, dbsession): + opening = dbsession.query(func.sum(Journal.amount * Journal.debit)) \ .join(Journal.voucher) \ .filter(Voucher.reconcile_date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \ .filter(Voucher.is_reconciled == True) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ - .filter(Journal.ledger_id == ledgerID) \ + .filter(Journal.ledger_id == ledger_id) \ .scalar() opening = 0 if opening is None else opening if opening < 0: @@ -111,14 +109,14 @@ def opening_balance(ledgerID, start_date): @view_config(request_method='POST', route_name='api_reconcile_id', renderer='json', permission='Reconcile') def save(request): - id = request.matchdict['id'] - account = LedgerBase.by_id(uuid.UUID(id)) + account = request.dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(request.matchdict['id'])).first() start_date = request.GET.get('StartDate', session_period_start(request)) finish_date = request.GET.get('FinishDate', session_period_finish(request)) for item in request.json_body['Body']: if 'VoucherID' not in item: continue - voucher = Voucher.by_id(uuid.UUID(item['VoucherID'])) + + voucher = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(item['VoucherID'])).first() is_reconciled = item['IsReconciled'] reconcile_date = datetime.datetime.strptime(item['ReconcileDate'], '%d-%b-%Y') voucher.is_reconciled = is_reconciled @@ -128,5 +126,5 @@ def save(request): info = {'StartDate': start_date, 'FinishDate': finish_date, 'Account': {'LedgerID': account.id, 'Name': account.name}, 'Body': [], 'Footer': {}} - build_report(request, info) + build_report(request, info, request.dbsession) return info diff --git a/brewman/views/reports/stock_movement.py b/brewman/views/reports/stock_movement.py index b940c027..745f1929 100644 --- a/brewman/views/reports/stock_movement.py +++ b/brewman/views/reports/stock_movement.py @@ -5,7 +5,6 @@ from sqlalchemy.sql.expression import func from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import Product, CostCentre from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory @@ -27,17 +26,17 @@ def get_stock_movement(request): report = {'StartDate': start_date, 'FinishDate': finish_date} start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y') finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y') - report['Body'] = build_stock_movement(start_date, finish_date) + report['Body'] = build_stock_movement(start_date, finish_date, request.dbsession) return report else: return {'StartDate': session_period_start(request), 'FinishDate': session_period_finish(request), 'Body': []} -def build_stock_movement(start_date, finish_date): +def build_stock_movement(start_date, finish_date, dbsession): dict = {} quantity_sum = func.sum(Journal.debit * Inventory.quantity).label('quantity') - openings = DBSession.query(Product, quantity_sum) \ + openings = dbsession.query(Product, quantity_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Voucher.date < start_date) \ .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \ @@ -45,7 +44,7 @@ def build_stock_movement(start_date, finish_date): for product, quantity in openings: dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name, 'Opening': quantity} - purchases = DBSession.query(Product, quantity_sum) \ + purchases = dbsession.query(Product, quantity_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Voucher.date >= start_date) \ .filter(Voucher.date <= finish_date) \ @@ -58,7 +57,7 @@ def build_stock_movement(start_date, finish_date): else: dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name, 'Purchase': quantity} - issues = DBSession.query(Product, quantity_sum) \ + issues = dbsession.query(Product, quantity_sum) \ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \ .filter(Voucher.date >= start_date) \ .filter(Voucher.date <= finish_date) \ @@ -85,4 +84,4 @@ def build_stock_movement(start_date, finish_date): list.remove(item) else: item['Closing'] = closing - return list \ No newline at end of file + return list diff --git a/brewman/views/reports/trial_balance.py b/brewman/views/reports/trial_balance.py index 28b4a13c..6e1453b6 100644 --- a/brewman/views/reports/trial_balance.py +++ b/brewman/views/reports/trial_balance.py @@ -5,11 +5,11 @@ from sqlalchemy.sql.expression import func from pyramid.view import view_config -from brewman.models import DBSession from brewman.models.master import LedgerBase 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', permission='Trial Balance') @view_config(request_method='GET', route_name='trial_balance_date', permission='Trial Balance') @@ -18,6 +18,7 @@ def html(request): 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') def report_blank(request): return {'Date': session_period_finish(request), 'Body': []} @@ -26,21 +27,20 @@ def report_blank(request): @view_config(request_method='GET', route_name='api_trial_balance_date', renderer='json', permission='Trial Balance') def report_data(request): date = request.matchdict.get('date', None) - return {'Date': date, 'Body': build_report(date)} + return {'Date': date, 'Body': build_report(date, request.dbsession)} -def build_report(date): +def build_report(date, dbsession): date = datetime.datetime.strptime(date, '%d-%b-%Y') amount_sum = func.sum(Journal.amount * Journal.debit).label('amount') - query = DBSession.query(LedgerBase, amount_sum)\ - .join(Journal.voucher).join(Journal.ledger)\ - .filter(Voucher.date <= date).filter(Voucher.type != VoucherType.by_name('Issue').id).group_by(LedgerBase)\ + query = dbsession.query(LedgerBase, amount_sum) \ + .join(Journal.voucher).join(Journal.ledger) \ + .filter(Voucher.date <= date).filter(Voucher.type != VoucherType.by_name('Issue').id).group_by(LedgerBase) \ .order_by(LedgerBase.type).order_by(func.abs(amount_sum).desc()).all() - body = [] for ledger, amount in query: if amount != 0: tag = 'Debit' if amount > 0 else 'Credit' - body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag:amount}) + body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag: amount}) return body diff --git a/brewman/views/reports/unposted.py b/brewman/views/reports/unposted.py index 5b8215f6..fe231772 100644 --- a/brewman/views/reports/unposted.py +++ b/brewman/views/reports/unposted.py @@ -7,6 +7,7 @@ from pyramid.view import view_config from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.views.services.voucher import get_edit_url + @view_config(request_method='GET', route_name='unposted', permission='Post Vouchers') def html(request): package, resource = 'brewman:static/base.html'.split(':', 1) @@ -18,32 +19,33 @@ def html(request): def report_data(request): return build_report(request) + def build_report(request): body = [] - query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True))\ - .filter(Voucher.posted == False)\ - .filter(Voucher.type != VoucherType.by_name('Issue').id)\ - .order_by(Voucher.date).order_by(Voucher.last_edit_date).all() + query = request.dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \ + .filter(Voucher.posted == False) \ + .filter(Voucher.type != VoucherType.by_name('Issue').id) \ + .order_by(Voucher.date).order_by(Voucher.last_edit_date).all() for voucher in query: debit = 0 credit = 0 - nameDebit = "" - nameCredit = "" + name_debit = "" + name_credit = "" for journal in voucher.journals: if journal.debit == 1: debit += journal.amount - nameDebit += "{0} / ".format(journal.ledger.name) + name_debit += "{0} / ".format(journal.ledger.name) else: credit += journal.amount - nameCredit += "{0} / ".format(journal.ledger.name) - nameDebit = nameDebit[:-3] - nameCredit = nameCredit[:-3] + name_credit += "{0} / ".format(journal.ledger.name) + name_debit = name_debit[:-3] + name_credit = name_credit[:-3] body.append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher), - 'Type': VoucherType.by_id(voucher.type).name, - 'Narration': voucher.narration, 'Posted': voucher.posted, - 'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit,'CreditA': credit}) + 'Type': VoucherType.by_id(voucher.type).name, + 'Narration': voucher.narration, 'Posted': voucher.posted, + 'DebitN': name_debit, 'DebitA': debit, 'CreditN': name_credit, 'CreditA': credit}) - return body \ No newline at end of file + return body diff --git a/brewman/views/services/batch.py b/brewman/views/services/batch.py index b3342336..754d9051 100644 --- a/brewman/views/services/batch.py +++ b/brewman/views/services/batch.py @@ -12,12 +12,19 @@ def batch_term(request): date = request.GET.get('date', None) date = None if date is None or date == '' else datetime.datetime.strptime(date, '%d-%b-%Y') list = [] - for index, item in enumerate(Batch.list(filter, include_nil=False, date=date)): - text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format(item.product.name, item.product.units, - item.quantity_remaining, item.rate, item.name.strftime('%d-%b-%Y')) - list.append({'BatchID': item.id, 'Name': text, 'QuantityRemaining': item.quantity_remaining, - 'Rate': item.rate, 'Tax': item.tax, 'Discount': item.discount, - 'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units}}) + for index, item in enumerate(Batch.list(filter, include_nil=False, date=date, dbsession=request.dbsession)): + text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format( + item.product.name, + item.product.units, + item.quantity_remaining, + item.rate, + item.name.strftime('%d-%b-%Y') + ) + list.append({ + 'BatchID': item.id, 'Name': text, 'QuantityRemaining': item.quantity_remaining, + 'Rate': item.rate, 'Tax': item.tax, 'Discount': item.discount, + 'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units} + }) if count is not None and index == count - 1: break return list diff --git a/brewman/views/services/cost_centre.py b/brewman/views/services/cost_centre.py index 32f5efbf..c6930455 100644 --- a/brewman/views/services/cost_centre.py +++ b/brewman/views/services/cost_centre.py @@ -5,34 +5,33 @@ from pyramid.view import view_config from sqlalchemy.orm.util import aliased from sqlalchemy.sql.expression import and_ -from brewman.models import DBSession from brewman.models.voucher import Voucher, Journal, VoucherType @view_config(route_name='api_issues_grid', request_param='Source', renderer='json', permission='Issue', trans=True) def grid_date(request): date = datetime.datetime.strptime(request.matchdict['date'], '%d-%b-%Y') - return get_grid(date, uuid.UUID(request.GET['Source']), uuid.UUID(request.GET['Destination'])) + return get_grid(date, uuid.UUID(request.GET['Source']), uuid.UUID(request.GET['Destination']), request.dbsession) @view_config(route_name='api_issues_grid', renderer='json', permission='Issue', trans=True) def grid_voucher(request): - voucher = Voucher.by_id(uuid.UUID(request.matchdict['date'])) + voucher = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(request.matchdict['date'])).first() source = [j.cost_centre_id for j in voucher.journals if j.debit == -1] source = source[0] destination = [j.cost_centre_id for j in voucher.journals if j.debit == 1] destination = destination[0] - return get_grid(voucher.date, source, destination) + return get_grid(voucher.date, source, destination, request.dbsession) -def get_grid(date, source, destination): +def get_grid(date, source, destination, dbsession): list = [] source_journal = aliased(Journal) destination_journal = aliased(Journal) source_or = (and_(source_journal.cost_centre_id == source, source_journal.debit == -1)) destination_or = (and_(destination_journal.cost_centre_id == destination, destination_journal.debit == 1)) - query = DBSession.query(Voucher, source_journal.amount) \ + query = dbsession.query(Voucher, source_journal.amount) \ .join(source_journal, Voucher.journals) \ .join(destination_journal, Voucher.journals) \ .filter(Voucher.date == date) \ diff --git a/brewman/views/services/login.py b/brewman/views/services/login.py index 025c2dd0..29c19ba3 100644 --- a/brewman/views/services/login.py +++ b/brewman/views/services/login.py @@ -1,15 +1,13 @@ +import transaction from datetime import datetime, timedelta from pyramid.httpexceptions import HTTPFound from pyramid.response import Response - from pyramid.security import remember, forget from pyramid.view import view_config -from sqlalchemy import and_, or_ -import transaction -from brewman import groupfinder -from brewman.models import DBSession +from sqlalchemy import and_ + from brewman.models.auth import User, Client, LoginHistory @@ -24,18 +22,19 @@ def logout(request): def login(request): username = request.json_body.get('username', None) password = request.json_body.get('password', None) - found, user = User.auth(username, password) + found, user = User.auth(username, password, request.dbsession) - client = Client.by_code(request.cookies.get('ClientID', None)) + client = Client.by_code(request.cookies.get('ClientID', None), request.dbsession) otp = request.json_body.get('otp', None) client_name = request.json_body.get('ClientName', None) - allowed, client, response = check_client(client, otp, client_name, user if found else None) + if user is not None: + allowed, client, response = check_client(client, otp, client_name, user, request.dbsession) if found and allowed: headers = remember(request, str(user.id)) request.response.headers = headers request.response.set_cookie('ClientID', value=str(client.code), max_age=365 * 24 * 60 * 60) - record_login(user.id, client) + record_login(user.id, client, request.dbsession) transaction.commit() return request.response elif not found: @@ -48,11 +47,15 @@ def login(request): return response -def check_client(client, otp, client_name, user): - outside_login_allowed = False if user is None else True if 'Clients' in groupfinder(user.id, None) else False +def check_client(client, otp, client_name, user, dbsession): + outside_login_allowed = False + for group in user.groups: + for perm in group.roles: + if perm.name == 'Clients': + outside_login_allowed = True - if len(Client.enabled_list()) == 0 and outside_login_allowed: - client = Client.create() + if dbsession.query(Client).filter(Client.enabled == True).count() == 0 and outside_login_allowed: + client = Client.create(dbsession) client.otp = None client.name = 'Created on login by ' + user.name client.enabled = True @@ -60,10 +63,10 @@ def check_client(client, otp, client_name, user): if client is None: if outside_login_allowed: - client = Client.create() + client = Client.create(dbsession) return True, client, None else: - client = Client.create() + client = Client.create(dbsession) response = Response("Unknown Client") response.status_int = 403 response.set_cookie('ClientID', value=str(client.code), max_age=10 * 365 * 24 * 60 * 60) @@ -92,30 +95,33 @@ def check_client(client, otp, client_name, user): return True, client, None -def record_login(user_id, client): +def record_login(user_id, client, dbsession): history = LoginHistory(user_id) history.client = client - DBSession.add(history) + dbsession.add(history) - recent_logins = DBSession.query(LoginHistory.client_id.distinct()) \ + recent_logins = dbsession.query(LoginHistory.client_id.distinct()) \ .filter(LoginHistory.date > datetime.utcnow() - timedelta(days=90)).subquery() - deletable_clients = DBSession.query(Client.id) \ + deletable_clients = dbsession.query(Client.id) \ .filter(Client.creation_date < datetime.utcnow() - timedelta(days=3)) \ .filter(Client.enabled == False).subquery() - LoginHistory.__table__.delete( - and_( - ~LoginHistory.client_id.in_(recent_logins), - LoginHistory.client_id.in_(deletable_clients) + dbsession.execute( + LoginHistory.__table__.delete( + and_( + ~LoginHistory.client_id.in_(recent_logins), + LoginHistory.client_id.in_(deletable_clients) + ) ) - ).execute() + ) - Client.__table__.delete( - and_( - Client.creation_date < datetime.utcnow() - timedelta(days=3), - Client.enabled == False, - ~Client.id.in_(recent_logins) + dbsession.execute( + Client.__table__.delete( + and_( + Client.creation_date < datetime.utcnow() - timedelta(days=3), + Client.enabled == False, + ~Client.id.in_(recent_logins) + ) ) - ).execute() - + ) diff --git a/brewman/views/services/session.py b/brewman/views/services/session.py index 89aaac4d..58830aef 100644 --- a/brewman/views/services/session.py +++ b/brewman/views/services/session.py @@ -1,9 +1,8 @@ -from datetime import date, timedelta, datetime import uuid +from datetime import date, timedelta from pyramid.view import view_config -from brewman import groupfinder from brewman.models.auth import Role, User @@ -48,13 +47,10 @@ def user_permission(request): elif 'auth' in request.session: auth = request.session['auth'] else: - user = User.by_id(uuid.UUID(user_id)) - auth = {'isAuthenticated': True, 'Name': user.name, 'UserID': user.id} - session_perms = groupfinder(user.id, request) - perms = {} - for item in Role.list(): - perms[item.name] = True if item.name in session_perms else False - auth['perms'] = perms + user = request.dbsession.query(User).filter(User.id == uuid.UUID(user_id)).one() + auth = {'isAuthenticated': True, 'Name': user.name, 'UserID': user.id, 'perms': {}} + for item in request.dbsession.query(Role).order_by(Role.name).all(): + auth['perms'][item.name] = request.has_permission(item.name) request.session['auth'] = auth return auth diff --git a/brewman/views/services/voucher/__init__.py b/brewman/views/services/voucher/__init__.py index 488a42d3..e09d5643 100644 --- a/brewman/views/services/voucher/__init__.py +++ b/brewman/views/services/voucher/__init__.py @@ -1,15 +1,13 @@ import datetime -from decimal import Decimal +import pkg_resources +import transaction import uuid -import pkg_resources +from decimal import Decimal from pyramid.response import Response, FileResponse from pyramid.view import view_config from sqlalchemy import func, or_ -import transaction -from brewman import groupfinder -from brewman.models import DBSession from brewman.models.auth import User from brewman.models.master import LedgerBase, CostCentre, Employee, AttendanceType, Ledger from brewman.models.validation_exception import ValidationError @@ -21,8 +19,6 @@ from .purchase import purchase_create_voucher, purchase_update_voucher from .service_charge import service_charge_create_voucher, service_charge_update_voucher from ..session import get_first_day -__author__ = 'tanshu' - @view_config(request_method='GET', route_name='journal_id', permission='Journal') @view_config(request_method='GET', route_name='journal', permission='Journal') @@ -49,9 +45,9 @@ def journal_get(request): @view_config(request_method='POST', route_name='api_voucher_id', request_param='post', renderer='json', permission='Post Vouchers', trans=True) def voucher_post(request): - user = User.by_id(uuid.UUID(request.authenticated_userid)) - voucher = Voucher.by_id(uuid.UUID(request.matchdict['id'])) - start, finish = get_lock_info() + user = request.dbsession.query(User).filter(User.id == uuid.UUID(request.authenticated_userid)).one() + voucher = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(request.matchdict['id'])).first() + start, finish = get_lock_info(request.dbsession) if start is not None and start > voucher.date: raise ValidationError("Vouchers before {0} have been locked.".format(start.strftime('%d-%b-%Y'))) elif finish is not None and finish < voucher.date: @@ -59,26 +55,26 @@ def voucher_post(request): voucher.posted = True voucher.poster_id = user.id transaction.commit() - return voucher_info(Voucher.by_id(voucher.id), request) + new_voucher = request.dbsession.query(Voucher).filter(Voucher.id == voucher.id).first() + return voucher_info(new_voucher, request) def check_delete_permissions(request, voucher): - user = User.by_id(uuid.UUID(request.authenticated_userid)) - permissions = groupfinder(user.id, request) + user = request.dbsession.query(User).filter(User.id == uuid.UUID(request.authenticated_userid)).one() - if voucher.posted and not 'Edit Posted Vouchers' in permissions: + if voucher.posted and not request.has_permission('Edit Posted Vouchers'): response = Response("You are not allowed to edit posted vouchers") response.status_int = 403 return response - elif voucher.user_id != user.id and "Edit Other User's Vouchers" not in permissions: + elif voucher.user_id != user.id and not request.has_permission("Edit Other User's Vouchers"): response = Response("You are not allowed to edit other user's vouchers") response.status_int = 403 return response - elif VoucherType.by_id(voucher.type).name not in permissions: + elif not request.has_permission(VoucherType.by_id(voucher.type).name): response = Response("You are not allowed (0) vouchers".format(VoucherType.by_id(voucher.type).name)) response.status_int = 403 return response - start, finish = get_lock_info() + start, finish = get_lock_info(request.dbsession) if start is not None and start > voucher.date: response = Response("Vouchers before {0} have been locked.".format(start.strftime('%d-%b-%Y'))) response.status_int = 403 @@ -91,8 +87,8 @@ def check_delete_permissions(request, voucher): @view_config(request_method='DELETE', route_name='api_voucher_id', renderer='json', trans=True) def delete(request): - voucher = Voucher.by_id(uuid.UUID(request.matchdict['id'])) - images = DbImage.by_resource_id(voucher.id, 'voucher') + voucher = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(request.matchdict['id'])).first() + images = request.dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all() permission = check_delete_permissions(request, voucher) if permission is not None: return permission @@ -104,7 +100,13 @@ def delete(request): destination = item.cost_centre_id else: source = item.cost_centre_id - batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None + if source == CostCentre.cost_centre_purchase(): + batch_consumed = True + elif destination == CostCentre.cost_centre_purchase(): + batch_consumed = False + else: + batch_consumed = None + if batch_consumed is None: pass elif batch_consumed: @@ -119,7 +121,7 @@ def delete(request): item.batch.quantity_remaining -= item.quantity elif voucher.type == VoucherType.by_name('Purchase').id: for item in voucher.inventories: - uses = DBSession.query(func.count(Inventory.id)) \ + uses = request.dbsession.query(func.count(Inventory.id)) \ .filter(Inventory.batch_id == item.batch.id) \ .filter(Inventory.id != item.id).scalar() if uses > 0: @@ -129,18 +131,19 @@ def delete(request): for item in voucher.inventories: item.batch.quantity_remaining += item.quantity for b in batches_to_delete: - DBSession.delete(b) - DBSession.delete(voucher) + request.dbsession.delete(b) + request.dbsession.delete(voucher) for image in images: - DBSession.delete(image) + request.dbsession.delete(image) transaction.commit() - return blank_voucher(info=json_voucher) + return blank_voucher(info=json_voucher, dbsession=request.dbsession) @view_config(request_method='GET', route_name='api_voucher_id', renderer='json', trans=True) def get_old(request): id = request.matchdict.get('id', None) - return voucher_info(Voucher.by_id(uuid.UUID(id)), request) + voucher = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(id)).first() + return voucher_info(voucher, request) def voucher_info(voucher, request): @@ -178,9 +181,10 @@ def voucher_info(voucher, request): 'CostCentre': {'CostCentreID': item.journal.ledger.cost_centre.id, 'Name': item.journal.ledger.cost_centre.name}}}}) for item in voucher.service_charges: + employee = request.dbsession.query(Employee).filter(Employee.id == item.journal.ledger_id).first() json_voucher['ServiceCharges'].append( {'EmployeeID': item.journal.ledger_id, 'Name': item.journal.ledger.name, - 'Designation': Employee.by_id(item.journal.ledger_id).designation, + 'Designation': employee.designation, 'Department': item.journal.ledger.cost_centre.name, 'DaysWorked': item.days_worked, 'Points': item.points}) if len(json_voucher['ServiceCharges']) > 0: json_voucher['ServiceCharge'] = [x.amount for x in voucher.journals if @@ -198,7 +202,7 @@ def voucher_info(voucher, request): 'QuantityRemaining': item.batch.quantity_remaining, 'Tax': item.batch.tax, 'Discount': item.batch.discount, 'Rate': item.batch.rate, 'Product': {'ProductID': item.batch.product.id, 'Name': item.batch.product.full_name}}}) - images = DbImage.by_resource_id(voucher.id, 'voucher') + images = request.dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all() for image in images: resized = request.route_url('db_image', id=image.id, type='resized') thumbnail = request.route_url('db_image', id=image.id, type='thumbnail') @@ -206,7 +210,7 @@ def voucher_info(voucher, request): return json_voucher -def blank_voucher(info): +def blank_voucher(info, dbsession): if 'Type' not in info: raise ValidationError('Voucher Type is null') type = info['Type'] @@ -219,7 +223,7 @@ def blank_voucher(info): elif type == 'Payment': ledger = None if info is not None and 'Account' in info and info['Account'] is not None: - ledger = LedgerBase.by_id(info['Account']) + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(info['Account'])).first() if ledger is not None: ledger = {'LedgerID': ledger.id, 'Name': ledger.name} else: @@ -228,7 +232,7 @@ def blank_voucher(info): elif type == 'Receipt': ledger = None if info is not None and 'Account' in info and info['Account'] is not None: - ledger = LedgerBase.by_id(info['Account']) + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(info['Account'])).first() if ledger is not None: ledger = {'LedgerID': ledger.id, 'Name': ledger.name} else: @@ -268,24 +272,26 @@ def blank_voucher(info): elif type == 'Salary Deduction': json_voucher['SalaryDeductions'] = [] elif type == 'Service Charge': - json_voucher['ServiceCharges'], json_voucher['ServiceCharge'] = service_charge_employees(info['Date']) + json_voucher['ServiceCharges'], json_voucher['ServiceCharge'] = service_charge_employees( + info['Date'], dbsession + ) else: raise ValidationError("Voucher of type \"{0}\" does not exist.".format(type)) json_voucher['Files'] = [] return json_voucher -def service_charge_employees(date): +def service_charge_employees(date, dbsession): date = datetime.datetime.strptime(date, '%d-%b-%Y') start_date = get_first_day(date) finish_date = date + datetime.timedelta(1) details = [] - employees = DBSession().query(Employee) \ + employees = dbsession.query(Employee) \ .filter(Employee.joining_date <= finish_date) \ .filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \ .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() for employee in employees: - att = DBSession.query(Attendance) \ + att = dbsession.query(Attendance) \ .filter(Attendance.employee_id == employee.id) \ .filter(Attendance.date >= start_date) \ .filter(Attendance.date < finish_date) \ @@ -295,7 +301,7 @@ def service_charge_employees(date): details.append({'EmployeeID': employee.id, 'Name': employee.name, 'Designation': employee.designation, 'Department': employee.cost_centre.name, 'DaysWorked': att, 'Points': employee.service_points}) - amount = DBSession.query(func.sum(Journal.amount * Journal.debit)) \ + amount = dbsession.query(func.sum(Journal.amount * Journal.debit)) \ .join(Journal.voucher) \ .filter(Voucher.date < finish_date) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ diff --git a/brewman/views/services/voucher/credit_salary.py b/brewman/views/services/voucher/credit_salary.py index 89678bac..19d935d6 100644 --- a/brewman/views/services/voucher/credit_salary.py +++ b/brewman/views/services/voucher/credit_salary.py @@ -6,44 +6,41 @@ from pyramid.view import view_config from sqlalchemy import or_ import transaction -from ....models import DBSession from ....models.auth import User from ....models.master import Employee, AttendanceType, Ledger from ....models.voucher import Voucher, VoucherType, Attendance, Journal from ..session import get_first_day, get_last_day -__author__ = 'tanshu' - @view_config(request_method='POST', route_name='api_credit_salary', renderer='json', permission='Attendance', trans=True) def credit_salary(request): - user = User.by_id(uuid.UUID(request.authenticated_userid)) + user = request.dbsession.query(User).filter(User.id == uuid.UUID(request.authenticated_userid)).one() month = datetime.datetime.strptime(request.json_body['Month'], '%d-%b-%Y') start_date = get_first_day(month) finish_date = get_last_day(month) voucher = Voucher(date=finish_date, narration='Auto Generated Salary Entry', user_id=user.id, type=VoucherType.by_name('Journal'), posted=True, poster_id=user.id) - DBSession.add(voucher) - for item in salary_journals(start_date, finish_date): + request.dbsession.add(voucher) + for item in salary_journals(start_date, finish_date, request.dbsession): voucher.journals.append(item) - DBSession.add(item) + request.dbsession.add(item) transaction.commit() return {'message': 'Salary Entry created'} -def salary_journals(start_date, finish_date): +def salary_journals(start_date, finish_date, dbsession): days = calendar.monthrange(start_date.year, start_date.month)[1] finish_date = finish_date + datetime.timedelta(1) amount = 0 journals = [] - employees = DBSession().query(Employee) \ + employees = dbsession.query(Employee) \ .filter(Employee.joining_date <= finish_date) \ .filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \ .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() for employee in employees: - att = DBSession.query(Attendance) \ + att = dbsession.query(Attendance) \ .filter(Attendance.employee_id == employee.id) \ .filter(Attendance.date >= start_date) \ .filter(Attendance.date < finish_date) \ @@ -55,7 +52,6 @@ def salary_journals(start_date, finish_date): amount += att journals.append( Journal(amount=att, debit=-1, ledger_id=employee.id, cost_centre_id=employee.cost_centre_id)) - salary = Ledger.salary() - salary = Ledger.by_id(uuid.UUID(salary['LedgerID'])) + salary = dbsession.query(Ledger).filter(Ledger.id == uuid.UUID(Ledger.salary()['LedgerID'])).first() journals.append(Journal(amount=amount, debit=1, ledger_id=salary.id, cost_centre_id=salary.cost_centre_id)) return journals diff --git a/brewman/views/services/voucher/empty_voucher.py b/brewman/views/services/voucher/emptyvoucher.py similarity index 89% rename from brewman/views/services/voucher/empty_voucher.py rename to brewman/views/services/voucher/emptyvoucher.py index d29f8eba..e2e2644e 100644 --- a/brewman/views/services/voucher/empty_voucher.py +++ b/brewman/views/services/voucher/emptyvoucher.py @@ -2,11 +2,9 @@ from pyramid.view import view_config, view_defaults from brewman.views.services.session import session_current_date from brewman.views.services.voucher import blank_voucher -__author__ = 'tanshu' - @view_defaults(request_method='GET', route_name='api_voucher', renderer='json') -class blank_voucher_view(object): +class EmptyVoucher(object): def __init__(self, request): self.request = request @@ -14,34 +12,28 @@ class blank_voucher_view(object): def journal(self): return self.get_blank() - @view_config(request_param='type=Payment', permission='Payment') def payment(self): account = self.request.GET.get('a', None) return self.get_blank({'Account': account}) - @view_config(request_param='type=Receipt', permission='Receipt') def receipt(self): account = self.request.GET.get('a', None) return self.get_blank({'Account': account}) - @view_config(request_param='type=Purchase', permission='Purchase') def purchase(self): return self.get_blank() - @view_config(request_param='type=Purchase Return', permission='Purchase Return') def purchase_return(self): return self.get_blank() - @view_config(request_param='type=Salary Deduction', permission='Purchase Return') def purchase_return(self): return self.get_blank() - @view_config(request_param='type=Issue', permission='Issue') def issue(self): voucher_type = self.request.GET.get('type', None) @@ -49,7 +41,8 @@ class blank_voucher_view(object): source = self.request.GET.get('Source', None) destination = self.request.GET.get('Destination', None) if date is not None and source is not None and destination is not None: - return blank_voucher({'Type': voucher_type, 'Date': date, 'Source': source, 'Destination': destination}) + return blank_voucher({'Type': voucher_type, 'Date': date, 'Source': source, 'Destination': destination}, + self.request.dbsession) else: return self.get_blank() @@ -57,8 +50,8 @@ class blank_voucher_view(object): def service_charge(self): voucher_type = self.request.GET.get('type', None) date = self.request.GET.get('Date', None) - if date is not None : - return blank_voucher({'Type': voucher_type, 'Date': date}) + if date is not None: + return blank_voucher({'Type': voucher_type, 'Date': date}, self.request.dbsession) else: return self.get_blank() @@ -69,4 +62,4 @@ class blank_voucher_view(object): additional_info['Date'] = session_current_date(self.request) additional_info['Type'] = voucher_type - return blank_voucher(additional_info) + return blank_voucher(additional_info, self.request.dbsession) diff --git a/brewman/views/services/voucher/issue.py b/brewman/views/services/voucher/issue.py index 5cd346c5..574d43a5 100644 --- a/brewman/views/services/voucher/issue.py +++ b/brewman/views/services/voucher/issue.py @@ -1,19 +1,16 @@ import datetime from decimal import Decimal import uuid -from brewman.models import DBSession from brewman.models.master import CostCentre, LedgerBase from brewman.models.operations import journals_valid, inventory_valid from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal -__author__ = 'tanshu' - -def issue_create_voucher(json, user): +def issue_create_voucher(json, user, dbsession): dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name('Issue')) - DBSession.add(voucher) + dbsession.add(voucher) for item in json['Journals']: if int(item['Debit']) == 1: @@ -22,19 +19,24 @@ def issue_create_voucher(json, user): source = uuid.UUID(item['CostCentre']['CostCentreID']) if source == destination: raise ValidationError("Source cannot be the same as destination") - batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None + if source == CostCentre.cost_centre_purchase(): + batch_consumed = True + elif destination == CostCentre.cost_centre_purchase(): + batch_consumed = False + else: + batch_consumed = None for item in json['Inventories']: - issue_create_inventory(voucher, item, batch_consumed) + issue_create_inventory(voucher, item, batch_consumed, dbsession) for item in issue_create_journals(voucher.inventories, source, destination): voucher.journals.append(item) - DBSession.add(item) + dbsession.add(item) journals_valid(voucher) inventory_valid(voucher) return voucher -def issue_create_inventory(voucher, item, batch_consumed): - batch = Batch.by_id(uuid.UUID(item['Batch']['BatchID'])) +def issue_create_inventory(voucher, item, batch_consumed, dbsession): + batch = dbsession.query(Batch).filter(Batch.id == uuid.UUID(item['Batch']['BatchID'])).first() inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None quantity = round(Decimal(item['Quantity']), 2) @@ -54,7 +56,7 @@ def issue_create_inventory(voucher, item, batch_consumed): item = Inventory(id=inventory_id, product_id=batch.product.id, quantity=quantity, rate=batch.rate, tax=batch.tax, discount=batch.discount, batch=batch) voucher.inventories.append(item) - DBSession.add(item) + dbsession.add(item) def issue_create_journals(inventories, source, destination): @@ -67,7 +69,7 @@ def issue_create_journals(inventories, source, destination): cost_centre_id=destination)] -def issue_update_voucher(voucher, json, user): +def issue_update_voucher(voucher, json, user, dbsession): voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher.narration = json['Narration'] voucher.user_id = user.id @@ -78,7 +80,12 @@ def issue_update_voucher(voucher, json, user): destination = item.cost_centre_id else: source = item.cost_centre_id - old_batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None + if source == CostCentre.cost_centre_purchase(): + old_batch_consumed = True + elif destination == CostCentre.cost_centre_purchase(): + old_batch_consumed = False + else: + old_batch_consumed = None for item in json['Journals']: if int(item['Debit']) == 1: @@ -88,25 +95,31 @@ def issue_update_voucher(voucher, json, user): if source == destination: raise ValidationError("Source cannot be the same as destination") - new_batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None + if source == CostCentre.cost_centre_purchase(): + new_batch_consumed = True + elif destination == CostCentre.cost_centre_purchase(): + new_batch_consumed = False + else: + new_batch_consumed = None + if new_batch_consumed != old_batch_consumed: raise ValidationError("Purchase cost centre cannot be changed") - issue_update_inventory(voucher, json['Inventories'], old_batch_consumed) + issue_update_inventory(voucher, json['Inventories'], old_batch_consumed, dbsession) issue_update_journals(voucher, source, destination) journals_valid(voucher) inventory_valid(voucher) return voucher -def issue_update_inventory(voucher, newInventories, batch_consumed): +def issue_update_inventory(voucher, new_inventories, batch_consumed, dbsession): for it in range(len(voucher.inventories), 0, -1): item = voucher.inventories[it - 1] found = False - for j in range(len(newInventories), 0, -1): - i = newInventories[j - 1] + for j in range(len(new_inventories), 0, -1): + i = new_inventories[j - 1] if 'InventoryID' in i and item.id == uuid.UUID(i['InventoryID']): - batch = Batch.by_id(uuid.UUID(i['Batch']['BatchID'])) + batch = dbsession.query(Batch).filter(Batch.id == uuid.UUID(i['Batch']['BatchID'])).first() found = True if item.batch_id != batch.id: raise ValidationError('Product / Batch cannot be changed') @@ -116,8 +129,10 @@ def issue_update_inventory(voucher, newInventories, batch_consumed): if new_quantity <= 0: raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name)) if batch_consumed is True and new_quantity - old_quantity > quantity_remaining: - raise ValidationError("Maximum quantity available for {0} is {1}".format(item.product.full_name, - old_quantity + quantity_remaining)) + raise ValidationError("Maximum quantity available for {0} is {1}".format( + item.product.full_name, old_quantity + quantity_remaining + ) + ) if item.batch.name > voucher.date: raise ValidationError("Batch of {0} was purchased after the issue date".format(item.product.name)) @@ -133,7 +148,7 @@ def issue_update_inventory(voucher, newInventories, batch_consumed): item.tax = batch.tax item.discount = batch.discount - newInventories.remove(i) + new_inventories.remove(i) break if not found: if batch_consumed is None: @@ -146,10 +161,10 @@ def issue_update_inventory(voucher, newInventories, batch_consumed): "Product {0} cannot be removed, minimum quantity is {1}".format(item.product.name, item.batch.quantity_remaining)) item.batch.quantity_remaining -= item.quantity - DBSession.delete(item) + dbsession.delete(item) voucher.inventories.remove(item) - for i in newInventories: - issue_create_inventory(voucher, i, batch_consumed) + for i in new_inventories: + issue_create_inventory(voucher, i, batch_consumed, dbsession) def issue_update_journals(voucher, source, destination): @@ -165,5 +180,3 @@ def issue_update_journals(voucher, source, destination): else: item.cost_centre_id = destination item.amount = round(amount, 2) - - diff --git a/brewman/views/services/voucher/journal.py b/brewman/views/services/voucher/journal.py index 1d4980cf..ed8be42c 100644 --- a/brewman/views/services/voucher/journal.py +++ b/brewman/views/services/voucher/journal.py @@ -2,70 +2,67 @@ import datetime from decimal import Decimal import uuid -from brewman.models import DBSession from brewman.models.master import LedgerBase from brewman.models.operations import journals_valid from brewman.models.voucher import Journal, Voucher, VoucherType, DbImage -__author__ = 'tanshu' - - -def journal_create_voucher(json, files, user): +def journal_create_voucher(json, files, user, dbsession): dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type'])) - DBSession.add(voucher) + dbsession.add(voucher) for item in json['Journals']: - ledger = LedgerBase.by_id(uuid.UUID(item['Ledger']['LedgerID'])) + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(item['Ledger']['LedgerID'])).first() journal_id = uuid.UUID(item['JournalID']) if 'JournalID' in item else None amount = round(Decimal(item['Amount']), 2) journal = Journal(id=journal_id, amount=amount, debit=int(item['Debit']), ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id) voucher.journals.append(journal) - DBSession.add(journal) + dbsession.add(journal) journals_valid(voucher) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher -def journal_update_voucher(voucher, json, files, user): +def journal_update_voucher(voucher, json, files, user, dbsession): voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher.narration = json['Narration'] voucher.user_id = user.id voucher.posted = False voucher.last_edit_date = datetime.datetime.utcnow() - newJournals = json['Journals'] + new_journals = json['Journals'] for i in range(len(voucher.journals), 0, -1): item = voucher.journals[i - 1] found = False - for i in range(len(newJournals), 0, -1): - j = newJournals[i - 1] - if 'JournalID' in j and item.id == uuid.UUID(j['JournalID']): - ledger = LedgerBase.by_id(uuid.UUID(j['Ledger']['LedgerID'])) + for j in range(len(new_journals), 0, -1): + new_item = new_journals[j - 1] + if 'JournalID' in new_item and item.id == uuid.UUID(new_item['JournalID']): + ledger = dbsession.query(LedgerBase).filter( + LedgerBase.id == uuid.UUID(new_item['Ledger']['LedgerID'])).first() found = True - item.debit = int(j['Debit']) - item.amount = round(Decimal(j['Amount']), 2) + item.debit = int(new_item['Debit']) + item.amount = round(Decimal(new_item['Amount']), 2) item.ledger_id = ledger.id item.cost_centre_id = ledger.cost_centre_id - newJournals.remove(j) + new_journals.remove(new_item) break if not found: voucher.journals.remove(item) - for j in newJournals: - ledger = LedgerBase.by_id(uuid.UUID(j['Ledger']['LedgerID'])) - journal = Journal(id=None, amount=round(Decimal(j['Amount']), 2), debit=int(j['Debit']), ledger_id=ledger.id, + for new_item in new_journals: + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(new_item['Ledger']['LedgerID'])).first() + journal = Journal(id=None, amount=round(Decimal(new_item['Amount']), 2), debit=int(new_item['Debit']), + ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id) - DBSession.add(journal) + dbsession.add(journal) voucher.journals.append(journal) journals_valid(voucher) old_files = [uuid.UUID(f['ID']) for f in json['Files'] if 'ID' in f] - for image in [i for i in DbImage.by_resource_id(voucher.id, 'voucher') if i.id not in old_files]: - DBSession.delete(image) + images = dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all() + for image in [i for i in images if i.id not in old_files]: + dbsession.delete(image) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher - - diff --git a/brewman/views/services/voucher/purchase.py b/brewman/views/services/voucher/purchase.py index e1b41190..1ec08b3b 100644 --- a/brewman/views/services/voucher/purchase.py +++ b/brewman/views/services/voucher/purchase.py @@ -4,37 +4,33 @@ import uuid from sqlalchemy import func -from brewman.models import DBSession from brewman.models.master import Product, LedgerBase from brewman.models.operations import journals_valid, inventory_valid from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal, DbImage -__author__ = 'tanshu' - - -def purchase_create_voucher(json, files, user): +def purchase_create_voucher(json, files, user, dbsession): dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type'])) - DBSession.add(voucher) + dbsession.add(voucher) for item in json['Inventories']: - purchase_create_inventory(voucher, item, dt) - for item in purchase_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']): + purchase_create_inventory(voucher, item, dt, dbsession) + for item in purchase_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID'], dbsession): voucher.journals.append(item) - DBSession.add(item) + dbsession.add(item) journals_valid(voucher) inventory_valid(voucher) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher -def purchase_create_inventory(voucher, item, date): +def purchase_create_inventory(voucher, item, date, dbsession): if 'Product' not in item or 'ProductID' not in item['Product']: raise ValidationError('No Product in item') - product = Product.by_id(uuid.UUID(item['Product']['ProductID'])) + product = dbsession.query(Product).filter(Product.id == uuid.UUID(item['Product']['ProductID'])).first() if product is None: raise ValidationError('No Product in item') inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None @@ -44,20 +40,21 @@ def purchase_create_inventory(voucher, item, date): discount = round(Decimal(item['Discount']), 5) batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax, discount=discount) - DBSession.add(batch) + dbsession.add(batch) inventory = Inventory(id=inventory_id, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax, discount=discount) product.price = rate voucher.inventories.append(inventory) - DBSession.add(inventory) + dbsession.add(inventory) -def purchase_create_journals(inventories, ledgerID): - otherLedger = LedgerBase.by_id(uuid.UUID(ledgerID)) +def purchase_create_journals(inventories, ledger_id, dbsession): + other_ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(ledger_id)).first() journals = dict() amount = 0 for item in inventories: - ledger = Product.by_id(item.product_id).ledger + product = dbsession.query(Product).filter(Product.id == item.product_id).first() + ledger = product.ledger item_amount = round(item.amount, 2) amount += item_amount if ledger.id in journals: @@ -65,39 +62,40 @@ def purchase_create_journals(inventories, ledgerID): else: journals[ledger.id] = Journal(debit=1, cost_centre_id=ledger.cost_centre_id, ledger_id=ledger.id, amount=item_amount) - journals[otherLedger.id] = Journal(debit=-1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id, - amount=amount) + journals[other_ledger.id] = Journal(debit=-1, cost_centre_id=other_ledger.cost_centre_id, ledger_id=other_ledger.id, + amount=amount) return list(journals.values()) -def purchase_update_voucher(voucher, json, files, user): +def purchase_update_voucher(voucher, json, files, user, dbsession): voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher.narration = json['Narration'] voucher.user_id = user.id voucher.posted = False voucher.last_edit_date = datetime.datetime.utcnow() - purchase_update_inventory(voucher, json['Inventories']) - purchase_update_journals(voucher, json['Journals']) + purchase_update_inventory(voucher, json['Inventories'], dbsession) + purchase_update_journals(voucher, json['Journals'], dbsession) journals_valid(voucher) inventory_valid(voucher) old_files = [uuid.UUID(f['ID']) for f in json['Files'] if 'ID' in f] - for image in [i for i in DbImage.by_resource_id(voucher.id, 'voucher') if i.id not in old_files]: - DBSession.delete(image) + images = dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all() + for image in [i for i in images if i.id not in old_files]: + dbsession.delete(image) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher -def purchase_update_inventory(voucher, newInventories): +def purchase_update_inventory(voucher, new_inventories, dbsession): for it in range(len(voucher.inventories), 0, -1): item = voucher.inventories[it - 1] found = False - for j in range(len(newInventories), 0, -1): - i = newInventories[j - 1] + for j in range(len(new_inventories), 0, -1): + i = new_inventories[j - 1] if 'InventoryID' in i and item.id == uuid.UUID(i['InventoryID']): - product = Product.by_id(uuid.UUID(i['Product']['ProductID'])) + product = dbsession.query(Product).filter(Product.id == uuid.UUID(i['Product']['ProductID'])).first() found = True if item.product_id != product.id: raise ValidationError('Product cannot be changed') @@ -126,21 +124,21 @@ def purchase_update_inventory(voucher, newInventories): item.tax = tax item.batch.tax = tax product.price = rate - newInventories.remove(i) + new_inventories.remove(i) # TODO: Update all references of the batch with the new rates break if not found: - uses = DBSession.query(func.count(Inventory.id)) \ + uses = dbsession.query(func.count(Inventory.id)) \ .filter(Inventory.batch_id == item.batch.id) \ .filter(Inventory.id != item.id).scalar() if uses > 0: raise ValidationError("{0} has been issued, it cannot be deleted".format(item.product.name)) else: - DBSession.delete(item.batch) - DBSession.delete(item) + dbsession.delete(item.batch) + dbsession.delete(item) voucher.inventories.remove(item) - for i in newInventories: - product = Product.by_id(uuid.UUID(i['Product']['ProductID'])) + for i in new_inventories: + product = dbsession.query(Product).filter(Product.id == uuid.UUID(i['Product']['ProductID'])).first() new_quantity = round(Decimal(i['Quantity']), 2) rate = round(Decimal(i['Rate']), 2) tax = round(Decimal(i['Tax']), 5) @@ -150,20 +148,22 @@ def purchase_update_inventory(voucher, newInventories): inventory = Inventory(id=None, product_id=product.id, batch=batch, quantity=new_quantity, rate=rate, tax=tax, discount=discount) inventory.voucher_id = voucher.id - DBSession.add(batch) + dbsession.add(batch) inventory.batch_id = batch.id product.price = rate voucher.inventories.append(inventory) - DBSession.add(inventory) + dbsession.add(inventory) -def purchase_update_journals(voucher, journals): +def purchase_update_journals(voucher, journals, dbsession): other_ledger = [ff for ff in journals if ff['Debit'] == -1] - other_ledger = LedgerBase.by_id(uuid.UUID(other_ledger[0]['Ledger']['LedgerID'])) + other_ledger = dbsession.query(LedgerBase).filter( + LedgerBase.id == uuid.UUID(other_ledger[0]['Ledger']['LedgerID'])).first() journals = dict() amount = 0 for item in voucher.inventories: - ledger = Product.by_id(item.product_id).ledger + product = dbsession.query(Product).filter(Product.id == item.product_id).first() + ledger = product.ledger amount += item.amount if ledger.id in journals: journals[ledger.id].amount += item.amount @@ -180,11 +180,9 @@ def purchase_update_journals(voucher, journals): item.cost_centre_id = journals[item.ledger_id].cost_centre_id del journals[item.ledger_id] else: - DBSession.delete(item) + dbsession.delete(item) voucher.journals.remove(item) for item in journals.values(): item.amount = round(item.amount, 2) voucher.journals.append(item) - DBSession.add(item) - - + dbsession.add(item) diff --git a/brewman/views/services/voucher/purchase_return.py b/brewman/views/services/voucher/purchase_return.py index 65c02b4a..4f6f70e4 100644 --- a/brewman/views/services/voucher/purchase_return.py +++ b/brewman/views/services/voucher/purchase_return.py @@ -1,34 +1,32 @@ import datetime from decimal import Decimal import uuid -from brewman.models import DBSession from brewman.models.master import Product, LedgerBase from brewman.models.operations import inventory_valid, journals_valid from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal, DbImage -__author__ = 'tanshu' - -def purchase_return_create_voucher(json, files, user): +def purchase_return_create_voucher(json, files, user, dbsession): dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type'])) - DBSession.add(voucher) + dbsession.add(voucher) for item in json['Inventories']: - purchase_return_create_inventory(voucher, item) - for item in purchase_return_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']): + purchase_return_create_inventory(voucher, item, dbsession) + for item in purchase_return_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID'], + dbsession): voucher.journals.append(item) - DBSession.add(item) + dbsession.add(item) journals_valid(voucher) inventory_valid(voucher) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher -def purchase_return_create_inventory(voucher, item): - batch = Batch.by_id(uuid.UUID(item['Batch']['BatchID'])) +def purchase_return_create_inventory(voucher, item, dbsession): + batch = dbsession.query(Batch).filter(Batch.id == uuid.UUID(item['Batch']['BatchID'])).first() inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None quantity = Decimal(item['Quantity']) @@ -44,54 +42,56 @@ def purchase_return_create_inventory(voucher, item): item = Inventory(id=inventory_id, product_id=batch.product.id, quantity=quantity, rate=batch.rate, tax=batch.tax, discount=batch.discount, batch=batch) voucher.inventories.append(item) - DBSession.add(item) + dbsession.add(item) -def purchase_return_create_journals(inventories, ledgerID): - otherLedger = LedgerBase.by_id(uuid.UUID(ledgerID)) +def purchase_return_create_journals(inventories, ledger_id, dbsession): + other_ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == uuid.UUID(ledger_id)).first() journals = dict() amount = 0 for item in inventories: - ledger = Product.by_id(item.product_id).ledger + product = dbsession.query(Product).filter(Product.id == item.product_id).first() + ledger = product.ledger amount += round(item.amount, 2) if ledger.id in journals: journals[ledger.id].amount += round(item.amount, 2) else: journals[ledger.id] = Journal(debit=-1, cost_centre_id=ledger.cost_centre_id, ledger_id=ledger.id, amount=round(item.amount, 2)) - journals[otherLedger.id] = Journal(debit=1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id, - amount=amount) + journals[other_ledger.id] = Journal(debit=1, cost_centre_id=other_ledger.cost_centre_id, ledger_id=other_ledger.id, + amount=amount) return list(journals.values()) -def purchase_return_update_voucher(voucher, json, files, user): +def purchase_return_update_voucher(voucher, json, files, user, dbsession): voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher.narration = json['Narration'] voucher.user_id = user.id voucher.posted = False voucher.last_edit_date = datetime.datetime.utcnow() - purchase_return_update_inventory(voucher, json['Inventories'], json['Date']) - purchase_return_update_journals(voucher, json['Journals']) + purchase_return_update_inventory(voucher, json['Inventories'], json['Date'], dbsession) + purchase_return_update_journals(voucher, json['Journals'], dbsession) journals_valid(voucher) inventory_valid(voucher) old_files = [uuid.UUID(f['ID']) for f in json['Files'] if 'ID' in f] - for image in [i for i in DbImage.by_resource_id(voucher.id, 'voucher') if i.id not in old_files]: - DBSession.delete(image) + images = dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all() + for image in [i for i in images if i.id not in old_files]: + dbsession.delete(image) for key, value in files.items(): - DBSession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) + dbsession.add(DbImage(voucher.id, 'voucher', value['f'], value['t'])) return voucher -def purchase_return_update_inventory(voucher, newInventories, date): +def purchase_return_update_inventory(voucher, new_inventories, date, dbsession): for it in range(len(voucher.inventories), 0, -1): item = voucher.inventories[it - 1] found = False - for j in range(len(newInventories), 0, -1): - i = newInventories[j - 1] + for j in range(len(new_inventories), 0, -1): + i = new_inventories[j - 1] if 'InventoryID' in i and item.id == uuid.UUID(i['InventoryID']): - product = Product.by_id(uuid.UUID(i['Product']['ProductID'])) + product = dbsession.query(Product).filter(Product.id == uuid.UUID(i['Product']['ProductID'])).first() found = True if item.product_id != product.id: raise ValidationError('Product cannot be changed') @@ -99,37 +99,42 @@ def purchase_return_update_inventory(voucher, newInventories, date): if quantity == 0: raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name)) if quantity - item.quantity > item.batch.quantity_remaining: - raise ValidationError("Maximum quantity available for {0} is {1}".format(item.product.full_name, - item.quantity + item.batch.quantity_remaining)) + raise ValidationError( + "Maximum quantity available for {0} is {1}".format( + item.product.full_name, item.quantity + item.batch.quantity_remaining + ) + ) if item.batch.name > voucher.date: raise ValidationError("Batch of {0} was purchased after the issue date".format(item.product.name)) item.batch.quantity_remaining -= (quantity - item.quantity) item.quantity = quantity - newInventories.remove(i) + new_inventories.remove(i) break if not found: item.batch.quantity_remaining += item.quantity voucher.inventories.remove(item) - DBSession.delete(item) - for i in newInventories: - purchase_return_create_inventory(voucher, i) + dbsession.delete(item) + for i in new_inventories: + purchase_return_create_inventory(voucher, i, dbsession) -def purchase_return_update_journals(voucher, journals): - otherLedger = [ff for ff in journals if ff['Debit'] == 1] - otherLedger = LedgerBase.by_id(uuid.UUID(otherLedger[0]['Ledger']['LedgerID'])) +def purchase_return_update_journals(voucher, journals, dbsession): + other_ledger = [ff for ff in journals if ff['Debit'] == 1] + other_ledger = dbsession.query(LedgerBase).filter( + LedgerBase.id == uuid.UUID(other_ledger[0]['Ledger']['LedgerID'])).first() journals = dict() amount = 0 for item in voucher.inventories: - ledger = Product.by_id(item.product_id).ledger + product = dbsession.query(Product).filter(Product.id == item.product_id).first() + ledger = product.ledger amount += round(item.amount, 2) if ledger.id in journals: journals[ledger.id].amount += round(item.amount, 2) else: journals[ledger.id] = Journal(debit=-1, cost_centre_id=ledger.cost_centre_id, ledger_id=ledger.id, amount=round(item.amount, 2)) - journals[otherLedger.id] = Journal(debit=1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id, - amount=amount) + journals[other_ledger.id] = Journal(debit=1, cost_centre_id=other_ledger.cost_centre_id, ledger_id=other_ledger.id, + amount=amount) for i in range(len(voucher.journals), 0, -1): item = voucher.journals[i - 1] if item.ledger_id in journals: @@ -138,11 +143,9 @@ def purchase_return_update_journals(voucher, journals): item.cost_centre_id = journals[item.ledger_id].cost_centre_id del journals[item.ledger_id] else: - DBSession.delete(item) + dbsession.delete(item) voucher.journals.remove(item) for item in journals.values(): item.amount = item.amount voucher.journals.append(item) - DBSession.add(item) - - + dbsession.add(item) diff --git a/brewman/views/services/voucher/salary_deduction.py b/brewman/views/services/voucher/salary_deduction.py index afb5bd6a..104b6e35 100644 --- a/brewman/views/services/voucher/salary_deduction.py +++ b/brewman/views/services/voucher/salary_deduction.py @@ -1,40 +1,37 @@ import datetime -from decimal import Decimal from math import ceil import uuid -from brewman.models import DBSession from brewman.models.master import LedgerBase, Employee from brewman.models.operations import journals_valid from brewman.models.validation_exception import ValidationError from brewman.models.voucher import Journal, Voucher, VoucherType, SalaryDeduction from brewman.views.services.session import get_last_day -__author__ = 'tanshu' -def salary_deduction_create_voucher(json, user): +def salary_deduction_create_voucher(json, user, dbsession): dt = get_last_day(datetime.datetime.strptime(json['Date'], '%d-%b-%Y')) days_in_month = dt.day voucher = Voucher(date=dt, user_id=user.id, type=VoucherType.by_id(12)) - DBSession.add(voucher) + dbsession.add(voucher) exp, total = 0, 0 for item in json['SalaryDeductions']: - item_exp, item_total = add_salary_deduction(item, days_in_month, voucher) + item_exp, item_total = add_salary_deduction(item, days_in_month, voucher, dbsession) exp += item_exp total += item_total - ledger = LedgerBase.by_id(LedgerBase.esi_pf_expense()) + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == LedgerBase.esi_pf_expense()).first() journal = Journal(amount=exp, debit=1, ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id) - DBSession.add(journal) + dbsession.add(journal) voucher.journals.append(journal) - ledger = LedgerBase.by_id(LedgerBase.esi_pf_payable()) + ledger = dbsession.query(LedgerBase).filter(LedgerBase.id == LedgerBase.esi_pf_payable()).first() journal = Journal(amount=total, debit=-1, ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id) - DBSession.add(journal) + dbsession.add(journal) voucher.journals.append(journal) journals_valid(voucher) return voucher -def salary_deduction_update_voucher(voucher, json, user): +def salary_deduction_update_voucher(voucher, json, user, dbsession): dt = get_last_day(datetime.datetime.strptime(json['Date'], '%d-%b-%Y')) if dt != voucher.date.date(): raise ValidationError("Date Cannot be changed for Salary Deduction voucher!") @@ -43,24 +40,24 @@ def salary_deduction_update_voucher(voucher, json, user): voucher.posted = False voucher.last_edit_date = datetime.datetime.utcnow() - newDeductions = json['SalaryDeductions'] + new_deductions = json['SalaryDeductions'] exp, total, journals = 0, 0, [] for i in range(len(voucher.salary_deductions), 0, -1): item = voucher.salary_deductions[i - 1] found = False - for i in range(len(newDeductions), 0, -1): - j = newDeductions[i - 1] - if 'SalaryDeductionID' in j and item.id == uuid.UUID(j['SalaryDeductionID']): + for j in range(len(new_deductions), 0, -1): + new_item = new_deductions[j - 1] + if 'SalaryDeductionID' in new_item and item.id == uuid.UUID(new_item['SalaryDeductionID']): journals.append(item.journal.id) exp += item.esi_er + item.pf_er total += item.esi_ee + item.pf_ee + item.esi_er + item.pf_er - newDeductions.remove(j) + new_deductions.remove(new_item) break if not found: voucher.salary_deductions.remove(item) voucher.journals.remove(item.journal) - for j in newDeductions: - item_exp, item_total = add_salary_deduction(j, days_in_month, voucher) + for new_item in new_deductions: + item_exp, item_total = add_salary_deduction(new_item, days_in_month, voucher, dbsession) exp += item_exp total += item_total @@ -75,19 +72,19 @@ def salary_deduction_update_voucher(voucher, json, user): return voucher -def add_salary_deduction(item, days_in_month, voucher): - ledger = Employee.by_id(uuid.UUID(item['Journal']['Ledger']['LedgerID'])) +def add_salary_deduction(item, days_in_month, voucher, dbsession): + ledger = dbsession.query(Employee).filter(Employee.id == uuid.UUID(item['Journal']['Ledger']['LedgerID'])).first() gross_salary = int(item['GrossSalary']) days_worked = int(item['DaysWorked']) esi_ee, esi_er, esi_both = esi_contribution(gross_salary, days_worked, days_in_month) pf_ee, pf_er, pf_both = pf_contribution(gross_salary, days_worked, days_in_month) journal = Journal(amount=esi_ee + pf_ee, debit=1, ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id) sd = SalaryDeduction(journal=journal, gross_salary=gross_salary, days_worked=days_worked, esi_ee=esi_ee, - pf_ee=pf_ee, esi_er=esi_er, pf_er=pf_er) + pf_ee=pf_ee, esi_er=esi_er, pf_er=pf_er) voucher.journals.append(journal) voucher.salary_deductions.append(sd) - DBSession.add(journal) - DBSession.add(sd) + dbsession.add(journal) + dbsession.add(sd) return esi_er + pf_er, esi_both + pf_both diff --git a/brewman/views/services/voucher/save_voucher.py b/brewman/views/services/voucher/savevoucher.py similarity index 77% rename from brewman/views/services/voucher/save_voucher.py rename to brewman/views/services/voucher/savevoucher.py index 2caf849f..84bc22f7 100644 --- a/brewman/views/services/voucher/save_voucher.py +++ b/brewman/views/services/voucher/savevoucher.py @@ -15,31 +15,29 @@ from . import service_charge_create_voucher from .purchase_return import purchase_return_create_voucher from .salary_deduction import salary_deduction_create_voucher -__author__ = 'tanshu' - @view_defaults(request_method='POST', route_name='api_voucher', renderer='json', trans=True) -class save_voucher(object): +class SaveVoucher(object): def __init__(self, request): - def parse_post(request): - keys = request.POST.keys() + def parse_post(req): + keys = req.POST.keys() files = {} model = {} for key in keys: if key == 'model': - model = loads(request.POST[key], encoding=request.charset) + model = loads(req.POST[key], encoding=req.charset) else: index = key[1:] if index in files: - files[index][key[:1]] = bytearray(request.POST[key].file.read()) + files[index][key[:1]] = bytearray(req.POST[key].file.read()) else: - files[index] = {key[:1]: bytearray(request.POST[key].file.read())} + files[index] = {key[:1]: bytearray(req.POST[key].file.read())} return model, files self.request = request - self.user = User.by_id(uuid.UUID(request.authenticated_userid)) + self.user = request.dbsession.query(User).filter(User.id == uuid.UUID(request.authenticated_userid)).one() self.json, self.files = parse_post(request) - self.start, self.finish = get_lock_info() + self.start, self.finish = get_lock_info(request.dbsession) self.voucher_date = datetime.datetime.strptime(self.json['Date'], '%d-%b-%Y') @view_config(request_param='type=Journal', permission='Journal') @@ -81,17 +79,18 @@ class save_voucher(object): raise ValidationError("Vouchers after {0} have been locked.".format(self.finish.strftime('%d-%b-%Y'))) if self.json['Type'] in ['Journal', 'Payment', 'Receipt']: - voucher = journal_create_voucher(self.json, self.files, self.user) + voucher = journal_create_voucher(self.json, self.files, self.user, self.request.dbsession) elif self.json['Type'] in ['Purchase']: - voucher = purchase_create_voucher(self.json, self.files, self.user) + voucher = purchase_create_voucher(self.json, self.files, self.user, self.request.dbsession) elif self.json['Type'] in ['Purchase Return']: - voucher = purchase_return_create_voucher(self.json, self.files, self.user) + voucher = purchase_return_create_voucher(self.json, self.files, self.user, self.request.dbsession) elif self.json['Type'] in ['Issue']: - voucher = issue_create_voucher(self.json, self.user) + voucher = issue_create_voucher(self.json, self.user, self.request.dbsession) elif self.json['Type'] in ['Salary Deduction']: - voucher = salary_deduction_create_voucher(self.json, self.user) + voucher = salary_deduction_create_voucher(self.json, self.user, self.request.dbsession) elif self.json['Type'] in ['Service Charge']: - voucher = service_charge_create_voucher(self.json, self.user) + voucher = service_charge_create_voucher(self.json, self.user, self.request.dbsession) transaction.commit() session_current_date_set(self.request, self.json['Date']) - return voucher_info(Voucher.by_id(voucher.id), self.request) + new_voucher = self.request.dbsession.query(Voucher).filter(Voucher.id == voucher.id).first() + return voucher_info(new_voucher, self.request) diff --git a/brewman/views/services/voucher/service_charge.py b/brewman/views/services/voucher/service_charge.py index 721df5de..d8a75cc8 100644 --- a/brewman/views/services/voucher/service_charge.py +++ b/brewman/views/services/voucher/service_charge.py @@ -4,24 +4,21 @@ import uuid from sqlalchemy import or_, func -from brewman.models import DBSession from brewman.models.master import Employee, AttendanceType, Ledger from brewman.models.operations import journals_valid from brewman.models.voucher import Journal, Voucher, VoucherType, Attendance, ServiceCharge from brewman.views.services.session import get_first_day -__author__ = 'tanshu' - - -def service_charge_create_voucher(json, user): +def service_charge_create_voucher(json, user, dbsession): date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher = Voucher(date=date, user_id=user.id, type=VoucherType.by_id(13)) - DBSession.add(voucher) + dbsession.add(voucher) - employees = get_employees(get_first_day(date), date + datetime.timedelta(1), json['ServiceCharges']) - amount = balance(date) * Decimal(.7) * Decimal(.9) + employees = get_employees(get_first_day(date), date + datetime.timedelta(1), json['ServiceCharges'], + dbsession=dbsession) + amount = balance(date, dbsession=dbsession) * Decimal(.7) * Decimal(.9) total_points = 0 for item in employees: @@ -36,27 +33,28 @@ def service_charge_create_voucher(json, user): sc = ServiceCharge(journal=journal, days_worked=item['DaysWorked'], points=item['Points']) voucher.journals.append(journal) voucher.service_charges.append(sc) - DBSession.add(journal) - DBSession.add(sc) + dbsession.add(journal) + dbsession.add(sc) total_amount += item_amount - sc = Ledger.by_id(Ledger.service_charge_id()) + sc = dbsession.query(Ledger).filter(Ledger.id == Ledger.service_charge_id()).first() journal = Journal(amount=total_amount, debit=1, ledger_id=sc.id, cost_centre_id=sc.cost_centre_id) voucher.journals.append(journal) - DBSession.add(journal) + dbsession.add(journal) journals_valid(voucher) return voucher -def service_charge_update_voucher(voucher, json, user): +def service_charge_update_voucher(voucher, json, user, dbsession): date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') voucher.date = date voucher.user_id = user.id voucher.posted = False voucher.last_edit_date = datetime.datetime.utcnow() - employees = get_employees(get_first_day(date), date + datetime.timedelta(1), json['ServiceCharges'], voucher.journals) - amount = balance(date, voucher.id) * Decimal(.7) * Decimal(.9) + employees = get_employees(get_first_day(date), date + datetime.timedelta(1), json['ServiceCharges'], + voucher.journals, dbsession=dbsession) + amount = balance(date, voucher.id, dbsession) * Decimal(.7) * Decimal(.9) total_points = 0 for item in employees: @@ -79,9 +77,9 @@ def service_charge_update_voucher(voucher, json, user): return voucher -def get_employees(start_date, finish_date, json, voucher_employees=None): +def get_employees(start_date, finish_date, json, voucher_employees=None, dbsession=None): details = [] - employees = DBSession().query(Employee) \ + employees = dbsession.query(Employee) \ .filter(Employee.joining_date <= finish_date) \ .filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \ .order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all() @@ -89,7 +87,7 @@ def get_employees(start_date, finish_date, json, voucher_employees=None): check_if_employees_changed(json, employees, voucher_employees) for employee in employees: - att = DBSession.query(Attendance) \ + att = dbsession.query(Attendance) \ .filter(Attendance.employee_id == employee.id) \ .filter(Attendance.date >= start_date) \ .filter(Attendance.date < finish_date) \ @@ -104,8 +102,8 @@ def get_employees(start_date, finish_date, json, voucher_employees=None): return details -def balance(date, voucher_id=None): - amount = DBSession.query(func.sum(Journal.amount * Journal.debit)) \ +def balance(date, voucher_id=None, dbsession=None): + amount = dbsession.query(func.sum(Journal.amount * Journal.debit)) \ .join(Journal.voucher) \ .filter(Voucher.date < date + datetime.timedelta(1)) \ .filter(Voucher.type != VoucherType.by_name('Issue').id) \ @@ -129,4 +127,4 @@ def check_if_employees_changed(json, db, voucher): if len(json) != len(db) != len(voucher): raise ValueError("Employee missing in json data") if len(json ^ db) != 0 or len(db ^ voucher) != 0: - raise ValueError("Employee missing in json data") \ No newline at end of file + raise ValueError("Employee missing in json data") diff --git a/brewman/views/services/voucher/update_voucher.py b/brewman/views/services/voucher/updatevoucher.py similarity index 79% rename from brewman/views/services/voucher/update_voucher.py rename to brewman/views/services/voucher/updatevoucher.py index 5e14e473..7dc06f05 100644 --- a/brewman/views/services/voucher/update_voucher.py +++ b/brewman/views/services/voucher/updatevoucher.py @@ -1,12 +1,11 @@ import datetime -from json import loads +import transaction import uuid +from json import loads from pyramid.response import Response from pyramid.view import view_defaults, view_config -import transaction -from brewman import groupfinder from brewman.models.auth import User from brewman.models.voucher import Voucher from brewman.views import get_lock_info @@ -16,11 +15,9 @@ from . import service_charge_update_voucher from brewman.views.services.voucher.purchase_return import purchase_return_update_voucher from brewman.views.services.voucher.salary_deduction import salary_deduction_update_voucher -__author__ = 'tanshu' - @view_defaults(request_method='POST', route_name='api_voucher_id', renderer='json', trans=True) -class update_voucher(object): +class UpdateVoucher(object): def __init__(self, request): def parse_post(request): keys = request.POST.keys() @@ -38,18 +35,18 @@ class update_voucher(object): return model, files self.request = request - self.user = User.by_id(uuid.UUID(request.authenticated_userid)) - self.voucher = Voucher.by_id(uuid.UUID(request.matchdict.get('id', None))) + self.user = request.dbsession.query(User).filter(User.id == uuid.UUID(request.authenticated_userid)).one() + self.voucher = self.request.dbsession.query(Voucher).filter( + Voucher.id == uuid.UUID(request.matchdict['id'])).first() self.json, self.files = parse_post(request) - self.start, self.finish = get_lock_info() + self.start, self.finish = get_lock_info(request.dbsession) self.voucher_date = datetime.datetime.strptime(self.json['Date'], '%d-%b-%Y') - permissions = groupfinder(self.user.id, self.request) - if self.voucher.posted and not 'Edit Posted Vouchers' in permissions: + if self.voucher.posted and not request.has_permission('Edit Posted Vouchers'): response = Response("You are not allowed to edit posted vouchers") response.status_int = 403 self.error = response - elif self.voucher.user_id != self.user.id and "Edit Other User's Vouchers" not in permissions: + elif self.voucher.user_id != self.user.id and not request.has_permission("Edit Other User's Vouchers"): response = Response("You are not allowed to edit other user's vouchers") response.status_int = 403 self.error = response @@ -100,17 +97,20 @@ class update_voucher(object): if self.error is not None: return self.error if self.json['Type'] in ['Journal', 'Payment', 'Receipt']: - voucher = journal_update_voucher(self.voucher, self.json, self.files, self.user) + voucher = journal_update_voucher(self.voucher, self.json, self.files, self.user, self.request.dbsession) elif self.json['Type'] in ['Purchase']: - voucher = purchase_update_voucher(self.voucher, self.json, self.files, self.user) + voucher = purchase_update_voucher(self.voucher, self.json, self.files, self.user, self.request.dbsession) elif self.json['Type'] in ['Purchase Return']: - voucher = purchase_return_update_voucher(self.voucher, self.json, self.files, self.user) + voucher = purchase_return_update_voucher( + self.voucher, self.json, self.files, self.user, self.request.dbsession + ) elif self.json['Type'] in ['Issue']: - voucher = issue_update_voucher(self.voucher, self.json, self.user) + voucher = issue_update_voucher(self.voucher, self.json, self.user, self.request.dbsession) elif self.json['Type'] in ['Salary Deduction']: - voucher = salary_deduction_update_voucher(self.voucher, self.json, self.user) + voucher = salary_deduction_update_voucher(self.voucher, self.json, self.user, self.request.dbsession) elif self.json['Type'] in ['Service Charge']: - voucher = service_charge_update_voucher(self.voucher, self.json, self.user) + voucher = service_charge_update_voucher(self.voucher, self.json, self.user, self.request.dbsession) transaction.commit() session_current_date_set(self.request, self.json['Date']) - return voucher_info(Voucher.by_id(voucher.id), self.request) + new_voucher = self.request.dbsession.query(Voucher).filter(Voucher.id == voucher.id).first() + return voucher_info(new_voucher, self.request) diff --git a/setup.py b/setup.py index ac2ed98b..de38fa35 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ with open(os.path.join(here, 'CHANGES.txt')) as f: requires = [ 'pyramid', 'waitress', + 'pyramid_tm', 'transaction', 'zope.sqlalchemy', 'SQLAlchemy', @@ -18,7 +19,7 @@ requires = [ ] setup(name='brewman', - version='3.3', + version='4.0', description='brewman', long_description=README + '\n\n' + CHANGES, classifiers=[