From 62918bcee5c35234f9ce71a88532955c6a755e22 Mon Sep 17 00:00:00 2001 From: Tanshu Date: Thu, 3 Oct 2013 15:42:43 +0530 Subject: [PATCH] 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 --- brewman/brewman/__init__.py | 2 + brewman/brewman/models/master.py | 6 +- brewman/brewman/models/voucher.py | 41 +++--- .../js/angular-locale_en-in-1.2.0-rc.1.js | 98 +++++++++++++ .../brewman/static/partial/attendance.html | 4 +- .../brewman/static/partial/balance-sheet.html | 8 +- brewman/brewman/static/partial/cash-flow.html | 8 +- .../brewman/static/partial/closing-stock.html | 8 +- brewman/brewman/static/partial/daybook.html | 12 +- brewman/brewman/static/partial/issue.html | 10 +- brewman/brewman/static/partial/journal.html | 2 +- brewman/brewman/static/partial/ledger.html | 15 +- .../static/partial/net-transactions.html | 4 +- brewman/brewman/static/partial/payment.html | 2 +- .../static/partial/product-ledger.html | 38 ++--- .../brewman/static/partial/profit-loss.html | 8 +- .../static/partial/purchase-entries.html | 18 +-- .../static/partial/purchase-return.html | 10 +- brewman/brewman/static/partial/purchase.html | 12 +- .../partial/raw-material-cost-detail.html | 14 +- .../static/partial/raw-material-cost.html | 12 +- brewman/brewman/static/partial/receipt.html | 2 +- brewman/brewman/static/partial/reconcile.html | 99 +++++++++++++ brewman/brewman/static/partial/settings.html | 37 ++++- .../brewman/static/partial/trial-balance.html | 8 +- brewman/brewman/static/partial/unposted.html | 14 +- .../static/scripts/angular_directive.js | 34 ++++- .../brewman/static/scripts/angular_filter.js | 50 +++++-- .../brewman/static/scripts/angular_service.js | 4 + brewman/brewman/static/scripts/overlord.js | 3 + brewman/brewman/static/scripts/payment.js | 4 +- brewman/brewman/static/scripts/reconcile.js | 110 +++++++++++++++ brewman/brewman/static/scripts/settings.js | 74 +++++++++- brewman/brewman/templates/angular_base.mako | 3 + brewman/brewman/views/Management/stock.py | 81 +++++++++++ brewman/brewman/views/account.py | 8 +- .../brewman/views/reports/balance_sheet.py | 14 +- brewman/brewman/views/reports/cash_flow.py | 28 ++-- .../brewman/views/reports/closing_stock.py | 2 +- brewman/brewman/views/reports/daybook.py | 18 +-- brewman/brewman/views/reports/ledger.py | 85 +++++------ .../brewman/views/reports/net_transactions.py | 3 +- .../brewman/views/reports/product_ledger.py | 61 ++++---- brewman/brewman/views/reports/profit_loss.py | 17 +-- .../views/reports/raw_material_cost.py | 57 ++++---- brewman/brewman/views/reports/reconcile.py | 132 ++++++++++++++++++ .../brewman/views/reports/trial_balance.py | 3 +- brewman/brewman/views/reports/unposted.py | 3 +- .../views/services/voucher/__init__.py | 4 +- .../views/services/voucher/purchase.py | 6 +- brewman/development.ini | 8 +- 51 files changed, 990 insertions(+), 314 deletions(-) create mode 100644 brewman/brewman/static/js/angular-locale_en-in-1.2.0-rc.1.js create mode 100644 brewman/brewman/static/partial/reconcile.html create mode 100644 brewman/brewman/static/scripts/reconcile.js create mode 100644 brewman/brewman/views/Management/stock.py create mode 100644 brewman/brewman/views/reports/reconcile.py diff --git a/brewman/brewman/__init__.py b/brewman/brewman/__init__.py index 05e29bfe..08ccc082 100644 --- a/brewman/brewman/__init__.py +++ b/brewman/brewman/__init__.py @@ -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') diff --git a/brewman/brewman/models/master.py b/brewman/brewman/models/master.py index 1b61a8a9..fac9a82a 100644 --- a/brewman/brewman/models/master.py +++ b/brewman/brewman/models/master.py @@ -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) diff --git a/brewman/brewman/models/voucher.py b/brewman/brewman/models/voucher.py index a680dab7..93d215c1 100644 --- a/brewman/brewman/models/voucher.py +++ b/brewman/brewman/models/voucher.py @@ -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 diff --git a/brewman/brewman/static/js/angular-locale_en-in-1.2.0-rc.1.js b/brewman/brewman/static/js/angular-locale_en-in-1.2.0-rc.1.js new file mode 100644 index 00000000..6be8b880 --- /dev/null +++ b/brewman/brewman/static/js/angular-locale_en-in-1.2.0-rc.1.js @@ -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;} +}); +}]); \ No newline at end of file diff --git a/brewman/brewman/static/partial/attendance.html b/brewman/brewman/static/partial/attendance.html index 426ca185..4329e256 100644 --- a/brewman/brewman/static/partial/attendance.html +++ b/brewman/brewman/static/partial/attendance.html @@ -21,7 +21,7 @@ - + @@ -33,7 +33,7 @@ - + diff --git a/brewman/brewman/static/partial/balance-sheet.html b/brewman/brewman/static/partial/balance-sheet.html index 47701432..e849cbe3 100644 --- a/brewman/brewman/static/partial/balance-sheet.html +++ b/brewman/brewman/static/partial/balance-sheet.html @@ -31,16 +31,16 @@ - - + + - - + +
CodeCode Name Designation Department
{{item.Code}}{{item.Code}} {{item.Name}} {{item.Designation}} {{item.Department}}
{{item.Group}} {{item.Name}}{{item.SubAmount}}{{item.Amount}}{{item.SubAmount | currency | clr}}{{item.Amount | currency | clr}}
{{item.Group}} {{item.Name}}{{item.SubAmount}}{{item.Amount}}{{item.SubAmount | currency | clr}}{{item.Amount | currency | clr}}
diff --git a/brewman/brewman/static/partial/cash-flow.html b/brewman/brewman/static/partial/cash-flow.html index 5d639dec..f83ea7dd 100644 --- a/brewman/brewman/static/partial/cash-flow.html +++ b/brewman/brewman/static/partial/cash-flow.html @@ -38,15 +38,15 @@ {{item.Name}} - {{item.Inflow}} - {{item.Outflow}} + {{item.Inflow | currency | clr}} + {{item.Outflow | currency | clr}} {{item.Name}} - {{item.Inflow}} - {{item.Outflow}} + {{item.Inflow | currency | clr}} + {{item.Outflow | currency | clr}} diff --git a/brewman/brewman/static/partial/closing-stock.html b/brewman/brewman/static/partial/closing-stock.html index bbcefef0..3d722b39 100644 --- a/brewman/brewman/static/partial/closing-stock.html +++ b/brewman/brewman/static/partial/closing-stock.html @@ -29,10 +29,10 @@ - {{item.Product}} - {{item.Group}} - {{item.Quantity}} - {{item.Amount}} + {{item.Product}} + {{item.Group}} + {{item.Quantity | number:2}} + {{item.Amount | currency}} diff --git a/brewman/brewman/static/partial/daybook.html b/brewman/brewman/static/partial/daybook.html index dc5e233b..6707f946 100644 --- a/brewman/brewman/static/partial/daybook.html +++ b/brewman/brewman/static/partial/daybook.html @@ -33,9 +33,9 @@ Type Narration Debit - Amount + Amount Credit - Amount + Amount @@ -43,10 +43,10 @@ {{item.Date}} {{item.Type}} {{item.Narration}} - {{item.DebitN}} - {{item.DebitA}} - {{item.CreditN}} - {{item.CreditA}} + {{item.DebitN}} + {{item.DebitA | currency}} + {{item.CreditN}} + {{item.CreditA | currency}} diff --git a/brewman/brewman/static/partial/issue.html b/brewman/brewman/static/partial/issue.html index 172b9eab..7b3c0de5 100644 --- a/brewman/brewman/static/partial/issue.html +++ b/brewman/brewman/static/partial/issue.html @@ -9,7 +9,7 @@ - {{item.Amount}} + {{item.Amount | currency}} Load @@ -37,7 +37,7 @@ ₹ - + @@ -75,9 +75,9 @@ {{inventory.Product.Name}} {{inventory.Batch.Name}} - {{inventory.Quantity}} - {{inventory.Rate}} - {{inventory.Amount}} + {{inventory.Quantity | number:2}} + {{inventory.Rate | currency}} + {{inventory.Amount | currency}}
{{journal.Debit | debit}} {{journal.Ledger.Name}} - {{journal.Amount}} + {{journal.Amount | currency}}
- + {{item.Date}} {{item.Name}} {{item.Type}} {{item.Narration}} - {{item.Debit}} - {{item.Credit}} - {{item.Running}} + {{item.Debit | currency | clr}} + {{item.Credit | currency | clr}} + {{item.Running | accounting}} @@ -67,9 +68,9 @@ {{info.Footer.Name}} {{info.Footer.Type}} {{info.Footer.Narration}} - {{info.Footer.Debit}} - {{info.Footer.Credit}} - {{info.Footer.Running}} + {{info.Footer.Debit | currency}} + {{info.Footer.Credit | currency}} + {{info.Footer.Running | accounting}} diff --git a/brewman/brewman/static/partial/net-transactions.html b/brewman/brewman/static/partial/net-transactions.html index e4eb8ef5..b4061bf2 100644 --- a/brewman/brewman/static/partial/net-transactions.html +++ b/brewman/brewman/static/partial/net-transactions.html @@ -39,8 +39,8 @@ {{item.Type}} {{item.Name}} - {{item.Debit}} - {{item.Credit}} + {{item.Debit | accounting}} + {{item.Credit | accounting}} diff --git a/brewman/brewman/static/partial/payment.html b/brewman/brewman/static/partial/payment.html index c3669af6..b49f7a6e 100644 --- a/brewman/brewman/static/partial/payment.html +++ b/brewman/brewman/static/partial/payment.html @@ -55,7 +55,7 @@ {{journal.Ledger.Name}} - {{journal.Amount}} + {{journal.Amount | currency}}
Particulars Type Narration - Debit Q - Debit A - Credit Q - Credit A - Running Q - Running A + Debit Q + Debit A + Credit Q + Credit A + Running Q + Running A @@ -59,26 +59,26 @@ {{item.Name}} {{item.Type}} {{item.Narration}} - {{item.DebitQ}} - {{item.DebitA}} - {{item.CreditQ}} - {{item.CreditA}} - {{item.RunningQ}} - {{item.RunningA}} + {{item.DebitQ | number:2 | clr}} + {{item.DebitA | currency | clr}} + {{item.CreditQ | number:2 | clr}} + {{item.CreditA | currency | clr}} + {{item.RunningQ | number:2}} + {{item.RunningA | currency}} - {{info.Footer.Date}} + {{info.Footer.Date}} {{info.Footer.Name}} {{info.Footer.Type}} {{info.Footer.Narration}} - {{info.Footer.DebitQ}} - {{info.Footer.DebitA}} - {{info.Footer.CreditQ}} - {{info.Footer.CreditA}} - {{info.Footer.RunningQ}} - {{info.Footer.RunningA}} + {{info.Footer.DebitQ | number:2}} + {{info.Footer.DebitA | currency}} + {{info.Footer.CreditQ | number:2}} + {{info.Footer.CreditA | currency}} + {{info.Footer.RunningQ | number:2}} + {{info.Footer.RunningA | currency}} diff --git a/brewman/brewman/static/partial/profit-loss.html b/brewman/brewman/static/partial/profit-loss.html index a99d5d46..c026b1ad 100644 --- a/brewman/brewman/static/partial/profit-loss.html +++ b/brewman/brewman/static/partial/profit-loss.html @@ -40,16 +40,16 @@ {{item.Group}} {{item.Name}} - {{item.SubAmount}} - {{item.Amount}} + {{item.SubAmount | currency | clr}} + {{item.Amount | currency | clr}} {{item.Group}} {{item.Name}} - {{item.SubAmount}} - {{item.Amount}} + {{item.SubAmount | currency | clr}} + {{item.Amount | currency | clr}} diff --git a/brewman/brewman/static/partial/purchase-entries.html b/brewman/brewman/static/partial/purchase-entries.html index 775e687d..76f58253 100644 --- a/brewman/brewman/static/partial/purchase-entries.html +++ b/brewman/brewman/static/partial/purchase-entries.html @@ -32,21 +32,21 @@ Date Supplier Product - Quantity - Rate - Tax - Amount + Quantity + Rate + Tax + Amount - {{items.Date}} + {{items.Date}} {{items.Supplier}} {{item.Product}} - {{item.Quantity}} - {{item.Rate}} - {{item.Tax}} - {{item.Amount}} + {{item.Quantity | number:2}} + {{item.Rate | currency}} + {{item.Tax | percent}} + {{item.Amount | currency}} diff --git a/brewman/brewman/static/partial/purchase-return.html b/brewman/brewman/static/partial/purchase-return.html index c31fdf98..a482a9b3 100644 --- a/brewman/brewman/static/partial/purchase-return.html +++ b/brewman/brewman/static/partial/purchase-return.html @@ -57,11 +57,11 @@ {{inventory.Product.Name}} - {{inventory.Quantity}} - {{inventory.Rate}} - {{inventory.Tax}} - {{inventory.Discount}} - {{inventory.Amount}} + {{inventory.Quantity | number:2}} + {{inventory.Rate | currency}} + {{inventory.Tax | percent}} + {{inventory.Discount | percent}} + {{inventory.Amount | currency}}
@@ -63,11 +63,11 @@ {{inventory.Product.Name}} - {{inventory.Quantity}} - {{inventory.Rate}} - {{inventory.Tax}} - {{inventory.Discount}} - {{inventory.Amount}} + {{inventory.Quantity | number:2}} + {{inventory.Rate | currency}} + {{inventory.Tax | percent}} + {{inventory.Discount | percent}} + {{inventory.Amount | currency}}
Product Group - Quantity - Net - Gross + Quantity + Net + Gross - + {{item.Name}} {{item.Group}} - {{item.Quantity}} - {{item.Net}} - {{item.Gross}} + {{item.Quantity | number:2}} + {{item.Net | currency}} + {{item.Gross | currency}} diff --git a/brewman/brewman/static/partial/raw-material-cost.html b/brewman/brewman/static/partial/raw-material-cost.html index 7403821e..e9971135 100644 --- a/brewman/brewman/static/partial/raw-material-cost.html +++ b/brewman/brewman/static/partial/raw-material-cost.html @@ -38,17 +38,17 @@ {{item.Name}} - {{item.Issue}} - {{item.Sale}} - {{item.Rmc}} + {{item.Issue | currency}} + {{item.Sale | currency}} + {{item.Rmc | percent}} {{item.Name}} - {{item.Issue}} - {{item.Sale}} - {{item.Rmc}} + {{item.Issue | currency}} + {{item.Sale | currency}} + {{item.Rmc | percent}} diff --git a/brewman/brewman/static/partial/receipt.html b/brewman/brewman/static/partial/receipt.html index 8d2f63c8..43cb1935 100644 --- a/brewman/brewman/static/partial/receipt.html +++ b/brewman/brewman/static/partial/receipt.html @@ -55,7 +55,7 @@ {{journal.Ledger.Name}} - {{journal.Amount}} + {{journal.Amount | currency}}
-
+
+ + +
+
+ + + + +
+
+
+
+ + + + +
+
+ +
+ +
+
+ +
+ +
+ +
+
diff --git a/brewman/brewman/static/partial/trial-balance.html b/brewman/brewman/static/partial/trial-balance.html index e01d4fd1..c1d01ef0 100644 --- a/brewman/brewman/static/partial/trial-balance.html +++ b/brewman/brewman/static/partial/trial-balance.html @@ -28,10 +28,10 @@ - {{item.Type}} -
{{item.Name}} - {{item.Debit}} - {{item.Credit}} + {{item.Type}} + {{item.Name}} + {{item.Debit | accounting}} + {{item.Credit | accounting}} diff --git a/brewman/brewman/static/partial/unposted.html b/brewman/brewman/static/partial/unposted.html index 36c685de..4c2cae95 100644 --- a/brewman/brewman/static/partial/unposted.html +++ b/brewman/brewman/static/partial/unposted.html @@ -9,21 +9,21 @@ Type Narration Debit - Amount + Amount Credit - Amount + Amount - {{item.Date}} + {{item.Date}} {{item.Type}} {{item.Narration}} - {{item.DebitN}} - {{item.DebitA}} - {{item.CreditN}} - {{item.CreditA}} + {{item.DebitN}} + {{item.DebitA | currency}} + {{item.CreditN}} + {{item.CreditA | currency}} diff --git a/brewman/brewman/static/scripts/angular_directive.js b/brewman/brewman/static/scripts/angular_directive.js index 5b3c1fd7..b9c6346d 100644 --- a/brewman/brewman/static/scripts/angular_directive.js +++ b/brewman/brewman/static/scripts/angular_directive.js @@ -141,4 +141,36 @@ overlord_directive.directive('onReturn', function () { } }); }; -}); \ No newline at end of file +}); + +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); + } + }; +}]); \ No newline at end of file diff --git a/brewman/brewman/static/scripts/angular_filter.js b/brewman/brewman/static/scripts/angular_filter.js index ca25c515..65eba4ce 100644 --- a/brewman/brewman/static/scripts/angular_filter.js +++ b/brewman/brewman/static/scripts/angular_filter.js @@ -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'; + } + }; +}]); \ No newline at end of file diff --git a/brewman/brewman/static/scripts/angular_service.js b/brewman/brewman/static/scripts/angular_service.js index fc5453bd..035abba0 100644 --- a/brewman/brewman/static/scripts/angular_service.js +++ b/brewman/brewman/static/scripts/angular_service.js @@ -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'); }]); diff --git a/brewman/brewman/static/scripts/overlord.js b/brewman/brewman/static/scripts/overlord.js index 23b720bc..94fa4113 100644 --- a/brewman/brewman/static/scripts/overlord.js +++ b/brewman/brewman/static/scripts/overlord.js @@ -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}). diff --git a/brewman/brewman/static/scripts/payment.js b/brewman/brewman/static/scripts/payment.js index ca2439de..08f6bebd 100644 --- a/brewman/brewman/static/scripts/payment.js +++ b/brewman/brewman/static/scripts/payment.js @@ -203,5 +203,5 @@ var PaymentModalCtrl = ['$scope', '$modalInstance', '$q', 'edit', 'Account', fun deferred.resolve(result); }); return deferred.promise; - } -}] + }; +}]; diff --git a/brewman/brewman/static/scripts/reconcile.js b/brewman/brewman/static/scripts/reconcile.js new file mode 100644 index 00000000..97e06255 --- /dev/null +++ b/brewman/brewman/static/scripts/reconcile.js @@ -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('
').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; + }] +}; + + diff --git a/brewman/brewman/static/scripts/settings.js b/brewman/brewman/static/scripts/settings.js index 9760b3eb..f7ca8003 100644 --- a/brewman/brewman/static/scripts/settings.js +++ b/brewman/brewman/static/scripts/settings.js @@ -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 = { diff --git a/brewman/brewman/templates/angular_base.mako b/brewman/brewman/templates/angular_base.mako index afbdc2a5..c1107fe2 100644 --- a/brewman/brewman/templates/angular_base.mako +++ b/brewman/brewman/templates/angular_base.mako @@ -34,6 +34,7 @@ + @@ -69,6 +70,7 @@ + @@ -133,6 +135,7 @@ class="caret">