diff --git a/mifosng-db/migrations/core_db/V17__update_stretchy_reporting_ddl.sql b/mifosng-db/migrations/core_db/V17__update_stretchy_reporting_ddl.sql new file mode 100644 index 000000000..6a244b249 --- /dev/null +++ b/mifosng-db/migrations/core_db/V17__update_stretchy_reporting_ddl.sql @@ -0,0 +1,90 @@ +/* +Reason for all the tmp tables and renames is had mysql problems with foreign keys doing alter table commands +*/ + +CREATE TABLE `stretchy_report_tmp` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_name` varchar(100) NOT NULL, + `report_type` varchar(20) NOT NULL, + `report_subtype` varchar(20) DEFAULT NULL, + `report_category` varchar(45) DEFAULT NULL, + `report_sql` text, + `description` text, + `core_report` tinyint(1) DEFAULT '0', + `use_report` tinyint(1) DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `report_name_UNIQUE` (`report_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into stretchy_report_tmp +(id, report_name, report_type, report_subtype, report_category, +report_sql, description, core_report, use_report) +select report_id, report_name, report_type, report_subtype, report_category, +report_sql, description, core_report, use_report +from stretchy_report; + +CREATE TABLE `stretchy_parameter_tmp` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `parameter_name` varchar(45) NOT NULL, + `parameter_variable` varchar(45) DEFAULT NULL, + `parameter_label` varchar(45) NOT NULL, + `parameter_displayType` varchar(45) NOT NULL, + `parameter_FormatType` varchar(10) NOT NULL, + `parameter_default` varchar(45) NOT NULL, + `special` varchar(1) DEFAULT NULL, + `selectOne` varchar(1) DEFAULT NULL, + `selectAll` varchar(1) DEFAULT NULL, + `parameter_sql` text, + `parent_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`parameter_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into stretchy_parameter_tmp +(id, parameter_name, parameter_variable, parameter_label, parameter_displayType, parameter_FormatType, +parameter_default, special, selectOne, selectAll, parameter_sql, parent_id) +select parameter_id, parameter_name, parameter_variable, parameter_label, parameter_displayType, parameter_FormatType, +parameter_default, special, selectOne, selectAll, parameter_sql, parent_parameter_id +from stretchy_parameter; + +CREATE TABLE `stretchy_report_parameter_tmp` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_id` int(11) NOT NULL, + `parameter_id` int(11) NOT NULL, + `report_parameter_name` varchar(45) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `report_id_name_UNIQUE` (`report_id`,`report_parameter_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +insert into stretchy_report_parameter_tmp(report_id, parameter_id, report_parameter_name) +select report_id, parameter_id, report_parameter_name +from stretchy_report_parameter; + + +ALTER TABLE `stretchy_parameter_tmp` + ADD CONSTRAINT `fk_stretchy_parameter_001` + FOREIGN KEY (`parent_id` ) + REFERENCES `stretchy_parameter_tmp` (`id` ) + ON DELETE RESTRICT ON UPDATE RESTRICT, + ADD INDEX `fk_stretchy_parameter_001_idx` (`parent_id` ASC); + + +ALTER TABLE `stretchy_report_parameter_tmp` + ADD CONSTRAINT `fk_report_parameter_001` FOREIGN KEY (`report_id` ) + REFERENCES `stretchy_report_tmp` (`id` ) ON DELETE CASCADE ON UPDATE RESTRICT, + + ADD CONSTRAINT `fk_report_parameter_002` FOREIGN KEY (`parameter_id` ) + REFERENCES `stretchy_parameter_tmp` (`id` ) ON DELETE RESTRICT ON UPDATE RESTRICT, + + ADD INDEX `fk_report_parameter_001_idx` (`report_id` ASC), + ADD INDEX `fk_report_parameter_002_idx` (`parameter_id` ASC) ; + + +drop table stretchy_report_parameter; +drop table stretchy_report; +drop table stretchy_parameter; + +rename table +stretchy_report_tmp to stretchy_report, +stretchy_parameter_tmp to stretchy_parameter, +stretchy_report_parameter_tmp to stretchy_report_parameter; \ No newline at end of file diff --git a/mifosng-db/migrations/core_db/V18__update_stretchy_reporting_reportSql.sql b/mifosng-db/migrations/core_db/V18__update_stretchy_reporting_reportSql.sql new file mode 100644 index 000000000..b0dcad307 --- /dev/null +++ b/mifosng-db/migrations/core_db/V18__update_stretchy_reporting_reportSql.sql @@ -0,0 +1,7 @@ + +UPDATE `stretchy_parameter` SET `parameter_sql`='select sp.parameter_name, sp.parameter_variable, sp.parameter_label, sp.parameter_displayType, \r sp.parameter_FormatType, sp.parameter_default, sp.selectOne, sp.selectAll, spp.parameter_name as parentParameterName\r from stretchy_parameter sp\r left join stretchy_parameter spp on spp.id = sp.parent_id\r where sp.special is null\r and exists \r (select \'f\' \r from stretchy_report sr\r join stretchy_report_parameter srp on srp.report_id = sr.id\r where sr.report_name in(${reportListing})\r and srp.parameter_id = sp.id\r )\r order by sp.id' WHERE `id`='1002'; + +UPDATE `stretchy_parameter` SET `parameter_sql`='select r.id as report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,\nrp.id as parameter_id, rp.report_parameter_name, p.parameter_name\n from stretchy_report r\n left join stretchy_report_parameter rp on rp.report_id = r.id \n left join stretchy_parameter p on p.id = rp.parameter_id\n where r.use_report is true\n and exists\n ( select \'f\'\n from m_appuser_role ur \n join m_role r on r.id = ur.role_id\n join m_role_permission rp on rp.role_id = r.id\n join m_permission p on p.id = rp.permission_id\n where ur.appuser_id = ${currentUserId}\n and (p.code in (\'ALL_FUNCTIONS_READ\', \'ALL_FUNCTIONS\') or p.code = concat(\"READ_\", r.report_name)) )\n order by r.report_category, r.report_name, rp.id' WHERE `id`='1001'; + +UPDATE `stretchy_parameter` SET `parameter_sql`='select r.id as report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,\n rp.id as parameter_id, rp.report_parameter_name, p.parameter_name\n from stretchy_report r\n left join stretchy_report_parameter rp on rp.report_id = r.id\n left join stretchy_parameter p on p.id = rp.parameter_id\n where r.report_category = \'${reportCategory}\'\n and r.use_report is true\n and exists\n (select \'f\'\n from m_appuser_role ur \n join m_role r on r.id = ur.role_id\n join m_role_permission rp on rp.role_id = r.id\n join m_permission p on p.id = rp.permission_id\n where ur.appuser_id = ${currentUserId}\n and (p.code in (\'ALL_FUNCTIONS_READ\', \'ALL_FUNCTIONS\') or p.code = concat(\"READ_\", r.report_name)) )\n order by r.report_category, r.report_name, rp.id' WHERE `id`='1003'; + diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/domain/Report.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/domain/Report.java new file mode 100644 index 000000000..008a2cd3d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/domain/Report.java @@ -0,0 +1,286 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.dataqueries.domain; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.organisation.monetary.domain.Money; +import org.mifosplatform.portfolio.charge.domain.Charge; +import org.mifosplatform.portfolio.fund.domain.Fund; +import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator; +import org.springframework.data.jpa.domain.AbstractPersistable; + +import com.google.gson.JsonArray; +/* +@Entity +@Table(name = "stretchy_report", uniqueConstraints = { @UniqueConstraint(columnNames = { "report_name" }, name = "unq_report_name") }) +public class Report extends AbstractPersistable { + +@Column(name = "report_name", nullable = false, unique = true) +private String reportName; + +@Column(name = "report_type", nullable = false) +private String reportType; + +@Column(name = "report_subtype") +private String reportSubType; + +@Column(name = "report_category") +private String reportCategory; + +@Column(name = "description") +private String description; + +@Column(name = "core_report", nullable = false) +private boolean core_Report; + +//only defines if report should appear in reference app UI List +@Column(name = "use_report", nullable = false) +private boolean useReport; + +@Column(name = "report_sql") +private String reportSql; + + + @ManyToMany + @JoinTable(name = "stretchy_report_parameter", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id")) + private List charges; + + + public static Report assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy, + final List productCharges, final JsonCommand command, final AprCalculator aprCalculator) { + + final String name = command.stringValueOfParameterNamed("name"); + final String description = command.stringValueOfParameterNamed("description"); + final String currencyCode = command.stringValueOfParameterNamed("currencyCode"); + final Integer digitsAfterDecimal = command.integerValueOfParameterNamed("digitsAfterDecimal"); + + final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal); + final BigDecimal principal = command.bigDecimalValueOfParameterNamed("principal"); + final BigDecimal minPrincipal = command.bigDecimalValueOfParameterNamed("minPrincipal"); + final BigDecimal maxPrincipal = command.bigDecimalValueOfParameterNamed("maxPrincipal"); + + final InterestMethod interestMethod = InterestMethod.fromInt(command.integerValueOfParameterNamed("interestType")); + final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command + .integerValueOfParameterNamed("interestCalculationPeriodType")); + final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.integerValueOfParameterNamed("amortizationType")); + final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.fromInt(command + .integerValueOfParameterNamed("repaymentFrequencyType")); + final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType.fromInt(command + .integerValueOfParameterNamed("interestRateFrequencyType")); + final BigDecimal interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod"); + final BigDecimal minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod"); + final BigDecimal maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod"); + final BigDecimal annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod); + + final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery"); + final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments"); + final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments"); + final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments"); + final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance"); + final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule")); + + return new Report(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal, + interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod, + repaymentEvery, repaymentFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, inArrearsTolerance, productCharges, + accountingRuleType); + } + + protected Report() { + this.loanProductRelatedDetail = null; + this.loanProductMinMaxConstraints = null; + } + + public Report(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name, + final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal, + final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal, + final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod, + final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType, + final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod, + final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery, + final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments, + final Integer defaultMinNumberOfInstallments, final Integer defaultMaxNumberOfInstallments, + final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List charges, + final AccountingRuleType accountingRuleType) { + this.fund = fund; + this.transactionProcessingStrategy = transactionProcessingStrategy; + this.name = name.trim(); + if (StringUtils.isNotBlank(description)) { + this.description = description.trim(); + } else { + this.description = null; + } + + if (charges != null) { + this.charges = charges; + } + + this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency, defaultPrincipal, defaultNominalInterestRatePerPeriod, + interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery, + repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance); + + this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal, + defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments, + defaultMaxNumberOfInstallments); + + if (accountingRuleType != null) { + this.accountingRule = accountingRuleType.getValue(); + } + } + + public MonetaryCurrency getCurrency() { + return this.loanProductRelatedDetail.getCurrency(); + } + + public boolean update(final List newProductCharges) { + boolean updated = false; + if (this.charges != null) { + final Set setOfCharges = new HashSet(this.charges); + + updated = setOfCharges.addAll(newProductCharges); + if (updated) { + this.charges = newProductCharges; + } + } + return updated; + } + + public Integer getAccountingType() { + return this.accountingRule; + } + + public Map update(final JsonCommand command, final AprCalculator aprCalculator) { + + final Map actualChanges = this.loanProductRelatedDetail.update(command, aprCalculator); + actualChanges.putAll(this.loanProductMinMaxConstraints().update(command)); + + final String accountingTypeParamName = "accountingRule"; + if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) { + final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName); + actualChanges.put(accountingTypeParamName, newValue); + this.accountingRule = newValue; + } + + final String nameParamName = "name"; + if (command.isChangeInStringParameterNamed(nameParamName, this.name)) { + final String newValue = command.stringValueOfParameterNamed(nameParamName); + actualChanges.put(nameParamName, newValue); + this.name = newValue; + } + + final String descriptionParamName = "description"; + if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) { + final String newValue = command.stringValueOfParameterNamed(descriptionParamName); + actualChanges.put(descriptionParamName, newValue); + this.description = newValue; + } + + Long existingFundId = null; + if (this.fund != null) { + existingFundId = this.fund.getId(); + } + final String fundIdParamName = "fundId"; + if (command.isChangeInLongParameterNamed(fundIdParamName, existingFundId)) { + final Long newValue = command.longValueOfParameterNamed(fundIdParamName); + actualChanges.put(fundIdParamName, newValue); + } + + Long existingStrategyId = null; + if (this.transactionProcessingStrategy != null) { + existingStrategyId = this.transactionProcessingStrategy.getId(); + } + final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId"; + if (command.isChangeInLongParameterNamed(transactionProcessingStrategyParamName, existingStrategyId)) { + final Long newValue = command.longValueOfParameterNamed(transactionProcessingStrategyParamName); + actualChanges.put(transactionProcessingStrategyParamName, newValue); + } + + final String chargesParamName = "charges"; + if (command.hasParameter(chargesParamName)) { + JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName); + if (jsonArray != null) { + + } + actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName)); + } + + return actualChanges; + } + + public boolean isCashBasedAccountingEnabled() { + return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule); + } + + public boolean isAccrualBasedAccountingEnabled() { + return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingRule); + } + + public Money getPrincipalAmount(){ + return this.loanProductRelatedDetail.getPrincipal(); + } + + public Money getMinPrincipalAmount(){ + return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMinPrincipal()); + } + + public Money getMaxPrincipalAmount(){ + return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMaxPrincipal()); + } + + public BigDecimal getNominalInterestRatePerPeriod() { + return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod(); + } + + public BigDecimal getMinNominalInterestRatePerPeriod() { + return this.loanProductMinMaxConstraints().getMinNominalInterestRatePerPeriod(); + } + + public BigDecimal getMaxNominalInterestRatePerPeriod(){ + return this.loanProductMinMaxConstraints().getMaxNominalInterestRatePerPeriod(); + } + + public Integer getNumberOfRepayments(){ + return this.loanProductRelatedDetail().getNumberOfRepayments(); + } + + public Integer getMinNumberOfRepayments() { + return this.loanProductMinMaxConstraints().getMinNumberOfRepayments(); + } + + public Integer getMaxNumberOfRepayments() { + return this.loanProductMinMaxConstraints().getMaxNumberOfRepayments(); + } + + public LoanProductRelatedDetail loanProductRelatedDetail(){ + return this.loanProductRelatedDetail; + } + + public LoanProductMinMaxConstraints loanProductMinMaxConstraints() { + //If all min and max fields are null then loanProductMinMaxConstraints initialising to null + //Reset LoanProductMinMaxConstraints with null values. + this.loanProductMinMaxConstraints = (this.loanProductMinMaxConstraints == null) ? new LoanProductMinMaxConstraints(null, null, null, null, null, null) + : this.loanProductMinMaxConstraints; + return loanProductMinMaxConstraints; + } +} +*/ \ No newline at end of file