Merge pull request #502 from johnw65/externalIds

mifosx-567  allow post and put for externalId for loanproduct
This commit is contained in:
John Woodlock
2013-08-01 11:18:15 -07:00
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')
values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0)
INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker`)
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;
@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> {
@Column(name = "firstname", length = 50)
@@ -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"));
@@ -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<String, Object> 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<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.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;
@@ -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<Long> {
@ManyToOne
@@ -87,6 +88,9 @@ public class LoanProduct extends AbstractPersistable<Long> {
@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<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 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<Long> {
final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged,
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> 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<Long> {
if (closeDate != null) {
this.closeDate = closeDate.toDateMidnight().toDate();
}
this.externalId = externalId;
}
public MonetaryCurrency getCurrency() {
@@ -329,6 +336,14 @@ public class LoanProduct extends AbstractPersistable<Long> {
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<Long> {
public String productName() {
return this.name;
}
public String getExternalId() {
return externalId;
}
}
@@ -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(),
@@ -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);
}
}
@@ -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