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:
1 parent
f8bdf9d731
commit
62918bcee5
51 files changed
+989
-313
No files matched your search
@@ -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')
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -69,7 +69,7 @@ class Voucher(Base):
|
||||
journals = relationship('Journal', 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",
|
||||
cascade_backrefs=False)
|
||||
cascade_backrefs=False)
|
||||
|
||||
def _get_type(self):
|
||||
return self._type
|
||||
@@ -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):
|
||||
@@ -167,7 +168,7 @@ class SalaryDeduction(Base):
|
||||
pf_er = Column('PfEmployer', Integer)
|
||||
|
||||
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,
|
||||
esi_ee=None, pf_ee=None, esi_er=None, pf_er=None):
|
||||
@@ -290,23 +291,23 @@ class Attendance(Base):
|
||||
return DBSession.query(cls)
|
||||
|
||||
def create(self):
|
||||
old = DBSession.query(Attendance).filter(Attendance.date == self.date)\
|
||||
.filter(Attendance.employee_id == self.employee_id)\
|
||||
.filter(Attendance.is_valid == True).first()
|
||||
old = DBSession.query(Attendance).filter(Attendance.date == self.date) \
|
||||
.filter(Attendance.employee_id == self.employee_id) \
|
||||
.filter(Attendance.is_valid == True).first()
|
||||
if old is None or old.attendance_type != self.attendance_type:
|
||||
if old is not None:
|
||||
old.is_valid = False
|
||||
DBSession.add(self)
|
||||
|
||||
|
||||
class Fingerprint(Base):
|
||||
class Fingerprint(Base):
|
||||
__tablename__ = 'entities_fingerprints'
|
||||
|
||||
id = Column('FingerprintID', GUID(), primary_key=True, default=uuid.uuid4)
|
||||
employee_id = Column('EmployeeID', GUID(), ForeignKey('entities_employees.LedgerID'))
|
||||
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.employee_id = employee_id
|
||||
self.date = date
|
||||
@@ -321,8 +322,8 @@ class Fingerprint(Base):
|
||||
return DBSession.query(cls)
|
||||
|
||||
def create(self):
|
||||
old = DBSession.query(Fingerprint).filter(Fingerprint.date == self.date)\
|
||||
.filter(Fingerprint.employee_id == self.employee_id).first()
|
||||
old = DBSession.query(Fingerprint).filter(Fingerprint.date == self.date) \
|
||||
.filter(Fingerprint.employee_id == self.employee_id).first()
|
||||
if old is None:
|
||||
DBSession.add(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">
|
||||
<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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -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}).
|
||||
|
||||
|
||||
@@ -203,5 +203,5 @@ var PaymentModalCtrl = ['$scope', '$modalInstance', '$q', 'edit', 'Account', fun
|
||||
deferred.resolve(result);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
}]
|
||||
};
|
||||
}];
|
||||
@@ -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, 'á');
|
||||
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;
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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]
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import datetime
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
|
||||
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.voucher import get_edit_url
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='daybook', renderer='brewman:templates/angular_base.mako',
|
||||
permission='Daybook')
|
||||
permission='Daybook')
|
||||
def daybook_get(request):
|
||||
return {}
|
||||
|
||||
@@ -27,11 +28,11 @@ def daybook_report(request):
|
||||
def build_report(request, start_date, finish_date):
|
||||
report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': []}
|
||||
|
||||
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True))\
|
||||
.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.date).order_by(Voucher.last_edit_date).all()
|
||||
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(finish_date, '%d-%b-%Y')) \
|
||||
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
|
||||
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
|
||||
|
||||
for voucher in query:
|
||||
debit = 0
|
||||
@@ -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
|
||||
@@ -1,5 +1,5 @@
|
||||
import datetime
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.sql.expression import func
|
||||
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.voucher import get_edit_url
|
||||
|
||||
|
||||
@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',
|
||||
permission='Ledger')
|
||||
permission='Ledger')
|
||||
def html(request):
|
||||
return {}
|
||||
|
||||
@@ -40,78 +41,68 @@ 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))\
|
||||
.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.date).order_by(Voucher.last_edit_date).all()
|
||||
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.date).order_by(Voucher.last_edit_date).all()
|
||||
|
||||
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:
|
||||
for journal in voucher.journals:
|
||||
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 = 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:
|
||||
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
|
||||
@@ -1,5 +1,5 @@
|
||||
import datetime
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.sql.expression import func
|
||||
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.voucher import get_edit_url
|
||||
|
||||
|
||||
@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',
|
||||
permission='Product Ledger')
|
||||
permission='Product Ledger')
|
||||
def html(request):
|
||||
return {}
|
||||
|
||||
@@ -54,23 +55,23 @@ def build_report(request, info):
|
||||
|
||||
query = DBSession.query(Voucher, Inventory, Journal).options(
|
||||
joinedload(Journal.ledger, innerjoin=True),
|
||||
joinedload(Journal.costcenter, 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 >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\
|
||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\
|
||||
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
|
||||
joinedload(Journal.costcenter, 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 >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
|
||||
.order_by(Voucher.date).order_by(Voucher.last_edit_date).all()
|
||||
|
||||
for row in query:
|
||||
journalDebit = row.Journal.debit * -1
|
||||
name = row.Journal.costcenter.name if row.Voucher.type == VoucherType.by_name(
|
||||
'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,30 +86,28 @@ 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):
|
||||
quantity, amount = DBSession.query(func.sum(Inventory.quantity * Journal.debit),
|
||||
func.sum(Inventory.amount * Journal.debit))\
|
||||
.join(Voucher)\
|
||||
.filter(Voucher.id == Inventory.voucher_id)\
|
||||
.filter(Voucher.id == Journal.voucher_id)\
|
||||
.filter(Inventory.product_id == product_id)\
|
||||
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase())\
|
||||
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y'))\
|
||||
.one()
|
||||
func.sum(Inventory.amount * Journal.debit)) \
|
||||
.join(Voucher) \
|
||||
.filter(Voucher.id == Inventory.voucher_id) \
|
||||
.filter(Voucher.id == Journal.voucher_id) \
|
||||
.filter(Inventory.product_id == product_id) \
|
||||
.filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
|
||||
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
||||
.one()
|
||||
|
||||
if quantity and quantity > 0:
|
||||
debitQuantity = "{0:.2f}".format(quantity)
|
||||
debitAmount = "\u20B9 {0:.2f}".format(amount)
|
||||
debitQuantity = quantity
|
||||
debitAmount = amount
|
||||
else:
|
||||
debitQuantity = ''
|
||||
debitAmount = ''
|
||||
|
||||
@@ -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,10 +10,11 @@ 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')
|
||||
permission='Raw Material Cost')
|
||||
@view_config(request_method='GET', route_name='raw_material_cost_id', renderer='brewman:templates/angular_base.mako',
|
||||
permission='Raw Material Cost')
|
||||
permission='Raw Material Cost')
|
||||
def get_html(request):
|
||||
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',
|
||||
permission='Raw Material Cost')
|
||||
permission='Raw Material Cost')
|
||||
def report_data(request):
|
||||
start_date = request.GET.get('StartDate', 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',
|
||||
permission='Raw Material Cost')
|
||||
permission='Raw Material Cost')
|
||||
def report_id(request):
|
||||
id = request.matchdict.get('id', 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_sale = (func.sum(case([(LedgerBase.type == 3, Journal.signed_amount)], else_=0)) * -1).label('Sale')
|
||||
|
||||
query = DBSession.query(CostCenter, sum_issue, sum_sale)\
|
||||
.join(CostCenter.journals).join(Journal.voucher).join(Journal.ledger)\
|
||||
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\
|
||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\
|
||||
.filter(Journal.cost_center_id != CostCenter.cost_center_purchase())\
|
||||
.filter(LedgerBase.type.in_([2, 3]))\
|
||||
.group_by(CostCenter)\
|
||||
.order_by(sum_sale.desc()).all()
|
||||
query = DBSession.query(CostCenter, sum_issue, sum_sale) \
|
||||
.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(finish_date, '%d-%b-%Y')) \
|
||||
.filter(Journal.cost_center_id != CostCenter.cost_center_purchase()) \
|
||||
.filter(LedgerBase.type.in_([2, 3])) \
|
||||
.group_by(CostCenter) \
|
||||
.order_by(sum_sale.desc()).all()
|
||||
|
||||
issues = 0
|
||||
sales = 0
|
||||
@@ -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
|
||||
|
||||
@@ -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_gross = func.sum(Inventory.amount * Journal.debit).label('Gross')
|
||||
|
||||
query = DBSession.query(Product, sum_quantity, sum_net, sum_gross)\
|
||||
.join(Product.inventories).join(Inventory.voucher).join(Voucher.journals).join(Product.product_group)\
|
||||
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'))\
|
||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y'))\
|
||||
.filter(Voucher.type == 3)\
|
||||
.filter(Journal.cost_center_id == cost_center_id)\
|
||||
.group_by(Product).group_by(Journal.debit).group_by(ProductGroup.name)\
|
||||
.order_by(ProductGroup.name).order_by(sum_net.desc()).all()
|
||||
query = DBSession.query(Product, sum_quantity, sum_net, sum_gross) \
|
||||
.join(Product.inventories).join(Inventory.voucher).join(Voucher.journals).join(Product.product_group) \
|
||||
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
|
||||
.filter(Voucher.type == 3) \
|
||||
.filter(Journal.cost_center_id == cost_center_id) \
|
||||
.group_by(Product).group_by(Journal.debit).group_by(ProductGroup.name) \
|
||||
.order_by(ProductGroup.name).order_by(sum_net.desc()).all()
|
||||
|
||||
groups = {}
|
||||
counter = 0
|
||||
@@ -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'])
|
||||
|
||||
@@ -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
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user