Opening Balances: initial commit

This commit is contained in:
Binny G Sreevas 2014-11-21 20:34:38 +05:30
parent a88ed8fc37
commit fb0d8d42ae
9 changed files with 284 additions and 2 deletions

View File

@ -750,6 +750,8 @@
"label.heading.createclosure":"Create Closure",
"label.heading.financialactivity.accountmappings":"Accounts Linked to Financial Activities",
"label.listof.financialactivity.accountmappings":"List of Financial Activity and GL Account Mappings",
"label.heading.define.openingbalances":"Migrate Opening Balances (Office-wise)",
"label.define.openingbalances":"Set or update office-level opening balances for GL Accounts",
"label.heading.financial.activity.type":"Financial Activity",
"label.heading.financial.activity.account.name":"Account Name",
"label.heading.transferredfrom": "Transferred From",
@ -765,6 +767,8 @@
"label.heading.periodicaccrualaccounting":"Execute Periodic Accrual Accounting",
"label.periodicaccrual.tilldate":"Accrue Till",
"validation.msg.periodicaccrual.accrueTill.is.greater.than.date":"Date can't be in future",
"label.heading.openingbalances.migration":"Opening Balances Migration",
"label.anchor.define.openingbalances":"Migrate Opening Balances",
"#Menu Links": "..",
"label.menu.filterbyoffice": "Filter by office",
@ -828,6 +832,8 @@
"label.input.entryid":"Entry ID",
"label.input.filterbyAccountGlcodeAccounttype":"Filter by Account/GL code/Account type",
"label.input.financial.activity.type":"Financial activity",
"label.input.date.of.opening.balances":"Date of opening balances",
"label.input.opening.balances.contra.account":"Opening balances contra",
"#journalEntryType code ": ".............",
"journalEntryType.credit": "Credit",

View File

@ -0,0 +1,104 @@
(function (module) {
mifosX.controllers = _.extend(module, {
DefineOpeningBalancesController: function (scope, resourceFactory, location, translate, routeParams, dateFilter) {
scope.first = {};
scope.formData = {};
scope.first.date = new Date();
scope.accountClosures = [];
scope.restrictDate = new Date();
resourceFactory.officeResource.getAllOffices(function (data) {
scope.offices = data;
});
resourceFactory.currencyConfigResource.get({fields: 'selectedCurrencyOptions'}, function (data) {
scope.currencyOptions = data.selectedCurrencyOptions;
scope.formData.currencyCode = scope.currencyOptions[0].code;
});
scope.submit = function () {
var reqDate = dateFilter(scope.first.date, scope.df);
this.formData.locale = scope.optlang.code;
this.formData.dateFormat = scope.df;
this.formData.transactionDate = reqDate;
this.formData.currencyCode = scope.formData.currencyCode;
this.formData.credits = [];
this.formData.debits = [];
var noErrors = true;
for (var i in scope.allGls) {
if (scope.allGls[i].credit && scope.allGls[i].credit != "" && scope.allGls[i].debit && scope.allGls[i].debit != "") {
if(noErrors){
scope.errorDetails = [];
noErrors = false;
var errorObj = new Object();
errorObj.code = 'error.msg.accounting.defining.openingbalance.both.credit.debits.are.passed';
scope.errorDetails.push(errorObj);
}
} else if (scope.allGls[i].debit && scope.allGls[i].debit != "") {
this.formData.debits.push({"glAccountId":scope.allGls[i].glAccountId, "amount":scope.allGls[i].debit});
} else if (scope.allGls[i].credit && scope.allGls[i].credit) {
this.formData.credits.push({"glAccountId":scope.allGls[i].glAccountId, "amount":scope.allGls[i].credit});
}
}
if(noErrors){
delete scope.errorDetails;
resourceFactory.journalEntriesResource.save({command:"defineOpeningBalance"}, this.formData, function (data) {
location.path('/viewtransactions/' + data.transactionId);
});
}
}
scope.updateDebitCreditAmounts = function (gl) {
if (gl.amount) {
if (gl.entryType) {
if (gl.entryType.value == "DEBIT") {
gl.debit = gl.amount;
} else if (gl.entryType.value == "CREDIT") {
gl.credit = gl.amount;
}
}
}
}
scope.mergeAllGLs = function () {
scope.allGls = [];
scope.debitTotal = 0;
_.each(scope.data.assetAccountOpeningBalances, function(gl){
scope.updateDebitCreditAmounts(gl);
scope.allGls.push(gl);
});
_.each(scope.data.liabityAccountOpeningBalances, function(gl){
scope.updateDebitCreditAmounts(gl);
scope.allGls.push(gl);
});
_.each(scope.data.equityAccountOpeningBalances, function(gl){
scope.updateDebitCreditAmounts(gl);
scope.allGls.push(gl);
});
_.each(scope.data.incomeAccountOpeningBalances, function(gl){
scope.updateDebitCreditAmounts(gl);
scope.allGls.push(gl);
});
_.each(scope.data.expenseAccountOpeningBalances, function(gl){
scope.updateDebitCreditAmounts(gl);
scope.allGls.push(gl);
});
}
scope.retrieveOpeningBalances = function (officeId) {
resourceFactory.officeOpeningResource.get({officeId: officeId}, function (data) {
scope.data = data;
scope.mergeAllGLs();
});
}
}
});
mifosX.ng.application.controller('DefineOpeningBalancesController', ['$scope', 'ResourceFactory', '$location', '$translate', '$routeParams', 'dateFilter', mifosX.controllers.DefineOpeningBalancesController]).run(function ($log) {
$log.info("DefineOpeningBalancesController initialized");
});
}(mifosX.controllers || {}));

