Feature: Credit Service Charge with adjustable service points

Refactor: Renamed column, table, and uses of Cost Center to Cost Centre
Refactor: Renamed costcenter to cost_centre
This commit is contained in:
tanshu committed 2015-02-12 17:42:46 +05:30
1 parent fdcedb262c
commit 6a815692bd
58 files changed
+822 -505

No files matched your search

+3 -2
View File
@@ -59,7 +59,7 @@ def main(global_config, **settings):
config.add_route('api_account_type_list', '/api/AccountTypes')
add_route(config, 'cost_center', '/CostCenter')
add_route(config, 'cost_centre', '/CostCentre')
add_route(config, 'account', '/Account')
add_route(config, 'employee', '/Employee')
add_route(config, 'user', '/User')
@@ -84,6 +84,8 @@ def main(global_config, **settings):
config.add_route('api_issues_grid', '/api/Issues/Services/{date}')
config.add_route('salary_deduction_id', '/SalaryDeduction/{id}')
config.add_route('salary_deduction', '/SalaryDeduction')
config.add_route('service_charge_id', '/ServiceCharge/{id}')
config.add_route('service_charge', '/ServiceCharge')
config.add_route('db_image', '/api/DbImage/{id}/{type}')
config.add_route('api_voucher_id', '/api/Voucher/{id}')
@@ -106,7 +108,6 @@ def main(global_config, **settings):
config.add_route('attendance_report', '/AttendanceReport')
config.add_route('api_credit_salary', '/api/CreditSalary')
config.add_route('api_credit_service_charge', '/api/CreditServiceCharge')
config.add_route('employee_functions', '/EmployeeFunctions')
config.add_route('api_fingerprint', '/api/Fingerprint')
+8 -7
View File
@@ -27,7 +27,7 @@ def fixtures(engine):
import uuid
from brewman.models.messaging import Tag, Thread, Subscriber, thread_tag, Post
from brewman.models.voucher import Attendance, Batch, Fingerprint, Inventory, Journal, Product, SalaryDeduction, Voucher, VoucherType
from brewman.models.master import Product, AttendanceType, CostCenter, Employee, Ledger, LedgerBase, LedgerType, ProductGroup, MenuItem, Recipe, RecipeItem
from brewman.models.master import Product, AttendanceType, CostCentre, Employee, Ledger, LedgerBase, LedgerType, ProductGroup, MenuItem, Recipe, RecipeItem
from brewman.models.auth import Client, Group, Role, User, role_group, user_group, LoginHistory
Base.metadata.create_all(engine)
@@ -46,7 +46,7 @@ def fixtures(engine):
roles = [Role('Attendance', uuid.UUID('09d05434-a09a-fa45-963b-769a2e3fc667')),
Role('Trial Balance', uuid.UUID('3b099fec-ddc5-4243-b30e-afb78d9ca14a')),
Role('Cash Flow', uuid.UUID('c4d3ae29-420b-ea4c-ae90-00a356263fd9')),
Role('Cost Centers', uuid.UUID('6fcc1a20-6aec-e840-b334-1632b34aeab8')),
Role('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')),
@@ -84,18 +84,19 @@ def fixtures(engine):
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_centers = [CostCenter('Overall', uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), True),
CostCenter('Purchase', uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3'), True),
CostCenter('Kitchen', uuid.UUID('b2d398ce-e3cc-c542-9feb-5d7783e899df'), True)]
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_center in cost_centers:
DBSession.add(cost_center)
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),
+19 -15
View File
@@ -197,15 +197,15 @@ class ProductGroup(Base):
return uuid.UUID('e6bf81b9-1e9b-499f-81d5-ab5662e9d9b1')
class CostCenter(Base):
__tablename__ = 'cost_centers'
class CostCentre(Base):
__tablename__ = 'cost_centres'
id = Column('CostCenterID', GUID(), primary_key=True, default=uuid.uuid4)
id = Column('CostCentreID', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('Name', Unicode(255), unique=True)
is_fixture = Column('IsFixture', Boolean, nullable=False)
ledgers = relationship('LedgerBase', backref='costcenter')
journals = relationship('Journal', backref='costcenter')
ledgers = relationship('LedgerBase', backref='cost_centre')
journals = relationship('Journal', backref='cost_centre')
@property
def __name__(self):
@@ -225,20 +225,20 @@ class CostCenter(Base):
return DBSession.query(cls).order_by(cls.name).all()
@classmethod
def cost_center_purchase(cls):
def cost_centre_purchase(cls):
return uuid.UUID('7b845f95-dfef-fa4a-897c-f0baf15284a3')
@classmethod
def cost_center_kitchen(cls):
def cost_centre_kitchen(cls):
return uuid.UUID('b2d398ce-e3cc-c542-9feb-5d7783e899df')
@classmethod
def cost_center_overall(cls):
def cost_centre_overall(cls):
return uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d')
@classmethod
def overall(cls):
return {'CostCenterID': uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), 'Name': 'Overall'}
return {'CostCentreID': uuid.UUID('36f59436-522a-0746-ae94-e0f746bf6c0d'), 'Name': 'Overall'}
class LedgerBase(Base):
@@ -251,7 +251,7 @@ class LedgerBase(Base):
ledger_type = Column('ledger_type', Unicode(50), nullable=False)
is_active = Column('IsActive', Boolean)
is_reconcilable = Column('IsReconcilable', Boolean)
costcenter_id = Column('CostCenterID', GUID(), ForeignKey('cost_centers.CostCenterID'))
cost_centre_id = Column('CostCentreID', GUID(), ForeignKey('cost_centres.CostCentreID'))
is_fixture = Column('IsFixture', Boolean, nullable=False)
__mapper_args__ = {'polymorphic_on': ledger_type}
@@ -266,14 +266,14 @@ class LedgerBase(Base):
def type_object(self):
return LedgerType.by_id(self.type)
def __init__(self, code=None, name=None, type=None, is_active=None, is_reconcilable=False, costcenter_id=None,
def __init__(self, code=None, name=None, type=None, is_active=None, is_reconcilable=False, cost_centre_id=None,
id=None, is_fixture=False):
self.code = code
self.name = name
self.type = type
self.is_active = is_active
self.is_reconcilable = is_reconcilable
self.costcenter_id = costcenter_id
self.cost_centre_id = cost_centre_id
self.id = id
self.is_fixture = is_fixture
@@ -351,6 +351,10 @@ class LedgerBase(Base):
def service_charge(cls):
return {'LedgerID': 'b7eff754-e8ba-e047-ab06-9132c15c7640', 'Name': 'Service Charges'}
@classmethod
def service_charge_id(cls):
return uuid.UUID('b7eff754-e8ba-e047-ab06-9132c15c7640')
@classmethod
def esi_pf_expense(cls):
return uuid.UUID('d2a1a286-e900-764b-a1a5-9f4b00dbb940')
@@ -378,7 +382,7 @@ class Employee(LedgerBase):
attendances = relationship('Attendance', backref='employee', cascade=None, cascade_backrefs=False)
fingerprints = relationship('Fingerprint', backref='employee', cascade=None, cascade_backrefs=False)
def __init__(self, code=None, name=None, is_active=None, costcenter_id=None, designation=None, salary=None,
def __init__(self, code=None, name=None, is_active=None, cost_centre_id=None, designation=None, salary=None,
service_points=None, joining_date=None, leaving_date=None):
self.designation = designation
self.salary = salary
@@ -386,7 +390,7 @@ class Employee(LedgerBase):
self.joining_date = joining_date
self.leaving_date = leaving_date
super().__init__(code=code, name=name, type=10, is_active=is_active, is_reconcilable=False,
costcenter_id=costcenter_id)
cost_centre_id=cost_centre_id)
def create(self):
code = DBSession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0]
@@ -403,7 +407,7 @@ class Employee(LedgerBase):
@classmethod
def list(cls):
return DBSession.query(Employee).order_by(desc(Employee.is_active)).order_by(Ledger.costcenter_id).order_by(
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
+5 -5
View File
@@ -1,4 +1,4 @@
from brewman.models.master import CostCenter
from brewman.models.master import CostCentre
from brewman.models.validation_exception import ValidationError
__author__ = 'tanshu'
@@ -36,7 +36,7 @@ def check_batch_insert(voucher):
# Issue
purchase = None
for item in voucher.journals:
if item.cost_center_id == CostCenter.cost_center_purchase():
if item.cost_centre_id == CostCentre.cost_centre_purchase():
purchase = item
if purchase == None:
return
@@ -54,7 +54,7 @@ def check_batch_insert(voucher):
def issue_new(voucher):
consuming = filter(lambda x: x.cost_center_id == CostCenter.cost_center_purchase(), voucher.journals)
consuming = filter(lambda x: x.cost_centre_id == CostCentre.cost_centre_purchase(), voucher.journals)
if not len(consuming):
consuming = False
elif consuming[0].debit == 1:
@@ -74,7 +74,7 @@ def issue_new(voucher):
def issue_update(voucher):
consuming = filter(lambda x: x.cost_center_id == CostCenter.cost_center_purchase(), voucher.journals)
consuming = filter(lambda x: x.cost_centre_id == CostCentre.cost_centre_purchase(), voucher.journals)
if not len(consuming):
consuming = False
elif consuming[0].debit == 1:
@@ -150,7 +150,7 @@ def journals_valid(voucher):
def is_distinct_journal(journals):
found = set()
for item in journals:
itemHash = hash(item.ledger_id) ^ hash(item.cost_center_id)
itemHash = hash(item.ledger_id) ^ hash(item.cost_centre_id)
if itemHash in found:
raise ValidationError("Duplicate journals")
else:
+28 -6
View File
@@ -2,9 +2,8 @@ from datetime import datetime
import uuid
from sqlalchemy.dialects.postgresql import BYTEA
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy import Column, Integer, Boolean, Unicode, DateTime, Numeric, ForeignKey, UniqueConstraint, Index
from sqlalchemy import Column, Integer, Boolean, Unicode, DateTime, Numeric, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship, synonym, backref
from brewman.models.guidtype import GUID
@@ -32,6 +31,7 @@ class VoucherType:
list.append(VoucherType(10, 'Opening Balance'))
list.append(VoucherType(11, 'Closing Balance'))
list.append(VoucherType(12, 'Salary Deduction'))
list.append(VoucherType(13, 'Service Charge'))
return list
@classmethod
@@ -72,7 +72,8 @@ class Voucher(Base):
inventories = relationship('Inventory', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False)
salary_deductions = relationship('SalaryDeduction', backref='voucher', cascade="delete, delete-orphan",
cascade_backrefs=False)
service_charges = relationship('ServiceCharge', backref='voucher', cascade="delete, delete-orphan",
cascade_backrefs=False)
def _get_type(self):
@@ -128,7 +129,7 @@ class Journal(Base):
amount = Column('Amount', Numeric)
voucher_id = Column('VoucherID', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False, index=True)
ledger_id = Column('LedgerID', GUID(), ForeignKey('ledgers.LedgerID'), nullable=False)
cost_center_id = Column('CostCenterID', GUID(), ForeignKey('cost_centers.CostCenterID'), nullable=False)
cost_centre_id = Column('CostCentreID', GUID(), ForeignKey('cost_centres.CostCentreID'), nullable=False)
@hybrid_property
def signed_amount(self):
@@ -138,13 +139,13 @@ class Journal(Base):
def __name__(self):
return self.name
def __init__(self, id=None, debit=None, amount=None, voucher_id=None, ledger_id=None, cost_center_id=None):
def __init__(self, id=None, debit=None, amount=None, voucher_id=None, ledger_id=None, cost_centre_id=None):
self.id = id
self.debit = debit
self.amount = amount
self.voucher_id = voucher_id
self.ledger_id = ledger_id
self.cost_center_id = cost_center_id
self.cost_centre_id = cost_centre_id
@classmethod
def by_id(cls, id):
@@ -189,6 +190,27 @@ class SalaryDeduction(Base):
self.journal = journal
class ServiceCharge(Base):
__tablename__ = 'service_charges'
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
voucher_id = Column('voucher_id', GUID(), ForeignKey('vouchers.VoucherID'), nullable=False)
journal_id = Column('journal_id', GUID(), ForeignKey('journals.JournalID'), nullable=False)
days_worked = Column('days_worked', Integer, nullable=False)
points = Column('points', Numeric(precision=5, scale=2), nullable=False)
journal = relationship(Journal, backref=backref('service_charge', uselist=False), cascade=None,
cascade_backrefs=False)
def __init__(self, id=None, voucher_id=None, journal_id=None, journal=None, days_worked=None, points=None):
self.id = id
self.voucher_id = voucher_id
self.journal_id = journal_id
self.days_worked = days_worked
self.points = points
if journal_id is None and journal is not None:
self.journal = journal
class Inventory(Base):
__tablename__ = 'inventories'
__table_args__ = (UniqueConstraint('VoucherID', 'BatchID'), )
+5 -3
View File
@@ -43,6 +43,7 @@
<script src="/js/angular-route.min.js"></script>
<script src="/js/angular-sanitize.min.js"></script>
<script src="/js/loading-bar.min.js"></script>
<script src="/js/ui-bootstrap-custom-0.12.0.min.js"></script>
<script src="/script/overlord.js"></script>
<script src="/script/angular_directive.js"></script>
@@ -53,7 +54,6 @@
<script src="/script/login.js"></script>
<script src="/script/settings.js"></script>
<script src="/script/message.js"></script>
<script src="/js/ui-bootstrap-custom-0.12.0.min.js"></script>
<script src="/script/journal.js"></script>
<script src="/script/payment.js"></script>
@@ -62,6 +62,7 @@
<script src="/script/purchase-return.js"></script>
<script src="/script/issue.js"></script>
<script src="/script/salary-deduction.js"></script>
<script src="/script/service-charge.js"></script>
<script src="/script/employee-attendance.js"></script>
<script src="/script/employee-functions.js"></script>
@@ -88,7 +89,7 @@
<script src="/script/user.js"></script>
<script src="/script/group.js"></script>
<script src="/script/client.js"></script>
<script src="/script/cost-center.js"></script>
<script src="/script/cost-centre.js"></script>
<script src="/script/product.js"></script>
<script src="/script/product-group.js"></script>
@@ -171,6 +172,7 @@
<li><a href="/EmployeeAttendance">Employee Attendance</a></li>
<li><a href="/EmployeeFunctions">Employee Functions</a></li>
<li><a href="/SalaryDeduction">Credit Esi / Pf</a></li>
<li><a href="/ServiceCharge">Service Charges</a></li>
<li><a href="/AccountsTesting/Employees/SalarySheet.aspx">Salary Sheet</a></li>
<li><a href="/AccountsTesting/Employees/PaymentSheet.aspx">Employee Payment Sheet</a></li>
<li><a href="/features/elements.html">Display Salary Sheet</a></li>
@@ -182,7 +184,7 @@
class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/Accounts">Accounts</a></li>
<li><a href="/CostCenters">Cost Centers</a></li>
<li><a href="/CostCentres">Cost Centres</a></li>
<li><a href="/Products">Products</a></li>
<li><a href="/Recipes">Recipes</a></li>
<li><a href="/ProductGroups">Product Groups</a></li>
+3 -3
View File
@@ -37,11 +37,11 @@
</div>
</div>
<div class="form-group">
<label for="ddlCostCenter" class="col-md-2 control-label">Cost Center</label>
<label for="ddlCostCentre" class="col-md-2 control-label">Cost Centre</label>
<div class="col-md-10">
<select id="ddlCostCenter" class="form-control" ng-model="account.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in costCenters"> </select>
<select id="ddlCostCentre" class="form-control" ng-model="account.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in costCentres"> </select>
</div>
</div>
+2 -2
View File
@@ -18,7 +18,7 @@
<th>Type</th>
<th>Is Active?</th>
<th>Is Reconcilable?</th>
<th>Cost Center</th>
<th>Cost Centre</th>
</tr>
</thead>
<tbody>
@@ -28,7 +28,7 @@
<td>{{item.Type}}</td>
<td>{{item.IsActive}}</td>
<td>{{item.IsReconcilable}}</td>
<td>{{item.CostCenter}}</td>
<td>{{item.CostCentre}}</td>
</tr>
</tbody>
</table>
@@ -1,11 +1,11 @@
<form class="form-horizontal" role=form>
<h2>Cost Center Detail</h2>
<h2>Cost Centre Detail</h2>
<div class="form-group">
<label for="txtName" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="txtName" class="form-control" ng-model="costCenter.Name" focus-on="foName"/>
<input type="text" id="txtName" class="form-control" ng-model="costCentre.Name" focus-on="foName"/>
</div>
</div>
<div class="form-group">
@@ -1,4 +1,4 @@
<h2>Cost Centers <a href="/CostCenter" class="btn btn-success pull-right">Add <i class="glyphicon glyphicon-plus"></i></a></h2>
<h2>Cost Centres <a href="/CostCentre" class="btn btn-success pull-right">Add <i class="glyphicon glyphicon-plus"></i></a></h2>
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
+4 -4
View File
@@ -16,7 +16,7 @@
</div>
</div>
<div class="form-group">
<label for="txtDesignation" class="col-md-2 control-label">Name</label>
<label for="txtDesignation" class="col-md-2 control-label">Designation</label>
<div class="col-md-10">
<input type="text" id="txtDesignation" class="form-control" ng-model="employee.Designation"/>
@@ -46,11 +46,11 @@
</div>
</div>
<div class="form-group">
<label for="ddlCostCenter" class="col-md-2 control-label">Cost Center</label>
<label for="ddlCostCentre" class="col-md-2 control-label">Cost Centre</label>
<div class="col-md-10">
<select id="ddlCostCenter" class="form-control" ng-model="employee.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in costCenters"> </select>
<select id="ddlCostCentre" class="form-control" ng-model="employee.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in costCentres"> </select>
</div>
</div>
@@ -19,37 +19,6 @@
</button>
</div>
</div>
<h2>Credit Service Charge</h2>
<div class="form-group">
<label for="txtScMonth" class="col-md-2 control-label">Month</label>
<div class="col-md-3">
<div class="input-group">
<input id="txtScMonth" type="text" class="form-control" datepicker-popup="dd-MMM-yyyy"
datepicker-mode="month" is-open="scmOpen" ng-focus="scmOpen = true" ng-model="sc.Month"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<label for="txtScCreditDate" class="col-md-2 control-label">Credit Date</label>
<div class="col-md-3">
<div class="input-group">
<input id="txtScCreditDate" type="text" class="form-control" datepicker-popup="dd-MMM-yyyy"
is-open="sccdOpen" ng-focus="sccdOpen = true" ng-model="sc.CreditDate"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<div class="col-md-2">
<button class="btn btn-block btn-success" tan-click="creditServiceCharge()">Credit <i
class="glyphicon glyphicon-screenshot"></i>
</button>
</div>
</div>
<h2>Attendance Record</h2>
<div class="form-group">
+1 -1
View File
@@ -30,7 +30,7 @@
<td>{{item.Designation}}</td>
<td>{{item.Salary}}</td>
<td>{{item.ServicePoints}}</td>
<td>{{item.CostCenter}}</td>
<td>{{item.CostCentre}}</td>
<td>{{item.JoiningDate}}</td>
<td>{{item.LeavingDate}}</td>
</tr>
@@ -0,0 +1,76 @@
<form class="form-horizontal" role=form id="form">
<h2>Employee Service Charge</h2>
<div class="form-group">
<label for="txtDate" class="col-md-2 control-label">Date</label>
<div class="col-md-10">
<div class="input-group">
<input class="form-control" id="txtDate" type="text" datepicker-popup="dd-MMM-yyyy"
is-open="dOpen" ng-focus="dOpen = true" ng-model="voucher.Date"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
</div>
<div class="form-group">
<label for="txtInfo" class="col-md-2 control-label"></label>
<div class="col-md-10">
Total Service Charge: <strong>{{voucher.ServiceCharge | number:2}}</strong>
Total Points: <strong>{{TotalPoints() | number:2}}</strong>
Point Value: <strong>{{PointValue() | number:2}}</strong>
</div>
</div>
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Designation</th>
<th>Department</th>
<th>Days Worked</th>
<th>Service Points</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="serviceCharge in voucher.ServiceCharges">
<td>{{serviceCharge.Name}}</td>
<td>{{serviceCharge.Designation}}</td>
<td>{{serviceCharge.Department}}</td>
<td>{{serviceCharge.DaysWorked}}</td>
<td>
<div class="input-group">
<span class="input-group-btn" style="width:auto">
<button class="btn btn-danger" ng-click="less(serviceCharge)"><i class="glyphicon glyphicon-minus"></i></button>
</span>
<input type="number" class="form-control" ng-model="serviceCharge.Points" step=".25">
<span class="input-group-btn" style="width:auto">
<button class="btn btn-success" ng-click="more(serviceCharge)"><i class="glyphicon glyphicon-plus"></i></button>
</span>
</div>
</td>
<td class="text-right">{{employeeAmount(serviceCharge) | number:0}}</td>
</tr>
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" tan-click="save()" ng-disabled="preventAlteration(voucher)">
{{voucher.VoucherID | save_button}}
</button>
<button class="btn btn-inverse" tan-click="post()" ng-hide="!voucher.VoucherID"
ng-disabled="voucher.Posted || !perms['Post Vouchers']">{{voucher.Posted | posted}}
</button>
<button class="btn btn-danger" ng-hide="!voucher.VoucherID" ng-disabled="preventAlteration(voucher)"
ng-click="confirm()">Delete
</button>
</div>
</div>
<div class="col-md-offset-2 col-md-10">
<small>Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}}
by {{voucher.User.Name}}. Posted by {{voucher.Poster}}
</small>
</div>
</form>
+4 -4
View File
@@ -29,13 +29,13 @@
</div>
</div>
<div class="col-md-3" ng-repeat="journal in voucher.Journals | journalDebit:-1">
<select id="ddlSourceCostCenter" class="form-control" ng-model="journal.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in costCenters"> </select>
<select id="ddlSourceCostCentre" class="form-control" ng-model="journal.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in costCentres"> </select>
</div>
<div class="col-md-5" ng-repeat="journal in voucher.Journals | journalDebit:1">
<div class="input-group">
<select id="ddlDestinationCostCenter" class="form-control" ng-model="journal.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in costCenters"> </select>
<select id="ddlDestinationCostCentre" class="form-control" ng-model="journal.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in costCentres"> </select>
<span class="input-group-addon">₹</span>
<input type="text" class="form-control" placeholder="Amount" value="{{journal.Amount | number:2}}"/>
</div>
@@ -29,7 +29,7 @@
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Cost Center</th>
<th>Cost Centre</th>
<th>Issue</th>
<th>Sale</th>
<th>Rmc</th>
+1 -1
View File
@@ -52,7 +52,7 @@
<tr ng-repeat="deduction in voucher.SalaryDeductions">
<td>{{deduction.Journal.Ledger.Name}}</td>
<td>{{deduction.Journal.Ledger.Designation}}</td>
<td>{{deduction.Journal.Ledger.CostCenter.Name}}</td>
<td>{{deduction.Journal.Ledger.CostCentre.Name}}</td>
<td>{{deduction.GrossSalary}}</td>
<td>{{deduction.DaysWorked}}</td>
<td>{{deduction.EsiEmployee}}</td>
+6 -6
View File
@@ -18,7 +18,7 @@ var AccountListController = ['$scope', '$location', '$routeParams', 'Tokenizer',
't': {'Col': 'Type', 'Comparator': 'text'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
'r': {'Col': 'IsReconcilable', 'Comparator': 'boolean'},
'c': {'Col': 'CostCenter', 'Comparator': 'text'}
'c': {'Col': 'CostCentre', 'Comparator': 'text'}
},
def: 'n',
sorter: {
@@ -26,7 +26,7 @@ var AccountListController = ['$scope', '$location', '$routeParams', 'Tokenizer',
't': 'Type',
'a': 'IsActive',
'r': 'IsReconcilable',
'c': 'CostCenter'
'c': 'CostCentre'
}
};
$scope.filterAccounts = _.debounce(function (q) {
@@ -76,11 +76,11 @@ AccountListController.resolve = {
}]
};
var AccountController = ['$scope', '$location', '$modal', 'account', 'accountTypes', 'costCenters', function ($scope, $location, $modal, account, accountTypes, costCenters) {
var AccountController = ['$scope', '$location', '$modal', 'account', 'accountTypes', 'costCentres', function ($scope, $location, $modal, account, accountTypes, costCentres) {
$scope.account = account;
$scope.accountTypes = accountTypes;
$scope.costCenters = costCenters;
$scope.costCentres = costCentres;
$scope.save = function () {
$scope.account.$save(function () {
@@ -131,7 +131,7 @@ AccountController.resolve = {
accountTypes: ['AccountType', function (AccountType) {
return AccountType.query({}).$promise;
}],
costCenters: ['CostCenter', function (CostCenter) {
return CostCenter.query({}).$promise;
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};
+29 -6
View File
@@ -85,9 +85,9 @@ overlordService.factory('ProductLedger', ['$resource', function ($resource) {
return $resource('/api/ProductLedger/:id');
}]);
overlordService.factory('CostCenter', ['$resource', function ($resource) {
return $resource('/api/CostCenter/:id',
{id: '@CostCenterID'}, {
overlordService.factory('CostCentre', ['$resource', function ($resource) {
return $resource('/api/CostCentre/:id',
{id: '@CostCentreID'}, {
query: {method: 'GET', params: {list: true}, isArray: true}
});
}]);
@@ -139,9 +139,9 @@ overlordService.factory('ProductGroup', ['$resource', function ($resource) {
});
}]);
overlordService.factory('CostCenter', ['$resource', function ($resource) {
return $resource('/api/CostCenter/:id',
{id: '@CostCenterID'}, {
overlordService.factory('CostCentre', ['$resource', function ($resource) {
return $resource('/api/CostCentre/:id',
{id: '@CostCentreID'}, {
query: {method: 'GET', params: {list: true}, isArray: true}
});
}]);
@@ -270,6 +270,29 @@ overlordService.factory('Tokenizer', ['$filter', function ($filter) {
return obj.toLowerCase().indexOf(text) > -1;
}
},
'date': function (obj, text) {
var reGoodDate = /^((0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012]|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[- /.](19|20)?[0-9]{2})*$/i,
asDateObject = function (input) {
if (angular.isDate(input)) {
return input;
}
},
op = opLength(text),
ob = op ? asDateObject(obj) : '',
tex = op ? asDateObject(text.substr(op).trim()) : '';
if (op) {
return operators[text.substr(0, op)](ob, tex);
} else {
return obj.toString().indexOf(text) > -1;
}
if (text.indexOf('!') === 0) {
return obj.toLowerCase().indexOf(text.substr(1)) <= -1;
} else {
return obj.toLowerCase().indexOf(text) > -1;
}
},
'boolean': function (obj, text) {
return obj === isTrue(text);
},
-41
View File
@@ -1,41 +0,0 @@
'use strict';
var CostCenterListController = ['$scope', 'costCenters', function ($scope, costCenters) {
$scope.info = costCenters;
}];
CostCenterListController.resolve = {
costCenters: ['CostCenter', function (CostCenter) {
return CostCenter.query({}).$promise;
}]
};
var CostCenterController = ['$scope', '$routeParams', '$location', 'costCenter', function ($scope, $routeParams, $location, costCenter) {
$scope.costCenter = costCenter;
$scope.save = function () {
$scope.costCenter.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCenters')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.costCenter.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCenters')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.foName = true;
}];
CostCenterController.resolve = {
costCenter: ['$route', 'CostCenter', function ($route, CostCenter) {
var id = $route.current.params.id;
return CostCenter.get({id: id}).$promise;
}]
};
+41
View File
@@ -0,0 +1,41 @@
'use strict';
var CostCentreListController = ['$scope', 'costCentres', function ($scope, costCentres) {
$scope.info = costCentres;
}];
CostCentreListController.resolve = {
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};
var CostCentreController = ['$scope', '$routeParams', '$location', 'costCentre', function ($scope, $routeParams, $location, costCentre) {
$scope.costCentre = costCentre;
$scope.save = function () {
$scope.costCentre.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCentres')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.costCentre.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCentres')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.foName = true;
}];
CostCentreController.resolve = {
costCentre: ['$route', 'CostCentre', function ($route, CostCentre) {
var id = $route.current.params.id;
return CostCentre.get({id: id}).$promise;
}]
};
@@ -17,25 +17,6 @@ var EmployeeFunctionsController = ['$scope', '$http', 'asDateFilter', function (
});
};
$scope.creditServiceCharge = function () {
if (!angular.isDate($scope.sc.Month)) {
return;
}
var ServiceChargeMonth = asDate($scope.sc.Month);
if (!angular.isDate($scope.sc.CreditDate)) {
return;
}
var CreditDate = asDate($scope.sc.CreditDate);
return $http.
post('/api/CreditServiceCharge', {Month: ServiceChargeMonth, CreditDate: CreditDate}).
success(function (data) {
$scope.toasts.push({Type: 'Success', Message: data.message});
}).
error(function (errorMessage) {
$scope.toasts.push({Type: 'Danger', Message: errorMessage});
});
};
$scope.attendanceRecordUrl = function () {
if (!$scope.record.StartDate || !$scope.record.FinishDate) {
return;
+6 -6
View File
@@ -19,7 +19,7 @@ var EmployeeListController = ['$scope', '$location', '$routeParams', 'Tokenizer'
's': {'Col': 'Salary', 'Comparator': 'numeric'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
'des': {'Col': 'Designation', 'Comparator': 'text'},
'dep': {'Col': 'CostCenter', 'Comparator': 'text'}
'dep': {'Col': 'CostCentre', 'Comparator': 'text'}
},
def: 'n',
sorter: {
@@ -28,7 +28,7 @@ var EmployeeListController = ['$scope', '$location', '$routeParams', 'Tokenizer'
's': 'Salary',
'a': 'IsActive',
'des': 'Designation',
'dep': 'CostCenter'
'dep': 'CostCentre'
}
};
$scope.filterEmployees = _.debounce(function (q) {
@@ -79,10 +79,10 @@ EmployeeListController.resolve = {
}]
};
var EmployeeController = ['$scope', '$routeParams', '$location', 'asDateFilter', '$modal', 'employee', 'costCenters', function ($scope, $routeParams, $location, asDate, $modal, employee, costCenters) {
var EmployeeController = ['$scope', '$routeParams', '$location', 'asDateFilter', '$modal', 'employee', 'costCentres', function ($scope, $routeParams, $location, asDate, $modal, employee, costCentres) {
$scope.employee = employee;
$scope.costCenters = costCenters;
$scope.costCentres = costCentres;
$scope.save = function () {
$scope.employee.JoiningDate = asDate($scope.employee.JoiningDate);
@@ -132,7 +132,7 @@ EmployeeController.resolve = {
var id = $route.current.params.id;
return Employee.get({id: id}).$promise;
}],
costCenters: ['CostCenter', function (CostCenter) {
return CostCenter.query({}).$promise;
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};
+5 -5
View File
@@ -1,8 +1,8 @@
'use strict';
var IssueController = ['$scope', '$routeParams', '$location', 'asDateFilter', 'voucher', 'costCenters', 'smallGrid', 'IssueGrid', 'Voucher', '$modal', 'Batch', function ($scope, $routeParams, $location, asDate, voucher, costCenters, smallGrid, IssueGrid, Voucher, $modal, Batch) {
var IssueController = ['$scope', '$routeParams', '$location', 'asDateFilter', 'voucher', 'costCentres', 'smallGrid', 'IssueGrid', 'Voucher', '$modal', 'Batch', function ($scope, $routeParams, $location, asDate, voucher, costCentres, smallGrid, IssueGrid, Voucher, $modal, Batch) {
$scope.voucher = voucher;
$scope.costCenters = costCenters;
$scope.costCentres = costCentres;
$scope.smallGrid = smallGrid;
if (angular.isUndefined($routeParams.Source) && angular.isUndefined($routeParams.Destination) && angular.isUndefined($routeParams.id)) {
@@ -81,7 +81,7 @@ var IssueController = ['$scope', '$routeParams', '$location', 'asDateFilter', 'v
function getDebitCredit(journals, type) {
for (var i = 0, l = journals.length; i < l; i++) {
if (journals[i].Debit === type) {
return journals[i].CostCenter.CostCenterID;
return journals[i].CostCentre.CostCentreID;
}
}
}
@@ -279,8 +279,8 @@ IssueController.resolve = {
return [];
}
}],
costCenters: ['CostCenter', function (CostCenter) {
return CostCenter.query({}).$promise;
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};
+6 -3
View File
@@ -28,6 +28,9 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/SalaryDeduction', {templateUrl: '/partial/salary-deduction.html', controller: SalaryDeductionController, resolve: SalaryDeductionController.resolve}).
when('/SalaryDeduction/:id', {templateUrl: '/partial/salary-deduction.html', controller: SalaryDeductionController, resolve: SalaryDeductionController.resolve}).
when('/ServiceCharge', {templateUrl: '/partial/employee-service-charge.html', controller: ServiceChargeController, resolve: ServiceChargeController.resolve}).
when('/ServiceCharge/:id', {templateUrl: '/partial/employee-service-charge.html', controller: ServiceChargeController, resolve: ServiceChargeController.resolve}).
when('/Ledger', {templateUrl: '/partial/ledger.html', controller: LedgerController, resolve: LedgerController.resolve}).
when('/Ledger/:id', {templateUrl: '/partial/ledger.html', controller: LedgerController, resolve: LedgerController.resolve}).
@@ -75,9 +78,9 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/Employee', {templateUrl: '/partial/employee-detail.html', controller: EmployeeController, resolve: EmployeeController.resolve}).
when('/Employee/:id', {templateUrl: '/partial/employee-detail.html', controller: EmployeeController, resolve: EmployeeController.resolve}).
when('/CostCenters', {templateUrl: '/partial/cost-center-list.html', controller: CostCenterListController, resolve: CostCenterListController.resolve}).
when('/CostCenter', {templateUrl: '/partial/cost-center-detail.html', controller: CostCenterController, resolve: CostCenterController.resolve}).
when('/CostCenter/:id', {templateUrl: '/partial/cost-center-detail.html', controller: CostCenterController, resolve: CostCenterController.resolve}).
when('/CostCentres', {templateUrl: '/partial/cost-centre-list.html', controller: CostCentreListController, resolve: CostCentreListController.resolve}).
when('/CostCentre', {templateUrl: '/partial/cost-centre-detail.html', controller: CostCentreController, resolve: CostCentreController.resolve}).
when('/CostCentre/:id', {templateUrl: '/partial/cost-centre-detail.html', controller: CostCentreController, resolve: CostCentreController.resolve}).
when('/Products', {templateUrl: '/partial/product-list.html', controller: ProductListController, resolve: ProductListController.resolve, reloadOnSearch:false}).
when('/Product', {templateUrl: '/partial/product-detail.html', controller: ProductController, resolve: ProductController.resolve}).
+114
View File
@@ -0,0 +1,114 @@
'use strict';
var ServiceChargeController = ['$scope', '$location', '$routeParams', 'numberFilter', 'asDateFilter', '$modal', 'voucher', function ($scope, $location, $routeParams, numberFilter, asDate, $modal, voucher) {
$scope.voucher = voucher;
$scope.TotalPoints = function (){
return _($scope.voucher.ServiceCharges).map(function (item) {
return item.DaysWorked * Number(item.Points);
}).reduce(function (sum, item) {
return sum + item;
});
};
$scope.PointValue = function () {
return Math.round($scope.voucher.ServiceCharge * 100 / $scope.TotalPoints()) / 100;
};
$scope.less = function (employee) {
if (employee.Points >= 1) {
employee.Points -= 1;
}
};
$scope.more = function (employee) {
employee.Points += 1;
};
$scope.$watch('voucher.Date', function (newDate, oldDate) {
var nDate = asDate(newDate),
oDate = asDate(oldDate);
if (nDate !== oDate && !angular.isUndefined(nDate)) {
if (angular.isUndefined($routeParams.id)) {
return voucher.$get({type: 'Service Charge', Date: nDate}).$promise;
}
}
}, true);
$scope.employeeAmount = function (employee) {
return Number(employee.Points) * employee.DaysWorked * $scope.PointValue();
}
$scope.preventAlteration = function (voucher) {
if (angular.isUndefined($scope.perms)) {
return false;
} else if (angular.isUndefined(voucher.VoucherID)) {
return !$scope.perms['Service Charge'];
} else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) {
return true;
} else if (voucher.User.UserID !== $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) {
return true;
} else {
return false;
}
};
$scope.save = function () {
$scope.voucher.Date = asDate($scope.voucher.Date);
$scope.voucher.$save({type: 'Service Charge'}, function (u) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/ServiceCharge/' + u.VoucherID);
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.voucher.$delete(function () {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/ServiceCharge').replace();
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.post = function () {
$scope.voucher.$post(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.confirm = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.title = "Delete Voucher";
$scope.body = "Are you sure? This cannot be undone.";
$scope.isDelete = true;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
$scope.delete();
});
};
}];
ServiceChargeController.resolve = {
voucher: ['$route', 'Voucher', function ($route, Voucher) {
var id = $route.current.params.id;
if (angular.isUndefined(id)) {
return Voucher.get({type: 'Service Charge'}).$promise;
} else {
return Voucher.get({id: id}).$promise;
}
}]
};
+9 -10
View File
@@ -2,14 +2,13 @@ import datetime
from decimal import Decimal
import uuid
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import func, and_, distinct
from sqlalchemy.orm import aliased
import transaction
from brewman.models import DBSession
from brewman.models.master import LedgerBase, CostCenter, Ledger, Employee
from brewman.models.master import LedgerBase, CostCentre, Ledger, Employee
from brewman.models.validation_exception import TryCatchFunction
from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, \
Attendance, DbImage
@@ -21,10 +20,10 @@ __author__ = 'tanshu'
@view_config(request_method='POST', route_name='api_rebase', renderer='json', permission='Rebase')
@TryCatchFunction
def rebase(request):
DBSession.execute('SET statement_timeout TO 300000;')
# 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(authenticated_userid(request))
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)
@@ -37,7 +36,7 @@ def rebase(request):
for i in voucher_b.inventories:
DBSession.add(i)
cleanup_lint(date, accounts, batches)
DBSession.execute('RESET statement_timeout;')
# DBSession.execute('RESET statement_timeout;')
transaction.commit()
return {}
@@ -60,12 +59,12 @@ def opening_ledgers(date, user_id):
if ledger.type_object.balance_sheet and ledger.id != LedgerBase.suspense() and amount != 0:
running_total += amount
journal = Journal(amount=abs(amount), debit=-1 if amount < 0 else 1, ledger_id=ledger.id,
cost_center_id=ledger.costcenter_id)
cost_centre_id=ledger.cost_centre_id)
voucher.journals.append(journal)
accounts.append(ledger.id)
if running_total != 0:
journal = Journal(amount=abs(amount), debit=-1 if amount * -1 < 0 else 1, ledger_id=LedgerBase.suspense(),
cost_center_id=CostCenter.cost_center_overall())
cost_centre_id=CostCentre.cost_centre_overall())
voucher.journals.append(journal)
return voucher, accounts
@@ -77,7 +76,7 @@ def opening_batches(date, user_id):
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_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.having(sum_func != 0) \
.group_by(Batch).all()
@@ -93,9 +92,9 @@ def opening_batches(date, user_id):
voucher.inventories.append(inventory)
batches.append(batch.id)
voucher.journals.append(Journal(amount=abs(total), debit=-1, ledger_id=LedgerBase.all_purchases(),
cost_center_id=CostCenter.cost_center_overall()))
cost_centre_id=CostCentre.cost_centre_overall()))
voucher.journals.append(Journal(amount=abs(total), debit=1, ledger_id=LedgerBase.all_purchases(),
cost_center_id=CostCenter.cost_center_purchase()))
cost_centre_id=CostCentre.cost_centre_purchase()))
return voucher, batches
+12 -10
View File
@@ -1,22 +1,24 @@
import datetime
from decimal import Decimal
import uuid
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import func
import transaction
from brewman.models import DBSession
from brewman.models.master import LedgerBase, CostCenter, Product
from brewman.models.master import LedgerBase, CostCentre, Product
from brewman.models.validation_exception import TryCatchFunction, 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')
@TryCatchFunction
def rebase(request):
user_id = uuid.UUID(authenticated_userid(request))
user_id = uuid.UUID(request.authenticated_userid)
product = Product.by_id(uuid.UUID(request.matchdict['id']))
quantity = round(Decimal(request.GET['Quantity']), 2)
@@ -47,7 +49,7 @@ def get_closing_stock(product, finish_date=None):
.filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product.id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase())
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase())
if finish_date is not None:
query = query.filter(Voucher.date <= finish_date)
query = query.one()
@@ -74,11 +76,11 @@ def create_voucher(batch, quantity, date, user_id):
DBSession.add(voucher)
if quantity > 0:
source = CostCenter.cost_center_overall()
destination = CostCenter.cost_center_purchase()
source = CostCentre.cost_centre_overall()
destination = CostCentre.cost_centre_purchase()
else:
destination = CostCenter.cost_center_overall()
source = CostCenter.cost_center_purchase()
destination = CostCentre.cost_centre_overall()
source = CostCentre.cost_centre_purchase()
inventory = Inventory(product_id=batch.product.id, quantity=abs(quantity), rate=batch.rate, tax=batch.tax,
discount=batch.discount, batch=batch)
@@ -86,9 +88,9 @@ def create_voucher(batch, quantity, date, user_id):
DBSession.add(inventory)
amount = round(inventory.amount, 2)
source = Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_center_id=source)
source = Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_centre_id=source)
voucher.journals.append(source)
DBSession.add(source)
destination = Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_center_id=destination)
destination = Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=amount, cost_centre_id=destination)
voucher.journals.append(destination)
DBSession.add(destination)
+9 -10
View File
@@ -1,15 +1,14 @@
import uuid
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy.orm import joinedload_all
import transaction
from brewman import groupfinder
from brewman.models import DBSession
from brewman.models.master import CostCenter, Ledger, LedgerType, LedgerBase
from brewman.models.master import CostCentre, Ledger, LedgerType, LedgerBase
from brewman.models.validation_exception import ValidationError, TryCatchFunction
from brewman.models.voucher import Voucher, Journal, VoucherType
@@ -28,7 +27,7 @@ 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'],
costcenter_id=uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create()
cost_centre_id=uuid.UUID(request.json_body['CostCentre']['CostCentreID'])).create()
transaction.commit()
return account_info(item.id)
@@ -46,7 +45,7 @@ def update(request):
item.name = request.json_body['Name']
item.is_active = request.json_body['IsActive']
item.is_reconcilable = request.json_body['IsReconcilable']
item.costcenter_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
item.cost_centre_id = uuid.UUID(request.json_body['CostCentre']['CostCentreID'])
transaction.commit()
return account_info(item.id)
@@ -54,7 +53,7 @@ def update(request):
@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(authenticated_userid(request), request))
can_delete, reason = account.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request))
if can_delete:
delete_with_data(account)
transaction.commit()
@@ -83,7 +82,7 @@ def show_list(request):
ledgers = []
for item in list:
ledgers.append({'Name': item.name, 'Type': item.type_object.name, 'IsActive': 'Yes' if item.is_active else 'No',
'IsReconcilable': 'Yes' if item.is_reconcilable else '', 'CostCenter': item.costcenter.name,
'IsReconcilable': 'Yes' if item.is_reconcilable else '', 'CostCentre': item.cost_centre.name,
'IsFixture': item.is_fixture, 'Url': request.route_url('account_id', id=item.id)})
return ledgers
@@ -121,13 +120,13 @@ def account_type_list(request):
def account_info(id):
if id is None:
account = {'Code': '(Auto)', 'Type': LedgerType.by_name('Creditors').id, 'IsActive': True,
'IsReconcilable': False, 'CostCenter': CostCenter.overall()}
'IsReconcilable': False, 'CostCentre': CostCentre.overall()}
else:
account = Ledger.by_id(id)
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,
'CostCenter': {'CostCenterID': account.costcenter_id, 'Name': account.costcenter.name}}
'CostCentre': {'CostCentreID': account.cost_centre_id, 'Name': account.cost_centre.name}}
return account
+8 -5
View File
@@ -1,11 +1,12 @@
import datetime
import uuid
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid
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, TryCatchFunction
@@ -13,8 +14,10 @@ from brewman.models.voucher import Attendance
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')
@@ -51,7 +54,7 @@ def attendance_date_report(date):
employees = DBSession().query(Employee) \
.filter(Employee.joining_date <= date) \
.filter(or_(Employee.is_active, Employee.leaving_date >= date)) \
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
.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(
Attendance.date == date).filter(Attendance.is_valid == True).first()
@@ -59,7 +62,7 @@ def attendance_date_report(date):
prints, hours, worked = get_prints(item.id, date)
report['Body'].append({'id': item.id, 'Code': item.code, 'Name': item.name, 'Designation': item.designation,
'Department': item.costcenter.name, 'AttendanceTypeID': att, 'Prints': prints,
'Department': item.cost_centre.name, 'AttendanceTypeID': att, 'Prints': prints,
'Hours': hours, 'Worked': worked})
return report
@@ -67,7 +70,7 @@ def attendance_date_report(date):
@view_config(request_method='POST', route_name='api_attendance_date', renderer='json', permission='Attendance')
@TryCatchFunction
def save(request):
user_id = uuid.UUID(authenticated_userid(request))
user_id = uuid.UUID(request.authenticated_userid)
date = request.matchdict.get('date', None)
date_object = datetime.datetime.strptime(date, '%d-%b-%Y')
@@ -129,7 +132,7 @@ def employee_attendance(employee, start_date, finish_date):
def save_employee_attendance(request):
start_date = None
finish_date = None
user_id = uuid.UUID(authenticated_userid(request))
user_id = uuid.UUID(request.authenticated_userid)
employee = Employee.by_id(uuid.UUID(request.matchdict['id']))
for item in request.json_body['Body']:
if start_date is None:
+2 -2
View File
@@ -29,9 +29,9 @@ def attendance_record(start_date, finish_date):
employees = DBSession().query(Employee)\
.filter(Employee.joining_date <= finish_date)\
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))\
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
.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.costcenter.name, employee.salary,
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):
+3 -6
View File
@@ -1,22 +1,21 @@
import re
import uuid
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
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 TryCatchFunction, ValidationError
class UserView(object):
def __init__(self, request):
self.request = request
self.user = authenticated_userid(request)
self.user = request.authenticated_userid
self.permissions = None
self.has_permission = False
if self.user is not None:
@@ -117,8 +116,6 @@ class UserView(object):
def show_name(self):
list = User.query().filter(User.locked_out == False).order_by(User.name).all()
users = [{'Name': item.name} for item in list]
# for item in list:
# users.append({'Name': item.name})
return users
-87
View File
@@ -1,87 +0,0 @@
import uuid
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.master import CostCenter
from brewman.models.validation_exception import ValidationError, TryCatchFunction
@view_config(route_name='cost_center_list', permission='Authenticated')
@view_config(request_method='GET', route_name='cost_center_id', permission='Cost Centers')
@view_config(request_method='GET', route_name='cost_center', permission='Cost Centers')
def html(request):
package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_cost_center', renderer='json', permission='Cost Centers')
@TryCatchFunction
def save(request):
item = CostCenter(request.json_body['Name'])
DBSession.add(item)
transaction.commit()
return cost_center_info(item.id)
@view_config(request_method='POST', route_name='api_cost_center_id', renderer='json', permission='Cost Centers')
@TryCatchFunction
def update(request):
item = CostCenter.by_id(uuid.UUID(request.matchdict['id']))
if item.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
item.name = request.json_body['Name']
transaction.commit()
return cost_center_info(item.id)
@view_config(request_method='DELETE', route_name='api_cost_center_id', renderer='json', permission='Cost Centers')
def delete(request):
item = request.matchdict.get('id', None)
item = None if item is None else CostCenter.by_id(uuid.UUID(item))
if item is None:
response = Response("Cost Center not found")
response.status_int = 500
return response
elif item.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
else:
response = Response("Cost Center deletion not implemented")
response.status_int = 500
return response
@view_config(request_method='GET', route_name='api_cost_center_id', renderer='json', permission='Cost Centers')
def show_id(request):
return cost_center_info(uuid.UUID(request.matchdict.get('id', None)))
@view_config(request_method='GET', route_name='api_cost_center', renderer='json', permission='Cost Centers')
def show_blank(request):
return cost_center_info(None)
@view_config(request_method='GET', route_name='api_cost_center', request_param='list', renderer='json',
permission='Authenticated')
def show_list(request):
list = CostCenter.list()
cost_centers = []
for item in list:
cost_centers.append({'CostCenterID': item.id, 'Name': item.name, 'IsFixture': item.is_fixture,
'Url': request.route_url('cost_center_id', id=item.id)})
return cost_centers
def cost_center_info(id):
if id is None:
return {}
else:
cost_center = CostCenter.by_id(id)
return {'CostCenterID': cost_center.id, 'Name': cost_center.name, 'IsFixture': cost_center.is_fixture}
+87
View File
@@ -0,0 +1,87 @@
import uuid
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.master import CostCentre
from brewman.models.validation_exception import ValidationError, TryCatchFunction
@view_config(route_name='cost_centre_list', permission='Authenticated')
@view_config(request_method='GET', route_name='cost_centre_id', permission='Cost Centres')
@view_config(request_method='GET', route_name='cost_centre', permission='Cost Centres')
def html(request):
package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
return FileResponse(file, request=request)
@view_config(request_method='POST', route_name='api_cost_centre', renderer='json', permission='Cost Centres')
@TryCatchFunction
def save(request):
item = CostCentre(request.json_body['Name'])
DBSession.add(item)
transaction.commit()
return cost_centre_info(item.id)
@view_config(request_method='POST', route_name='api_cost_centre_id', renderer='json', permission='Cost Centres')
@TryCatchFunction
def update(request):
item = CostCentre.by_id(uuid.UUID(request.matchdict['id']))
if item.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
item.name = request.json_body['Name']
transaction.commit()
return cost_centre_info(item.id)
@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))
if item is None:
response = Response("Cost Centre not found")
response.status_int = 500
return response
elif item.is_fixture:
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
else:
response = Response("Cost Centre deletion not implemented")
response.status_int = 500
return response
@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)))
@view_config(request_method='GET', route_name='api_cost_centre', renderer='json', permission='Cost Centres')
def show_blank(request):
return cost_centre_info(None)
@view_config(request_method='GET', route_name='api_cost_centre', request_param='list', renderer='json',
permission='Authenticated')
def show_list(request):
list = CostCentre.list()
cost_centres = []
for item in list:
cost_centres.append({'CostCentreID': item.id, 'Name': item.name, 'IsFixture': item.is_fixture,
'Url': request.route_url('cost_centre_id', id=item.id)})
return cost_centres
def cost_centre_info(id):
if id is None:
return {}
else:
cost_centre = CostCentre.by_id(id)
return {'CostCentreID': cost_centre.id, 'Name': cost_centre.name, 'IsFixture': cost_centre.is_fixture}
+3 -4
View File
@@ -1,15 +1,14 @@
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import func
from brewman import groupfinder
from brewman.models import DBSession
from brewman.models.master import LedgerBase
from brewman.models.validation_exception import TryCatchFunction
from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish, session_period_start, session_current_date
from brewman.views.services.session import session_period_finish, session_period_start
@view_config(route_name='dashboard', permission='Authenticated')
@@ -22,7 +21,7 @@ def html(request):
@view_config(route_name='api_dashboard', renderer='json')
@TryCatchFunction
def dashboard(request):
user = authenticated_userid(request)
user = request.authenticated_userid
if user is None or 'Dashboard' not in groupfinder(user, request):
return {'Enabled': False}
start_date = request.GET.get('s', session_period_start(request))
+11 -12
View File
@@ -1,17 +1,16 @@
import datetime
import uuid
from decimal import Decimal
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy.orm import joinedload_all
import transaction
from brewman import groupfinder
from brewman.models import DBSession
from brewman.models.master import CostCenter, Employee, LedgerBase, Ledger
from brewman.models.master import CostCentre, Employee, LedgerBase, Ledger
from brewman.models.validation_exception import ValidationError, TryCatchFunction
from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views import to_uuid
@@ -34,7 +33,7 @@ def save(request):
if name == '':
raise ValidationError('Name cannot be blank')
cost_center_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
cost_centre_id = uuid.UUID(request.json_body['CostCentre']['CostCentreID'])
designation = request.json_body.get('Designation', '').strip()
try:
@@ -67,7 +66,7 @@ def save(request):
except (ValueError, KeyError, TypeError):
raise ValidationError("Leaving Date is not a valid date")
item = Employee(0, name, is_active, cost_center_id, designation, salary, service_points, joining_date,
item = Employee(0, name, is_active, cost_centre_id, designation, salary, service_points, joining_date,
leaving_date).create()
transaction.commit()
return employee_info(item.id)
@@ -84,7 +83,7 @@ def update(request):
if item.name == '':
raise ValidationError('Name cannot be blank')
item.costcenter_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
item.cost_centre_id = uuid.UUID(request.json_body['CostCentre']['CostCentreID'])
item.designation = request.json_body.get('Designation', '').strip()
try:
@@ -125,7 +124,7 @@ def update(request):
@TryCatchFunction
def delete(request):
employee = Employee.by_id(uuid.UUID(request.matchdict['id']))
can_delete, reason = employee.can_delete('Advanced Delete' in groupfinder(authenticated_userid(request), request))
can_delete, reason = employee.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request))
if can_delete:
delete_with_data(employee)
transaction.commit()
@@ -160,7 +159,7 @@ def show_list(request):
ledgers.append(
{'Code': item.code, 'Name': item.name, 'Designation': item.designation, 'Salary': item.salary,
'ServicePoints': item.service_points, 'IsActive': item.is_active,
'CostCenter': item.costcenter.name, 'Url': request.route_url('employee_id', id=item.id),
'CostCentre': item.cost_centre.name, 'Url': request.route_url('employee_id', id=item.id),
'JoiningDate': item.joining_date.strftime('%d-%b-%Y'),
'LeavingDate': '' if item.is_active else item.leaving_date.strftime('%d-%b-%Y')})
return ledgers
@@ -177,7 +176,7 @@ def show_term(request):
list = []
for index, item in enumerate(LedgerBase.list(10, filter)):
list.append({'LedgerID': item.id, 'Name': item.name, 'Designation': item.designation,
'CostCenter': {'CostCenterID': item.costcenter.id, 'Name': item.costcenter.name}})
'CostCentre': {'CostCentreID': item.cost_centre.id, 'Name': item.cost_centre.name}})
if count is not None and index == count - 1:
break
return list
@@ -185,7 +184,7 @@ def show_term(request):
def employee_info(id):
if id is None:
employee = {'Code': '(Auto)', 'IsActive': True, 'CostCenter': CostCenter.overall()}
employee = {'Code': '(Auto)', 'IsActive': True, 'CostCentre': CostCentre.overall()}
else:
employee = Employee.by_id(id)
if employee is None:
@@ -194,7 +193,7 @@ def employee_info(id):
'IsActive': employee.is_active, 'Designation': employee.designation, 'Salary': employee.salary,
'ServicePoints': employee.service_points, 'JoiningDate': employee.joining_date.strftime('%d-%b-%Y'),
'LeavingDate': None if employee.is_active else employee.leaving_date.strftime('%d-%b-%Y'),
'CostCenter': {'CostCenterID': employee.costcenter_id, 'Name': employee.costcenter.name}}
'CostCentre': {'CostCentreID': employee.cost_centre_id, 'Name': employee.cost_centre.name}}
return employee
+7 -9
View File
@@ -1,16 +1,14 @@
import datetime
import uuid
import pkg_resources
from pyramid.response import FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy.orm import joinedload_all
import transaction
from brewman import groupfinder
from brewman.models import DBSession
from brewman.models.auth import User
from brewman.models.messaging import Thread, Post, Tag, Subscriber
from brewman.models.tzinfoutc import get_age
from brewman.models.validation_exception import TryCatchFunction, ValidationError
@@ -27,7 +25,7 @@ def html(request):
@view_config(request_method='POST', route_name='api_message', renderer='json', permission='Authenticated')
@TryCatchFunction
def save(request):
user_id = uuid.UUID(authenticated_userid(request))
user_id = uuid.UUID(request.authenticated_userid)
user_name = User.by_id(user_id).name
title = request.json_body['Title'].strip()
if Thread.by_title(title) is not None:
@@ -60,7 +58,7 @@ def save(request):
@view_config(request_method='POST', route_name='api_message_id', renderer='json', permission='Authenticated')
@TryCatchFunction
def update(request):
user_id = uuid.UUID(authenticated_userid(request))
user_id = uuid.UUID(request.authenticated_userid)
user_name = User.by_id(user_id).name
super_user = 'Messages' in groupfinder(user_id, request)
thread = Thread.by_id(uuid.UUID(request.matchdict['id']))
@@ -127,14 +125,14 @@ def update(request):
@view_config(request_method='GET', route_name='api_message', renderer='json', permission='Authenticated')
def show_blank(request):
user = User.by_id(authenticated_userid(request)).name
user = User.by_id(request.authenticated_userid).name
return {'Title': '', 'User': user, 'Tags': [], 'Priority': 4, 'Public': False,
'Posts': [], 'Closed': False, 'Subscribers': [user]}
@view_config(request_method='GET', route_name='api_message_id', renderer='json', permission='Authenticated')
def show_id(request):
user_id = authenticated_userid(request) and uuid.UUID(authenticated_userid(request))
user_id = request.authenticated_userid and uuid.UUID(request.authenticated_userid)
thread = Thread.by_id(request.matchdict['id'])
subscriber = [s for s in thread.subscribers if s.user_id == user_id]
if len(subscriber) > 0:
@@ -146,7 +144,7 @@ def show_id(request):
@view_config(request_method='GET', route_name='api_message', renderer='json', request_param='list')
def show_list(request):
user_id = authenticated_userid(request) and uuid.UUID(authenticated_userid(request))
user_id = request.authenticated_userid and uuid.UUID(request.authenticated_userid)
list = Thread.query()
type = request.params.get('type', 'open')
+1 -2
View File
@@ -3,7 +3,6 @@ import uuid
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import desc
from sqlalchemy.orm import joinedload_all
@@ -109,7 +108,7 @@ def update(request):
@TryCatchFunction
def delete(request):
product = Product.by_id(uuid.UUID(request.matchdict['id']))
can_delete, reason = product.can_delete('Advanced Delete' in groupfinder(authenticated_userid(request), request))
can_delete, reason = product.can_delete('Advanced Delete' in groupfinder(request.authenticated_userid, request))
if can_delete:
delete_with_data(product)
+4 -4
View File
@@ -6,7 +6,7 @@ from sqlalchemy.sql.expression import func
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import Product, CostCenter
from brewman.models.master import Product, CostCentre
from brewman.models.voucher import Voucher, Journal, Inventory
from brewman.views.services.session import session_period_finish
@@ -38,7 +38,7 @@ def build_report(date):
query = DBSession.query(Product, quantity_sum, amount_sum) \
.join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \
.filter(Voucher.date <= date) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.group_by(Product) \
.order_by(amount_sum.desc()).all()
@@ -54,7 +54,7 @@ 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_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.scalar()
return 0 if opening_stock is None else opening_stock
@@ -63,6 +63,6 @@ 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_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.scalar()
return 0 if closing_stock is None else closing_stock
+5 -5
View File
@@ -8,7 +8,7 @@ import uuid
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import Product, CostCenter
from brewman.models.master import Product, CostCentre
from brewman.models.validation_exception import ValidationError, TryCatchFunction
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
@@ -62,18 +62,18 @@ def build_report(request, info):
query = DBSession.query(Voucher, Inventory, Journal).options(
joinedload(Journal.ledger, innerjoin=True),
joinedload(Journal.costcenter, innerjoin=True)) \
joinedload(Journal.cost_centre, innerjoin=True)) \
.filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product_id) \
.filter(Journal.cost_center_id != CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id != CostCentre.cost_centre_purchase()) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
for row in query:
journalDebit = row.Journal.debit * -1
name = row.Journal.costcenter.name if row.Voucher.type == VoucherType.by_name(
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
@@ -108,7 +108,7 @@ def opening_balance(product_id, start_date):
.filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product_id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.one()
+1 -1
View File
@@ -6,7 +6,7 @@ from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import CostCenter, LedgerType, LedgerBase
from brewman.models.master import CostCentre, LedgerType, LedgerBase
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish
+2 -2
View File
@@ -6,7 +6,7 @@ from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import CostCenter, Product
from brewman.models.master import CostCentre, Product
from brewman.models.voucher import Voucher, Journal, Inventory, VoucherType
from brewman.views.services.session import session_period_start, session_period_finish
@@ -42,7 +42,7 @@ def build_report(request, start_date, finish_date):
.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) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.group_by(Product).order_by(desc(amount_sum)).all()
total_amount = 0
+10 -10
View File
@@ -7,7 +7,7 @@ from sqlalchemy.sql.expression import func, case
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import LedgerBase, CostCenter, Product, ProductGroup
from brewman.models.master import LedgerBase, CostCentre, Product, ProductGroup
from brewman.models.voucher import Voucher, Journal, Inventory
from brewman.views.services.session import session_period_start, session_period_finish
@@ -50,24 +50,24 @@ def build_report(request, start_date, finish_date):
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')
query = DBSession.query(CostCenter, sum_issue, sum_sale) \
.join(CostCenter.journals).join(Journal.voucher).join(Journal.ledger) \
query = 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')) \
.filter(Journal.cost_center_id != CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id != CostCentre.cost_centre_purchase()) \
.filter(LedgerBase.type.in_([2, 3])) \
.group_by(CostCenter) \
.group_by(CostCentre) \
.order_by(sum_sale.desc()).all()
issues = 0
sales = 0
for cost_center, issue, sale in query:
for cost_centre, issue, sale in query:
issues += issue
sales += sale
rmc = 0 if sale == 0 else issue / sale
report['Body'].append(
{'Name': cost_center.name, 'Issue': issue, 'Sale': sale, 'Rmc': rmc,
'Url': request.route_url('raw_material_cost_id', id=str(cost_center.id),
{'Name': cost_centre.name, 'Issue': issue, 'Sale': sale, 'Rmc': rmc,
'Url': request.route_url('raw_material_cost_id', id=str(cost_centre.id),
_query={'StartDate': start_date, 'FinishDate': finish_date})})
rmc = 0 if sales == 0 else issues / sales
@@ -76,7 +76,7 @@ def build_report(request, start_date, finish_date):
return report
def build_report_id(request, cost_center_id, start_date, finish_date):
def build_report_id(request, cost_centre_id, start_date, finish_date):
report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': []}
sum_quantity = func.sum(Inventory.quantity * Journal.debit).label('quantity')
@@ -88,7 +88,7 @@ def build_report_id(request, cost_center_id, start_date, finish_date):
.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 == 3) \
.filter(Journal.cost_center_id == cost_center_id) \
.filter(Journal.cost_centre_id == cost_centre_id) \
.group_by(Product).group_by(Journal.debit).group_by(ProductGroup.name) \
.order_by(ProductGroup.name).order_by(sum_net.desc()).all()
+4 -4
View File
@@ -6,7 +6,7 @@ from sqlalchemy.sql.expression import func
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import Product, CostCenter
from brewman.models.master import Product, CostCentre
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish
@@ -40,7 +40,7 @@ def build_stock_movement(start_date, finish_date):
openings = DBSession.query(Product, quantity_sum) \
.join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \
.filter(Voucher.date < start_date) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.group_by(Product).all()
for product, quantity in openings:
dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name,
@@ -50,7 +50,7 @@ def build_stock_movement(start_date, finish_date):
.filter(Voucher.date >= start_date) \
.filter(Voucher.date <= finish_date) \
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.group_by(Product).all()
for product, quantity in purchases:
if product.id in dict:
@@ -63,7 +63,7 @@ def build_stock_movement(start_date, finish_date):
.filter(Voucher.date >= start_date) \
.filter(Voucher.date <= finish_date) \
.filter(Voucher.type == VoucherType.by_name('Issue').id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) \
.group_by(Product).all()
for product, quantity in issues:
if product.id in dict:
@@ -22,9 +22,9 @@ def grid_date(request):
@TryCatchFunction
def grid_voucher(request):
voucher = Voucher.by_id(uuid.UUID(request.matchdict['date']))
source = [j.cost_center_id for j in voucher.journals if j.debit == -1]
source = [j.cost_centre_id for j in voucher.journals if j.debit == -1]
source = source[0]
destination = [j.cost_center_id for j in voucher.journals if j.debit == 1]
destination = [j.cost_centre_id for j in voucher.journals if j.debit == 1]
destination = destination[0]
return get_grid(voucher.date, source, destination)
@@ -34,8 +34,8 @@ def get_grid(date, source, destination):
source_journal = aliased(Journal)
destination_journal = aliased(Journal)
source_or = (and_(source_journal.cost_center_id == source, source_journal.debit == -1))
destination_or = (and_(destination_journal.cost_center_id == destination, destination_journal.debit == 1))
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)\
.join(source_journal, Voucher.journals)\
.join(destination_journal, Voucher.journals)\
+5 -2
View File
@@ -1,22 +1,25 @@
from datetime import date, timedelta
import uuid
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from brewman import groupfinder
from brewman.models.auth import Role, User
def session_current_date(request):
session = request.session
if 'currentDate' not in session:
session['currentDate'] = date.today().strftime('%d-%b-%Y')
return session['currentDate']
def session_current_date_set(request, date):
session = request.session
session['currentDate'] = date
return session['currentDate']
def session_period_start(request):
session = request.session
if 'periodStart' not in session:
@@ -33,7 +36,7 @@ def session_period_finish(request):
@view_config(route_name='api_auth', renderer='json')
def user_permission(request):
user_id = authenticated_userid(request)
user_id = request.authenticated_userid
if user_id is None:
auth = {'isAuthenticated': False, 'perms': {}}
elif 'auth' in request.session:
+65 -17
View File
@@ -1,22 +1,25 @@
import datetime
from decimal import Decimal
import uuid
import pkg_resources
from pyramid.response import Response, FileResponse
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import func
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, CostCenter
from brewman.models.master import LedgerBase, CostCentre, Employee, AttendanceType, Ledger
from brewman.models.validation_exception import ValidationError, TryCatchFunction
from brewman.models.voucher import Voucher, VoucherType, Inventory, DbImage
from brewman.models.voucher import Voucher, VoucherType, Inventory, DbImage, Attendance, Journal
from brewman.views import get_lock_info
from .issue import issue_create_voucher, issue_update_voucher
from .journal import journal_update_voucher, journal_create_voucher
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'
@@ -36,6 +39,8 @@ __author__ = 'tanshu'
@view_config(request_method='GET', route_name='issue', permission='Issue')
@view_config(request_method='GET', route_name='salary_deduction_id', permission='Issue')
@view_config(request_method='GET', route_name='salary_deduction', permission='Issue')
@view_config(request_method='GET', route_name='service_charge_id', permission='Service Charge')
@view_config(request_method='GET', route_name='service_charge', permission='Service Charge')
def journal_get(request):
package, resource = 'brewman:static/base.html'.split(':', 1)
file = pkg_resources.resource_filename(package, resource)
@@ -46,7 +51,7 @@ def journal_get(request):
permission='Post Vouchers')
@TryCatchFunction
def voucher_post(request):
user = User.by_id(uuid.UUID(authenticated_userid(request)))
user = User.by_id(uuid.UUID(request.authenticated_userid))
voucher = Voucher.by_id(uuid.UUID(request.matchdict['id']))
start, finish = get_lock_info()
if start is not None and start > voucher.date:
@@ -60,7 +65,7 @@ def voucher_post(request):
def check_delete_permissions(request, voucher):
user = User.by_id(uuid.UUID(authenticated_userid(request)))
user = User.by_id(uuid.UUID(request.authenticated_userid))
permissions = groupfinder(user.id, request)
if voucher.posted and not 'Edit Posted Vouchers' in permissions:
@@ -99,10 +104,10 @@ def delete(request):
if voucher.type == VoucherType.by_name('Issue').id:
for item in voucher.journals:
if item.debit == 1:
destination = item.cost_center_id
destination = item.cost_centre_id
else:
source = item.cost_center_id
batch_consumed = True if source == CostCenter.cost_center_purchase() else False if destination == CostCenter.cost_center_purchase() else None
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 batch_consumed is None:
pass
elif batch_consumed:
@@ -151,6 +156,7 @@ def voucher_info(voucher, request):
'Journals': [],
'Inventories': [],
'SalaryDeductions': [],
'ServiceCharges': [],
'Files': [],
'CreationDate': voucher.creation_date.strftime('%d-%b-%Y %H:%M'),
'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'),
@@ -161,7 +167,7 @@ def voucher_info(voucher, request):
for item in voucher.journals:
json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount,
'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name},
'CostCenter': {'CostCenterID': item.cost_center_id}})
'CostCentre': {'CostCentreID': item.cost_centre_id}})
for item in voucher.salary_deductions:
json_voucher['SalaryDeductions'].append(
{'GrossSalary': item.gross_salary,
@@ -173,8 +179,16 @@ def voucher_info(voucher, request):
'Journal': {'JournalID': item.journal.id,
'Ledger': {'LedgerID': item.journal.ledger.id, 'Name': item.journal.ledger.name,
'Designation': item.journal.ledger.designation,
'CostCenter': {'CostCenterID': item.journal.ledger.costcenter.id,
'Name': item.journal.ledger.costcenter.name}}}})
'CostCentre': {'CostCentreID': item.journal.ledger.cost_centre.id,
'Name': item.journal.ledger.cost_centre.name}}}})
for item in voucher.service_charges:
json_voucher['ServiceCharges'].append(
{'EmployeeID': item.journal.ledger_id, 'Name': item.journal.ledger.name,
'Designation': Employee.by_id(item.journal.ledger_id).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
x.ledger_id == Ledger.service_charge_id()][0]
for item in voucher.inventories:
text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format(item.product.name, item.product.units,
item.batch.quantity_remaining, item.batch.rate,
@@ -233,36 +247,68 @@ def blank_voucher(info):
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
'Amount': 0,
'Debit': -1,
'CostCenter': {'CostCenterID': info['Source']}})
'CostCentre': {'CostCentreID': info['Source']}})
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
'Amount': 0,
'Debit': 1,
'CostCenter': {'CostCenterID': info['Destination']}})
'CostCentre': {'CostCentreID': info['Destination']}})
elif 'Journals' not in info:
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
'Amount': 0,
'Debit': -1,
'CostCenter': {'CostCenterID': CostCenter.cost_center_purchase()}})
'CostCentre': {'CostCentreID': CostCentre.cost_centre_purchase()}})
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
'Amount': 0,
'Debit': 1,
'CostCenter': {'CostCenterID': CostCenter.cost_center_kitchen()}})
'CostCentre': {'CostCentreID': CostCentre.cost_centre_kitchen()}})
else:
json_voucher['Date'] = info['Date']
for item in info['Journals']:
json_voucher['Journals'].append({'Ledger': {'LedgerID': item['Ledger']['LedgerID']},
'Amount': 0,
'Debit': item['Debit'],
'CostCenter': {'CostCenterID': item['CostCenter']['CostCenterID']}})
'CostCentre': {'CostCentreID': item['CostCentre']['CostCentreID']}})
elif type == 'Salary Deduction':
json_voucher['SalaryDeductions'] = []
elif type == 'Service Charge':
json_voucher['ServiceCharges'], json_voucher['ServiceCharge'] = service_charge_employees(info['Date'])
else:
raise ValidationError("Voucher of type \"{0}\" does not exist.".format(type))
json_voucher['Files'] = []
return json_voucher
def service_charge_employees(date):
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) \
.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) \
.filter(Attendance.employee_id == employee.id) \
.filter(Attendance.date >= start_date) \
.filter(Attendance.date < finish_date) \
.filter(Attendance.is_valid == True) \
.all()
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
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)) \
.join(Journal.voucher) \
.filter(Voucher.date < finish_date) \
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
.filter(Journal.ledger_id == Ledger.service_charge_id()) \
.scalar()
amount = 0 if amount is None else amount * Decimal(.7) * Decimal(.9) * -1
return details, amount
def get_edit_url(request, voucher):
if voucher.type == 1:
return request.route_url('journal_id', id=voucher.id)
@@ -278,5 +324,7 @@ def get_edit_url(request, voucher):
return request.route_url('purchase_return_id', id=voucher.id)
elif voucher.type == 12:
return request.route_url('salary_deduction_id', id=voucher.id)
elif voucher.type == 13:
return request.route_url('service_charge_id', id=voucher.id)
else:
return '#'
@@ -1,10 +1,11 @@
import calendar
import datetime
import uuid
from pyramid.security import authenticated_userid
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
@@ -12,13 +13,14 @@ from ....models.validation_exception import TryCatchFunction
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')
@TryCatchFunction
def credit_salary(request):
user = User.by_id(uuid.UUID(authenticated_userid(request)))
user = User.by_id(uuid.UUID(request.authenticated_userid))
month = datetime.datetime.strptime(request.json_body['Month'], '%d-%b-%Y')
start_date = get_first_day(month)
@@ -41,7 +43,7 @@ def salary_journals(start_date, finish_date):
employees = DBSession().query(Employee) \
.filter(Employee.joining_date <= finish_date) \
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
.order_by(Employee.cost_centre_id).order_by(Employee.designation).order_by(Employee.name).all()
for employee in employees:
att = DBSession.query(Attendance) \
.filter(Attendance.employee_id == employee.id) \
@@ -53,9 +55,10 @@ def salary_journals(start_date, finish_date):
att = round(att * employee.salary / days)
if att != 0:
amount += att
journals.append(Journal(amount=att, debit=-1, ledger_id=employee.id, cost_center_id=employee.costcenter_id))
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']))
journals.append(Journal(amount=amount, debit=1, ledger_id=salary.id, cost_center_id=salary.costcenter_id))
journals.append(Journal(amount=amount, debit=1, ledger_id=salary.id, cost_centre_id=salary.cost_centre_id))
return journals
@@ -1,83 +0,0 @@
import datetime
import uuid
from decimal import Decimal
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import or_, func
import transaction
from ....models import DBSession
from ....models.auth import User
from ....models.master import Employee, AttendanceType, Ledger
from ....models.validation_exception import TryCatchFunction
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_service_charge', renderer='json', permission='Attendance')
@TryCatchFunction
def credit_sc(request):
user = User.by_id(uuid.UUID(authenticated_userid(request)))
month = datetime.datetime.strptime(request.json_body['Month'], '%d-%b-%Y')
credit_date = datetime.datetime.strptime(request.json_body['CreditDate'], '%d-%b-%Y')
amount = balance(month)
start_date = get_first_day(month)
finish_date = get_last_day(month)
voucher = Voucher(date=credit_date, narration='Auto Generated Service Charge Entry', user_id=user.id,
type=VoucherType.by_name('Journal'), posted=True, poster_id=user.id)
DBSession.add(voucher)
for item in service_charge_journals(amount, start_date, finish_date):
voucher.journals.append(item)
DBSession.add(item)
transaction.commit()
return {'message': 'Salary Entry created'}
def service_charge_journals(amount, start_date, finish_date):
amount = amount * Decimal(.7) * Decimal(.9)
total_points = 0
details = []
finish_date = finish_date + datetime.timedelta(1)
journals = []
employees = DBSession().query(Employee) \
.filter(Employee.joining_date <= finish_date) \
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date)) \
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
for employee in employees:
if employee.service_points != 0:
att = DBSession.query(Attendance) \
.filter(Attendance.employee_id == employee.id) \
.filter(Attendance.date >= start_date) \
.filter(Attendance.date < finish_date) \
.filter(Attendance.is_valid == True) \
.all()
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
points = Decimal(att) * employee.service_points
if points != 0:
total_points += points
details.append({'Employee': employee, 'Points': points})
if total_points == 0:
raise ValueError("There is no data to credit service charges")
point_value = round(amount / total_points, 2)
amount = 0
for item in details:
ee = item['Employee']
employee_amount = round(point_value * item['Points'])
journal = Journal(amount=employee_amount, debit=-1, ledger_id=ee.id, cost_center_id=ee.costcenter_id)
journals.append(journal)
amount += employee_amount
sc = Ledger.by_id(uuid.UUID(Ledger.service_charge()['LedgerID']))
journals.append(Journal(amount=amount, debit=1, ledger_id=sc.id, cost_center_id=sc.costcenter_id))
return journals
def balance(date):
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) \
.filter(Journal.ledger_id == uuid.UUID(Ledger.service_charge()['LedgerID'])) \
.scalar()
return 0 if amount is None else amount * -1
@@ -53,6 +53,15 @@ class blank_voucher_view(object):
else:
return self.get_blank()
@view_config(request_param='type=Service Charge', permission='Service Charge')
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})
else:
return self.get_blank()
def get_blank(self, additional_info=None):
voucher_type = self.request.GET.get('type', None)
if additional_info is None:
+15 -15
View File
@@ -2,7 +2,7 @@ import datetime
from decimal import Decimal
import uuid
from brewman.models import DBSession
from brewman.models.master import CostCenter, LedgerBase
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
@@ -17,12 +17,12 @@ def issue_create_voucher(json, user):
for item in json['Journals']:
if int(item['Debit']) == 1:
destination = uuid.UUID(item['CostCenter']['CostCenterID'])
destination = uuid.UUID(item['CostCentre']['CostCentreID'])
else:
source = uuid.UUID(item['CostCenter']['CostCenterID'])
source = uuid.UUID(item['CostCentre']['CostCentreID'])
if source == destination:
raise ValidationError("Source cannot be the same as destination")
batch_consumed = True if source == CostCenter.cost_center_purchase() else False if destination == CostCenter.cost_center_purchase() else None
batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None
for item in json['Inventories']:
issue_create_inventory(voucher, item, batch_consumed)
for item in issue_create_journals(voucher.inventories, source, destination):
@@ -62,9 +62,9 @@ def issue_create_journals(inventories, source, destination):
for item in inventories:
amount += item.amount
return [Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=round(amount, 2),
cost_center_id=source),
cost_centre_id=source),
Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=round(amount, 2),
cost_center_id=destination)]
cost_centre_id=destination)]
def issue_update_voucher(voucher, json, user):
@@ -75,22 +75,22 @@ def issue_update_voucher(voucher, json, user):
for item in voucher.journals:
if item.debit == 1:
destination = item.cost_center_id
destination = item.cost_centre_id
else:
source = item.cost_center_id
old_batch_consumed = True if source == CostCenter.cost_center_purchase() else False if destination == CostCenter.cost_center_purchase() else None
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
for item in json['Journals']:
if int(item['Debit']) == 1:
destination = uuid.UUID(item['CostCenter']['CostCenterID'])
destination = uuid.UUID(item['CostCentre']['CostCentreID'])
else:
source = uuid.UUID(item['CostCenter']['CostCenterID'])
source = uuid.UUID(item['CostCentre']['CostCentreID'])
if source == destination:
raise ValidationError("Source cannot be the same as destination")
new_batch_consumed = True if source == CostCenter.cost_center_purchase() else False if destination == CostCenter.cost_center_purchase() else None
new_batch_consumed = True if source == CostCentre.cost_centre_purchase() else False if destination == CostCentre.cost_centre_purchase() else None
if new_batch_consumed != old_batch_consumed:
raise ValidationError("Purchase cost center cannot be changed")
raise ValidationError("Purchase cost centre cannot be changed")
issue_update_inventory(voucher, json['Inventories'], old_batch_consumed)
issue_update_journals(voucher, source, destination)
@@ -160,10 +160,10 @@ def issue_update_journals(voucher, source, destination):
for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1]
if item.debit == -1:
item.cost_center_id = source
item.cost_centre_id = source
item.amount = round(amount, 2)
else:
item.cost_center_id = destination
item.cost_centre_id = destination
item.amount = round(amount, 2)
+3 -3
View File
@@ -20,7 +20,7 @@ def journal_create_voucher(json, files, user):
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_center_id=ledger.costcenter_id)
cost_centre_id=ledger.cost_centre_id)
voucher.journals.append(journal)
DBSession.add(journal)
journals_valid(voucher)
@@ -48,7 +48,7 @@ def journal_update_voucher(voucher, json, files, user):
item.debit = int(j['Debit'])
item.amount = round(Decimal(j['Amount']), 2)
item.ledger_id = ledger.id
item.cost_center_id = ledger.costcenter_id
item.cost_centre_id = ledger.cost_centre_id
newJournals.remove(j)
break
if not found:
@@ -56,7 +56,7 @@ def journal_update_voucher(voucher, json, files, user):
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,
cost_center_id=ledger.costcenter_id)
cost_centre_id=ledger.cost_centre_id)
DBSession.add(journal)
voucher.journals.append(journal)
journals_valid(voucher)
+5 -5
View File
@@ -63,9 +63,9 @@ def purchase_create_journals(inventories, ledgerID):
if ledger.id in journals:
journals[ledger.id].amount += item_amount
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
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_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
journals[otherLedger.id] = Journal(debit=-1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id,
amount=amount)
return list(journals.values())
@@ -168,16 +168,16 @@ def purchase_update_journals(voucher, journals):
if ledger.id in journals:
journals[ledger.id].amount += item.amount
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
journals[ledger.id] = Journal(debit=1, cost_centre_id=ledger.cost_centre_id, ledger_id=ledger.id,
amount=item.amount)
journals[other_ledger.id] = Journal(debit=-1, cost_center_id=other_ledger.costcenter_id, ledger_id=other_ledger.id,
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:
item.debit = journals[item.ledger_id].debit
item.amount = round(journals[item.ledger_id].amount, 2)
item.cost_center_id = journals[item.ledger_id].cost_center_id
item.cost_centre_id = journals[item.ledger_id].cost_centre_id
del journals[item.ledger_id]
else:
DBSession.delete(item)
@@ -57,9 +57,9 @@ def purchase_return_create_journals(inventories, ledgerID):
if ledger.id in journals:
journals[ledger.id].amount += round(item.amount, 2)
else:
journals[ledger.id] = Journal(debit=-1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
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_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
journals[otherLedger.id] = Journal(debit=1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id,
amount=amount)
return list(journals.values())
@@ -126,16 +126,16 @@ def purchase_return_update_journals(voucher, journals):
if ledger.id in journals:
journals[ledger.id].amount += round(item.amount, 2)
else:
journals[ledger.id] = Journal(debit=-1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
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_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
journals[otherLedger.id] = Journal(debit=1, cost_centre_id=otherLedger.cost_centre_id, ledger_id=otherLedger.id,
amount=amount)
for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1]
if item.ledger_id in journals:
item.debit = journals[item.ledger_id].debit
item.amount = journals[item.ledger_id].amount
item.cost_center_id = journals[item.ledger_id].cost_center_id
item.cost_centre_id = journals[item.ledger_id].cost_centre_id
del journals[item.ledger_id]
else:
DBSession.delete(item)
@@ -22,11 +22,11 @@ def salary_deduction_create_voucher(json, user):
exp += item_exp
total += item_total
ledger = LedgerBase.by_id(LedgerBase.esi_pf_expense())
journal = Journal(amount=exp, debit=1, ledger_id=ledger.id, cost_center_id=ledger.costcenter_id)
journal = Journal(amount=exp, debit=1, ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id)
DBSession.add(journal)
voucher.journals.append(journal)
ledger = LedgerBase.by_id(LedgerBase.esi_pf_payable())
journal = Journal(amount=total, debit=-1, ledger_id=ledger.id, cost_center_id=ledger.costcenter_id)
journal = Journal(amount=total, debit=-1, ledger_id=ledger.id, cost_centre_id=ledger.cost_centre_id)
DBSession.add(journal)
voucher.journals.append(journal)
@@ -81,7 +81,7 @@ def add_salary_deduction(item, days_in_month, voucher):
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_center_id=ledger.costcenter_id)
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)
voucher.journals.append(journal)
@@ -2,7 +2,6 @@ import uuid
from json import loads
import datetime
from pyramid.security import authenticated_userid
from pyramid.view import view_defaults, view_config
import transaction
@@ -12,6 +11,7 @@ from brewman.models.voucher import Voucher
from brewman.views import get_lock_info
from brewman.views.services.session import session_current_date_set
from . import voucher_info, journal_create_voucher, purchase_create_voucher, issue_create_voucher
from . import service_charge_create_voucher
from .purchase_return import purchase_return_create_voucher
from .salary_deduction import salary_deduction_create_voucher
@@ -38,7 +38,7 @@ class save_voucher(object):
return model, files
self.request = request
self.user = User.by_id(uuid.UUID(authenticated_userid(request)))
self.user = User.by_id(uuid.UUID(request.authenticated_userid))
self.json, self.files = parse_post(request)
self.start, self.finish = get_lock_info()
self.voucher_date = datetime.datetime.strptime(self.json['Date'], '%d-%b-%Y')
@@ -77,6 +77,10 @@ class save_voucher(object):
def salary_deduction(self):
return self.save()
@view_config(request_param='type=Service Charge', permission='Service Charge')
def salary_deduction(self):
return self.save()
@TryCatchFunction
def save(self):
if self.start is not None and self.start > self.voucher_date:
@@ -94,6 +98,8 @@ class save_voucher(object):
voucher = issue_create_voucher(self.json, self.user)
elif self.json['Type'] in ['Salary Deduction']:
voucher = salary_deduction_create_voucher(self.json, self.user)
elif self.json['Type'] in ['Service Charge']:
voucher = service_charge_create_voucher(self.json, self.user)
transaction.commit()
session_current_date_set(self.request, self.json['Date'])
return voucher_info(Voucher.by_id(voucher.id), self.request)
@@ -0,0 +1,132 @@
import datetime
from decimal import Decimal
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):
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)
employees = get_employees(get_first_day(date), date + datetime.timedelta(1), json['ServiceCharges'])
amount = balance(date) * Decimal(.7) * Decimal(.9)
total_points = 0
for item in employees:
total_points += item['Points'] * item['DaysWorked']
point_value = round(amount / total_points, 2)
total_amount = 0
for item in employees:
item_amount = round(item['Points'] * item['DaysWorked'] * point_value)
employee = item['Employee']
journal = Journal(amount=item_amount, debit=-1, ledger_id=employee.id, cost_centre_id=employee.cost_centre_id)
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)
total_amount += item_amount
sc = Ledger.by_id(Ledger.service_charge_id())
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)
journals_valid(voucher)
return voucher
def service_charge_update_voucher(voucher, json, user):
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)
total_points = 0
for item in employees:
total_points += item['Points'] * item['DaysWorked']
point_value = round(amount / total_points, 2)
total_amount = 0
for item in voucher.service_charges:
employee = [e for e in employees if e['Employee'].id == item.journal.ledger_id][0]
item_amount = round(employee['Points'] * employee['DaysWorked'] * point_value)
item.days_worked = employee['DaysWorked']
item.points = employee['Points']
item.journal.amount = item_amount
total_amount += item_amount
journal = [j for j in voucher.journals if j.ledger_id == Ledger.service_charge_id()][0]
journal.amount = total_amount
journals_valid(voucher)
return voucher
def get_employees(start_date, finish_date, json, voucher_employees=None):
details = []
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()
check_if_employees_changed(json, employees, voucher_employees)
for employee in employees:
att = DBSession.query(Attendance) \
.filter(Attendance.employee_id == employee.id) \
.filter(Attendance.date >= start_date) \
.filter(Attendance.date < finish_date) \
.filter(Attendance.is_valid == True) \
.all()
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
details.append({'Employee': employee, 'DaysWorked': round(Decimal(att), 2)})
for item in details:
j = [x for x in json if uuid.UUID(x['EmployeeID']) == item['Employee'].id][0]
item['Points'] = round(Decimal(j['Points']), 2)
json.remove(j)
return details
def balance(date, voucher_id=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) \
.filter(Journal.ledger_id == Ledger.service_charge_id())
if voucher_id is not None:
amount = amount.filter(Voucher.id != voucher_id)
amount = amount.scalar()
return 0 if amount is None else amount * -1
def check_if_employees_changed(json, db, voucher):
json = set([uuid.UUID(x['EmployeeID']) for x in json])
db = set([x.id for x in db])
voucher = set([x.ledger_id for x in voucher]) if voucher is not None else None
if voucher is None:
if len(json) != len(db):
raise ValueError("Employee missing in json data")
if len(json ^ db) != 0:
raise ValueError("Employee missing in json data")
else:
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")
@@ -1,20 +1,23 @@
import datetime
from json import loads
import uuid
from pyramid.response import Response
from pyramid.security import authenticated_userid
from pyramid.view import view_defaults, view_config
import transaction
from brewman import groupfinder
from brewman.models.auth import User
from brewman.models.validation_exception import ValidationError, TryCatchFunction
from brewman.models.validation_exception import TryCatchFunction
from brewman.models.voucher import Voucher
from brewman.views import get_lock_info
from brewman.views.services.session import session_current_date_set
from . import voucher_info, issue_update_voucher, purchase_update_voucher, journal_update_voucher
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'
@@ -37,13 +40,12 @@ class update_voucher(object):
return model, files
self.request = request
self.user = User.by_id(uuid.UUID(authenticated_userid(request)))
self.user = User.by_id(uuid.UUID(request.authenticated_userid))
self.voucher = Voucher.by_id(uuid.UUID(request.matchdict.get('id', None)))
self.json, self.files = parse_post(request)
self.start, self.finish = get_lock_info()
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:
response = Response("You are not allowed to edit posted vouchers")
@@ -98,6 +100,10 @@ class update_voucher(object):
def salary_deduction(self):
return self.update()
@view_config(request_param='type=Service Charge', permission='Service Charge')
def service_charge(self):
return self.update()
@TryCatchFunction
def update(self):
if self.error is not None:
@@ -112,6 +118,8 @@ class update_voucher(object):
voucher = issue_update_voucher(self.voucher, self.json, self.user)
elif self.json['Type'] in ['Salary Deduction']:
voucher = salary_deduction_update_voucher(self.voucher, self.json, self.user)
elif self.json['Type'] in ['Service Charge']:
voucher = service_charge_update_voucher(self.voucher, self.json, self.user)
transaction.commit()
session_current_date_set(self.request, self.json['Date'])
return voucher_info(Voucher.by_id(voucher.id), self.request)