Feature: Account reconcilliation built.

Fix: Made most of the columns on entities_vouchers NOT NULL.
Fix: Renamed ReconcilliationDate to ReconcileDate NOT NULL
Fix: IsReconciled is the check on reconcilliation.
Feature: Changed output of formatted currency to numbers with formatting in html.
Feature: Html number formatting with indian locale info enables lakhs and crores formatting of currency.
TODO: Started work on reset stock.  Not working yet
TODO: Satrted work on Server-sent Events directive, not working yet
Feature: Created accounting, clr and percent filters
This commit is contained in:
Tanshu committed 2013-10-03 15:42:43 +05:30
1 parent f8bdf9d731
commit 62918bcee5
51 files changed
+990 -314

No files matched your search

+2
View File
@@ -105,6 +105,7 @@ def main(global_config, **settings):
config.add_route('api_fingerprint', '/api/Fingerprint') config.add_route('api_fingerprint', '/api/Fingerprint')
add_route(config, 'ledger', '/Ledger', has_list=False) add_route(config, 'ledger', '/Ledger', has_list=False)
add_route(config, 'reconcile', '/Reconcile', has_list=False)
add_route(config, 'product_ledger', '/ProductLedger', has_list=False) add_route(config, 'product_ledger', '/ProductLedger', has_list=False)
add_route(config, 'trial_balance', '/TrialBalance', has_list=False, variable='date') add_route(config, 'trial_balance', '/TrialBalance', has_list=False, variable='date')
@@ -131,6 +132,7 @@ def main(global_config, **settings):
config.add_route('api_auth', '/api/Auth') config.add_route('api_auth', '/api/Auth')
config.add_route('api_rebase', '/api/Rebase/{date}') config.add_route('api_rebase', '/api/Rebase/{date}')
config.add_route('api_reset_stock', '/api/ResetStock/{id}')
config.add_route('api_batch', '/api/Batch') config.add_route('api_batch', '/api/Batch')
+4 -2
View File
@@ -197,13 +197,15 @@ class LedgerBase(Base):
return DBSession.query(cls).all() return DBSession.query(cls).all()
@classmethod @classmethod
def list(cls, type, name): def list(cls, type, name, is_reconcilable):
query = DBSession.query(cls) query = DBSession.query(cls)
if type is not None: if type is not None:
if not isinstance(type, int): if not isinstance(type, int):
type = int(type) type = int(type)
query = query.filter(cls.type == type) query = query.filter(cls.type == type)
if name != None: if is_reconcilable is not None:
query = query.filter(cls.is_reconcilable == is_reconcilable)
if name is not None:
for item in name.split(): for item in name.split():
query = query.filter(cls.name.ilike('%' + item + '%')) query = query.filter(cls.name.ilike('%' + item + '%'))
return query.order_by(cls.name) return query.order_by(cls.name)
+21 -20
View File
@@ -52,14 +52,14 @@ class Voucher(Base):
__tablename__ = 'entities_vouchers' __tablename__ = 'entities_vouchers'
id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4)
date = Column('Date', DateTime) date = Column('Date', DateTime, nullable=False)
reconcilliation_date = Column('ReconcilliationDate', DateTime) reconcile_date = Column('ReconcileDate', DateTime, nullable=False)
narration = Column('Narration', Unicode(1000)) is_reconciled = Column('IsReconciled', DateTime, nullable=False)
posted = Column('Posted', Boolean) narration = Column('Narration', Unicode(1000), nullable=False)
creation_date = Column('CreationDate', DateTime(timezone=True)) posted = Column('Posted', Boolean, nullable=False)
creation_date = Column('CreationDate', DateTime(timezone=True), nullable=False)
last_edit_date = Column('LastEditDate', DateTime(timezone=True)) last_edit_date = Column('LastEditDate', DateTime(timezone=True), nullable=False)
_type = Column('VoucherType', Integer) _type = Column('VoucherType', Integer, nullable=False)
user_id = Column('UserID', GUID(), ForeignKey('auth_users.UserID'), nullable=False) user_id = Column('UserID', GUID(), ForeignKey('auth_users.UserID'), nullable=False)
poster_id = Column('PosterID', GUID(), ForeignKey('auth_users.UserID')) poster_id = Column('PosterID', GUID(), ForeignKey('auth_users.UserID'))
@@ -69,7 +69,7 @@ class Voucher(Base):
journals = relationship('Journal', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False) journals = relationship('Journal', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False)
inventories = relationship('Inventory', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False) inventories = relationship('Inventory', backref='voucher', cascade="delete, delete-orphan", cascade_backrefs=False)
salary_deductions = relationship('SalaryDeduction', backref='voucher', cascade="delete, delete-orphan", salary_deductions = relationship('SalaryDeduction', backref='voucher', cascade="delete, delete-orphan",
cascade_backrefs=False) cascade_backrefs=False)
def _get_type(self): def _get_type(self):
return self._type return self._type
@@ -90,10 +90,10 @@ class Voucher(Base):
def __name__(self): def __name__(self):
return self.name return self.name
def __init__(self, date=None, reconcilliation_date=None, narration='', posted=False, creation_date=None, def __init__(self, date=None, reconcile_date=None, narration='', posted=False, creation_date=None,
last_edit_date=None, type=None, user_id=None, poster_id=None): last_edit_date=None, type=None, user_id=None, poster_id=None, is_reconciled=False):
self.date = date self.date = date
self.reconcilliation_date = reconcilliation_date self.reconcile_date = reconcile_date if reconcile_date and is_reconciled else date
self.narration = narration self.narration = narration
self.posted = posted self.posted = posted
self.creation_date = datetime.utcnow() if creation_date is None else creation_date self.creation_date = datetime.utcnow() if creation_date is None else creation_date
@@ -101,6 +101,7 @@ class Voucher(Base):
self.type = type self.type = type
self.user_id = user_id self.user_id = user_id
self.poster_id = poster_id self.poster_id = poster_id
self.is_reconciled = is_reconciled
@classmethod @classmethod
def by_id(cls, id): def by_id(cls, id):
@@ -167,7 +168,7 @@ class SalaryDeduction(Base):
pf_er = Column('PfEmployer', Integer) pf_er = Column('PfEmployer', Integer)
journal = relationship(Journal, backref=backref('salary_deduction', uselist=False), cascade=None, journal = relationship(Journal, backref=backref('salary_deduction', uselist=False), cascade=None,
cascade_backrefs=False) cascade_backrefs=False)
def __init__(self, id=None, voucher_id=None, journal_id=None, journal=None, gross_salary=None, days_worked=None, def __init__(self, id=None, voucher_id=None, journal_id=None, journal=None, gross_salary=None, days_worked=None,
esi_ee=None, pf_ee=None, esi_er=None, pf_er=None): esi_ee=None, pf_ee=None, esi_er=None, pf_er=None):
@@ -290,23 +291,23 @@ class Attendance(Base):
return DBSession.query(cls) return DBSession.query(cls)
def create(self): def create(self):
old = DBSession.query(Attendance).filter(Attendance.date == self.date)\ old = DBSession.query(Attendance).filter(Attendance.date == self.date) \
.filter(Attendance.employee_id == self.employee_id)\ .filter(Attendance.employee_id == self.employee_id) \
.filter(Attendance.is_valid == True).first() .filter(Attendance.is_valid == True).first()
if old is None or old.attendance_type != self.attendance_type: if old is None or old.attendance_type != self.attendance_type:
if old is not None: if old is not None:
old.is_valid = False old.is_valid = False
DBSession.add(self) DBSession.add(self)
class Fingerprint(Base): class Fingerprint(Base):
__tablename__ = 'entities_fingerprints' __tablename__ = 'entities_fingerprints'
id = Column('FingerprintID', GUID(), primary_key=True, default=uuid.uuid4) id = Column('FingerprintID', GUID(), primary_key=True, default=uuid.uuid4)
employee_id = Column('EmployeeID', GUID(), ForeignKey('entities_employees.LedgerID')) employee_id = Column('EmployeeID', GUID(), ForeignKey('entities_employees.LedgerID'))
date = Column('Date', DateTime) date = Column('Date', DateTime)
def __init__(self, id=None, employee_id=None,date=None): def __init__(self, id=None, employee_id=None, date=None):
self.id = id self.id = id
self.employee_id = employee_id self.employee_id = employee_id
self.date = date self.date = date
@@ -321,8 +322,8 @@ class Fingerprint(Base):
return DBSession.query(cls) return DBSession.query(cls)
def create(self): def create(self):
old = DBSession.query(Fingerprint).filter(Fingerprint.date == self.date)\ old = DBSession.query(Fingerprint).filter(Fingerprint.date == self.date) \
.filter(Fingerprint.employee_id == self.employee_id).first() .filter(Fingerprint.employee_id == self.employee_id).first()
if old is None: if old is None:
DBSession.add(self) DBSession.add(self)
return self return self
@@ -0,0 +1,98 @@
angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", {
"DATETIME_FORMATS": {
"AMPMS": [
"AM",
"PM"
],
"DAY": [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
"MONTH": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
"SHORTDAY": [
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
],
"SHORTMONTH": [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
],
"fullDate": "EEEE d MMMM y",
"longDate": "d MMMM y",
"medium": "dd-MMM-y h:mm:ss a",
"mediumDate": "dd-MMM-y",
"mediumTime": "h:mm:ss a",
"short": "dd/MM/yy h:mm a",
"shortDate": "dd/MM/yy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
"CURRENCY_SYM": "\u20b9",
"DECIMAL_SEP": ".",
"GROUP_SEP": ",",
"PATTERNS": [
{
"gSize": 2,
"lgSize": 3,
"macFrac": 0,
"maxFrac": 3,
"minFrac": 0,
"minInt": 1,
"negPre": "-",
"negSuf": "",
"posPre": "",
"posSuf": ""
},
{
"gSize": 2,
"lgSize": 3,
"macFrac": 0,
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4\u00a0-",
"negSuf": "",
"posPre": "\u00a4\u00a0",
"posSuf": ""
}
]
},
"id": "en-in",
"pluralCat": function (n) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
@@ -21,7 +21,7 @@
<table id="gvGrid" class="table table-condensed table-bordered table-striped"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th class="right">Code</th> <th class="text-right">Code</th>
<th>Name</th> <th>Name</th>
<th>Designation</th> <th>Designation</th>
<th>Department</th> <th>Department</th>
@@ -33,7 +33,7 @@
<tr ng-repeat="item in info.Body" <tr ng-repeat="item in info.Body"
ng-class="{0:'', 1:'Present', 2:'Off', 3:'Leave', 4:'Absent', 5:'HalfDay', 6:'Double', 7:'PaidLeaveAvailed', 8:'CasualLeaveAvailed', 9:'Overtime', 10:'OffWorked', 11:'COff', 12:'HalfPL', 13:'HalfCL'}[item.AttendanceTypeID]" ng-class="{0:'', 1:'Present', 2:'Off', 3:'Leave', 4:'Absent', 5:'HalfDay', 6:'Double', 7:'PaidLeaveAvailed', 8:'CasualLeaveAvailed', 9:'Overtime', 10:'OffWorked', 11:'COff', 12:'HalfPL', 13:'HalfCL'}[item.AttendanceTypeID]"
ng-controller="AttendanceSubCtrl"> ng-controller="AttendanceSubCtrl">
<td class="right">{{item.Code}}</td> <td class="text-right">{{item.Code}}</td>
<td><i class="glyphicon glyphicon-leaf" ng-show="isDirty()"></i> {{item.Name}}</td> <td><i class="glyphicon glyphicon-leaf" ng-show="isDirty()"></i> {{item.Name}}</td>
<td>{{item.Designation}}</td> <td>{{item.Designation}}</td>
<td>{{item.Department}}</td> <td>{{item.Department}}</td>
@@ -31,16 +31,16 @@
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<td>{{item.Group}}</td> <td>{{item.Group}}</td>
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td> <td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="right">{{item.Amount}}</td> <td class="text-right">{{item.Amount | currency | clr}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr ng-repeat="item in info.Footer"> <tr ng-repeat="item in info.Footer">
<td><strong>{{item.Group}}</strong></td> <td><strong>{{item.Group}}</strong></td>
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td> <td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="right"><strong>{{item.Amount}}</strong></td> <td class="text-right"><strong>{{item.Amount | currency | clr}}</strong></td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
@@ -38,15 +38,15 @@
<tbody> <tbody>
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="right">{{item.Inflow}}</td> <td class="text-right">{{item.Inflow | currency | clr}}</td>
<td class="right">{{item.Outflow}}</td> <td class="text-right">{{item.Outflow | currency | clr}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr ng-repeat="item in info.Footer"> <tr ng-repeat="item in info.Footer">
<td>{{item.Name}}</a></td> <td>{{item.Name}}</a></td>
<td class="right">{{item.Inflow}}</td> <td class="text-right">{{item.Inflow | currency | clr}}</td>
<td class="right">{{item.Outflow}}</td> <td class="text-right">{{item.Outflow | currency | clr}}</td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
@@ -29,10 +29,10 @@
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<th><a href="{{item.Url}}">{{item.Product}}</a></th> <td><a href="{{item.Url}}">{{item.Product}}</a></td>
<th>{{item.Group}}</th> <td>{{item.Group}}</td>
<th class="right">{{item.Quantity}}</th> <td class="text-right">{{item.Quantity | number:2}}</td>
<th class="right">{{item.Amount}}</th> <td class="text-right">{{item.Amount | currency}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+6 -6
View File
@@ -33,9 +33,9 @@
<th>Type</th> <th>Type</th>
<th>Narration</th> <th>Narration</th>
<th>Debit</th> <th>Debit</th>
<th class="right">Amount</th> <th class="text-right">Amount</th>
<th>Credit</th> <th>Credit</th>
<th class="right">Amount</th> <th class="text-right">Amount</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -43,10 +43,10 @@
<td><a href="{{item.Url}}">{{item.Date}}</a></td> <td><a href="{{item.Url}}">{{item.Date}}</a></td>
<td>{{item.Type}}</td> <td>{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
<td class="right">{{item.DebitN}}</td> <td class="text-right">{{item.DebitN}}</td>
<td class="right">{{item.DebitA}}</td> <td class="text-right">{{item.DebitA | currency}}</td>
<td class="right">{{item.CreditN}}</td> <td class="text-right">{{item.CreditN}}</td>
<td class="right">{{item.CreditA}}</td> <td class="text-right">{{item.CreditA | currency}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+5 -5
View File
@@ -9,7 +9,7 @@
</tr> </tr>
</thead> </thead>
<tr ng-repeat="item in smallGrid"> <tr ng-repeat="item in smallGrid">
<td>{{item.Amount}}</td> <td>{{item.Amount | currency}}</td>
<td> <td>
<a class="btn btn-info" href="/Issue/{{item.VoucherID}}">Load <i <a class="btn btn-info" href="/Issue/{{item.VoucherID}}">Load <i
class="glyphicon glyphicon-eye-open"></i></a> class="glyphicon glyphicon-eye-open"></i></a>
@@ -37,7 +37,7 @@
<select id="ddlDestinationCostCenter" class="form-control" ng-model="journal.CostCenter.CostCenterID" <select id="ddlDestinationCostCenter" class="form-control" ng-model="journal.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in cost_centers"> </select> ng-options="l.CostCenterID as l.Name for l in cost_centers"> </select>
<span class="input-group-addon">₹</span> <span class="input-group-addon">₹</span>
<input type="text" class="form-control" placeholder="Amount" ng-model="journal.Amount"/> <input type="text" class="form-control" placeholder="Amount" value="{{journal.Amount | number:2}}"/>
</div> </div>
</div> </div>
</div> </div>
@@ -75,9 +75,9 @@
<tr ng-repeat="inventory in voucher.Inventories"> <tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td> <td>{{inventory.Product.Name}}</td>
<td>{{inventory.Batch.Name}}</td> <td>{{inventory.Batch.Name}}</td>
<td>{{inventory.Quantity}}</td> <td>{{inventory.Quantity | number:2}}</td>
<td>{{inventory.Rate}}</td> <td>{{inventory.Rate | currency}}</td>
<td>{{inventory.Amount}}</td> <td>{{inventory.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeInventory(inventory)"><i <a class="btn btn-danger" ng-click="removeInventory(inventory)"><i
+1 -1
View File
@@ -55,7 +55,7 @@
<tr ng-repeat="journal in voucher.Journals"> <tr ng-repeat="journal in voucher.Journals">
<td>{{journal.Debit | debit}}</td> <td>{{journal.Debit | debit}}</td>
<td>{{journal.Ledger.Name}}</td> <td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td> <td class="text-right">{{journal.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i <a class="btn btn-danger" ng-click="removeJournal(journal)"><i
+8 -7
View File
@@ -51,14 +51,15 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body" ng-class="{danger:!item.Posted, warning:$index==selected}" ng-click="setSelected($index)"> <tr ng-repeat="item in info.Body" ng-class="{danger:!item.Posted, warning:$index==selected}"
ng-click="setSelected($index)">
<td class="no-wrap">{{item.Date}}</td> <td class="no-wrap">{{item.Date}}</td>
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="no-wrap">{{item.Type}}</td> <td class="no-wrap">{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
<td class="right no-wrap">{{item.Debit}}</td> <td class="text-right no-wrap">{{item.Debit | currency | clr}}</td>
<td class="right no-wrap">{{item.Credit}}</td> <td class="text-right no-wrap">{{item.Credit | currency | clr}}</td>
<td class="right no-wrap">{{item.Running}}</td> <td class="text-right no-wrap">{{item.Running | accounting}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
@@ -67,9 +68,9 @@
<td>{{info.Footer.Name}}</td> <td>{{info.Footer.Name}}</td>
<td>{{info.Footer.Type}}</td> <td>{{info.Footer.Type}}</td>
<td>{{info.Footer.Narration}}</td> <td>{{info.Footer.Narration}}</td>
<td class="right">{{info.Footer.Debit}}</td> <td class="text-right no-wrap">{{info.Footer.Debit | currency}}</td>
<td class="right">{{info.Footer.Credit}}</td> <td class="text-right no-wrap">{{info.Footer.Credit | currency}}</td>
<td class="right">{{info.Footer.Running}}</td> <td class="text-right no-wrap">{{info.Footer.Running | accounting}}</td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
@@ -39,8 +39,8 @@
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<td>{{item.Type}}</td> <td>{{item.Type}}</td>
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.Debit}}</td> <td class="text-right">{{item.Debit | accounting}}</td>
<td class="right">{{item.Credit}}</td> <td class="text-right">{{item.Credit | accounting}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+1 -1
View File
@@ -55,7 +55,7 @@
<tbody id="tbodyMain"> <tbody id="tbodyMain">
<tr ng-repeat="journal in voucher.Journals | journalDebit:1"> <tr ng-repeat="journal in voucher.Journals | journalDebit:1">
<td>{{journal.Ledger.Name}}</td> <td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td> <td class="text-right">{{journal.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i <a class="btn btn-danger" ng-click="removeJournal(journal)"><i
@@ -45,12 +45,12 @@
<th>Particulars</th> <th>Particulars</th>
<th>Type</th> <th>Type</th>
<th>Narration</th> <th>Narration</th>
<th class="right">Debit Q</th> <th class="text-right">Debit Q</th>
<th class="right">Debit A</th> <th class="text-right">Debit A</th>
<th class="right">Credit Q</th> <th class="text-right">Credit Q</th>
<th class="right">Credit A</th> <th class="text-right">Credit A</th>
<th class="right">Running Q</th> <th class="text-right">Running Q</th>
<th class="right">Running A</th> <th class="text-right">Running A</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -59,26 +59,26 @@
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Type}}</td> <td>{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
<td class="right">{{item.DebitQ}}</td> <td class="text-right">{{item.DebitQ | number:2 | clr}}</td>
<td class="right">{{item.DebitA}}</td> <td class="text-right">{{item.DebitA | currency | clr}}</td>
<td class="right">{{item.CreditQ}}</td> <td class="text-right">{{item.CreditQ | number:2 | clr}}</td>
<td class="right">{{item.CreditA}}</td> <td class="text-right">{{item.CreditA | currency | clr}}</td>
<td class="right">{{item.RunningQ}}</td> <td class="text-right">{{item.RunningQ | number:2}}</td>
<td class="right">{{item.RunningA}}</td> <td class="text-right">{{item.RunningA | currency}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<td>{{info.Footer.Date}}</td> <td class="no-wrap">{{info.Footer.Date}}</td>
<td>{{info.Footer.Name}}</td> <td>{{info.Footer.Name}}</td>
<td>{{info.Footer.Type}}</td> <td>{{info.Footer.Type}}</td>
<td>{{info.Footer.Narration}}</td> <td>{{info.Footer.Narration}}</td>
<td class="right">{{info.Footer.DebitQ}}</td> <td class="text-right">{{info.Footer.DebitQ | number:2}}</td>
<td class="right">{{info.Footer.DebitA}}</td> <td class="text-right">{{info.Footer.DebitA | currency}}</td>
<td class="right">{{info.Footer.CreditQ}}</td> <td class="text-right">{{info.Footer.CreditQ | number:2}}</td>
<td class="right">{{info.Footer.CreditA}}</td> <td class="text-right">{{info.Footer.CreditA | currency}}</td>
<td class="right">{{info.Footer.RunningQ}}</td> <td class="text-right">{{info.Footer.RunningQ | number:2}}</td>
<td class="right">{{info.Footer.RunningA}}</td> <td class="text-right">{{info.Footer.RunningA | currency}}</td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
@@ -40,16 +40,16 @@
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<td>{{item.Group}}</td> <td>{{item.Group}}</td>
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td> <td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="right">{{item.Amount}}</td> <td class="text-right">{{item.Amount | currency | clr}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr ng-repeat="item in info.Footer"> <tr ng-repeat="item in info.Footer">
<td><strong>{{item.Group}}</strong></td> <td><strong>{{item.Group}}</strong></td>
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td> <td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="right"><strong>{{item.Amount}}</strong></td> <td class="text-right"><strong>{{item.Amount | currency | clr}}</strong></td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
@@ -32,21 +32,21 @@
<th>Date</th> <th>Date</th>
<th>Supplier</th> <th>Supplier</th>
<th>Product</th> <th>Product</th>
<th class="right">Quantity</th> <th class="text-right">Quantity</th>
<th class="right">Rate</th> <th class="text-right">Rate</th>
<th class="right">Tax</th> <th class="text-right">Tax</th>
<th class="right">Amount</th> <th class="text-right">Amount</th>
</tr> </tr>
</thead> </thead>
<tbody ng-repeat="items in info.Body"> <tbody ng-repeat="items in info.Body">
<tr ng-repeat="item in items.Products"> <tr ng-repeat="item in items.Products">
<td ng-if="$first" rowspan="{{items.Products.length}}">{{items.Date}}</td> <td ng-if="$first" rowspan="{{items.Products.length}}" class="no-wrap">{{items.Date}}</td>
<td ng-if="$first" rowspan="{{items.Products.length}}"><a href="{{items.Url}}">{{items.Supplier}}</a></td> <td ng-if="$first" rowspan="{{items.Products.length}}"><a href="{{items.Url}}">{{items.Supplier}}</a></td>
<td>{{item.Product}}</td> <td>{{item.Product}}</td>
<td class="right">{{item.Quantity}}</td> <td class="text-right">{{item.Quantity | number:2}}</td>
<td class="right">{{item.Rate}}</td> <td class="text-right">{{item.Rate | currency}}</td>
<td class="right">{{item.Tax}}</td> <td class="text-right">{{item.Tax | percent}}</td>
<td class="right">{{item.Amount}}</td> <td class="text-right">{{item.Amount | currency}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -57,11 +57,11 @@
<tbody id="tbodyMain"> <tbody id="tbodyMain">
<tr ng-repeat="inventory in voucher.Inventories"> <tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td> <td>{{inventory.Product.Name}}</td>
<td>{{inventory.Quantity}}</td> <td class="text-right">{{inventory.Quantity | number:2}}</td>
<td>{{inventory.Rate}}</td> <td class="text-right">{{inventory.Rate | currency}}</td>
<td>{{inventory.Tax}}</td> <td class="text-right">{{inventory.Tax | percent}}</td>
<td>{{inventory.Discount}}</td> <td class="text-right">{{inventory.Discount | percent}}</td>
<td>{{inventory.Amount}}</td> <td class="text-right">{{inventory.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeInventory(inventory)"><i <a class="btn btn-danger" ng-click="removeInventory(inventory)"><i
+6 -6
View File
@@ -19,7 +19,7 @@
<input type="text" class="form-control" ng-model="journal.Ledger" <input type="text" class="form-control" ng-model="journal.Ledger"
typeahead="account as account.Name for account in accounts($viewValue)" typeahead="account as account.Name for account in accounts($viewValue)"
typeahead-editable="false"/><span class="input-group-addon">₹</span> typeahead-editable="false"/><span class="input-group-addon">₹</span>
<input type="text" class="form-control" placeholder="Amount" ng-model="journal.Amount"/> <input type="text" class="form-control" placeholder="Amount" value="{{journal.Amount | number:2}}"/>
</div> </div>
</div> </div>
</div> </div>
@@ -63,11 +63,11 @@
<tbody id="tbodyMain"> <tbody id="tbodyMain">
<tr ng-repeat="inventory in voucher.Inventories"> <tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td> <td>{{inventory.Product.Name}}</td>
<td>{{inventory.Quantity}}</td> <td class="text-right">{{inventory.Quantity | number:2}}</td>
<td>{{inventory.Rate}}</td> <td class="text-right">{{inventory.Rate | currency}}</td>
<td>{{inventory.Tax}}</td> <td class="text-right">{{inventory.Tax | percent}}</td>
<td>{{inventory.Discount}}</td> <td class="text-right">{{inventory.Discount | percent}}</td>
<td>{{inventory.Amount}}</td> <td class="text-right">{{inventory.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeInventory(inventory)"><i <a class="btn btn-danger" ng-click="removeInventory(inventory)"><i
@@ -31,18 +31,18 @@
<tr> <tr>
<th>Product</th> <th>Product</th>
<th>Group</th> <th>Group</th>
<th class="right">Quantity</th> <th class="text-right">Quantity</th>
<th class="right">Net</th> <th class="text-right">Net</th>
<th class="right">Gross</th> <th class="text-right">Gross</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body" ng-class="{true:'error', false:''}[item.Heading]"> <tr ng-repeat="item in info.Body" ng-class="{true:'warning', false:''}[item.Heading]">
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Group}}</td> <td>{{item.Group}}</td>
<td class="right">{{item.Quantity}}</td> <td class="text-right">{{item.Quantity | number:2}}</td>
<td class="right">{{item.Net}}</td> <td class="text-right">{{item.Net | currency}}</td>
<td class="right">{{item.Gross}}</td> <td class="text-right">{{item.Gross | currency}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -38,17 +38,17 @@
<tbody> <tbody>
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="right">{{item.Issue}}</td> <td class="text-right">{{item.Issue | currency}}</td>
<td class="right">{{item.Sale}}</td> <td class="text-right">{{item.Sale | currency}}</td>
<td class="right">{{item.Rmc}}</td> <td class="text-right">{{item.Rmc | percent}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr ng-repeat="item in info.Footer"> <tr ng-repeat="item in info.Footer">
<td>{{item.Name}}</td> <td>{{item.Name}}</td>
<td class="right">{{item.Issue}}</td> <td class="text-right">{{item.Issue | currency}}</td>
<td class="right">{{item.Sale}}</td> <td class="text-right">{{item.Sale | currency}}</td>
<td class="right">{{item.Rmc}}</td> <td class="text-right">{{item.Rmc | percent}}</td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
+1 -1
View File
@@ -55,7 +55,7 @@
<tbody id="tbodyMain"> <tbody id="tbodyMain">
<tr ng-repeat="journal in voucher.Journals | journalDebit:-1"> <tr ng-repeat="journal in voucher.Journals | journalDebit:-1">
<td>{{journal.Ledger.Name}}</td> <td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td> <td class="text-right">{{journal.Amount | currency}}</td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i <a class="btn btn-danger" ng-click="removeJournal(journal)"><i
@@ -0,0 +1,99 @@
<form class="form-horizontal" role=form>
<h2>Reconciliation</h2>
<div class="form-group">
<label for="txtStartDate" class="col-md-2 control-label">Date</label>
<div class="col-md-5">
<div class="input-group">
<input class="form-control" id="txtStartDate" type="text" datepicker-popup="dd-MMM-yyyy"
ng-model="info.StartDate"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<div class="col-md-5">
<div class="input-group">
<input type="text" id="txtFinishDate" class="form-control" datepicker-popup="dd-MMM-yyyy"
ng-model="info.FinishDate"/>
<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="txtLedger" class="col-md-2 control-label">Ledger</label>
<div class="col-md-10">
<div class="input-group">
<input type="text" id="txtLedger" class="form-control" ng-model="info.Account"
typeahead="account as account.Name for account in accounts($viewValue)"
typeahead-editable="false" on-return="show()" typeahead-min-length="0"/>
<span class="input-group-btn">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i>
</button>
</span>
</div>
</div>
</div>
<table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Date</th>
<th>Particulars</th>
<th>Debit</th>
<th>Credit</th>
<th>Running</th>
<th>Reconcile Date</th>
</tr>
</thead>
<tbody ng-repeat="item in info.Body">
<tr ng-class="{warning:item.IsReconciled}">
<td class="no-wrap">{{item.Date}}</td>
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right no-wrap">{{item.Debit | currency | clr}}</td>
<td class="text-right no-wrap">{{item.Credit | currency | clr}}</td>
<td class="text-right no-wrap">{{item.Running | accounting}}</td>
<td class="col-md-3">
<div class="input-group">
<span class="input-group-addon">
<input type="checkbox" ng-model="item.IsReconciled">
</span>
<input type="text" class="form-control" datepicker-popup="dd-MMM-yyyy"
ng-model="item.ReconcileDate"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</td>
</tr>
<tr>
<td colspan="6"ng-class="{warning:item.IsReconciled}">
<blockquote>
<p>{{item.Narration}}</p>
<small>{{item.Type}}</small>
</blockquote>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="no-wrap">{{info.Footer.Date}}</td>
<td>{{info.Footer.Name}}</td>
<td class="text-right no-wrap">{{info.Footer.Debit | currency}}</td>
<td class="text-right no-wrap">{{info.Footer.Credit | currency}}</td>
<td class="text-right no-wrap">{{info.Footer.Running | accounting}}</td>
<td></td>
</tr>
</tfoot>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-info" ng-click="downloadTable()">Download <i
class="glyphicon glyphicon-download-alt"></i></button>
</div>
</div>
</form>
+36 -1
View File
@@ -34,9 +34,44 @@
</div> </div>
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<button class="btn btn-block btn-danger" ng-click="rebaseData()">Rebase <i <button class="btn btn-block btn-danger" ng-click="confirmRebase()">Rebase <i
class="glyphicon glyphicon-fire"></i></button> class="glyphicon glyphicon-fire"></i></button>
</div> </div>
</div> </div>
<div class="form-group">
<label for="txtResetDate" class="col-md-2 control-label">Reset Stock</label>
<div class="col-md-2">
<div class="input-group">
<input class="form-control" id="txtResetDate" type="text" datepicker-popup="dd-MMM-yyyy"
ng-model="resetDate"/>
<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">
<div class="input-group">
<input class="form-control" type="text" datepicker-popup="dd-MMM-yyyy" ng-model="stockDate"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<div class="col-md-4">
<input type="text" id="txtProduct" class="form-control" ng-model="product"
typeahead="product as product.Name for product in products($viewValue)"
typeahead-editable="false"/>
</div>
<div class="col-md-1">
<input type="text" class="form-control" placeholder="Qty" ng-model="qty"/>
</div>
<div class="col-md-1">
<button class="btn btn-block btn-danger" ng-click="confirmResetStock()">Reset <i
class="glyphicon glyphicon-paperclip"></i></button>
</div>
</div>
</form> </form>
@@ -28,10 +28,10 @@
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body">
<th>{{item.Type}}</th> <td>{{item.Type}}</td>
<th><a href="{{item.Url}}">{{item.Name}}</a></th> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<th>{{item.Debit}}</th> <td class="text-right">{{item.Debit | accounting}}</td>
<th>{{item.Credit}}</th> <td class="text-right">{{item.Credit | accounting}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+7 -7
View File
@@ -9,21 +9,21 @@
<th>Type</th> <th>Type</th>
<th>Narration</th> <th>Narration</th>
<th>Debit</th> <th>Debit</th>
<th class="right">Amount</th> <th class="text-right">Amount</th>
<th>Credit</th> <th>Credit</th>
<th class="right">Amount</th> <th class="text-right">Amount</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info"> <tr ng-repeat="item in info">
<td></td> <td></td>
<td><a href="{{item.Url}}">{{item.Date}}</a></td> <td class="no-wrap"><a href="{{item.Url}}">{{item.Date}}</a></td>
<td>{{item.Type}}</td> <td>{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
<td class="right">{{item.DebitN}}</td> <td class="text-right">{{item.DebitN}}</td>
<td class="right">{{item.DebitA}}</td> <td class="text-right">{{item.DebitA | currency}}</td>
<td class="right">{{item.CreditN}}</td> <td class="text-right">{{item.CreditN}}</td>
<td class="right">{{item.CreditA}}</td> <td class="text-right">{{item.CreditA | currency}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+33 -1
View File
@@ -141,4 +141,36 @@ overlord_directive.directive('onReturn', function () {
} }
}); });
}; };
}); });
overlord_directive.directive('tanSse', ['$parse', function ($parse) {
return{
restrict: 'EM',
link: function ($scope, element, attrs) {
var url = attrs.url,
subScope = $scope.$new(),
statusSetter = $parse($scope.status).assign;
$scope.$on('$destroy', function () {
subScope.close();
subScope.$destroy();
});
subScope.source = new EventSource(url);
subScope.source.onopen = function (e) {
statusSetter($scope, 'Open');
subScope.$emit('sse:open');
};
subScope.source.onmessage = function (e) {
var data = JSON.parse(e.data);
subScope.$emit('sse:message', data);
};
subScope.source.onerror = function (e) {
statusSetter($scope, 'Closed');
subScope.$emit('sse:error');
};
source.addEventListener('message', function (e) {
console.log(e.data);
}, false);
}
};
}]);
+37 -13
View File
@@ -60,7 +60,7 @@ overlord_filter.filter('localTime', function () {
Oct: 10, Oct: 10,
Nov: 11, Nov: 11,
Dec: 12 Dec: 12
} };
var months_reverse = { var months_reverse = {
1: 'Jan', 1: 'Jan',
2: 'Feb', 2: 'Feb',
@@ -74,19 +74,12 @@ overlord_filter.filter('localTime', function () {
10: 'Oct', 10: 'Oct',
11: 'Nov', 11: 'Nov',
12: 'Dec' 12: 'Dec'
} };
function padNumber(input, length) { function padNumber(input, width) {
if (typeof input === 'number'){ input = input + '';
input = '' + input; width = width || 2;
} return input.length >= width ? input : new Array(width - input.length + 1).join('0') + input;
if (typeof length === 'undefined' || !length) {
length = 2;
}
while (input.length < length) {
input = '0' + input;
}
return input;
} }
return function (input) { return function (input) {
@@ -104,3 +97,34 @@ overlord_filter.filter('localTime', function () {
}; };
}); });
overlord_filter.filter('percent', ['numberFilter', function (numberFilter) {
return function (input) {
if (!angular.isNumber(input)) {
return input;
}
return numberFilter(input * 100, 2) + '%';
};
}]);
overlord_filter.filter('clr', function () {
return function (input) {
if (input === '\u20B9\u00A00.00' || input === '0.00') {
return '';
}
return input;
};
});
overlord_filter.filter('accounting', ['currencyFilter', function (currencyFilter) {
return function (amount) {
amount = currencyFilter(amount);
if (amount === '') {
return '';
}
if (amount.indexOf('-') !== -1) {
return amount.replace('-', '') + '\u00A0Cr';
} else {
return amount + '\u00A0Dr';
}
};
}]);
+4
View File
@@ -33,6 +33,10 @@ overlord_service.factory('Ledger', ['$resource', function ($resource) {
return $resource('/api/Ledger/:id'); return $resource('/api/Ledger/:id');
}]); }]);
overlord_service.factory('Reconcile', ['$resource', function ($resource) {
return $resource('/api/Reconcile/:id', {id: '@Account.LedgerID'});
}]);
overlord_service.factory('ProductLedger', ['$resource', function ($resource) { overlord_service.factory('ProductLedger', ['$resource', function ($resource) {
return $resource('/api/ProductLedger/:id'); return $resource('/api/ProductLedger/:id');
}]); }]);
@@ -31,6 +31,9 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/Ledger', {templateUrl: '/partial/ledger.html', controller: LedgerCtrl, resolve: LedgerCtrl.resolve}). when('/Ledger', {templateUrl: '/partial/ledger.html', controller: LedgerCtrl, resolve: LedgerCtrl.resolve}).
when('/Ledger/:id', {templateUrl: '/partial/ledger.html', controller: LedgerCtrl, resolve: LedgerCtrl.resolve}). when('/Ledger/:id', {templateUrl: '/partial/ledger.html', controller: LedgerCtrl, resolve: LedgerCtrl.resolve}).
when('/Reconcile', {templateUrl: '/partial/reconcile.html', controller: ReconcileCtrl, resolve: ReconcileCtrl.resolve}).
when('/Reconcile/:id', {templateUrl: '/partial/reconcile.html', controller: ReconcileCtrl, resolve: ReconcileCtrl.resolve}).
when('/ProductLedger', {templateUrl: '/partial/product-ledger.html', controller: ProductLedgerCtrl, resolve: ProductLedgerCtrl.resolve}). when('/ProductLedger', {templateUrl: '/partial/product-ledger.html', controller: ProductLedgerCtrl, resolve: ProductLedgerCtrl.resolve}).
when('/ProductLedger/:id', {templateUrl: '/partial/product-ledger.html', controller: ProductLedgerCtrl, resolve: ProductLedgerCtrl.resolve}). when('/ProductLedger/:id', {templateUrl: '/partial/product-ledger.html', controller: ProductLedgerCtrl, resolve: ProductLedgerCtrl.resolve}).
+2 -2
View File
@@ -203,5 +203,5 @@ var PaymentModalCtrl = ['$scope', '$modalInstance', '$q', 'edit', 'Account', fun
deferred.resolve(result); deferred.resolve(result);
}); });
return deferred.promise; return deferred.promise;
} };
}] }];
+110
View File
@@ -0,0 +1,110 @@
'use strict';
var ReconcileCtrl = ['$scope', '$routeParams', '$location', '$q', 'dateFilter', 'reconcile', 'Reconcile', 'Account', function ($scope, $routeParams, $location, $q, dateFilter, reconcile, Reconcile, Account) {
$scope.info = reconcile;
$scope.show = function () {
var id = $scope.info.Account.LedgerID;
var start_date = angular.isDate($scope.info.StartDate) ? dateFilter($scope.info.StartDate, 'dd-MMM-yyyy') : $scope.info.StartDate;
var finish_date = angular.isDate($scope.info.FinishDate) ? dateFilter($scope.info.FinishDate, 'dd-MMM-yyyy') : $scope.info.FinishDate;
if (id === $routeParams.id && start_date === $routeParams.StartDate && finish_date === $routeParams.FinishDate) {
Reconcile.get({id: id, StartDate: start_date, FinishDate: finish_date}, function (data) {
$scope.info = data;
});
} else {
$location.path('/Reconcile/' + id).search('StartDate', start_date).search('FinishDate', finish_date);
}
};
$scope.save = function () {
var i, l,
len = $scope.info.Body.length;
for (i = 0, l = len; i < l; i++) {
if (angular.isDate($scope.info.Body[i].ReconcileDate)) {
$scope.info.Body[i].ReconcileDate = dateFilter($scope.info.Body[i].ReconcileDate, 'dd-MMM-yyyy');
}
}
$scope.info.$save({StartDate: $routeParams.StartDate, FinishDate: $routeParams.FinishDate}, function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$scope.info = u;
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.downloadTable = function () {
var table = $('#gvGrid'),
html = table.clone().wrap('<div></div>').parent().html();
html = html.replace(/á/g, '&aacute;');
window.open('data:application/vnd.ms-excel;charset=UTF-8,' + encodeURIComponent(html));
};
if ($routeParams.id) {
$('#gvGrid').focus();
} else {
$('#txtLedger').focus();
}
$scope.selected = -1;
$scope.setSelected = function (index) {
$scope.selected = index;
};
$scope.shortcuts = {
'up': function () {
if ($scope.selected > 0) {
$scope.$apply(function () {
$scope.selected = $scope.selected -= 1;
});
}
},
'down': function () {
if ($scope.selected < $scope.info.Body.length - 1) {
$scope.$apply(function () {
$scope.selected = $scope.selected += 1;
});
}
},
'alt+r': function () {
console.log('alt+r');
},
'enter': function () {
var path = $scope.info.Body[$scope.selected].Url.replace(/^(?:\/\/|[^\/]+)*/, "");
$scope.$apply(function () {
$location.path(path).search('StartDate', null).search('FinishDate', null);
});
},
'alt+u': function () {
console.log('alt+u');
}
};
$scope.accounts = function ($viewValue) {
var deferred = $q.defer();
Account.autocomplete({term: $viewValue, count: 20, r:true}, function (result) {
deferred.resolve(result);
});
return deferred.promise;
};
}];
ReconcileCtrl.resolve = {
reconcile: ['$q', '$route', 'Reconcile', function ($q, $route, Reconcile) {
var deferred = $q.defer();
var id = $route.current.params.id;
var start_date = $route.current.params.StartDate;
var finish_date = $route.current.params.FinishDate;
var successCb = function (result) {
deferred.resolve(result);
};
if (typeof id === 'undefined') {
Reconcile.get({}, successCb);
} else {
Reconcile.get({id: id, StartDate: start_date, FinishDate: finish_date}, successCb);
}
return deferred.promise;
}]
};
+73 -1
View File
@@ -1,6 +1,6 @@
'use strict'; 'use strict';
var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scope, $http, dateFilter, lockDate) { var SettingsCtrl = ['$scope', '$http', '$q', 'dateFilter', '$modal', 'lockDate', 'Product', function ($scope, $http, $q, dateFilter, $modal, lockDate, Product) {
$scope.lockDate = lockDate.data['Lock Date']; $scope.lockDate = lockDate.data['Lock Date'];
$scope.rebaseDate = ''; $scope.rebaseDate = '';
$scope.setLockDate = function () { $scope.setLockDate = function () {
@@ -28,6 +28,26 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scop
}); });
}; };
$scope.confirmRebase = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.title = "Rebase Data";
$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.rebaseData();
});
};
$scope.rebaseData = function () { $scope.rebaseData = function () {
if ($scope.rebaseDate === '') { if ($scope.rebaseDate === '') {
return; return;
@@ -43,6 +63,58 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scop
$scope.toasts.push({Type: 'Danger', Message: errorMessage}); $scope.toasts.push({Type: 'Danger', Message: errorMessage});
}); });
}; };
$scope.confirmResetStock = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.title = "Reset Stock";
$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.resetStock();
});
};
$scope.resetStock = function () {
if (angular.isUndefined($scope.resetDate) || $scope.resetDate === '') {
return;
}
if (angular.isUndefined($scope.stockDate) || $scope.stockDate === '') {
return;
}
if (angular.isUndefined($scope.product) || $scope.product === '') {
return;
}
if (angular.isUndefined($scope.qty) || $scope.qty === '') {
return;
}
var resetDate = angular.isDate($scope.resetDate) ? dateFilter($scope.resetDate, 'dd-MMM-yyyy') : $scope.resetDate;
var stockDate = angular.isDate($scope.stockDate) ? dateFilter($scope.stockDate, 'dd-MMM-yyyy') : $scope.stockDate;
var qty = Number($scope.qty);
$http({method: 'POST', url: '/api/ResetStock/' + $scope.product.ProductID, params: {StockDate: stockDate, ResetDate: resetDate, Quantity: qty}}).
success(function (data) {
$scope.toasts.push({Type: 'Success', Message: 'Data rebased!'});
}).
error(function (errorMessage) {
$scope.toasts.push({Type: 'Danger', Message: errorMessage});
});
};
$scope.products = function ($viewValue) {
var deferred = $q.defer();
Product.autocomplete({term: $viewValue, count: 20}, function (result) {
deferred.resolve(result);
});
return deferred.promise;
};
}]; }];
SettingsCtrl.resolve = { SettingsCtrl.resolve = {
@@ -34,6 +34,7 @@
<script src="/js/chosen.min.js"></script> <script src="/js/chosen.min.js"></script>
<script src="/js/angular.min-1.2.0-rc.1.js"></script> <script src="/js/angular.min-1.2.0-rc.1.js"></script>
<script src="/js/angular-locale_en-in-1.2.0-rc.1.js"></script>
<script src="/js/angular-animate.min-1.2.0-rc.1.js"></script> <script src="/js/angular-animate.min-1.2.0-rc.1.js"></script>
<script src="/js/angular-cookies.min-1.2.0-rc.1.js"></script> <script src="/js/angular-cookies.min-1.2.0-rc.1.js"></script>
<script src="/js/angular-resource.min-1.2.0-rc.1.js"></script> <script src="/js/angular-resource.min-1.2.0-rc.1.js"></script>
@@ -69,6 +70,7 @@
<script src="/script/employee-functions.js"></script> <script src="/script/employee-functions.js"></script>
<script src="/script/attendance.js"></script> <script src="/script/attendance.js"></script>
<script src="/script/ledger.js"></script> <script src="/script/ledger.js"></script>
<script src="/script/reconcile.js"></script>
<script src="/script/product-ledger.js"></script> <script src="/script/product-ledger.js"></script>
<script src="/script/trial-balance.js"></script> <script src="/script/trial-balance.js"></script>
<script src="/script/net-transactions.js"></script> <script src="/script/net-transactions.js"></script>
@@ -133,6 +135,7 @@
class="caret"></b></a> class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="/Ledger">Display Ledger</a></li> <li><a href="/Ledger">Display Ledger</a></li>
<li><a href="/Reconcile">Ledger Reconcilliation</a></li>
<li><a href="/ProductLedger">Product Ledger</a></li> <li><a href="/ProductLedger">Product Ledger</a></li>
<li><a href="/CashFlow">Cash Flow</a></li> <li><a href="/CashFlow">Cash Flow</a></li>
<li><a href="/Daybook">Day Book</a></li> <li><a href="/Daybook">Day Book</a></li>
+81
View File
@@ -0,0 +1,81 @@
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_
from sqlalchemy.orm import aliased, joinedload
import transaction
from brewman.models import DBSession
from brewman.models.master import LedgerBase, CostCenter, Product, Ledger
from brewman.models.validation_exception import TryCatchFunction
from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, Attendance
__author__ = 'tanshu'
@view_config(request_method='POST', route_name='api_reset_stock', renderer='json', permission='Authenticated')
#@view_config(request_method='POST', route_name='api_reset_stock', renderer='json', permission='Reset Stock')
@TryCatchFunction
def rebase(request):
product = Product.by_id(uuid.UUID(request.matchdict['id']))
quantity = round(Decimal(request.GET['Quantity']), 2)
stock_date = datetime.datetime.strptime(request.GET['StockDate'], '%d-%b-%Y')
reset_date = datetime.datetime.strptime(request.GET['ResetDate'], '%d-%b-%Y')
change = quantity - get_closing_stock(product, stock_date)
report = build_report(product, reset_date)
transaction.commit()
return {}
def build_report(product, start_date):
query = DBSession.query(Voucher, Batch, Journal).options(
joinedload(Voucher.journals, innerjoin=True),
joinedload(Voucher.inventories, innerjoin=True),
joinedload(Inventory.batch, 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(Voucher.date >= start_date).order_by(Voucher.date.desc()).all()
for voucher, inventory, batch, journal in query:
pass
#journalDebit = journal.debit * -1
#name = journal.costcenter.name if voucher.type == VoucherType.by_name(
# 'Issue').id else journal.ledger.name
#debitQ = "{0:.2f}".format(inventory.quantity) if journalDebit == 1 else ""
#debitA = "\u20B9 {0:.2f}".format(inventory.amount) if journalDebit == 1 else ""
#creditQ = "{0:.2f}".format(inventory.quantity) if journalDebit != 1 else ""
#creditA = "\u20B9 {0:.2f}".format(inventory.amount) if journalDebit != 1 else ""
#
#runningTotalQ += (inventory.quantity * journalDebit)
#runningTotalA += (inventory.amount * journalDebit)
#
#if journalDebit == 1:
# totalDebitQ += inventory.quantity
# totalDebitA += inventory.amount
#else:
# totalCreditQ += inventory.quantity
# totalCreditA += inventory.amount
#
#info['Body'].append(
# {'Date': row.Voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, row.Voucher),
# 'Type': VoucherType.by_id(row.Voucher.type).name, 'Narration': row.Voucher.narration, 'DebitQ': debitQ,
# 'DebitA': debitA,
# 'CreditQ': creditQ, 'CreditA': creditA, 'RunningQ': "{0:.2f}".format(runningTotalQ),
# 'RunningA': "\u20B9 {0:.2f}".format(runningTotalA)})
def get_closing_stock(product, finish_date):
query = DBSession.query(func.sum(Inventory.quantity * Journal.debit)) \
.join(Voucher) \
.filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product.id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Voucher.date <= finish_date) \
.one()
return 0 if query is None else query[0]
+5 -3
View File
@@ -94,14 +94,16 @@ def show_term(request):
type = int(type) if type is not None else None type = int(type) if type is not None else None
filter = request.GET.get('term', None) filter = request.GET.get('term', None)
filter = filter if filter is not None and filter is not '' else None filter = filter if filter is not None and filter is not '' else None
is_reconcilable = request.GET.get('r', None)
is_reconcilable = is_reconcilable if is_reconcilable is not None else None
count = request.GET.get('count', None) count = request.GET.get('count', None)
count = None if count is None or count == '' else int(count) count = None if count is None or count == '' else int(count)
return ledger_list(type, filter, count) return ledger_list(type, filter, count, is_reconcilable)
def ledger_list(type=None, filter=None, count=None): def ledger_list(type=None, filter=None, count=None, is_reconcilable=None):
list = [] list = []
for index, item in enumerate(LedgerBase.list(type, filter)): for index, item in enumerate(LedgerBase.list(type, filter, is_reconcilable)):
list.append({'LedgerID': item.id, 'Name': item.name}) list.append({'LedgerID': item.id, 'Name': item.name})
if count is not None and index == count - 1: if count is not None and index == count - 1:
break break
@@ -9,7 +9,7 @@ from brewman.models.master import LedgerType, LedgerBase
from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.reports.closing_stock import get_closing_stock from brewman.views.reports.closing_stock import get_closing_stock
from brewman.views.reports.profit_loss import get_accumulated_profit from brewman.views.reports.profit_loss import get_accumulated_profit
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_finish
@view_config(request_method='GET', route_name='balance_sheet', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='balance_sheet', renderer='brewman:templates/angular_base.mako',
@@ -41,16 +41,14 @@ def build_balance_sheet(finish_date):
# Add Net Profit / Loss # Add Net Profit / Loss
closing_stock = get_closing_stock(finish_date) closing_stock = get_closing_stock(finish_date)
net_profit = get_accumulated_profit(finish_date) - closing_stock net_profit = get_accumulated_profit(finish_date) - closing_stock
#net_profit = get_accumulated_profit(finish_date)
total_amount = net_profit total_amount = net_profit
report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit', report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit', 'SubAmount': net_profit, 'Order': 79})
'SubAmount': "\u20B9 {0:,.2f}".format(net_profit), 'Order': 79})
capital_group = LedgerType.by_id(5) capital_group = LedgerType.by_id(5)
groups[capital_group.id] = {'Group': capital_group.name, 'Amount': total_amount, 'Order': capital_group.order} groups[capital_group.id] = {'Group': capital_group.name, 'Amount': total_amount, 'Order': capital_group.order}
total_amount += closing_stock total_amount += closing_stock
report.append({'Name': 'Closing Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(closing_stock), 'Order': 20.001}) report.append({'Name': 'Closing Stock', 'SubAmount': closing_stock, 'Order': 20.001})
asset_group = LedgerType.by_id(4) asset_group = LedgerType.by_id(4)
groups[asset_group.id] = {'Group': asset_group.name, 'Amount': closing_stock, 'Order': asset_group.order} groups[asset_group.id] = {'Group': asset_group.name, 'Amount': closing_stock, 'Order': asset_group.order}
@@ -73,8 +71,7 @@ def build_balance_sheet(finish_date):
if amount != 0: if amount != 0:
counter += .001 counter += .001
report.append( report.append(
{'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount), {'Name': ledger.name, 'SubAmount': amount, 'Order': ledger_type.order + counter})
'Order': ledger_type.order + counter})
if ledger_type.id in groups: if ledger_type.id in groups:
groups[ledger_type.id]['Amount'] += amount groups[ledger_type.id]['Amount'] += amount
else: else:
@@ -82,8 +79,7 @@ def build_balance_sheet(finish_date):
# Add Subtotals # Add Subtotals
for item in groups.values(): for item in groups.values():
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
report.append(item) report.append(item)
footer = [{'Name': 'Total', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100}] footer = [{'Name': 'Total', 'Amount': total_amount, 'Order': 100}]
return sorted(report, key=lambda d: d['Order']), footer return sorted(report, key=lambda d: d['Order']), footer
+13 -15
View File
@@ -58,23 +58,22 @@ def build_report(request, start_date, finish_date):
.group_by(LedgerBase.type)\ .group_by(LedgerBase.type)\
.order_by(func.sum(Journal.signed_amount)).all() .order_by(func.sum(Journal.signed_amount)).all()
totalInflow = 0 total_inflow = 0
totalOutflow = 0 total_outflow = 0
for ledgerType, amount in query: for ledgerType, amount in query:
lt = LedgerType.by_id(ledgerType) lt = LedgerType.by_id(ledgerType)
inflow = "\u20B9 {0:.2f}".format(amount * -1) if amount < 0 else "" inflow = amount * -1 if amount < 0 else 0
outflow = "\u20B9 {0:.2f}".format(amount) if amount >= 0 else "" outflow = amount if amount >= 0 else 0
totalInflow += (amount * -1) if amount < 0 else 0 total_inflow += (amount * -1) if amount < 0 else 0
totalOutflow += amount if amount >= 0 else 0 total_outflow += amount if amount >= 0 else 0
report['Body'].append({'Name': lt.name, 'Url': request.route_url('cash_flow_id', id=str(lt.id), report['Body'].append({'Name': lt.name, 'Url': request.route_url('cash_flow_id', id=str(lt.id),
_query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow}) _query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow})
report['Footer'].append({'Name': 'Total', 'Inflow': "\u20B9 {0:.2f}".format(totalInflow), report['Footer'].append({'Name': 'Total', 'Inflow': total_inflow, 'Outflow': total_outflow})
'Outflow': "\u20B9 {0:.2f}".format(totalOutflow)})
netInflow = totalInflow - totalOutflow net_inflow = total_inflow - total_outflow
report['Footer'].append({'Name': 'Net', 'Inflow': ("\u20B9 {0:.2f}".format(netInflow) if netInflow >= 0 else ""), report['Footer'].append({'Name': 'Net', 'Inflow': (net_inflow if net_inflow >= 0 else 0),
'Outflow': ("\u20B9 {0:.2f}".format(netInflow * -1) if netInflow < 0 else "")}) 'Outflow': (net_inflow * -1 if net_inflow < 0 else 0)})
return report return report
@@ -102,13 +101,12 @@ def build_report_id(request, ledger_type, start_date, finish_date):
totalInflow = 0 totalInflow = 0
totalOutflow = 0 totalOutflow = 0
for ledger, amount in query: for ledger, amount in query:
inflow = "\u20B9 {0:.2f}".format(amount * -1) if amount < 0 else "" inflow = amount * -1 if amount < 0 else 0
outflow = "\u20B9 {0:.2f}".format(amount) if amount >= 0 else "" outflow = amount if amount >= 0 else 0
totalInflow += (amount * -1) if amount < 0 else 0 totalInflow += (amount * -1) if amount < 0 else 0
totalOutflow += amount if amount >= 0 else 0 totalOutflow += amount if amount >= 0 else 0
report['Body'].append({'Name': ledger.name, 'Url': request.route_url('ledger_id', id=ledger.id, report['Body'].append({'Name': ledger.name, 'Url': request.route_url('ledger_id', id=ledger.id,
_query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow}) _query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow})
report['Footer'].append({'Name': 'Total', 'Inflow': "\u20B9 {0:.2f}".format(totalInflow), report['Footer'].append({'Name': 'Total', 'Inflow': totalInflow, 'Outflow': totalOutflow})
'Outflow': "\u20B9 {0:.2f}".format(totalOutflow)})
return report return report
@@ -44,7 +44,7 @@ def build_report(date):
for product, quantity, amount in query: for product, quantity, amount in query:
if quantity != 0 and amount != 0: if quantity != 0 and amount != 0:
body.append({'Product': product.full_name, 'Group': product.product_group.name, body.append({'Product': product.full_name, 'Group': product.product_group.name,
'Quantity': "{0:,.2f}".format(quantity), 'Amount': "\u20B9 {0:,.2f}".format(amount)}) 'Quantity': quantity, 'Amount': amount})
return body return body
+9 -9
View File
@@ -1,5 +1,5 @@
import datetime import datetime
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from pyramid.view import view_config from pyramid.view import view_config
@@ -7,8 +7,9 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish, session_period_start from brewman.views.services.session import session_period_finish, session_period_start
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='daybook', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='daybook', renderer='brewman:templates/angular_base.mako',
permission='Daybook') permission='Daybook')
def daybook_get(request): def daybook_get(request):
return {} return {}
@@ -27,11 +28,11 @@ def daybook_report(request):
def build_report(request, start_date, finish_date): def build_report(request, start_date, finish_date):
report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': []} report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': []}
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True))\ query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
.filter(Voucher.type != VoucherType.by_name('Issue').id)\ .filter(Voucher.type != VoucherType.by_name('Issue').id) \
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all() .order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
for voucher in query: for voucher in query:
debit = 0 debit = 0
@@ -51,6 +52,5 @@ def build_report(request, start_date, finish_date):
report['Body'].append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher), report['Body'].append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher),
'Type': VoucherType.by_id(voucher.type).name, 'Type': VoucherType.by_id(voucher.type).name,
'Narration': voucher.narration, 'Posted': voucher.posted, 'Narration': voucher.narration, 'Posted': voucher.posted,
'DebitN': nameDebit, 'DebitA': "\u20B9\u00A0{0:.2f}".format(debit), 'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit, 'CreditA': credit})
'CreditN': nameCredit,'CreditA': "\u20B9\u00A0{0:.2f}".format(credit)})
return report return report
+38 -47
View File
@@ -1,5 +1,5 @@
import datetime import datetime
from sqlalchemy.orm import joinedload_all from sqlalchemy.orm import joinedload_all
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
import uuid import uuid
@@ -13,10 +13,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='ledger_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='ledger_id', renderer='brewman:templates/angular_base.mako',
permission='Ledger') permission='Ledger')
@view_config(request_method='GET', route_name='ledger', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='ledger', renderer='brewman:templates/angular_base.mako',
permission='Ledger') permission='Ledger')
def html(request): def html(request):
return {} return {}
@@ -40,78 +41,68 @@ def show_data(request):
build_report(request, info) build_report(request, info)
return info return info
def build_report(request, info): def build_report(request, info):
ledger_id = info['Ledger']['LedgerID'] ledger_id = info['Ledger']['LedgerID']
start_date = info['StartDate'] start_date = info['StartDate']
finish_date = info['FinishDate'] finish_date = info['FinishDate']
totalDebit, totalCredit, runningTotal, opening = opening_balance(ledger_id, start_date) total_debit, total_credit, running_total, opening = opening_balance(ledger_id, start_date)
info['Body'].append(opening) info['Body'].append(opening)
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True))\ query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
.filter(Voucher.journals.any(Journal.ledger_id == ledger_id))\ .filter(Voucher.journals.any(Journal.ledger_id == ledger_id)) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
.filter(Voucher.type != VoucherType.by_name('Issue').id)\ .filter(Voucher.type != VoucherType.by_name('Issue').id) \
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all() .order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
for voucher in query: for voucher in query:
debit = 0 debit = 0
credit = 0 credit = 0
journalDebit = 0 journal_debit = 0
name = "" name = ""
for journal in voucher.journals: for journal in voucher.journals:
if journal.ledger_id == ledger_id: if journal.ledger_id == ledger_id:
if voucher.posted: if voucher.posted:
runningTotal += (journal.amount * journal.debit) running_total += (journal.amount * journal.debit)
journalDebit = journal.debit journal_debit = journal.debit
if journal.debit == 1: if journal.debit == 1:
debit = "\u20B9 {0:,.2f}".format(journal.amount) debit = journal.amount
totalDebit += journal.amount total_debit += journal.amount
credit = "" credit = ""
else: else:
credit = "\u20B9 {0:,.2f}".format(journal.amount) credit = journal.amount
totalCredit += journal.amount total_credit += journal.amount
debit = "" debit = ""
for journal in voucher.journals: for journal in voucher.journals:
if journal.debit != journalDebit: if journal.debit != journal_debit:
name += "{0} / ".format(journal.ledger.name) name += "{0} / ".format(journal.ledger.name)
name = name[:-3] name = name[:-3]
running = "\u20B9\u00A0{0:,.2f}".format(abs(runningTotal)) + (' Dr' if runningTotal >= 0 else ' Cr')
info['Body'].append( info['Body'].append(
{'Date': voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, voucher), {'Date': voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, voucher),
'Type': VoucherType.by_id(voucher.type).name, 'Narration': voucher.narration, 'Debit': debit, 'Type': VoucherType.by_id(voucher.type).name, 'Narration': voucher.narration, 'Debit': debit,
'Credit': credit, 'Running': running, 'Posted': voucher.posted}) 'Credit': credit, 'Running': running_total, 'Posted': voucher.posted})
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance',
'Narration': '', 'Debit': "\u20B9 {0:,.2f}".format(totalDebit), 'Narration': '', 'Debit': total_debit, 'Credit': total_credit,
'Credit': "\u20B9 {0:,.2f}".format(totalCredit), 'Running': running_total, 'Posted': True}
'Running': "\u20B9 {0:,.2f}".format(abs(runningTotal)) + (
' Dr' if runningTotal >= 0 else ' Cr'),
'Posted': True}
def opening_balance(ledgerID, start_date): def opening_balance(ledgerID, start_date):
runningTotal = 0 opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \
opening = DBSession.query(func.sum(Journal.amount * Journal.debit))\ .join(Journal.voucher) \
.join(Journal.voucher)\ .filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.type != VoucherType.by_name('Issue').id) \
.filter(Voucher.type != VoucherType.by_name('Issue').id)\ .filter(Journal.ledger_id == ledgerID) \
.filter(Journal.ledger_id == ledgerID)\ .scalar()
.scalar() opening = 0 if opening is None else opening
if opening is None or opening == 0: if opening < 0:
creditShow = "" credit = opening * -1
debitShow = "" debit = 0
elif opening < 0:
creditShow = "\u20B9 {0:.2f}".format(opening * -1)
debitShow = ""
runningTotal = opening
else: else:
debitShow = "\u20B9 {0:.2f}".format(opening) debit = opening
creditShow = "" credit = 0
runningTotal = opening return 0, 0, opening, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
running = "\u20B9 {0:,.2f}".format(abs(runningTotal)) + (' Dr' if runningTotal >= 0 else ' Cr') 'Narration': '', 'Debit': debit, 'Credit': credit, 'Running': opening, 'Posted': True}
return 0, 0, runningTotal, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
'Narration': '', 'Debit': debitShow, 'Credit': creditShow,
'Running': running, 'Posted': True}
@@ -45,6 +45,5 @@ def build_report(start_date, finish_date):
for ledger, amount in query: for ledger, amount in query:
if amount != 0: if amount != 0:
tag = 'Debit' if amount > 0 else 'Credit' tag = 'Debit' if amount > 0 else 'Credit'
val = "\u20B9 {0:,.2f} Dr".format(amount) if amount > 0 else "\u20B9 {0:,.2f} Cr".format(amount * -1) body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag: amount})
body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag: val})
return body return body
+30 -31
View File
@@ -1,5 +1,5 @@
import datetime import datetime
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
import uuid import uuid
@@ -12,10 +12,11 @@ from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
from brewman.views.services.voucher import get_edit_url from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='product_ledger_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_ledger_id', renderer='brewman:templates/angular_base.mako',
permission='Product Ledger') permission='Product Ledger')
@view_config(request_method='GET', route_name='product_ledger', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_ledger', renderer='brewman:templates/angular_base.mako',
permission='Product Ledger') permission='Product Ledger')
def html(request): def html(request):
return {} return {}
@@ -54,23 +55,23 @@ def build_report(request, info):
query = DBSession.query(Voucher, Inventory, Journal).options( query = DBSession.query(Voucher, Inventory, Journal).options(
joinedload(Journal.ledger, innerjoin=True), joinedload(Journal.ledger, innerjoin=True),
joinedload(Journal.costcenter, innerjoin=True))\ joinedload(Journal.costcenter, innerjoin=True)) \
.filter(Voucher.id == Inventory.voucher_id)\ .filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id)\ .filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product_id)\ .filter(Inventory.product_id == product_id) \
.filter(Journal.cost_center_id != CostCenter.cost_center_purchase())\ .filter(Journal.cost_center_id != CostCenter.cost_center_purchase()) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_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() .order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
for row in query: for row in query:
journalDebit = row.Journal.debit * -1 journalDebit = row.Journal.debit * -1
name = row.Journal.costcenter.name if row.Voucher.type == VoucherType.by_name( name = row.Journal.costcenter.name if row.Voucher.type == VoucherType.by_name(
'Issue').id else row.Journal.ledger.name 'Issue').id else row.Journal.ledger.name
debitQ = "{0:.2f}".format(row.Inventory.quantity) if journalDebit == 1 else "" debitQ = row.Inventory.quantity if journalDebit == 1 else 0
debitA = "\u20B9 {0:.2f}".format(row.Inventory.amount) if journalDebit == 1 else "" debitA = row.Inventory.amount if journalDebit == 1 else 0
creditQ = "{0:.2f}".format(row.Inventory.quantity) if journalDebit != 1 else "" creditQ = row.Inventory.quantity if journalDebit != 1 else 0
creditA = "\u20B9 {0:.2f}".format(row.Inventory.amount) if journalDebit != 1 else "" creditA = row.Inventory.amount if journalDebit != 1 else 0
runningTotalQ += (row.Inventory.quantity * journalDebit) runningTotalQ += (row.Inventory.quantity * journalDebit)
runningTotalA += (row.Inventory.amount * journalDebit) runningTotalA += (row.Inventory.amount * journalDebit)
@@ -85,30 +86,28 @@ def build_report(request, info):
info['Body'].append( info['Body'].append(
{'Date': row.Voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, row.Voucher), {'Date': row.Voucher.date.strftime('%d-%b-%Y'), 'Name': name, 'Url': get_edit_url(request, row.Voucher),
'Type': VoucherType.by_id(row.Voucher.type).name, 'Narration': row.Voucher.narration, 'DebitQ': debitQ, 'Type': VoucherType.by_id(row.Voucher.type).name, 'Narration': row.Voucher.narration, 'DebitQ': debitQ,
'DebitA': debitA, 'DebitA': debitA, 'CreditQ': creditQ, 'CreditA': creditA, 'RunningQ': runningTotalQ,
'CreditQ': creditQ, 'CreditA': creditA, 'RunningQ': "{0:.2f}".format(runningTotalQ), 'RunningA': runningTotalA})
'RunningA': "\u20B9 {0:.2f}".format(runningTotalA)})
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', 'Narration': '', info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', 'Narration': '',
'DebitQ': "{0:,.2f}".format(totalDebitQ), 'DebitA': "\u20B9 {0:,.2f}".format(totalDebitA), 'DebitQ': totalDebitQ, 'DebitA': totalDebitA, 'CreditQ': totalCreditQ, 'CreditA': totalCreditA,
'CreditQ': "{0:,.2f}".format(totalCreditQ), 'CreditA': "\u20B9 {0:,.2f}".format(totalCreditA), 'RunningQ': runningTotalQ, 'RunningA': runningTotalA}
'RunningQ': "{0:,.2f}".format(runningTotalQ), 'RunningA': "\u20B9 {0:,.2f}".format(runningTotalA)}
def opening_balance(product_id, start_date): def opening_balance(product_id, start_date):
quantity, amount = DBSession.query(func.sum(Inventory.quantity * Journal.debit), quantity, amount = DBSession.query(func.sum(Inventory.quantity * Journal.debit),
func.sum(Inventory.amount * Journal.debit))\ func.sum(Inventory.amount * Journal.debit)) \
.join(Voucher)\ .join(Voucher) \
.filter(Voucher.id == Inventory.voucher_id)\ .filter(Voucher.id == Inventory.voucher_id) \
.filter(Voucher.id == Journal.voucher_id)\ .filter(Voucher.id == Journal.voucher_id) \
.filter(Inventory.product_id == product_id)\ .filter(Inventory.product_id == product_id) \
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase())\ .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.one() .one()
if quantity and quantity > 0: if quantity and quantity > 0:
debitQuantity = "{0:.2f}".format(quantity) debitQuantity = quantity
debitAmount = "\u20B9 {0:.2f}".format(amount) debitAmount = amount
else: else:
debitQuantity = '' debitQuantity = ''
debitAmount = '' debitAmount = ''
+7 -10
View File
@@ -4,9 +4,9 @@ from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config from pyramid.view import view_config
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import CostCenter, LedgerType, LedgerBase from brewman.models.master import LedgerType, LedgerBase
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.reports.closing_stock import get_opening_stock, get_closing_stock from brewman.views.reports.closing_stock import get_opening_stock, get_closing_stock
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@@ -51,9 +51,8 @@ def build_profit_loss(start_date, finish_date):
closing_stock = get_closing_stock(finish_date) closing_stock = get_closing_stock(finish_date)
total_amount = (opening_stock - closing_stock) * -1 total_amount = (opening_stock - closing_stock) * -1
report.append( report.append({'Name': 'Opening Stock', 'SubAmount': opening_stock * -1, 'Order': 20.0001})
{'Name': 'Opening Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(opening_stock * -1), 'Order': 20.0001}) report.append({'Name': 'Closing Stock', 'SubAmount': closing_stock, 'Order': 29})
report.append({'Name': 'Closing Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(closing_stock), 'Order': 29})
purchase_group = LedgerType.by_id(2) purchase_group = LedgerType.by_id(2)
groups[purchase_group.id] = {'Group': purchase_group.name, 'Amount': total_amount, 'Order': purchase_group.order} groups[purchase_group.id] = {'Group': purchase_group.name, 'Amount': total_amount, 'Order': purchase_group.order}
@@ -66,8 +65,7 @@ def build_profit_loss(start_date, finish_date):
if amount != 0: if amount != 0:
counter += .001 counter += .001
report.append({'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount), report.append({'Name': ledger.name, 'SubAmount': amount, 'Order': ledger_type.order + counter})
'Order': ledger_type.order + counter})
if ledger_type.id in groups: if ledger_type.id in groups:
groups[ledger_type.id]['Amount'] += amount groups[ledger_type.id]['Amount'] += amount
else: else:
@@ -75,15 +73,14 @@ def build_profit_loss(start_date, finish_date):
# Add Subtotals # Add Subtotals
for item in groups.values(): for item in groups.values():
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
report.append(item) report.append(item)
footer = [] footer = []
# Add Net # Add Net
if total_amount > 0: if total_amount > 0:
footer.append({'Group': 'Net Profit', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100}) footer.append({'Group': 'Net Profit', 'Amount': total_amount, 'Order': 100})
else: else:
footer.append({'Group': 'Net Loss', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100}) footer.append({'Group': 'Net Loss', 'Amount': total_amount, 'Order': 100})
return sorted(report, key=lambda d: d['Order']), footer return sorted(report, key=lambda d: d['Order']), footer
@@ -10,10 +10,11 @@ from brewman.models.master import LedgerBase, CostCenter, Product, ProductGroup
from brewman.models.voucher import Voucher, Journal, Inventory from brewman.models.voucher import Voucher, Journal, Inventory
from brewman.views.services.session import session_period_start, session_period_finish from brewman.views.services.session import session_period_start, session_period_finish
@view_config(request_method='GET', route_name='raw_material_cost', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='raw_material_cost', renderer='brewman:templates/angular_base.mako',
permission='Raw Material Cost') permission='Raw Material Cost')
@view_config(request_method='GET', route_name='raw_material_cost_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='raw_material_cost_id', renderer='brewman:templates/angular_base.mako',
permission='Raw Material Cost') permission='Raw Material Cost')
def get_html(request): def get_html(request):
return {} return {}
@@ -25,7 +26,7 @@ def report_blank(request):
@view_config(request_method='GET', route_name='api_raw_material_cost', request_param='StartDate', renderer='json', @view_config(request_method='GET', route_name='api_raw_material_cost', request_param='StartDate', renderer='json',
permission='Raw Material Cost') permission='Raw Material Cost')
def report_data(request): def report_data(request):
start_date = request.GET.get('StartDate', None) start_date = request.GET.get('StartDate', None)
finish_date = request.GET.get('FinishDate', None) finish_date = request.GET.get('FinishDate', None)
@@ -33,7 +34,7 @@ def report_data(request):
@view_config(request_method='GET', route_name='api_raw_material_cost_id', request_param='StartDate', renderer='json', @view_config(request_method='GET', route_name='api_raw_material_cost_id', request_param='StartDate', renderer='json',
permission='Raw Material Cost') permission='Raw Material Cost')
def report_id(request): def report_id(request):
id = request.matchdict.get('id', None) id = request.matchdict.get('id', None)
start_date = request.GET.get('StartDate', None) start_date = request.GET.get('StartDate', None)
@@ -47,14 +48,14 @@ def build_report(request, start_date, finish_date):
sum_issue = func.sum(case([(LedgerBase.type == 2, Journal.signed_amount)], else_=0)).label('Issue') sum_issue = func.sum(case([(LedgerBase.type == 2, Journal.signed_amount)], else_=0)).label('Issue')
sum_sale = (func.sum(case([(LedgerBase.type == 3, Journal.signed_amount)], else_=0)) * -1).label('Sale') sum_sale = (func.sum(case([(LedgerBase.type == 3, Journal.signed_amount)], else_=0)) * -1).label('Sale')
query = DBSession.query(CostCenter, sum_issue, sum_sale)\ query = DBSession.query(CostCenter, sum_issue, sum_sale) \
.join(CostCenter.journals).join(Journal.voucher).join(Journal.ledger)\ .join(CostCenter.journals).join(Journal.voucher).join(Journal.ledger) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_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_center_id != CostCenter.cost_center_purchase()) \
.filter(LedgerBase.type.in_([2, 3]))\ .filter(LedgerBase.type.in_([2, 3])) \
.group_by(CostCenter)\ .group_by(CostCenter) \
.order_by(sum_sale.desc()).all() .order_by(sum_sale.desc()).all()
issues = 0 issues = 0
sales = 0 sales = 0
@@ -63,13 +64,12 @@ def build_report(request, start_date, finish_date):
sales += sale sales += sale
rmc = 0 if sale == 0 else issue / sale rmc = 0 if sale == 0 else issue / sale
report['Body'].append( report['Body'].append(
{'Name': cost_center.name, 'Url': request.route_url('raw_material_cost_id', id=str(cost_center.id), {'Name': cost_center.name, 'Issue': issue, 'Sale': sale, 'Rmc': rmc,
_query={'StartDate': start_date, 'FinishDate': finish_date}), 'Issue': "\u20B9 {0:.2f}".format(issue), 'Url': request.route_url('raw_material_cost_id', id=str(cost_center.id),
'Sale': "\u20B9 {0:.2f}".format(sale), 'Rmc': "\u20B9 {0:.2%}".format(rmc)}) _query={'StartDate': start_date, 'FinishDate': finish_date})})
rmc = 0 if sales == 0 else issues / sales rmc = 0 if sales == 0 else issues / sales
report['Footer'].append({'Name': 'Total', 'Issue': "\u20B9 {0:.2f}".format(issues), report['Footer'].append({'Name': 'Total', 'Issue': issues, 'Sale': sales, 'Rmc': rmc})
'Sale': "\u20B9 {0:.2f}".format(sales), 'Rmc': "\u20B9 {0:.2%}".format(rmc)})
return report return report
@@ -81,14 +81,14 @@ def build_report_id(request, cost_center_id, start_date, finish_date):
sum_net = func.sum(Inventory.rate * Inventory.quantity * Journal.debit).label('Net') sum_net = func.sum(Inventory.rate * Inventory.quantity * Journal.debit).label('Net')
sum_gross = func.sum(Inventory.amount * Journal.debit).label('Gross') sum_gross = func.sum(Inventory.amount * Journal.debit).label('Gross')
query = DBSession.query(Product, sum_quantity, sum_net, sum_gross)\ query = DBSession.query(Product, sum_quantity, sum_net, sum_gross) \
.join(Product.inventories).join(Inventory.voucher).join(Voucher.journals).join(Product.product_group)\ .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals).join(Product.product_group) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\ .filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\ .filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
.filter(Voucher.type == 3)\ .filter(Voucher.type == 3) \
.filter(Journal.cost_center_id == cost_center_id)\ .filter(Journal.cost_center_id == cost_center_id) \
.group_by(Product).group_by(Journal.debit).group_by(ProductGroup.name)\ .group_by(Product).group_by(Journal.debit).group_by(ProductGroup.name) \
.order_by(ProductGroup.name).order_by(sum_net.desc()).all() .order_by(ProductGroup.name).order_by(sum_net.desc()).all()
groups = {} groups = {}
counter = 0 counter = 0
@@ -104,13 +104,10 @@ def build_report_id(request, cost_center_id, start_date, finish_date):
groups[product.product_group_id] = group groups[product.product_group_id] = group
counter += 1 counter += 1
list.append( list.append(
{'Name': product.full_name, 'Group': product.product_group.name, 'Quantity': "{0:.2f}".format(quantity), {'Name': product.full_name, 'Group': product.product_group.name, 'Quantity': quantity, 'Net': net,
'Net': "\u20B9 {0:,.2f}".format(net), 'Gross': "\u20B9 {0:,.2f}".format(gross), 'Order': counter, 'Gross': gross, 'Order': counter, 'Heading': False})
'Heading': False})
for item in groups.values(): for item in groups.values():
item['Net'] = "\u20B9 {0:,.2f}".format(item['Net'])
item['Gross'] = "\u20B9 {0:,.2f}".format(item['Gross'])
list.append(item) list.append(item)
report['Body'] = sorted(list, key=lambda d: d['Order']) report['Body'] = sorted(list, key=lambda d: d['Order'])
+132
View File
@@ -0,0 +1,132 @@
import datetime
from sqlalchemy.orm import joinedload_all
from sqlalchemy.sql.expression import func
import uuid
from pyramid.view import view_config
import transaction
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_start, session_period_finish
from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='reconcile_id', renderer='brewman:templates/angular_base.mako',
permission='Reconcile')
@view_config(request_method='GET', route_name='reconcile', renderer='brewman:templates/angular_base.mako',
permission='Reconcile')
def html(request):
return {}
@view_config(request_method='GET', route_name='api_reconcile', renderer='json', permission='Reconcile')
def show_blank(request):
return {'StartDate': session_period_start(request),
'FinishDate': session_period_finish(request), 'Ledger': None, 'Body': [], 'Footer': {}}
@view_config(request_method='GET', route_name='api_reconcile_id', renderer='json', permission='Reconcile')
@TryCatchFunction
def show_data(request):
id = request.matchdict['id']
account = LedgerBase.by_id(uuid.UUID(id))
start_date = request.GET.get('StartDate', session_period_start(request))
finish_date = request.GET.get('FinishDate', session_period_finish(request))
info = {'StartDate': start_date, 'FinishDate': finish_date,
'Account': {'LedgerID': account.id, 'Name': account.name},
'Body': [], 'Footer': {}}
build_report(request, info)
return info
def build_report(request, info):
ledger_id = info['Account']['LedgerID']
start_date = info['StartDate']
finish_date = info['FinishDate']
total_debit, total_credit, running_total, opening = opening_balance(ledger_id, start_date)
info['Body'].append(opening)
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
.filter(Voucher.journals.any(Journal.ledger_id == ledger_id)) \
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
.order_by(Voucher.reconcile_date).order_by(Voucher.last_edit_date).all()
for voucher in query:
debit = 0
credit = 0
journal_debit = 0
name = ""
for journal in voucher.journals:
if journal.ledger_id == ledger_id:
if voucher.posted:
running_total += (journal.amount * journal.debit)
journal_debit = journal.debit
if journal.debit == 1:
debit = journal.amount
total_debit += journal.amount
credit = ""
else:
credit = journal.amount
total_credit += journal.amount
debit = ""
for journal in voucher.journals:
if journal.debit != journal_debit:
name += "{0} / ".format(journal.ledger.name)
name = name[:-3]
info['Body'].append(
{'VoucherID': voucher.id, 'Date': voucher.date.strftime('%d-%b-%Y'), 'Name': name,
'Url': get_edit_url(request, voucher), 'Type': VoucherType.by_id(voucher.type).name,
'Narration': voucher.narration, 'Debit': debit, 'Credit': credit, 'Running': running_total,
'ReconcileDate': voucher.reconcile_date.strftime('%d-%b-%Y'), 'IsReconciled': voucher.is_reconciled})
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance',
'Narration': '', 'Debit': total_debit, 'Credit': total_credit,
'Running': running_total, 'Posted': True}
def opening_balance(ledgerID, start_date):
opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \
.join(Journal.voucher) \
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
.filter(Journal.ledger_id == ledgerID) \
.scalar()
opening = 0 if opening is None else opening
if opening < 0:
credit = opening * -1
debit = 0
else:
debit = opening
credit = 0
return 0, 0, opening, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
'Narration': '', 'Debit': debit, 'Credit': credit, 'Running': opening, 'Posted': True}
@view_config(request_method='POST', route_name='api_reconcile_id', renderer='json', permission='Reconcile')
def save(request):
id = request.matchdict['id']
account = LedgerBase.by_id(uuid.UUID(id))
start_date = request.GET.get('StartDate', session_period_start(request))
finish_date = request.GET.get('FinishDate', session_period_finish(request))
for item in request.json_body['Body']:
if 'VoucherID' not in item:
continue
voucher = Voucher.by_id(uuid.UUID(item['VoucherID']))
is_reconciled = item['IsReconciled']
reconcile_date = datetime.datetime.strptime(item['ReconcileDate'], '%d-%b-%Y')
voucher.is_reconciled = is_reconciled
voucher.reconcile_date = reconcile_date
transaction.commit()
info = {'StartDate': start_date, 'FinishDate': finish_date,
'Account': {'LedgerID': account.id, 'Name': account.name},
'Body': [], 'Footer': {}}
build_report(request, info)
return info
@@ -40,6 +40,5 @@ def build_report(date):
for ledger, amount in query: for ledger, amount in query:
if amount != 0: if amount != 0:
tag = 'Debit' if amount > 0 else 'Credit' tag = 'Debit' if amount > 0 else 'Credit'
val = "\u20B9 {0:,.2f} Dr".format(amount) if amount > 0 else "\u20B9 {0:,.2f} Cr".format(amount * -1) body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag:amount})
body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag:val})
return body return body
+1 -2
View File
@@ -41,7 +41,6 @@ def build_report(request):
body.append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher), body.append({'Date': voucher.date.strftime('%d-%b-%Y'), 'Url': get_edit_url(request, voucher),
'Type': VoucherType.by_id(voucher.type).name, 'Type': VoucherType.by_id(voucher.type).name,
'Narration': voucher.narration, 'Posted': voucher.posted, 'Narration': voucher.narration, 'Posted': voucher.posted,
'DebitN': nameDebit, 'DebitA': "\u20B9 {0:.2f}".format(debit), 'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit,'CreditA': credit})
'CreditN': nameCredit,'CreditA': "\u20B9 {0:.2f}".format(credit)})
return body return body
@@ -153,8 +153,8 @@ def voucher_info(voucher):
'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'), 'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'),
'User': {'UserID': voucher.user.id, 'Name': voucher.user.name}, 'User': {'UserID': voucher.user.id, 'Name': voucher.user.name},
'Poster': voucher.poster.name if voucher.posted else ''} 'Poster': voucher.poster.name if voucher.posted else ''}
if voucher.reconcilliation_date is not None: if voucher.reconcile_date is not None:
json_voucher['ReconcilliationDate'] = voucher.reconcilliation_date.strftime('%d-%b-%Y %H:%M') json_voucher['ReconcileDate'] = voucher.reconcile_date.strftime('%d-%b-%Y %H:%M')
for item in voucher.journals: for item in voucher.journals:
json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount, json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount,
'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name}, 'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name},
@@ -147,8 +147,8 @@ def purchase_update_inventory(voucher, newInventories):
def purchase_update_journals(voucher, journals): def purchase_update_journals(voucher, journals):
otherLedger = [ff for ff in journals if ff['Debit'] == -1] other_ledger = [ff for ff in journals if ff['Debit'] == -1]
otherLedger = LedgerBase.by_id(uuid.UUID(otherLedger[0]['Ledger']['LedgerID'])) other_ledger = LedgerBase.by_id(uuid.UUID(other_ledger[0]['Ledger']['LedgerID']))
journals = dict() journals = dict()
amount = 0 amount = 0
for item in voucher.inventories: for item in voucher.inventories:
@@ -159,7 +159,7 @@ def purchase_update_journals(voucher, journals):
else: else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id, journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount) amount=item.amount)
journals[otherLedger.id] = Journal(debit=-1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id, journals[other_ledger.id] = Journal(debit=-1, cost_center_id=other_ledger.costcenter_id, ledger_id=other_ledger.id,
amount=amount) amount=amount)
for i in range(len(voucher.journals), 0, -1): for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1] item = voucher.journals[i - 1]
+4 -4
View File
@@ -1,7 +1,7 @@
[app:main] [app:main]
use = egg:brewman use = egg:brewman
pyramid.reload_templates = true pyramid.reload_templates = false
pyramid.debug_authorization = false pyramid.debug_authorization = false
pyramid.debug_notfound = false pyramid.debug_notfound = false
pyramid.debug_routematch = false pyramid.debug_routematch = false
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
# pyramid.includes = # pyramid.includes =
# pyramid_debugtoolbar # pyramid_debugtoolbar
# sqlalchemy.url = postgresql://hops:123456@localhost:8765/hops # sqlalchemy.url = postgresql://hops:123456@localhost:8765/hops
sqlalchemy.url = sqlite:///%(here)s/database/brewman.db sqlalchemy.url = postgresql://postgres:123456@localhost:5432/hops
[server:main] [server:main]
use = egg:waitress#main use = egg:waitress#main
@@ -28,11 +28,11 @@ keys = console
keys = generic keys = generic
[logger_root] [logger_root]
level = INFO level = WARNING
handlers = console handlers = console
[logger_brewman] [logger_brewman]
level = DEBUG level = WARNING
handlers = handlers =
qualname = brewman qualname = brewman