View File

@ -0,0 +1,42 @@
(function (module) {
mifosX.filters = _.extend(module, {
AddUpTotalFor: function () {
return function (data, key, conditionfield, conditionvalue) {
if (typeof (data) === 'undefined' && typeof (key) === 'undefined') {
return 0;
}
if (data) {
var sum = 0;
for (var i = 0; i < data.length; i++) {
if (data[i][key]) {
if (conditionfield) {
condFields = conditionfield.split(".");
if (condFields.length == 1) {
if (data[i][condFields[0]] == conditionvalue) {
sum = sum + data[i][key];
}
} else if (condFields.length == 2) {
if (data[i][condFields[0]][condFields[1]] == conditionvalue) {
sum = sum + data[i][key];
}
} else if (condFields.length == 3) {
if (data[i][condFields[0]][condFields[1]][condFields[2]] == conditionvalue) {
sum = sum + data[i][key];
}
}
} else {
sum = sum + data[i][key];
}
}
}
return sum;
} else {
return 0;
}
}
}
});
mifosX.ng.application.filter('AddUpTotalFor', [mifosX.filters.AddUpTotalFor]).run(function ($log) {
$log.info("AddUpTotalFor filter initialized");
});
}(mifosX.filters || {}));

View File

@ -208,7 +208,8 @@ define(['Q', 'underscore', 'mifosX'], function (Q) {
'main/ProfileController',
'main/ViewMakerCheckerTaskController',
'main/AdHocQuerySearchController',
'accounting/AccOGMController'
'accounting/AccOGMController',
'accounting/DefineOpeningBalancesController'
],
filters: [
'StatusLookup',
@ -220,7 +221,8 @@ define(['Q', 'underscore', 'mifosX'], function (Q) {
'DotRemove',
'FormatNumber',
'TranslateDataTableColumn',
'SearchFilter'
'SearchFilter',
'AddUpTotalFor'
],
directives: [
'DialogDirective',

View File

@ -0,0 +1,40 @@
(function (module) {
mifosX.models = _.extend(module, {
CashierTxnAmount: function (data) {
this.txnType = data.txnType.value;
this.amount = data.txnAmount;
this.cashInAmount = function () {
if (this.txnType == 'Cash In') {
return this.amount;
} else {
return '';
}
};
this.cashOutAmount = function () {
if (this.txnType == 'Cash Out') {
return this.amount;
} else {
return '';
}
};
this.allocAmount = function () {
if (this.txnType == 'Allocate Cash') {
return this.amount;
} else {
return '';
}
};
this.settleAmount = function () {
if (this.txnType == 'Settle Cash') {
return this.amount;
} else {
return '';
}
};
}
});
}(mifosX.models || {}));

View File

@ -325,6 +325,9 @@
.when('/run_periodic_accrual',{
templateUrl: 'views/accounting/periodic_accrual_accounting.html'
})
.when('/openingbalances',{
templateUrl: 'views/accounting/openingbalances.html'
})
.when('/viewcode/:id', {
templateUrl: 'views/system/viewcode.html'
})

View File

@ -239,6 +239,9 @@
periodicAccrualAccountingResource: defineResource(apiVer + "/runaccruals", {}, {
run: {method: 'POST', params: {}}
}),
officeOpeningResource: defineResource(apiVer + "/journalentries/openingbalance", {}, {
get: {method: 'GET', params: {}}
}),
codeResources: defineResource(apiVer + "/codes/:codeId", {codeId: "@codeId"}, {
getAllCodes: {method: 'GET', params: {}, isArray: true},
update: { method: 'PUT', params: {} }

View File

@ -26,6 +26,12 @@
<p class="list-group-item-text">{{ 'label.listof.financialactivity.accountmappings' | translate}}</p>
</a>
<a class="list-group-item" href="#/openingbalances" has-permission='READ_JOURNALENTRY'>
<h4 class="list-group-item-heading"><i class="icon-dollar icon-large"></i>&nbsp;&nbsp;{{
'label.heading.define.openingbalances' | translate}}</h4>
<p class="list-group-item-text">{{ 'label.define.openingbalances' | translate}}</p>
</a>
</div>
</div>
<div class="col-sm-6 col-md-6">

View File

@ -0,0 +1,76 @@
<div class="col-md-12" ng-controller="DefineOpeningBalancesController">
<ul class="breadcrumb">
<li><a href="#/accounting">{{'label.anchor.accounting' | translate}}</a></li>
<li class="active">{{'label.anchor.define.openingbalances' | translate}}</li>
</ul>
<api-validate></api-validate>
<form name="openingbalancesform" novalidate="" class="form-horizontal well" ng-submit="submit()">
<div class="form-group">
<label class="control-label col-sm-2">{{ 'label.input.office' | translate }}<span class="required">*</span></label>
<div class="col-sm-3">
<select chosen="offices" id="officeId" ng-model="formData.officeId" class="form-control"
ng-options="office.id as office.name for office in offices" value="{{office.id}}"
ng-change="retrieveOpeningBalances(formData.officeId)" required="required">
<option class="displaynone" value="">{{'label.selectoffice' | translate}}</option>
</select>
</div>
</div>
<div class="form-group" ng-show="formData.officeId">
<label class="control-label col-sm-2">{{ 'label.input.opening.balances.contra.account' | translate }}</label>
<div class="col-sm-3">
<label class="control-label">{{ data.contraAccount.name }}({{data.contraAccount.glCode}})</label>
</div>
</div>
<div class="form-group" ng-show="formData.officeId">
<label class="control-label col-sm-2">{{ 'label.input.date.of.opening.balances' | translate }}<span class="required">*</span></label>
<div class="col-sm-3">
<input class="date-disable form-control" type="text" datepicker-pop="dd MMMM yyyy" ng-model="first.date"
is-open="opened" min="'2000-01-01'" max="restrictDate"/>
</div>
<label class="control-label col-sm-2">{{ 'label.input.currency' | translate }}&nbsp;<span
class="required">*</span></label>
<div class="col-sm-3">
<select id="currencyCode" name="currency" ng-model="formData.currencyCode" class="form-control"
ng-options="currency.code as (currency.name+' ('+ currency.displaySymbol +')') for currency in currencyOptions"
value="{{currency.code}}" required>
</select>
</div>
</div>
<table class="table" ng-show="allGls">
<thead>
<tr class="graybg">
<th>{{'label.heading.type' | translate}}</th>
<th>{{'label.heading.glcode' | translate}}</th>
<th>{{'label.heading.account' | translate}}</th>
<th>{{'label.heading.debit' | translate}} : {{ allGls | AddUpTotalFor:'amount':'entryType.value':'DEBIT' | number}} </th>
<th>{{'label.heading.credit' | translate}} : {{ allGls | AddUpTotalFor:'amount':'entryType.value':'CREDIT' | number}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="gl in allGls">
<td>
<span ng-show="allGls[$index].glAccountType.value != allGls[$index-1].glAccountType.value">
{{gl.glAccountType.value}}
</span>
</td>
<td>{{gl.glAccountCode}}</td>
<td>{{gl.glAccountName}}</td>
<td><input type="text" name="debits{{$index}}" ng-model="gl.debit" class="form-control" /></td>
<td><input type="text" name="credits{{$index}}" ng-model="gl.credit" class="form-control" /></td>
</tr>
</tbody>
</table>
<div class="col-md-offset-3">
<a id="cancel" href="#/accounting" class="btn btn-default">{{ 'label.button.cancel' | translate }}</a>
<button id="save" type="submit" class="btn btn-primary" has-permission='CREATE_JOURNALENTRY'>{{ 'label.button.save' | translate }}</button>
</div>
</form>
</div>