blob: ff27554715e86db213a32d26732f6d2e3c83b0ed [file] [log] [blame]
/**
* 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.savings.domain;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermParamName;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermTypeIdParamName;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepositTermParamName;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepositTermTypeIdParamName;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.minDepositTermParamName;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.minDepositTermTypeIdParamName;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
import org.joda.time.DateTimeConstants;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.joda.time.Weeks;
import org.joda.time.Years;
/**
* DepositTermDetail encapsulates all the details of a
* {@link FixedDepositProduct} that are also used and persisted by a
* {@link FixedDepositAccount}.
*/
@Embeddable
public class DepositTermDetail {
@Column(name = "min_deposit_term", nullable = true)
private Integer minDepositTerm;
@Column(name = "max_deposit_term", nullable = true)
private Integer maxDepositTerm;
@Column(name = "min_deposit_term_type_enum", nullable = true)
private Integer minDepositTermType;
@Column(name = "max_deposit_term_type_enum", nullable = true)
private Integer maxDepositTermType;
@Column(name = "in_multiples_of_deposit_term", nullable = true)
private Integer inMultiplesOfDepositTerm;
@Column(name = "in_multiples_of_deposit_term_type_enum", nullable = true)
private Integer inMultiplesOfDepositTermType;
public static DepositTermDetail createFrom(final Integer minDepositTerm, final Integer maxDepositTerm,
final SavingsPeriodFrequencyType minDepositTermType, final SavingsPeriodFrequencyType maxDepositTermType,
final Integer inMultiplesOfDepositTerm, final SavingsPeriodFrequencyType inMultiplesOfDepositTermType) {
return new DepositTermDetail(minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm,
inMultiplesOfDepositTermType);
}
protected DepositTermDetail() {
//
}
private DepositTermDetail(final Integer minDepositTerm, final Integer maxDepositTerm,
final SavingsPeriodFrequencyType minDepositTermType, final SavingsPeriodFrequencyType maxDepositTermType,
final Integer inMultiplesOfDepositTerm, final SavingsPeriodFrequencyType inMultiplesOfDepositTermType) {
this.minDepositTerm = minDepositTerm;
this.maxDepositTerm = maxDepositTerm;
this.minDepositTermType = (minDepositTermType == null) ? null : minDepositTermType.getValue();
this.maxDepositTermType = (maxDepositTermType == null) ? null : maxDepositTermType.getValue();
this.inMultiplesOfDepositTerm = inMultiplesOfDepositTerm;
this.inMultiplesOfDepositTermType = (inMultiplesOfDepositTermType == null) ? null : inMultiplesOfDepositTermType.getValue();
}
public Map<String, Object> update(final JsonCommand command, final DataValidatorBuilder baseDataValidator) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(10);
if (command.isChangeInIntegerParameterNamed(minDepositTermParamName, this.minDepositTerm)) {
final Integer newValue = command.integerValueOfParameterNamed(minDepositTermParamName);
actualChanges.put(minDepositTermParamName, newValue);
this.minDepositTerm = newValue;
}
if (command.isChangeInIntegerParameterNamed(maxDepositTermParamName, this.maxDepositTerm)) {
final Integer newValue = command.integerValueOfParameterNamed(maxDepositTermParamName);
actualChanges.put(maxDepositTermParamName, newValue);
this.maxDepositTerm = newValue;
}
if (command.isChangeInIntegerParameterNamed(minDepositTermTypeIdParamName, this.minDepositTermType)) {
final Integer newValue = command.integerValueOfParameterNamed(minDepositTermTypeIdParamName);
actualChanges.put(minDepositTermTypeIdParamName, SavingsEnumerations.depositTermFrequencyType(newValue));
this.minDepositTermType = newValue;
}
if (command.isChangeInIntegerParameterNamed(maxDepositTermTypeIdParamName, this.maxDepositTermType)) {
final Integer newValue = command.integerValueOfParameterNamed(maxDepositTermTypeIdParamName);
actualChanges.put(maxDepositTermTypeIdParamName, SavingsEnumerations.depositTermFrequencyType(newValue));
this.maxDepositTermType = newValue;
}
if (command.isChangeInIntegerParameterNamed(inMultiplesOfDepositTermParamName, this.inMultiplesOfDepositTerm)) {
final Integer newValue = command.integerValueOfParameterNamed(inMultiplesOfDepositTermParamName);
actualChanges.put(inMultiplesOfDepositTermParamName, newValue);
this.inMultiplesOfDepositTerm = newValue;
}
if (command.isChangeInIntegerParameterNamed(inMultiplesOfDepositTermTypeIdParamName, this.inMultiplesOfDepositTermType)) {
final Integer newValue = command.integerValueOfParameterNamed(inMultiplesOfDepositTermTypeIdParamName);
actualChanges.put(inMultiplesOfDepositTermTypeIdParamName, SavingsEnumerations.inMultiplesOfDepositTermFrequencyType(newValue));
this.inMultiplesOfDepositTermType = newValue;
}
if (isMinDepositTermGreaterThanMaxDepositTerm()) {
baseDataValidator.parameter(minDepositTermParamName).value(this.minDepositTerm)
.failWithCode(".greater.than.maxDepositTerm", this.minDepositTerm, this.maxDepositTerm);
}
return actualChanges;
}
public boolean isMinDepositTermGreaterThanMaxDepositTerm() {
if (this.minDepositTerm != null && this.maxDepositTerm != null) {
final Integer minDepositInDays = this.convertToSafeDays(minDepositTerm, SavingsPeriodFrequencyType.fromInt(minDepositTermType));
final Integer maxDepositInDays = this.convertToSafeDays(maxDepositTerm, SavingsPeriodFrequencyType.fromInt(maxDepositTermType));
if (minDepositInDays.compareTo(maxDepositInDays) > 0) { return true; }
}
return false;
}
public Integer minDepositTerm() {
return this.minDepositTerm;
}
public Integer maxDepositTerm() {
return this.maxDepositTerm;
}
public Integer minDepositTermType() {
return this.minDepositTermType;
}
public Integer maxDepositTermType() {
return this.maxDepositTermType;
}
public Integer inMultiplesOfDepositTerm() {
return this.inMultiplesOfDepositTerm;
}
public Integer inMultiplesOfDepositTermType() {
return this.inMultiplesOfDepositTermType;
}
public boolean isDepositBetweenMinAndMax(LocalDate depositStartDate, LocalDate depositEndDate) {
return isEqualOrGreaterThanMin(depositStartDate, depositEndDate) && isEqualOrLessThanMax(depositStartDate, depositEndDate);
}
public boolean isValidInMultiplesOfPeriod(final Integer depositPeriod, final SavingsPeriodFrequencyType depositPeriodFrequencyType) {
boolean isValidInMultiplesOfPeriod = true;
final Integer depositPeriodInDays = this.convertToSafeDays(depositPeriod, depositPeriodFrequencyType);
if (this.inMultiplesOfDepositTerm() != null) {
final Integer inMultiplesOfInDays = this.convertToSafeDays(this.inMultiplesOfDepositTerm(),
SavingsPeriodFrequencyType.fromInt(this.inMultiplesOfDepositTermType()));
final Integer minDepositInDays = this.convertToSafeDays(minDepositTerm, SavingsPeriodFrequencyType.fromInt(minDepositTermType));
isValidInMultiplesOfPeriod = ((depositPeriodInDays - minDepositInDays) % inMultiplesOfInDays == 0);
}
return isValidInMultiplesOfPeriod;
}
private boolean isEqualOrGreaterThanMin(LocalDate depositStartDate, LocalDate depositEndDate) {
if (minDepositTerm() == null) return true;
final SavingsPeriodFrequencyType periodFrequencyType = SavingsPeriodFrequencyType.fromInt(this.minDepositTermType());
final Integer depositPeriod = depositPeriod(depositStartDate, depositEndDate, periodFrequencyType);
return minDepositTerm() == null || depositPeriod.compareTo(minDepositTerm()) >= 0;
}
private boolean isEqualOrLessThanMax(LocalDate depositStartDate, LocalDate depositEndDate) {
if (maxDepositTerm() == null) return true;
final SavingsPeriodFrequencyType periodFrequencyType = SavingsPeriodFrequencyType.fromInt(this.maxDepositTermType());
final Integer depositPeriod = depositPeriod(depositStartDate, depositEndDate, periodFrequencyType);
return maxDepositTerm() == null || depositPeriod.compareTo(maxDepositTerm()) <= 0;
}
public Integer depositPeriod(final LocalDate periodStartDate, final LocalDate periodEndDate,
final SavingsPeriodFrequencyType periodFrequencyType) {
Integer actualDepositPeriod = 0;
switch (periodFrequencyType) {
case DAYS:
actualDepositPeriod = Days.daysBetween(periodStartDate, periodEndDate).getDays();
break;
case WEEKS:
actualDepositPeriod = Weeks.weeksBetween(periodStartDate, periodEndDate).getWeeks();
break;
case MONTHS:
actualDepositPeriod = Months.monthsBetween(periodStartDate, periodEndDate).getMonths();
break;
case YEARS:
actualDepositPeriod = Years.yearsBetween(periodStartDate, periodEndDate).getYears();
break;
case INVALID:
actualDepositPeriod = 0;// default value
break;
}
return actualDepositPeriod;
}
private Integer convertToSafeDays(final Integer period, final SavingsPeriodFrequencyType periodFrequencyType) {
Integer toDays = 0;
switch (periodFrequencyType) {
case DAYS:
toDays = period;
break;
case WEEKS:
toDays = period * DateTimeConstants.DAYS_PER_WEEK;
break;
case MONTHS:
toDays = period * 30;// converting to stard 30 days
break;
case YEARS:
toDays = period * 365;
break;
case INVALID:
toDays = 0;// default value
break;
}
return toDays;
}
public DepositTermDetail copy() {
final Integer minDepositTerm = this.minDepositTerm;
final Integer maxDepositTerm = this.maxDepositTerm;
final SavingsPeriodFrequencyType minDepositTermType = SavingsPeriodFrequencyType.fromInt(this.minDepositTermType);
final SavingsPeriodFrequencyType maxDepositTermType = SavingsPeriodFrequencyType.fromInt(this.maxDepositTermType);
final Integer inMultiplesOfDepositTerm = this.inMultiplesOfDepositTerm;
final SavingsPeriodFrequencyType inMultiplesOfDepositTermType = SavingsPeriodFrequencyType.fromInt(this
.inMultiplesOfDepositTermType());
return DepositTermDetail.createFrom(minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType);
}
}