Removed redundant operations.

Removed Unnecessary update in Journal model.
Added refresh button to Unposted page.
Base, Account, Attendance, Journal, Login, Logout, Unposted,  Controllers are Minifiable.
Modal Service and Directives are Minifiable.
Fixed EmployeeAttendanceCtrl.
Fixed Save Account. Added validation to vouchers.
Added rounding to Journal Voucher.
Purchase now updates product price.
This commit is contained in:
Tanshu 2012-11-20 23:21:10 +05:30
parent bb820febff
commit 517b56431a
24 changed files with 228 additions and 177 deletions

@ -1,100 +1,10 @@
from datetime import datetime
from sqlalchemy.sql.expression import func
from brewman.models import DBSession
from brewman.models.master import CostCenter
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, Batch
__author__ = 'tanshu'
def create_basic(voucher):
voucher.creation_date = datetime.now()
voucher.last_edit_date = datetime.now()
DBSession.add(voucher)
DBSession.flush()
def update_basic(voucher):
voucher.last_edit_date = datetime.now()
DBSession.add(voucher)
DBSession.flush()
def create_journal_voucher(voucher):
journals_valid(voucher)
create_basic(voucher)
for item in voucher.journals:
item.voucher_id = voucher.id
DBSession.add(item)
DBSession.flush()
def update_journal_voucher(voucher):
journals_valid(voucher)
update_basic(voucher)
def validate_new_purchase_voucher(voucher):
journals_valid(voucher)
for item in voucher.inventories:
batch = item.batch
if not batch.id is None:
raise ValidationError("New Purchase cannot have a Batch")
def update_purchase_voucher(voucher):
journals_valid(voucher)
# integrity has been checked by purchase update controller
update_basic(voucher)
DBSession.flush()
def create(voucher):
validate(voucher)
voucher.creation_date = datetime.now()
voucher.last_edit_date = datetime.now()
DBSession.add(voucher)
DBSession.flush()
for item in voucher.journals:
item.voucher_id = voucher.id
DBSession.add(item)
DBSession.flush()
consuming = None
for item in voucher.inventories:
item.voucher_id = voucher.id
if item.batch.id == None:
if voucher.type == 2: # new purchase
item.batch.quantity_remaining = item.quantity
DBSession.add(item.batch)
DBSession.flush()
else:
raise ValidationError("This is not possible, no batch on entries other than new purchase")
else:
if voucher.type == 9:
raise ValidationError("Verification Vouchers have been disabled")
elif voucher.type == 6:
# Purchase Return
item.batch.quantity_remaining -= item.quantity
elif voucher.type == 2:
# Purchase
raise ValidationError("This is not possible, batch entries on new purchase")
elif voucher.type == 3:
# Issue
if consuming is None:
consuming = filter(lambda x: x.cost_center_id == CostCenter.cost_center_purchase(),
voucher.journals)
if not len(consuming):
consuming = 0
else:
consuming = consuming[0].debit
item.batch.quantity_remaining += item.quantity * consuming
item.batch_id = item.batch.id
DBSession.add(item)
DBSession.flush()
def validate(voucher):
journals_valid(voucher)
if voucher.type in [2, 3, 6]:

@ -112,9 +112,6 @@ class Journal(Base):
def query(cls):
return DBSession.query(cls)
def update(self):
DBSession.flush()
class VoucherType:
def __init__(self, id, name):

@ -0,0 +1,88 @@
<form method="post" autocomplete="off" class="form-horizontal">
<legend>Credit Esi Pf</legend>
<div class="control-group">
<label for="txtDate" class="control-label">Date</label>
<div class="controls">
<datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div>
</div>
<div class="control-group">
<label for="txtEmployee" class="control-label">Employee</label>
<div class="controls">
<input type="text" ng-autocomplete id="txtEmployee" resource="Employee" model="employee"
value="{{info.Employee.Name}}"/>
<input type="text" class="span2" autocomplete="off" placeholder="Gross Salary" ng-model="grossSalary"/>
<input type="text" class="span2" autocomplete="off" placeholder="Days Worked" ng-model="daysWorked"/>
<button class="btn btn-info" ng-click="add()">Add <i class="icon-plus-sign icon-white"></i></button>
</div>
</div>
<div class=" control-group">
<label for="gvGrid" class="control-label"></label>
<div class="controls">
<table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Designation</th>
<th>Department</th>
<th>Gross Salary</th>
<th>Days Worked</th>
<th>Esi EE</th>
<th>Pf EE</th>
<th>Esi ER</th>
<th>Pf ER</th>
<th>Delete</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="tbodyMain">
<tr ng-repeat="deduction in voucher.SalaryDeductions">
<td>{{deduction.Employee.Name}}</td>
<td>{{deduction.Employee.Designation}}</td>
<td>{{deduction.Employee.Department}}</td>
<td>{{deduction.GrossSalary}}</td>
<td>{{deduction.DaysWorked}}</td>
<td>{{deduction.EsiEmployee}}</td>
<td>{{deduction.PfEmployee}}</td>
<td>{{deduction.EsiEmployer}}</td>
<td>{{deduction.PfEmployer}}</td>
<td>
<button class="btn btn-danger" ng-click="remove(deduction)"><i
class="icon-trash icon-white"></i> Delete
</button>
</td>
</tr>
</tbody>
<tfoot id="tfootMain">
</tfoot>
</table>
</div>
</div>
<div class="control-group">
<label for="txtNarration" class="control-label">Narration</label>
<div class="controls">
<textarea rows="2" cols="20" id="txtNarration"
class="non-search-box" ng-model="voucher.Narration"></textarea>
</div>
</div>
<div class="form-actions">
<button class="btn btn-primary" ng-click="save()"
ng-disabled="preventAlteration(voucher)">{{voucher.VoucherID | save_button}}
</button>
<button class="btn btn-inverse" ng-click="post()" ng-hide="!voucher.VoucherID"
ng-disabled="voucher.Posted || !perms['Post Vouchers']">{{voucher.Posted | posted}}
</button>
<button class="btn btn-danger" ng-hide="!voucher.VoucherID" ng-disabled="preventAlteration(voucher)"
ng-confirm title="Delete Voucher" action-text="Are you sure? This cannot be undone."
action-button-text="Delete" action-function="delete()"> Delete
</button>
</div>
<div class="row-fluid">
Created on {{voucher.CreationDate}} and Last Edited on {{voucher.LastEditDate}} by {{voucher.User.Name}}. Posted
by {{voucher.Poster}}
</div>
</form>

