diff --git a/mifosng-db/migrations/core_db/V92__group_center_assign_staff_permission.sql b/mifosng-db/migrations/core_db/V92__group_center_assign_staff_permission.sql index 2f8eaa718..d47106776 100644 --- a/mifosng-db/migrations/core_db/V92__group_center_assign_staff_permission.sql +++ b/mifosng-db/migrations/core_db/V92__group_center_assign_staff_permission.sql @@ -1,2 +1,2 @@ -INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker') -values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0) \ No newline at end of file +INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker`) +values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0); \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/domain/Staff.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/domain/Staff.java index bc07e68d3..d23c69a45 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/domain/Staff.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/domain/Staff.java @@ -22,7 +22,8 @@ import org.mifosplatform.organisation.office.domain.Office; import org.springframework.data.jpa.domain.AbstractPersistable; @Entity -@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") }) +@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") , +@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") }) public class Staff extends AbstractPersistable { @Column(name = "firstname", length = 50) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java index 6231b8454..167fc2c69 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java @@ -69,7 +69,7 @@ public class LoanProductsApiResource { "graceOnInterestPayment", "graceOnInterestCharged", "interestRatePerPeriod", "minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType", "interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", - "charges", "accountingRule", "accountingMappings", "paymentChannelToFundSourceMappings", "fundOptions", "paymentTypeOptions", + "charges", "accountingRule", "externalId", "accountingMappings", "paymentChannelToFundSourceMappings", "fundOptions", "paymentTypeOptions", "currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "transactionProcessingStrategyOptions", "chargeOptions", "accountingOptions", "accountingRuleOptions", "accountingMappingOptions")); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java index c1d28c0a5..57380472a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java @@ -42,6 +42,7 @@ public class LoanProductData { private final LocalDate startDate; private final LocalDate closeDate; private final String status; + private final String externalId; // terms private final CurrencyData currency; private final BigDecimal principal; @@ -135,12 +136,13 @@ public class LoanProductData { final LocalDate startDate = null; final LocalDate closeDate = null; final String status = null; + final String externalId = null; return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, - accountingType, includeInBorrowerCycle, startDate, closeDate, status); + accountingType, includeInBorrowerCycle, startDate, closeDate, status, externalId); } public static LoanProductData lookupWithCurrency(final Long id, final String name, final CurrencyData currency) { @@ -176,13 +178,14 @@ public class LoanProductData { final LocalDate startDate = null; final LocalDate closeDate = null; final String status = null; + final String externalId = null; return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, - accountingType, includeInBorrowerCycle, startDate, closeDate, status); + accountingType, includeInBorrowerCycle, startDate, closeDate, status, externalId); } public static LoanProductData sensibleDefaultsForNewLoanProductCreation() { @@ -224,13 +227,14 @@ public class LoanProductData { final LocalDate startDate = null; final LocalDate closeDate = null; final String status = null; + final String externalId = null; return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, - accountingType, includeInBorrowerCycle, startDate, closeDate, status); + accountingType, includeInBorrowerCycle, startDate, closeDate, status, externalId); } public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map accountingMappings, @@ -254,7 +258,7 @@ public class LoanProductData { final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final Collection charges, final EnumOptionData accountingType, final boolean includeInBorrowerCycle, - final LocalDate startDate, final LocalDate closeDate, final String status) { + final LocalDate startDate, final LocalDate closeDate, final String status, final String externalId) { this.id = id; this.name = name; this.description = description; @@ -289,6 +293,7 @@ public class LoanProductData { this.startDate = startDate; this.closeDate = closeDate; this.status = status; + this.externalId = externalId; this.chargeOptions = null; this.penaltyOptions = null; @@ -343,6 +348,7 @@ public class LoanProductData { this.startDate = productData.startDate; this.closeDate = productData.closeDate; this.status = productData.status; + this.externalId = productData.externalId; this.charges = nullIfEmpty(productData.charges()); this.accountingRule = productData.accountingRule; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java index 2d4164b1e..ec000bbea 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java @@ -47,7 +47,8 @@ import com.google.gson.JsonArray; * They allow for constraints to be added at product level. */ @Entity -@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") }) +@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name"), +@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") }) public class LoanProduct extends AbstractPersistable { @ManyToOne @@ -87,6 +88,9 @@ public class LoanProduct extends AbstractPersistable { @Column(name = "close_date", nullable = true) @Temporal(TemporalType.DATE) private Date closeDate; + + @Column(name = "external_id", length = 100, nullable = true, unique = true) + private String externalId; public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy, final List productCharges, final JsonCommand command, final AprCalculator aprCalculator) { @@ -130,12 +134,13 @@ public class LoanProduct extends AbstractPersistable { final LocalDate startDate = command.localDateValueOfParameterNamed("startDate"); final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate"); + final String externalId = command.stringValueOfParameterNamed("externalId"); return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, - amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate); + amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, externalId); } protected LoanProduct() { @@ -155,7 +160,7 @@ public class LoanProduct extends AbstractPersistable { final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List charges, final AccountingRuleType accountingRuleType, final boolean includeInBorrowerCycle, final LocalDate startDate, - final LocalDate closeDate) { + final LocalDate closeDate, final String externalId) { this.fund = fund; this.transactionProcessingStrategy = transactionProcessingStrategy; this.name = name.trim(); @@ -192,6 +197,8 @@ public class LoanProduct extends AbstractPersistable { if (closeDate != null) { this.closeDate = closeDate.toDateMidnight().toDate(); } + + this.externalId = externalId; } public MonetaryCurrency getCurrency() { @@ -329,6 +336,14 @@ public class LoanProduct extends AbstractPersistable { this.closeDate = null; } } + + final String externalIdTypeParamName = "externalId"; + if (command.isChangeInStringParameterNamed(externalIdTypeParamName, this.externalId)) { + final String newValue = command.stringValueOfParameterNamed(externalIdTypeParamName); + actualChanges.put(accountingTypeParamName, newValue); + this.externalId = newValue; + } + return actualChanges; } @@ -412,5 +427,9 @@ public class LoanProduct extends AbstractPersistable { public String productName() { return this.name; } + + public String getExternalId() { + return externalId; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductDataValidator.java index d57fd8b16..3f0177aba 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductDataValidator.java @@ -43,7 +43,7 @@ public final class LoanProductDataValidator { "minNumberOfRepayments", "maxNumberOfRepayments", "repaymentFrequencyType", "interestRatePerPeriod", "minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "graceOnPrincipalPayment", - "graceOnInterestPayment", "graceOnInterestCharged", "charges", "accountingRule","includeInBorrowerCycle", "startDate", "closeDate", + "graceOnInterestPayment", "graceOnInterestCharged", "charges", "accountingRule","includeInBorrowerCycle", "startDate", "closeDate", "externalId", LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java index 5ba844d04..7610b6db1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -106,7 +106,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo + "lp.grace_on_principal_periods as graceOnPrincipalPayment, lp.grace_on_interest_periods as graceOnInterestPayment, lp.grace_interest_free_periods as graceOnInterestCharged," + "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, " + "lp.accounting_type as accountingType, lp.include_in_borrower_cycle as includeInBorrowerCycle, lp.start_date as startDate, lp.close_date as closeDate, " - + "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol " + + "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol, lp.external_id as externalId " + " from m_product_loan lp " + " left join m_fund f on f.id = lp.fund_id" + " left join ref_loan_transaction_processing_strategy ltps on ltps.id = lp.loan_transaction_strategy_id" @@ -180,13 +180,14 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo } else { status = "loanProduct.active"; } + final String externalId = rs.getString("externalId"); return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, transactionStrategyId, transactionStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, - graceOnInterestCharged, this.charges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, status); + graceOnInterestCharged, this.charges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, status, externalId); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java index a0709ed0e..197ab221b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java @@ -226,7 +226,13 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { Throwable realCause = dve.getMostSpecificCause(); - if (realCause.getMessage().contains("unq_name")) { + + if (realCause.getMessage().contains("external_id")) { + + final String externalId = command.stringValueOfParameterNamed("externalId"); + throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.externalId", "Loan Product with externalId `" + externalId + + "` already exists", "externalId", externalId); + } else if (realCause.getMessage().contains("unq_name")) { final String name = command.stringValueOfParameterNamed("name"); throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name