mifosx-567 allow post and put for externalId for loanproduct

This commit is contained in:
John Woodlock
2013-08-01 19:15:28 +01:00
parent c1aa16c754
commit b6a164c8c2
8 changed files with 48 additions and 15 deletions
@@ -1,2 +1,2 @@
INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker') INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker`)
values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0) values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0);
@@ -22,7 +22,8 @@ import org.mifosplatform.organisation.office.domain.Office;
import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity @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<Long> { public class Staff extends AbstractPersistable<Long> {
@Column(name = "firstname", length = 50) @Column(name = "firstname", length = 50)
@@ -69,7 +69,7 @@ public class LoanProductsApiResource {
"graceOnInterestPayment", "graceOnInterestCharged", "interestRatePerPeriod", "minInterestRatePerPeriod", "graceOnInterestPayment", "graceOnInterestCharged", "interestRatePerPeriod", "minInterestRatePerPeriod",
"maxInterestRatePerPeriod", "interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType", "maxInterestRatePerPeriod", "interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType",
"interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName",
"charges", "accountingRule", "accountingMappings", "paymentChannelToFundSourceMappings", "fundOptions", "paymentTypeOptions", "charges", "accountingRule", "externalId", "accountingMappings", "paymentChannelToFundSourceMappings", "fundOptions", "paymentTypeOptions",
"currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "amortizationTypeOptions", "currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "amortizationTypeOptions",
"interestTypeOptions", "interestCalculationPeriodTypeOptions", "transactionProcessingStrategyOptions", "chargeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "transactionProcessingStrategyOptions", "chargeOptions",
"accountingOptions", "accountingRuleOptions", "accountingMappingOptions")); "accountingOptions", "accountingRuleOptions", "accountingMappingOptions"));
@@ -42,6 +42,7 @@ public class LoanProductData {
private final LocalDate startDate; private final LocalDate startDate;
private final LocalDate closeDate; private final LocalDate closeDate;
private final String status; private final String status;
private final String externalId;
// terms // terms
private final CurrencyData currency; private final CurrencyData currency;
private final BigDecimal principal; private final BigDecimal principal;
@@ -135,12 +136,13 @@ public class LoanProductData {
final LocalDate startDate = null; final LocalDate startDate = null;
final LocalDate closeDate = null; final LocalDate closeDate = null;
final String status = null; final String status = null;
final String externalId = null;
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, 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) { 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 startDate = null;
final LocalDate closeDate = null; final LocalDate closeDate = null;
final String status = null; final String status = null;
final String externalId = null;
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges,
accountingType, includeInBorrowerCycle, startDate, closeDate, status); accountingType, includeInBorrowerCycle, startDate, closeDate, status, externalId);
} }
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() { public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
@@ -224,13 +227,14 @@ public class LoanProductData {
final LocalDate startDate = null; final LocalDate startDate = null;
final LocalDate closeDate = null; final LocalDate closeDate = null;
final String status = null; final String status = null;
final String externalId = null;
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
transactionProcessingStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, 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<String, Object> accountingMappings, public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
@@ -254,7 +258,7 @@ public class LoanProductData {
final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName, final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName,
final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged,
final Collection<ChargeData> charges, final EnumOptionData accountingType, final boolean includeInBorrowerCycle, final Collection<ChargeData> 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.id = id;
this.name = name; this.name = name;
this.description = description; this.description = description;
@@ -289,6 +293,7 @@ public class LoanProductData {
this.startDate = startDate; this.startDate = startDate;
this.closeDate = closeDate; this.closeDate = closeDate;
this.status = status; this.status = status;
this.externalId = externalId;
this.chargeOptions = null; this.chargeOptions = null;
this.penaltyOptions = null; this.penaltyOptions = null;
@@ -343,6 +348,7 @@ public class LoanProductData {
this.startDate = productData.startDate; this.startDate = productData.startDate;
this.closeDate = productData.closeDate; this.closeDate = productData.closeDate;
this.status = productData.status; this.status = productData.status;
this.externalId = productData.externalId;
this.charges = nullIfEmpty(productData.charges()); this.charges = nullIfEmpty(productData.charges());
this.accountingRule = productData.accountingRule; this.accountingRule = productData.accountingRule;
@@ -47,7 +47,8 @@ import com.google.gson.JsonArray;
* They allow for constraints to be added at product level. * They allow for constraints to be added at product level.
*/ */
@Entity @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<Long> { public class LoanProduct extends AbstractPersistable<Long> {
@ManyToOne @ManyToOne
@@ -88,6 +89,9 @@ public class LoanProduct extends AbstractPersistable<Long> {
@Temporal(TemporalType.DATE) @Temporal(TemporalType.DATE)
private Date closeDate; 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, public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) { final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
@@ -130,12 +134,13 @@ public class LoanProduct extends AbstractPersistable<Long> {
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate"); final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate"); final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate");
final String externalId = command.stringValueOfParameterNamed("externalId");
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal, return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal,
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate,
interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments, interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, minNumberOfRepayments, maxNumberOfRepayments, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate); amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, externalId);
} }
protected LoanProduct() { protected LoanProduct() {
@@ -155,7 +160,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged,
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges, final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges,
final AccountingRuleType accountingRuleType, final boolean includeInBorrowerCycle, final LocalDate startDate, final AccountingRuleType accountingRuleType, final boolean includeInBorrowerCycle, final LocalDate startDate,
final LocalDate closeDate) { final LocalDate closeDate, final String externalId) {
this.fund = fund; this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy; this.transactionProcessingStrategy = transactionProcessingStrategy;
this.name = name.trim(); this.name = name.trim();
@@ -192,6 +197,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
if (closeDate != null) { if (closeDate != null) {
this.closeDate = closeDate.toDateMidnight().toDate(); this.closeDate = closeDate.toDateMidnight().toDate();
} }
this.externalId = externalId;
} }
public MonetaryCurrency getCurrency() { public MonetaryCurrency getCurrency() {
@@ -329,6 +336,14 @@ public class LoanProduct extends AbstractPersistable<Long> {
this.closeDate = null; 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; return actualChanges;
} }
@@ -413,4 +428,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
return this.name; return this.name;
} }
public String getExternalId() {
return externalId;
}
} }
@@ -43,7 +43,7 @@ public final class LoanProductDataValidator {
"minNumberOfRepayments", "maxNumberOfRepayments", "repaymentFrequencyType", "interestRatePerPeriod", "minNumberOfRepayments", "maxNumberOfRepayments", "repaymentFrequencyType", "interestRatePerPeriod",
"minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType", "minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType",
"interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "graceOnPrincipalPayment", "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.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.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(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
@@ -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.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.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, " + "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 " + " from m_product_loan lp "
+ " left join m_fund f on f.id = lp.fund_id" + " 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" + " 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 { } else {
status = "loanProduct.active"; status = "loanProduct.active";
} }
final String externalId = rs.getString("externalId");
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
transactionStrategyId, transactionStrategyName, graceOnPrincipalPayment, graceOnInterestPayment, transactionStrategyId, transactionStrategyName, graceOnPrincipalPayment, graceOnInterestPayment,
graceOnInterestCharged, this.charges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, status); graceOnInterestCharged, this.charges, accountingRuleType, includeInBorrowerCycle, startDate, closeDate, status, externalId);
} }
} }
@@ -226,7 +226,13 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause(); 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"); final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name