take care of most of open new deposit account use case - interest calculation is remaining.
This commit is contained in:
@@ -18,8 +18,8 @@ CREATE TABLE `portfolio_deposit_account` (
|
||||
`actual_maturity_date` DATE DEFAULT NULL,
|
||||
`projected_interest_accrued_on_maturity` decimal(19,6) NOT NULL,
|
||||
`actual_interest_accrued` decimal(19,6) DEFAULT NULL,
|
||||
`projected_total_return_on_maturity_amount` decimal(19,6) NOT NULL,
|
||||
`actual_total_return` decimal(19,6) DEFAULT NULL,
|
||||
`projected_total_maturity_amount` decimal(19,6) NOT NULL,
|
||||
`actual_total_amount` decimal(19,6) DEFAULT NULL,
|
||||
`can_renew` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`renewed_account_id` bigint(20) DEFAULT NULL,
|
||||
`can_pre_close` tinyint(1) NOT NULL DEFAULT '0',
|
||||
|
||||
+26
-15
@@ -3,6 +3,8 @@ package org.mifosng.platform.api.commands;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Immutable command used when create/renewing deposit accounts
|
||||
*/
|
||||
@@ -13,12 +15,14 @@ public class DepositAccountCommand {
|
||||
private final Long productId;
|
||||
private final String externalId;
|
||||
|
||||
private final String currencyCode;
|
||||
private final Integer digitsAfterDecimal;
|
||||
private final BigDecimal depositAmount;
|
||||
private final BigDecimal maturityInterestRate;
|
||||
private final Integer termInMonths;
|
||||
|
||||
private final Integer interestCompoundedEvery;
|
||||
private final Integer interestCompoundedEveryPeriodType;
|
||||
private final LocalDate commencementDate;
|
||||
|
||||
private final Set<String> modifiedParameters;
|
||||
|
||||
public DepositAccountCommand(final Set<String> modifiedParameters,
|
||||
@@ -26,23 +30,22 @@ public class DepositAccountCommand {
|
||||
final Long clientId,
|
||||
final Long productId,
|
||||
final String externalId,
|
||||
final String currencyCode,
|
||||
final Integer digitsAfterDecimal,
|
||||
final BigDecimal depositAmount,
|
||||
final BigDecimal interestRate,
|
||||
final Integer termInMonths) {
|
||||
final Integer termInMonths, final Integer compoundingInterestFrequency, final Integer compoundingInterestFrequencyType, final LocalDate commencementDate) {
|
||||
this.id = id;
|
||||
this.clientId = clientId;
|
||||
this.productId = productId;
|
||||
this.externalId = externalId;
|
||||
|
||||
this.currencyCode = currencyCode;
|
||||
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||
this.depositAmount = depositAmount;
|
||||
this.maturityInterestRate = interestRate;
|
||||
this.termInMonths = termInMonths;
|
||||
|
||||
this.modifiedParameters = modifiedParameters;
|
||||
this.interestCompoundedEvery = compoundingInterestFrequency;
|
||||
this.interestCompoundedEveryPeriodType = compoundingInterestFrequencyType;
|
||||
this.commencementDate = commencementDate;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@@ -61,14 +64,6 @@ public class DepositAccountCommand {
|
||||
return externalId;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return currencyCode;
|
||||
}
|
||||
|
||||
public Integer getDigitsAfterDecimal() {
|
||||
return digitsAfterDecimal;
|
||||
}
|
||||
|
||||
public BigDecimal getDepositAmount() {
|
||||
return depositAmount;
|
||||
}
|
||||
@@ -80,6 +75,22 @@ public class DepositAccountCommand {
|
||||
public Integer getTermInMonths() {
|
||||
return termInMonths;
|
||||
}
|
||||
|
||||
public Integer getInterestCompoundedEvery() {
|
||||
return interestCompoundedEvery;
|
||||
}
|
||||
|
||||
public Integer getInterestCompoundedEveryPeriodType() {
|
||||
return interestCompoundedEveryPeriodType;
|
||||
}
|
||||
|
||||
public LocalDate getCommencementDate() {
|
||||
return commencementDate;
|
||||
}
|
||||
|
||||
public boolean isNoFieldChanged() {
|
||||
return this.modifiedParameters.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isCurrencyCodeChanged() {
|
||||
return this.modifiedParameters.contains("currencyCode");
|
||||
|
||||
+11
-5
@@ -1493,7 +1493,9 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
||||
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(
|
||||
Arrays.asList("clientId", "productId", "externalId", "currencyCode", "digitsAfterDecimal", "depositAmount", "maturityInterestRate", "termInMonths", "locale")
|
||||
Arrays.asList("clientId", "productId", "externalId", "depositAmount", "maturityInterestRate",
|
||||
"termInMonths", "interestCompoundedEvery", "interestCompoundedEveryPeriodType", "commencementDate",
|
||||
"locale", "dateFormat")
|
||||
);
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
@@ -1501,15 +1503,19 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
||||
Long clientId = extractLongParameter("clientId", requestMap, modifiedParameters);
|
||||
Long productId = extractLongParameter("productId", requestMap, modifiedParameters);
|
||||
String externalId = extractStringParameter("externalId", requestMap,modifiedParameters);
|
||||
String currencyCode=extractStringParameter("currencyCode", requestMap,modifiedParameters);
|
||||
Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters);
|
||||
BigDecimal depositAmount=extractBigDecimalParameter("depositAmount", requestMap, modifiedParameters);
|
||||
BigDecimal interestRate = extractBigDecimalParameter("maturityInterestRate", requestMap, modifiedParameters);
|
||||
Integer termInMonths = extractIntegerParameter("termInMonths", requestMap, modifiedParameters);
|
||||
|
||||
// isRenewable, isPreClosureAllowed, expectedDepositDate, pojectMaturityDate, projectedInterestAccrued
|
||||
Integer interestCompoundedEvery = extractIntegerParameter("interestCompoundedEvery", requestMap, modifiedParameters);
|
||||
Integer interestCompoundedEveryPeriodType = extractIntegerParameter("interestCompoundedEveryPeriodType", requestMap, modifiedParameters);
|
||||
LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters);
|
||||
|
||||
return new DepositAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode, digitsAfterDecimalValue, depositAmount, interestRate, termInMonths);
|
||||
// TODO - isRenewable, isPreClosureAllowed
|
||||
|
||||
return new DepositAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId,
|
||||
externalId, depositAmount, interestRate, termInMonths,
|
||||
interestCompoundedEvery, interestCompoundedEveryPeriodType, commencementDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -113,4 +113,8 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
|
||||
public void validateInterestRateInRange(final BigDecimal interestRate) {
|
||||
this.depositProductRelatedDetail.validateInterestRateInRange(interestRate);
|
||||
}
|
||||
|
||||
public void validateDepositInRange(final BigDecimal depositAmount) {
|
||||
this.depositProductRelatedDetail.validateDepositInRange(depositAmount);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-2
@@ -8,7 +8,7 @@ import javax.persistence.Embedded;
|
||||
|
||||
import org.mifosng.platform.api.commands.DepositProductCommand;
|
||||
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||
import org.mifosng.platform.exceptions.InterestRateOutsideRangeException;
|
||||
import org.mifosng.platform.exceptions.ValueOutsideRangeException;
|
||||
|
||||
@Embeddable
|
||||
public class DepositProductRelatedDetail {
|
||||
@@ -169,7 +169,28 @@ public class DepositProductRelatedDetail {
|
||||
}
|
||||
|
||||
if (!inRange) {
|
||||
throw new InterestRateOutsideRangeException(interestRate, this.maturityMinInterestRate, this.maturityMaxInterestRate);
|
||||
final String actualValue = interestRate.toPlainString();
|
||||
final String minValue = (this.maturityMinInterestRate == null) ? "" : this.maturityMinInterestRate.toPlainString();
|
||||
final String maxValue = (this.maturityMaxInterestRate == null) ? "" : this.maturityMaxInterestRate.toPlainString();
|
||||
throw new ValueOutsideRangeException(actualValue, minValue, maxValue, "deposit.account.maturityInterestRate");
|
||||
}
|
||||
}
|
||||
|
||||
public void validateDepositInRange(final BigDecimal depositAmount) {
|
||||
boolean inRange = true;
|
||||
if (depositAmount.compareTo(this.minimumBalance) < 0) {
|
||||
inRange = false;
|
||||
}
|
||||
|
||||
if (this.maximumBalance != null && this.maximumBalance.compareTo(depositAmount) < 0) {
|
||||
inRange = false;
|
||||
}
|
||||
|
||||
if (!inRange) {
|
||||
final String actualValue = depositAmount.toPlainString();
|
||||
final String minValue = (this.minimumBalance == null) ? "" : this.minimumBalance.toPlainString();
|
||||
final String maxValue = (this.minimumBalance == null) ? "" : this.minimumBalance.toPlainString();
|
||||
throw new ValueOutsideRangeException(actualValue, minValue, maxValue, "deposit.account.deposit.amount");
|
||||
}
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* Exception thrown when an attempt is made update the parent of a root office.
|
||||
*/
|
||||
public class InterestRateOutsideRangeException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InterestRateOutsideRangeException(final BigDecimal interestRate, final BigDecimal rangeMin, final BigDecimal rangeMax) {
|
||||
super("error.msg.deposit.account.maturityInterestRate.outside.of.allowed.range", "Interest rate of " + interestRate.toPlainString() + " is outside of allowed range of ["
|
||||
+ rangeMin.toPlainString() + ", " + rangeMax.toPlainString() + "].", interestRate, rangeMin, rangeMax);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown when an attempt is made update the parent of a root office.
|
||||
*/
|
||||
public class ValueOutsideRangeException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ValueOutsideRangeException(final String actualValue, final String rangeMin, final String rangeMax, final String fieldCode) {
|
||||
super("error.msg." + fieldCode + ".outside.of.allowed.range", actualValue + " is outside of allowed range of ["
|
||||
+ rangeMin + ", " + rangeMax + "].", actualValue, rangeMin, rangeMax);
|
||||
}
|
||||
}
|
||||
+91
-5
@@ -1,78 +1,164 @@
|
||||
package org.mifosng.platform.saving.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosng.platform.api.commands.DepositAccountCommand;
|
||||
import org.mifosng.platform.client.domain.Client;
|
||||
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||
import org.mifosng.platform.currency.domain.Money;
|
||||
import org.mifosng.platform.deposit.domain.DepositProduct;
|
||||
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
|
||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@Table(name = "portfolio_deposit_account", uniqueConstraints = @UniqueConstraint(name="deposit_acc_external_id", columnNames = { "external_id" }))
|
||||
public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "client_id", nullable = false)
|
||||
private Client client;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "product_id")
|
||||
private final DepositProduct product;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "external_id")
|
||||
private String externalId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@Column(name = "deposit_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal depositAmount;
|
||||
|
||||
@Column(name = "maturity_interest_rate", scale = 6, precision = 19, nullable = false)
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "maturity_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal interestRate;
|
||||
|
||||
@Column(name = "tenure_months", nullable = false)
|
||||
private Integer tenureInMonths;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "interest_compounding_frequency", nullable = false)
|
||||
private Integer interestCompoundedEvery;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "interest_compounding_frequency_enum", nullable = false)
|
||||
private PeriodFrequencyType interestCompoundedFrequencyType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "projected_commencement_date")
|
||||
private Date projectedCommencementDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "actual_commencement_date")
|
||||
private Date actualCommencementDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "projected_maturity_date")
|
||||
private Date projectedMaturityDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "actual_maturity_date")
|
||||
private Date actualMaturityDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal projectedInterestAccruedOnMaturity;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal interestAccrued;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal projectedTotalOnMaturity;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal total;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal preClosureInterestRate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "can_renew", nullable = false)
|
||||
private boolean renewalAllowed;
|
||||
private boolean renewalAllowed = false;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "can_pre_close", nullable = false)
|
||||
private boolean preClosureAllowed;
|
||||
private boolean preClosureAllowed = false;
|
||||
|
||||
@Column(name = "is_deleted", nullable=false)
|
||||
private boolean deleted = false;
|
||||
|
||||
public static DepositAccount openNew(
|
||||
final Client client, final DepositProduct product,
|
||||
final String externalId, final Money deposit, final BigDecimal interestRate, final Integer termInMonths,
|
||||
final Integer interestCompoundedEvery,
|
||||
final PeriodFrequencyType interestCompoundedFrequencyPeriodType,
|
||||
final LocalDate commencementDate) {
|
||||
return new DepositAccount(client, product, externalId, deposit, interestRate, termInMonths,
|
||||
interestCompoundedEvery, interestCompoundedFrequencyPeriodType, commencementDate);
|
||||
}
|
||||
|
||||
protected DepositAccount() {
|
||||
this.product = null;
|
||||
}
|
||||
|
||||
public DepositAccount(
|
||||
private DepositAccount(
|
||||
final Client client, final DepositProduct product,
|
||||
final String externalId, final Money deposit, final BigDecimal interestRate, final Integer termInMonths) {
|
||||
final String externalId, final Money deposit, final BigDecimal interestRate, final Integer termInMonths,
|
||||
final Integer interestCompoundedEvery,
|
||||
final PeriodFrequencyType interestCompoundedFrequencyPeriodType,
|
||||
final LocalDate commencementDate) {
|
||||
this.client = client;
|
||||
this.product = product;
|
||||
this.externalId = externalId;
|
||||
this.currency = deposit.getCurrency();
|
||||
this.depositAmount = deposit.getAmount();
|
||||
product.validateDepositInRange(this.depositAmount);
|
||||
this.interestRate = interestRate;
|
||||
product.validateInterestRateInRange(interestRate);
|
||||
this.tenureInMonths = termInMonths;
|
||||
|
||||
this.interestCompoundedEvery = interestCompoundedEvery;
|
||||
this.interestCompoundedFrequencyType = interestCompoundedFrequencyPeriodType;
|
||||
if (commencementDate != null) {
|
||||
this.projectedCommencementDate = commencementDate.toDate();
|
||||
this.projectedMaturityDate = commencementDate.plusMonths(this.tenureInMonths).toDate();
|
||||
}
|
||||
|
||||
this.preClosureInterestRate = BigDecimal.ZERO;
|
||||
|
||||
// derived fields
|
||||
this.projectedInterestAccruedOnMaturity = BigDecimal.ZERO;
|
||||
this.projectedTotalOnMaturity = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
|
||||
+16
-4
@@ -3,12 +3,12 @@ package org.mifosng.platform.savingproduct.service;
|
||||
import org.mifosng.platform.api.commands.DepositAccountCommand;
|
||||
import org.mifosng.platform.client.domain.Client;
|
||||
import org.mifosng.platform.client.domain.ClientRepository;
|
||||
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||
import org.mifosng.platform.currency.domain.Money;
|
||||
import org.mifosng.platform.deposit.domain.DepositProduct;
|
||||
import org.mifosng.platform.deposit.domain.DepositProductRepository;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.DepositProductNotFoundException;
|
||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||
import org.mifosng.platform.saving.domain.DepositAccount;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -40,9 +40,21 @@ public class DepositAccountAssembler {
|
||||
throw new DepositProductNotFoundException(command.getProductId());
|
||||
}
|
||||
|
||||
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
|
||||
Money deposit = Money.of(currency, command.getDepositAmount());
|
||||
// currency details inherited from product setting
|
||||
Money deposit = Money.of(product.getCurrency(), command.getDepositAmount());
|
||||
|
||||
return new DepositAccount(client, product, command.getExternalId(), deposit, command.getMaturityInterestRate(), command.getTermInMonths());
|
||||
// default to months for now.
|
||||
Integer interestCompoundingPeriodType = PeriodFrequencyType.MONTHS.getValue();
|
||||
if (command.getInterestCompoundedEveryPeriodType() != null) {
|
||||
interestCompoundingPeriodType = command.getInterestCompoundedEveryPeriodType();
|
||||
}
|
||||
PeriodFrequencyType compoundingInterestFrequency = PeriodFrequencyType.fromInt(interestCompoundingPeriodType);
|
||||
|
||||
// boolean renewalAllowed = product.isr
|
||||
|
||||
DepositAccount account = DepositAccount.openNew(client, product, command.getExternalId(), deposit, command.getMaturityInterestRate(),
|
||||
command.getTermInMonths(), command.getInterestCompoundedEvery(), compoundingInterestFrequency, command.getCommencementDate());
|
||||
|
||||
return account;
|
||||
}
|
||||
}
|
||||
+14
-8
@@ -27,16 +27,20 @@ public class DepositAccountCommandValidator {
|
||||
baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull();
|
||||
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().notNull().inMinMaxRange(0, 6);
|
||||
baseDataValidator.reset().parameter("depositAmount").value(command.getDepositAmount()).ignoreIfNull().notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull().notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("termInMonths").value(command.getTermInMonths()).ignoreIfNull().notNull().integerGreaterThanZero();
|
||||
|
||||
baseDataValidator.reset().anyOfNotNull(
|
||||
command.getClientId(), command.getProductId(), command.getExternalId(),
|
||||
command.getCurrencyCode(), command.getDigitsAfterDecimal(),
|
||||
command.getDepositAmount(), command.getMaturityInterestRate(), command.getTermInMonths());
|
||||
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).ignoreIfNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
|
||||
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
|
||||
|
||||
if (command.isNoFieldChanged()) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(".no.parameters.for.update");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update.");
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), "id");
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||
@@ -53,12 +57,14 @@ public class DepositAccountCommandValidator {
|
||||
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
|
||||
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6);
|
||||
baseDataValidator.reset().parameter("depositAmount").value(command.getDepositAmount()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("termInMonths").value(command.getTermInMonths()).notNull().integerGreaterThanZero();
|
||||
|
||||
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).notNull().inMinMaxRange(2, 2);
|
||||
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull();
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||
}
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
return "da.id as id, da.client_id as clientId, da.product_id as productId,"
|
||||
+ " da.currency_code as currencyCode, da.currency_digits as currencyDigits, "
|
||||
+ " da.deposit_amount as depositAmount, "
|
||||
+ " da.maturity_interest_rate as interestRate, "
|
||||
+ " da.maturity_nominal_interest_rate as interestRate, "
|
||||
+ " da.created_date as createdon, da.lastmodified_date as modifiedon, "
|
||||
+ " c.firstname as firstname, c.lastname as lastname, pd.name as productName,"
|
||||
+ " curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol"
|
||||
|
||||
+55
-23
@@ -3,17 +3,23 @@ package org.mifosng.platform.savingproduct.service;
|
||||
import org.mifosng.platform.api.commands.DepositAccountCommand;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.exceptions.DepositAccountNotFoundException;
|
||||
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
|
||||
import org.mifosng.platform.exceptions.ProductNotFoundException;
|
||||
import org.mifosng.platform.saving.domain.DepositAccount;
|
||||
import org.mifosng.platform.saving.domain.DepositAccountRepository;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements DepositAccountWritePlatformService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DepositAccountWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DepositAccountRepository depositAccountRepository;
|
||||
private final DepositAccountAssembler depositAccountAssembler;
|
||||
@@ -28,40 +34,66 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
this.depositAccountRepository = depositAccountRepository;
|
||||
this.depositAccountAssembler = depositAccountAssembler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Guaranteed to throw an exception no matter what the data integrity issue is.
|
||||
*/
|
||||
private void handleDataIntegrityIssues(final DepositAccountCommand command, DataIntegrityViolationException dve) {
|
||||
|
||||
Throwable realCause = dve.getMostSpecificCause();
|
||||
if (realCause.getMessage().contains("deposit_acc_external_id")) {
|
||||
throw new PlatformDataIntegrityException("error.msg.desposit.account.duplicate.externalId", "Deposit account with externalId " + command.getExternalId() + " already exists", "externalId", command.getExternalId());
|
||||
}
|
||||
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.deposit.account.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier createDepositAccount(final DepositAccountCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
|
||||
validator.validateForCreate();
|
||||
|
||||
final DepositAccount account = this.depositAccountAssembler.assembleFrom(command);
|
||||
this.depositAccountRepository.save(account);
|
||||
|
||||
return new EntityIdentifier(account.getId());
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
|
||||
validator.validateForCreate();
|
||||
|
||||
final DepositAccount account = this.depositAccountAssembler.assembleFrom(command);
|
||||
this.depositAccountRepository.save(account);
|
||||
|
||||
return new EntityIdentifier(account.getId());
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return new EntityIdentifier(Long.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier updateDepositAccount(final DepositAccountCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
|
||||
validator.validateForUpdate();
|
||||
|
||||
final DepositAccount account = this.depositAccountAssembler.assembleFrom(command);
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new DepositAccountNotFoundException(command.getId());
|
||||
try {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
|
||||
validator.validateForUpdate();
|
||||
|
||||
// FIXME - update scenarios to be completely done
|
||||
final DepositAccount account = this.depositAccountAssembler.assembleFrom(command);
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new DepositAccountNotFoundException(command.getId());
|
||||
}
|
||||
|
||||
account.update(command);
|
||||
this.depositAccountRepository.save(account);
|
||||
|
||||
return new EntityIdentifier(account.getId());
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return new EntityIdentifier(Long.valueOf(-1));
|
||||
}
|
||||
|
||||
account.update(command);
|
||||
this.depositAccountRepository.save(account);
|
||||
|
||||
return new EntityIdentifier(Long.valueOf(1));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
Reference in New Issue
Block a user