diff --git a/brewman/brewman/__init__.py b/brewman/brewman/__init__.py index d0d79a37..05e29bfe 100644 --- a/brewman/brewman/__init__.py +++ b/brewman/brewman/__init__.py @@ -130,6 +130,7 @@ def main(global_config, **settings): config.add_route('purchase_entries', '/PurchaseEntries') config.add_route('api_auth', '/api/Auth') + config.add_route('api_rebase', '/api/Rebase/{date}') config.add_route('api_batch', '/api/Batch') diff --git a/brewman/brewman/models/voucher.py b/brewman/brewman/models/voucher.py index bb8dd83c..783505fc 100644 --- a/brewman/brewman/models/voucher.py +++ b/brewman/brewman/models/voucher.py @@ -25,7 +25,7 @@ class VoucherType: list.append(VoucherType(5, 'Receipt')) list.append(VoucherType(6, 'Purchase Return')) list.append(VoucherType(7, 'Opening Ledgers')) - list.append(VoucherType(8, 'Opening Inventories')) + list.append(VoucherType(8, 'Opening Batches')) list.append(VoucherType(9, 'Verification')) list.append(VoucherType(10, 'Opening Balance')) list.append(VoucherType(11, 'Closing Balance')) diff --git a/brewman/brewman/static/partial/settings.html b/brewman/brewman/static/partial/settings.html index 474e957b..183cd82e 100644 --- a/brewman/brewman/static/partial/settings.html +++ b/brewman/brewman/static/partial/settings.html @@ -20,4 +20,23 @@ + +
+ + +
+
+ + + + +
+
+
+ +
+
+ diff --git a/brewman/brewman/static/scripts/settings.js b/brewman/brewman/static/scripts/settings.js index 5f302ac0..9760b3eb 100644 --- a/brewman/brewman/static/scripts/settings.js +++ b/brewman/brewman/static/scripts/settings.js @@ -2,11 +2,11 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scope, $http, dateFilter, lockDate) { $scope.lockDate = lockDate.data['Lock Date']; + $scope.rebaseDate = ''; $scope.setLockDate = function () { if (angular.isDate($scope.lockDate)) { $scope.lockDate = dateFilter($scope.lockDate, 'dd-MMM-yyyy'); } - $http({method: 'POST', url: '/api/LockDate', params: {Date: $scope.lockDate}}). success(function (data) { $scope.lockDate = data['Lock Date']; @@ -16,6 +16,7 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scop $scope.toasts.push({Type: 'Danger', Message: errorMessage}); }); }; + $scope.clearLockDate = function () { $http({method: 'POST', url: '/api/LockDate', params: {Clear: ''}}). success(function (data) { @@ -26,7 +27,23 @@ var SettingsCtrl = ['$scope', '$http', 'dateFilter', 'lockDate', function ($scop $scope.toasts.push({Type: 'Danger', Message: errorMessage}); }); }; -}] + + $scope.rebaseData = function () { + if ($scope.rebaseDate === '') { + return; + } + if (angular.isDate($scope.rebaseDate)) { + $scope.rebaseDate = dateFilter($scope.rebaseDate, 'dd-MMM-yyyy'); + } + $http({method: 'POST', url: '/api/Rebase/' + $scope.rebaseDate}). + success(function (data) { + $scope.toasts.push({Type: 'Success', Message: 'Data rebased!'}); + }). + error(function (errorMessage) { + $scope.toasts.push({Type: 'Danger', Message: errorMessage}); + }); + }; +}]; SettingsCtrl.resolve = { lockDate: ['$http', function ($http) { diff --git a/brewman/brewman/views/Management/__init__.py b/brewman/brewman/views/Management/__init__.py new file mode 100644 index 00000000..5e84a522 --- /dev/null +++ b/brewman/brewman/views/Management/__init__.py @@ -0,0 +1 @@ +__author__ = 'tanshu' diff --git a/brewman/brewman/views/Management/rebase.py b/brewman/brewman/views/Management/rebase.py new file mode 100644 index 00000000..551a89f8 --- /dev/null +++ b/brewman/brewman/views/Management/rebase.py @@ -0,0 +1,106 @@ +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 +import transaction +from brewman.models import DBSession +from brewman.models.master import LedgerBase, CostCenter, Product +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_rebase', renderer='json', permission='Rebase') +@TryCatchFunction +def rebase(request): + date = request.matchdict.get('date', None) + date = datetime.datetime.strptime(date, '%d-%b-%Y') + user_id = uuid.UUID(authenticated_userid(request)) + voucher_l = opening_ledgers(date, user_id) + voucher_b, batches = opening_batches(date, user_id) + delete_data(date, batches) + DBSession.add(voucher_l) + for j in voucher_l.journals: + DBSession.add(j) + DBSession.add(voucher_b) + for j in voucher_b.journals: + DBSession.add(j) + for i in voucher_b.inventories: + DBSession.add(i) + transaction.commit() + return {} + + +def opening_ledgers(date, user_id): + running_total = 0 + + sum_func = func.sum(Journal.signed_amount) + query = DBSession.query(LedgerBase, sum_func) \ + .join(Journal, Voucher.journals).join(LedgerBase, Journal.ledger) \ + .filter(Voucher.date < date).filter(Voucher.type != VoucherType.by_name('Issue').id) \ + .having(sum_func != 0) \ + .group_by(LedgerBase).all() + + dt = date - datetime.timedelta(days=1) + voucher = Voucher(date=dt, narration='Opening Ledgers', user_id=user_id, posted=True, + type=VoucherType.by_name('Opening Ledgers')) + for ledger, amount in query: + amount = round(Decimal(amount), 2) + if amount != 0: + running_total += amount + journal = Journal(amount=abs(amount), debit=-1 if amount < 0 else 1, ledger_id=ledger.id, + cost_center_id=ledger.costcenter_id) + voucher.journals.append(journal) + if running_total != 0: + journal = Journal(amount=abs(amount), debit=-1 if amount * -1 < 0 else 1, ledger_id=LedgerBase.suspense(), + cost_center_id=CostCenter.cost_center_overall()) + voucher.journals.append(journal) + return voucher + + +def opening_batches(date, user_id): + total = 0 + batches = [] + sum_func = func.sum(Journal.debit * Inventory.quantity) + query = DBSession.query(Batch, sum_func) \ + .join(Journal, Voucher.journals).join(Inventory, Voucher.inventories).join(Batch, Inventory.batch) \ + .filter(Voucher.date < date) \ + .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \ + .having(sum_func != 0) \ + .group_by(Batch).all() + + dt = date - datetime.timedelta(days=1) + voucher = Voucher(date=dt, narration='Opening Batches', user_id=user_id, posted=True, + type=VoucherType.by_name('Opening Batches')) + for batch, quantity in query: + quantity = round(Decimal(quantity), 2) + if quantity != 0: + total += quantity * batch.rate * (1 + batch.tax) * (1 - batch.discount) + inventory = Inventory(product_id=batch.product_id, batch=batch, quantity=quantity, rate=batch.rate, + tax=batch.tax, discount=batch.discount) + voucher.inventories.append(inventory) + batches.append(batch.id) + voucher.journals.append(Journal(amount=abs(total), debit=-1, ledger_id=LedgerBase.all_purchases(), + cost_center_id=CostCenter.cost_center_overall())) + voucher.journals.append(Journal(amount=abs(total), debit=1, ledger_id=LedgerBase.all_purchases(), + cost_center_id=CostCenter.cost_center_purchase())) + return voucher, batches + + +def delete_data(date, batches): + sub_voucher = aliased(Voucher) + sub_query = DBSession.query(sub_voucher.id).filter(sub_voucher.date < date).subquery() + + Inventory.__table__.delete(Inventory.voucher_id.in_(sub_query)).execute() + SalaryDeduction.__table__.delete(SalaryDeduction.voucher_id.in_(sub_query)).execute() + Journal.__table__.delete(Journal.voucher_id.in_(sub_query)).execute() + Voucher.__table__.delete(Voucher.date < date).execute() + + Batch.__table__.delete(and_(~Batch.inventories.any(), ~Batch.id.in_(batches))).execute() + + Fingerprint.__table__.delete(Fingerprint.date < date).execute() + Attendance.__table__.delete(Attendance.date < date).execute() \ No newline at end of file diff --git a/brewman/brewman/views/settings.py b/brewman/brewman/views/Management/settings.py similarity index 100% rename from brewman/brewman/views/settings.py rename to brewman/brewman/views/Management/settings.py