Changed the autocomplete from jQuery to Bootstrap.typeahead
Added DeepLabel factory to get values from inside nested json objects. Split SalaryDeductionController into its own file.
This commit is contained in:
parent
105f72f50f
commit
5a28d9717b
|
@ -12,7 +12,7 @@
|
||||||
<label for="txtEmployee" class="control-label">Employee</label>
|
<label for="txtEmployee" class="control-label">Employee</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtEmployee" resource="Employee" model="info.Employee"
|
<input type="text" ng-autocomplete id="txtEmployee" resource="Employee" label="Name" model="info.Employee"
|
||||||
value="{{info.Employee.Name}}"/>
|
value="{{info.Employee.Name}}"/>
|
||||||
<button class="btn btn-info" ng-click="show()">Show</button>
|
<button class="btn btn-info" ng-click="show()">Show</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class=" control-group">
|
<div class=" control-group">
|
||||||
<label for="editBatch">Product</label>
|
<label for="editBatch">Product</label>
|
||||||
<input type="text" ng-autocomplete id="editBatch" resource="Batch" model="edit.Batch" value="{{edit.Batch.Product.Name}}"/>
|
<input type="text" ng-autocomplete id="editBatch" resource="Batch" label="Name" model="edit.Batch" value="{{edit.Batch.Product.Name}}"/>
|
||||||
<label for="editQuantity">Quantity</label>
|
<label for="editQuantity">Quantity</label>
|
||||||
<input type="text" id="editQuantity" autocomplete="off" class="non-search-box inline"
|
<input type="text" id="editQuantity" autocomplete="off" class="non-search-box inline"
|
||||||
placeholder="Quantity" ng-model="edit.Quantity"/>
|
placeholder="Quantity" ng-model="edit.Quantity"/>
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<label for="txtBatch" class="control-label">Product</label>
|
<label for="txtBatch" class="control-label">Product</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtBatch" resource="Batch" model="batch" value="{{batch.Name}}"/>
|
<input type="text" ng-autocomplete id="txtBatch" resource="Batch" label="Name" model="batch" value="{{batch.Name}}"/>
|
||||||
<input type="text" id="txtQuantity" class="span2" autocomplete="off" placeholder="Quantity"
|
<input type="text" id="txtQuantity" class="span2" autocomplete="off" placeholder="Quantity"
|
||||||
ng-model="quantity"/>
|
ng-model="quantity"/>
|
||||||
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
|
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class=" control-group">
|
<div class=" control-group">
|
||||||
<label for="editAccount">Account</label>
|
<label for="editAccount">Account</label>
|
||||||
<input type="text" ng-autocomplete id="editAccount" resource="Account" model="edit.Ledger"
|
<input type="text" ng-autocomplete id="editAccount" resource="Account" label="Name" model="edit.Ledger"
|
||||||
value="{{edit.Ledger.Name}}"/>
|
value="{{edit.Ledger.Name}}"/>
|
||||||
<label for="editAmount">Amount</label>
|
<label for="editAmount">Amount</label>
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<option value="1">Dr</option>
|
<option value="1">Dr</option>
|
||||||
<option value="-1">Cr</option>
|
<option value="-1">Cr</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" ng-autocomplete id="txtLedger" resource="Account" model="ledger" value="{{ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="txtLedger" resource="Account" label="Name" model="ledger" value="{{ledger.Name}}"/>
|
||||||
<div class="input-prepend">
|
<div class="input-prepend">
|
||||||
<span class="add-on">₹</span><input type="text" id="txtAmount" class="span2" autocomplete="off"
|
<span class="add-on">₹</span><input type="text" id="txtAmount" class="span2" autocomplete="off"
|
||||||
placeholder="Amount" ng-model="amount"/>
|
placeholder="Amount" ng-model="amount"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label for="txtLedger" class="control-label">Ledger</label>
|
<label for="txtLedger" class="control-label">Ledger</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtLedger" resource="Account" model="info.Ledger" value="{{info.Ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="txtLedger" resource="Account" label="Name" model="info.Ledger" value="{{info.Ledger.Name}}"/>
|
||||||
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
|
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class=" control-group">
|
<div class=" control-group">
|
||||||
<label for="editAccount">Account</label>
|
<label for="editAccount">Account</label>
|
||||||
<input type="text" ng-autocomplete id="editAccount" resource="Account" model="edit.Ledger" value="{{edit.Ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="editAccount" resource="Account" label="Name" model="edit.Ledger" value="{{edit.Ledger.Name}}"/>
|
||||||
<label for="editAmount">Amount</label>
|
<label for="editAmount">Amount</label>
|
||||||
|
|
||||||
<div class="input-prepend input-append">
|
<div class="input-prepend input-append">
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<label for="txtLedger" class="control-label">Account</label>
|
<label for="txtLedger" class="control-label">Account</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtLedger" resource="Account" model="ledger" value="{{ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="txtLedger" resource="Account" label="Name" model="ledger" value="{{ledger.Name}}"/>
|
||||||
<div class=" input-prepend">
|
<div class=" input-prepend">
|
||||||
<span class="add-on">₹</span>
|
<span class="add-on">₹</span>
|
||||||
<input type="text" id="txtAmount" class="span2" autocomplete="off"
|
<input type="text" id="txtAmount" class="span2" autocomplete="off"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label for="txtProduct" class="control-label">Ledger</label>
|
<label for="txtProduct" class="control-label">Ledger</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtProduct" resource="Product" model="info.Product"
|
<input type="text" ng-autocomplete id="txtProduct" resource="Product" label="Name" model="info.Product"
|
||||||
value="{{info.Product.Name}}"/>
|
value="{{info.Product.Name}}"/>
|
||||||
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
|
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class=" control-group">
|
<div class=" control-group">
|
||||||
<label for="editBatch">Product</label>
|
<label for="editBatch">Product</label>
|
||||||
<input type="text" ng-autocomplete id="editBatch" resource="Batch" model="edit.Batch" value="{{edit.Batch.Product.Name}}"/>
|
<input type="text" ng-autocomplete id="editBatch" resource="Batch" label="Name" model="edit.Batch" value="{{edit.Batch.Product.Name}}"/>
|
||||||
<label for="editQuantity">Quantity</label>
|
<label for="editQuantity">Quantity</label>
|
||||||
<input type="text" id="editQuantity" autocomplete="off" class="non-search-box inline"
|
<input type="text" id="editQuantity" autocomplete="off" class="non-search-box inline"
|
||||||
placeholder="Quantity" ng-model="edit.Quantity"/>
|
placeholder="Quantity" ng-model="edit.Quantity"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label for="txtLedger" class="control-label">Ledger</label>
|
<label for="txtLedger" class="control-label">Ledger</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="txtLedger" ng-autocomplete resource="Account" model="journal.Ledger" value="{{journal.Ledger.Name}}"/>
|
<input type="text" id="txtLedger" ng-autocomplete resource="Account" label="Name" model="journal.Ledger" value="{{journal.Ledger.Name}}"/>
|
||||||
|
|
||||||
<div class="input-prepend">
|
<div class="input-prepend">
|
||||||
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2"
|
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2"
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<label for="txtBatch" class="control-label">Product</label>
|
<label for="txtBatch" class="control-label">Product</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtBatch" resource="Batch" model="batch"/>
|
<input type="text" ng-autocomplete id="txtBatch" resource="Batch" label="Name" model="batch"/>
|
||||||
<input type="text" id="txtQuantity" class="span2" autocomplete="off"
|
<input type="text" id="txtQuantity" class="span2" autocomplete="off"
|
||||||
placeholder="Quantity" ng-model="quantity"/>
|
placeholder="Quantity" ng-model="quantity"/>
|
||||||
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
|
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label for="txtLedger" class="control-label">Account</label>
|
<label for="txtLedger" class="control-label">Account</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="txtLedger" ng-autocomplete resource="Account" model="journal.Ledger" value="{{journal.Ledger.Name}}"/>
|
<input type="text" id="txtLedger" ng-autocomplete resource="Account" label="Name" model="journal.Ledger" value="{{journal.Ledger.Name}}"/>
|
||||||
|
|
||||||
<div class="input-prepend">
|
<div class="input-prepend">
|
||||||
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2"
|
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2"
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<label for="txtProduct" class="control-label">Product</label>
|
<label for="txtProduct" class="control-label">Product</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtProduct" class="search-box" resource="Product" model="product"/>
|
<input type="text" ng-autocomplete id="txtProduct" class="search-box" resource="Product" label="Name" model="product"/>
|
||||||
<input type="text" id="txtQuantity" autocomplete="off" class="non-search-box inline"
|
<input type="text" id="txtQuantity" autocomplete="off" class="non-search-box inline"
|
||||||
placeholder="Quantity" ng-model="quantity"/>
|
placeholder="Quantity" ng-model="quantity"/>
|
||||||
<input type="text" id="txtPrice" autocomplete="off" class="non-search-box inline"
|
<input type="text" id="txtPrice" autocomplete="off" class="non-search-box inline"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class=" control-group">
|
<div class=" control-group">
|
||||||
<label for="editAccount">Account</label>
|
<label for="editAccount">Account</label>
|
||||||
<input type="text" ng-autocomplete id="editAccount" resource="Account" model="edit.Ledger" value="{{edit.Ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="editAccount" resource="Account" label="Name" model="edit.Ledger" value="{{edit.Ledger.Name}}"/>
|
||||||
<label for="editAmount">Amount</label>
|
<label for="editAmount">Amount</label>
|
||||||
|
|
||||||
<div class="input-prepend input-append">
|
<div class="input-prepend input-append">
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<label for="txtLedger" class="control-label">Account</label>
|
<label for="txtLedger" class="control-label">Account</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtLedger" resource="Account" model="ledger" value="{{ledger.Name}}"/>
|
<input type="text" ng-autocomplete id="txtLedger" resource="Account" label="Name" model="ledger" value="{{ledger.Name}}"/>
|
||||||
<div class=" input-prepend">
|
<div class=" input-prepend">
|
||||||
<span class="add-on">₹</span>
|
<span class="add-on">₹</span>
|
||||||
<input type="text" id="txtAmount" class="span2" autocomplete="off"
|
<input type="text" id="txtAmount" class="span2" autocomplete="off"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<label for="txtEmployee" class="control-label">Employee</label>
|
<label for="txtEmployee" class="control-label">Employee</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" ng-autocomplete id="txtEmployee" resource="Employee" model="employee"
|
<input type="text" ng-autocomplete id="txtEmployee" resource="Employee" label="Name" model="employee"
|
||||||
value="{{info.Employee.Name}}"/>
|
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="Gross Salary" ng-model="grossSalary"/>
|
||||||
<input type="text" class="span2" autocomplete="off" placeholder="Days Worked" ng-model="daysWorked"/>
|
<input type="text" class="span2" autocomplete="off" placeholder="Days Worked" ng-model="daysWorked"/>
|
||||||
|
|
|
@ -1,32 +1,40 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var overlord_directive = angular.module('overlord.directive', []);
|
var overlord_directive = angular.module('overlord.directive', []);
|
||||||
overlord_directive.directive('ngAutocomplete', ['$q', '$parse', function ($q, $parse) {
|
overlord_directive.directive('ngAutocomplete', ['$q', '$parse', 'DeepLabel', function ($q, $parse, DeepLabel) {
|
||||||
return {
|
return {
|
||||||
restrict:'A',
|
restrict:'A',
|
||||||
link:function (scope, element, attrs, ngModel) {
|
link:function (scope, element, attrs, ngModel) {
|
||||||
element.autocomplete({
|
var labels = [],
|
||||||
source:function (request, response) {
|
mapped = {},
|
||||||
var Entity = angular.injector(['overlord.service']).get(attrs.resource),
|
deepLabel = DeepLabel;
|
||||||
deferred = $q.defer();
|
|
||||||
|
|
||||||
deferred.promise.then(function (result) {
|
|
||||||
response(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
Entity.autocomplete({term:request.term, count:20}, function (result) {
|
element.typeahead({
|
||||||
scope.$apply(function () {
|
source:function (query, process) {
|
||||||
deferred.resolve(result);
|
var Entity = angular.injector(['overlord.service']).get(attrs.resource);
|
||||||
});
|
Entity.autocomplete({term:query, count:20}, function (result) {
|
||||||
|
labels = [];
|
||||||
|
mapped = {};
|
||||||
|
$.each(result, function (i, item) {
|
||||||
|
var label = deepLabel(item, attrs.label);
|
||||||
|
mapped[label] = item
|
||||||
|
labels.push(label)
|
||||||
|
})
|
||||||
|
process(labels)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
minLength:1,
|
minLength:1,
|
||||||
autoFocus:true,
|
items:20,
|
||||||
select:function (event, ui) {
|
matcher:function (item) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
updater:function (item) {
|
||||||
var model = $parse(attrs.model);
|
var model = $parse(attrs.model);
|
||||||
var modelSetter = model.assign;
|
var modelSetter = model.assign;
|
||||||
modelSetter(scope, ui.item.model);
|
modelSetter(scope, mapped[item]);
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,3 +146,20 @@ overlord_service.factory('AttendanceTypes', ['$resource', function ($resource) {
|
||||||
overlord_service.factory('EmployeeAttendance', ['$resource', function ($resource) {
|
overlord_service.factory('EmployeeAttendance', ['$resource', function ($resource) {
|
||||||
return $resource('/EmployeeAttendance/:id', {id:'@Employee.LedgerID'});
|
return $resource('/EmployeeAttendance/:id', {id:'@Employee.LedgerID'});
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
overlord_service.factory('DeepLabel', function () {
|
||||||
|
return function getLabel(o, s) {
|
||||||
|
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
|
||||||
|
s = s.replace(/^\./, ''); // strip a leading dot
|
||||||
|
var a = s.split('.');
|
||||||
|
while (a.length) {
|
||||||
|
var n = a.shift();
|
||||||
|
if (n in o) {
|
||||||
|
o = o[n];
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
|
@ -22,160 +22,3 @@ var EmployeeFunctionsCtrl = ['$scope', '$http', function ($scope, $http) {
|
||||||
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
var SalaryDeductionCtrl = ['$scope', '$location', 'voucher', function ($scope, $location, voucher) {
|
|
||||||
$scope.voucher = voucher;
|
|
||||||
$scope.name = '';
|
|
||||||
|
|
||||||
function getOldItem(ledgerID, items) {
|
|
||||||
for (var i = 0, l = items.length; i < l; i++) {
|
|
||||||
if (items[i].Journal.Ledger.LedgerID === ledgerID) {
|
|
||||||
return journals[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function daysInMonthFunction(date) {
|
|
||||||
var months = {
|
|
||||||
Jan:1,
|
|
||||||
Feb:2,
|
|
||||||
Mar:3,
|
|
||||||
Apr:4,
|
|
||||||
May:5,
|
|
||||||
Jun:6,
|
|
||||||
Jul:7,
|
|
||||||
Aug:8,
|
|
||||||
Sep:9,
|
|
||||||
Oct:10,
|
|
||||||
Nov:11,
|
|
||||||
Dev:12
|
|
||||||
}
|
|
||||||
if (!date.match(/^\d{2}-[\w]{3}-[\d]{4}$/g)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var parts = date.split("-");
|
|
||||||
return new Date(parseInt(parts[2]), months[parts[1]], 0).getDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEsi(grossSalary, daysWorked, daysInMonth) {
|
|
||||||
var limit = 15000,
|
|
||||||
employee_rate = .0175,
|
|
||||||
employer_rate = .0475;
|
|
||||||
var employee = (grossSalary > limit) ? 0 : Math.ceil(employee_rate * grossSalary * daysWorked / daysInMonth)
|
|
||||||
var employer = (grossSalary > limit) ? 0 : Math.ceil(employer_rate * grossSalary * daysWorked / daysInMonth)
|
|
||||||
return {ee:employee, er:employer, both:employee + employer};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPf(grossSalary, daysWorked, daysInMonth) {
|
|
||||||
var limit = 6500,
|
|
||||||
employee_rate = .12,
|
|
||||||
employer_rate = .12 + .011 + .005 + .0001;
|
|
||||||
var employee = (grossSalary > limit) ? 0 : Math.ceil(employee_rate * grossSalary * daysWorked / daysInMonth)
|
|
||||||
var employer = (grossSalary > limit) ? 0 : Math.ceil(employer_rate * grossSalary * daysWorked / daysInMonth)
|
|
||||||
return {ee:employee, er:employer, both:employee + employer};
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.add = function () {
|
|
||||||
var oldJournal = getOldItem($scope.employee.LedgerID, this.voucher.SalaryDeductions),
|
|
||||||
grossSalary = parseInt($scope.grossSalary),
|
|
||||||
daysWorked = parseInt($scope.daysWorked),
|
|
||||||
daysInMonth = daysInMonthFunction($scope.voucher.Date),
|
|
||||||
esi = getEsi(grossSalary, daysWorked, daysInMonth),
|
|
||||||
pf = getPf(grossSalary, daysWorked, daysInMonth);
|
|
||||||
|
|
||||||
if (typeof oldJournal !== 'undefined') {
|
|
||||||
$scope.toasts.push({Type:'Error', Message:'Employee has already been added!'});
|
|
||||||
} else {
|
|
||||||
this.voucher.SalaryDeductions.push(
|
|
||||||
{
|
|
||||||
Journal:{Ledger:$scope.employee},
|
|
||||||
GrossSalary:grossSalary,
|
|
||||||
DaysWorked:daysWorked,
|
|
||||||
EsiEmployee:esi.ee,
|
|
||||||
PfEmployee:pf.ee,
|
|
||||||
EsiEmployer:esi.er,
|
|
||||||
PfEmployer:pf.er
|
|
||||||
}
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
delete $scope.employee;
|
|
||||||
delete $scope.grossSalary;
|
|
||||||
delete $scope.daysWorked;
|
|
||||||
$('#txtEmployee').val('');
|
|
||||||
$('#txtEmployee').focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.remove = function (deduction) {
|
|
||||||
var index = this.voucher.SalaryDeductions.indexOf(deduction);
|
|
||||||
this.voucher.SalaryDeductions.splice(index, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.preventAlteration = function (voucher) {
|
|
||||||
if (typeof $scope.perms === 'undefined') {
|
|
||||||
return false;
|
|
||||||
} else if (typeof voucher.VoucherID === 'undefined') {
|
|
||||||
return !$scope.perms['Salary Deduction'];
|
|
||||||
} else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) {
|
|
||||||
return true;
|
|
||||||
} else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.get = function (voucherid) {
|
|
||||||
$scope.voucher = Voucher.get({VoucherID:voucherid}, function (u, putResponseHeaders) {
|
|
||||||
$scope.toasts.push({Type:'Success', Message:''});
|
|
||||||
}, function (data, status) {
|
|
||||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.save = function () {
|
|
||||||
$scope.voucher.$save({type:'Salary Deduction'}, function (u, putResponseHeaders) {
|
|
||||||
$scope.toasts.push({Type:'Success', Message:''});
|
|
||||||
$location.path('/SalaryDeduction/' + u.VoucherID);
|
|
||||||
}, function (data, status) {
|
|
||||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.delete = function () {
|
|
||||||
$scope.voucher.$delete(function (u, putResponseHeaders) {
|
|
||||||
$scope.toasts.push({Type:'Success', Message:''});
|
|
||||||
$location.path('/SalaryDeduction').replace();
|
|
||||||
}, function (data, status) {
|
|
||||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.post = function () {
|
|
||||||
$scope.voucher.$post(function (u, putResponseHeaders) {
|
|
||||||
$scope.toasts.push({Type:'Success', Message:''});
|
|
||||||
}, function (data, status) {
|
|
||||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}]
|
|
||||||
|
|
||||||
|
|
||||||
SalaryDeductionCtrl.resolve = {
|
|
||||||
voucher:['$q', '$route', 'Voucher', function ($q, $route, Voucher) {
|
|
||||||
var deferred = $q.defer();
|
|
||||||
|
|
||||||
var id = $route.current.params.id;
|
|
||||||
|
|
||||||
var successCb = function (result) {
|
|
||||||
deferred.resolve(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof id === 'undefined') {
|
|
||||||
Voucher.get({type:'Salary Deduction'}, successCb);
|
|
||||||
} else {
|
|
||||||
Voucher.get({id:id}, successCb);
|
|
||||||
}
|
|
||||||
return deferred.promise;
|
|
||||||
}]
|
|
||||||
};
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var SalaryDeductionCtrl = ['$scope', '$location', 'voucher', function ($scope, $location, voucher) {
|
||||||
|
$scope.voucher = voucher;
|
||||||
|
$scope.name = '';
|
||||||
|
|
||||||
|
function getOldItem(ledgerID, items) {
|
||||||
|
for (var i = 0, l = items.length; i < l; i++) {
|
||||||
|
if (items[i].Journal.Ledger.LedgerID === ledgerID) {
|
||||||
|
return items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function daysInMonthFunction(date) {
|
||||||
|
var months = {
|
||||||
|
Jan:1,
|
||||||
|
Feb:2,
|
||||||
|
Mar:3,
|
||||||
|
Apr:4,
|
||||||
|
May:5,
|
||||||
|
Jun:6,
|
||||||
|
Jul:7,
|
||||||
|
Aug:8,
|
||||||
|
Sep:9,
|
||||||
|
Oct:10,
|
||||||
|
Nov:11,
|
||||||
|
Dev:12
|
||||||
|
}
|
||||||
|
if (!date.match(/^\d{2}-[\w]{3}-[\d]{4}$/g)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var parts = date.split("-");
|
||||||
|
return new Date(parseInt(parts[2]), months[parts[1]], 0).getDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEsi(grossSalary, daysWorked, daysInMonth) {
|
||||||
|
var limit = 15000,
|
||||||
|
employee_rate = .0175,
|
||||||
|
employer_rate = .0475;
|
||||||
|
var employee = (grossSalary > limit) ? 0 : Math.ceil(employee_rate * grossSalary * daysWorked / daysInMonth)
|
||||||
|
var employer = (grossSalary > limit) ? 0 : Math.ceil(employer_rate * grossSalary * daysWorked / daysInMonth)
|
||||||
|
return {ee:employee, er:employer, both:employee + employer};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPf(grossSalary, daysWorked, daysInMonth) {
|
||||||
|
var limit = 6500,
|
||||||
|
employee_rate = .12,
|
||||||
|
employer_rate = .12 + .011 + .005 + .0001;
|
||||||
|
var employee = (grossSalary > limit) ? 0 : Math.ceil(employee_rate * grossSalary * daysWorked / daysInMonth)
|
||||||
|
var employer = (grossSalary > limit) ? 0 : Math.ceil(employer_rate * grossSalary * daysWorked / daysInMonth)
|
||||||
|
return {ee:employee, er:employer, both:employee + employer};
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.add = function () {
|
||||||
|
var oldJournal = getOldItem($scope.employee.LedgerID, this.voucher.SalaryDeductions),
|
||||||
|
grossSalary = parseInt($scope.grossSalary),
|
||||||
|
daysWorked = parseInt($scope.daysWorked),
|
||||||
|
daysInMonth = daysInMonthFunction($scope.voucher.Date),
|
||||||
|
esi = getEsi(grossSalary, daysWorked, daysInMonth),
|
||||||
|
pf = getPf(grossSalary, daysWorked, daysInMonth);
|
||||||
|
|
||||||
|
if (typeof oldJournal !== 'undefined') {
|
||||||
|
$scope.toasts.push({Type:'Error', Message:'Employee has already been added!'});
|
||||||
|
} else {
|
||||||
|
this.voucher.SalaryDeductions.push(
|
||||||
|
{
|
||||||
|
Journal:{Ledger:$scope.employee},
|
||||||
|
GrossSalary:grossSalary,
|
||||||
|
DaysWorked:daysWorked,
|
||||||
|
EsiEmployee:esi.ee,
|
||||||
|
PfEmployee:pf.ee,
|
||||||
|
EsiEmployer:esi.er,
|
||||||
|
PfEmployer:pf.er
|
||||||
|
}
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
delete $scope.employee;
|
||||||
|
delete $scope.grossSalary;
|
||||||
|
delete $scope.daysWorked;
|
||||||
|
$('#txtEmployee').val('');
|
||||||
|
$('#txtEmployee').focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.remove = function (deduction) {
|
||||||
|
var index = this.voucher.SalaryDeductions.indexOf(deduction);
|
||||||
|
this.voucher.SalaryDeductions.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.preventAlteration = function (voucher) {
|
||||||
|
if (typeof $scope.perms === 'undefined') {
|
||||||
|
return false;
|
||||||
|
} else if (typeof voucher.VoucherID === 'undefined') {
|
||||||
|
return !$scope.perms['Salary Deduction'];
|
||||||
|
} else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) {
|
||||||
|
return true;
|
||||||
|
} else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.get = function (voucherid) {
|
||||||
|
$scope.voucher = Voucher.get({VoucherID:voucherid}, function (u, putResponseHeaders) {
|
||||||
|
$scope.toasts.push({Type:'Success', Message:''});
|
||||||
|
}, function (data, status) {
|
||||||
|
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.save = function () {
|
||||||
|
$scope.voucher.$save({type:'Salary Deduction'}, function (u, putResponseHeaders) {
|
||||||
|
$scope.toasts.push({Type:'Success', Message:''});
|
||||||
|
$location.path('/SalaryDeduction/' + u.VoucherID);
|
||||||
|
}, function (data, status) {
|
||||||
|
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.delete = function () {
|
||||||
|
$scope.voucher.$delete(function (u, putResponseHeaders) {
|
||||||
|
$scope.toasts.push({Type:'Success', Message:''});
|
||||||
|
$location.path('/SalaryDeduction').replace();
|
||||||
|
}, function (data, status) {
|
||||||
|
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.post = function () {
|
||||||
|
$scope.voucher.$post(function (u, putResponseHeaders) {
|
||||||
|
$scope.toasts.push({Type:'Success', Message:''});
|
||||||
|
}, function (data, status) {
|
||||||
|
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
|
SalaryDeductionCtrl.resolve = {
|
||||||
|
voucher:['$q', '$route', 'Voucher', function ($q, $route, Voucher) {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
|
||||||
|
var id = $route.current.params.id;
|
||||||
|
|
||||||
|
var successCb = function (result) {
|
||||||
|
deferred.resolve(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof id === 'undefined') {
|
||||||
|
Voucher.get({type:'Salary Deduction'}, successCb);
|
||||||
|
} else {
|
||||||
|
Voucher.get({id:id}, successCb);
|
||||||
|
}
|
||||||
|
return deferred.promise;
|
||||||
|
}]
|
||||||
|
};
|
|
@ -40,6 +40,7 @@
|
||||||
<script src="/script/purchase.js"> </script>
|
<script src="/script/purchase.js"> </script>
|
||||||
<script src="/script/purchase-return.js"> </script>
|
<script src="/script/purchase-return.js"> </script>
|
||||||
<script src="/script/issue.js"> </script>
|
<script src="/script/issue.js"> </script>
|
||||||
|
<script src="/script/salary-deduction.js"> </script>
|
||||||
|
|
||||||
<script src="/script/employee-attendance.js"> </script>
|
<script src="/script/employee-attendance.js"> </script>
|
||||||
<script src="/script/employee-functions.js"> </script>
|
<script src="/script/employee-functions.js"> </script>
|
||||||
|
|
|
@ -102,7 +102,7 @@ def show_term(request):
|
||||||
def ledger_list(type=None, filter=None, count=None):
|
def ledger_list(type=None, filter=None, count=None):
|
||||||
list = []
|
list = []
|
||||||
for index, item in enumerate(LedgerBase.list(type, filter)):
|
for index, item in enumerate(LedgerBase.list(type, filter)):
|
||||||
list.append({'label': item.name, 'model': {'LedgerID': item.id, 'Name': item.name}})
|
list.append({'LedgerID': item.id, 'Name': item.name})
|
||||||
if count is not None and index == count - 1:
|
if count is not None and index == count - 1:
|
||||||
break
|
break
|
||||||
return list
|
return list
|
||||||
|
|
|
@ -105,10 +105,8 @@ def show_term(request):
|
||||||
|
|
||||||
list = []
|
list = []
|
||||||
for index, item in enumerate(LedgerBase.list(10, filter)):
|
for index, item in enumerate(LedgerBase.list(10, filter)):
|
||||||
list.append({'label': item.name,
|
list.append({'LedgerID': item.id, 'Name': item.name, 'Designation': item.designation,
|
||||||
'model': {'LedgerID': item.id, 'Name': item.name, 'Designation': item.designation,
|
'CostCenter': {'CostCenterID': item.costcenter.id, 'Name': item.costcenter.name}})
|
||||||
'CostCenter': {'CostCenterID': item.costcenter.id,
|
|
||||||
'Name': item.costcenter.name}}})
|
|
||||||
if count is not None and index == count - 1:
|
if count is not None and index == count - 1:
|
||||||
break
|
break
|
||||||
return list
|
return list
|
||||||
|
|
|
@ -102,8 +102,7 @@ def show_term(request):
|
||||||
count = None if count is None or count == '' else int(count)
|
count = None if count is None or count == '' else int(count)
|
||||||
list = []
|
list = []
|
||||||
for index, item in enumerate(Product.list(filter)):
|
for index, item in enumerate(Product.list(filter)):
|
||||||
list.append({'label': item.full_name,
|
list.append({'ProductID': item.id, 'Name': item.full_name, 'Price': item.price})
|
||||||
'model': {'ProductID': item.id, 'Name': item.full_name, 'Price': item.price}})
|
|
||||||
if count is not None and index == count - 1:
|
if count is not None and index == count - 1:
|
||||||
break
|
break
|
||||||
return list
|
return list
|
||||||
|
|
|
@ -13,11 +13,9 @@ def batch_term(request):
|
||||||
text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format(item.product.name, item.product.units,
|
text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format(item.product.name, item.product.units,
|
||||||
item.quantity_remaining,
|
item.quantity_remaining,
|
||||||
item.rate, item.name)
|
item.rate, item.name)
|
||||||
list.append({'label': text,
|
list.append({'BatchID': item.id, 'Name': text, 'QuantityRemaining': item.quantity_remaining,
|
||||||
'model': {
|
'Rate': item.rate, 'Tax': item.tax, 'Discount': item.discount,
|
||||||
'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units},
|
'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units}})
|
||||||
'BatchID': item.id, 'Name': text, 'QuantityRemaining': item.quantity_remaining,
|
|
||||||
'Rate': item.rate, 'Tax': item.tax, 'Discount': item.discount}})
|
|
||||||
if count is not None and index == count - 1:
|
if count is not None and index == count - 1:
|
||||||
break
|
break
|
||||||
return list
|
return list
|
||||||
|
|
Loading…
Reference in New Issue