blob: b6649a68dda1d24b17ee34e25be165718ffb0c9a [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.floatingrates.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
import org.apache.fineract.useradministration.domain.AppUser;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.joda.time.LocalDate;
import org.springframework.data.jpa.domain.AbstractPersistable;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@Entity
@Table(name = "m_floating_rates", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
public class FloatingRate extends AbstractPersistable<Long> {
@Column(name = "name", length = 200, unique = true, nullable = false)
private String name;
@Column(name = "is_base_lending_rate", nullable = false)
private boolean isBaseLendingRate;
@Column(name = "is_active", nullable = false)
private boolean isActive;
@OrderBy(value = "fromDate,id")
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "floatingRate", orphanRemoval = true)
private Set<FloatingRatePeriod> floatingRatePeriods;
@ManyToOne(optional = true)
@JoinColumn(name = "createdby_id", nullable = false)
private AppUser createdBy;
@ManyToOne(optional = true)
@JoinColumn(name = "lastmodifiedby_id", nullable = false)
private AppUser modifiedBy;
@Column(name = "created_date", nullable = false)
private Date createdOn;
@Column(name = "lastmodified_date", nullable = false)
private Date modifiedOn;
public FloatingRate() {
}
public FloatingRate(String name, boolean isBaseLendingRate,
boolean isActive, Set<FloatingRatePeriod> floatingRatePeriods,
AppUser createdBy, AppUser modifiedBy, Date createdOn,
Date modifiedOn) {
this.name = name;
this.isBaseLendingRate = isBaseLendingRate;
this.isActive = isActive;
this.floatingRatePeriods = floatingRatePeriods;
this.createdBy = createdBy;
this.createdOn = createdOn;
this.modifiedBy = modifiedBy;
this.modifiedOn = modifiedOn;
if (floatingRatePeriods != null) {
for (FloatingRatePeriod ratePeriod : floatingRatePeriods) {
ratePeriod.updateFloatingRate(this);
}
}
}
public static FloatingRate createNew(AppUser currentUser,
JsonCommand command) {
final String name = command.stringValueOfParameterNamed("name");
final boolean isBaseLendingRate = command
.parameterExists("isBaseLendingRate") ? command
.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate")
: false;
final boolean isActive = command.parameterExists("isActive") ? command
.booleanPrimitiveValueOfParameterNamed("isActive") : true;
final Set<FloatingRatePeriod> floatingRatePeriods = getRatePeriods(
currentUser, command);
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
return new FloatingRate(name, isBaseLendingRate, isActive,
floatingRatePeriods, currentUser, currentUser,
currentDate.toDate(), currentDate.toDate());
}
private static Set<FloatingRatePeriod> getRatePeriods(
final AppUser currentUser, final JsonCommand command) {
if (!command.parameterExists("ratePeriods")) {
return null;
}
Set<FloatingRatePeriod> ratePeriods = new HashSet<>();
JsonArray arrayOfParameterNamed = command
.arrayOfParameterNamed("ratePeriods");
for (final JsonElement ratePeriod : arrayOfParameterNamed) {
final JsonObject ratePeriodObject = ratePeriod.getAsJsonObject();
final JsonParserHelper helper = new JsonParserHelper();
final Date fromDate = helper.extractLocalDateNamed("fromDate",
ratePeriod, new HashSet<String>()).toDate();
final BigDecimal interestRate = ratePeriodObject
.get("interestRate").getAsBigDecimal();
final boolean isDifferentialToBaseLendingRate = helper
.parameterExists("isDifferentialToBaseLendingRate",
ratePeriod) ? ratePeriodObject.get(
"isDifferentialToBaseLendingRate").getAsBoolean() : false;
final boolean isActive = true;
final Date currentDate = DateUtils.getDateOfTenant();
ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate,
isDifferentialToBaseLendingRate, isActive, currentUser,
currentUser, currentDate, currentDate));
}
return ratePeriods;
}
public String getName() {
return this.name;
}
public boolean isBaseLendingRate() {
return this.isBaseLendingRate;
}
public boolean isActive() {
return this.isActive;
}
public Set<FloatingRatePeriod> getFloatingRatePeriods() {
return this.floatingRatePeriods;
}
public AppUser getCreatedBy() {
return this.createdBy;
}
public AppUser getModifiedBy() {
return this.modifiedBy;
}
public Date getCreatedOn() {
return this.createdOn;
}
public Date getModifiedOn() {
return this.modifiedOn;
}
public Map<String, Object> update(final JsonCommand command,
final AppUser appUser) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
if (command.isChangeInStringParameterNamed("name", this.name)) {
final String newValue = command.stringValueOfParameterNamed("name");
actualChanges.put("name", newValue);
this.name = newValue;
}
if (command.isChangeInBooleanParameterNamed("isBaseLendingRate",
this.isBaseLendingRate)) {
final boolean newValue = command
.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate");
actualChanges.put("isBaseLendingRate", newValue);
this.isBaseLendingRate = newValue;
}
if (command.isChangeInBooleanParameterNamed("isActive", this.isActive)) {
final boolean newValue = command
.booleanPrimitiveValueOfParameterNamed("isActive");
actualChanges.put("isActive", newValue);
this.isActive = newValue;
}
final Set<FloatingRatePeriod> newRatePeriods = getRatePeriods(appUser,
command);
if (newRatePeriods != null && !newRatePeriods.isEmpty()) {
updateRatePeriods(newRatePeriods, appUser);
actualChanges.put("ratePeriods",
command.jsonFragment("ratePeriods"));
}
return actualChanges;
}
private void updateRatePeriods(
final Set<FloatingRatePeriod> newRatePeriods, final AppUser appUser) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
if (this.floatingRatePeriods != null) {
for (FloatingRatePeriod ratePeriod : this.floatingRatePeriods) {
LocalDate fromDate = LocalDate.fromDateFields(ratePeriod
.getFromDate());
if (fromDate.isAfter(today)) {
ratePeriod.setActive(false);
ratePeriod.setModifiedBy(appUser);
ratePeriod.setModifiedOn(today.toDate());
}
}
}
for (FloatingRatePeriod newRatePeriod : newRatePeriods) {
newRatePeriod.updateFloatingRate(this);
this.floatingRatePeriods.add(newRatePeriod);
}
}
public Collection<FloatingRatePeriodData> fetchInterestRates(
final FloatingRateDTO floatingRateDTO) {
Collection<FloatingRatePeriodData> applicableRates = new ArrayList<>();
FloatingRatePeriod previousPeriod = null;
boolean addPeriodData = false;
for (FloatingRatePeriod floatingRatePeriod : this.floatingRatePeriods) {
if (floatingRatePeriod.isActive()) {
// will enter
if (applicableRates.isEmpty()
&& floatingRateDTO.getStartDate().isBefore(
floatingRatePeriod.fetchFromDate())) {
if (floatingRateDTO.isFloatingInterestRate()) {
addPeriodData = true;
}
if (previousPeriod != null) {
applicableRates.add(previousPeriod
.toData(floatingRateDTO));
} else if (!addPeriodData) {
applicableRates.add(floatingRatePeriod
.toData(floatingRateDTO));
}
}
if (addPeriodData) {
applicableRates.add(floatingRatePeriod
.toData(floatingRateDTO));
}
previousPeriod = floatingRatePeriod;
}
}
if (applicableRates.isEmpty() && previousPeriod != null) {
applicableRates.add(previousPeriod.toData(floatingRateDTO));
}
return applicableRates;
}
}