MIFOSX-2426 : added support for Interest Rate Charts based on Amount
This commit is contained in:
+7
-4
@@ -142,7 +142,12 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
public static Calendar createRepeatingCalendar(final String title, final LocalDate startDate, final Integer typeId,
|
||||
final CalendarFrequencyType frequencyType, final Integer interval, final Integer repeatsOnDay) {
|
||||
final String recurrence = constructRecurrence(frequencyType, interval, repeatsOnDay);
|
||||
return createRepeatingCalendar(title, startDate, typeId, recurrence);
|
||||
}
|
||||
|
||||
public static Calendar createRepeatingCalendar(final String title, final LocalDate startDate, final Integer typeId,
|
||||
final String recurrence) {
|
||||
final String description = null;
|
||||
final String location = null;
|
||||
final LocalDate endDate = null;
|
||||
@@ -151,8 +156,6 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final Integer remindById = null;
|
||||
final Integer firstReminder = null;
|
||||
final Integer secondReminder = null;
|
||||
final String recurrence = constructRecurrence(frequencyType, interval, repeatsOnDay);
|
||||
|
||||
return new Calendar(title, description, location, startDate, endDate, duration, typeId, repeating, recurrence, remindById,
|
||||
firstReminder, secondReminder);
|
||||
}
|
||||
@@ -233,7 +236,7 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command, final Boolean areActiveEntitiesSynced ) {
|
||||
public Map<String, Object> update(final JsonCommand command, final Boolean areActiveEntitiesSynced) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
@@ -345,7 +348,7 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
* calendar then do not allow to change meeting frequency
|
||||
*/
|
||||
|
||||
if ( areActiveEntitiesSynced && !CalendarUtils.isFrequencySame(this.recurrence, newRecurrence)) {
|
||||
if (areActiveEntitiesSynced && !CalendarUtils.isFrequencySame(this.recurrence, newRecurrence)) {
|
||||
final String defaultUserMessage = "Update of meeting frequency is not supported";
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.frequency", defaultUserMessage);
|
||||
}
|
||||
|
||||
+6
-4
@@ -44,6 +44,7 @@ public class InterestRateChartApiConstants {
|
||||
public static final String endDateParamName = "endDate";
|
||||
public static final String productIdParamName = "productId";
|
||||
public static final String productNameParamName = "productName";
|
||||
public static final String isPrimaryGroupingByAmountParamName = "isPrimaryGroupingByAmount";
|
||||
|
||||
// interest rate chart Slabs parameters
|
||||
// public static final String periodTypeParamName = "periodType";
|
||||
@@ -63,13 +64,14 @@ public class InterestRateChartApiConstants {
|
||||
public static final String deleteParamName = "delete";
|
||||
|
||||
public static final Set<String> INTERESTRATE_CHART_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, productIdParamName,
|
||||
chartSlabs));
|
||||
dateFormatParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, productIdParamName, chartSlabs,
|
||||
isPrimaryGroupingByAmountParamName));
|
||||
|
||||
public static final Set<String> INTERESTRATE_CHART_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs,
|
||||
deleteParamName));
|
||||
deleteParamName, isPrimaryGroupingByAmountParamName));
|
||||
|
||||
public static final Set<String> INTERESTRATE_CHART_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs));
|
||||
dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs,
|
||||
isPrimaryGroupingByAmountParamName));
|
||||
}
|
||||
+37
-28
@@ -18,9 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.interestratechart.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
@@ -38,9 +37,10 @@ public class InterestRateChartData {
|
||||
private final LocalDate endDate;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final boolean isPrimaryGroupingByAmount;
|
||||
|
||||
// associations
|
||||
private Set<InterestRateChartSlabData> chartSlabs;
|
||||
private Collection<InterestRateChartSlabData> chartSlabs;
|
||||
|
||||
// template
|
||||
private final Collection<EnumOptionData> periodTypes;
|
||||
@@ -53,9 +53,9 @@ public class InterestRateChartData {
|
||||
private final Collection<CodeValueData> clientClassificationOptions;
|
||||
|
||||
public static InterestRateChartData instance(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
|
||||
Long savingsProductId, String savingsProductName) {
|
||||
boolean isPrimaryGroupingByAmount, Long savingsProductId, String savingsProductName) {
|
||||
Collection<EnumOptionData> periodTypes = null;
|
||||
Set<InterestRateChartSlabData> chartSlabs = null;
|
||||
Collection<InterestRateChartSlabData> chartSlabs = null;
|
||||
final Collection<EnumOptionData> entityTypeOptions = null;
|
||||
final Collection<EnumOptionData> attributeNameOptions = null;
|
||||
final Collection<EnumOptionData> conditionTypeOptions = null;
|
||||
@@ -63,17 +63,18 @@ public class InterestRateChartData {
|
||||
final Collection<CodeValueData> genderOptions = null;
|
||||
final Collection<CodeValueData> clientTypeOptions = null;
|
||||
final Collection<CodeValueData> clientClassificationOptions = null;
|
||||
return new InterestRateChartData(id, name, description, fromDate, endDate, savingsProductId, savingsProductName, chartSlabs,
|
||||
periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
|
||||
clientTypeOptions, clientClassificationOptions);
|
||||
return new InterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId,
|
||||
savingsProductName, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
|
||||
incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
}
|
||||
|
||||
public static InterestRateChartData withSlabs(InterestRateChartData interestRateChartData, Set<InterestRateChartSlabData> chartSlabs) {
|
||||
public static InterestRateChartData withSlabs(InterestRateChartData interestRateChartData, Collection<InterestRateChartSlabData> chartSlabs) {
|
||||
return new InterestRateChartData(interestRateChartData.id, interestRateChartData.name, interestRateChartData.description,
|
||||
interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.productId,
|
||||
interestRateChartData.productName, chartSlabs, interestRateChartData.periodTypes, interestRateChartData.entityTypeOptions,
|
||||
interestRateChartData.attributeNameOptions, interestRateChartData.conditionTypeOptions,
|
||||
interestRateChartData.incentiveTypeOptions, interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
|
||||
interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.isPrimaryGroupingByAmount,
|
||||
interestRateChartData.productId, interestRateChartData.productName, chartSlabs, interestRateChartData.periodTypes,
|
||||
interestRateChartData.entityTypeOptions, interestRateChartData.attributeNameOptions,
|
||||
interestRateChartData.conditionTypeOptions, interestRateChartData.incentiveTypeOptions,
|
||||
interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
|
||||
interestRateChartData.clientClassificationOptions);
|
||||
}
|
||||
|
||||
@@ -83,9 +84,10 @@ public class InterestRateChartData {
|
||||
final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
|
||||
final Collection<CodeValueData> clientClassificationOptions) {
|
||||
return new InterestRateChartData(interestRateChartData.id, interestRateChartData.name, interestRateChartData.description,
|
||||
interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.productId,
|
||||
interestRateChartData.productName, interestRateChartData.chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions,
|
||||
conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.isPrimaryGroupingByAmount,
|
||||
interestRateChartData.productId, interestRateChartData.productName, interestRateChartData.chartSlabs, periodTypes,
|
||||
entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions,
|
||||
clientClassificationOptions);
|
||||
}
|
||||
|
||||
public static InterestRateChartData template(Collection<EnumOptionData> periodTypes,
|
||||
@@ -98,26 +100,28 @@ public class InterestRateChartData {
|
||||
final String description = null;
|
||||
final LocalDate fromDate = null;
|
||||
final LocalDate endDate = null;
|
||||
final boolean isPrimaryGroupingByAmount = false;
|
||||
final Long savingsProductId = null;
|
||||
final String savingsProductName = null;
|
||||
final Set<InterestRateChartSlabData> chartSlabs = null;
|
||||
final Collection<InterestRateChartSlabData> chartSlabs = null;
|
||||
|
||||
return new InterestRateChartData(id, name, description, fromDate, endDate, savingsProductId, savingsProductName, chartSlabs,
|
||||
periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
|
||||
clientTypeOptions, clientClassificationOptions);
|
||||
return new InterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId,
|
||||
savingsProductName, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
|
||||
incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
}
|
||||
|
||||
private InterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate, Long savingsProductId,
|
||||
String savingsProductName, Set<InterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes,
|
||||
final Collection<EnumOptionData> entityTypeOptions, final Collection<EnumOptionData> attributeNameOptions,
|
||||
final Collection<EnumOptionData> conditionTypeOptions, final Collection<EnumOptionData> incentiveTypeOptions,
|
||||
final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
|
||||
final Collection<CodeValueData> clientClassificationOptions) {
|
||||
private InterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
|
||||
boolean isPrimaryGroupingByAmount, Long savingsProductId, String savingsProductName, Collection<InterestRateChartSlabData> chartSlabs,
|
||||
Collection<EnumOptionData> periodTypes, final Collection<EnumOptionData> entityTypeOptions,
|
||||
final Collection<EnumOptionData> attributeNameOptions, final Collection<EnumOptionData> conditionTypeOptions,
|
||||
final Collection<EnumOptionData> incentiveTypeOptions, final Collection<CodeValueData> genderOptions,
|
||||
final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.fromDate = fromDate;
|
||||
this.endDate = endDate;
|
||||
this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
|
||||
this.chartSlabs = chartSlabs;
|
||||
this.productId = savingsProductId;
|
||||
this.productName = savingsProductName;
|
||||
@@ -133,7 +137,7 @@ public class InterestRateChartData {
|
||||
|
||||
public void addChartSlab(final InterestRateChartSlabData chartSlab) {
|
||||
if (this.chartSlabs == null) {
|
||||
this.chartSlabs = new HashSet<>();
|
||||
this.chartSlabs = new ArrayList<>();
|
||||
}
|
||||
|
||||
this.chartSlabs.add(chartSlab);
|
||||
@@ -159,7 +163,7 @@ public class InterestRateChartData {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public Set<InterestRateChartSlabData> chartSlabs() {
|
||||
public Collection<InterestRateChartSlabData> chartSlabs() {
|
||||
return this.chartSlabs;
|
||||
}
|
||||
|
||||
@@ -195,4 +199,9 @@ public class InterestRateChartData {
|
||||
return this.clientClassificationOptions;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPrimaryGroupingByAmount() {
|
||||
return this.isPrimaryGroupingByAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+16
-5
@@ -26,6 +26,7 @@ import static org.apache.fineract.portfolio.interestratechart.InterestRateChartA
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.endDateParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.idParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.productIdParamName;
|
||||
|
||||
@@ -98,6 +99,11 @@ public class InterestRateChartDataValidator {
|
||||
toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
|
||||
baseDataValidator.reset().parameter(endDateParamName).value(toDate).notNull();
|
||||
}
|
||||
|
||||
Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
|
||||
if (isPrimaryGroupingByAmount == null) {
|
||||
isPrimaryGroupingByAmount = false;
|
||||
}
|
||||
|
||||
if (fromDate != null && toDate != null) {
|
||||
if (fromDate.isAfter(toDate)) {
|
||||
@@ -106,7 +112,7 @@ public class InterestRateChartDataValidator {
|
||||
}
|
||||
|
||||
// validate chart Slabs
|
||||
validateChartSlabs(element, baseDataValidator);
|
||||
validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
|
||||
}
|
||||
|
||||
public void validateUpdate(final String json) {
|
||||
@@ -151,6 +157,11 @@ public class InterestRateChartDataValidator {
|
||||
toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
|
||||
baseDataValidator.reset().parameter(endDateParamName).value(toDate).notNull();
|
||||
}
|
||||
|
||||
Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
|
||||
if (isPrimaryGroupingByAmount == null) {
|
||||
isPrimaryGroupingByAmount = false;
|
||||
}
|
||||
|
||||
if (fromDate != null && toDate != null) {
|
||||
if (fromDate.isAfter(toDate)) {
|
||||
@@ -158,7 +169,7 @@ public class InterestRateChartDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
validateChartSlabs(element, baseDataValidator);
|
||||
validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
|
||||
|
||||
}
|
||||
|
||||
@@ -166,7 +177,7 @@ public class InterestRateChartDataValidator {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void validateChartSlabs(JsonElement element, DataValidatorBuilder baseDataValidator) {
|
||||
private void validateChartSlabs(JsonElement element, DataValidatorBuilder baseDataValidator,final boolean isPrimaryGroupingByAmount) {
|
||||
|
||||
if (element.isJsonObject()) {
|
||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||
@@ -178,9 +189,9 @@ public class InterestRateChartDataValidator {
|
||||
if (this.fromApiJsonHelper.parameterExists(idParamName, interstRateChartElement)) {
|
||||
final Long id = this.fromApiJsonHelper.extractLongNamed(idParamName, interstRateChartElement);
|
||||
baseDataValidator.reset().parameter(idParamName).value(id).notNull().integerGreaterThanZero();
|
||||
this.chartSlabDataValidator.validateChartSlabsUpdate(interstRateChartElement, baseDataValidator, locale);
|
||||
this.chartSlabDataValidator.validateChartSlabsUpdate(interstRateChartElement, baseDataValidator, locale, isPrimaryGroupingByAmount);
|
||||
} else {
|
||||
this.chartSlabDataValidator.validateChartSlabsCreate(interstRateChartElement, baseDataValidator, locale);
|
||||
this.chartSlabDataValidator.validateChartSlabsCreate(interstRateChartElement, baseDataValidator, locale, isPrimaryGroupingByAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
-21
@@ -84,12 +84,14 @@ public class InterestRateChartSlabDataValidator {
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
|
||||
baseDataValidator.reset().parameter(currencyCodeParamName).value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
|
||||
validateChartSlabsCreate(element, baseDataValidator, locale);
|
||||
final Boolean isPrimaryGroupingByAmount = null;
|
||||
validateChartSlabsCreate(element, baseDataValidator, locale, isPrimaryGroupingByAmount);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateChartSlabsCreate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale) {
|
||||
public void validateChartSlabsCreate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale,
|
||||
final Boolean isPrimaryGroupingByAmount) {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
|
||||
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
|
||||
@@ -97,17 +99,25 @@ public class InterestRateChartSlabDataValidator {
|
||||
}
|
||||
|
||||
final Integer periodType = this.fromApiJsonHelper.extractIntegerNamed(periodTypeParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull()
|
||||
.isOneOfTheseValues(PeriodFrequencyType.integerValues());
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(periodTypeParamName, element)) {
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType)
|
||||
.isOneOfTheseValues(PeriodFrequencyType.integerValues());
|
||||
}
|
||||
Integer toPeriod = null;
|
||||
|
||||
final Integer fromPeriod = this.fromApiJsonHelper.extractIntegerNamed(fromPeriodParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull().integerZeroOrGreater();
|
||||
if (this.fromApiJsonHelper.parameterExists(fromPeriodParamName, element)) {
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).integerZeroOrGreater();
|
||||
}
|
||||
|
||||
if ((isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) || (periodType != null || fromPeriod != null)) {
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull();
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(toPeriodParamName, element)) {
|
||||
toPeriod = this.fromApiJsonHelper.extractIntegerNamed(toPeriodParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).notNull().integerZeroOrGreater();
|
||||
baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromPeriod != null && toPeriod != null) {
|
||||
@@ -115,21 +125,26 @@ public class InterestRateChartSlabDataValidator {
|
||||
baseDataValidator.parameter(fromPeriodParamName).value(fromPeriod).failWithCode("fromperiod.greater.than.to.period");
|
||||
}
|
||||
}
|
||||
BigDecimal amountRangeFrom = null;
|
||||
BigDecimal amountRangeTo = null;
|
||||
final BigDecimal amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
|
||||
final BigDecimal amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
|
||||
if (this.fromApiJsonHelper.parameterExists(amountRangeFromParamName, element)) {
|
||||
amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).zeroOrPositiveAmount();
|
||||
if (isPrimaryGroupingByAmount != null && isPrimaryGroupingByAmount) {
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(amountRangeToParamName, element)) {
|
||||
amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).positiveAmount();
|
||||
}
|
||||
|
||||
if (amountRangeFrom == null && fromPeriod == null) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("fromperiod.or.amountRangeFrom.required");
|
||||
}
|
||||
|
||||
if (amountRangeFrom != null && amountRangeTo != null) {
|
||||
if (amountRangeFrom.compareTo(amountRangeTo) > 1) {
|
||||
baseDataValidator.parameter(fromPeriodParamName).value(fromPeriod).failWithCode("fromperiod.greater.than.toperiod");
|
||||
baseDataValidator.parameter(amountRangeFromParamName).value(fromPeriod).failWithCode("from.amount.greater.than.to.amount");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,12 +167,14 @@ public class InterestRateChartSlabDataValidator {
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
final JsonObject objectElement = element.getAsJsonObject();
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(objectElement);
|
||||
validateChartSlabsUpdate(element, baseDataValidator, locale);
|
||||
final Boolean isPrimaryGroupingByAmount = null;
|
||||
validateChartSlabsUpdate(element, baseDataValidator, locale, isPrimaryGroupingByAmount);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateChartSlabsUpdate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale) {
|
||||
public void validateChartSlabsUpdate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale,
|
||||
final Boolean isPrimaryGroupingByAmount) {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
|
||||
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
|
||||
@@ -166,8 +183,12 @@ public class InterestRateChartSlabDataValidator {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(periodTypeParamName, element)) {
|
||||
final Integer periodType = this.fromApiJsonHelper.extractIntegerNamed(periodTypeParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull()
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType)
|
||||
.isOneOfTheseValues(PeriodFrequencyType.integerValues());
|
||||
if (isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) {
|
||||
baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Integer fromPeriod = null;
|
||||
@@ -175,12 +196,15 @@ public class InterestRateChartSlabDataValidator {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(fromPeriodParamName, element)) {
|
||||
fromPeriod = this.fromApiJsonHelper.extractIntegerNamed(fromPeriodParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull().integerGreaterThanNumber(-1);
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).integerZeroOrGreater();
|
||||
if (isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) {
|
||||
baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(toPeriodParamName, element)) {
|
||||
toPeriod = this.fromApiJsonHelper.extractIntegerNamed(toPeriodParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).notNull().integerGreaterThanNumber(-1);
|
||||
baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromPeriod != null && toPeriod != null) {
|
||||
@@ -192,12 +216,15 @@ public class InterestRateChartSlabDataValidator {
|
||||
BigDecimal amountRangeTo = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(amountRangeFromParamName, element)) {
|
||||
amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).zeroOrPositiveAmount();
|
||||
if (isPrimaryGroupingByAmount != null && isPrimaryGroupingByAmount) {
|
||||
baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(amountRangeToParamName, element)) {
|
||||
amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
|
||||
baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).positiveAmount();
|
||||
}
|
||||
|
||||
if (amountRangeFrom != null && amountRangeTo != null) {
|
||||
|
||||
+73
-10
@@ -51,6 +51,7 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants;
|
||||
import org.apache.fineract.portfolio.interestratechart.InterestRateChartSlabApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@@ -82,12 +83,11 @@ public class InterestRateChart extends AbstractPersistable<Long> {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(INTERESTRATE_CHART_RESOURCE_NAME);
|
||||
|
||||
this.chartFields = chartFields;
|
||||
// validate before setting the other fields
|
||||
this.validateChartSlabs(baseDataValidator);
|
||||
this.throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
this.chartFields = chartFields;
|
||||
this.addChartSlabs(interestRateChartSlabs);
|
||||
|
||||
}
|
||||
@@ -97,22 +97,85 @@ public class InterestRateChart extends AbstractPersistable<Long> {
|
||||
|
||||
Integer tmpPeriodType = null;
|
||||
List<InterestRateChartSlab> chartSlabsList = new ArrayList<>(chartSlabs);
|
||||
boolean isPrimaryGroupingByAmount = this.chartFields.isPrimaryGroupingByAmount();
|
||||
chartSlabsList.sort(new InterestRateChartSlabComparator<InterestRateChartSlab>(isPrimaryGroupingByAmount));
|
||||
boolean isPeriodChart = !isPrimaryGroupingByAmount;
|
||||
boolean isAmountChart = isPrimaryGroupingByAmount;
|
||||
|
||||
for (int i = 0; i < chartSlabsList.size(); i++) {
|
||||
InterestRateChartSlab iSlabs = chartSlabsList.get(i);
|
||||
if (tmpPeriodType == null) {
|
||||
if (!iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) {
|
||||
if (isPrimaryGroupingByAmount) {
|
||||
baseDataValidator.parameter(InterestRateChartSlabApiConstants.amountRangeFromParamName).failWithCode("cannot.be.blank");
|
||||
} else {
|
||||
baseDataValidator.parameter(InterestRateChartSlabApiConstants.fromPeriodParamName).failWithCode("cannot.be.blank");
|
||||
}
|
||||
|
||||
} else if (i > 0) {
|
||||
if (isPeriodChart ^ iSlabs.slabFields().fromPeriod() != null) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.incomplete");
|
||||
isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null;
|
||||
}
|
||||
if (isAmountChart ^ iSlabs.slabFields().getAmountRangeFrom() != null) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.incomplete");
|
||||
isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
tmpPeriodType = iSlabs.slabFields().periodType();
|
||||
} else if (!iSlabs.slabFields().periodType().equals(tmpPeriodType)) {
|
||||
if (iSlabs.slabFields().isNotProperChartStart()) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.start.incorrect", iSlabs.slabFields()
|
||||
.fromPeriod(), iSlabs.slabFields().getAmountRangeFrom());
|
||||
}
|
||||
isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null;
|
||||
isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null;
|
||||
} else if (iSlabs.slabFields().periodType() != null && !iSlabs.slabFields().periodType().equals(tmpPeriodType)) {
|
||||
baseDataValidator.parameter(periodTypeParamName).value(iSlabs.slabFields().periodType())
|
||||
.failWithCode("period.type.is.not.same", tmpPeriodType);
|
||||
}
|
||||
for (int j = i + 1; j < chartSlabsList.size(); j++) {
|
||||
InterestRateChartSlab jSlabs = chartSlabsList.get(j);
|
||||
if (iSlabs.slabFields().isPeriodOverlapping(jSlabs.slabFields())) {
|
||||
baseDataValidator
|
||||
.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.overlapping", iSlabs.slabFields().fromPeriod(),
|
||||
iSlabs.slabFields().toPeriod(), jSlabs.slabFields().fromPeriod(), jSlabs.slabFields().toPeriod());
|
||||
if (i + 1 < chartSlabsList.size()) {
|
||||
InterestRateChartSlab nextSlabs = chartSlabsList.get(i + 1);
|
||||
if (iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)
|
||||
&& nextSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) {
|
||||
if (iSlabs.slabFields().isRateChartOverlapping(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.overlapping", iSlabs.slabFields()
|
||||
.fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields()
|
||||
.toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs
|
||||
.slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo());
|
||||
} else if (iSlabs.slabFields().isRateChartHasGap(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.has.gap", iSlabs.slabFields()
|
||||
.fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields()
|
||||
.toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs
|
||||
.slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo());
|
||||
}
|
||||
if (isPrimaryGroupingByAmount) {
|
||||
if (!iSlabs.slabFields().isAmountSame(nextSlabs.slabFields())) {
|
||||
if (InterestRateChartSlabFields.isNotProperPeriodStart(nextSlabs.slabFields())) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.start.incorrect",
|
||||
nextSlabs.slabFields().toPeriod());
|
||||
}
|
||||
if (iSlabs.slabFields().toPeriod() != null) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.end.incorrect", iSlabs
|
||||
.slabFields().toPeriod());
|
||||
}
|
||||
|
||||
}
|
||||
} else if (!iSlabs.slabFields().isPeriodsSame(nextSlabs.slabFields())) {
|
||||
if (InterestRateChartSlabFields.isNotProperAmountStart(nextSlabs.slabFields())) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.start.incorrect", nextSlabs
|
||||
.slabFields().getAmountRangeFrom());
|
||||
}
|
||||
if (iSlabs.slabFields().getAmountRangeTo() != null) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.end.incorrect", iSlabs
|
||||
.slabFields().getAmountRangeTo());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else if (iSlabs.slabFields().isNotProperPriodEnd()) {
|
||||
baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.end.incorrect",
|
||||
iSlabs.slabFields().toPeriod(), iSlabs.slabFields().getAmountRangeTo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-10
@@ -24,6 +24,7 @@ import static org.apache.fineract.portfolio.interestratechart.InterestRateChartA
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.localeParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
@@ -56,19 +57,24 @@ public class InterestRateChartFields {
|
||||
@Column(name = "end_date", nullable = false)
|
||||
private Date endDate;
|
||||
|
||||
@Column(name = "is_primary_grouping_by_amount", nullable = false)
|
||||
private boolean isPrimaryGroupingByAmount;
|
||||
|
||||
protected InterestRateChartFields() {
|
||||
//
|
||||
}
|
||||
|
||||
public static InterestRateChartFields createNew(String name, String description, LocalDate fromDate, LocalDate toDate) {
|
||||
return new InterestRateChartFields(name, description, fromDate, toDate);
|
||||
public static InterestRateChartFields createNew(String name, String description, LocalDate fromDate, LocalDate toDate,
|
||||
boolean isPrimaryGroupingByAmount) {
|
||||
return new InterestRateChartFields(name, description, fromDate, toDate, isPrimaryGroupingByAmount);
|
||||
}
|
||||
|
||||
private InterestRateChartFields(String name, String description, LocalDate fromDate, LocalDate toDate) {
|
||||
private InterestRateChartFields(String name, String description, LocalDate fromDate, LocalDate toDate, boolean isPrimaryGroupingByAmount) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.fromDate = fromDate.toDate();
|
||||
this.endDate = (toDate == null) ? null : toDate.toDate();
|
||||
this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
|
||||
}
|
||||
|
||||
public void update(JsonCommand command, final Map<String, Object> actualChanges, final DataValidatorBuilder baseDataValidator) {
|
||||
@@ -106,6 +112,12 @@ public class InterestRateChartFields {
|
||||
this.endDate = newValue.toDate();
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(isPrimaryGroupingByAmountParamName, this.isPrimaryGroupingByAmount)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isPrimaryGroupingByAmountParamName);
|
||||
actualChanges.put(isPrimaryGroupingByAmountParamName, newValue);
|
||||
this.isPrimaryGroupingByAmount = newValue;
|
||||
}
|
||||
|
||||
if (isFromDateAfterToDate()) {
|
||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||
}
|
||||
@@ -144,20 +156,22 @@ public class InterestRateChartFields {
|
||||
final LocalDate thatFromDate = that.getFromDateAsLocalDate();
|
||||
LocalDate thatEndDate = that.getEndDateAsLocalDate();
|
||||
thatEndDate = thatEndDate == null ? DateUtils.getLocalDateOfTenant() : thatEndDate;
|
||||
|
||||
|
||||
final LocalDateInterval thisInterval = LocalDateInterval.create(thisFromDate, thisEndDate);
|
||||
final LocalDateInterval thatInterval = LocalDateInterval.create(thatFromDate, thatEndDate);
|
||||
|
||||
if(thisInterval.containsPortionOf(thatInterval) || thatInterval.containsPortionOf(thisInterval)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (thisInterval.containsPortionOf(thatInterval) || thatInterval.containsPortionOf(thisInterval)) { return true; }
|
||||
return false;// no overlapping
|
||||
}
|
||||
|
||||
public boolean isApplicableChartFor(final LocalDate target){
|
||||
|
||||
public boolean isApplicableChartFor(final LocalDate target) {
|
||||
final LocalDate endDate = this.endDate == null ? DateUtils.getLocalDateOfTenant() : this.getEndDateAsLocalDate();
|
||||
final LocalDateInterval interval = LocalDateInterval.create(getFromDateAsLocalDate(), endDate);
|
||||
return interval.contains(target);
|
||||
}
|
||||
|
||||
public boolean isPrimaryGroupingByAmount() {
|
||||
return this.isPrimaryGroupingByAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.interestratechart.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChartSlabs;
|
||||
|
||||
/**
|
||||
* Sort InterestRateChartSlab by input range
|
||||
*/
|
||||
public class InterestRateChartSlabComparator<T> implements Comparator<T> {
|
||||
|
||||
private final boolean isPrimaryGroupingByAmount;
|
||||
|
||||
public InterestRateChartSlabComparator(final boolean isPrimaryGroupingByAmount) {
|
||||
this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(final T o1, final T o2) {
|
||||
int compareResult = 0;
|
||||
InterestRateChartSlabFields slabs1 = null;
|
||||
InterestRateChartSlabFields slabs2 = null;
|
||||
if (o1 instanceof InterestRateChartSlab) {
|
||||
slabs1 = ((InterestRateChartSlab) o1).slabFields();
|
||||
slabs2 = ((InterestRateChartSlab) o2).slabFields();
|
||||
} else if (o1 instanceof DepositAccountInterestRateChartSlabs) {
|
||||
slabs1 = ((DepositAccountInterestRateChartSlabs) o1).slabFields();
|
||||
slabs2 = ((DepositAccountInterestRateChartSlabs) o2).slabFields();
|
||||
} else {
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
if (slabs1.isPeriodsSame(slabs2) && slabs1.isAmountSame(slabs2)) {
|
||||
compareResult = 0;
|
||||
} else {
|
||||
if (isPrimaryGroupingByAmount) {
|
||||
if (slabs1.isAmountSame(slabs2)) {
|
||||
compareResult = comparePeriods(slabs1, slabs2);
|
||||
} else {
|
||||
compareResult = compareAmounts(slabs1, slabs2);
|
||||
}
|
||||
} else {
|
||||
if (slabs1.isPeriodsSame(slabs2)) {
|
||||
compareResult = compareAmounts(slabs1, slabs2);
|
||||
} else {
|
||||
compareResult = comparePeriods(slabs1, slabs2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
private int comparePeriods(final InterestRateChartSlabFields slabs1, InterestRateChartSlabFields slabs2) {
|
||||
int compareResult = 0;
|
||||
Integer periodFrom1 = slabs1.fromPeriod();
|
||||
Integer periodFrom2 = slabs2.fromPeriod();
|
||||
if (periodFrom1 != null && periodFrom2 != null) {
|
||||
compareResult = periodFrom1.compareTo(periodFrom2);
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
private int compareAmounts(final InterestRateChartSlabFields slabs1, InterestRateChartSlabFields slabs2) {
|
||||
int compareResult = 0;
|
||||
BigDecimal amountFrom1 = slabs1.getAmountRangeFrom();
|
||||
BigDecimal amountFrom2 = slabs2.getAmountRangeFrom();
|
||||
if (amountFrom1 != null && amountFrom2 != null) {
|
||||
compareResult = amountFrom1.compareTo(amountFrom2);
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
}
|
||||
+138
-10
@@ -51,15 +51,23 @@ public class InterestRateChartSlabFields {
|
||||
@Column(name = "period_type_enum", nullable = false)
|
||||
private Integer periodType;
|
||||
|
||||
@Column(name = "from_period", nullable = false)
|
||||
@Column(name = "from_period")
|
||||
private Integer fromPeriod;
|
||||
|
||||
@Column(name = "to_period", nullable = true)
|
||||
@Column(name = "to_period")
|
||||
private Integer toPeriod;
|
||||
|
||||
@Column(name = "amount_range_from", scale = 6, precision = 19)
|
||||
private BigDecimal amountRangeFrom;
|
||||
|
||||
public BigDecimal getAmountRangeFrom() {
|
||||
return this.amountRangeFrom;
|
||||
}
|
||||
|
||||
public BigDecimal getAmountRangeTo() {
|
||||
return this.amountRangeTo;
|
||||
}
|
||||
|
||||
@Column(name = "amount_range_to", scale = 6, precision = 19)
|
||||
private BigDecimal amountRangeTo;
|
||||
|
||||
@@ -84,7 +92,7 @@ public class InterestRateChartSlabFields {
|
||||
final Integer fromPeriod, final Integer toPeriod, final BigDecimal amountRangeFrom, final BigDecimal amountRangeTo,
|
||||
final BigDecimal annualInterestRate, final String currencyCode) {
|
||||
this.description = description;
|
||||
this.periodType = (periodFrequencyType == null) ? null : periodFrequencyType.getValue();
|
||||
this.periodType = (periodFrequencyType == null || periodFrequencyType.isInvalid()) ? null : periodFrequencyType.getValue();
|
||||
this.fromPeriod = fromPeriod;
|
||||
this.toPeriod = toPeriod;
|
||||
this.amountRangeFrom = amountRangeFrom;
|
||||
@@ -183,17 +191,129 @@ public class InterestRateChartSlabFields {
|
||||
return this.toPeriod;
|
||||
}
|
||||
|
||||
public boolean isPeriodOverlapping(final InterestRateChartSlabFields that) {
|
||||
if (that.toPeriod == null) {
|
||||
if (this.toPeriod == null) { return true; }
|
||||
return that.fromPeriod <= this.toPeriod;
|
||||
public boolean isRateChartHasGap(final InterestRateChartSlabFields that, final boolean isPrimaryGroupingByAmount) {
|
||||
boolean isPeriodSame = isPeriodsSame(that);
|
||||
boolean isAmountSame = isAmountSame(that);
|
||||
boolean hasPeriods = this.fromPeriod != null || that.fromPeriod != null;
|
||||
boolean hasAmounts = this.amountRangeFrom != null || that.amountRangeFrom != null;
|
||||
if (isPrimaryGroupingByAmount) {
|
||||
if (isAmountSame) {
|
||||
if (hasPeriods) {
|
||||
if (this.toPeriod == null) { return true; }
|
||||
return isNotProperPeriodStart(that.fromPeriod);
|
||||
}
|
||||
} else {
|
||||
return isNotProperAmountStart(that.amountRangeFrom) || isNotProperPeriodStart(that);
|
||||
}
|
||||
} else {
|
||||
if (isPeriodSame) {
|
||||
if (hasAmounts) {
|
||||
if (this.amountRangeTo == null) { return true; }
|
||||
return isNotProperAmountStart(that.amountRangeFrom);
|
||||
}
|
||||
} else {
|
||||
return isNotProperPeriodStart(that.fromPeriod) || isNotProperAmountStart(that);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isValidChart(boolean isPrimaryGroupingByAmount) {
|
||||
return (!isPrimaryGroupingByAmount && this.fromPeriod != null) || (isPrimaryGroupingByAmount && this.amountRangeFrom != null);
|
||||
}
|
||||
|
||||
public boolean isNotProperChartStart() {
|
||||
return isNotProperPeriodStart(this) || isNotProperAmountStart(this);
|
||||
}
|
||||
|
||||
public static boolean isNotProperAmountStart(final InterestRateChartSlabFields interestRateChartSlabFields) {
|
||||
return interestRateChartSlabFields.amountRangeFrom != null
|
||||
&& (interestRateChartSlabFields.amountRangeFrom.compareTo(BigDecimal.ONE) != 0 && interestRateChartSlabFields.amountRangeFrom
|
||||
.compareTo(BigDecimal.ZERO) != 0);
|
||||
}
|
||||
|
||||
private boolean isNotProperAmountStart(final BigDecimal amount) {
|
||||
return this.amountRangeTo == null || (amount != null && amount.compareTo(this.amountRangeTo.add(BigDecimal.ONE)) != 0);
|
||||
}
|
||||
|
||||
private boolean isNotProperPeriodStart(final Integer period) {
|
||||
return this.toPeriod == null || (period != null && period.compareTo(this.toPeriod + 1) != 0);
|
||||
}
|
||||
|
||||
public static boolean isNotProperPeriodStart(InterestRateChartSlabFields interestRateChartSlabFields) {
|
||||
return interestRateChartSlabFields.fromPeriod != null
|
||||
&& !(interestRateChartSlabFields.fromPeriod.equals(1) || interestRateChartSlabFields.fromPeriod.equals(0));
|
||||
}
|
||||
|
||||
public boolean isNotProperPriodEnd() {
|
||||
return !(this.toPeriod == null && this.amountRangeTo == null);
|
||||
|
||||
}
|
||||
|
||||
public boolean isRateChartOverlapping(final InterestRateChartSlabFields that, final boolean isPrimaryGroupingByAmount) {
|
||||
boolean isPeriodOverLapping = isPeriodOverlapping(that);
|
||||
boolean isAmountOverLapping = isAmountOverlapping(that);
|
||||
boolean isPeriodSame = isPeriodsSame(that);
|
||||
boolean isAmountSame = isAmountSame(that);
|
||||
boolean isOverlapping = false;
|
||||
if (isPrimaryGroupingByAmount) {
|
||||
isOverlapping = (isAmountOverLapping && !isAmountSame) || (isPeriodOverLapping && isAmountSame);
|
||||
} else {
|
||||
isOverlapping = (isPeriodOverLapping && !isPeriodSame) || (isAmountOverLapping && isPeriodSame);
|
||||
}
|
||||
|
||||
return isOverlapping;
|
||||
}
|
||||
|
||||
private boolean isPeriodOverlapping(final InterestRateChartSlabFields that) {
|
||||
if (isIntegerSame(that.toPeriod, this.toPeriod)) {
|
||||
return true;
|
||||
} else if (isIntegerSame(that.fromPeriod, this.fromPeriod)) {
|
||||
return true;
|
||||
} else if (this.toPeriod == null) {
|
||||
return true;
|
||||
} else if (that.toPeriod == null) { return that.fromPeriod <= this.toPeriod; }
|
||||
return this.fromPeriod <= that.toPeriod && that.fromPeriod <= this.toPeriod;
|
||||
}
|
||||
|
||||
private boolean isAmountOverlapping(final InterestRateChartSlabFields that) {
|
||||
if (isBigDecimalSame(that.amountRangeFrom, this.amountRangeFrom)) {
|
||||
return true;
|
||||
} else if (isBigDecimalSame(that.amountRangeTo, this.amountRangeTo)) {
|
||||
return true;
|
||||
} else if (this.amountRangeTo == null) {
|
||||
return true;
|
||||
} else if (that.amountRangeTo == null) { return that.amountRangeFrom.compareTo(this.amountRangeTo) < 1; }
|
||||
return this.amountRangeFrom.compareTo(that.amountRangeTo) < 1 && that.amountRangeFrom.compareTo(this.amountRangeTo) < 1;
|
||||
}
|
||||
|
||||
public boolean isAmountSame(final InterestRateChartSlabFields that) {
|
||||
return isBigDecimalSame(this.amountRangeFrom, that.amountRangeFrom) && isBigDecimalSame(this.amountRangeTo, that.amountRangeTo);
|
||||
}
|
||||
|
||||
public boolean isPeriodsSame(final InterestRateChartSlabFields that) {
|
||||
return isIntegerSame(this.fromPeriod, that.fromPeriod) && isIntegerSame(this.toPeriod, that.toPeriod);
|
||||
}
|
||||
|
||||
public boolean isIntegerSame(final Integer obj1, final Integer obj2) {
|
||||
if (obj1 == null || obj2 == null) {
|
||||
if (obj1 == obj2) { return true; }
|
||||
return false;
|
||||
}
|
||||
return obj1.equals(obj2);
|
||||
}
|
||||
|
||||
public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) {
|
||||
if (obj1 == null || obj2 == null) {
|
||||
if (obj1 == obj2) { return true; }
|
||||
return false;
|
||||
}
|
||||
return obj1.compareTo(obj2) == 0;
|
||||
}
|
||||
|
||||
public boolean isBetweenPeriod(final LocalDate periodStartDate, final LocalDate periodEndDate) {
|
||||
final Integer compare = depositPeriod(periodStartDate, periodEndDate);
|
||||
return (compare < this.fromPeriod || (this.toPeriod != null && compare > this.toPeriod)) ? false : true;
|
||||
return isPeriodBetween(compare);
|
||||
}
|
||||
|
||||
public boolean isAmountRangeProvided() {
|
||||
@@ -233,8 +353,16 @@ public class InterestRateChartSlabFields {
|
||||
returnValue = depositAmount.compareTo(amountRangeFrom) >= 0 && depositAmount.compareTo(amountRangeTo) <= 0;
|
||||
} else if (amountRangeFrom != null) {
|
||||
returnValue = depositAmount.compareTo(amountRangeFrom) >= 0;
|
||||
} else if (amountRangeTo != null) {
|
||||
returnValue = depositAmount.compareTo(amountRangeTo) <= 0;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean isPeriodBetween(final Integer periods) {
|
||||
boolean returnValue = true;
|
||||
if (fromPeriod != null && toPeriod != null) {
|
||||
returnValue = periods.compareTo(fromPeriod) >= 0 && periods.compareTo(toPeriod) <= 0;
|
||||
} else if (fromPeriod != null) {
|
||||
returnValue = periods.compareTo(fromPeriod) >= 0;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
+16
-14
@@ -22,6 +22,7 @@ import static org.apache.fineract.portfolio.interestratechart.InterestRateChartA
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.descriptionParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.endDateParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartSlabApiConstants.currencyCodeParamName;
|
||||
|
||||
@@ -65,33 +66,38 @@ public class InterestRateChartAssembler {
|
||||
* request
|
||||
*/
|
||||
public InterestRateChart assembleFrom(final JsonCommand command) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
@SuppressWarnings("unused")
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(INTERESTRATE_CHART_RESOURCE_NAME);
|
||||
final JsonElement element = command.parsedJson();
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
|
||||
final InterestRateChart newChart = this.assembleFrom(element, currencyCode);
|
||||
|
||||
final InterestRateChart newChart = this.assembleFrom(element, currencyCode, baseDataValidator);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
return newChart;
|
||||
}
|
||||
|
||||
public InterestRateChart assembleFrom(final JsonElement element, final String currencyCode) {
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
public InterestRateChart assembleFrom(final JsonElement element, final String currencyCode, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
|
||||
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
|
||||
final LocalDate fromDate = this.fromApiJsonHelper.extractLocalDateNamed(fromDateParamName, element);
|
||||
final LocalDate toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
|
||||
|
||||
Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
|
||||
if (isPrimaryGroupingByAmount == null) {
|
||||
isPrimaryGroupingByAmount = false;
|
||||
}
|
||||
|
||||
// assemble chart Slabs
|
||||
final Collection<InterestRateChartSlab> newChartSlabs = this.chartSlabAssembler.assembleChartSlabsFrom(element,
|
||||
currencyCode);
|
||||
final Collection<InterestRateChartSlab> newChartSlabs = this.chartSlabAssembler.assembleChartSlabsFrom(element, currencyCode);
|
||||
|
||||
final InterestRateChartFields fields = InterestRateChartFields.createNew(name, description, fromDate, toDate);
|
||||
final InterestRateChartFields fields = InterestRateChartFields.createNew(name, description, fromDate, toDate,
|
||||
isPrimaryGroupingByAmount);
|
||||
final InterestRateChart newChart = InterestRateChart.createNew(fields, newChartSlabs);
|
||||
newChart.validateChartSlabs(baseDataValidator);
|
||||
return newChart;
|
||||
}
|
||||
|
||||
@@ -100,8 +106,4 @@ public class InterestRateChartAssembler {
|
||||
.findOneWithNotFoundDetection(interestRateChartId);
|
||||
return interestRateChart;
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+23
-4
@@ -86,8 +86,21 @@ public class InterestRateChartReadPlatformServiceImpl implements InterestRateCha
|
||||
@Override
|
||||
public Collection<InterestRateChartData> retrieveAllWithSlabs(Long productId) {
|
||||
this.context.authenticatedUser();
|
||||
String sql = "select " + this.chartExtractor.schema() + " where sp.id = ? order by irc.id, ircd.id";
|
||||
return this.jdbcTemplate.query(sql, this.chartExtractor, new Object[] { productId });
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ");
|
||||
sql.append(this.chartExtractor.schema());
|
||||
sql.append(" where sp.id = ? order by irc.id, ");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END,");
|
||||
sql.append("ircd.from_period, ircd.to_period,");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END");
|
||||
|
||||
return this.jdbcTemplate.query(sql.toString(), this.chartExtractor, new Object[] { productId });
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,6 +190,7 @@ public class InterestRateChartReadPlatformServiceImpl implements InterestRateCha
|
||||
sqlBuilder
|
||||
.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription,")
|
||||
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
|
||||
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount, ")
|
||||
.append("ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, ")
|
||||
.append("ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, ")
|
||||
.append("ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, ")
|
||||
@@ -239,6 +253,7 @@ public class InterestRateChartReadPlatformServiceImpl implements InterestRateCha
|
||||
|
||||
sqlBuilder.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription, ")
|
||||
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
|
||||
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount, ")
|
||||
.append("sp.id as savingsProductId, sp.name as savingsProductName ").append("from ")
|
||||
.append("m_interest_rate_chart irc ")
|
||||
.append("left join m_deposit_product_interest_rate_chart dpirc on irc.id=dpirc.interest_rate_chart_id ")
|
||||
@@ -253,10 +268,11 @@ public class InterestRateChartReadPlatformServiceImpl implements InterestRateCha
|
||||
final String description = rs.getString("ircDescription");
|
||||
final LocalDate fromDate = JdbcSupport.getLocalDate(rs, "ircFromDate");
|
||||
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "ircEndDate");
|
||||
final boolean isPrimaryGroupingByAmount = rs.getBoolean("isPrimaryGroupingByAmount");
|
||||
final Long savingsProductId = JdbcSupport.getLongDefaultToNullIfZero(rs, "savingsProductId");
|
||||
final String savingsProductName = rs.getString("savingsProductName");
|
||||
|
||||
return InterestRateChartData.instance(id, name, description, fromDate, endDate, savingsProductId, savingsProductName);
|
||||
return InterestRateChartData.instance(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId, savingsProductName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -299,7 +315,10 @@ public class InterestRateChartReadPlatformServiceImpl implements InterestRateCha
|
||||
final Integer fromPeriod = JdbcSupport.getInteger(rs, "ircdFromPeriod");
|
||||
final Integer toPeriod = JdbcSupport.getInteger(rs, "ircdToPeriod");
|
||||
final Integer periodTypeId = JdbcSupport.getInteger(rs, "ircdPeriodTypeId");
|
||||
final EnumOptionData periodType = InterestRateChartEnumerations.periodType(periodTypeId);
|
||||
EnumOptionData periodType = null;
|
||||
if (periodTypeId != null) {
|
||||
periodType = InterestRateChartEnumerations.periodType(periodTypeId);
|
||||
}
|
||||
final BigDecimal amountRangeFrom = rs.getBigDecimal("ircdAmountRangeFrom");
|
||||
final BigDecimal amountRangeTo = rs.getBigDecimal("ircdAmountRangeTo");
|
||||
final BigDecimal annualInterestRate = rs.getBigDecimal("ircdAnnualInterestRate");
|
||||
|
||||
+35
-32
@@ -18,9 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
@@ -38,10 +37,11 @@ public class DepositAccountInterestRateChartData {
|
||||
private final String description;
|
||||
private final LocalDate fromDate;
|
||||
private final LocalDate endDate;
|
||||
private final boolean isPrimaryGroupingByAmount;
|
||||
private final Long accountId;
|
||||
private final String accountNumber;
|
||||
// associations
|
||||
private Set<DepositAccountInterestRateChartSlabData> chartSlabs;
|
||||
private Collection<DepositAccountInterestRateChartSlabData> chartSlabs;
|
||||
|
||||
// template
|
||||
private final Collection<EnumOptionData> periodTypes;
|
||||
@@ -54,8 +54,8 @@ public class DepositAccountInterestRateChartData {
|
||||
private final Collection<CodeValueData> clientClassificationOptions;
|
||||
|
||||
public static DepositAccountInterestRateChartData instance(Long id, String name, String description, LocalDate fromDate,
|
||||
LocalDate endDate, Long accountId, String accountNumber, Set<DepositAccountInterestRateChartSlabData> chartSlabs,
|
||||
Collection<EnumOptionData> periodTypes) {
|
||||
LocalDate endDate, boolean isPrimaryGroupingByAmount, Long accountId, String accountNumber,
|
||||
Collection<DepositAccountInterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes) {
|
||||
|
||||
final Collection<EnumOptionData> entityTypeOptions = null;
|
||||
final Collection<EnumOptionData> attributeNameOptions = null;
|
||||
@@ -64,17 +64,17 @@ public class DepositAccountInterestRateChartData {
|
||||
final Collection<CodeValueData> genderOptions = null;
|
||||
final Collection<CodeValueData> clientTypeOptions = null;
|
||||
final Collection<CodeValueData> clientClassificationOptions = null;
|
||||
return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, accountId, accountNumber, chartSlabs,
|
||||
periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
|
||||
clientTypeOptions, clientClassificationOptions);
|
||||
return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, accountId,
|
||||
accountNumber, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
|
||||
incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
}
|
||||
|
||||
public static DepositAccountInterestRateChartData from(InterestRateChartData productChartData) {
|
||||
final Long id = null;
|
||||
final Long accountId = null;
|
||||
final String accountNumber = null;
|
||||
Set<DepositAccountInterestRateChartSlabData> fromProdChartSlabs = new HashSet<>();
|
||||
Set<InterestRateChartSlabData> productChartSlabDatas = productChartData.chartSlabs();
|
||||
Collection<DepositAccountInterestRateChartSlabData> fromProdChartSlabs = new ArrayList<>();
|
||||
Collection<InterestRateChartSlabData> productChartSlabDatas = productChartData.chartSlabs();
|
||||
if (productChartSlabDatas != null) {
|
||||
for (InterestRateChartSlabData productChartSlabData : productChartSlabDatas) {
|
||||
fromProdChartSlabs.add(DepositAccountInterestRateChartSlabData.from(productChartSlabData));
|
||||
@@ -82,20 +82,20 @@ public class DepositAccountInterestRateChartData {
|
||||
}
|
||||
|
||||
return new DepositAccountInterestRateChartData(id, productChartData.name(), productChartData.description(),
|
||||
productChartData.fromDate(), productChartData.endDate(), accountId, accountNumber, fromProdChartSlabs,
|
||||
productChartData.periodTypes(), productChartData.entityTypeOptions(), productChartData.attributeNameOptions(),
|
||||
productChartData.conditionTypeOptions(), productChartData.incentiveTypeOptions(), productChartData.genderOptions(),
|
||||
productChartData.clientTypeOptions(), productChartData.clientClassificationOptions());
|
||||
productChartData.fromDate(), productChartData.endDate(), productChartData.isPrimaryGroupingByAmount(), accountId,
|
||||
accountNumber, fromProdChartSlabs, productChartData.periodTypes(), productChartData.entityTypeOptions(),
|
||||
productChartData.attributeNameOptions(), productChartData.conditionTypeOptions(), productChartData.incentiveTypeOptions(),
|
||||
productChartData.genderOptions(), productChartData.clientTypeOptions(), productChartData.clientClassificationOptions());
|
||||
}
|
||||
|
||||
public static DepositAccountInterestRateChartData withSlabs(DepositAccountInterestRateChartData interestRateChartData,
|
||||
Set<DepositAccountInterestRateChartSlabData> chartSlabs) {
|
||||
Collection<DepositAccountInterestRateChartSlabData> chartSlabs) {
|
||||
return new DepositAccountInterestRateChartData(interestRateChartData.id, interestRateChartData.name,
|
||||
interestRateChartData.description, interestRateChartData.fromDate, interestRateChartData.endDate,
|
||||
interestRateChartData.accountId, interestRateChartData.accountNumber, chartSlabs, interestRateChartData.periodTypes,
|
||||
interestRateChartData.entityTypeOptions, interestRateChartData.attributeNameOptions,
|
||||
interestRateChartData.conditionTypeOptions, interestRateChartData.incentiveTypeOptions,
|
||||
interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
|
||||
interestRateChartData.isPrimaryGroupingByAmount, interestRateChartData.accountId, interestRateChartData.accountNumber,
|
||||
chartSlabs, interestRateChartData.periodTypes, interestRateChartData.entityTypeOptions,
|
||||
interestRateChartData.attributeNameOptions, interestRateChartData.conditionTypeOptions,
|
||||
interestRateChartData.incentiveTypeOptions, interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
|
||||
interestRateChartData.clientClassificationOptions);
|
||||
}
|
||||
|
||||
@@ -106,9 +106,9 @@ public class DepositAccountInterestRateChartData {
|
||||
final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
|
||||
return new DepositAccountInterestRateChartData(interestRateChartData.id, interestRateChartData.name,
|
||||
interestRateChartData.description, interestRateChartData.fromDate, interestRateChartData.endDate,
|
||||
interestRateChartData.accountId, interestRateChartData.accountNumber, interestRateChartData.chartSlabs, periodTypes,
|
||||
entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions,
|
||||
clientClassificationOptions);
|
||||
interestRateChartData.isPrimaryGroupingByAmount, interestRateChartData.accountId, interestRateChartData.accountNumber,
|
||||
interestRateChartData.chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
|
||||
incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
}
|
||||
|
||||
public static DepositAccountInterestRateChartData template(Collection<EnumOptionData> periodTypes,
|
||||
@@ -123,23 +123,26 @@ public class DepositAccountInterestRateChartData {
|
||||
final LocalDate endDate = null;
|
||||
final Long accountId = null;
|
||||
final String accountNumber = null;
|
||||
final Set<DepositAccountInterestRateChartSlabData> chartSlabs = null;
|
||||
return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, accountId, accountNumber, chartSlabs,
|
||||
periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
|
||||
clientTypeOptions, clientClassificationOptions);
|
||||
final boolean isPrimaryGroupingByAmount = false;
|
||||
final Collection<DepositAccountInterestRateChartSlabData> chartSlabs = null;
|
||||
return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, accountId,
|
||||
accountNumber, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
|
||||
incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
|
||||
}
|
||||
|
||||
private DepositAccountInterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
|
||||
Long accountId, String accountNumber, Set<DepositAccountInterestRateChartSlabData> chartSlabs,
|
||||
Collection<EnumOptionData> periodTypes, final Collection<EnumOptionData> entityTypeOptions,
|
||||
final Collection<EnumOptionData> attributeNameOptions, final Collection<EnumOptionData> conditionTypeOptions,
|
||||
final Collection<EnumOptionData> incentiveTypeOptions, final Collection<CodeValueData> genderOptions,
|
||||
final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
|
||||
final boolean isPrimaryGroupingByAmount, Long accountId, String accountNumber,
|
||||
Collection<DepositAccountInterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes,
|
||||
final Collection<EnumOptionData> entityTypeOptions, final Collection<EnumOptionData> attributeNameOptions,
|
||||
final Collection<EnumOptionData> conditionTypeOptions, final Collection<EnumOptionData> incentiveTypeOptions,
|
||||
final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
|
||||
final Collection<CodeValueData> clientClassificationOptions) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.fromDate = fromDate;
|
||||
this.endDate = endDate;
|
||||
this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
|
||||
this.chartSlabs = chartSlabs;
|
||||
this.accountId = accountId;
|
||||
this.accountNumber = accountNumber;
|
||||
@@ -155,7 +158,7 @@ public class DepositAccountInterestRateChartData {
|
||||
|
||||
public void addChartSlab(final DepositAccountInterestRateChartSlabData chartSlab) {
|
||||
if (this.chartSlabs == null) {
|
||||
this.chartSlabs = new HashSet<>();
|
||||
this.chartSlabs = new ArrayList<>();
|
||||
}
|
||||
|
||||
this.chartSlabs.add(chartSlab);
|
||||
|
||||
+47
-13
@@ -35,16 +35,24 @@ import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumb
|
||||
import org.apache.fineract.infrastructure.accountnumberformat.domain.EntityAccountType;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.apache.fineract.portfolio.calendar.domain.Calendar;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountOnClosureType;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
@@ -71,6 +79,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository,
|
||||
@@ -79,7 +88,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final DepositAccountAssembler depositAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService,
|
||||
final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
final ConfigurationDomainService configurationDomainService,
|
||||
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository) {
|
||||
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository,
|
||||
final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
this.savingsAccountRepository = savingsAccountRepository;
|
||||
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
||||
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
||||
@@ -89,6 +99,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.accountNumberFormatRepository = accountNumberFormatRepository;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -129,6 +140,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
boolean isAccountTransfer = false;
|
||||
final boolean isPreMatureClosure = false;
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
account.updateDepositAmount(transactionAmount);
|
||||
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate,
|
||||
transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction);
|
||||
|
||||
@@ -241,18 +253,15 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
if (onClosureType.isReinvest()) {
|
||||
RecurringDepositAccount reinvestedDeposit = account.reInvest(transactionAmount);
|
||||
depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
reinvestedDeposit.processAccountUponActivation(fmt, user);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
this.savingsAccountRepository.save(reinvestedDeposit);
|
||||
|
||||
Money amountForDeposit = reinvestedDeposit.activateWithBalance();
|
||||
if (amountForDeposit.isGreaterThanZero()) {
|
||||
handleRDDeposit(reinvestedDeposit, fmt, reinvestedDeposit.getActivationLocalDate(), amountForDeposit.getAmount(),
|
||||
paymentDetail, isRegularTransaction);
|
||||
}
|
||||
final CalendarInstance calendarInstance = getCalendarInstance(account, reinvestedDeposit);
|
||||
this.calendarInstanceRepository.save(calendarInstance);
|
||||
final Calendar calendar = calendarInstance.getCalendar();
|
||||
final PeriodFrequencyType frequencyType = CalendarFrequencyType.from(CalendarUtils.getFrequency(calendar.getRecurrence()));
|
||||
Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence());
|
||||
frequency = frequency == -1 ? 1 : frequency;
|
||||
reinvestedDeposit.generateSchedule(frequencyType, frequency, calendar);
|
||||
reinvestedDeposit.processAccountUponActivation(fmt, user);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
this.savingsAccountRepository.save(reinvestedDeposit);
|
||||
@@ -292,6 +301,31 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
return savingsTransactionId;
|
||||
}
|
||||
|
||||
private CalendarInstance getCalendarInstance(final RecurringDepositAccount account, RecurringDepositAccount reinvestedDeposit) {
|
||||
CalendarInstance calendarInstance = null;
|
||||
CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||
account.getId(), CalendarEntityType.SAVINGS.getValue(), CalendarType.COLLECTION.getValue());
|
||||
if (account.isCalendarInherited()) {
|
||||
calendarInstance = CalendarInstance.from(parentCalendarInstance.getCalendar(), account.getId(),
|
||||
CalendarEntityType.SAVINGS.getValue());
|
||||
} else {
|
||||
LocalDate calendarStartDate = reinvestedDeposit.depositStartDate();
|
||||
Calendar parentCalendar = parentCalendarInstance.getCalendar();
|
||||
final String recurrence = parentCalendar.getRecurrence();
|
||||
final String title = "recurring_savings_" + reinvestedDeposit.getId();
|
||||
final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(),
|
||||
recurrence);
|
||||
calendarInstance = CalendarInstance.from(calendar, reinvestedDeposit.getId(), CalendarEntityType.SAVINGS.getValue());
|
||||
}
|
||||
if (calendarInstance == null) {
|
||||
final String defaultUserMessage = "No valid recurring details available for recurring depost account creation.";
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.recurring.deposit.account.cannot.create.no.valid.recurring.details.available", defaultUserMessage,
|
||||
account.clientId());
|
||||
}
|
||||
return calendarInstance;
|
||||
}
|
||||
|
||||
private void autoGenerateAccountNumber(final SavingsAccount account) {
|
||||
if (account.isAccountNumberRequiresAutoGeneration()) {
|
||||
final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.SAVINGS);
|
||||
|
||||
+5
@@ -92,6 +92,7 @@ public class DepositAccountInterestRateChart extends AbstractPersistable<Long> {
|
||||
if (this.chartSlabs == null) {
|
||||
this.chartSlabs = new HashSet<>();
|
||||
}
|
||||
|
||||
return this.chartSlabs;
|
||||
}
|
||||
|
||||
@@ -153,4 +154,8 @@ public class DepositAccountInterestRateChart extends AbstractPersistable<Long> {
|
||||
|
||||
return effectiveInterestRate;
|
||||
}
|
||||
|
||||
public boolean isPrimaryGroupingByAmount() {
|
||||
return this.chartFields.isPrimaryGroupingByAmount();
|
||||
}
|
||||
}
|
||||
+23
-5
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.adjustAdvanceTowardsFuturePaymentsParamName;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.allowWithdrawalParamName;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.chartsParamName;
|
||||
@@ -52,11 +54,16 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalA
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
@@ -147,7 +154,11 @@ public class DepositProductAssembler {
|
||||
// Savings product charges
|
||||
final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
|
||||
// Interest rate charts
|
||||
final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode());
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode(), baseDataValidator);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
if (interestRate == null) {
|
||||
interestRate = BigDecimal.ZERO;
|
||||
}
|
||||
@@ -164,6 +175,10 @@ public class DepositProductAssembler {
|
||||
return fixedDepositProduct;
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
public RecurringDepositProduct assembleRecurringDepositProduct(final JsonCommand command) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed(nameParamName);
|
||||
@@ -225,7 +240,11 @@ public class DepositProductAssembler {
|
||||
// Savings product charges
|
||||
final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
|
||||
// Interest rate charts
|
||||
final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode());
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode(), baseDataValidator);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
if (interestRate == null) {
|
||||
interestRate = BigDecimal.ZERO;
|
||||
@@ -435,15 +454,14 @@ public class DepositProductAssembler {
|
||||
return charges;
|
||||
}
|
||||
|
||||
private Set<InterestRateChart> assembleListOfCharts(JsonCommand command, String currencyCode) {
|
||||
private Set<InterestRateChart> assembleListOfCharts(JsonCommand command, String currencyCode, DataValidatorBuilder baseDataValidator) {
|
||||
final Set<InterestRateChart> charts = new HashSet<>();
|
||||
|
||||
if (command.parameterExists(chartsParamName)) {
|
||||
final JsonArray chartsArray = command.arrayOfParameterNamed(chartsParamName);
|
||||
if (chartsArray != null) {
|
||||
for (int i = 0; i < chartsArray.size(); i++) {
|
||||
final JsonObject interstRateChartElement = chartsArray.get(i).getAsJsonObject();
|
||||
InterestRateChart chart = this.chartAssembler.assembleFrom(interstRateChartElement, currencyCode);
|
||||
InterestRateChart chart = this.chartAssembler.assembleFrom(interstRateChartElement, currencyCode, baseDataValidator);
|
||||
charts.add(chart);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ public class FixedDepositProduct extends SavingsProduct {
|
||||
}
|
||||
} else {
|
||||
// assemble chart
|
||||
final InterestRateChart newChart = this.chartAssembler.assembleFrom(chartElement, this.currency().getCode());
|
||||
final InterestRateChart newChart = this.chartAssembler.assembleFrom(chartElement, this.currency().getCode(), baseDataValidator);
|
||||
this.addChart(newChart);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-6
@@ -174,12 +174,29 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
final Map<String, Object> termAndPreClosureChanges = accountTermAndPreClosure.update(command, baseDataValidator);
|
||||
actualChanges.putAll(termAndPreClosureChanges);
|
||||
recurringDetail.update(command);
|
||||
|
||||
validateDomainRules(baseDataValidator);
|
||||
super.validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator);
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void updateDepositAmount() {
|
||||
BigDecimal recurringAmount = getRecurringDetail().mandatoryRecommendedDepositAmount();
|
||||
Integer numberOfDepositPeriods = depositScheduleInstallments().size();
|
||||
if (this.accountTermAndPreClosure.depositPeriod() != null && recurringAmount != null && numberOfDepositPeriods != null) {
|
||||
BigDecimal depositAmount = Money.of(product.currency(), recurringAmount).multipliedBy(numberOfDepositPeriods)
|
||||
.plus(this.minRequiredOpeningBalance).getAmount();
|
||||
accountTermAndPreClosure.updateDepositAmount(depositAmount);
|
||||
} else if (accountTermAndPreClosure.depositAmount() == null) {
|
||||
accountTermAndPreClosure.updateDepositAmount(Money.zero(product.currency()).getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
public void updateDepositAmount(final BigDecimal depositAmount) {
|
||||
if (this.accountTermAndPreClosure.depositPeriod() == null) {
|
||||
accountTermAndPreClosure.updateDepositAmount(accountTermAndPreClosure.depositAmount().add(depositAmount));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BigDecimal getEffectiveInterestRateAsFraction(final MathContext mc, final LocalDate interestPostingUpToDate) {
|
||||
boolean isPreMatureClosure = false;
|
||||
@@ -207,7 +224,7 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
if (depositCloseDate == null) {
|
||||
depositCloseDate = LocalDate.now();
|
||||
depositCloseDate = DateUtils.getLocalDateOfTenant();
|
||||
}
|
||||
|
||||
final BigDecimal depositAmount = accountTermAndPreClosure.depositAmount();
|
||||
@@ -966,8 +983,8 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
.failWithCode("deposit.period.must.be.greater.than.lock.in.period",
|
||||
"Deposit period must be greater than account lock-in period.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (firstDepositDateBeforeAccountSubmittedOrActivationDate()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"expected.first.deposit.date.must.be.after.account.submitted.or.activation.date");
|
||||
@@ -989,7 +1006,7 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME);
|
||||
LocalDate maturityDate = calculateMaturityDate();
|
||||
if (this.chart != null && maturityDate != null) {
|
||||
if (this.chart != null) {
|
||||
final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate();
|
||||
LocalDate chartEndDate = this.chart.getEndDateAsLocalDate();
|
||||
chartEndDate = chartEndDate == null ? DateUtils.getLocalDateOfTenant() : chartEndDate;
|
||||
@@ -999,7 +1016,11 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available.for.date.range");
|
||||
}
|
||||
|
||||
final BigDecimal maturityAmount = this.accountTermAndPreClosure.maturityAmount();
|
||||
if (maturityDate == null) {
|
||||
maturityDate = DateUtils.getLocalDateOfTenant();
|
||||
}
|
||||
|
||||
final BigDecimal maturityAmount = this.accountTermAndPreClosure.depositAmount();
|
||||
BigDecimal applicableInterestRate = this.chart.getApplicableInterestRate(maturityAmount, depositStartDate(), maturityDate,
|
||||
this.client);
|
||||
|
||||
@@ -1012,7 +1033,7 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
baseDataValidator.reset().parameter(DepositsApiConstants.nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate)
|
||||
.failWithCodeNoParameterAddedToErrorCode("interest.chart.or.nominal.interest.rate.required");
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
/**
|
||||
* final boolean recurringFrequencyBeforeDepositPeriod =
|
||||
* recurringFrequencyBeforeDepositPeriod();
|
||||
@@ -1117,6 +1138,7 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
installmentDate = DepositAccountUtils.calculateNextDepositDate(installmentDate, frequency, recurringEvery);
|
||||
installmentNumber += 1;
|
||||
}
|
||||
updateDepositAmount();
|
||||
}
|
||||
|
||||
private LocalDate calcualteScheduleTillDate(final PeriodFrequencyType frequency, final Integer recurringEvery) {
|
||||
|
||||
+34
-6
@@ -90,8 +90,20 @@ public class DepositAccountInterestRateChartReadPlatformServiceImpl implements D
|
||||
@Override
|
||||
public DepositAccountInterestRateChartData retrieveOneWithSlabs(Long chartId) {
|
||||
this.context.authenticatedUser();
|
||||
final String sql = "select " + this.chartExtractor.schema() + " where irc.id = ? order by ircd.id asc";
|
||||
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql, this.chartExtractor,
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ");
|
||||
sql.append(this.chartExtractor.schema());
|
||||
sql.append(" where irc.id = ? order by irc.id asc, ");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END,");
|
||||
sql.append("ircd.from_period, ircd.to_period,");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END");
|
||||
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
|
||||
new Object[] { chartId });
|
||||
if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(chartId); }
|
||||
|
||||
@@ -122,8 +134,21 @@ public class DepositAccountInterestRateChartReadPlatformServiceImpl implements D
|
||||
@Override
|
||||
public DepositAccountInterestRateChartData retrieveOneWithSlabsOnAccountId(Long accountId) {
|
||||
this.context.authenticatedUser();
|
||||
final String sql = "select " + this.chartExtractor.schema() + " where irc.savings_account_id = ? order by ircd.id asc";
|
||||
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql, this.chartExtractor,
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ");
|
||||
sql.append(this.chartExtractor.schema());
|
||||
sql.append(" where irc.savings_account_id = ? order by irc.id asc, ");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END,");
|
||||
sql.append("ircd.from_period, ircd.to_period,");
|
||||
sql.append("CASE ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
|
||||
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
|
||||
sql.append("END");
|
||||
|
||||
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
|
||||
new Object[] { accountId });
|
||||
if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(accountId); }
|
||||
|
||||
@@ -167,6 +192,7 @@ public class DepositAccountInterestRateChartReadPlatformServiceImpl implements D
|
||||
sqlBuilder
|
||||
.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription,")
|
||||
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
|
||||
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
|
||||
.append("ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, ")
|
||||
.append("ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, ")
|
||||
.append("ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, ")
|
||||
@@ -231,6 +257,7 @@ public class DepositAccountInterestRateChartReadPlatformServiceImpl implements D
|
||||
|
||||
sqlBuilder.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription, ")
|
||||
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
|
||||
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
|
||||
.append("sa.id as accountId, sa.account_no as accountNumber ").append("from ")
|
||||
.append("m_savings_account_interest_rate_chart irc left join m_savings_account sa on irc.savings_account_id=sa.id ");
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
@@ -243,12 +270,13 @@ public class DepositAccountInterestRateChartReadPlatformServiceImpl implements D
|
||||
final String description = rs.getString("ircDescription");
|
||||
final LocalDate fromDate = JdbcSupport.getLocalDate(rs, "ircFromDate");
|
||||
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "ircEndDate");
|
||||
final boolean isPrimaryGroupingByAmount = rs.getBoolean("isPrimaryGroupingByAmount");
|
||||
final Long accountId = rs.getLong("accountId");
|
||||
final String accountNumber = rs.getString("accountNumber");
|
||||
final Collection<EnumOptionData> periodTypes = InterestRateChartEnumerations.periodType(PeriodFrequencyType.values());
|
||||
|
||||
return DepositAccountInterestRateChartData.instance(id, name, description, fromDate, endDate, accountId, accountNumber, null,
|
||||
periodTypes);
|
||||
return DepositAccountInterestRateChartData.instance(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount,
|
||||
accountId, accountNumber, null, periodTypes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
ALTER TABLE `m_interest_rate_slab`
|
||||
CHANGE COLUMN `from_period` `from_period` INT(11) NULL DEFAULT NULL,
|
||||
CHANGE COLUMN `period_type_enum` `period_type_enum` SMALLINT(5) NULL DEFAULT NULL ;
|
||||
|
||||
ALTER TABLE `m_interest_rate_chart`
|
||||
ADD COLUMN `is_primary_grouping_by_amount` TINYINT(1) NOT NULL DEFAULT '0';
|
||||
|
||||
ALTER TABLE `m_savings_account_interest_rate_chart`
|
||||
ADD COLUMN `is_primary_grouping_by_amount` TINYINT NOT NULL DEFAULT '0' ;
|
||||
|
||||
ALTER TABLE `m_savings_account_interest_rate_slab`
|
||||
CHANGE COLUMN `period_type_enum` `period_type_enum` SMALLINT(5) NULL DEFAULT NULL,
|
||||
CHANGE COLUMN `from_period` `from_period` INT(11) NULL DEFAULT NULL;
|
||||
Reference in New Issue
Block a user