From ca5bc6325a8fa1b5fc8be4fe44bb036307ff267c Mon Sep 17 00:00:00 2001 From: Angel Cajas Date: Mon, 24 Aug 2020 14:18:15 -0600 Subject: [PATCH] Rate Module (#3000) New pages were added for Rate definition and rates can be added in loan products and accounts Co-authored-by: Angel Cajas --- app/global-translations/locale-en.json | 13 +- app/global-translations/locale-es.json | 10 ++ .../loanAccount/EditLoanAccAppController.js | 63 +++++++- .../loanAccount/NewLoanAccAppController.js | 58 ++++++- .../loanAccount/ViewLoanDetailsController.js | 1 + .../ViewLoanTransactionController.js | 141 +++++++++++++++++- .../product/CreateLoanProductController.js | 58 ++++++- .../product/CreateRateController.js | 37 +++++ .../product/EditLoanProductController.js | 74 ++++++++- .../controllers/product/EditRateController.js | 42 ++++++ .../controllers/product/RateController.js | 33 ++++ .../product/ViewLoanProductController.js | 2 +- .../controllers/product/ViewRateController.js | 19 +++ app/scripts/mifosXComponents.js | 6 +- app/scripts/routes.js | 12 ++ .../services/ResourceFactoryProvider.js | 6 + app/views/loans/editloanaccount.html | 38 ++++- app/views/loans/newloanaccount.html | 40 ++++- app/views/loans/view_loan_transaction.html | 14 ++ app/views/products/createloanproduct.html | 73 ++++++++- app/views/products/createrate.html | 72 +++++++++ app/views/products/editloanproduct.html | 61 +++++++- app/views/products/editrate.html | 55 +++++++ app/views/products/products.html | 6 + app/views/products/rates.html | 40 +++++ app/views/products/viewrate.html | 35 +++++ 26 files changed, 985 insertions(+), 24 deletions(-) create mode 100644 app/scripts/controllers/product/CreateRateController.js create mode 100644 app/scripts/controllers/product/EditRateController.js create mode 100644 app/scripts/controllers/product/RateController.js create mode 100644 app/scripts/controllers/product/ViewRateController.js create mode 100644 app/views/products/createrate.html create mode 100644 app/views/products/editrate.html create mode 100644 app/views/products/rates.html create mode 100644 app/views/products/viewrate.html diff --git a/app/global-translations/locale-en.json b/app/global-translations/locale-en.json index dc15343a..be3e94a2 100644 --- a/app/global-translations/locale-en.json +++ b/app/global-translations/locale-en.json @@ -4232,7 +4232,7 @@ "label.createdselfserviceuser": "Self Service User created successfully", "validation.msg.client.dateOfBirth.is.greater.than.date" : "Client date of birth can not be greater than the client submitted on date.", - + "label.input.maturity.instruction" : "Maturity Instruction", "label.input.apply.maturity.instructions" :"Add Maturity Instructions", "label.input.transfer.to.account" : "Transfer To Savings Account", @@ -4246,5 +4246,16 @@ "error.msg.user.self.service.user.already.exist" : "Self Service User ID is already created. Go to Admin -> Users to edit or delete the self-service user.", + + "label.anchor.rates": "Rates", + "label.heading.rates": "Rates", + "label.rates" : "Define rates for loan products, savings and deposit products.", + "label.button.createrate" : "Create Rate", + "label.anchor.createrate" : "Create Rate", + "label.heading.rateappliesto" : "Rate applies to", + "label.anchor.editrate": "Edit Rate", + "label.error.rate.already.exist" : "Rate already exist.", + "label.selectrate" : "Select Rate", + "----End---": "--End of file--- " } diff --git a/app/global-translations/locale-es.json b/app/global-translations/locale-es.json index af9edd1e..88d7a820 100644 --- a/app/global-translations/locale-es.json +++ b/app/global-translations/locale-es.json @@ -4007,5 +4007,15 @@ "label.input.emi.change.upto": "Fecha de finalización de cambio de EMI", "label.input.changeEMI": "Cambiar EMI", "label.input.installment.date": "Fecha de abono", + "#Rates":"...", + "label.anchor.rates": "Tasas", + "label.heading.rates": "Tasas", + "label.rates" : "Definir tasas para el Producto-préstamo, ahorros y depósitos de productos.", + "label.button.createrate" : "Crear Tasa", + "label.anchor.createrate" : "Crear Tasa", + "label.heading.rateappliesto" : "Tasa aplica a", + "label.anchor.editrate": "Editar Tasa", + "label.error.rate.already.exist" : "Tasa ya existe.", + "label.selectrate" : "Seleccione Tasa", "----End---": "---Fin del archivo---" } diff --git a/app/scripts/controllers/loanAccount/EditLoanAccAppController.js b/app/scripts/controllers/loanAccount/EditLoanAccAppController.js index 7c82f3fc..ea7afc6f 100755 --- a/app/scripts/controllers/loanAccount/EditLoanAccAppController.js +++ b/app/scripts/controllers/loanAccount/EditLoanAccAppController.js @@ -9,6 +9,7 @@ scope.collaterals = []; scope.restrictDate = new Date(); scope.date = {}; + scope.rateFlag = false; resourceFactory.loanResource.get({loanId: routeParams.id, template: true, associations: 'charges,collateral,meeting,multiDisburseDetails',staffInSelectedOfficeOnly:true}, function (data) { scope.loanaccountinfo = data; @@ -51,6 +52,7 @@ } scope.previewClientLoanAccInfo(); + scope.ratesEnabled= scope.loanaccountinfo.isRatesEnabled; }); @@ -162,7 +164,66 @@ } scope.formData.interestRateDifferential = scope.loanaccountinfo.interestRateDifferential ; scope.formData.isFloatingInterestRate = scope.loanaccountinfo.isFloatingInterestRate ; - } + //Load Rates information + scope.formData.rates = scope.loanaccountinfo.rates; + scope.firstChange = false; + scope.rateOptions = scope.loanaccountinfo.product.rates.filter(function(rate){ + var exist = false; + scope.formData.rates.forEach(function(addedRate){ + if(rate.id === addedRate.id){ + exist = true; + } + }); + return !exist; + }); + if (scope.formData.rates && scope.formData.rates.length>0){ + scope.rateFlag=true; + }else{ + scope.rateFlag=false; + } + }; + + //Rate + scope.rateSelected = function(currentRate){ + if(currentRate && !scope.checkIfRateAlreadyExist(currentRate)){ + scope.rateFlag=true; + scope.formData.rates.push(currentRate); + scope.rateOptions.splice(scope.rateOptions.indexOf(currentRate),1); + scope.currentRate = ''; + currentRate = ''; + scope.calculateRates(); + } + }; + + scope.checkIfRateAlreadyExist = function(currentRate){ + var exist = false; + scope.formData.rates.forEach(function(rate){ + if(rate.id === currentRate.id){ + exist = true; + } + }); + return exist; + }; + + scope.calculateRates = function(){ + var total = 0; + scope.formData.rates.forEach(function(rate){ + total += rate.percentage; + }); + if (total===0){ + scope.rateFlag=false; + total=undefined; + } + scope.formData.interestRatePerPeriod = total; + + + }; + + scope.deleteRate = function (index){ + scope.rateOptions.push(scope.formData.rates[index]); + scope.formData.rates.splice(index,1); + scope.calculateRates(); + }; scope.addCharge = function () { if (scope.chargeFormData.chargeId) { diff --git a/app/scripts/controllers/loanAccount/NewLoanAccAppController.js b/app/scripts/controllers/loanAccount/NewLoanAccAppController.js index d4dd9c23..b9c78799 100755 --- a/app/scripts/controllers/loanAccount/NewLoanAccAppController.js +++ b/app/scripts/controllers/loanAccount/NewLoanAccAppController.js @@ -1,6 +1,6 @@ (function (module) { mifosX.controllers = _.extend(module, { - NewLoanAccAppController: function (scope, routeParams, resourceFactory, location, dateFilter, uiConfigService, WizardHandler) { + NewLoanAccAppController: function (scope, routeParams, resourceFactory, location, dateFilter, uiConfigService, WizardHandler, translate) { scope.previewRepayment = false; scope.clientId = routeParams.clientId; scope.groupId = routeParams.groupId; @@ -22,6 +22,8 @@ scope.customSteps = []; scope.tempDataTables = []; scope.disabled = true; + scope.translate= translate; + scope.rateFlag=false; scope.date.first = new Date(); @@ -50,6 +52,7 @@ resourceFactory.loanResource.get(scope.inparams, function (data) { scope.products = data.productOptions; + scope.ratesEnabled = data.isRatesEnabled; if (data.clientName) { scope.clientName = data.clientName; @@ -181,9 +184,58 @@ scope.loandetails = angular.copy(scope.formData); scope.loandetails.productName = scope.formValue(scope.products,scope.formData.productId,'id','name'); + scope.formData.rates = scope.loanaccountinfo.product.rates; + if (scope.formData.rates && scope.formData.rates.length>0){ + scope.rateFlag=true; + } + scope.rateOptions = []; }; - scope.$watch('formData',function(newVal){ + //Rate + scope.rateSelected = function(currentRate){ + + if(currentRate && !scope.checkIfRateAlreadyExist(currentRate)){ + scope.rateFlag=true; + scope.formData.rates.push(currentRate); + scope.rateOptions.splice(scope.rateOptions.indexOf(currentRate),1); + scope.currentRate = ''; + currentRate = ''; + scope.calculateRates(); + } + }; + + scope.checkIfRateAlreadyExist = function(currentRate){ + var exist = false; + scope.formData.rates.forEach(function(rate){ + if(rate.id === currentRate.id){ + exist = true; + } + }); + + return exist + }; + + scope.calculateRates = function(){ + var total = 0; + scope.formData.rates.forEach(function(rate){ + total += rate.percentage; + }); + if (total===0){ + total=undefined; + scope.rateFlag=false; + } + scope.formData.interestRatePerPeriod = total; + + + }; + + scope.deleteRate = function (index){ + scope.rateOptions.push(scope.formData.rates[index]); + scope.formData.rates.splice(index,1); + scope.calculateRates(); + }; + + scope.$watch('formData',function(newVal){ scope.loandetails = angular.extend(scope.loandetails,newVal); },true); @@ -416,7 +468,7 @@ } } }); - mifosX.ng.application.controller('NewLoanAccAppController', ['$scope', '$routeParams', 'ResourceFactory', '$location', 'dateFilter', 'UIConfigService', 'WizardHandler', mifosX.controllers.NewLoanAccAppController]).run(function ($log) { + mifosX.ng.application.controller('NewLoanAccAppController', ['$scope', '$routeParams', 'ResourceFactory', '$location', 'dateFilter', 'UIConfigService', 'WizardHandler', '$translate',mifosX.controllers.NewLoanAccAppController]).run(function ($log) { $log.info("NewLoanAccAppController initialized"); }); }(mifosX.controllers || {})); diff --git a/app/scripts/controllers/loanAccount/ViewLoanDetailsController.js b/app/scripts/controllers/loanAccount/ViewLoanDetailsController.js index 02146dbf..065a9c31 100755 --- a/app/scripts/controllers/loanAccount/ViewLoanDetailsController.js +++ b/app/scripts/controllers/loanAccount/ViewLoanDetailsController.js @@ -12,6 +12,7 @@ scope.loandetails = []; scope.routeTo = function (loanId, transactionId, transactionTypeId) { if (transactionTypeId == 2 || transactionTypeId == 4 || transactionTypeId == 1) { + $rootScope.rates = scope.loandetails.rates; location.path('/viewloantrxn/' + loanId + '/trxnId/' + transactionId); }; }; diff --git a/app/scripts/controllers/loanAccount/ViewLoanTransactionController.js b/app/scripts/controllers/loanAccount/ViewLoanTransactionController.js index edbef148..fb6456ec 100644 --- a/app/scripts/controllers/loanAccount/ViewLoanTransactionController.js +++ b/app/scripts/controllers/loanAccount/ViewLoanTransactionController.js @@ -1,12 +1,39 @@ (function (module) { mifosX.controllers = _.extend(module, { - ViewLoanTransactionController: function (scope, resourceFactory, location, routeParams, dateFilter, $uibModal) { + ViewLoanTransactionController: function (scope, resourceFactory, location, routeParams, dateFilter, $uibModal, $rootScope) { + scope.details = []; + //Get loan rates to be defined in transaction details + scope.rates = $rootScope.rates; + //Obtain total rate percentage + scope.totalRatePercentage = 0; + if (scope.rates){ + scope.rates.forEach(function (rate) { + scope.totalRatePercentage += (rate.percentage/100); + }); + } + //get Tax from configuration + scope.tax = 0; + resourceFactory.configurationResource.get(function (data) { + for (var i in data.globalConfiguration) { + if('vat-tax' === data.globalConfiguration[i].name){ + scope.tax = (data.globalConfiguration[i].value/100); + break; + } + } + for (var i in data.globalConfiguration) { + if('sub-rates' === data.globalConfiguration[i].name){ + scope.ratesEnabled = (data.globalConfiguration[i].value); + break; + } + } + }); resourceFactory.loanTrxnsResource.get({loanId: routeParams.accountId, transactionId: routeParams.id}, function (data) { scope.transaction = data; scope.transaction.accountId = routeParams.accountId; + scope.generateDetailTable(); }); - + scope.undo = function (accountId, transactionId) { $uibModal.open({ templateUrl: 'undotransaction.html', @@ -36,10 +63,118 @@ $uibModalInstance.dismiss('cancel'); }; }; + scope.generateDetailTable = function () { + //add principal amount + var principalDetail = { + description: 'label.view.principalpaymentdetail', + containsAmount: true, + boldTitle: true, + align: 'left', + amount: scope.transaction.principalPortion.toFixed(3) + }; + scope.details.push(principalDetail); + //Check for interest details + var rateHeader = { + description: 'label.view.interestspayment', + containsAmount: scope.rates? false : true, + boldTitle: true, + amount: scope.rates? undefined : scope.transaction.interestPortion.toFixed(3) + }; + scope.details.push(rateHeader); + if (scope.ratesEnabled && scope.rates) { + scope.rates.forEach(function (rate) { + var rateDetail = { + description: rate.name, + containsAmount: true, + boldTitle: false, + amount: (((scope.transaction.interestPortion * (rate.percentage / 100)) / (scope.totalRatePercentage)) + / (1 + (scope.tax ? scope.tax : 0))).toFixed(3) + }; + scope.details.push(rateDetail); + if (scope.tax) { + var rateTaxDetail = { + description: 'IVA', + containsAmount: true, + boldTitle: false, + amount: (rateDetail.amount * scope.tax).toFixed(3) + }; + scope.details.push(rateTaxDetail); + } + }); + //Set total amount for rates + var totalRateDetail = { + description: 'label.view.interestspaymentTotal', + containsAmount: true, + boldTitle: true, + isTotal: true, + align: 'right', + amount: scope.transaction.interestPortion.toFixed(3) + }; + scope.details.push(totalRateDetail); + } + //Calculate total amount por charges + scope.availableCharges = {}; + if (scope.transaction.loanChargePaidByList) { + scope.transaction.loanChargePaidByList.forEach(function (data) { + var chargePaidBy = { + id: data['id'], + amount: data['amount'], + type: data['name'] + }; + if (scope.availableCharges.hasOwnProperty(chargePaidBy.type)) { + scope.availableCharges[chargePaidBy.type] = (scope.availableCharges[chargePaidBy.type] + + chargePaidBy.amount); + } else { + scope.availableCharges[chargePaidBy.type] = chargePaidBy.amount; + } + }); + } + + //Add charge header + if (Object.keys(scope.availableCharges).length >= 1) { + var chargeHeaderDetail = { + description: 'label.input.charges', + containsAmount: false, + boldTitle: true + }; + scope.details.push(chargeHeaderDetail); + } + + for (var key in scope.availableCharges) { + var chargeDetail = { + description: key, + containsAmount: true, + boldTitle: false, + amount: (scope.availableCharges[key].toFixed(3) / (1 + + scope.tax ? scope.tax :0)).toFixed(3) + }; + scope.details.push(chargeDetail); + if (scope.tax) { + var chargeTaxDetail = { + description: 'IVA', + containsAmount: true, + boldTitle: false, + amount: (chargeDetail.amount * scope.tax).toFixed(3) + }; + scope.details.push(chargeTaxDetail); + } + } + + if (Object.keys(scope.availableCharges).length >= 1) { + var chargeTotalDetail = { + description: 'Total', + containsAmount: true, + boldTitle: true, + align: 'right', + amount: scope.transaction.penaltyChargesPortion.toFixed(3) + }; + scope.details.push(chargeTotalDetail); + } + }; } }); - mifosX.ng.application.controller('ViewLoanTransactionController', ['$scope', 'ResourceFactory', '$location', '$routeParams', 'dateFilter', '$uibModal', mifosX.controllers.ViewLoanTransactionController]).run(function ($log) { + mifosX.ng.application.controller('ViewLoanTransactionController', ['$scope', 'ResourceFactory', '$location', '$routeParams', 'dateFilter', '$uibModal', '$rootScope', mifosX.controllers.ViewLoanTransactionController]).run(function ($log) { $log.info("ViewLoanTransactionController initialized"); }); }(mifosX.controllers || {})); diff --git a/app/scripts/controllers/product/CreateLoanProductController.js b/app/scripts/controllers/product/CreateLoanProductController.js index 74c32bae..46041ad1 100755 --- a/app/scripts/controllers/product/CreateLoanProductController.js +++ b/app/scripts/controllers/product/CreateLoanProductController.js @@ -1,6 +1,6 @@ (function (module) { mifosX.controllers = _.extend(module, { - CreateLoanProductController: function (scope, $rootScope, resourceFactory, location, dateFilter,WizardHandler) { + CreateLoanProductController: function (scope, $rootScope, resourceFactory, location, dateFilter,WizardHandler, translate) { scope.restrictDate = new Date(); scope.formData = {}; scope.loanproduct = {}; @@ -32,6 +32,10 @@ scope.transactionProcessingStrategy = true; scope.allowAttributeConfiguration = true; scope.interestRecalculationOnDayTypeOptions = []; + scope.translate = translate; + //Rates + scope.rates = []; + scope.rateFlag = false; for (var i = 1; i <= 28; i++) { scope.interestRecalculationOnDayTypeOptions.push(i); } @@ -82,6 +86,10 @@ scope.product.interestRecalculationNthDayTypeOptions.push({"code" : "onDay", "id" : -2, "value" : "on day"}); scope.loanproduct = angular.copy(scope.formData); scope.isClicked = false; + + //Rate Module + scope.rateOptions = scope.product.rateOptions || []; + scope.enableRates = scope.product.isRatesEnabled; }); scope.$watch('formData',function(newVal){ @@ -121,7 +129,50 @@ } }; - scope.deleteCharge = function (index) { + //Rate + scope.rateSelected = function (currentRate) { + + if (currentRate) { + scope.rateFlag = true; + scope.rates.push(currentRate); + scope.rateOptions.splice(scope.rateOptions.indexOf(currentRate), 1); + scope.currentRate = ''; + scope.calculateRates(); + } + }; + + scope.calculateRates = function () { + var total = 0; + var minRate = 0; + scope.rates.forEach(function (rate) { + if (rate.percentage < minRate || minRate === 0) { + minRate = rate.percentage; + } + total += rate.percentage; + }); + + if (minRate === 0) { + minRate = undefined; + } + if (total === 0) { + total = undefined; + scope.rateFlag = false; + } + + scope.formData.minInterestRatePerPeriod = minRate; + //Assign the same total range to this values. + scope.formData.interestRatePerPeriod = total; + scope.formData.maxInterestRatePerPeriod = total; + scope.calculatedRatePerPeriod = total; + }; + + scope.deleteRate = function (index) { + scope.rateOptions.push(scope.rates[index]); + scope.rates.splice(index, 1); + scope.calculateRates(); + }; + + scope.deleteCharge = function (index) { scope.charges.splice(index, 1); }; @@ -325,6 +376,7 @@ this.formData.dateFormat = scope.df; this.formData.startDate = reqFirstDate; this.formData.closeDate = reqSecondDate; + this.formData.rates = scope.rates; //Interest recalculation data if (this.formData.isInterestRecalculationEnabled) { @@ -392,7 +444,7 @@ }; } }); - mifosX.ng.application.controller('CreateLoanProductController', ['$scope','$rootScope', 'ResourceFactory', '$location', 'dateFilter','WizardHandler', mifosX.controllers.CreateLoanProductController]).run(function ($log) { + mifosX.ng.application.controller('CreateLoanProductController', ['$scope','$rootScope', 'ResourceFactory', '$location', 'dateFilter','WizardHandler', '$translate', mifosX.controllers.CreateLoanProductController]).run(function ($log) { $log.info("CreateLoanProductController initialized"); }); }(mifosX.controllers || {})); diff --git a/app/scripts/controllers/product/CreateRateController.js b/app/scripts/controllers/product/CreateRateController.js new file mode 100644 index 00000000..77637f13 --- /dev/null +++ b/app/scripts/controllers/product/CreateRateController.js @@ -0,0 +1,37 @@ +/** + * Created by Jose on 24/07/2017. + */ +(function (module) { + mifosX.controllers = _.extend(module, { + CreateRateController: function (scope, resourceFactory, location, dateFilter, translate, webStorage) { + scope.template = []; + scope.formData = {}; + scope.first = {}; + scope.rateError = false; + scope.translate = translate; + //Right now only loan is accepted for a rate. + scope.rateOptions = [{id : "m_loan"}]; + scope.setChoice = function () { + if (this.formData.active) { + scope.choice = 1; + } + else if (!this.formData.active) { + scope.choice = 0; + } + }; + + scope.submit = function () { + this.formData.locale = scope.optlang.code; + resourceFactory.rateResource.save(this.formData, function (data) { + location.path('/rates/'); + },function(error){ + scope.rateError = true; + + }); + }; + } + }); + mifosX.ng.application.controller('CreateRateController', ['$scope', 'ResourceFactory', '$location', 'dateFilter', '$translate','webStorage', mifosX.controllers.CreateRateController]).run(function ($log) { + $log.info("CreateRateController initialized"); + }); +}(mifosX.controllers || {})); diff --git a/app/scripts/controllers/product/EditLoanProductController.js b/app/scripts/controllers/product/EditLoanProductController.js index 901ef5bf..84308f8d 100755 --- a/app/scripts/controllers/product/EditLoanProductController.js +++ b/app/scripts/controllers/product/EditLoanProductController.js @@ -1,6 +1,6 @@ (function (module) { mifosX.controllers = _.extend(module, { - EditLoanProductController: function (scope, resourceFactory, location, routeParams, dateFilter) { + EditLoanProductController: function (scope, resourceFactory, location, routeParams, dateFilter, translate) { scope.formData = {}; scope.restrictDate = new Date(); scope.charges = []; @@ -15,12 +15,17 @@ scope.pvFlag = false; scope.rvFlag = false; scope.interestRecalculationOnDayTypeOptions = []; + scope.translate = translate; + //Rates + scope.rates = []; + scope.rateFlag = false; for (var i = 1; i <= 28; i++) { scope.interestRecalculationOnDayTypeOptions.push(i); } resourceFactory.loanProductResource.get({loanProductId: routeParams.id, template: 'true'}, function (data) { scope.product = data; + scope.ratesEnabled = data.ratesEnabled; scope.assetAccountOptions = scope.product.accountingMappingOptions.assetAccountOptions || []; scope.incomeAccountOptions = scope.product.accountingMappingOptions.incomeAccountOptions || []; scope.expenseAccountOptions = scope.product.accountingMappingOptions.expenseAccountOptions || []; @@ -241,8 +246,73 @@ scope.formData.minimumGap = scope.product.minimumGap; scope.formData.maximumGap = scope.product.maximumGap; scope.formData.canUseForTopup = scope.product.canUseForTopup; + + //Rate Module + scope.formData.rates = scope.product.rates; + scope.rateOptions = scope.product.rateOptions || []; + scope.calculatedRatePerPeriod = scope.product.interestRatePerPeriod; + scope.enableRates = scope.product.isRatesEnabled; + + if (scope.enableRates){ + if (scope.formData.rates && scope.formData.rates.length>0){ + scope.rateFlag=true; + } + scope.formData.rates.forEach(function(rate){ + scope.rateOptions.forEach(function(rateOption, index, array){ + if(rate.name === rateOption.name){ + scope.rateOptions.splice(index,1); + } + }); + }); + } }); + //Rate + scope.rateSelected = function(currentRate){ + + if(currentRate){ + scope.formData.rates.push(currentRate); + scope.rateOptions.splice(scope.rateOptions.indexOf(currentRate),1); + scope.currentRate = ''; + scope.calculateRates(); + } + }; + + scope.calculateRates = function(){ + var total = 0; + var minRate = 0; + scope.formData.rates.forEach(function(rate){ + if(rate.percentage < minRate || minRate === 0){ + minRate = rate.percentage; + } + total += rate.percentage; + }); + + if (minRate===0){ + minRate=undefined; + } + if (total===0){ + total=undefined; + scope.rateFlag=false; + } + scope.formData.minInterestRatePerPeriod = minRate; + + //Assign the same total range to this values. + scope.formData.interestRatePerPeriod = total; + scope.formData.maxInterestRatePerPeriod = total; + scope.calculatedRatePerPeriod = total; + + console.log(scope.formData); + + }; + + scope.deleteRate = function (index){ + scope.rateOptions.push(scope.formData.rates[index]); + scope.formData.rates.splice(index,1); + scope.calculateRates(); + }; + + scope.chargeSelected = function (chargeId) { if(chargeId){ resourceFactory.chargeResource.get({chargeId: chargeId, template: 'true'}, this.formData, function (data) { @@ -526,7 +596,7 @@ } } }); - mifosX.ng.application.controller('EditLoanProductController', ['$scope', 'ResourceFactory', '$location', '$routeParams', 'dateFilter', mifosX.controllers.EditLoanProductController]).run(function ($log) { + mifosX.ng.application.controller('EditLoanProductController', ['$scope', 'ResourceFactory', '$location', '$routeParams', 'dateFilter', '$translate', mifosX.controllers.EditLoanProductController]).run(function ($log) { $log.info("EditLoanProductController initialized"); }); }(mifosX.controllers || {})); diff --git a/app/scripts/controllers/product/EditRateController.js b/app/scripts/controllers/product/EditRateController.js new file mode 100644 index 00000000..7e171879 --- /dev/null +++ b/app/scripts/controllers/product/EditRateController.js @@ -0,0 +1,42 @@ +/** + * Created by Jose on 25/07/2017. + */ +(function (module) { + mifosX.controllers = _.extend(module, { + EditRateController: function (scope, resourceFactory, location, routeParams, dateFilter) { + scope.template = []; + scope.showdatefield = false; + scope.repeatEvery = false; + scope.first = {}; + scope.flag = false; + scope.showPenalty = true ; + + + resourceFactory.rateResource.getRate({rateId: routeParams.rateId}, function (data) { + scope.template = data; + + scope.formData = { + id: data.id, + name: data.name, + active: data.active, + percentage: data.percentage, + productApply : data.productApply + }; + + + }); + + + scope.submit = function () { + this.formData.locale = scope.optlang.code; + this.formData.active = this.formData.active || false; + resourceFactory.rateResource.update({rateId: routeParams.rateId}, this.formData, function (data) { + location.path('/viewrate/' + routeParams.rateId); + }); + }; + } + }); + mifosX.ng.application.controller('EditRateController', ['$scope', 'ResourceFactory', '$location', '$routeParams', 'dateFilter', mifosX.controllers.EditRateController]).run(function ($log) { + $log.info("EditRateController initialized"); + }); +}(mifosX.controllers || {})); diff --git a/app/scripts/controllers/product/RateController.js b/app/scripts/controllers/product/RateController.js new file mode 100644 index 00000000..799a9965 --- /dev/null +++ b/app/scripts/controllers/product/RateController.js @@ -0,0 +1,33 @@ +/** + * Created by Jose on 24/07/2017. + */ +(function (module) { + mifosX.controllers = _.extend(module, { + RateController: function (scope, resourceFactory, location) { + scope.rates = []; + + scope.routeTo = function (id) { + location.path('/viewrate/' + id); + }; + + if (!scope.searchCriteria.rates) { + scope.searchCriteria.rates = null; + scope.saveSC(); + } + scope.filterText = scope.searchCriteria.rates || ''; + + scope.onFilter = function () { + scope.searchCriteria.rates = scope.filterText; + scope.saveSC(); + }; + + scope.RatesPerPage = 15; + resourceFactory.rateResource.getAllRates(function (data) { + scope.rates = data; + }); + } + }); + mifosX.ng.application.controller('RateController', ['$scope', 'ResourceFactory', '$location', mifosX.controllers.RateController]).run(function ($log) { + $log.info("RateController initialized"); + }); +}(mifosX.controllers || {})); \ No newline at end of file diff --git a/app/scripts/controllers/product/ViewLoanProductController.js b/app/scripts/controllers/product/ViewLoanProductController.js index c66c77fc..c6360ae5 100755 --- a/app/scripts/controllers/product/ViewLoanProductController.js +++ b/app/scripts/controllers/product/ViewLoanProductController.js @@ -32,7 +32,7 @@ else{ scope.allowAttributeConfiguration = false; } - + scope.enableRates = scope.loanproduct.isRatesEnabled; }); scope.scrollto = function (link) { diff --git a/app/scripts/controllers/product/ViewRateController.js b/app/scripts/controllers/product/ViewRateController.js new file mode 100644 index 00000000..413882eb --- /dev/null +++ b/app/scripts/controllers/product/ViewRateController.js @@ -0,0 +1,19 @@ +/** + * Created by Jose on 25/07/2017. + */ +(function (module) { + mifosX.controllers = _.extend(module, { + ViewRateController: function (scope, routeParams, resourceFactory, location, $uibModal) { + scope.rate = []; + scope.choice = 0; + resourceFactory.rateResource.getRate({rateId: routeParams.rateId}, function (data) { + scope.rate = data; + }); + + + } + }); + mifosX.ng.application.controller('ViewRateController', ['$scope', '$routeParams', 'ResourceFactory', '$location', '$uibModal', mifosX.controllers.ViewRateController]).run(function ($log) { + $log.info("ViewRateController initialized"); + }); +}(mifosX.controllers || {})); diff --git a/app/scripts/mifosXComponents.js b/app/scripts/mifosXComponents.js index 695e1c44..70cba0fc 100755 --- a/app/scripts/mifosXComponents.js +++ b/app/scripts/mifosXComponents.js @@ -327,7 +327,11 @@ define(['Q', 'underscore', 'mifosX'], function (Q) { 'adhocquery/AdHocQueryListController', 'adhocquery/CreateAdHocQueryController', 'adhocquery/ViewAdHocQueryController', - 'adhocquery/EditAdHocQueryController' + 'adhocquery/EditAdHocQueryController', + 'product/RateController', + 'product/CreateRateController', + 'product/ViewRateController', + 'product/EditRateController' ], filters: [ 'StatusLookup', diff --git a/app/scripts/routes.js b/app/scripts/routes.js index 0067d379..883cc5c1 100755 --- a/app/scripts/routes.js +++ b/app/scripts/routes.js @@ -1019,6 +1019,18 @@ .when('/externalservicesCB/CreditBureau/mapcblp', { templateUrl: 'views/administration/MapCreditBureauToLP.html' }) + .when('/rates', { + templateUrl: 'views/products/rates.html' + }) + .when('/createrate', { + templateUrl: 'views/products/createrate.html' + }) + .when('/viewrate/:rateId', { + templateUrl: 'views/products/viewrate.html' + }) + .when('/editrate/:rateId', { + templateUrl: 'views/products/editrate.html' + }) .otherwise({ templateUrl: "views/errors/404.html" }); diff --git a/app/scripts/services/ResourceFactoryProvider.js b/app/scripts/services/ResourceFactoryProvider.js index d66cc180..a7e58cef 100755 --- a/app/scripts/services/ResourceFactoryProvider.js +++ b/app/scripts/services/ResourceFactoryProvider.js @@ -735,6 +735,12 @@ twoFactorConfigResource: defineResource(apiVer+"/twofactor/configure", {}, { getAllConfigs: {method: 'GET', params: {}}, put: {method: 'PUT', params: {}} + }), + rateResource: defineResource(apiVer + "/rates/:rateId", {rateId: '@rateId'}, { + getAllRates: {method: 'GET', params: {}, isArray: true}, + getRate: {method: 'GET', params: {}}, + update: {method: 'PUT', params: {}}, + save: {method: 'POST', params: {}} }) }; }]; diff --git a/app/views/loans/editloanaccount.html b/app/views/loans/editloanaccount.html index 4d5cce0e..4af1c78e 100755 --- a/app/views/loans/editloanaccount.html +++ b/app/views/loans/editloanaccount.html @@ -198,7 +198,7 @@ class="required">*   {{loanaccountinfo.interestRateFrequencyType.value}} + ng-model="formData.interestRatePerPeriod" ng-disabled="rateFlag"/>  {{loanaccountinfo.interestRateFrequencyType.value}} @@ -441,6 +441,42 @@
+ +
+

{{ 'label.heading.rates' | translate }}

+
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + +
{{'label.heading.name' | translate}}{{'label.heading.percentage' | translate}}{{'label.heading.actions' | translate}}
{{rate.name}}{{rate.percentage| number}}
+
+ +
  {{loanaccountinfo.interestRateFrequencyType.value}} @@ -569,6 +569,44 @@
+ + +
+
+

{{ 'label.heading.rates' | translate }}

+
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + +
{{'label.heading.name' | translate}}{{'label.heading.percentage' | translate}}{{'label.heading.actions' | translate}}
{{rate.name}}{{rate.percentage | number}}
+
+ +

+ + + + + + + diff --git a/app/views/products/editloanproduct.html b/app/views/products/editloanproduct.html index 1be187e8..3b09bec8 100755 --- a/app/views/products/editloanproduct.html +++ b/app/views/products/editloanproduct.html @@ -331,21 +331,76 @@
+ + +
+
+ +
+ +
+
+ + + +
+
+ +
+
+
+ + + + + + + + + + + + + + +
{{'label.heading.name' | translate}}{{'label.heading.percentage' | translate}}{{'label.heading.actions' | translate}}
{{rate.name}}{{rate.percentage|number}}
+
+ + +
+ class="form-control" number-format ng-model="formData.minInterestRatePerPeriod" ng-disabled="enableRates&&rateFlag">
+ number-format late-validate ng-disabled="enableRates&&rateFlag"/>
+ number-format class="form-control" ng-model="formData.maxInterestRatePerPeriod" ng-disabled="enableRates&&rateFlag">
+
+
+
+
+ + +
+ +
+
+
+ + +
+ + + +
+
+ +
+ + +
+ +
+
+ +
+ {{'label.button.cancel' | translate}} + +
+ + + diff --git a/app/views/products/products.html b/app/views/products/products.html index 4595bfa8..8a48ecdb 100644 --- a/app/views/products/products.html +++ b/app/views/products/products.html @@ -33,6 +33,12 @@

{{'label.definecharges' | translate}}

+ + +

  {{ + 'label.anchor.rates' | translate }}

+

{{'label.rates' | translate}}

+
diff --git a/app/views/products/rates.html b/app/views/products/rates.html new file mode 100644 index 00000000..6637c9c9 --- /dev/null +++ b/app/views/products/rates.html @@ -0,0 +1,40 @@ + +
+ + +
+ +
+ + + + + + + + + + + + + + + + +
{{'label.heading.name' | translate}}{{'label.heading.chargeappliesto' | translate}}{{'label.heading.active' | translate}}
{{rate.name}}{{rate.productApply | translate }}{{rate.active | YesOrNo | translate}} +
+ +
+
\ No newline at end of file diff --git a/app/views/products/viewrate.html b/app/views/products/viewrate.html new file mode 100644 index 00000000..ce8d86d6 --- /dev/null +++ b/app/views/products/viewrate.html @@ -0,0 +1,35 @@ +
+ +
+

{{rate.name}} + +

+
+
+
+ + + + + + + + + + + + + + +
{{'label.heading.percentage' | translate}}{{rate.percentage | number}}
{{'label.heading.active' | translate}}{{rate.active | YesOrNo | translate}}
{{'label.heading.rateappliesto' | translate}}{{rate.productApply | translate}}
+
+
+
+
\ No newline at end of file