@ -23,10 +23,10 @@
</div>
</div>
<div class="control-group" ng-show="showOTP">
<label class="control-label" for="name">Client Name</label>
<label class="control-label" for="clientName">Client Name</label>
<div class="controls">
<input type="text" ng-model="name" id="name" required placeholder="Client Name"/>
<input type="text" ng-model="name" id="clientName" required placeholder="Client Name"/>
</div>
</div>
<div class="control-group">

@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label>
<div class="controls">
<datepicker id="txtDate" model="info" prop="FinishDate" ng-model="info.Date"></datepicker>
<datepicker id="txtDate" model="info.Date" ng-model="info.Date"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div>
</div>

@ -1,5 +1,5 @@
<form method="post" autocomplete="off" class="form-horizontal">
<legend>Unposted Entries</legend>
<legend>Unposted Entries <a class="btn btn-success pull-right" ng-click="refresh()">Refresh <i class="icon-refresh icon-white"></i></a></legend>
<div class="control-group">
<label for="gvGrid" class="control-label"></label>

@ -1,10 +1,10 @@
'use strict';
function AccountListCtrl($scope, accounts) {
var AccountListCtrl = ['$scope', 'accounts', function ($scope, accounts) {
$scope.info = accounts;
}
}];
AccountListCtrl.resolve = {
accounts:function ($q, $route, Account) {
accounts:['$q', '$route', 'Account', function ($q, $route, Account) {
var deferred = $q.defer();
var successCb = function (result) {
@ -13,10 +13,10 @@ AccountListCtrl.resolve = {
Account.query({}, successCb);
return deferred.promise;
}
}]
};
function AccountCtrl($scope, $location, account, account_types, cost_centers) {
var AccountCtrl = ['$scope', '$location', 'account', 'account_types', 'cost_centers', function ($scope, $location, account, account_types, cost_centers) {
$scope.account = account;
$scope.account_types = account_types;
@ -41,10 +41,10 @@ function AccountCtrl($scope, $location, account, account_types, cost_centers) {
};
$('#txtName').focus();
}
}]
AccountCtrl.resolve = {
account:function ($q, $route, Account) {
account:['$q', '$route', 'Account', function ($q, $route, Account) {
var deferred = $q.defer();
var id = $route.current.params.id;
@ -54,8 +54,8 @@ AccountCtrl.resolve = {
Account.get({id: id}, successCb);
return deferred.promise;
},
account_types:function ($q, $route, AccountType) {
}],
account_types:['$q', 'AccountType', function ($q, AccountType) {
var deferred = $q.defer();
var successCb = function (result) {
@ -64,8 +64,8 @@ AccountCtrl.resolve = {
AccountType.query({}, successCb);
return deferred.promise;
},
cost_centers:function ($q, $route, CostCenter) {
}],
cost_centers:['$q', 'CostCenter', function ($q, CostCenter) {
var deferred = $q.defer();
var successCb = function (result) {
@ -74,5 +74,5 @@ AccountCtrl.resolve = {
CostCenter.query({}, successCb);
return deferred.promise;
}
}]
};

@ -1,7 +1,7 @@
'use strict';
var overlord_directive = angular.module('overlord.directive', []);
overlord_directive.directive('ngAutocomplete', function ($q, $parse) {
overlord_directive.directive('ngAutocomplete', ['$q', '$parse', function ($q, $parse) {
return {
restrict:'A',
link:function (scope, element, attrs, ngModel) {
@ -31,9 +31,9 @@ overlord_directive.directive('ngAutocomplete', function ($q, $parse) {
});
}
};
});
}]);
overlord_directive.directive('datepicker', function ($parse) {
overlord_directive.directive('datepicker', ['$parse', function ($parse) {
return {
restrict:'E',
replace:true,
@ -53,7 +53,7 @@ overlord_directive.directive('datepicker', function ($parse) {
});
}
};
});
}]);
overlord_directive.directive('fadey', function () {
return {
@ -76,7 +76,7 @@ overlord_directive.directive('fadey', function () {
};
});
overlord_directive.directive('ngConfirm', function (modal, $parse) {
overlord_directive.directive('ngConfirm', ['modal', '$parse', function (modal, $parse) {
return {
restrict:'A',
link:function postLink(scope, element, attrs) {
@ -102,7 +102,7 @@ overlord_directive.directive('ngConfirm', function (modal, $parse) {
}
};
});
}]);
(function (angular) {
/*
@ -161,7 +161,7 @@ overlord_directive.directive('journal-edit', function () {
};
});
overlord_directive.directive('ngEditRepeat', function (modal, $parse) {
overlord_directive.directive('ngEditRepeat', ['modal','$parse', function (modal, $parse) {
return {
restrict:'E',
template:'' +
@ -195,5 +195,5 @@ overlord_directive.directive('ngEditRepeat', function (modal, $parse) {
}
}
};
});
}]);

@ -1,6 +1,6 @@
'use strict';
function AttendanceCtrl($scope, $location, Attendance, attendance_types, info) {
var AttendanceCtrl = ['$scope', '$location', 'Attendance', 'attendance_types', 'info', function ($scope, $location, Attendance, attendance_types, info) {
$scope.attendance_types = attendance_types;
$scope.info = info;
$scope.show = function () {
@ -14,9 +14,9 @@ function AttendanceCtrl($scope, $location, Attendance, attendance_types, info) {
});
};
$('#txtDate').focus();
}
}];
AttendanceCtrl.resolve = {
info:function ($q, $route, Attendance) {
info:['$q', '$route', 'Attendance', function ($q, $route, Attendance) {
var deferred = $q.defer();
var date = $route.current.params.date;
var successCb = function (result) {
@ -29,13 +29,13 @@ AttendanceCtrl.resolve = {
Attendance.get({date:date}, successCb);
}
return deferred.promise;
},
attendance_types:function ($q, AttendanceTypes) {
}],
attendance_types:['$q', 'AttendanceTypes', function ($q, AttendanceTypes) {
var deferred = $q.defer();
var successCb = function (result) {
deferred.resolve(result);
};
AttendanceTypes.query({}, successCb);
return deferred.promise;
}
}]
};

@ -0,0 +1,29 @@
'use strict';var overlord=angular.module("overlord",["overlord.directive","overlord.filter","overlord.service","ngCookies"]).config(["$routeProvider","$locationProvider",function(a,c){a.when("/",{templateUrl:"/partial/home.html"}).when("/login",{templateUrl:"/partial/login.html",controller:LoginCtrl}).when("/logout",{templateUrl:"/partial/home.html",controller:LogoutCtrl}).when("/Journal",{templateUrl:"/partial/journal.html",controller:JournalCtrl,resolve:JournalCtrl.resolve}).when("/Journal/:id",
{templateUrl:"/partial/journal.html",controller:JournalCtrl,resolve:JournalCtrl.resolve}).when("/Payment",{templateUrl:"/partial/payment.html",controller:PaymentCtrl,resolve:PaymentCtrl.resolve}).when("/Payment/:id",{templateUrl:"/partial/payment.html",controller:PaymentCtrl,resolve:PaymentCtrl.resolve}).when("/Receipt",{templateUrl:"/partial/receipt.html",controller:ReceiptCtrl,resolve:ReceiptCtrl.resolve}).when("/Receipt/:id",{templateUrl:"/partial/receipt.html",controller:ReceiptCtrl,resolve:ReceiptCtrl.resolve}).when("/Purchase",
{templateUrl:"/partial/purchase.html",controller:PurchaseCtrl,resolve:PurchaseCtrl.resolve}).when("/Purchase/:id",{templateUrl:"/partial/purchase.html",controller:PurchaseCtrl,resolve:PurchaseCtrl.resolve}).when("/Return",{templateUrl:"/partial/purchase-return.html",controller:PurchaseReturnCtrl,resolve:PurchaseReturnCtrl.resolve}).when("/Return/:id",{templateUrl:"/partial/purchase-return.html",controller:PurchaseReturnCtrl,resolve:PurchaseReturnCtrl.resolve}).when("/Issue",{templateUrl:"/partial/issue.html",
controller:IssueCtrl,resolve:IssueCtrl.resolve}).when("/Issue/:id",{templateUrl:"/partial/issue.html",controller:IssueCtrl,resolve:IssueCtrl.resolve}).when("/Ledger",{templateUrl:"/partial/ledger.html",controller:LedgerCtrl,resolve:LedgerCtrl.resolve}).when("/Ledger/:id",{templateUrl:"/partial/ledger.html",controller:LedgerCtrl,resolve:LedgerCtrl.resolve}).when("/ProductLedger",{templateUrl:"/partial/product-ledger.html",controller:ProductLedgerCtrl,resolve:ProductLedgerCtrl.resolve}).when("/ProductLedger/:id",
{templateUrl:"/partial/product-ledger.html",controller:ProductLedgerCtrl,resolve:ProductLedgerCtrl.resolve}).when("/CashFlow",{templateUrl:"/partial/cash-flow.html",controller:CashFlowCtrl,resolve:CashFlowCtrl.resolve}).when("/CashFlow/:id",{templateUrl:"/partial/cash-flow.html",controller:CashFlowCtrl,resolve:CashFlowCtrl.resolve}).when("/RawMaterialCost",{templateUrl:"/partial/raw-material-cost.html",controller:RawMaterialCostCtrl,resolve:RawMaterialCostCtrl.resolve}).when("/RawMaterialCost/:id",
{templateUrl:"/partial/raw-material-cost-detail.html",controller:RawMaterialCostCtrl,resolve:RawMaterialCostCtrl.resolve}).when("/Attendance",{templateUrl:"/partial/attendance.html",controller:AttendanceCtrl,resolve:AttendanceCtrl.resolve}).when("/Attendance/:date",{templateUrl:"/partial/attendance.html",controller:AttendanceCtrl,resolve:AttendanceCtrl.resolve}).when("/EmployeeAttendance",{templateUrl:"/partial/employee-attendance.html",controller:EmployeeAttendanceCtrl,resolve:EmployeeAttendanceCtrl.resolve}).when("/EmployeeAttendance/:id",
{templateUrl:"/partial/employee-attendance.html",controller:EmployeeAttendanceCtrl,resolve:EmployeeAttendanceCtrl.resolve}).when("/Daybook",{templateUrl:"/partial/daybook.html",controller:DaybookCtrl,resolve:DaybookCtrl.resolve}).when("/Unposted",{templateUrl:"/partial/unposted.html",controller:UnpostedCtrl,resolve:UnpostedCtrl.resolve}).when("/ProfitLoss",{templateUrl:"/partial/profit-loss.html",controller:ProfitLossCtrl,resolve:ProfitLossCtrl.resolve}).when("/PurchaseEntries",{templateUrl:"/partial/purchase-entries.html",
controller:PurchaseEntriesCtrl,resolve:PurchaseEntriesCtrl.resolve}).when("/EmployeeFunctions",{templateUrl:"/partial/employee-functions.html",controller:EmployeeFunctionsCtrl}).when("/TrialBalance",{templateUrl:"/partial/trial-balance.html",controller:TrialBalanceCtrl,resolve:TrialBalanceCtrl.resolve}).when("/TrialBalance/:date",{templateUrl:"/partial/trial-balance.html",controller:TrialBalanceCtrl,resolve:TrialBalanceCtrl.resolve}).when("/ClosingStock",{templateUrl:"/partial/closing-stock.html",
controller:ClosingStockCtrl,resolve:ClosingStockCtrl.resolve}).when("/ClosingStock/:date",{templateUrl:"/partial/closing-stock.html",controller:ClosingStockCtrl,resolve:ClosingStockCtrl.resolve}).when("/Accounts",{templateUrl:"/partial/account-list.html",controller:AccountListCtrl,resolve:AccountListCtrl.resolve}).when("/Account",{templateUrl:"/partial/account-detail.html",controller:AccountCtrl,resolve:AccountCtrl.resolve}).when("/Account/:id",{templateUrl:"/partial/account-detail.html",controller:AccountCtrl,
resolve:AccountCtrl.resolve}).when("/Employees",{templateUrl:"/partial/employee-list.html",controller:EmployeeListCtrl,resolve:EmployeeListCtrl.resolve}).when("/Employee",{templateUrl:"/partial/employee-detail.html",controller:EmployeeCtrl,resolve:EmployeeCtrl.resolve}).when("/Employee/:id",{templateUrl:"/partial/employee-detail.html",controller:EmployeeCtrl,resolve:EmployeeCtrl.resolve}).when("/CostCenters",{templateUrl:"/partial/cost-center-list.html",controller:CostCenterListCtrl,resolve:CostCenterListCtrl.resolve}).when("/CostCenter",
{templateUrl:"/partial/cost-center-detail.html",controller:CostCenterCtrl,resolve:CostCenterCtrl.resolve}).when("/CostCenter/:id",{templateUrl:"/partial/cost-center-detail.html",controller:CostCenterCtrl,resolve:CostCenterCtrl.resolve}).when("/Products",{templateUrl:"/partial/product-list.html",controller:ProductListCtrl,resolve:ProductListCtrl.resolve}).when("/Product",{templateUrl:"/partial/product-detail.html",controller:ProductCtrl,resolve:ProductCtrl.resolve}).when("/Product/:id",{templateUrl:"/partial/product-detail.html",
controller:ProductCtrl,resolve:ProductCtrl.resolve}).when("/ProductGroups",{templateUrl:"/partial/product-group-list.html",controller:ProductGroupListCtrl,resolve:ProductGroupListCtrl.resolve}).when("/ProductGroup",{templateUrl:"/partial/product-group-detail.html",controller:ProductGroupCtrl,resolve:ProductGroupCtrl.resolve}).when("/ProductGroup/:id",{templateUrl:"/partial/product-group-detail.html",controller:ProductGroupCtrl,resolve:ProductGroupCtrl.resolve}).when("/Users",{templateUrl:"/partial/user-list.html",
controller:UserListCtrl,resolve:UserListCtrl.resolve}).when("/User",{templateUrl:"/partial/user-detail.html",controller:UserCtrl,resolve:UserCtrl.resolve}).when("/User/:id",{templateUrl:"/partial/user-detail.html",controller:UserCtrl,resolve:UserCtrl.resolve}).when("/Groups",{templateUrl:"/partial/group-list.html",controller:GroupListCtrl,resolve:GroupListCtrl.resolve}).when("/Group",{templateUrl:"/partial/group-detail.html",controller:GroupCtrl,resolve:GroupCtrl.resolve}).when("/Group/:id",{templateUrl:"/partial/group-detail.html",
controller:GroupCtrl,resolve:GroupCtrl.resolve}).when("/Clients",{templateUrl:"/partial/client-list.html",controller:ClientCtrl,resolve:ClientCtrl.resolve}).otherwise({templateUrl:"/partial/404.html"});c.html5Mode(!0).hashPrefix("!")}]).config(["$httpProvider",function(a){a.responseInterceptors.push("spinnerInterceptor");a.defaults.transformRequest.push(function(a,b){var d=angular.injector(["ng"]).get("$rootScope");"application/json"===b()["Content-Type"]&&d&&d.$broadcast("spinnerStart","http");return a})}]).factory("spinnerInterceptor",
["$q","$rootScope",function(a,c){return function(b){return b.then(function(a){"application/json; charset=utf-8"===a.headers()["content-type"]&&c.$broadcast("spinnerStop","http");return a},function(b){var e="application/json; charset=utf-8"===b.headers()["content-type"];e&&c.$broadcast("spinnerStop","http");401==b.status&&!e&&c.$broadcast("event:loginRequired");return a.reject(b)})}}]);
overlord.controller("BaseCtrl",["$rootScope","$scope","Auth","$location","$routeParams",function(a,c,b,d,e){a.spinner={http:0,route:!1};a.$on("event:loginRequired",function(){if(a.auth.isAuthenticated)d.path("/");else{var b=e.came_from;"undefined"===typeof b&&"/login"!==d.path()&&(b=d.path());d.path("/login").search({came_from:b})}});c.$on("spinnerStart",function(b,c){"http"===c?a.spinner.http+=1:a.spinner.route=!1;$("#spinner").show()});c.$on("spinnerStop",function(b,c){"http"===c?a.spinner.http-=
1:a.spinner.route=!1;0>=a.spinner.http&&!1===a.spinner.route&&$("#spinner").hide()});c.toasts=[];c.clearToast=function(a){var b=c.toasts.indexOf(a);-1!==b&&this.destroy(function(){c.toasts.splice(b,1)})};a.$on("$routeChangeStart",function(){a.$broadcast("spinnerStart","route");b.get(function(b){a.auth=b;a.perms=b.perms})});a.$on("$routeChangeSuccess",function(){a.$broadcast("spinnerStop","route")});a.$on("$routeChangeError",function(){a.$broadcast("spinnerStop","route")})}]);
var overlord_directive=angular.module("overlord.directive",[]);overlord_directive.directive("ngAutocomplete",["$q","$parse",function(a,c){return{restrict:"A",link:function(b,d,e){d.autocomplete({source:function(c,d){var f=angular.injector(["overlord.service"]).get(e.resource),h=a.defer();h.promise.then(function(a){d(a)});f.autocomplete({term:c.term,count:20},function(a){b.$apply(function(){h.resolve(a)})})},minLength:1,autoFocus:!0,select:function(a,d){var f=c(e.model).assign;f(b,d.item.model);b.$apply()}})}}}]);
overlord_directive.directive("datepicker",["$parse",function(a){return{restrict:"E",replace:!0,transclude:!0,template:'<input type="text" />',link:function(c,b,d){b.datepicker({dateFormat:"dd-M-yy",showOtherMonths:!0,selectOtherMonths:!0,onSelect:function(b){var g=a(d.model).assign;g(c,b);c.$apply()}})}}}]);overlord_directive.directive("fadey",function(){return{restrict:"A",link:function(a,c){c=jQuery(c);c.hide();c.fadeIn(500);a.destroy=function(b){c.fadeOut(500,function(){b&&b.apply(a)})}}}});
overlord_directive.directive("ngConfirm",["modal","$parse",function(a,c){return{restrict:"A",link:function(b,d,e){var g={};"undefined"!==typeof e.url?d.bind("click",function(){if("undefined"!==typeof e.before){var d=c(e.before);b.$apply(function(){d(b)})}a.template(e.url,e.onAction,e.onCancel,b,g)}):d.bind("click",function(){a.confirm(e.title,e.actionText,{text:e.actionButtonText,click:e.actionFunction,"class":e["class"]},{text:e.cancelButtonText,click:e.cancelFunction},b,g)})}}}]);
(function(){var a={transclude:"element",priority:1E3,terminal:!0,compile:function(a,b,d){return function(a,b,c){b[0].doNotMove=!0;var f,h;a.$watch(c.ngmIf,function(c){f&&(f.remove(),f=null);h&&h.$destroy();c&&(h=a.$new(),d(h,function(a){f=a;b.after(a)}));b.parent().trigger("$childrenChanged")})}}};overlord_directive.directive("ngmIf",function(){return a})})(angular);
overlord_directive.directive("journal-edit",function(){return{restrict:"A",replace:!0,transclude:!0,templateUrl:"/partial/journal-modal.html",link:function(a,c,b){c.bind("click",function(){modal.confirm(b.title,b.actionText,{text:b.actionButtonText,click:b.actionFunction,"class":b["class"]},{text:b.cancelButtonText,click:b.cancelFunction},a,options)})}}});
overlord_directive.directive("ngEditRepeat",["modal","$parse",function(a,c){return{restrict:"E",template:'<div class="btn-group"> <a class="btn btn-danger" ng-click="removeJournal(journal)"><i class="icon-trash icon-white"></i> Delete</a> <a class="btn btn-danger dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a> <ul class="dropdown-menu"> <li><a ng-confirm url="/partial/journal-modal.html" before="toggleEdit(journal)" on-action="toggleEdit(journal, true)" on-cancel="toggleEdit(journal, false)"><i class="icon-pencil"></i> Edit</a></li> </ul></div>',link:function(b,
d,e){var g={};"undefined"!==typeof e.url?d.bind("click",function(){if("undefined"!==typeof e.before){var d=c(e.before);b.$apply(function(){d(b)})}a.template(e.url,e.onAction,e.onCancel,b,g)}):d.bind("click",function(){a.confirm(e.title,e.actionText,{text:e.actionButtonText,click:e.actionFunction,"class":e["class"]},{text:e.cancelButtonText,click:e.cancelFunction},b,g)})}}}]);
var AttendanceCtrl=["$scope","$location","Attendance","attendance_types","info",function(a,c,b,d,e){a.attendance_types=d;a.info=e;a.show=function(){c.path("/Attendance/"+a.info.Date)};a.save=function(){a.info.$save(function(b){a.toasts.push({Type:"Success",Message:b.Code})},function(b){a.toasts.push({Type:"Error",Message:b.data})})};$("#txtDate").focus()}];
AttendanceCtrl.resolve={info:["$q","$route","Attendance",function(a,c,b){var d=a.defer(),a=c.current.params.date,c=function(a){d.resolve(a)};"undefined"===typeof a?b.get({},c):b.get({date:a},c);return d.promise}],attendance_types:["$q","AttendanceTypes",function(a,c){var b=a.defer();c.query({},function(a){b.resolve(a)});return b.promise}]};var AccountListCtrl=["$scope","accounts",function(a,c){a.info=c}];
AccountListCtrl.resolve={accounts:["$q","$route","Account",function(a,c,b){var d=a.defer();b.query({},function(a){d.resolve(a)});return d.promise}]};
var AccountCtrl=["$scope","$location","account","account_types","cost_centers",function(a,c,b,d,e){a.account=b;a.account_types=d;a.cost_centers=e;a.save=function(){a.account.$save(function(){a.toasts.push({Type:"Success",Message:""});c.path("/Accounts")},function(b){a.toasts.push({Type:"Error",Message:b.data})})};a.delete=function(){a.account.$delete(function(){a.toasts.push({Type:"Success",Message:""});c.path("/Accounts")},function(b){a.toasts.push({Type:"Error",Message:b.data})})};$("#txtName").focus()}];
AccountCtrl.resolve={account:["$q","$route","Account",function(a,c,b){var d=a.defer();b.get({id:c.current.params.id},function(a){d.resolve(a)});return d.promise}],account_types:["$q","AccountType",function(a,c){var b=a.defer();c.query({},function(a){b.resolve(a)});return b.promise}],cost_centers:["$q","CostCenter",function(a,c){var b=a.defer();c.query({},function(a){b.resolve(a)});return b.promise}]};

@ -1,10 +1,10 @@
'use strict';
function EmployeeAttendanceCtrl($scope, $location, EmployeeAttendance, attendance_types, info) {
function EmployeeAttendanceCtrl($scope, $location, $routeParams, EmployeeAttendance, attendance_types, info) {
$scope.attendance_types = attendance_types;
$scope.info = info;
$scope.show = function () {
var id = $scope.info.Ledger.LedgerID;
var id = $scope.info.Employee.LedgerID;
var start_date = $scope.info.StartDate;
var finish_date = $scope.info.FinishDate;
if (id == $routeParams.id && start_date == $routeParams.StartDate && finish_date == $routeParams.FinishDate) {

@ -1,6 +1,6 @@
'use strict';
function JournalCtrl($scope, $location, voucher) {
var JournalCtrl = ['$scope', '$location', 'voucher', function ($scope, $location, voucher) {
$scope.voucher = voucher;
$scope.name = '';
$scope.debit = 1;
@ -121,10 +121,10 @@ function JournalCtrl($scope, $location, voucher) {
}
}
}
}
}]
JournalCtrl.resolve = {
voucher:function ($q, $route, Voucher) {
voucher:['$q', '$route', 'Voucher', function ($q, $route, Voucher) {
var deferred = $q.defer();
var id = $route.current.params.id;
@ -139,5 +139,5 @@ JournalCtrl.resolve = {
Voucher.get({id:id}, successCb);
}
return deferred.promise;
}
}]
};

@ -1,6 +1,6 @@
'use strict';
function LoginCtrl($scope, $http, $location, $routeParams, $cookieStore) {
var LoginCtrl = ['$scope', '$http', '$location', '$routeParams', '$cookieStore', function ($scope, $http, $location, $routeParams, $cookieStore) {
$scope.showOTP = false;
$scope.submit = function () {
if ($scope.showOTP) {
@ -23,14 +23,15 @@ function LoginCtrl($scope, $http, $location, $routeParams, $cookieStore) {
if (status === 403 && ['Unknown Client', 'OTP not supplied', 'OTP is wrong'].indexOf(data) !== -1) {
$scope.showOTP = true;
$scope.clientID = $cookieStore.get('ClientID');
$scope.$apply();
}
$scope.toasts.push({Type:'Error', Message:data});
});
};
$('#username').focus();
}
}]
function LogoutCtrl($scope, $http, $location) {
var LogoutCtrl = ['$scope', '$http', '$location', function ($scope, $http, $location) {
$http.
post('/logout').
success(function () {
@ -40,4 +41,4 @@ function LogoutCtrl($scope, $http, $location) {
error(function (errorMessage) {
$scope.toasts.push({Type:'Error', Message:errorMessage});
});
}
}]

@ -1,6 +1,6 @@
'use strict';
overlord_service.factory('modal', function ($http, $compile) {
overlord_service.factory('modal', ['$http', '$compile', function ($http, $compile) {
var modal = {};
modal.get = function (create) {
@ -116,4 +116,4 @@ overlord_service.factory('modal', function ($http, $compile) {
return modal;
});
}]);

@ -88,20 +88,20 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
otherwise({templateUrl:'/partial/404.html'});
$locationProvider.html5Mode(true).hashPrefix('!');
}])
.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('spinnerInterceptor');
var spinnerFunction = function (data, headersGetter) {
var scope = angular.injector(['ng']).get('$rootScope'),
headers = headersGetter(),
isResourceRequest = headers['Content-Type'] === "application/json";
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.responseInterceptors.push('spinnerInterceptor');
var spinnerFunction = function (data, headersGetter) {
var scope = angular.injector(['ng']).get('$rootScope'),
headers = headersGetter(),
isResourceRequest = headers['Content-Type'] === "application/json";
if (isResourceRequest && scope) {
scope.$broadcast('spinnerStart', 'http');
}
return data;
};
$httpProvider.defaults.transformRequest.push(spinnerFunction);
})
if (isResourceRequest && scope) {
scope.$broadcast('spinnerStart', 'http');
}
return data;
};
$httpProvider.defaults.transformRequest.push(spinnerFunction);
}])
.factory('spinnerInterceptor', ['$q', '$rootScope', function ($q, $rootScope) {
return function (promise) {
return promise.then(function (response) {
@ -128,7 +128,7 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
};
}]);
function BaseCtrl($rootScope, $scope, Auth, $location, $routeParams) {
overlord.controller('BaseCtrl', ['$rootScope', '$scope', 'Auth', '$location', '$routeParams', function ($rootScope, $scope, Auth, $location, $routeParams) {
$rootScope.spinner = {http:0, route:false};
$rootScope.$on('event:loginRequired', function () {
if ($rootScope.auth.isAuthenticated) {
@ -186,3 +186,5 @@ function BaseCtrl($rootScope, $scope, Auth, $location, $routeParams) {
$rootScope.$broadcast('spinnerStop', 'route');
});
}
]);

@ -1,17 +1,23 @@
'use strict';
function UnpostedCtrl($scope, info) {
var UnpostedCtrl = ['$scope', 'info', 'Unposted', function ($scope, info, Unposted) {
$scope.info = info;
}
$scope.refresh = function () {
Unposted.query({}, function (result) {
$scope.info = result;
$scope.apply();
});
}
}]
UnpostedCtrl.resolve = {
info:function ($q, Unposted) {
info:['$q', 'Unposted', function ($q, Unposted) {
var deferred = $q.defer();
var successCb = function(result){
var successCb = function (result) {
deferred.resolve(result);
};
Unposted.query({}, successCb);
return deferred.promise;
}
};
}]
}

@ -20,7 +20,7 @@ def html(request):
def save(request):
try:
item = Ledger(code=0, name=request.json_body['Name'], type=int(request.json_body['Type']),
is_active=request.json_body['IsActive'], is_reconcilble=request.json_body['IsReconcilable'],
is_active=request.json_body['IsActive'], is_reconcilable=request.json_body['IsReconcilable'],
costcenter_id=uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create()
transaction.commit()
return account_info(item.id)

@ -1,5 +1,6 @@
import uuid
from pyramid.response import Response
from pyramid.view import view_config
import transaction
from brewman.models import DBSession

@ -38,7 +38,6 @@ def show_data(request):
build_report(request, info)
return info
def build_report(request, info):
ledger_id = info['Ledger']['LedgerID']
start_date = info['StartDate']
@ -118,3 +117,5 @@ def opening_balance(ledgerID, start_date):
return debit, credit, runningTotal, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
'Narration': '', 'Debit': debitShow, 'Credit': creditShow,
'Running': running, 'Posted': True}

@ -3,6 +3,7 @@ from decimal import Decimal
import uuid
from brewman.models import DBSession
from brewman.models.master import Product, CostCenter, LedgerBase
from brewman.models.operations import journals_valid, inventory_valid
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@ -26,7 +27,8 @@ def issue_create_voucher(json, user):
for item in issue_create_journals(voucher.inventories, source, destination):
DBSession.add(item)
voucher.journals.append(item)
DBSession.flush()
journals_valid(voucher)
inventory_valid(voucher)
return voucher
@ -89,6 +91,8 @@ def issue_update_voucher(voucher, json, user):
issue_update_inventory(voucher, json['Inventories'], old_batch_consumed)
issue_update_journals(voucher, source, destination)
journals_valid(voucher)
inventory_valid(voucher)
return voucher

@ -3,22 +3,24 @@ from decimal import Decimal
import uuid
from brewman.models import DBSession
from brewman.models.master import LedgerBase
from brewman.models.operations import update_journal_voucher, create_journal_voucher
from brewman.models.operations import journals_valid
from brewman.models.voucher import Journal, Voucher, VoucherType
__author__ = 'tanshu'
def journal_create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type']),
posted=False)
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type']))
DBSession.add(voucher)
for item in json['Journals']:
ledger = LedgerBase.by_id(uuid.UUID(item['Ledger']['LedgerID']))
journal_id = uuid.UUID(item['JournalID']) if 'JournalID' in item else None
voucher.journals.append(
Journal(id=journal_id, amount=Decimal(item['Amount']), debit=int(item['Debit']), ledger_id=ledger.id,
cost_center_id=ledger.costcenter_id))
create_journal_voucher(voucher)
amount = round(Decimal(item['Amount']), 2)
journal = Journal(id=journal_id, amount=amount, debit=int(item['Debit']), ledger_id=ledger.id,
cost_center_id=ledger.costcenter_id)
voucher.journals.append(journal)
DBSession.add(journal)
journals_valid(voucher)
return voucher
@ -39,7 +41,7 @@ def journal_update_voucher(voucher, json, user):
ledger = LedgerBase.by_id(uuid.UUID(j['Ledger']['LedgerID']))
found = True
item.debit = int(j['Debit'])
item.amount = Decimal(j['Amount'])
item.amount = round(Decimal(j['Amount']), 2)
item.ledger_id = ledger.id
item.cost_center_id = ledger.costcenter_id
newJournals.remove(j)
@ -48,12 +50,11 @@ def journal_update_voucher(voucher, json, user):
voucher.journals.remove(item)
for j in newJournals:
ledger = LedgerBase.by_id(uuid.UUID(j['Ledger']['LedgerID']))
journal = Journal(id=None, amount=Decimal(j['Amount']), debit=int(j['Debit']), ledger_id=ledger.id,
journal = Journal(id=None, amount=round(Decimal(j['Amount']), 2), debit=int(j['Debit']), ledger_id=ledger.id,
cost_center_id=ledger.costcenter_id)
DBSession.add(journal)
voucher.journals.append(journal)
update_journal_voucher(voucher)
# voucher.validate()
journals_valid(voucher)
return voucher

@ -3,6 +3,7 @@ from decimal import Decimal
import uuid
from brewman.models import DBSession
from brewman.models.master import Product, LedgerBase
from brewman.models.operations import journals_valid, inventory_valid
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@ -14,11 +15,12 @@ def purchase_create_voucher(json, user):
DBSession.add(voucher)
for item in json['Inventories']:
voucher.inventories.append(purchase_create_inventory(voucher, item, json['Date']))
purchase_create_inventory(voucher, item, json['Date'])
for item in purchase_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']):
DBSession.add(item)
voucher.journals.append(item)
DBSession.flush()
journals_valid(voucher)
inventory_valid(voucher)
return voucher
@ -34,8 +36,9 @@ def purchase_create_inventory(voucher, item, date):
DBSession.add(batch)
inventory = Inventory(id=inventory_id, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax,
discount=discount)
product.price = rate
DBSession.add(inventory)
voucher.inventories.append(item)
voucher.inventories.append(inventory)
@ -45,12 +48,13 @@ def purchase_create_journals(inventories, ledgerID):
amount = 0
for item in inventories:
ledger = Product.by_id(item.product_id).ledger
amount += round(item.amount, 2)
item_amount = round(item.amount, 2)
amount += item_amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
journals[ledger.id].amount += item_amount
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
amount=item_amount)
journals[otherLedger.id] = Journal(debit=-1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
amount=amount)
return list(journals.values())
@ -65,6 +69,8 @@ def purchase_update_voucher(voucher, json, user):
purchase_update_inventory(voucher, json['Inventories'], json['Date'])
purchase_update_journals(voucher, json['Journals'])
journals_valid(voucher)
inventory_valid(voucher)
return voucher
@ -98,6 +104,7 @@ def purchase_update_inventory(voucher, newInventories, date):
item.batch.discount = discount
item.tax = tax
item.batch.tax = tax
product.price = rate
newInventories.remove(i)
#TODO: Update all references of the batch with the new rates
break
@ -122,6 +129,7 @@ def purchase_update_inventory(voucher, newInventories, date):
inventory.voucher_id = voucher.id
DBSession.add(batch)
inventory.batch_id = batch.id
product.price = rate
DBSession.add(inventory)
voucher.inventories.append(inventory)

@ -3,6 +3,7 @@ from decimal import Decimal
import uuid
from brewman.models import DBSession
from brewman.models.master import Product, LedgerBase
from brewman.models.operations import inventory_valid, journals_valid
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@ -18,7 +19,8 @@ def purchase_return_create_voucher(json, user):
for item in purchase_return_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']):
DBSession.add(item)
voucher.journals.append(item)
DBSession.flush()
journals_valid(voucher)
inventory_valid(voucher)
return voucher
@ -66,6 +68,8 @@ def purchase_return_update_voucher(voucher, json, user):
purchase_return_update_inventory(voucher, json['Inventories'], json['Date'])
purchase_return_update_journals(voucher, json['Journals'])
journals_valid(voucher)
inventory_valid(voucher)
return voucher

@ -1 +0,0 @@
env\Scripts\pserve brewman\development.ini --reload