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
+918 -242

No files matched your search

+2
View File
@@ -105,6 +105,7 @@ def main(global_config, **settings):
config.add_route('api_fingerprint', '/api/Fingerprint')
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, '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_rebase', '/api/Rebase/{date}')
config.add_route('api_reset_stock', '/api/ResetStock/{id}')
config.add_route('api_batch', '/api/Batch')
+4 -2
View File
@@ -197,13 +197,15 @@ class LedgerBase(Base):
return DBSession.query(cls).all()
@classmethod
def list(cls, type, name):
def list(cls, type, name, is_reconcilable):
query = DBSession.query(cls)
if type is not None:
if not isinstance(type, int):
type = int(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():
query = query.filter(cls.name.ilike('%' + item + '%'))
return query.order_by(cls.name)
+12 -11
View File
@@ -52,14 +52,14 @@ class Voucher(Base):
__tablename__ = 'entities_vouchers'
id = Column('VoucherID', GUID(), primary_key=True, default=uuid.uuid4)
date = Column('Date', DateTime)
reconcilliation_date = Column('ReconcilliationDate', DateTime)
narration = Column('Narration', Unicode(1000))
posted = Column('Posted', Boolean)
creation_date = Column('CreationDate', DateTime(timezone=True))
last_edit_date = Column('LastEditDate', DateTime(timezone=True))
_type = Column('VoucherType', Integer)
date = Column('Date', DateTime, nullable=False)
reconcile_date = Column('ReconcileDate', DateTime, nullable=False)
is_reconciled = Column('IsReconciled', DateTime, nullable=False)
narration = Column('Narration', Unicode(1000), nullable=False)
posted = Column('Posted', Boolean, nullable=False)
creation_date = Column('CreationDate', DateTime(timezone=True), nullable=False)
last_edit_date = Column('LastEditDate', DateTime(timezone=True), nullable=False)
_type = Column('VoucherType', Integer, nullable=False)
user_id = Column('UserID', GUID(), ForeignKey('auth_users.UserID'), nullable=False)
poster_id = Column('PosterID', GUID(), ForeignKey('auth_users.UserID'))
@@ -90,10 +90,10 @@ class Voucher(Base):
def __name__(self):
return self.name
def __init__(self, date=None, reconcilliation_date=None, narration='', posted=False, creation_date=None,
last_edit_date=None, type=None, user_id=None, poster_id=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, is_reconciled=False):
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.posted = posted
self.creation_date = datetime.utcnow() if creation_date is None else creation_date
@@ -101,6 +101,7 @@ class Voucher(Base):
self.type = type
self.user_id = user_id
self.poster_id = poster_id
self.is_reconciled = is_reconciled
@classmethod
def by_id(cls, id):
@@ -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">
<thead>
<tr>
<th class="right">Code</th>
<th class="text-right">Code</th>
<th>Name</th>
<th>Designation</th>
<th>Department</th>
@@ -33,7 +33,7 @@
<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-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>{{item.Designation}}</td>
<td>{{item.Department}}</td>
@@ -31,16 +31,16 @@
<tr ng-repeat="item in info.Body">
<td>{{item.Group}}</td>
<td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td>
<td class="right">{{item.Amount}}</td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<td><strong>{{item.Group}}</strong></td>
<td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td>
<td class="right"><strong>{{item.Amount}}</strong></td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="text-right"><strong>{{item.Amount | currency | clr}}</strong></td>
</tr>
</tfoot>
</table>
@@ -38,15 +38,15 @@
<tbody>
<tr ng-repeat="item in info.Body">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="right">{{item.Inflow}}</td>
<td class="right">{{item.Outflow}}</td>
<td class="text-right">{{item.Inflow | currency | clr}}</td>
<td class="text-right">{{item.Outflow | currency | clr}}</td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<td>{{item.Name}}</a></td>
<td class="right">{{item.Inflow}}</td>
<td class="right">{{item.Outflow}}</td>
<td class="text-right">{{item.Inflow | currency | clr}}</td>
<td class="text-right">{{item.Outflow | currency | clr}}</td>
</tr>
</tfoot>
</table>
@@ -29,10 +29,10 @@
</thead>
<tbody>
<tr ng-repeat="item in info.Body">
<th><a href="{{item.Url}}">{{item.Product}}</a></th>
<th>{{item.Group}}</th>
<th class="right">{{item.Quantity}}</th>
<th class="right">{{item.Amount}}</th>
<td><a href="{{item.Url}}">{{item.Product}}</a></td>
<td>{{item.Group}}</td>
<td class="text-right">{{item.Quantity | number:2}}</td>
<td class="text-right">{{item.Amount | currency}}</td>
</tr>
</tbody>
</table>
+6 -6
View File
@@ -33,9 +33,9 @@
<th>Type</th>
<th>Narration</th>
<th>Debit</th>
<th class="right">Amount</th>
<th class="text-right">Amount</th>
<th>Credit</th>
<th class="right">Amount</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
@@ -43,10 +43,10 @@
<td><a href="{{item.Url}}">{{item.Date}}</a></td>
<td>{{item.Type}}</td>
<td>{{item.Narration}}</td>
<td class="right">{{item.DebitN}}</td>
<td class="right">{{item.DebitA}}</td>
<td class="right">{{item.CreditN}}</td>
<td class="right">{{item.CreditA}}</td>
<td class="text-right">{{item.DebitN}}</td>
<td class="text-right">{{item.DebitA | currency}}</td>
<td class="text-right">{{item.CreditN}}</td>
<td class="text-right">{{item.CreditA | currency}}</td>
</tr>
</tbody>
</table>
+5 -5
View File
@@ -9,7 +9,7 @@
</tr>
</thead>
<tr ng-repeat="item in smallGrid">
<td>{{item.Amount}}</td>
<td>{{item.Amount | currency}}</td>
<td>
<a class="btn btn-info" href="/Issue/{{item.VoucherID}}">Load <i
class="glyphicon glyphicon-eye-open"></i></a>
@@ -37,7 +37,7 @@
<select id="ddlDestinationCostCenter" class="form-control" ng-model="journal.CostCenter.CostCenterID"
ng-options="l.CostCenterID as l.Name for l in cost_centers"> </select>
<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>
@@ -75,9 +75,9 @@
<tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td>
<td>{{inventory.Batch.Name}}</td>
<td>{{inventory.Quantity}}</td>
<td>{{inventory.Rate}}</td>
<td>{{inventory.Amount}}</td>
<td>{{inventory.Quantity | number:2}}</td>
<td>{{inventory.Rate | currency}}</td>
<td>{{inventory.Amount | currency}}</td>
<td>
<div class="btn-group">
<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">
<td>{{journal.Debit | debit}}</td>
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td class="text-right">{{journal.Amount | currency}}</td>
<td>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
+8 -7
View File
@@ -51,14 +51,15 @@
</tr>
</thead>
<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><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="no-wrap">{{item.Type}}</td>
<td>{{item.Narration}}</td>
<td class="right no-wrap">{{item.Debit}}</td>
<td class="right no-wrap">{{item.Credit}}</td>
<td class="right no-wrap">{{item.Running}}</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>
</tr>
</tbody>
<tfoot>
@@ -67,9 +68,9 @@
<td>{{info.Footer.Name}}</td>
<td>{{info.Footer.Type}}</td>
<td>{{info.Footer.Narration}}</td>
<td class="right">{{info.Footer.Debit}}</td>
<td class="right">{{info.Footer.Credit}}</td>
<td class="right">{{info.Footer.Running}}</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>
</tr>
</tfoot>
</table>
@@ -39,8 +39,8 @@
<tr ng-repeat="item in info.Body">
<td>{{item.Type}}</td>
<td>{{item.Name}}</td>
<td class="right">{{item.Debit}}</td>
<td class="right">{{item.Credit}}</td>
<td class="text-right">{{item.Debit | accounting}}</td>
<td class="text-right">{{item.Credit | accounting}}</td>
</tr>
</tbody>
</table>
+1 -1
View File
@@ -55,7 +55,7 @@
<tbody id="tbodyMain">
<tr ng-repeat="journal in voucher.Journals | journalDebit:1">
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td class="text-right">{{journal.Amount | currency}}</td>
<td>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
@@ -45,12 +45,12 @@
<th>Particulars</th>
<th>Type</th>
<th>Narration</th>
<th class="right">Debit Q</th>
<th class="right">Debit A</th>
<th class="right">Credit Q</th>
<th class="right">Credit A</th>
<th class="right">Running Q</th>
<th class="right">Running A</th>
<th class="text-right">Debit Q</th>
<th class="text-right">Debit A</th>
<th class="text-right">Credit Q</th>
<th class="text-right">Credit A</th>
<th class="text-right">Running Q</th>
<th class="text-right">Running A</th>
</tr>
</thead>
<tbody>
@@ -59,26 +59,26 @@
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Type}}</td>
<td>{{item.Narration}}</td>
<td class="right">{{item.DebitQ}}</td>
<td class="right">{{item.DebitA}}</td>
<td class="right">{{item.CreditQ}}</td>
<td class="right">{{item.CreditA}}</td>
<td class="right">{{item.RunningQ}}</td>
<td class="right">{{item.RunningA}}</td>
<td class="text-right">{{item.DebitQ | number:2 | clr}}</td>
<td class="text-right">{{item.DebitA | currency | clr}}</td>
<td class="text-right">{{item.CreditQ | number:2 | clr}}</td>
<td class="text-right">{{item.CreditA | currency | clr}}</td>
<td class="text-right">{{item.RunningQ | number:2}}</td>
<td class="text-right">{{item.RunningA | currency}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>{{info.Footer.Date}}</td>
<td class="no-wrap">{{info.Footer.Date}}</td>
<td>{{info.Footer.Name}}</td>
<td>{{info.Footer.Type}}</td>
<td>{{info.Footer.Narration}}</td>
<td class="right">{{info.Footer.DebitQ}}</td>
<td class="right">{{info.Footer.DebitA}}</td>
<td class="right">{{info.Footer.CreditQ}}</td>
<td class="right">{{info.Footer.CreditA}}</td>
<td class="right">{{info.Footer.RunningQ}}</td>
<td class="right">{{info.Footer.RunningA}}</td>
<td class="text-right">{{info.Footer.DebitQ | number:2}}</td>
<td class="text-right">{{info.Footer.DebitA | currency}}</td>
<td class="text-right">{{info.Footer.CreditQ | number:2}}</td>
<td class="text-right">{{info.Footer.CreditA | currency}}</td>
<td class="text-right">{{info.Footer.RunningQ | number:2}}</td>
<td class="text-right">{{info.Footer.RunningA | currency}}</td>
</tr>
</tfoot>
</table>
@@ -40,16 +40,16 @@
<tr ng-repeat="item in info.Body">
<td>{{item.Group}}</td>
<td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td>
<td class="right">{{item.Amount}}</td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<td><strong>{{item.Group}}</strong></td>
<td>{{item.Name}}</td>
<td class="right">{{item.SubAmount}}</td>
<td class="right"><strong>{{item.Amount}}</strong></td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>
<td class="text-right"><strong>{{item.Amount | currency | clr}}</strong></td>
</tr>
</tfoot>
</table>
@@ -32,21 +32,21 @@
<th>Date</th>
<th>Supplier</th>
<th>Product</th>
<th class="right">Quantity</th>
<th class="right">Rate</th>
<th class="right">Tax</th>
<th class="right">Amount</th>
<th class="text-right">Quantity</th>
<th class="text-right">Rate</th>
<th class="text-right">Tax</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody ng-repeat="items in info.Body">
<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>{{item.Product}}</td>
<td class="right">{{item.Quantity}}</td>
<td class="right">{{item.Rate}}</td>
<td class="right">{{item.Tax}}</td>
<td class="right">{{item.Amount}}</td>
<td class="text-right">{{item.Quantity | number:2}}</td>
<td class="text-right">{{item.Rate | currency}}</td>
<td class="text-right">{{item.Tax | percent}}</td>
<td class="text-right">{{item.Amount | currency}}</td>
</tr>
</tbody>
</table>
@@ -57,11 +57,11 @@
<tbody id="tbodyMain">
<tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td>
<td>{{inventory.Quantity}}</td>
<td>{{inventory.Rate}}</td>
<td>{{inventory.Tax}}</td>
<td>{{inventory.Discount}}</td>
<td>{{inventory.Amount}}</td>
<td class="text-right">{{inventory.Quantity | number:2}}</td>
<td class="text-right">{{inventory.Rate | currency}}</td>
<td class="text-right">{{inventory.Tax | percent}}</td>
<td class="text-right">{{inventory.Discount | percent}}</td>
<td class="text-right">{{inventory.Amount | currency}}</td>
<td>
<div class="btn-group">
<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"
typeahead="account as account.Name for account in accounts($viewValue)"
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>
@@ -63,11 +63,11 @@
<tbody id="tbodyMain">
<tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td>
<td>{{inventory.Quantity}}</td>
<td>{{inventory.Rate}}</td>
<td>{{inventory.Tax}}</td>
<td>{{inventory.Discount}}</td>
<td>{{inventory.Amount}}</td>
<td class="text-right">{{inventory.Quantity | number:2}}</td>
<td class="text-right">{{inventory.Rate | currency}}</td>
<td class="text-right">{{inventory.Tax | percent}}</td>
<td class="text-right">{{inventory.Discount | percent}}</td>
<td class="text-right">{{inventory.Amount | currency}}</td>
<td>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeInventory(inventory)"><i
@@ -31,18 +31,18 @@
<tr>
<th>Product</th>
<th>Group</th>
<th class="right">Quantity</th>
<th class="right">Net</th>
<th class="right">Gross</th>
<th class="text-right">Quantity</th>
<th class="text-right">Net</th>
<th class="text-right">Gross</th>
</tr>
</thead>
<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>{{item.Group}}</td>
<td class="right">{{item.Quantity}}</td>
<td class="right">{{item.Net}}</td>
<td class="right">{{item.Gross}}</td>
<td class="text-right">{{item.Quantity | number:2}}</td>
<td class="text-right">{{item.Net | currency}}</td>
<td class="text-right">{{item.Gross | currency}}</td>
</tr>
</tbody>
</table>
@@ -38,17 +38,17 @@
<tbody>
<tr ng-repeat="item in info.Body">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="right">{{item.Issue}}</td>
<td class="right">{{item.Sale}}</td>
<td class="right">{{item.Rmc}}</td>
<td class="text-right">{{item.Issue | currency}}</td>
<td class="text-right">{{item.Sale | currency}}</td>
<td class="text-right">{{item.Rmc | percent}}</td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<td>{{item.Name}}</td>
<td class="right">{{item.Issue}}</td>
<td class="right">{{item.Sale}}</td>
<td class="right">{{item.Rmc}}</td>
<td class="text-right">{{item.Issue | currency}}</td>
<td class="text-right">{{item.Sale | currency}}</td>
<td class="text-right">{{item.Rmc | percent}}</td>
</tr>
</tfoot>
</table>
+1 -1
View File
@@ -55,7 +55,7 @@
<tbody id="tbodyMain">
<tr ng-repeat="journal in voucher.Journals | journalDebit:-1">
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td class="text-right">{{journal.Amount | currency}}</td>
<td>
<div class="btn-group">
<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 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>
</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>
@@ -28,10 +28,10 @@
</thead>
<tbody>
<tr ng-repeat="item in info.Body">
<th>{{item.Type}}</th>
<th><a href="{{item.Url}}">{{item.Name}}</a></th>
<th>{{item.Debit}}</th>
<th>{{item.Credit}}</th>
<td>{{item.Type}}</td>
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right">{{item.Debit | accounting}}</td>
<td class="text-right">{{item.Credit | accounting}}</td>
</tr>
</tbody>
</table>
+7 -7
View File
@@ -9,21 +9,21 @@
<th>Type</th>
<th>Narration</th>
<th>Debit</th>
<th class="right">Amount</th>
<th class="text-right">Amount</th>
<th>Credit</th>
<th class="right">Amount</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info">
<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.Narration}}</td>
<td class="right">{{item.DebitN}}</td>
<td class="right">{{item.DebitA}}</td>
<td class="right">{{item.CreditN}}</td>
<td class="right">{{item.CreditA}}</td>
<td class="text-right">{{item.DebitN}}</td>
<td class="text-right">{{item.DebitA | currency}}</td>
<td class="text-right">{{item.CreditN}}</td>
<td class="text-right">{{item.CreditA | currency}}</td>
</tr>
</tbody>
</table>
+32
View File
@@ -142,3 +142,35 @@ 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,
Nov: 11,
Dec: 12
}
};
var months_reverse = {
1: 'Jan',
2: 'Feb',
@@ -74,19 +74,12 @@ overlord_filter.filter('localTime', function () {
10: 'Oct',
11: 'Nov',
12: 'Dec'
}
};
function padNumber(input, length) {
if (typeof input === 'number'){
input = '' + input;
}
if (typeof length === 'undefined' || !length) {
length = 2;
}
while (input.length < length) {
input = '0' + input;
}
return input;
function padNumber(input, width) {
input = input + '';
width = width || 2;
return input.length >= width ? input : new Array(width - input.length + 1).join('0') + 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');
}]);
overlord_service.factory('Reconcile', ['$resource', function ($resource) {
return $resource('/api/Reconcile/:id', {id: '@Account.LedgerID'});
}]);
overlord_service.factory('ProductLedger', ['$resource', function ($resource) {
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/: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/: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);
});
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';
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.rebaseDate = '';
$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 () {
if ($scope.rebaseDate === '') {
return;
@@ -43,6 +63,58 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scop
$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 = {
@@ -34,6 +34,7 @@
<script src="/js/chosen.min.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-cookies.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/attendance.js"></script>
<script src="/script/ledger.js"></script>
<script src="/script/reconcile.js"></script>
<script src="/script/product-ledger.js"></script>
<script src="/script/trial-balance.js"></script>
<script src="/script/net-transactions.js"></script>
@@ -133,6 +135,7 @@
class="caret"></b></a>
<ul class="dropdown-menu">
<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="/CashFlow">Cash Flow</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
filter = request.GET.get('term', 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 = 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 = []
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})
if count is not None and index == count - 1:
break
@@ -9,7 +9,7 @@ from brewman.models.master import LedgerType, LedgerBase
from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.reports.closing_stock import get_closing_stock
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',
@@ -41,16 +41,14 @@ def build_balance_sheet(finish_date):
# Add Net Profit / Loss
closing_stock = get_closing_stock(finish_date)
net_profit = get_accumulated_profit(finish_date) - closing_stock
#net_profit = get_accumulated_profit(finish_date)
total_amount = net_profit
report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit',
'SubAmount': "\u20B9 {0:,.2f}".format(net_profit), 'Order': 79})
report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit', 'SubAmount': net_profit, 'Order': 79})
capital_group = LedgerType.by_id(5)
groups[capital_group.id] = {'Group': capital_group.name, 'Amount': total_amount, 'Order': capital_group.order}
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)
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:
counter += .001
report.append(
{'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount),
'Order': ledger_type.order + counter})
{'Name': ledger.name, 'SubAmount': amount, 'Order': ledger_type.order + counter})
if ledger_type.id in groups:
groups[ledger_type.id]['Amount'] += amount
else:
@@ -82,8 +79,7 @@ def build_balance_sheet(finish_date):
# Add Subtotals
for item in groups.values():
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
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
+13 -15
View File
@@ -58,23 +58,22 @@ def build_report(request, start_date, finish_date):
.group_by(LedgerBase.type)\
.order_by(func.sum(Journal.signed_amount)).all()
totalInflow = 0
totalOutflow = 0
total_inflow = 0
total_outflow = 0
for ledgerType, amount in query:
lt = LedgerType.by_id(ledgerType)
inflow = "\u20B9 {0:.2f}".format(amount * -1) if amount < 0 else ""
outflow = "\u20B9 {0:.2f}".format(amount) if amount >= 0 else ""
totalInflow += (amount * -1) if amount < 0 else 0
totalOutflow += amount if amount >= 0 else 0
inflow = amount * -1 if amount < 0 else 0
outflow = amount if amount >= 0 else 0
total_inflow += (amount * -1) if amount < 0 else 0
total_outflow += amount if amount >= 0 else 0
report['Body'].append({'Name': lt.name, 'Url': request.route_url('cash_flow_id', id=str(lt.id),
_query={'StartDate': start_date, 'FinishDate': finish_date}), 'Inflow': inflow, 'Outflow': outflow})
report['Footer'].append({'Name': 'Total', 'Inflow': "\u20B9 {0:.2f}".format(totalInflow),
'Outflow': "\u20B9 {0:.2f}".format(totalOutflow)})
report['Footer'].append({'Name': 'Total', 'Inflow': total_inflow, 'Outflow': total_outflow})
netInflow = totalInflow - totalOutflow
report['Footer'].append({'Name': 'Net', 'Inflow': ("\u20B9 {0:.2f}".format(netInflow) if netInflow >= 0 else ""),
'Outflow': ("\u20B9 {0:.2f}".format(netInflow * -1) if netInflow < 0 else "")})
net_inflow = total_inflow - total_outflow
report['Footer'].append({'Name': 'Net', 'Inflow': (net_inflow if net_inflow >= 0 else 0),
'Outflow': (net_inflow * -1 if net_inflow < 0 else 0)})
return report
@@ -102,13 +101,12 @@ def build_report_id(request, ledger_type, start_date, finish_date):
totalInflow = 0
totalOutflow = 0
for ledger, amount in query:
inflow = "\u20B9 {0:.2f}".format(amount * -1) if amount < 0 else ""
outflow = "\u20B9 {0:.2f}".format(amount) if amount >= 0 else ""
inflow = amount * -1 if amount < 0 else 0
outflow = amount if amount >= 0 else 0
totalInflow += (amount * -1) if amount < 0 else 0
totalOutflow += amount if amount >= 0 else 0
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})
report['Footer'].append({'Name': 'Total', 'Inflow': "\u20B9 {0:.2f}".format(totalInflow),
'Outflow': "\u20B9 {0:.2f}".format(totalOutflow)})
report['Footer'].append({'Name': 'Total', 'Inflow': totalInflow, 'Outflow': totalOutflow})
return report
@@ -44,7 +44,7 @@ def build_report(date):
for product, quantity, amount in query:
if quantity != 0 and amount != 0:
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
+2 -2
View File
@@ -7,6 +7,7 @@ from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.services.session import session_period_finish, session_period_start
from brewman.views.services.voucher import get_edit_url
@view_config(request_method='GET', route_name='daybook', renderer='brewman:templates/angular_base.mako',
permission='Daybook')
def daybook_get(request):
@@ -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),
'Type': VoucherType.by_id(voucher.type).name,
'Narration': voucher.narration, 'Posted': voucher.posted,
'DebitN': nameDebit, 'DebitA': "\u20B9\u00A0{0:.2f}".format(debit),
'CreditN': nameCredit,'CreditA': "\u20B9\u00A0{0:.2f}".format(credit)})
'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit, 'CreditA': credit})
return report
+22 -31
View File
@@ -13,6 +13,7 @@ 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='ledger_id', renderer='brewman:templates/angular_base.mako',
permission='Ledger')
@view_config(request_method='GET', route_name='ledger', renderer='brewman:templates/angular_base.mako',
@@ -40,11 +41,12 @@ def show_data(request):
build_report(request, info)
return info
def build_report(request, info):
ledger_id = info['Ledger']['LedgerID']
start_date = info['StartDate']
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)
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
@@ -57,61 +59,50 @@ def build_report(request, info):
for voucher in query:
debit = 0
credit = 0
journalDebit = 0
journal_debit = 0
name = ""
for journal in voucher.journals:
if journal.ledger_id == ledger_id:
if voucher.posted:
runningTotal += (journal.amount * journal.debit)
journalDebit = journal.debit
running_total += (journal.amount * journal.debit)
journal_debit = journal.debit
if journal.debit == 1:
debit = "\u20B9 {0:,.2f}".format(journal.amount)
totalDebit += journal.amount
debit = journal.amount
total_debit += journal.amount
credit = ""
else:
credit = "\u20B9 {0:,.2f}".format(journal.amount)
totalCredit += journal.amount
credit = journal.amount
total_credit += journal.amount
debit = ""
for journal in voucher.journals:
if journal.debit != journalDebit:
if journal.debit != journal_debit:
name += "{0} / ".format(journal.ledger.name)
name = name[:-3]
running = "\u20B9\u00A0{0:,.2f}".format(abs(runningTotal)) + (' Dr' if runningTotal >= 0 else ' Cr')
info['Body'].append(
{'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, 'Posted': voucher.posted})
'Credit': credit, 'Running': running_total, 'Posted': voucher.posted})
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance',
'Narration': '', 'Debit': "\u20B9 {0:,.2f}".format(totalDebit),
'Credit': "\u20B9 {0:,.2f}".format(totalCredit),
'Running': "\u20B9 {0:,.2f}".format(abs(runningTotal)) + (
' Dr' if runningTotal >= 0 else ' Cr'),
'Posted': True}
'Narration': '', 'Debit': total_debit, 'Credit': total_credit,
'Running': running_total, 'Posted': True}
def opening_balance(ledgerID, start_date):
runningTotal = 0
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()
if opening is None or opening == 0:
creditShow = ""
debitShow = ""
elif opening < 0:
creditShow = "\u20B9 {0:.2f}".format(opening * -1)
debitShow = ""
runningTotal = opening
opening = 0 if opening is None else opening
if opening < 0:
credit = opening * -1
debit = 0
else:
debitShow = "\u20B9 {0:.2f}".format(opening)
creditShow = ""
runningTotal = opening
running = "\u20B9 {0:,.2f}".format(abs(runningTotal)) + (' Dr' if runningTotal >= 0 else ' Cr')
return 0, 0, runningTotal, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
'Narration': '', 'Debit': debitShow, 'Credit': creditShow,
'Running': running, 'Posted': True}
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}
@@ -45,6 +45,5 @@ def build_report(start_date, finish_date):
for ledger, amount in query:
if amount != 0:
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: val})
body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag: amount})
return body
+11 -12
View File
@@ -12,6 +12,7 @@ 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.voucher import get_edit_url
@view_config(request_method='GET', route_name='product_ledger_id', renderer='brewman:templates/angular_base.mako',
permission='Product Ledger')
@view_config(request_method='GET', route_name='product_ledger', renderer='brewman:templates/angular_base.mako',
@@ -67,10 +68,10 @@ def build_report(request, info):
journalDebit = row.Journal.debit * -1
name = row.Journal.costcenter.name if row.Voucher.type == VoucherType.by_name(
'Issue').id else row.Journal.ledger.name
debitQ = "{0:.2f}".format(row.Inventory.quantity) if journalDebit == 1 else ""
debitA = "\u20B9 {0:.2f}".format(row.Inventory.amount) if journalDebit == 1 else ""
creditQ = "{0:.2f}".format(row.Inventory.quantity) if journalDebit != 1 else ""
creditA = "\u20B9 {0:.2f}".format(row.Inventory.amount) if journalDebit != 1 else ""
debitQ = row.Inventory.quantity if journalDebit == 1 else 0
debitA = row.Inventory.amount if journalDebit == 1 else 0
creditQ = row.Inventory.quantity if journalDebit != 1 else 0
creditA = row.Inventory.amount if journalDebit != 1 else 0
runningTotalQ += (row.Inventory.quantity * journalDebit)
runningTotalA += (row.Inventory.amount * journalDebit)
@@ -85,14 +86,12 @@ def build_report(request, info):
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)})
'DebitA': debitA, 'CreditQ': creditQ, 'CreditA': creditA, 'RunningQ': runningTotalQ,
'RunningA': runningTotalA})
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance', 'Narration': '',
'DebitQ': "{0:,.2f}".format(totalDebitQ), 'DebitA': "\u20B9 {0:,.2f}".format(totalDebitA),
'CreditQ': "{0:,.2f}".format(totalCreditQ), 'CreditA': "\u20B9 {0:,.2f}".format(totalCreditA),
'RunningQ': "{0:,.2f}".format(runningTotalQ), 'RunningA': "\u20B9 {0:,.2f}".format(runningTotalA)}
'DebitQ': totalDebitQ, 'DebitA': totalDebitA, 'CreditQ': totalCreditQ, 'CreditA': totalCreditA,
'RunningQ': runningTotalQ, 'RunningA': runningTotalA}
def opening_balance(product_id, start_date):
@@ -107,8 +106,8 @@ def opening_balance(product_id, start_date):
.one()
if quantity and quantity > 0:
debitQuantity = "{0:.2f}".format(quantity)
debitAmount = "\u20B9 {0:.2f}".format(amount)
debitQuantity = quantity
debitAmount = amount
else:
debitQuantity = ''
debitAmount = ''
+7 -10
View File
@@ -4,9 +4,9 @@ from sqlalchemy.sql.expression import func, desc
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.master import CostCenter, LedgerType, LedgerBase
from brewman.models.master import 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.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)
total_amount = (opening_stock - closing_stock) * -1
report.append(
{'Name': 'Opening Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(opening_stock * -1), 'Order': 20.0001})
report.append({'Name': 'Closing Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(closing_stock), 'Order': 29})
report.append({'Name': 'Opening Stock', 'SubAmount': opening_stock * -1, 'Order': 20.0001})
report.append({'Name': 'Closing Stock', 'SubAmount': closing_stock, 'Order': 29})
purchase_group = LedgerType.by_id(2)
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:
counter += .001
report.append({'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount),
'Order': ledger_type.order + counter})
report.append({'Name': ledger.name, 'SubAmount': amount, 'Order': ledger_type.order + counter})
if ledger_type.id in groups:
groups[ledger_type.id]['Amount'] += amount
else:
@@ -75,15 +73,14 @@ def build_profit_loss(start_date, finish_date):
# Add Subtotals
for item in groups.values():
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
report.append(item)
footer = []
# Add Net
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:
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
@@ -10,6 +10,7 @@ from brewman.models.master import LedgerBase, CostCenter, Product, ProductGroup
from brewman.models.voucher import Voucher, Journal, Inventory
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',
permission='Raw Material Cost')
@view_config(request_method='GET', route_name='raw_material_cost_id', renderer='brewman:templates/angular_base.mako',
@@ -63,13 +64,12 @@ def build_report(request, start_date, finish_date):
sales += sale
rmc = 0 if sale == 0 else issue / sale
report['Body'].append(
{'Name': cost_center.name, 'Url': request.route_url('raw_material_cost_id', id=str(cost_center.id),
_query={'StartDate': start_date, 'FinishDate': finish_date}), 'Issue': "\u20B9 {0:.2f}".format(issue),
'Sale': "\u20B9 {0:.2f}".format(sale), 'Rmc': "\u20B9 {0:.2%}".format(rmc)})
{'Name': cost_center.name, 'Issue': issue, 'Sale': sale, 'Rmc': rmc,
'Url': request.route_url('raw_material_cost_id', id=str(cost_center.id),
_query={'StartDate': start_date, 'FinishDate': finish_date})})
rmc = 0 if sales == 0 else issues / sales
report['Footer'].append({'Name': 'Total', 'Issue': "\u20B9 {0:.2f}".format(issues),
'Sale': "\u20B9 {0:.2f}".format(sales), 'Rmc': "\u20B9 {0:.2%}".format(rmc)})
report['Footer'].append({'Name': 'Total', 'Issue': issues, 'Sale': sales, 'Rmc': rmc})
return report
@@ -104,13 +104,10 @@ def build_report_id(request, cost_center_id, start_date, finish_date):
groups[product.product_group_id] = group
counter += 1
list.append(
{'Name': product.full_name, 'Group': product.product_group.name, 'Quantity': "{0:.2f}".format(quantity),
'Net': "\u20B9 {0:,.2f}".format(net), 'Gross': "\u20B9 {0:,.2f}".format(gross), 'Order': counter,
'Heading': False})
{'Name': product.full_name, 'Group': product.product_group.name, 'Quantity': quantity, 'Net': net,
'Gross': gross, 'Order': counter, 'Heading': False})
for item in groups.values():
item['Net'] = "\u20B9 {0:,.2f}".format(item['Net'])
item['Gross'] = "\u20B9 {0:,.2f}".format(item['Gross'])
list.append(item)
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:
if amount != 0:
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:val})
body.append({'Type': ledger.type_object.name, 'Name': ledger.name, tag:amount})
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),
'Type': VoucherType.by_id(voucher.type).name,
'Narration': voucher.narration, 'Posted': voucher.posted,
'DebitN': nameDebit, 'DebitA': "\u20B9 {0:.2f}".format(debit),
'CreditN': nameCredit,'CreditA': "\u20B9 {0:.2f}".format(credit)})
'DebitN': nameDebit, 'DebitA': debit, 'CreditN': nameCredit,'CreditA': credit})
return body
@@ -153,8 +153,8 @@ def voucher_info(voucher):
'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'),
'User': {'UserID': voucher.user.id, 'Name': voucher.user.name},
'Poster': voucher.poster.name if voucher.posted else ''}
if voucher.reconcilliation_date is not None:
json_voucher['ReconcilliationDate'] = voucher.reconcilliation_date.strftime('%d-%b-%Y %H:%M')
if voucher.reconcile_date is not None:
json_voucher['ReconcileDate'] = voucher.reconcile_date.strftime('%d-%b-%Y %H:%M')
for item in voucher.journals:
json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount,
'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name},
@@ -147,8 +147,8 @@ def purchase_update_inventory(voucher, newInventories):
def purchase_update_journals(voucher, journals):
otherLedger = [ff for ff in journals if ff['Debit'] == -1]
otherLedger = LedgerBase.by_id(uuid.UUID(otherLedger[0]['Ledger']['LedgerID']))
other_ledger = [ff for ff in journals if ff['Debit'] == -1]
other_ledger = LedgerBase.by_id(uuid.UUID(other_ledger[0]['Ledger']['LedgerID']))
journals = dict()
amount = 0
for item in voucher.inventories:
@@ -159,7 +159,7 @@ def purchase_update_journals(voucher, journals):
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
journals[otherLedger.id] = Journal(debit=-1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
journals[other_ledger.id] = Journal(debit=-1, cost_center_id=other_ledger.costcenter_id, ledger_id=other_ledger.id,
amount=amount)
for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1]
+4 -4
View File
@@ -1,7 +1,7 @@
[app:main]
use = egg:brewman
pyramid.reload_templates = true
pyramid.reload_templates = false
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
# pyramid.includes =
# pyramid_debugtoolbar
# 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]
use = egg:waitress#main
@@ -28,11 +28,11 @@ keys = console
keys = generic
[logger_root]
level = INFO
level = WARNING
handlers = console
[logger_brewman]
level = DEBUG
level = WARNING
handlers =
qualname = brewman