FINERACT-1983: Date handling improvements - general
This commit is contained in:
+3
-4
@@ -66,15 +66,14 @@ public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosure
|
|||||||
final Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId);
|
final Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId);
|
||||||
// TODO: Get Tenant specific date
|
// TODO: Get Tenant specific date
|
||||||
// ensure closure date is not in the future
|
// ensure closure date is not in the future
|
||||||
final LocalDate todaysDate = DateUtils.getBusinessLocalDate();
|
|
||||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue());
|
final LocalDate closureDate = command.localDateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue());
|
||||||
if (closureDate.isAfter(todaysDate)) {
|
if (DateUtils.isDateInTheFuture(closureDate)) {
|
||||||
throw new GLClosureInvalidException(GlClosureInvalidReason.FUTURE_DATE, closureDate);
|
throw new GLClosureInvalidException(GlClosureInvalidReason.FUTURE_DATE, closureDate);
|
||||||
}
|
}
|
||||||
// shouldn't be before an existing accounting closure
|
// shouldn't be before an existing accounting closure
|
||||||
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
|
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
|
||||||
if (latestGLClosure != null) {
|
if (latestGLClosure != null) {
|
||||||
if (latestGLClosure.getClosingDate().isAfter(closureDate)) {
|
if (DateUtils.isAfter(latestGLClosure.getClosingDate(), closureDate)) {
|
||||||
throw new GLClosureInvalidException(GlClosureInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate());
|
throw new GLClosureInvalidException(GlClosureInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +121,7 @@ public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosure
|
|||||||
**/
|
**/
|
||||||
final LocalDate closureDate = glClosure.getClosingDate();
|
final LocalDate closureDate = glClosure.getClosingDate();
|
||||||
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(glClosure.getOffice().getId());
|
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(glClosure.getOffice().getId());
|
||||||
if (latestGLClosure.getClosingDate().isAfter(closureDate)) {
|
if (DateUtils.isAfter(latestGLClosure.getClosingDate(), closureDate)) {
|
||||||
throw new GLClosureInvalidDeleteException(latestGLClosure.getOffice().getId(), latestGLClosure.getOffice().getName(),
|
throw new GLClosureInvalidDeleteException(latestGLClosure.getOffice().getId(), latestGLClosure.getOffice().getName(),
|
||||||
latestGLClosure.getClosingDate());
|
latestGLClosure.getClosingDate());
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -30,6 +30,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_trial_balance")
|
@Table(name = "m_trial_balance")
|
||||||
@@ -70,9 +71,8 @@ public class TrialBalance extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
TrialBalance other = (TrialBalance) obj;
|
TrialBalance other = (TrialBalance) obj;
|
||||||
return Objects.equals(other.officeId, officeId) && Objects.equals(other.glAccountId, glAccountId)
|
return Objects.equals(other.officeId, officeId) && Objects.equals(other.glAccountId, glAccountId)
|
||||||
&& Objects.equals(other.amount, amount) && other.entryDate.compareTo(entryDate) == 0 ? Boolean.TRUE
|
&& Objects.equals(other.amount, amount) && DateUtils.isEqual(other.entryDate, entryDate)
|
||||||
: Boolean.FALSE && other.transactionDate.compareTo(transactionDate) == 0 ? Boolean.TRUE
|
&& DateUtils.isEqual(other.transactionDate, transactionDate) && Objects.equals(other.closingBalance, closingBalance);
|
||||||
: Boolean.FALSE && Objects.equals(other.closingBalance, closingBalance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
|||||||
this.subResourceId = subResourceId;
|
this.subResourceId = subResourceId;
|
||||||
this.commandAsJson = commandSerializedAsJson;
|
this.commandAsJson = commandSerializedAsJson;
|
||||||
this.maker = maker;
|
this.maker = maker;
|
||||||
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.madeOnDate = DateUtils.getAuditOffsetDateTime();
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.idempotencyKey = idempotencyKey;
|
this.idempotencyKey = idempotencyKey;
|
||||||
}
|
}
|
||||||
@@ -314,13 +314,13 @@ public class CommandSource extends AbstractPersistableCustom {
|
|||||||
|
|
||||||
public void markAsChecked(final AppUser checker) {
|
public void markAsChecked(final AppUser checker) {
|
||||||
this.checker = checker;
|
this.checker = checker;
|
||||||
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.checkedOnDate = DateUtils.getAuditOffsetDateTime();
|
||||||
this.status = CommandProcessingResultType.PROCESSED.getValue();
|
this.status = CommandProcessingResultType.PROCESSED.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markAsRejected(final AppUser checker) {
|
public void markAsRejected(final AppUser checker) {
|
||||||
this.checker = checker;
|
this.checker = checker;
|
||||||
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.checkedOnDate = DateUtils.getAuditOffsetDateTime();
|
||||||
this.status = CommandProcessingResultType.REJECTED.getValue();
|
this.status = CommandProcessingResultType.REJECTED.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public class PurgeProcessedCommandsTasklet implements Tasklet {
|
|||||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
||||||
try {
|
try {
|
||||||
Long numberOfDaysForPurgeCriteria = configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria();
|
Long numberOfDaysForPurgeCriteria = configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria();
|
||||||
OffsetDateTime dateForPurgeCriteria = DateUtils.getOffsetDateTimeOfTenant().minusDays(numberOfDaysForPurgeCriteria);
|
OffsetDateTime dateForPurgeCriteria = DateUtils.getAuditOffsetDateTime().minusDays(numberOfDaysForPurgeCriteria);
|
||||||
repository.deleteOlderEventsWithStatus(CommandProcessingResultType.PROCESSED.getValue(), dateForPurgeCriteria);
|
repository.deleteOlderEventsWithStatus(CommandProcessingResultType.PROCESSED.getValue(), dateForPurgeCriteria);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Error occurred while purging processed commands: ", e);
|
log.error("Error occurred while purging processed commands: ", e);
|
||||||
|
|||||||
+1
-4
@@ -19,7 +19,6 @@
|
|||||||
package org.apache.fineract.infrastructure.businessdate.service;
|
package org.apache.fineract.infrastructure.businessdate.service;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -70,8 +69,7 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat
|
|||||||
@Override
|
@Override
|
||||||
public HashMap<BusinessDateType, LocalDate> getBusinessDates() {
|
public HashMap<BusinessDateType, LocalDate> getBusinessDates() {
|
||||||
HashMap<BusinessDateType, LocalDate> businessDateMap = new HashMap<>();
|
HashMap<BusinessDateType, LocalDate> businessDateMap = new HashMap<>();
|
||||||
ZoneId zone = DateUtils.getDateTimeZoneOfTenant();
|
LocalDate tenantDate = DateUtils.getLocalDateOfTenant();
|
||||||
LocalDate tenantDate = LocalDate.now(zone);
|
|
||||||
businessDateMap.put(BusinessDateType.BUSINESS_DATE, tenantDate);
|
businessDateMap.put(BusinessDateType.BUSINESS_DATE, tenantDate);
|
||||||
businessDateMap.put(BusinessDateType.COB_DATE, tenantDate);
|
businessDateMap.put(BusinessDateType.COB_DATE, tenantDate);
|
||||||
if (configurationDomainService.isBusinessDateEnabled()) {
|
if (configurationDomainService.isBusinessDateEnabled()) {
|
||||||
@@ -80,7 +78,6 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat
|
|||||||
businessDateMap.put(BusinessDateType.valueOf(businessDateData.getType()), businessDateData.getDate());
|
businessDateMap.put(BusinessDateType.valueOf(businessDateData.getType()), businessDateData.getDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return businessDateMap;
|
return businessDateMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-5
@@ -132,15 +132,11 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
|
|||||||
private void updateBusinessDate(BusinessDate businessDate, LocalDate newDate, Map<String, Object> changes) {
|
private void updateBusinessDate(BusinessDate businessDate, LocalDate newDate, Map<String, Object> changes) {
|
||||||
LocalDate oldDate = businessDate.getDate();
|
LocalDate oldDate = businessDate.getDate();
|
||||||
|
|
||||||
if (!hasChange(oldDate, newDate)) {
|
if (DateUtils.isEqual(oldDate, newDate)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
businessDate.setDate(newDate);
|
businessDate.setDate(newDate);
|
||||||
repository.save(businessDate);
|
repository.save(businessDate);
|
||||||
changes.put(businessDate.getType().name(), newDate);
|
changes.put(businessDate.getType().name(), newDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasChange(@NotNull LocalDate oldDate, @NotNull LocalDate date) {
|
|
||||||
return (date.isBefore(oldDate) || date.isAfter(oldDate));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -32,6 +32,7 @@ import net.fortuna.ical4j.model.property.RRule;
|
|||||||
import net.fortuna.ical4j.validate.ValidationException;
|
import net.fortuna.ical4j.validate.ValidationException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.quartz.CronExpression;
|
import org.quartz.CronExpression;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
@@ -1045,7 +1046,7 @@ public class DataValidatorBuilder {
|
|||||||
|
|
||||||
if (this.value != null && date != null) {
|
if (this.value != null && date != null) {
|
||||||
final LocalDate dateVal = (LocalDate) this.value;
|
final LocalDate dateVal = (LocalDate) this.value;
|
||||||
if (date.isAfter(dateVal)) {
|
if (DateUtils.isAfter(date, dateVal)) {
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
.append(this.parameter).append(".is.less.than.date");
|
.append(this.parameter).append(".is.less.than.date");
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
||||||
@@ -1065,7 +1066,7 @@ public class DataValidatorBuilder {
|
|||||||
|
|
||||||
if (this.value != null && date != null) {
|
if (this.value != null && date != null) {
|
||||||
final LocalDate dateVal = (LocalDate) this.value;
|
final LocalDate dateVal = (LocalDate) this.value;
|
||||||
if (date.isBefore(dateVal)) {
|
if (DateUtils.isBefore(date, dateVal)) {
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
.append(this.parameter).append(".is.greater.than.date");
|
.append(this.parameter).append(".is.greater.than.date");
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
||||||
@@ -1085,7 +1086,7 @@ public class DataValidatorBuilder {
|
|||||||
|
|
||||||
if (this.value != null && date != null) {
|
if (this.value != null && date != null) {
|
||||||
final LocalDate dateVal = (LocalDate) this.value;
|
final LocalDate dateVal = (LocalDate) this.value;
|
||||||
if (dateVal.isAfter(date)) {
|
if (DateUtils.isAfter(dateVal, date)) {
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
.append(this.parameter).append(".is.greater.than.date");
|
.append(this.parameter).append(".is.greater.than.date");
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
||||||
@@ -1105,7 +1106,7 @@ public class DataValidatorBuilder {
|
|||||||
|
|
||||||
if (this.value != null && date != null) {
|
if (this.value != null && date != null) {
|
||||||
final LocalDate dateVal = (LocalDate) this.value;
|
final LocalDate dateVal = (LocalDate) this.value;
|
||||||
if (!dateVal.isEqual(date)) {
|
if (!DateUtils.isEqual(dateVal, date)) {
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
.append(this.parameter).append(".is.not.equal.to.date");
|
.append(this.parameter).append(".is.not.equal.to.date");
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter `").append(this.parameter)
|
||||||
|
|||||||
+3
-2
@@ -22,6 +22,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
public class LocalDateInterval {
|
public class LocalDateInterval {
|
||||||
|
|
||||||
@@ -66,11 +67,11 @@ public class LocalDateInterval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isBetweenInclusive(final LocalDate start, final LocalDate end, final LocalDate target) {
|
private boolean isBetweenInclusive(final LocalDate start, final LocalDate end, final LocalDate target) {
|
||||||
return !target.isBefore(start) && !target.isAfter(end);
|
return !DateUtils.isBefore(target, start) && !DateUtils.isAfter(target, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean fallsBefore(final LocalDate dateToCheck) {
|
public boolean fallsBefore(final LocalDate dateToCheck) {
|
||||||
return this.endDate.isBefore(dateToCheck);
|
return DateUtils.isBefore(this.endDate, dateToCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
-4
@@ -70,10 +70,6 @@ public final class DateUtils {
|
|||||||
return truncate == null ? now : now.truncatedTo(truncate);
|
return truncate == null ? now : now.truncatedTo(truncate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OffsetDateTime getOffsetDateTimeOfTenantWithMostPrecision() {
|
|
||||||
return getOffsetDateTimeOfTenant(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OffsetDateTime getOffsetDateTimeOfTenant() {
|
public static OffsetDateTime getOffsetDateTimeOfTenant() {
|
||||||
return getOffsetDateTimeOfTenant(null);
|
return getOffsetDateTimeOfTenant(null);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -20,6 +20,7 @@ package org.apache.fineract.infrastructure.core.service.database;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.sql.JDBCType;
|
import java.sql.JDBCType;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
|
||||||
|
|
||||||
@@ -272,7 +273,7 @@ public enum JdbcJavaType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@com.google.errorprone.annotations.Immutable
|
@com.google.errorprone.annotations.Immutable
|
||||||
private static final class DialectType {
|
private static final class DialectType implements Serializable {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JDBCType jdbcType;
|
private final JDBCType jdbcType;
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ public class SendAsynchronousEventsTasklet implements Tasklet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void markEventsAsSent(List<Long> eventIds) {
|
private void markEventsAsSent(List<Long> eventIds) {
|
||||||
OffsetDateTime sentAt = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
OffsetDateTime sentAt = DateUtils.getAuditOffsetDateTime();
|
||||||
|
|
||||||
// Partitioning dataset to avoid exception: PreparedStatement can have at most 65,535 parameters
|
// Partitioning dataset to avoid exception: PreparedStatement can have at most 65,535 parameters
|
||||||
List<List<Long>> partitions = Lists.partition(eventIds, 5_000);
|
List<List<Long>> partitions = Lists.partition(eventIds, 5_000);
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ public class ExternalEvent extends AbstractPersistableCustom {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
this.idempotencyKey = idempotencyKey;
|
this.idempotencyKey = idempotencyKey;
|
||||||
this.aggregateRootId = aggregateRootId;
|
this.aggregateRootId = aggregateRootId;
|
||||||
this.createdAt = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.createdAt = DateUtils.getAuditOffsetDateTime();
|
||||||
this.status = ExternalEventStatus.TO_BE_SENT;
|
this.status = ExternalEventStatus.TO_BE_SENT;
|
||||||
this.businessDate = DateUtils.getBusinessLocalDate();
|
this.businessDate = DateUtils.getBusinessLocalDate();
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-28
@@ -20,6 +20,7 @@ package org.apache.fineract.organisation.holiday.service;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||||
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
|
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
|
||||||
|
|
||||||
@@ -30,47 +31,29 @@ public final class HolidayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static LocalDate getRepaymentRescheduleDateToIfHoliday(LocalDate repaymentDate, final List<Holiday> holidays) {
|
public static LocalDate getRepaymentRescheduleDateToIfHoliday(LocalDate repaymentDate, final List<Holiday> holidays) {
|
||||||
|
|
||||||
for (final Holiday holiday : holidays) {
|
for (final Holiday holiday : holidays) {
|
||||||
if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate())
|
if (isHoliday(repaymentDate, holiday)) {
|
||||||
|| (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) {
|
repaymentDate = holiday.getRepaymentsRescheduledTo();
|
||||||
repaymentDate = getRepaymentRescheduleDateIfHoliday(repaymentDate, holidays);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return repaymentDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LocalDate getRepaymentRescheduleDateIfHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
|
|
||||||
|
|
||||||
for (final Holiday holiday : holidays) {
|
|
||||||
if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate())
|
|
||||||
|| (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) {
|
|
||||||
// should be take from holiday
|
|
||||||
return holiday.getRepaymentsRescheduledTo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return repaymentDate;
|
return repaymentDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isHoliday(final LocalDate date, final List<Holiday> holidays) {
|
public static boolean isHoliday(final LocalDate date, final List<Holiday> holidays) {
|
||||||
for (final Holiday holiday : holidays) {
|
return getApplicableHoliday(date, holidays) != null;
|
||||||
if (date.isEqual(holiday.getFromDate()) || date.isEqual(holiday.getToDate())
|
|
||||||
|| (date.isAfter(holiday.getFromDate()) && date.isBefore(holiday.getToDate()))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Holiday getApplicableHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
|
public static Holiday getApplicableHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
|
||||||
Holiday referedHoliday = null;
|
|
||||||
for (final Holiday holiday : holidays) {
|
for (final Holiday holiday : holidays) {
|
||||||
if (!repaymentDate.isBefore(holiday.getFromDate()) && !repaymentDate.isAfter(holiday.getToDate())) {
|
if (isHoliday(repaymentDate, holiday)) {
|
||||||
referedHoliday = holiday;
|
return holiday;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return referedHoliday;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHoliday(LocalDate date, Holiday holiday) {
|
||||||
|
return !DateUtils.isBefore(date, holiday.getFromDate()) && !DateUtils.isAfter(date, holiday.getToDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
|
public static void updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
|
||||||
|
|||||||
+4
-3
@@ -39,6 +39,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||||
import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf;
|
import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf;
|
||||||
import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated;
|
import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated;
|
||||||
@@ -155,11 +156,11 @@ public class Office extends AbstractPersistableCustom implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpeningDateBefore(final LocalDate baseDate) {
|
public boolean isOpeningDateBefore(final LocalDate baseDate) {
|
||||||
return getOpeningLocalDate().isBefore(baseDate);
|
return DateUtils.isBefore(getOpeningLocalDate(), baseDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpeningDateAfter(final LocalDate activationLocalDate) {
|
public boolean isOpeningDateAfter(final LocalDate baseDate) {
|
||||||
return getOpeningLocalDate().isAfter(activationLocalDate);
|
return DateUtils.isAfter(getOpeningLocalDate(), baseDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getOpeningLocalDate() {
|
public LocalDate getOpeningLocalDate() {
|
||||||
|
|||||||
+3
-3
@@ -28,6 +28,7 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||||
import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
|
import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
|
||||||
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
||||||
@@ -377,12 +378,11 @@ public final class CalendarData implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||||
return this.startDate != null && compareDate != null
|
return this.startDate != null && compareDate != null && !DateUtils.isAfter(this.startDate, compareDate);
|
||||||
&& (this.startDate.isBefore(compareDate) || this.startDate.equals(compareDate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||||
return this.endDate != null && compareDate != null && (this.endDate.isAfter(compareDate) || this.endDate.isEqual(compareDate));
|
return this.endDate != null && compareDate != null && !DateUtils.isBefore(this.endDate, compareDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||||
|
|||||||
+4
-4
@@ -20,10 +20,10 @@ package org.apache.fineract.portfolio.calendar.data;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
|
import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
|
||||||
|
|
||||||
public class CalendarHistoryDataWrapper {
|
public class CalendarHistoryDataWrapper {
|
||||||
@@ -37,16 +37,16 @@ public class CalendarHistoryDataWrapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(CalendarHistory calendarHistory1, CalendarHistory calendarHistory2) {
|
public int compare(CalendarHistory calendarHistory1, CalendarHistory calendarHistory2) {
|
||||||
return calendarHistory1.getEndDateLocalDate().compareTo(calendarHistory2.getEndDateLocalDate());
|
return DateUtils.compare(calendarHistory1.getEndDate(), calendarHistory2.getEndDate());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Collections.sort(this.calendarHistoryList, orderByDate);
|
this.calendarHistoryList.sort(orderByDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalendarHistory getCalendarHistory(final LocalDate dueRepaymentPeriodDate) {
|
public CalendarHistory getCalendarHistory(final LocalDate dueRepaymentPeriodDate) {
|
||||||
CalendarHistory calendarHistory = null;
|
CalendarHistory calendarHistory = null;
|
||||||
for (CalendarHistory history : this.calendarHistoryList) {
|
for (CalendarHistory history : this.calendarHistoryList) {
|
||||||
if (history.getEndDateLocalDate().isAfter(dueRepaymentPeriodDate)) {
|
if (DateUtils.isAfter(history.getEndDate(), dueRepaymentPeriodDate)) {
|
||||||
calendarHistory = history;
|
calendarHistory = history;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-29
@@ -175,23 +175,19 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> updateStartDateAndDerivedFeilds(final LocalDate newMeetingStartDate) {
|
public Map<String, Object> updateStartDateAndDerivedFeilds(final LocalDate newMeetingStartDate) {
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||||
|
|
||||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
if (DateUtils.isBefore(newMeetingStartDate, currentDate)) {
|
||||||
if (newMeetingStartDate.isBefore(currentDate)) {
|
|
||||||
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
||||||
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newMeetingStartDate,
|
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newMeetingStartDate,
|
||||||
getStartDateLocalDate());
|
getStartDateLocalDate());
|
||||||
} else if (isStartDateAfter(newMeetingStartDate) && isStartDateBeforeOrEqual(currentDate)) {
|
} else if (isStartDateAfter(newMeetingStartDate) && isStartDateBeforeOrEqual(currentDate)) {
|
||||||
// new meeting date should be on or after start date or current
|
// new meeting date should be on or after start date or current date
|
||||||
// date
|
|
||||||
final String defaultUserMessage = "New meeting effective from date cannot be a date before existing meeting start date";
|
final String defaultUserMessage = "New meeting effective from date cannot be a date before existing meeting start date";
|
||||||
throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newMeetingStartDate,
|
throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newMeetingStartDate,
|
||||||
getStartDateLocalDate());
|
getStartDateLocalDate());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
actualChanges.put(CalendarSupportedParameters.START_DATE.getValue(), newMeetingStartDate.toString());
|
actualChanges.put(CalendarSupportedParameters.START_DATE.getValue(), newMeetingStartDate.toString());
|
||||||
this.startDate = newMeetingStartDate;
|
this.startDate = newMeetingStartDate;
|
||||||
|
|
||||||
@@ -200,33 +196,25 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
* recurring day and update it if it is changed. For weekly type is weekday and for monthly type it is day
|
* recurring day and update it if it is changed. For weekly type is weekday and for monthly type it is day
|
||||||
* of the month
|
* of the month
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CalendarFrequencyType calendarFrequencyType = CalendarUtils.getFrequency(this.recurrence);
|
CalendarFrequencyType calendarFrequencyType = CalendarUtils.getFrequency(this.recurrence);
|
||||||
Integer interval = CalendarUtils.getInterval(this.recurrence);
|
Integer interval = CalendarUtils.getInterval(this.recurrence);
|
||||||
Integer repeatsOnDay = null;
|
Integer repeatsOnDay = null;
|
||||||
|
|
||||||
/*
|
// Repeats on day, need to derive based on the start date
|
||||||
* Repeats on day, need to derive based on the start date
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (calendarFrequencyType.isWeekly()) {
|
if (calendarFrequencyType.isWeekly()) {
|
||||||
repeatsOnDay = newMeetingStartDate.get(ChronoField.DAY_OF_WEEK);
|
repeatsOnDay = newMeetingStartDate.get(ChronoField.DAY_OF_WEEK);
|
||||||
} else if (calendarFrequencyType.isMonthly()) {
|
} else if (calendarFrequencyType.isMonthly()) {
|
||||||
repeatsOnDay = newMeetingStartDate.getDayOfMonth();
|
repeatsOnDay = newMeetingStartDate.getDayOfMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cover other recurrence also
|
// TODO cover other recurrence also
|
||||||
|
|
||||||
this.recurrence = constructRecurrence(calendarFrequencyType, interval, repeatsOnDay, null);
|
this.recurrence = constructRecurrence(calendarFrequencyType, interval, repeatsOnDay, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||||
|
|
||||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.TITLE.getValue(), this.title)) {
|
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.TITLE.getValue(), this.title)) {
|
||||||
@@ -234,13 +222,11 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
actualChanges.put(CalendarSupportedParameters.TITLE.getValue(), newValue);
|
actualChanges.put(CalendarSupportedParameters.TITLE.getValue(), newValue);
|
||||||
this.title = StringUtils.defaultIfEmpty(newValue, null);
|
this.title = StringUtils.defaultIfEmpty(newValue, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue(), this.description)) {
|
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue(), this.description)) {
|
||||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue());
|
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue());
|
||||||
actualChanges.put(CalendarSupportedParameters.DESCRIPTION.getValue(), newValue);
|
actualChanges.put(CalendarSupportedParameters.DESCRIPTION.getValue(), newValue);
|
||||||
this.description = StringUtils.defaultIfEmpty(newValue, null);
|
this.description = StringUtils.defaultIfEmpty(newValue, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.LOCATION.getValue(), this.location)) {
|
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.LOCATION.getValue(), this.location)) {
|
||||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.LOCATION.getValue());
|
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.LOCATION.getValue());
|
||||||
actualChanges.put(CalendarSupportedParameters.LOCATION.getValue(), newValue);
|
actualChanges.put(CalendarSupportedParameters.LOCATION.getValue(), newValue);
|
||||||
@@ -251,12 +237,11 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
final String localeAsInput = command.locale();
|
final String localeAsInput = command.locale();
|
||||||
final String startDateParamName = CalendarSupportedParameters.START_DATE.getValue();
|
final String startDateParamName = CalendarSupportedParameters.START_DATE.getValue();
|
||||||
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartDateLocalDate())) {
|
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartDateLocalDate())) {
|
||||||
|
|
||||||
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
|
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
|
||||||
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
|
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
|
||||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
|
||||||
if (newValue.isBefore(currentDate)) {
|
if (DateUtils.isBefore(newValue, currentDate)) {
|
||||||
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
||||||
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newValue, getStartDateLocalDate());
|
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newValue, getStartDateLocalDate());
|
||||||
} else if (isStartDateAfter(newValue) && isStartDateBeforeOrEqual(currentDate)) {
|
} else if (isStartDateAfter(newValue) && isStartDateBeforeOrEqual(currentDate)) {
|
||||||
@@ -472,24 +457,19 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStartDateBefore(final LocalDate compareDate) {
|
public boolean isStartDateBefore(final LocalDate compareDate) {
|
||||||
if (this.startDate != null && compareDate != null && getStartDateLocalDate().isBefore(compareDate)) {
|
return startDate != null && DateUtils.isBefore(startDate, compareDate);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||||
return this.startDate != null && compareDate != null
|
return startDate != null && !DateUtils.isAfter(startDate, compareDate);
|
||||||
&& (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStartDateAfter(final LocalDate compareDate) {
|
public boolean isStartDateAfter(final LocalDate compareDate) {
|
||||||
return this.startDate != null && compareDate != null && getStartDateLocalDate().isAfter(compareDate);
|
return compareDate != null && DateUtils.isAfter(startDate, compareDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||||
return this.endDate != null && compareDate != null
|
return compareDate != null && !DateUtils.isBefore(endDate, compareDate);
|
||||||
&& (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||||
@@ -585,7 +565,7 @@ public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
// validate with history details.
|
// validate with history details.
|
||||||
for (CalendarHistory history : history()) {
|
for (CalendarHistory history : history()) {
|
||||||
if (history.isBetweenStartAndEndDate(compareDate)) {
|
if (history.isBetweenStartAndEndDate(compareDate)) {
|
||||||
return CalendarUtils.isValidRedurringDate(history.getRecurrence(), history.getStartDateLocalDate(), compareDate,
|
return CalendarUtils.isValidRedurringDate(history.getRecurrence(), history.getStartDate(), compareDate,
|
||||||
isSkipRepaymentOnFirstMonth, numberOfDays);
|
isSkipRepaymentOnFirstMonth, numberOfDays);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-25
@@ -88,51 +88,63 @@ public enum CalendarEntityType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isGroup(final Integer value) {
|
public static boolean isGroup(final Integer value) {
|
||||||
return CalendarEntityType.GROUPS.value.equals(value) ? true : false;
|
return CalendarEntityType.GROUPS.value.equals(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isGroup(final String name) {
|
public static boolean isGroup(final String name) {
|
||||||
return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name) ? true : false;
|
return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCenter(final Integer value) {
|
public static boolean isCenter(final Integer value) {
|
||||||
return CalendarEntityType.CENTERS.value.equals(value) ? true : false;
|
return CalendarEntityType.CENTERS.value.equals(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCenter(final String name) {
|
public static boolean isCenter(final String name) {
|
||||||
return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name) ? true : false;
|
return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLoan(final Integer value) {
|
public static boolean isLoan(final Integer value) {
|
||||||
return CalendarEntityType.LOANS.value.equals(value) ? true : false;
|
return CalendarEntityType.LOANS.value.equals(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLoan(final String name) {
|
public static boolean isLoan(final String name) {
|
||||||
return CalendarEntityType.LOANS.name().equalsIgnoreCase(name) ? true : false;
|
return CalendarEntityType.LOANS.name().equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isClient(final Integer value) {
|
public static boolean isClient(final Integer value) {
|
||||||
return CalendarEntityType.CLIENTS.value.equals(value) ? true : false;
|
return CalendarEntityType.CLIENTS.value.equals(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isClient(final String name) {
|
public static boolean isClient(final String name) {
|
||||||
return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name) ? true : false;
|
return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSavings(final Integer value) {
|
||||||
|
return CalendarEntityType.SAVINGS.value.equals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSavings(final String name) {
|
||||||
|
return CalendarEntityType.SAVINGS.name().equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCenter() {
|
public boolean isCenter() {
|
||||||
return this.value.equals(CalendarEntityType.CENTERS.getValue());
|
return this == CENTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGroup() {
|
public boolean isGroup() {
|
||||||
return this.value.equals(CalendarEntityType.GROUPS.getValue());
|
return this == GROUPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoan() {
|
public boolean isLoan() {
|
||||||
return this.value.equals(CalendarEntityType.LOANS.getValue());
|
return this == LOANS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClient() {
|
public boolean isClient() {
|
||||||
return this.value.equals(CalendarEntityType.CLIENTS.getValue());
|
return this == CLIENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSavings() {
|
||||||
|
return this == SAVINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, CalendarEntityType> entityNameToEnumMap = new HashMap<>();
|
private static final Map<String, CalendarEntityType> entityNameToEnumMap = new HashMap<>();
|
||||||
@@ -146,17 +158,4 @@ public enum CalendarEntityType {
|
|||||||
public static CalendarEntityType getEntityType(String entityType) {
|
public static CalendarEntityType getEntityType(String entityType) {
|
||||||
return entityNameToEnumMap.get(entityType.toLowerCase());
|
return entityNameToEnumMap.get(entityType.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSavings(final Integer value) {
|
|
||||||
return CalendarEntityType.SAVINGS.value.equals(value) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isSavings(final String name) {
|
|
||||||
return CalendarEntityType.SAVINGS.name().equalsIgnoreCase(name) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSavings() {
|
|
||||||
return this.value.equals(CalendarEntityType.SAVINGS.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-9
@@ -25,6 +25,7 @@ import jakarta.persistence.ManyToOne;
|
|||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_calendar_history")
|
@Table(name = "m_calendar_history")
|
||||||
@@ -95,26 +96,24 @@ public class CalendarHistory extends AbstractPersistableCustom {
|
|||||||
return this.recurrence;
|
return this.recurrence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getStartDateLocalDate() {
|
public LocalDate getStartDate() {
|
||||||
return this.startDate;
|
return this.startDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getEndDateLocalDate() {
|
public LocalDate getEndDate() {
|
||||||
return this.endDate;
|
return this.endDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||||
return this.endDate != null && compareDate != null
|
return this.startDate != null && compareDate != null && !DateUtils.isAfter(this.startDate, compareDate);
|
||||||
&& (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||||
return this.startDate != null && compareDate != null
|
return this.endDate != null && compareDate != null && !DateUtils.isBefore(this.endDate, compareDate);
|
||||||
&& (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||||
return isStartDateBeforeOrEqual(compareDate) && (getEndDateLocalDate() == null || isEndDateAfterOrEqual(compareDate));
|
return isStartDateBeforeOrEqual(compareDate) && (getEndDate() == null || isEndDateAfterOrEqual(compareDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEndDate(LocalDate historyCalEndDate) {
|
public void updateEndDate(LocalDate historyCalEndDate) {
|
||||||
|
|||||||
+6
-8
@@ -103,14 +103,14 @@ public final class CalendarUtils {
|
|||||||
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
|
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
final Date seed = convertToiCal4JCompatibleDate(seedDate);
|
final Date seed = convertToiCal4JCompatibleDate(seedDate);
|
||||||
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
||||||
return nextRecDate == null ? null : LocalDateTime.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId());
|
return nextRecDate == null ? null : LocalDateTime.ofInstant(nextRecDate.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LocalDate getNextRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate startDate) {
|
private static LocalDate getNextRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate startDate) {
|
||||||
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
||||||
final Date seed = convertToiCal4JCompatibleDate(seedDate.atStartOfDay());
|
final Date seed = convertToiCal4JCompatibleDate(seedDate.atStartOfDay());
|
||||||
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
||||||
return nextRecDate == null ? null : LocalDate.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId());
|
return nextRecDate == null ? null : LocalDate.ofInstant(nextRecDate.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Date convertToiCal4JCompatibleDate(final LocalDateTime inputDate) {
|
private static Date convertToiCal4JCompatibleDate(final LocalDateTime inputDate) {
|
||||||
@@ -125,16 +125,16 @@ public final class CalendarUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) {
|
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) {
|
||||||
|
|
||||||
final LocalDate periodStartDate = DateUtils.getLocalDateOfTenant();
|
final LocalDate periodStartDate = DateUtils.getLocalDateOfTenant();
|
||||||
final LocalDate periodEndDate = (endDate == null) ? DateUtils.getLocalDateOfTenant().plusYears(5) : endDate;
|
final LocalDate periodEndDate = endDate == null ? periodStartDate.plusYears(5) : endDate;
|
||||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Collection<LocalDate> getRecurringDatesFrom(final String recurringRule, final LocalDate seedDate,
|
public static Collection<LocalDate> getRecurringDatesFrom(final String recurringRule, final LocalDate seedDate,
|
||||||
final LocalDate startDate) {
|
final LocalDate startDate) {
|
||||||
final LocalDate periodStartDate = (startDate == null) ? DateUtils.getLocalDateOfTenant() : startDate;
|
LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||||
final LocalDate periodEndDate = DateUtils.getLocalDateOfTenant().plusYears(5);
|
final LocalDate periodStartDate = startDate == null ? currentDate : startDate;
|
||||||
|
final LocalDate periodEndDate = currentDate.plusYears(5);
|
||||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,6 @@ public final class CalendarUtils {
|
|||||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||||
final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount, boolean isSkippMeetingOnFirstDay,
|
final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount, boolean isSkippMeetingOnFirstDay,
|
||||||
final Integer numberOfDays) {
|
final Integer numberOfDays) {
|
||||||
|
|
||||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||||
|
|
||||||
return getRecurringDates(recur, seedDate, periodStartDate, periodEndDate, maxCount, isSkippMeetingOnFirstDay, numberOfDays);
|
return getRecurringDates(recur, seedDate, periodStartDate, periodEndDate, maxCount, isSkippMeetingOnFirstDay, numberOfDays);
|
||||||
@@ -173,7 +172,6 @@ public final class CalendarUtils {
|
|||||||
|
|
||||||
private static Collection<LocalDate> convertToLocalDateList(final DateList dates, final LocalDate seedDate,
|
private static Collection<LocalDate> convertToLocalDateList(final DateList dates, final LocalDate seedDate,
|
||||||
final PeriodFrequencyType frequencyType, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) {
|
final PeriodFrequencyType frequencyType, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) {
|
||||||
|
|
||||||
final Collection<LocalDate> recurringDates = new ArrayList<>();
|
final Collection<LocalDate> recurringDates = new ArrayList<>();
|
||||||
|
|
||||||
for (@SuppressWarnings("rawtypes")
|
for (@SuppressWarnings("rawtypes")
|
||||||
|
|||||||
+9
-30
@@ -407,10 +407,6 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
return ClientStatus.fromInt(this.status).isPending();
|
return ClientStatus.fromInt(this.status).isPending();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDateInTheFuture(final LocalDate localDate) {
|
|
||||||
return localDate.isAfter(DateUtils.getBusinessLocalDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRejected() {
|
public boolean isRejected() {
|
||||||
return ClientStatus.fromInt(this.status).isRejected();
|
return ClientStatus.fromInt(this.status).isRejected();
|
||||||
}
|
}
|
||||||
@@ -444,49 +440,40 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||||
|
if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) {
|
||||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.in.the.future",
|
||||||
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (getActivationDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getActivationDate())) {
|
||||||
if (getActivationLocalDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getActivationLocalDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.activation.date",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.activation.date",
|
||||||
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (getActivationDate() != null && DateUtils.isAfter(getReopenedDate(), getActivationDate())) {
|
||||||
if (getReopenedDate() != null && getActivationLocalDate() != null && getReopenedDate().isAfter(getActivationLocalDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "reopened date cannot be after the submittedon date";
|
final String defaultUserMessage = "reopened date cannot be after the submittedon date";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.reopened.date",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.reopened.date",
|
||||||
defaultUserMessage, ClientApiConstants.reopenedDateParamName, this.reopenedDate);
|
defaultUserMessage, ClientApiConstants.reopenedDateParamName, this.reopenedDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (DateUtils.isDateInTheFuture(getActivationDate())) {
|
||||||
if (getActivationLocalDate() != null && isDateInTheFuture(getActivationLocalDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "Activation date cannot be in the future.";
|
final String defaultUserMessage = "Activation date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.activationDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.activationDate.in.the.future",
|
||||||
defaultUserMessage, ClientApiConstants.activationDateParamName, getActivationLocalDate());
|
defaultUserMessage, ClientApiConstants.activationDateParamName, getActivationDate());
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (getActivationDate() != null) {
|
||||||
if (getActivationLocalDate() != null) {
|
if (this.office.isOpeningDateAfter(getActivationDate())) {
|
||||||
if (this.office.isOpeningDateAfter(getActivationLocalDate())) {
|
|
||||||
final String defaultUserMessage = "Client activation date cannot be a date before the office opening date.";
|
final String defaultUserMessage = "Client activation date cannot be a date before the office opening date.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError(
|
final ApiParameterError error = ApiParameterError.parameterError(
|
||||||
"error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage,
|
"error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage,
|
||||||
ClientApiConstants.activationDateParamName, getActivationLocalDate());
|
ClientApiConstants.activationDateParamName, getActivationDate());
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,14 +505,6 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getActivationLocalDate() {
|
|
||||||
return this.activationDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDate getOfficeJoiningLocalDate() {
|
|
||||||
return this.officeJoiningDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOfficeIdentifiedBy(final Long officeId) {
|
public boolean isOfficeIdentifiedBy(final Long officeId) {
|
||||||
return this.office.identifiedBy(officeId);
|
return this.office.identifiedBy(officeId);
|
||||||
}
|
}
|
||||||
@@ -618,7 +597,7 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
||||||
return getActivationLocalDate().isAfter(submittedOn);
|
return DateUtils.isAfter(getActivationDate(), submittedOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChildOfGroup(final Long groupId) {
|
public boolean isChildOfGroup(final Long groupId) {
|
||||||
|
|||||||
+2
-1
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.floatingrates.data;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
public class FloatingRateDTO {
|
public class FloatingRateDTO {
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ public class FloatingRateDTO {
|
|||||||
BigDecimal rate = null;
|
BigDecimal rate = null;
|
||||||
for (FloatingRatePeriodData periodData : this.baseLendingRatePeriods) {
|
for (FloatingRatePeriodData periodData : this.baseLendingRatePeriods) {
|
||||||
final LocalDate periodFromDate = periodData.getFromDate();
|
final LocalDate periodFromDate = periodData.getFromDate();
|
||||||
if (periodFromDate.isBefore(date) || periodFromDate.isEqual(date)) {
|
if (!DateUtils.isAfter(periodFromDate, date)) {
|
||||||
rate = periodData.getInterestRate();
|
rate = periodData.getInterestRate();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -89,9 +89,8 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final String name = command.stringValueOfParameterNamed("name");
|
final String name = command.stringValueOfParameterNamed("name");
|
||||||
final boolean isBaseLendingRate = command.parameterExists("isBaseLendingRate")
|
final boolean isBaseLendingRate = command.parameterExists("isBaseLendingRate")
|
||||||
? command.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate")
|
&& command.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate");
|
||||||
: false;
|
final boolean isActive = !command.parameterExists("isActive") || command.booleanPrimitiveValueOfParameterNamed("isActive");
|
||||||
final boolean isActive = command.parameterExists("isActive") ? command.booleanPrimitiveValueOfParameterNamed("isActive") : true;
|
|
||||||
final List<FloatingRatePeriod> floatingRatePeriods = getRatePeriods(command);
|
final List<FloatingRatePeriod> floatingRatePeriods = getRatePeriods(command);
|
||||||
|
|
||||||
return new FloatingRate(name, isBaseLendingRate, isActive, floatingRatePeriods);
|
return new FloatingRate(name, isBaseLendingRate, isActive, floatingRatePeriods);
|
||||||
@@ -109,8 +108,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
final LocalDate fromDate = helper.extractLocalDateNamed("fromDate", ratePeriod, new HashSet<String>());
|
final LocalDate fromDate = helper.extractLocalDateNamed("fromDate", ratePeriod, new HashSet<String>());
|
||||||
final BigDecimal interestRate = ratePeriodObject.get("interestRate").getAsBigDecimal();
|
final BigDecimal interestRate = ratePeriodObject.get("interestRate").getAsBigDecimal();
|
||||||
final boolean isDifferentialToBaseLendingRate = helper.parameterExists("isDifferentialToBaseLendingRate", ratePeriod)
|
final boolean isDifferentialToBaseLendingRate = helper.parameterExists("isDifferentialToBaseLendingRate", ratePeriod)
|
||||||
? ratePeriodObject.get("isDifferentialToBaseLendingRate").getAsBoolean()
|
&& ratePeriodObject.get("isDifferentialToBaseLendingRate").getAsBoolean();
|
||||||
: false;
|
|
||||||
final boolean isActive = true;
|
final boolean isActive = true;
|
||||||
ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate, isDifferentialToBaseLendingRate, isActive));
|
ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate, isDifferentialToBaseLendingRate, isActive));
|
||||||
}
|
}
|
||||||
@@ -170,7 +168,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
if (this.floatingRatePeriods != null) {
|
if (this.floatingRatePeriods != null) {
|
||||||
for (FloatingRatePeriod ratePeriod : this.floatingRatePeriods) {
|
for (FloatingRatePeriod ratePeriod : this.floatingRatePeriods) {
|
||||||
LocalDate fromDate = ratePeriod.getFromDate();
|
LocalDate fromDate = ratePeriod.getFromDate();
|
||||||
if (fromDate.isAfter(today)) {
|
if (DateUtils.isAfter(fromDate, today)) {
|
||||||
ratePeriod.setActive(false);
|
ratePeriod.setActive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +186,7 @@ public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
for (FloatingRatePeriod floatingRatePeriod : this.floatingRatePeriods) {
|
for (FloatingRatePeriod floatingRatePeriod : this.floatingRatePeriods) {
|
||||||
if (floatingRatePeriod.isActive()) {
|
if (floatingRatePeriod.isActive()) {
|
||||||
// will enter
|
// will enter
|
||||||
if (applicableRates.isEmpty() && floatingRateDTO.getStartDate().isBefore(floatingRatePeriod.fetchFromDate())) {
|
if (applicableRates.isEmpty() && DateUtils.isBefore(floatingRateDTO.getStartDate(), floatingRatePeriod.fetchFromDate())) {
|
||||||
if (floatingRateDTO.isFloatingInterestRate()) {
|
if (floatingRateDTO.isFloatingInterestRate()) {
|
||||||
addPeriodData = true;
|
addPeriodData = true;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -340,7 +340,7 @@ public class GroupGeneralData implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChildGroup() {
|
public boolean isChildGroup() {
|
||||||
return this.centerId == null ? false : true;
|
return this.centerId != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getParentId() {
|
public Long getParentId() {
|
||||||
|
|||||||
+2
-1
@@ -25,6 +25,7 @@ import jakarta.persistence.ManyToOne;
|
|||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.staff.domain.Staff;
|
import org.apache.fineract.organisation.staff.domain.Staff;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -73,7 +74,7 @@ public class StaffAssignmentHistory extends AbstractAuditableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean matchesStartDateOf(final LocalDate matchingDate) {
|
public boolean matchesStartDateOf(final LocalDate matchingDate) {
|
||||||
return getStartDate().isEqual(matchingDate);
|
return DateUtils.isEqual(matchingDate, getStartDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getStartDate() {
|
public LocalDate getStartDate() {
|
||||||
|
|||||||
+2
-1
@@ -27,6 +27,7 @@ import java.util.Map;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class TaxComponentData implements Serializable {
|
public final class TaxComponentData implements Serializable {
|
||||||
@@ -136,7 +137,7 @@ public final class TaxComponentData implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFrom(final LocalDate target) {
|
private boolean occursOnDayFrom(final LocalDate target) {
|
||||||
return target != null && target.isAfter(startDate());
|
return DateUtils.isAfter(target, startDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate startDate() {
|
public LocalDate startDate() {
|
||||||
|
|||||||
+2
-4
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.tax.data;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
public class TaxComponentHistoryData implements Serializable {
|
public class TaxComponentHistoryData implements Serializable {
|
||||||
|
|
||||||
@@ -38,10 +39,7 @@ public class TaxComponentHistoryData implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
||||||
if (this.endDate == null) {
|
return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate()));
|
||||||
return target != null && target.isAfter(startDate());
|
|
||||||
}
|
|
||||||
return target != null && target.isAfter(startDate()) && !target.isAfter(endDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate startDate() {
|
public LocalDate startDate() {
|
||||||
|
|||||||
+2
-4
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.tax.data;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
public class TaxGroupMappingsData implements Serializable {
|
public class TaxGroupMappingsData implements Serializable {
|
||||||
|
|
||||||
@@ -44,10 +45,7 @@ public class TaxGroupMappingsData implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
||||||
if (this.endDate == null) {
|
return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate()));
|
||||||
return target != null && target.isAfter(startDate());
|
|
||||||
}
|
|
||||||
return target != null && target.isAfter(startDate()) && !target.isAfter(endDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate startDate() {
|
public LocalDate startDate() {
|
||||||
|
|||||||
+1
-1
@@ -167,7 +167,7 @@ public class TaxComponent extends AbstractAuditableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFrom(final LocalDate target) {
|
private boolean occursOnDayFrom(final LocalDate target) {
|
||||||
return target != null && target.isAfter(startDate());
|
return DateUtils.isAfter(target, startDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<TaxComponentHistory> getTaxComponentHistories() {
|
public Set<TaxComponentHistory> getTaxComponentHistories() {
|
||||||
|
|||||||
+2
-4
@@ -24,6 +24,7 @@ import jakarta.persistence.Table;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_tax_component_history")
|
@Table(name = "m_tax_component_history")
|
||||||
@@ -62,10 +63,7 @@ public class TaxComponentHistory extends AbstractAuditableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
||||||
if (this.endDate == null) {
|
return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate()));
|
||||||
return target != null && target.isAfter(startDate());
|
|
||||||
}
|
|
||||||
return target != null && target.isAfter(startDate()) && !target.isAfter(endDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getPercentage() {
|
public BigDecimal getPercentage() {
|
||||||
|
|||||||
+2
-4
@@ -28,6 +28,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.tax.api.TaxApiConstants;
|
import org.apache.fineract.portfolio.tax.api.TaxApiConstants;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -81,10 +82,7 @@ public class TaxGroupMappings extends AbstractAuditableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) {
|
||||||
if (this.endDate == null) {
|
return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate()));
|
||||||
return target != null && target.isAfter(startDate());
|
|
||||||
}
|
|
||||||
return target != null && target.isAfter(startDate()) && !target.isAfter(endDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaxComponent getTaxComponent() {
|
public TaxComponent getTaxComponent() {
|
||||||
|
|||||||
+2
@@ -30,4 +30,6 @@ public final class AppUserConstants {
|
|||||||
|
|
||||||
// TODO: Remove hard coding of system user name and make this a configurable parameter
|
// TODO: Remove hard coding of system user name and make this a configurable parameter
|
||||||
public static final String SYSTEM_USER_NAME = "system";
|
public static final String SYSTEM_USER_NAME = "system";
|
||||||
|
public static final Long ADMIN_USER_ID = 1L;
|
||||||
|
public static final Long SYSTEM_USER_ID = 2L;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -37,6 +37,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioPr
|
|||||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMapping;
|
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMapping;
|
||||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||||
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.office.domain.Office;
|
import org.apache.fineract.organisation.office.domain.Office;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ public class InvestorAccountingHelper {
|
|||||||
**/
|
**/
|
||||||
GLClosure gLClosure = getLatestClosureByBranch(officeId);
|
GLClosure gLClosure = getLatestClosureByBranch(officeId);
|
||||||
if (gLClosure != null) {
|
if (gLClosure != null) {
|
||||||
if (gLClosure.getClosingDate().isAfter(transactionDate) || gLClosure.getClosingDate().isEqual(transactionDate)) {
|
if (!DateUtils.isAfter(transactionDate, gLClosure.getClosingDate())) {
|
||||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, gLClosure.getClosingDate(), null,
|
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, gLClosure.getClosingDate(), null,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -170,7 +170,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
|
|||||||
throw new ExternalAssetOwnerInitiateTransferException(
|
throw new ExternalAssetOwnerInitiateTransferException(
|
||||||
String.format("This loan cannot be bought back, effective transfer is not in right state: %s",
|
String.format("This loan cannot be bought back, effective transfer is not in right state: %s",
|
||||||
effectiveTransfers.get(0).getStatus()));
|
effectiveTransfers.get(0).getStatus()));
|
||||||
} else if (settlementDate.isBefore(effectiveTransfers.get(0).getSettlementDate())) {
|
} else if (DateUtils.isBefore(settlementDate, effectiveTransfers.get(0).getSettlementDate())) {
|
||||||
throw new ExternalAssetOwnerInitiateTransferException(
|
throw new ExternalAssetOwnerInitiateTransferException(
|
||||||
String.format("This loan cannot be bought back, settlement date is earlier than effective transfer settlement date: %s",
|
String.format("This loan cannot be bought back, settlement date is earlier than effective transfer settlement date: %s",
|
||||||
effectiveTransfers.get(0).getSettlementDate()));
|
effectiveTransfers.get(0).getSettlementDate()));
|
||||||
@@ -251,7 +251,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateSettlementDate(LocalDate settlementDate) {
|
private void validateSettlementDate(LocalDate settlementDate) {
|
||||||
if (settlementDate.isBefore(ThreadLocalContextUtil.getBusinessDate())) {
|
if (DateUtils.isBeforeBusinessDate(settlementDate)) {
|
||||||
throw new ExternalAssetOwnerInitiateTransferException("Settlement date cannot be in the past");
|
throw new ExternalAssetOwnerInitiateTransferException("Settlement date cannot be in the past");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing disbursement information.
|
* Immutable data object representing disbursement information.
|
||||||
@@ -85,8 +86,7 @@ public final class DisbursementData implements Comparable<DisbursementData> {
|
|||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return DateUtils.compare(obj.expectedDisbursementDate, this.expectedDisbursementDate);
|
||||||
return obj.expectedDisbursementDate.compareTo(this.expectedDisbursementDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDueForDisbursement(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
public boolean isDueForDisbursement(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
||||||
@@ -96,14 +96,11 @@ public final class DisbursementData implements Comparable<DisbursementData> {
|
|||||||
|
|
||||||
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
||||||
final LocalDate target) {
|
final LocalDate target) {
|
||||||
return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToAndInclusive);
|
return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToAndInclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getWaivedChargeAmount() {
|
public BigDecimal getWaivedChargeAmount() {
|
||||||
if (this.waivedChargeAmount == null) {
|
return this.waivedChargeAmount == null ? BigDecimal.ZERO : this.waivedChargeAmount;
|
||||||
return BigDecimal.ZERO;
|
|
||||||
}
|
|
||||||
return this.waivedChargeAmount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -64,7 +65,7 @@ public class LoanTermVariationsData implements Comparable<LoanTermVariationsData
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFromAndUpTo(final LocalDate fromNotInclusive, final LocalDate upToInclusive, final LocalDate target) {
|
private boolean occursOnDayFromAndUpTo(final LocalDate fromNotInclusive, final LocalDate upToInclusive, final LocalDate target) {
|
||||||
return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToInclusive);
|
return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToInclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isApplicable(final LocalDate fromDate) {
|
public boolean isApplicable(final LocalDate fromDate) {
|
||||||
@@ -72,7 +73,7 @@ public class LoanTermVariationsData implements Comparable<LoanTermVariationsData
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursBefore(final LocalDate date, final LocalDate target) {
|
private boolean occursBefore(final LocalDate date, final LocalDate target) {
|
||||||
return target != null && !target.isAfter(date);
|
return target != null && !DateUtils.isAfter(target, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSpecificToInstallment() {
|
public boolean isSpecificToInstallment() {
|
||||||
@@ -84,7 +85,7 @@ public class LoanTermVariationsData implements Comparable<LoanTermVariationsData
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isProcessed() {
|
public Boolean isProcessed() {
|
||||||
return this.isProcessed == null ? false : this.isProcessed;
|
return this.isProcessed != null && this.isProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProcessed(Boolean isProcessed) {
|
public void setProcessed(Boolean isProcessed) {
|
||||||
|
|||||||
+3
-2
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
public class LoanTermVariationsDataWrapper {
|
public class LoanTermVariationsDataWrapper {
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ public class LoanTermVariationsDataWrapper {
|
|||||||
boolean hasVariation = false;
|
boolean hasVariation = false;
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
LoanTermVariationsData loanTermVariationsData = iterator.next();
|
LoanTermVariationsData loanTermVariationsData = iterator.next();
|
||||||
if (!loanTermVariationsData.getTermVariationApplicableFrom().isAfter(date)) {
|
if (!DateUtils.isAfter(loanTermVariationsData.getTermVariationApplicableFrom(), date)) {
|
||||||
hasVariation = true;
|
hasVariation = true;
|
||||||
}
|
}
|
||||||
iterator.previous();
|
iterator.previous();
|
||||||
@@ -123,7 +124,7 @@ public class LoanTermVariationsDataWrapper {
|
|||||||
public LoanTermVariationsData fetchLoanTermDueDateVariationsData(final LocalDate onDate) {
|
public LoanTermVariationsData fetchLoanTermDueDateVariationsData(final LocalDate onDate) {
|
||||||
LoanTermVariationsData data = null;
|
LoanTermVariationsData data = null;
|
||||||
for (LoanTermVariationsData termVariationsData : this.dueDateVariation) {
|
for (LoanTermVariationsData termVariationsData : this.dueDateVariation) {
|
||||||
if (onDate.isEqual(termVariationsData.getTermVariationApplicableFrom())) {
|
if (DateUtils.isEqual(onDate, termVariationsData.getTermVariationApplicableFrom())) {
|
||||||
data = termVariationsData;
|
data = termVariationsData;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-15
@@ -2352,8 +2352,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
final LocalDate submittalDate = this.submittedOnDate;
|
final LocalDate submittalDate = this.submittedOnDate;
|
||||||
if (DateUtils.isBefore(approvedOn, submittalDate)) {
|
if (DateUtils.isBefore(approvedOn, submittalDate)) {
|
||||||
final String errorMessage = "The date on which a loan is approved cannot be before its submittal date: "
|
final String errorMessage = "The date on which a loan is approved cannot be before its submittal date: " + submittalDate;
|
||||||
+ submittalDate.toString();
|
|
||||||
throw new InvalidLoanStateTransitionException("approval", "cannot.be.before.submittal.date", errorMessage,
|
throw new InvalidLoanStateTransitionException("approval", "cannot.be.before.submittal.date", errorMessage,
|
||||||
getApprovedOnDate(), submittalDate);
|
getApprovedOnDate(), submittalDate);
|
||||||
}
|
}
|
||||||
@@ -3394,8 +3393,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
incomePostTransactions.add(transaction);
|
incomePostTransactions.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
incomePostTransactions.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(incomePostTransactions, transactionComparator);
|
|
||||||
return incomePostTransactions;
|
return incomePostTransactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3408,8 +3406,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
repaymentsOrWaivers.add(transaction);
|
repaymentsOrWaivers.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
repaymentsOrWaivers.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(repaymentsOrWaivers, transactionComparator);
|
|
||||||
return repaymentsOrWaivers;
|
return repaymentsOrWaivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3422,8 +3419,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
repaymentsOrWaivers.add(transaction);
|
repaymentsOrWaivers.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
repaymentsOrWaivers.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(repaymentsOrWaivers, transactionComparator);
|
|
||||||
return repaymentsOrWaivers;
|
return repaymentsOrWaivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3434,8 +3430,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
repaymentsOrWaivers.add(transaction);
|
repaymentsOrWaivers.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
repaymentsOrWaivers.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(repaymentsOrWaivers, transactionComparator);
|
|
||||||
return repaymentsOrWaivers;
|
return repaymentsOrWaivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3446,8 +3441,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
transactions.add(transaction);
|
transactions.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
transactions.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(transactions, transactionComparator);
|
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3458,8 +3452,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
transactions.add(transaction);
|
transactions.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
|
transactions.sort(LoanTransactionComparator.INSTANCE);
|
||||||
Collections.sort(transactions, transactionComparator);
|
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6670,7 +6663,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
paidFromFutureInstallments = paidFromFutureInstallments.plus(balancesForCurrentPeroid[4])
|
paidFromFutureInstallments = paidFromFutureInstallments.plus(balancesForCurrentPeroid[4])
|
||||||
.minus(balancesForCurrentPeroid[2]);
|
.minus(balancesForCurrentPeroid[2]);
|
||||||
}
|
}
|
||||||
} else if (installment.getDueDate().isAfter(paymentDate)) {
|
} else {
|
||||||
paidFromFutureInstallments = paidFromFutureInstallments.plus(installment.getInterestPaid(currency))
|
paidFromFutureInstallments = paidFromFutureInstallments.plus(installment.getInterestPaid(currency))
|
||||||
.plus(installment.getPenaltyChargesPaid(currency)).plus(installment.getFeeChargesPaid(currency));
|
.plus(installment.getPenaltyChargesPaid(currency)).plus(installment.getFeeChargesPaid(currency));
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-13
@@ -363,13 +363,11 @@ public class LoanCharge extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
if (this.loan != null) {
|
if (this.loan != null) {
|
||||||
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
||||||
case PERCENT_OF_AMOUNT:
|
case PERCENT_OF_AMOUNT:
|
||||||
// If charge type is specified due date and loan is multi
|
// If charge type is specified due date and loan is multi disburment loan.
|
||||||
// disburment loan.
|
// Then we need to get as of this loan charge due date how much amount disbursed.
|
||||||
// Then we need to get as of this loan charge due date how
|
|
||||||
// much amount disbursed.
|
|
||||||
if (this.loan.isMultiDisburmentLoan() && this.isSpecifiedDueDate()) {
|
if (this.loan.isMultiDisburmentLoan() && this.isSpecifiedDueDate()) {
|
||||||
for (final LoanDisbursementDetails loanDisbursementDetails : this.loan.getDisbursementDetails()) {
|
for (final LoanDisbursementDetails loanDisbursementDetails : this.loan.getDisbursementDetails()) {
|
||||||
if (!loanDisbursementDetails.expectedDisbursementDate().isAfter(this.getDueDate())) {
|
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), this.getDueDate())) {
|
||||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal());
|
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,13 +633,12 @@ public class LoanCharge extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
private boolean occursOnDayFromExclusiveAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
private boolean occursOnDayFromExclusiveAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
||||||
final LocalDate target) {
|
final LocalDate target) {
|
||||||
return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToAndInclusive);
|
return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToAndInclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromAndInclusive, final LocalDate upToAndInclusive,
|
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromAndInclusive, final LocalDate upToAndInclusive,
|
||||||
final LocalDate target) {
|
final LocalDate target) {
|
||||||
return target != null && (target.isEqual(fromAndInclusive) || target.isAfter(fromAndInclusive))
|
return target != null && !DateUtils.isBefore(target, fromAndInclusive) && !DateUtils.isAfter(target, upToAndInclusive);
|
||||||
&& !target.isAfter(upToAndInclusive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFeeCharge() {
|
public boolean isFeeCharge() {
|
||||||
@@ -792,8 +789,9 @@ public class LoanCharge extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
public LoanInstallmentCharge getUnpaidInstallmentLoanCharge() {
|
public LoanInstallmentCharge getUnpaidInstallmentLoanCharge() {
|
||||||
LoanInstallmentCharge unpaidChargePerInstallment = null;
|
LoanInstallmentCharge unpaidChargePerInstallment = null;
|
||||||
for (final LoanInstallmentCharge loanChargePerInstallment : this.loanInstallmentCharge) {
|
for (final LoanInstallmentCharge loanChargePerInstallment : this.loanInstallmentCharge) {
|
||||||
if (loanChargePerInstallment.isPending() && (unpaidChargePerInstallment == null || unpaidChargePerInstallment
|
if (loanChargePerInstallment.isPending() && (unpaidChargePerInstallment == null
|
||||||
.getRepaymentInstallment().getDueDate().isAfter(loanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
|| DateUtils.isAfter(unpaidChargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||||
|
loanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||||
unpaidChargePerInstallment = loanChargePerInstallment;
|
unpaidChargePerInstallment = loanChargePerInstallment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -802,7 +800,7 @@ public class LoanCharge extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
|
|
||||||
public LoanInstallmentCharge getInstallmentLoanCharge(final LocalDate periodDueDate) {
|
public LoanInstallmentCharge getInstallmentLoanCharge(final LocalDate periodDueDate) {
|
||||||
for (final LoanInstallmentCharge loanChargePerInstallment : this.loanInstallmentCharge) {
|
for (final LoanInstallmentCharge loanChargePerInstallment : this.loanInstallmentCharge) {
|
||||||
if (periodDueDate.isEqual(loanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
if (DateUtils.isEqual(periodDueDate, loanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
||||||
return loanChargePerInstallment;
|
return loanChargePerInstallment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -974,8 +972,9 @@ public class LoanCharge extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
Money outstanding = Money.of(currency, loanChargePerInstallment.getAmountOutstanding());
|
Money outstanding = Money.of(currency, loanChargePerInstallment.getAmountOutstanding());
|
||||||
final boolean partiallyPaid = outstanding.isGreaterThanZero()
|
final boolean partiallyPaid = outstanding.isGreaterThanZero()
|
||||||
&& outstanding.isLessThan(loanChargePerInstallment.getAmount(currency));
|
&& outstanding.isLessThan(loanChargePerInstallment.getAmount(currency));
|
||||||
if ((partiallyPaid || loanChargePerInstallment.isPaid()) && (paidChargePerInstallment == null || paidChargePerInstallment
|
if ((partiallyPaid || loanChargePerInstallment.isPaid()) && (paidChargePerInstallment == null
|
||||||
.getRepaymentInstallment().getDueDate().isBefore(loanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
|| DateUtils.isBefore(paidChargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||||
|
loanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||||
paidChargePerInstallment = loanChargePerInstallment;
|
paidChargePerInstallment = loanChargePerInstallment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-8
@@ -27,6 +27,7 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -71,16 +72,11 @@ public class LoanDisbursementDetails extends AbstractPersistableCustom {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if (!(obj instanceof LoanDisbursementDetails)) {
|
if (!(obj instanceof LoanDisbursementDetails loanDisbursementDetails)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final LoanDisbursementDetails loanDisbursementDetails = (LoanDisbursementDetails) obj;
|
return loanDisbursementDetails.principal.equals(this.principal)
|
||||||
if (loanDisbursementDetails.principal.equals(this.principal)
|
&& DateUtils.isEqual(loanDisbursementDetails.expectedDisbursementDate, this.expectedDisbursementDate);
|
||||||
&& loanDisbursementDetails.expectedDisbursementDate.compareTo(this.expectedDisbursementDate) == 0 ? Boolean.TRUE
|
|
||||||
: Boolean.FALSE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-1
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
if (loanCharge.getLoan() != null && loanCharge.isSpecifiedDueDate()
|
if (loanCharge.getLoan() != null && loanCharge.isSpecifiedDueDate()
|
||||||
&& loanCharge.getLoan().isMultiDisburmentLoan()) {
|
&& loanCharge.getLoan().isMultiDisburmentLoan()) {
|
||||||
for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) {
|
for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) {
|
||||||
if (!loanDisbursementDetails.expectedDisbursementDate().isAfter(loanCharge.getDueDate())) {
|
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) {
|
||||||
amount = amount.add(loanDisbursementDetails.principal());
|
amount = amount.add(loanDisbursementDetails.principal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -230,7 +231,7 @@ public final class LoanSummaryWrapper {
|
|||||||
if (totalOverdue.isGreaterThanZero()) {
|
if (totalOverdue.isGreaterThanZero()) {
|
||||||
for (final LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) {
|
for (final LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) {
|
||||||
if (installment.isOverdueOn(from)) {
|
if (installment.isOverdueOn(from)) {
|
||||||
if (overdueSince == null || overdueSince.isAfter(installment.getDueDate())) {
|
if (overdueSince == null || DateUtils.isAfter(overdueSince, installment.getDueDate())) {
|
||||||
overdueSince = installment.getDueDate();
|
overdueSince = installment.getDueDate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-24
@@ -29,7 +29,6 @@ import jakarta.persistence.Table;
|
|||||||
import jakarta.persistence.UniqueConstraint;
|
import jakarta.persistence.UniqueConstraint;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -850,29 +849,6 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
this.manuallyAdjustedOrReversed = true;
|
this.manuallyAdjustedOrReversed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public OffsetDateTime getCreatedDateTime() {
|
|
||||||
return (this.getCreatedDate().isPresent() ? this.getCreatedDate().get() : DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLastTransaction(final LoanTransaction loanTransaction) {
|
|
||||||
boolean isLatest = false;
|
|
||||||
if (loanTransaction != null) {
|
|
||||||
isLatest = this.getTransactionDate().isBefore(loanTransaction.getTransactionDate())
|
|
||||||
|| (this.getTransactionDate().isEqual(loanTransaction.getTransactionDate())
|
|
||||||
&& this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime()));
|
|
||||||
}
|
|
||||||
return isLatest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLatestTransaction(final LoanTransaction loanTransaction) {
|
|
||||||
boolean isLatest = false;
|
|
||||||
if (loanTransaction != null) {
|
|
||||||
isLatest = this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime());
|
|
||||||
}
|
|
||||||
return isLatest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateLoanTransactionToRepaymentScheduleMappings(final Collection<LoanTransactionToRepaymentScheduleMapping> mappings) {
|
public void updateLoanTransactionToRepaymentScheduleMappings(final Collection<LoanTransactionToRepaymentScheduleMapping> mappings) {
|
||||||
Collection<LoanTransactionToRepaymentScheduleMapping> retainMappings = new ArrayList<>();
|
Collection<LoanTransactionToRepaymentScheduleMapping> retainMappings = new ArrayList<>();
|
||||||
for (LoanTransactionToRepaymentScheduleMapping updatedrepaymentScheduleMapping : mappings) {
|
for (LoanTransactionToRepaymentScheduleMapping updatedrepaymentScheduleMapping : mappings) {
|
||||||
@@ -963,6 +939,18 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBefore(final LocalDate date) {
|
||||||
|
return DateUtils.isBefore(getTransactionDate(), date);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAfter(final LocalDate date) {
|
||||||
|
return DateUtils.isAfter(getTransactionDate(), date);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOn(final LocalDate date) {
|
||||||
|
return DateUtils.isEqual(getTransactionDate(), date);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO missing hashCode(), equals(Object obj), but probably OK as long as
|
// TODO missing hashCode(), equals(Object obj), but probably OK as long as
|
||||||
// this is never stored in a Collection.
|
// this is never stored in a Collection.
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-33
@@ -19,47 +19,40 @@
|
|||||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort loan transactions by transaction date, created date and transaction type placing
|
* Sort loan transactions by transaction date, created date and transaction type placing
|
||||||
*/
|
*/
|
||||||
public class LoanTransactionComparator implements Comparator<LoanTransaction> {
|
public class LoanTransactionComparator implements Comparator<LoanTransaction> {
|
||||||
|
|
||||||
|
public static final LoanTransactionComparator INSTANCE = new LoanTransactionComparator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(final LoanTransaction o1, final LoanTransaction o2) {
|
public int compare(final LoanTransaction o1, final LoanTransaction o2) {
|
||||||
int compareResult = 0;
|
int result = DateUtils.compare(o1.getTransactionDate(), o2.getTransactionDate());
|
||||||
final int comparsion = o1.getTransactionDate().compareTo(o2.getTransactionDate());
|
if (result != 0) {
|
||||||
/**
|
return result;
|
||||||
* For transactions bearing the same transaction date, we sort transactions based on created date (when
|
|
||||||
* available) after which sorting for waivers takes place
|
|
||||||
**/
|
|
||||||
if (comparsion == 0) {
|
|
||||||
int comparisonBasedOnCreatedDate = 0;
|
|
||||||
if (o1.isIncomePosting() && o2.isNotIncomePosting()) {
|
|
||||||
compareResult = -1;
|
|
||||||
} else if (o1.isNotIncomePosting() && o2.isIncomePosting()) {
|
|
||||||
compareResult = 1;
|
|
||||||
} else {
|
|
||||||
compareResult = 0;
|
|
||||||
}
|
|
||||||
if (o1.getCreatedDateTime() != null && o2.getCreatedDateTime() != null) {
|
|
||||||
comparisonBasedOnCreatedDate = o1.getCreatedDateTime().compareTo(o2.getCreatedDateTime());
|
|
||||||
}
|
|
||||||
// equal transaction dates
|
|
||||||
if (comparisonBasedOnCreatedDate == 0) {
|
|
||||||
if (o1.isWaiver() && o2.isNotWaiver()) {
|
|
||||||
compareResult = -1;
|
|
||||||
} else if (o1.isNotWaiver() && o2.isWaiver()) {
|
|
||||||
compareResult = 1;
|
|
||||||
} else {
|
|
||||||
compareResult = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
compareResult = comparsion;
|
|
||||||
}
|
}
|
||||||
|
// For transactions bearing the same transaction date, we sort transactions based on created date (when
|
||||||
return compareResult;
|
// available) after which sorting for waivers takes place
|
||||||
|
result = o1.getCreatedDate().isPresent()
|
||||||
|
? (o2.getCreatedDate().isPresent() ? DateUtils.compare(o1.getCreatedDateTime(), o2.getCreatedDateTime()) : -1)
|
||||||
|
: (o2.getCreatedDate().isPresent() ? 1 : 0);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// equal transaction dates
|
||||||
|
if (o1.isIncomePosting() != o2.isIncomePosting()) {
|
||||||
|
return o1.isIncomePosting() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (o1.isWaiver() != o2.isWaiver()) {
|
||||||
|
return o1.isWaiver() ? -1 : 1;
|
||||||
|
}
|
||||||
|
result = o1.getId() != null ? (o2.getId() != null ? Long.compare(o1.getId(), o2.getId()) : -1) : (o2.getId() != null ? 1 : 0);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-23
@@ -200,11 +200,7 @@ public final class LoanSchedulePeriodData {
|
|||||||
this.totalOutstandingForPeriod = this.feeChargesOutstanding;
|
this.totalOutstandingForPeriod = this.feeChargesOutstanding;
|
||||||
this.totalActualCostOfLoanForPeriod = this.feeChargesDue;
|
this.totalActualCostOfLoanForPeriod = this.feeChargesDue;
|
||||||
this.totalInstallmentAmountForPeriod = null;
|
this.totalInstallmentAmountForPeriod = null;
|
||||||
if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) {
|
this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null;
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
|
||||||
} else {
|
|
||||||
this.totalOverdue = null;
|
|
||||||
}
|
|
||||||
this.totalCredits = BigDecimal.ZERO;
|
this.totalCredits = BigDecimal.ZERO;
|
||||||
this.downPaymentPeriod = false;
|
this.downPaymentPeriod = false;
|
||||||
}
|
}
|
||||||
@@ -263,12 +259,7 @@ public final class LoanSchedulePeriodData {
|
|||||||
this.totalOutstandingForPeriod = totalDueForPeriod;
|
this.totalOutstandingForPeriod = totalDueForPeriod;
|
||||||
this.totalActualCostOfLoanForPeriod = interestDueOnPrincipalOutstanding.add(feeChargesDueForPeriod);
|
this.totalActualCostOfLoanForPeriod = interestDueOnPrincipalOutstanding.add(feeChargesDueForPeriod);
|
||||||
this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod;
|
this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod;
|
||||||
|
this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null;
|
||||||
if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) {
|
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
|
||||||
} else {
|
|
||||||
this.totalOverdue = null;
|
|
||||||
}
|
|
||||||
this.totalCredits = BigDecimal.ZERO;
|
this.totalCredits = BigDecimal.ZERO;
|
||||||
this.downPaymentPeriod = false;
|
this.downPaymentPeriod = false;
|
||||||
}
|
}
|
||||||
@@ -322,12 +313,7 @@ public final class LoanSchedulePeriodData {
|
|||||||
this.totalOutstandingForPeriod = totalDueForPeriod;
|
this.totalOutstandingForPeriod = totalDueForPeriod;
|
||||||
this.totalActualCostOfLoanForPeriod = null;
|
this.totalActualCostOfLoanForPeriod = null;
|
||||||
this.totalInstallmentAmountForPeriod = totalDueForPeriod;
|
this.totalInstallmentAmountForPeriod = totalDueForPeriod;
|
||||||
|
this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null;
|
||||||
if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) {
|
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
|
||||||
} else {
|
|
||||||
this.totalOverdue = null;
|
|
||||||
}
|
|
||||||
this.totalCredits = BigDecimal.ZERO;
|
this.totalCredits = BigDecimal.ZERO;
|
||||||
this.downPaymentPeriod = true;
|
this.downPaymentPeriod = true;
|
||||||
}
|
}
|
||||||
@@ -396,12 +382,7 @@ public final class LoanSchedulePeriodData {
|
|||||||
this.totalOutstandingForPeriod = totalOutstanding;
|
this.totalOutstandingForPeriod = totalOutstanding;
|
||||||
this.totalActualCostOfLoanForPeriod = totalActualCostOfLoanForPeriod;
|
this.totalActualCostOfLoanForPeriod = totalActualCostOfLoanForPeriod;
|
||||||
this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod;
|
this.totalInstallmentAmountForPeriod = totalInstallmentAmountForPeriod;
|
||||||
|
this.totalOverdue = DateUtils.isBeforeBusinessDate(dueDate) ? this.totalOutstandingForPeriod : null;
|
||||||
if (dueDate.isBefore(DateUtils.getBusinessLocalDate())) {
|
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
|
||||||
} else {
|
|
||||||
this.totalOverdue = null;
|
|
||||||
}
|
|
||||||
this.totalCredits = totalCredits;
|
this.totalCredits = totalCredits;
|
||||||
this.downPaymentPeriod = isDownPayment;
|
this.downPaymentPeriod = isDownPayment;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@@ -26,6 +27,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
@@ -716,7 +718,7 @@ public final class LoanApplicationTerms {
|
|||||||
// number of days from 'ideal disbursement' to final date
|
// number of days from 'ideal disbursement' to final date
|
||||||
|
|
||||||
LocalDate loanStartDate = getExpectedDisbursementDate();
|
LocalDate loanStartDate = getExpectedDisbursementDate();
|
||||||
if (getInterestChargedFromDate() != null && loanStartDate.isBefore(getInterestChargedFromLocalDate())) {
|
if (DateUtils.isBefore(loanStartDate, getInterestChargedFromLocalDate())) {
|
||||||
loanStartDate = getInterestChargedFromLocalDate();
|
loanStartDate = getInterestChargedFromLocalDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,7 +775,7 @@ public final class LoanApplicationTerms {
|
|||||||
CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(getLoanTermPeriodFrequencyType()),
|
CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(getLoanTermPeriodFrequencyType()),
|
||||||
this.holidayDetailDTO.getWorkingDays(), isSkipRepaymentOnFirstDayOfMonth, numberOfDays);
|
this.holidayDetailDTO.getWorkingDays(), isSkipRepaymentOnFirstDayOfMonth, numberOfDays);
|
||||||
}
|
}
|
||||||
if (!expectedStartDate.isEqual(startDate)) {
|
if (!DateUtils.isEqual(expectedStartDate, startDate)) {
|
||||||
diffDays = Math.toIntExact(ChronoUnit.DAYS.between(startDate, expectedStartDate));
|
diffDays = Math.toIntExact(ChronoUnit.DAYS.between(startDate, expectedStartDate));
|
||||||
}
|
}
|
||||||
if (numberOfMonths == 0) {
|
if (numberOfMonths == 0) {
|
||||||
@@ -1368,6 +1370,7 @@ public final class LoanApplicationTerms {
|
|||||||
return this.multiDisburseLoan;
|
return this.multiDisburseLoan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public Money getMaxOutstandingBalance() {
|
public Money getMaxOutstandingBalance() {
|
||||||
return Money.of(getCurrency(), this.maxOutstandingBalance);
|
return Money.of(getCurrency(), this.maxOutstandingBalance);
|
||||||
}
|
}
|
||||||
@@ -1440,7 +1443,7 @@ public final class LoanApplicationTerms {
|
|||||||
|
|
||||||
int months = getPeriodsBetween(fromDate, toDate);
|
int months = getPeriodsBetween(fromDate, toDate);
|
||||||
fromDate = fromDate.plusMonths(months);
|
fromDate = fromDate.plusMonths(months);
|
||||||
isSameAsRepaymentPeriod = fromDate.isEqual(toDate);
|
isSameAsRepaymentPeriod = DateUtils.isEqual(fromDate, toDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
+3
-5
@@ -59,6 +59,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGL
|
|||||||
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.office.domain.Office;
|
import org.apache.fineract.organisation.office.domain.Office;
|
||||||
@@ -502,12 +503,9 @@ public class AccountingProcessorHelper {
|
|||||||
* @param transactionDate
|
* @param transactionDate
|
||||||
*/
|
*/
|
||||||
public void checkForBranchClosures(final GLClosure latestGLClosure, final LocalDate transactionDate) {
|
public void checkForBranchClosures(final GLClosure latestGLClosure, final LocalDate transactionDate) {
|
||||||
/**
|
// check if an accounting closure has happened for this branch after the transaction Date
|
||||||
* check if an accounting closure has happened for this branch after the transaction Date
|
|
||||||
**/
|
|
||||||
if (latestGLClosure != null) {
|
if (latestGLClosure != null) {
|
||||||
if (latestGLClosure.getClosingDate().isAfter(transactionDate)
|
if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) {
|
||||||
|| latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
|
||||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
||||||
null, null);
|
null, null);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -175,8 +175,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
|
|||||||
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
||||||
|
|
||||||
params.add(new Object[] { Boolean.TRUE, runningBalance, officeRunningBalance,
|
params.add(new Object[] { Boolean.TRUE, runningBalance, officeRunningBalance,
|
||||||
platformSecurityContext.authenticatedUser().getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
|
platformSecurityContext.authenticatedUser().getId(), DateUtils.getAuditOffsetDateTime(), entryData.getId() });
|
||||||
entryData.getId() });
|
|
||||||
batchIndex++;
|
batchIndex++;
|
||||||
if (batchIndex == batchUpdateSize || index == entryDataList.size() - 1) {
|
if (batchIndex == batchUpdateSize || index == entryDataList.size() - 1) {
|
||||||
this.jdbcTemplate.batchUpdate(sql, params);
|
this.jdbcTemplate.batchUpdate(sql, params);
|
||||||
@@ -213,7 +212,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
|
|||||||
for (JournalEntryData entryData : entryDataList) {
|
for (JournalEntryData entryData : entryDataList) {
|
||||||
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
||||||
params.add(new Object[] { runningBalance, platformSecurityContext.authenticatedUser().getId(),
|
params.add(new Object[] { runningBalance, platformSecurityContext.authenticatedUser().getId(),
|
||||||
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), entryData.getId() });
|
DateUtils.getAuditOffsetDateTime(), entryData.getId() });
|
||||||
}
|
}
|
||||||
this.jdbcTemplate.batchUpdate(sql, params);
|
this.jdbcTemplate.batchUpdate(sql, params);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-9
@@ -314,9 +314,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
|||||||
final LocalDate journalEntriesTransactionDate = journalEntries.get(0).getTransactionDate();
|
final LocalDate journalEntriesTransactionDate = journalEntries.get(0).getTransactionDate();
|
||||||
final GLClosure latestGLClosureByBranch = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
|
final GLClosure latestGLClosureByBranch = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
|
||||||
if (latestGLClosureByBranch != null) {
|
if (latestGLClosureByBranch != null) {
|
||||||
if (latestGLClosureByBranch.getClosingDate().isAfter(journalEntriesTransactionDate)
|
if (!DateUtils.isBefore(latestGLClosureByBranch.getClosingDate(), journalEntriesTransactionDate)) {
|
||||||
|| latestGLClosureByBranch.getClosingDate().compareTo(journalEntriesTransactionDate) == 0 ? Boolean.TRUE
|
|
||||||
: Boolean.FALSE) {
|
|
||||||
final String accountName = null;
|
final String accountName = null;
|
||||||
final String accountGLCode = null;
|
final String accountGLCode = null;
|
||||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED,
|
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED,
|
||||||
@@ -555,24 +553,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateBusinessRulesForJournalEntries(final JournalEntryCommand command) {
|
private void validateBusinessRulesForJournalEntries(final JournalEntryCommand command) {
|
||||||
/** check if date of Journal entry is valid ***/
|
// check if date of Journal entry is valid
|
||||||
final LocalDate transactionDate = command.getTransactionDate();
|
final LocalDate transactionDate = command.getTransactionDate();
|
||||||
// shouldn't be in the future
|
// shouldn't be in the future
|
||||||
final LocalDate todaysDate = DateUtils.getBusinessLocalDate();
|
if (DateUtils.isDateInTheFuture(transactionDate)) {
|
||||||
if (transactionDate.isAfter(todaysDate)) {
|
|
||||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.FUTURE_DATE, transactionDate, null, null);
|
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.FUTURE_DATE, transactionDate, null, null);
|
||||||
}
|
}
|
||||||
// shouldn't be before an accounting closure
|
// shouldn't be before an accounting closure
|
||||||
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(command.getOfficeId());
|
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(command.getOfficeId());
|
||||||
if (latestGLClosure != null) {
|
if (latestGLClosure != null) {
|
||||||
if (latestGLClosure.getClosingDate().isAfter(transactionDate)
|
if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) {
|
||||||
|| latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
|
||||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
||||||
null, null);
|
null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** check if credits and debits are valid **/
|
// check if credits and debits are valid
|
||||||
final SingleDebitOrCreditEntryCommand[] credits = command.getCredits();
|
final SingleDebitOrCreditEntryCommand[] credits = command.getCredits();
|
||||||
final SingleDebitOrCreditEntryCommand[] debits = command.getDebits();
|
final SingleDebitOrCreditEntryCommand[] debits = command.getDebits();
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -43,6 +43,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
|||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
@@ -107,7 +108,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
|
|||||||
private void validateForCreateJournalEntry(ProvisioningEntryData existingEntry, ProvisioningEntry requested) {
|
private void validateForCreateJournalEntry(ProvisioningEntryData existingEntry, ProvisioningEntry requested) {
|
||||||
LocalDate existingDate = existingEntry.getCreatedDate();
|
LocalDate existingDate = existingEntry.getCreatedDate();
|
||||||
LocalDate requestedDate = requested.getCreatedDate();
|
LocalDate requestedDate = requested.getCreatedDate();
|
||||||
if (existingDate.isAfter(requestedDate) || existingDate.compareTo(requestedDate) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
if (!DateUtils.isBefore(existingDate, requestedDate)) {
|
||||||
throw new ProvisioningJournalEntriesCannotbeCreatedException(existingEntry.getCreatedDate(), requestedDate);
|
throw new ProvisioningJournalEntriesCannotbeCreatedException(existingEntry.getCreatedDate(), requestedDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class LoanAccountLock {
|
|||||||
public LoanAccountLock(Long loanId, LockOwner lockOwner, LocalDate lockPlacedOnCobBusinessDate) {
|
public LoanAccountLock(Long loanId, LockOwner lockOwner, LocalDate lockPlacedOnCobBusinessDate) {
|
||||||
this.loanId = loanId;
|
this.loanId = loanId;
|
||||||
this.lockOwner = lockOwner;
|
this.lockOwner = lockOwner;
|
||||||
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.lockPlacedOn = DateUtils.getAuditOffsetDateTime();
|
||||||
this.lockPlacedOnCobBusinessDate = lockPlacedOnCobBusinessDate;
|
this.lockPlacedOnCobBusinessDate = lockPlacedOnCobBusinessDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +75,6 @@ public class LoanAccountLock {
|
|||||||
|
|
||||||
public void setNewLockOwner(LockOwner newLockOwner) {
|
public void setNewLockOwner(LockOwner newLockOwner) {
|
||||||
this.lockOwner = newLockOwner;
|
this.lockOwner = newLockOwner;
|
||||||
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
this.lockPlacedOn = DateUtils.getAuditOffsetDateTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -81,8 +81,8 @@ public class LoanCOBPartitioner implements Partitioner {
|
|||||||
}
|
}
|
||||||
StopWatch sw = new StopWatch();
|
StopWatch sw = new StopWatch();
|
||||||
sw.start();
|
sw.start();
|
||||||
List<LoanCOBPartition> loanCOBPartitions = new ArrayList<>(retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays,
|
List<LoanCOBPartition> loanCOBPartitions = new ArrayList<>(
|
||||||
businessDate, isCatchUp != null ? isCatchUp : false, partitionSize));
|
retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, businessDate, isCatchUp != null && isCatchUp, partitionSize));
|
||||||
sw.stop();
|
sw.stop();
|
||||||
// if there is no loan to be closed, we still would like to create at least one partition
|
// if there is no loan to be closed, we still would like to create at least one partition
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ public class LoanLockingServiceImpl implements LoanLockingService {
|
|||||||
UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ?
|
UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ?
|
||||||
""", accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
|
""", accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
|
||||||
ps.setString(1, lockOwner.name());
|
ps.setString(1, lockOwner.name());
|
||||||
ps.setObject(2, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
ps.setObject(2, DateUtils.getAuditOffsetDateTime());
|
||||||
ps.setLong(3, id);
|
ps.setLong(3, id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ public class LoanLockingServiceImpl implements LoanLockingService {
|
|||||||
ps.setLong(1, loanId);
|
ps.setLong(1, loanId);
|
||||||
ps.setLong(2, 1);
|
ps.setLong(2, 1);
|
||||||
ps.setString(3, lockOwner.name());
|
ps.setString(3, lockOwner.name());
|
||||||
ps.setObject(4, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
ps.setObject(4, DateUtils.getAuditOffsetDateTime());
|
||||||
ps.setObject(5, cobBusinessDate);
|
ps.setObject(5, cobBusinessDate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -32,6 +32,7 @@ import org.apache.fineract.cob.loan.RetrieveLoanIdService;
|
|||||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.infrastructure.core.config.TaskExecutorConstant;
|
import org.apache.fineract.infrastructure.core.config.TaskExecutorConstant;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractContext;
|
import org.apache.fineract.infrastructure.core.domain.FineractContext;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO;
|
import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO;
|
||||||
import org.apache.fineract.infrastructure.jobs.domain.JobParameterRepository;
|
import org.apache.fineract.infrastructure.jobs.domain.JobParameterRepository;
|
||||||
@@ -73,7 +74,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ
|
|||||||
LocalDate oldestCOBProcessedDate = !loanIdAndLastClosedBusinessDate.isEmpty()
|
LocalDate oldestCOBProcessedDate = !loanIdAndLastClosedBusinessDate.isEmpty()
|
||||||
? loanIdAndLastClosedBusinessDate.get(0).getLastClosedBusinessDate()
|
? loanIdAndLastClosedBusinessDate.get(0).getLastClosedBusinessDate()
|
||||||
: cobBusinessDate;
|
: cobBusinessDate;
|
||||||
if (oldestCOBProcessedDate.isBefore(cobBusinessDate)) {
|
if (DateUtils.isBefore(oldestCOBProcessedDate, cobBusinessDate)) {
|
||||||
executeLoanCOBDayByDayUntilCOBBusinessDate(oldestCOBProcessedDate, cobBusinessDate);
|
executeLoanCOBDayByDayUntilCOBBusinessDate(oldestCOBProcessedDate, cobBusinessDate);
|
||||||
}
|
}
|
||||||
} catch (NoSuchJobException e) {
|
} catch (NoSuchJobException e) {
|
||||||
@@ -92,7 +93,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ
|
|||||||
Job job = jobLocator.getJob(LoanCOBConstant.JOB_NAME);
|
Job job = jobLocator.getJob(LoanCOBConstant.JOB_NAME);
|
||||||
ScheduledJobDetail scheduledJobDetail = scheduledJobDetailRepository.findByJobName(LoanCOBConstant.JOB_HUMAN_READABLE_NAME);
|
ScheduledJobDetail scheduledJobDetail = scheduledJobDetailRepository.findByJobName(LoanCOBConstant.JOB_HUMAN_READABLE_NAME);
|
||||||
LocalDate executingBusinessDate = oldestCOBProcessedDate.plusDays(1);
|
LocalDate executingBusinessDate = oldestCOBProcessedDate.plusDays(1);
|
||||||
while (!executingBusinessDate.isAfter(cobBusinessDate)) {
|
while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) {
|
||||||
JobParameterDTO jobParameterDTO = new JobParameterDTO(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME,
|
JobParameterDTO jobParameterDTO = new JobParameterDTO(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME,
|
||||||
executingBusinessDate.format(DateTimeFormatter.ISO_DATE));
|
executingBusinessDate.format(DateTimeFormatter.ISO_DATE));
|
||||||
JobParameterDTO jobParameterCatchUpDTO = new JobParameterDTO(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME, "true");
|
JobParameterDTO jobParameterCatchUpDTO = new JobParameterDTO(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME, "true");
|
||||||
|
|||||||
+3
-2
@@ -51,6 +51,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild
|
|||||||
import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformRequestBodyItemLimitValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformRequestBodyItemLimitValidationException;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
|
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO;
|
import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO;
|
||||||
import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository;
|
import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository;
|
||||||
@@ -112,7 +113,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
|
|||||||
List<LoanIdAndLastClosedBusinessDate> loansToBeProcessed = getLoansToBeProcessed(loanIds, cobBusinessDate);
|
List<LoanIdAndLastClosedBusinessDate> loansToBeProcessed = getLoansToBeProcessed(loanIds, cobBusinessDate);
|
||||||
LocalDate executingBusinessDate = getOldestCOBBusinessDate(loansToBeProcessed).plusDays(1);
|
LocalDate executingBusinessDate = getOldestCOBBusinessDate(loansToBeProcessed).plusDays(1);
|
||||||
if (!loansToBeProcessed.isEmpty()) {
|
if (!loansToBeProcessed.isEmpty()) {
|
||||||
while (!executingBusinessDate.isAfter(cobBusinessDate)) {
|
while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) {
|
||||||
execute(getLoanIdsToBeProcessed(loansToBeProcessed, executingBusinessDate), jobName, executingBusinessDate);
|
execute(getLoanIdsToBeProcessed(loansToBeProcessed, executingBusinessDate), jobName, executingBusinessDate);
|
||||||
executingBusinessDate = executingBusinessDate.plusDays(1);
|
executingBusinessDate = executingBusinessDate.plusDays(1);
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
|
|||||||
List<Long> loanIdsToBeProcessed = new ArrayList<>();
|
List<Long> loanIdsToBeProcessed = new ArrayList<>();
|
||||||
loansToBeProcessed.forEach(loan -> {
|
loansToBeProcessed.forEach(loan -> {
|
||||||
if (loan.getLastClosedBusinessDate() != null) {
|
if (loan.getLastClosedBusinessDate() != null) {
|
||||||
if (loan.getLastClosedBusinessDate().isBefore(executingBusinessDate)) {
|
if (DateUtils.isBefore(loan.getLastClosedBusinessDate(), executingBusinessDate)) {
|
||||||
loanIdsToBeProcessed.add(loan.getId());
|
loanIdsToBeProcessed.add(loan.getId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@ public class ImportDocument extends AbstractPersistableCustom {
|
|||||||
final Boolean completed = Boolean.FALSE;
|
final Boolean completed = Boolean.FALSE;
|
||||||
final Integer successCount = 0;
|
final Integer successCount = 0;
|
||||||
final Integer failureCount = 0;
|
final Integer failureCount = 0;
|
||||||
final LocalDateTime endTime = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
|
final LocalDateTime endTime = DateUtils.getLocalDateTimeOfTenant();
|
||||||
|
|
||||||
return new ImportDocument(document, importTime, endTime, completed, entityType, createdBy, totalRecords, successCount,
|
return new ImportDocument(document, importTime, endTime, completed, entityType, createdBy, totalRecords, successCount,
|
||||||
failureCount);
|
failureCount);
|
||||||
|
|||||||
+1
-2
@@ -145,8 +145,7 @@ public final class ImportHandlerUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDate localDate = LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
return LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||||
return localDate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean readAsBoolean(int colIndex, Row row) {
|
public static Boolean readAsBoolean(int colIndex, Row row) {
|
||||||
|
|||||||
+1
-2
@@ -101,8 +101,7 @@ public class SharedProductsSheetPopulator extends AbstractWorkbookPopulator {
|
|||||||
if (marketDataSet != null && !marketDataSet.isEmpty()) {
|
if (marketDataSet != null && !marketDataSet.isEmpty()) {
|
||||||
LocalDate currentDate = DateUtils.getBusinessLocalDate();
|
LocalDate currentDate = DateUtils.getBusinessLocalDate();
|
||||||
for (ShareProductMarketPriceData data : marketDataSet) {
|
for (ShareProductMarketPriceData data : marketDataSet) {
|
||||||
LocalDate futureDate = data.getFromDate();
|
if (DateUtils.isBefore(data.getFromDate(), currentDate)) {
|
||||||
if (currentDate.isAfter(futureDate)) {
|
|
||||||
marketValue = data.getShareValue();
|
marketValue = data.getShareValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-27
@@ -160,7 +160,7 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
final Locale locale = command.extractLocale();
|
final Locale locale = command.extractLocale();
|
||||||
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
|
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
|
||||||
|
|
||||||
LocalDateTime recurrenceStartDate = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
|
LocalDateTime recurrenceStartDate = DateUtils.getLocalDateTimeOfTenant();
|
||||||
if (EmailCampaignType.fromInt(campaignType.intValue()).isSchedule()) {
|
if (EmailCampaignType.fromInt(campaignType.intValue()).isSchedule()) {
|
||||||
if (command.hasParameter(EmailCampaignValidator.recurrenceStartDate)) {
|
if (command.hasParameter(EmailCampaignValidator.recurrenceStartDate)) {
|
||||||
recurrenceStartDate = LocalDateTime.parse(command.stringValueOfParameterNamed(EmailCampaignValidator.recurrenceStartDate),
|
recurrenceStartDate = LocalDateTime.parse(command.stringValueOfParameterNamed(EmailCampaignValidator.recurrenceStartDate),
|
||||||
@@ -178,7 +178,6 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> update(JsonCommand command) {
|
public Map<String, Object> update(JsonCommand command) {
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
|
final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
|
||||||
|
|
||||||
if (command.isChangeInStringParameterNamed(EmailCampaignValidator.campaignName, this.campaignName)) {
|
if (command.isChangeInStringParameterNamed(EmailCampaignValidator.campaignName, this.campaignName)) {
|
||||||
@@ -229,7 +228,6 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void activate(final AppUser currentUser, final DateTimeFormatter formatter, final LocalDate activationLocalDate) {
|
public void activate(final AppUser currentUser, final DateTimeFormatter formatter, final LocalDate activationLocalDate) {
|
||||||
|
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
// handle errors if already activated
|
// handle errors if already activated
|
||||||
final String defaultUserMessage = "Cannot activate campaign. Campaign is already active.";
|
final String defaultUserMessage = "Cannot activate campaign. Campaign is already active.";
|
||||||
@@ -271,14 +269,13 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reactivate(final AppUser currentUser, final DateTimeFormatter dateTimeFormat, final LocalDate reactivateLocalDate) {
|
public void reactivate(final AppUser currentUser, final DateTimeFormatter dateTimeFormat, final LocalDate reactivateLocalDate) {
|
||||||
|
|
||||||
if (!isClosed()) {
|
if (!isClosed()) {
|
||||||
// handle errors if already activated
|
// handle errors if already activated
|
||||||
final String defaultUserMessage = "Cannot reactivate campaign. Campaign must be in closed state.";
|
final String defaultUserMessage = "Cannot reactivate campaign. Campaign must be in closed state.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.must.be.closed", defaultUserMessage,
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.must.be.closed", defaultUserMessage,
|
||||||
EmailCampaignValidator.statusParamName, EmailCampaignStatus.fromInt(this.status).getCode());
|
EmailCampaignValidator.statusParamName, EmailCampaignStatus.fromInt(this.status).getCode());
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
@@ -352,55 +349,45 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||||
|
if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) {
|
||||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
||||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (getApprovedOnDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getApprovedOnDate())) {
|
||||||
if (getApprovedOnDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getApprovedOnDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
||||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
if (DateUtils.isDateInTheFuture(getApprovedOnDate())) {
|
||||||
if (getApprovedOnDate() != null && isDateInTheFuture(getApprovedOnDate())) {
|
|
||||||
|
|
||||||
final String defaultUserMessage = "Activation date cannot be in the future.";
|
final String defaultUserMessage = "Activation date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
||||||
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateReactivationDate(final List<ApiParameterError> dataValidationErrors) {
|
private void validateReactivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||||
if (getApprovedOnDate() != null && isDateInTheFuture(getApprovedOnDate())) {
|
if (DateUtils.isDateInTheFuture(getApprovedOnDate())) {
|
||||||
|
|
||||||
final String defaultUserMessage = "Activation date cannot be in the future.";
|
final String defaultUserMessage = "Activation date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
||||||
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
if (getApprovedOnDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getApprovedOnDate())) {
|
if (getApprovedOnDate() != null && DateUtils.isAfter(getSubmittedOnDate(), getApprovedOnDate())) {
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
||||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
if (DateUtils.isDateInTheFuture(getSubmittedOnDate())) {
|
||||||
|
|
||||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
||||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||||
@@ -411,7 +398,7 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateClosureDate(final List<ApiParameterError> dataValidationErrors) {
|
private void validateClosureDate(final List<ApiParameterError> dataValidationErrors) {
|
||||||
if (getClosureDate() != null && isDateInTheFuture(getClosureDate())) {
|
if (getClosureDate() != null && DateUtils.isDateInTheFuture(getClosureDate())) {
|
||||||
final String defaultUserMessage = "closure date cannot be in the future.";
|
final String defaultUserMessage = "closure date cannot be in the future.";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.closureDate.in.the.future",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.closureDate.in.the.future",
|
||||||
defaultUserMessage, EmailCampaignValidator.closureDateParamName, this.closureDate);
|
defaultUserMessage, EmailCampaignValidator.closureDateParamName, this.closureDate);
|
||||||
@@ -419,9 +406,4 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
|||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDateInTheFuture(final LocalDate localDate) {
|
|
||||||
return localDate.isAfter(DateUtils.getBusinessLocalDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-49
@@ -31,7 +31,6 @@ import java.io.StringReader;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeFormatterBuilder;
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -56,11 +55,9 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
|||||||
import org.apache.fineract.infrastructure.core.api.JsonQuery;
|
import org.apache.fineract.infrastructure.core.api.JsonQuery;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
|
||||||
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.domain.Report;
|
import org.apache.fineract.infrastructure.dataqueries.domain.Report;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.domain.ReportParameterUsage;
|
import org.apache.fineract.infrastructure.dataqueries.domain.ReportParameterUsage;
|
||||||
@@ -98,7 +95,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult create(JsonCommand command) {
|
public CommandProcessingResult create(JsonCommand command) {
|
||||||
|
|
||||||
final AppUser currentUser = this.context.authenticatedUser();
|
final AppUser currentUser = this.context.authenticatedUser();
|
||||||
|
|
||||||
this.emailCampaignValidator.validateCreate(command.json());
|
this.emailCampaignValidator.validateCreate(command.json());
|
||||||
@@ -286,24 +282,21 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
|||||||
if (emailCampaign.isDirect()) {
|
if (emailCampaign.isDirect()) {
|
||||||
insertDirectCampaignIntoEmailOutboundTable(emailCampaign.getParamValue(), emailCampaign.getEmailSubject(),
|
insertDirectCampaignIntoEmailOutboundTable(emailCampaign.getParamValue(), emailCampaign.getEmailSubject(),
|
||||||
emailCampaign.getEmailMessage(), emailCampaign.getCampaignName(), emailCampaign.getId());
|
emailCampaign.getEmailMessage(), emailCampaign.getCampaignName(), emailCampaign.getId());
|
||||||
} else {
|
} else if (emailCampaign.isSchedule()) {
|
||||||
if (emailCampaign.isSchedule()) {
|
// if recurrence start date is in the past, calculate next trigger date, otherwise use recurrence start
|
||||||
|
// date as next trigger date when activating
|
||||||
/**
|
LocalDateTime nextTriggerDateWithTime;
|
||||||
* if recurrence start date is in the future calculate next trigger date if not use recurrence start
|
LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate();
|
||||||
* date us next trigger date when activating
|
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||||
*/
|
if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) {
|
||||||
LocalDateTime nextTriggerDateWithTime;
|
nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate,
|
||||||
if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) {
|
tenantDateTime);
|
||||||
nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(),
|
} else {
|
||||||
emailCampaign.getRecurrenceStartDate(), DateUtils.getLocalDateTimeOfTenant());
|
nextTriggerDateWithTime = recurrenceStartDate;
|
||||||
} else {
|
|
||||||
nextTriggerDateWithTime = emailCampaign.getRecurrenceStartDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
emailCampaign.setNextTriggerDate(nextTriggerDateWithTime);
|
|
||||||
this.emailCampaignRepository.saveAndFlush(emailCampaign);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emailCampaign.setNextTriggerDate(nextTriggerDateWithTime);
|
||||||
|
this.emailCampaignRepository.saveAndFlush(emailCampaign);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -420,7 +413,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult reactivateEmailCampaign(final Long campaignId, JsonCommand command) {
|
public CommandProcessingResult reactivateEmailCampaign(final Long campaignId, JsonCommand command) {
|
||||||
|
|
||||||
this.emailCampaignValidator.validateActivation(command.json());
|
this.emailCampaignValidator.validateActivation(command.json());
|
||||||
|
|
||||||
final AppUser currentUser = this.context.authenticatedUser();
|
final AppUser currentUser = this.context.authenticatedUser();
|
||||||
@@ -433,23 +425,18 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
|||||||
final LocalDate reactivationDate = command.localDateValueOfParameterNamed("activationDate");
|
final LocalDate reactivationDate = command.localDateValueOfParameterNamed("activationDate");
|
||||||
emailCampaign.reactivate(currentUser, fmt, reactivationDate);
|
emailCampaign.reactivate(currentUser, fmt, reactivationDate);
|
||||||
if (emailCampaign.isSchedule()) {
|
if (emailCampaign.isSchedule()) {
|
||||||
|
// if recurrence start date is in the past, calculate next trigger date, otherwise use recurrence start date
|
||||||
/**
|
// as next trigger date when activating
|
||||||
* if recurrence start date is in the future calculate next trigger date if not use recurrence start date us
|
|
||||||
* next trigger date when activating
|
|
||||||
*/
|
|
||||||
LocalDateTime nextTriggerDate = null;
|
LocalDateTime nextTriggerDate = null;
|
||||||
if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) {
|
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||||
nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getRecurrenceStartDate(),
|
LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate();
|
||||||
DateUtils.getLocalDateTimeOfTenant());
|
if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) {
|
||||||
|
nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate, tenantDateTime);
|
||||||
} else {
|
} else {
|
||||||
nextTriggerDate = emailCampaign.getRecurrenceStartDate();
|
nextTriggerDate = recurrenceStartDate;
|
||||||
}
|
}
|
||||||
// to get time of tenant
|
final String dateString = nextTriggerDate.toString() + " " + recurrenceStartDate.getHour() + ":"
|
||||||
final LocalDateTime getTime = emailCampaign.getRecurrenceStartDate();
|
+ recurrenceStartDate.getMinute() + ":" + recurrenceStartDate.getSecond();
|
||||||
|
|
||||||
final String dateString = nextTriggerDate.toString() + " " + getTime.getHour() + ":" + getTime.getMinute() + ":"
|
|
||||||
+ getTime.getSecond();
|
|
||||||
final DateTimeFormatter simpleDateFormat = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient()
|
final DateTimeFormatter simpleDateFormat = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient()
|
||||||
.appendPattern("yyyy-MM-dd HH:mm:ss").toFormatter();
|
.appendPattern("yyyy-MM-dd HH:mm:ss").toFormatter();
|
||||||
final LocalDateTime nextTriggerDateWithTime = LocalDateTime.parse(dateString, simpleDateFormat);
|
final LocalDateTime nextTriggerDateWithTime = LocalDateTime.parse(dateString, simpleDateFormat);
|
||||||
@@ -470,17 +457,4 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
|||||||
throw new PlatformDataIntegrityException("error.msg.email.campaign.unknown.data.integrity.issue",
|
throw new PlatformDataIntegrityException("error.msg.email.campaign.unknown.data.integrity.issue",
|
||||||
"Unknown data integrity issue with resource: " + realCause.getMessage());
|
"Unknown data integrity issue with resource: " + realCause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDateTime tenantDateTime() {
|
|
||||||
LocalDateTime today = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
|
|
||||||
final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
|
||||||
|
|
||||||
if (tenant != null) {
|
|
||||||
final ZoneId zone = ZoneId.of(tenant.getTimezoneId());
|
|
||||||
if (zone != null) {
|
|
||||||
today = LocalDateTime.now(zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return today;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.infrastructure.campaigns.jobs;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
|
||||||
|
|
||||||
public final class TenantDateTimeUtil {
|
|
||||||
|
|
||||||
private TenantDateTimeUtil() {}
|
|
||||||
|
|
||||||
public static LocalDateTime tenantDateTime() {
|
|
||||||
LocalDateTime today = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
|
|
||||||
final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
|
||||||
|
|
||||||
if (tenant != null) {
|
|
||||||
final ZoneId zone = ZoneId.of(tenant.getTimezoneId());
|
|
||||||
today = LocalDateTime.now(zone);
|
|
||||||
}
|
|
||||||
return today;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -80,7 +80,7 @@ public class ExecuteReportMailingJobsTasklet implements Tasklet {
|
|||||||
final LocalDateTime localDateTimeOftenant = DateUtils.getLocalDateTimeOfTenant();
|
final LocalDateTime localDateTimeOftenant = DateUtils.getLocalDateTimeOfTenant();
|
||||||
final LocalDateTime nextRunDateTime = reportMailingJob.getNextRunDateTime();
|
final LocalDateTime nextRunDateTime = reportMailingJob.getNextRunDateTime();
|
||||||
|
|
||||||
if (nextRunDateTime != null && nextRunDateTime.isBefore(localDateTimeOftenant)) {
|
if (nextRunDateTime != null && DateUtils.isBefore(nextRunDateTime, localDateTimeOftenant)) {
|
||||||
final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat
|
final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat
|
||||||
.newInstance(reportMailingJob.getEmailAttachmentFileFormat());
|
.newInstance(reportMailingJob.getEmailAttachmentFileFormat());
|
||||||
|
|
||||||
|
|||||||
+7
-9
@@ -43,7 +43,6 @@ import org.apache.fineract.infrastructure.campaigns.email.domain.EmailMessageRep
|
|||||||
import org.apache.fineract.infrastructure.campaigns.email.exception.EmailCampaignNotFound;
|
import org.apache.fineract.infrastructure.campaigns.email.exception.EmailCampaignNotFound;
|
||||||
import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignReadPlatformService;
|
import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignReadPlatformService;
|
||||||
import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignWritePlatformService;
|
import org.apache.fineract.infrastructure.campaigns.email.service.EmailCampaignWritePlatformService;
|
||||||
import org.apache.fineract.infrastructure.campaigns.jobs.TenantDateTimeUtil;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||||
import org.apache.fineract.portfolio.client.domain.Client;
|
import org.apache.fineract.portfolio.client.domain.Client;
|
||||||
@@ -69,11 +68,11 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet {
|
|||||||
.retrieveAllScheduleActiveCampaign();
|
.retrieveAllScheduleActiveCampaign();
|
||||||
if (emailCampaignDataCollection != null) {
|
if (emailCampaignDataCollection != null) {
|
||||||
for (EmailCampaignData emailCampaignData : emailCampaignDataCollection) {
|
for (EmailCampaignData emailCampaignData : emailCampaignDataCollection) {
|
||||||
LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime();
|
LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant();
|
||||||
LocalDateTime nextTriggerDate = emailCampaignData.getNextTriggerDate().toLocalDateTime();
|
LocalDateTime nextTriggerDate = emailCampaignData.getNextTriggerDate().toLocalDateTime();
|
||||||
|
|
||||||
log.debug("tenant time {} trigger time {}", tenantDateNow, nextTriggerDate);
|
log.debug("tenant time {} trigger time {}", tenantDateNow, nextTriggerDate);
|
||||||
if (nextTriggerDate.isBefore(tenantDateNow)) {
|
if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) {
|
||||||
insertDirectCampaignIntoEmailOutboundTable(emailCampaignData.getParamValue(), emailCampaignData.getEmailSubject(),
|
insertDirectCampaignIntoEmailOutboundTable(emailCampaignData.getParamValue(), emailCampaignData.getEmailSubject(),
|
||||||
emailCampaignData.getEmailMessage(), emailCampaignData.getCampaignName(), emailCampaignData.getId());
|
emailCampaignData.getEmailMessage(), emailCampaignData.getCampaignName(), emailCampaignData.getId());
|
||||||
updateTriggerDates(emailCampaignData.getId());
|
updateTriggerDates(emailCampaignData.getId());
|
||||||
@@ -115,13 +114,12 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet {
|
|||||||
.orElseThrow(() -> new EmailCampaignNotFound(campaignId));
|
.orElseThrow(() -> new EmailCampaignNotFound(campaignId));
|
||||||
LocalDateTime nextTriggerDate = emailCampaign.getNextTriggerDate();
|
LocalDateTime nextTriggerDate = emailCampaign.getNextTriggerDate();
|
||||||
emailCampaign.setLastTriggerDate(nextTriggerDate);
|
emailCampaign.setLastTriggerDate(nextTriggerDate);
|
||||||
LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(),
|
LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate,
|
||||||
emailCampaign.getNextTriggerDate(), nextTriggerDate);
|
nextTriggerDate);
|
||||||
if (newTriggerDateWithTime.isBefore(DateUtils.getLocalDateTimeOfTenant())) {
|
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||||
newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getNextTriggerDate(),
|
if (DateUtils.isBefore(newTriggerDateWithTime, tenantDateTime)) {
|
||||||
DateUtils.getLocalDateTimeOfTenant());
|
newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate, tenantDateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
emailCampaign.setNextTriggerDate(newTriggerDateWithTime);
|
emailCampaign.setNextTriggerDate(newTriggerDateWithTime);
|
||||||
emailCampaignRepository.saveAndFlush(emailCampaign);
|
emailCampaignRepository.saveAndFlush(emailCampaign);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -23,7 +23,6 @@ import java.util.Collection;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.fineract.infrastructure.campaigns.jobs.TenantDateTimeUtil;
|
|
||||||
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus;
|
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignStatus;
|
||||||
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType;
|
import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType;
|
||||||
import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
|
import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
|
||||||
@@ -51,12 +50,12 @@ public class UpdateSmsOutboundWithCampaignMessageTasklet implements Tasklet {
|
|||||||
.findByTriggerTypeAndStatus(SmsCampaignTriggerType.SCHEDULE.getValue(), SmsCampaignStatus.ACTIVE.getValue());
|
.findByTriggerTypeAndStatus(SmsCampaignTriggerType.SCHEDULE.getValue(), SmsCampaignStatus.ACTIVE.getValue());
|
||||||
if (!CollectionUtils.isEmpty(smsCampaignDataCollection)) {
|
if (!CollectionUtils.isEmpty(smsCampaignDataCollection)) {
|
||||||
for (SmsCampaign smsCampaign : smsCampaignDataCollection) {
|
for (SmsCampaign smsCampaign : smsCampaignDataCollection) {
|
||||||
LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime();
|
LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant();
|
||||||
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
||||||
|
|
||||||
log.debug("tenant time {} trigger time {} {}", tenantDateNow, nextTriggerDate,
|
log.debug("tenant time {} trigger time {} {}", tenantDateNow, nextTriggerDate,
|
||||||
JobName.UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE.name());
|
JobName.UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE.name());
|
||||||
if (nextTriggerDate.isBefore(tenantDateNow)) {
|
if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) {
|
||||||
smsCampaignWritePlatformService.insertDirectCampaignIntoSmsOutboundTable(smsCampaign);
|
smsCampaignWritePlatformService.insertDirectCampaignIntoSmsOutboundTable(smsCampaign);
|
||||||
updateTriggerDates(smsCampaign.getId());
|
updateTriggerDates(smsCampaign.getId());
|
||||||
}
|
}
|
||||||
@@ -70,11 +69,10 @@ public class UpdateSmsOutboundWithCampaignMessageTasklet implements Tasklet {
|
|||||||
.orElseThrow(() -> new SmsCampaignNotFound(campaignId));
|
.orElseThrow(() -> new SmsCampaignNotFound(campaignId));
|
||||||
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
||||||
smsCampaign.setLastTriggerDate(nextTriggerDate);
|
smsCampaign.setLastTriggerDate(nextTriggerDate);
|
||||||
LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(),
|
LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, nextTriggerDate);
|
||||||
nextTriggerDate);
|
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||||
if (nextRuntime.isBefore(DateUtils.getLocalDateTimeOfTenant())) {
|
if (DateUtils.isBefore(nextRuntime, tenantDateTime)) {
|
||||||
nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(),
|
nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, tenantDateTime);
|
||||||
DateUtils.getLocalDateTimeOfTenant());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
smsCampaign.setNextTriggerDate(nextRuntime);
|
smsCampaign.setNextTriggerDate(nextRuntime);
|
||||||
|
|||||||
+3
-6
@@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.infrastructure.core.domain;
|
package org.apache.fineract.infrastructure.core.domain;
|
||||||
|
|
||||||
|
import static org.apache.fineract.useradministration.service.AppUserConstants.ADMIN_USER_ID;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.apache.fineract.useradministration.domain.AppUserRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.AuditorAware;
|
import org.springframework.data.domain.AuditorAware;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
@@ -29,9 +29,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
|
|
||||||
public class AuditorAwareImpl implements AuditorAware<Long> {
|
public class AuditorAwareImpl implements AuditorAware<Long> {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AppUserRepository userRepository;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Long> getCurrentAuditor() {
|
public Optional<Long> getCurrentAuditor() {
|
||||||
Optional<Long> currentUserId;
|
Optional<Long> currentUserId;
|
||||||
@@ -50,6 +47,6 @@ public class AuditorAwareImpl implements AuditorAware<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Long> retrieveSuperUser() {
|
private Optional<Long> retrieveSuperUser() {
|
||||||
return Optional.of(1L);
|
return Optional.of(ADMIN_USER_ID); // TODO change to SYSTEM_USER_ID and add rights
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -420,7 +420,7 @@ public class ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl implemen
|
|||||||
LocalDate current = DateUtils.getLocalDateOfTenant();
|
LocalDate current = DateUtils.getLocalDateOfTenant();
|
||||||
LocalDate getExpiryDate = creditBureauToken.getExpires();
|
LocalDate getExpiryDate = creditBureauToken.getExpires();
|
||||||
|
|
||||||
if (getExpiryDate.isBefore(current)) {
|
if (DateUtils.isBefore(getExpiryDate, current)) {
|
||||||
this.tokenRepositoryWrapper.delete(creditBureauToken);
|
this.tokenRepositoryWrapper.delete(creditBureauToken);
|
||||||
creditBureauToken = null;
|
creditBureauToken = null;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -33,6 +33,7 @@ import lombok.Setter;
|
|||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants;
|
import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants;
|
||||||
import org.apache.fineract.infrastructure.entityaccess.exception.FineractEntityToEntityMappingDateException;
|
import org.apache.fineract.infrastructure.entityaccess.exception.FineractEntityToEntityMappingDateException;
|
||||||
|
|
||||||
@@ -69,7 +70,6 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> updateMap(final JsonCommand command) {
|
public Map<String, Object> updateMap(final JsonCommand command) {
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||||
|
|
||||||
if (command.isChangeInLongParameterNamed(FineractEntityApiResourceConstants.fromEnityType, this.fromId)) {
|
if (command.isChangeInLongParameterNamed(FineractEntityApiResourceConstants.fromEnityType, this.fromId)) {
|
||||||
@@ -95,10 +95,8 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom {
|
|||||||
actualChanges.put(FineractEntityApiResourceConstants.endDate, valueAsInput);
|
actualChanges.put(FineractEntityApiResourceConstants.endDate, valueAsInput);
|
||||||
this.endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
this.endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
||||||
}
|
}
|
||||||
if (startDate != null && endDate != null) {
|
if (endDate != null && DateUtils.isBefore(endDate, startDate)) {
|
||||||
if (endDate.isBefore(startDate)) {
|
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
|
|||||||
+3
-8
@@ -27,6 +27,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
|||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants;
|
import org.apache.fineract.infrastructure.entityaccess.api.FineractEntityApiResourceConstants;
|
||||||
import org.apache.fineract.infrastructure.entityaccess.data.FineractEntityDataValidator;
|
import org.apache.fineract.infrastructure.entityaccess.data.FineractEntityDataValidator;
|
||||||
import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccess;
|
import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccess;
|
||||||
@@ -86,9 +87,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public CommandProcessingResult createEntityToEntityMapping(Long relId, JsonCommand command) {
|
public CommandProcessingResult createEntityToEntityMapping(Long relId, JsonCommand command) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||||
|
|
||||||
final FineractEntityRelation mapId = this.fineractEntityRelationRepositoryWrapper.findOneWithNotFoundDetection(relId);
|
final FineractEntityRelation mapId = this.fineractEntityRelationRepositoryWrapper.findOneWithNotFoundDetection(relId);
|
||||||
@@ -99,10 +98,8 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
|||||||
final LocalDate endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
final LocalDate endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
||||||
|
|
||||||
fromApiJsonDeserializer.checkForEntity(relId.toString(), fromId, toId);
|
fromApiJsonDeserializer.checkForEntity(relId.toString(), fromId, toId);
|
||||||
if (startDate != null && endDate != null) {
|
if (endDate != null && DateUtils.isBefore(endDate, startDate)) {
|
||||||
if (endDate.isBefore(startDate)) {
|
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate);
|
final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate);
|
||||||
@@ -123,9 +120,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public CommandProcessingResult updateEntityToEntityMapping(Long mapId, JsonCommand command) {
|
public CommandProcessingResult updateEntityToEntityMapping(Long mapId, JsonCommand command) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||||
|
|
||||||
final FineractEntityToEntityMapping mapForUpdate = this.fineractEntityToEntityMappingRepositoryWrapper
|
final FineractEntityToEntityMapping mapForUpdate = this.fineractEntityToEntityMappingRepositoryWrapper
|
||||||
|
|||||||
+2
-3
@@ -63,7 +63,7 @@ public class UpdateNpaTasklet implements Tasklet {
|
|||||||
resetNPASqlBuilder.append("set is_npa = false").append(", last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ")
|
resetNPASqlBuilder.append("set is_npa = false").append(", last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ")
|
||||||
.append(fromPart).append(wherePart);
|
.append(fromPart).append(wherePart);
|
||||||
}
|
}
|
||||||
jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getAuditOffsetDateTime());
|
||||||
|
|
||||||
final StringBuilder updateSqlBuilder = new StringBuilder(900);
|
final StringBuilder updateSqlBuilder = new StringBuilder(900);
|
||||||
|
|
||||||
@@ -82,8 +82,7 @@ public class UpdateNpaTasklet implements Tasklet {
|
|||||||
.append(fromPart).append(wherePart);
|
.append(fromPart).append(wherePart);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(),
|
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(), DateUtils.getAuditOffsetDateTime());
|
||||||
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
|
||||||
|
|
||||||
log.debug("{}: Records affected by updateNPA: {}", ThreadLocalContextUtil.getTenant().getName(), result);
|
log.debug("{}: Records affected by updateNPA: {}", ThreadLocalContextUtil.getTenant().getName(), result);
|
||||||
return RepeatStatus.FINISHED;
|
return RepeatStatus.FINISHED;
|
||||||
|
|||||||
+2
-9
@@ -67,19 +67,12 @@ public class TFAccessToken extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return this.enabled && isDateInTheFuture(getValidTo()) && isDateInThePast(getValidFrom());
|
// valid_from is in the past inclusive, valid_to is in the future exclusive
|
||||||
|
return this.enabled && !DateUtils.isAfterTenantDateTime(getValidFrom()) && DateUtils.isAfterTenantDateTime(getValidTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessTokenData toTokenData() {
|
public AccessTokenData toTokenData() {
|
||||||
return new AccessTokenData().setToken(this.token).setValidFrom(getValidFrom().atZone(DateUtils.getDateTimeZoneOfTenant()))
|
return new AccessTokenData().setToken(this.token).setValidFrom(getValidFrom().atZone(DateUtils.getDateTimeZoneOfTenant()))
|
||||||
.setValidTo(getValidTo().atZone(DateUtils.getDateTimeZoneOfTenant()));
|
.setValidTo(getValidTo().atZone(DateUtils.getDateTimeZoneOfTenant()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDateInTheFuture(LocalDateTime dateTime) {
|
|
||||||
return dateTime.isAfter(DateUtils.getLocalDateTimeOfTenant());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDateInThePast(LocalDateTime dateTime) {
|
|
||||||
return (dateTime.isBefore(DateUtils.getLocalDateTimeOfTenant()) || dateTime.isEqual(DateUtils.getLocalDateTimeOfTenant()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -157,7 +157,7 @@ public class SpringSecurityPlatformSecurityContext implements PlatformSecurityCo
|
|||||||
|
|
||||||
final LocalDate passwordExpirationDate = passWordLastUpdateDate.plusDays(passwordDurationDays);
|
final LocalDate passwordExpirationDate = passWordLastUpdateDate.plusDays(passwordDurationDays);
|
||||||
|
|
||||||
if (DateUtils.getLocalDateOfTenant().isAfter(passwordExpirationDate)) {
|
if (DateUtils.isBeforeTenantDate(passwordExpirationDate)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ public class InteropTransactionsData extends CommandProcessingResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<InteropTransactionData> trans = account.getTransactions().stream().filter(filter).sorted((t1, t2) -> {
|
List<InteropTransactionData> trans = account.getTransactions().stream().filter(filter).sorted((t1, t2) -> {
|
||||||
int i = t2.getDateOf().compareTo(t1.getDateOf());
|
int i = DateUtils.compare(t2.getDateOf(), t1.getDateOf());
|
||||||
return i != 0 ? i : Long.signum(t2.getId() - t1.getId());
|
return i != 0 ? i : Long.signum(t2.getId() - t1.getId());
|
||||||
}).map(InteropTransactionData::build).collect(Collectors.toList());
|
}).map(InteropTransactionData::build).collect(Collectors.toList());
|
||||||
return new InteropTransactionsData(account.getId(), trans);
|
return new InteropTransactionsData(account.getId(), trans);
|
||||||
|
|||||||
+8
-11
@@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
|||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.organisation.holiday.api.HolidayApiConstants;
|
import org.apache.fineract.organisation.holiday.api.HolidayApiConstants;
|
||||||
import org.apache.fineract.organisation.holiday.data.HolidayDataValidator;
|
import org.apache.fineract.organisation.holiday.data.HolidayDataValidator;
|
||||||
@@ -206,18 +207,15 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateInputDates(final LocalDate fromDate, final LocalDate toDate, final LocalDate repaymentsRescheduledTo) {
|
private void validateInputDates(final LocalDate fromDate, final LocalDate toDate, final LocalDate repaymentsRescheduledTo) {
|
||||||
|
|
||||||
String defaultUserMessage = "";
|
String defaultUserMessage = "";
|
||||||
|
|
||||||
if (toDate.isBefore(fromDate)) {
|
if (DateUtils.isBefore(toDate, fromDate)) {
|
||||||
defaultUserMessage = "To Date date cannot be before the From Date.";
|
defaultUserMessage = "To Date date cannot be before the From Date.";
|
||||||
throw new HolidayDateException("to.date.cannot.be.before.from.date", defaultUserMessage, fromDate.toString(),
|
throw new HolidayDateException("to.date.cannot.be.before.from.date", defaultUserMessage, fromDate.toString(),
|
||||||
toDate.toString());
|
toDate.toString());
|
||||||
}
|
}
|
||||||
if (repaymentsRescheduledTo != null) {
|
if (repaymentsRescheduledTo != null) {
|
||||||
if ((repaymentsRescheduledTo.isEqual(fromDate) || repaymentsRescheduledTo.isEqual(toDate)
|
if (!DateUtils.isBefore(repaymentsRescheduledTo, fromDate) && !DateUtils.isAfter(repaymentsRescheduledTo, toDate)) {
|
||||||
|| (repaymentsRescheduledTo.isAfter(fromDate) && repaymentsRescheduledTo.isBefore(toDate)))) {
|
|
||||||
|
|
||||||
defaultUserMessage = "Repayments rescheduled date should be before from date or after to date.";
|
defaultUserMessage = "Repayments rescheduled date should be before from date or after to date.";
|
||||||
throw new HolidayDateException("repayments.rescheduled.date.should.be.before.from.date.or.after.to.date",
|
throw new HolidayDateException("repayments.rescheduled.date.should.be.before.from.date.or.after.to.date",
|
||||||
defaultUserMessage, repaymentsRescheduledTo.toString());
|
defaultUserMessage, repaymentsRescheduledTo.toString());
|
||||||
@@ -235,13 +233,12 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
|
|||||||
// validate repaymentsRescheduledTo date
|
// validate repaymentsRescheduledTo date
|
||||||
// 1. should be within a 30 days date range.
|
// 1. should be within a 30 days date range.
|
||||||
// 2. Alternative date should not be an exist holiday.//TBD
|
// 2. Alternative date should not be an exist holiday.//TBD
|
||||||
// 3. Holiday should not be on an repaymentsRescheduledTo date of
|
// 3. Holiday should not be on an repaymentsRescheduledTo date of another holiday.//TBD
|
||||||
// another holiday.//TBD
|
|
||||||
|
|
||||||
// restricting repaymentsRescheduledTo date to be within 30 days
|
// restricting repaymentsRescheduledTo date to be within 30 days range before or after from date and to
|
||||||
// range
|
// date.
|
||||||
// before or after from date and to date.
|
if (DateUtils.isBefore(repaymentsRescheduledTo, fromDate.minusDays(30))
|
||||||
if (repaymentsRescheduledTo.isBefore(fromDate.minusDays(30)) || repaymentsRescheduledTo.isAfter(toDate.plusDays(30))) {
|
|| DateUtils.isAfter(repaymentsRescheduledTo, toDate.plusDays(30))) {
|
||||||
defaultUserMessage = "Repayments Rescheduled to date must be within 30 days before or after from and to dates";
|
defaultUserMessage = "Repayments Rescheduled to date must be within 30 days before or after from and to dates";
|
||||||
throw new HolidayDateException("repayments.rescheduled.to.must.be.within.range", defaultUserMessage, fromDate.toString(),
|
throw new HolidayDateException("repayments.rescheduled.to.must.be.within.range", defaultUserMessage, fromDate.toString(),
|
||||||
toDate.toString(), repaymentsRescheduledTo.toString());
|
toDate.toString(), repaymentsRescheduledTo.toString());
|
||||||
|
|||||||
+15
-21
@@ -20,10 +20,10 @@ package org.apache.fineract.organisation.teller.data;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||||
import org.apache.fineract.organisation.teller.domain.Cashier;
|
import org.apache.fineract.organisation.teller.domain.Cashier;
|
||||||
import org.apache.fineract.organisation.teller.domain.Teller;
|
import org.apache.fineract.organisation.teller.domain.Teller;
|
||||||
@@ -54,7 +54,6 @@ public class CashierTransactionDataValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void validateSettleCashAndCashOutTransactions(final Long cashierId, String currencyCode, final BigDecimal transactionAmount) {
|
public void validateSettleCashAndCashOutTransactions(final Long cashierId, String currencyCode, final BigDecimal transactionAmount) {
|
||||||
|
|
||||||
final Integer offset = null;
|
final Integer offset = null;
|
||||||
final Integer limit = null;
|
final Integer limit = null;
|
||||||
final String orderBy = null;
|
final String orderBy = null;
|
||||||
@@ -64,7 +63,7 @@ public class CashierTransactionDataValidator {
|
|||||||
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
|
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
|
||||||
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.tellerManagementReadPlatformService
|
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.tellerManagementReadPlatformService
|
||||||
.retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters);
|
.retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters);
|
||||||
if (cashierTxnWithSummary.getNetCash().subtract(transactionAmount).compareTo(BigDecimal.ZERO) < 0) {
|
if (MathUtil.isGreaterThan(transactionAmount, cashierTxnWithSummary.getNetCash())) {
|
||||||
throw new CashierInsufficientAmountException();
|
throw new CashierInsufficientAmountException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,16 +80,12 @@ public class CashierTransactionDataValidator {
|
|||||||
final LocalDate endDate = cashier.getEndDate();
|
final LocalDate endDate = cashier.getEndDate();
|
||||||
final LocalDate tellerFromDate = teller.getStartDate();
|
final LocalDate tellerFromDate = teller.getStartDate();
|
||||||
final LocalDate tellerEndDate = teller.getEndDate();
|
final LocalDate tellerEndDate = teller.getEndDate();
|
||||||
/**
|
// to validate cashier date range in range of teller date range
|
||||||
* to validate cashier date range in range of teller date range
|
if (DateUtils.isBefore(fromDate, tellerFromDate) || DateUtils.isBefore(endDate, tellerFromDate)
|
||||||
*/
|
|| (tellerEndDate != null && (DateUtils.isAfter(fromDate, tellerEndDate) || DateUtils.isAfter(endDate, tellerEndDate)))) {
|
||||||
if (fromDate.isBefore(tellerFromDate) || endDate.isBefore(tellerFromDate)
|
|
||||||
|| (tellerEndDate != null && (fromDate.isAfter(tellerEndDate) || endDate.isAfter(tellerEndDate)))) {
|
|
||||||
throw new CashierDateRangeOutOfTellerDateRangeException();
|
throw new CashierDateRangeOutOfTellerDateRangeException();
|
||||||
}
|
}
|
||||||
/**
|
// to validate cashier has not been assigned for same duration
|
||||||
* to validate cashier has not been assigned for same duration
|
|
||||||
*/
|
|
||||||
String sql = "select count(*) from m_cashiers c where c.staff_id = " + staffId + " AND " + "(('" + fromDate
|
String sql = "select count(*) from m_cashiers c where c.staff_id = " + staffId + " AND " + "(('" + fromDate
|
||||||
+ "' BETWEEN c.start_date AND c.end_date OR '" + endDate + "' BETWEEN c.start_date AND c.end_date )"
|
+ "' BETWEEN c.start_date AND c.end_date OR '" + endDate + "' BETWEEN c.start_date AND c.end_date )"
|
||||||
+ " OR ( c.start_date BETWEEN '" + fromDate + "' AND '" + endDate + "' OR c.end_date BETWEEN '" + fromDate + "' AND '"
|
+ " OR ( c.start_date BETWEEN '" + fromDate + "' AND '" + endDate + "' OR c.end_date BETWEEN '" + fromDate + "' AND '"
|
||||||
@@ -98,8 +93,8 @@ public class CashierTransactionDataValidator {
|
|||||||
if (!cashier.getIsFullDay()) {
|
if (!cashier.getIsFullDay()) {
|
||||||
String startTime = cashier.getStartTime();
|
String startTime = cashier.getStartTime();
|
||||||
String endTime = cashier.getEndTime();
|
String endTime = cashier.getEndTime();
|
||||||
sql = sql + " AND ( Time(c.start_time) BETWEEN TIME(?) and TIME('" + endTime + "') or Time(c.end_time) BETWEEN TIME('"
|
sql = sql + " AND ( Time(c.start_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime
|
||||||
+ startTime + "') and TIME('" + endTime + "')) ";
|
+ "') or Time(c.end_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime + "')) ";
|
||||||
}
|
}
|
||||||
int count = this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR
|
int count = this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@@ -108,13 +103,13 @@ public class CashierTransactionDataValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void validateOnLoanDisbursal(AppUser user, String currencyCode, BigDecimal transactionAmount) {
|
public void validateOnLoanDisbursal(AppUser user, String currencyCode, BigDecimal transactionAmount) {
|
||||||
LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfTenant();
|
LocalDate tenantDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
OffsetDateTime tenantDateTime = DateUtils.getOffsetDateTimeOfTenant();
|
||||||
if (user.getStaff() != null) {
|
if (user.getStaff() != null) {
|
||||||
String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND "
|
String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND (case when c.full_day then '"
|
||||||
+ " (case when c.full_day then '" + localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date " + " else ('"
|
+ tenantDate + "' BETWEEN c.start_date AND c.end_date else ('" + tenantDate
|
||||||
+ localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date and " + " TIME('"
|
+ "' BETWEEN c.start_date AND c.end_date and TIME('" + tenantDateTime
|
||||||
+ ZonedDateTime.of(localDateTime, DateUtils.getDateTimeZoneOfTenant())
|
+ "') BETWEEN TIME(c.start_time) AND TIME(c.end_time)) end)";
|
||||||
+ "') BETWEEN TIME(c.start_time) AND TIME(c.end_time) ) end)";
|
|
||||||
try {
|
try {
|
||||||
Long cashierId = this.jdbcTemplate.queryForObject(sql, Long.class); // NOSONAR
|
Long cashierId = this.jdbcTemplate.queryForObject(sql, Long.class); // NOSONAR
|
||||||
validateSettleCashAndCashOutTransactions(cashierId, currencyCode, transactionAmount);
|
validateSettleCashAndCashOutTransactions(cashierId, currencyCode, transactionAmount);
|
||||||
@@ -122,6 +117,5 @@ public class CashierTransactionDataValidator {
|
|||||||
LOG.error("Problem occurred in validateOnLoanDisbursal function", e);
|
LOG.error("Problem occurred in validateOnLoanDisbursal function", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -35,6 +35,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.teller.exception.InvalidDateInputException;
|
import org.apache.fineract.organisation.teller.exception.InvalidDateInputException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -113,7 +114,7 @@ public final class TellerCommandFromApiJsonDeserializer {
|
|||||||
final String status = this.fromApiJsonHelper.extractStringNamed(STATUS, element);
|
final String status = this.fromApiJsonHelper.extractStringNamed(STATUS, element);
|
||||||
baseDataValidator.reset().parameter(STATUS).value(status).notBlank().notExceedingLengthOf(50);
|
baseDataValidator.reset().parameter(STATUS).value(status).notBlank().notExceedingLengthOf(50);
|
||||||
|
|
||||||
if (endDate != null && endDate.isBefore(startDate)) {
|
if (endDate != null && DateUtils.isBefore(endDate, startDate)) {
|
||||||
throw new InvalidDateInputException(startDate.toString(), endDate.toString());
|
throw new InvalidDateInputException(startDate.toString(), endDate.toString());
|
||||||
}
|
}
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
|||||||
+2
-2
@@ -75,12 +75,12 @@ public class ExecuteStandingInstructionsTasklet implements Tasklet {
|
|||||||
LocalDate startDate = data.validFrom();
|
LocalDate startDate = data.validFrom();
|
||||||
if (frequencyType.isMonthly()) {
|
if (frequencyType.isMonthly()) {
|
||||||
startDate = startDate.withDayOfMonth(data.recurrenceOnDay());
|
startDate = startDate.withDayOfMonth(data.recurrenceOnDay());
|
||||||
if (startDate.isBefore(data.validFrom())) {
|
if (DateUtils.isBefore(startDate, data.validFrom())) {
|
||||||
startDate = startDate.plusMonths(1);
|
startDate = startDate.plusMonths(1);
|
||||||
}
|
}
|
||||||
} else if (frequencyType.isYearly()) {
|
} else if (frequencyType.isYearly()) {
|
||||||
startDate = startDate.withDayOfMonth(data.recurrenceOnDay()).withMonth(data.recurrenceOnMonth());
|
startDate = startDate.withDayOfMonth(data.recurrenceOnDay()).withMonth(data.recurrenceOnMonth());
|
||||||
if (startDate.isBefore(data.validFrom())) {
|
if (DateUtils.isBefore(startDate, data.validFrom())) {
|
||||||
startDate = startDate.plusYears(1);
|
startDate = startDate.plusYears(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -536,8 +536,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
|||||||
BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(fromLoanAccountId).getPaidInAdvance();
|
BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(fromLoanAccountId).getPaidInAdvance();
|
||||||
final boolean backdatedTxnsAllowedTill = false;
|
final boolean backdatedTxnsAllowedTill = false;
|
||||||
|
|
||||||
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE
|
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 || transactionAmount.floatValue() > overpaid.floatValue()) {
|
||||||
: Boolean.FALSE || transactionAmount.floatValue() > overpaid.floatValue()) {
|
|
||||||
if (overpaid == null) {
|
if (overpaid == null) {
|
||||||
overpaid = BigDecimal.ZERO;
|
overpaid = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -279,7 +279,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
|||||||
periodStartDate = fromDate;
|
periodStartDate = fromDate;
|
||||||
} else {
|
} else {
|
||||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||||
if (seedDate.isBefore(currentDate.minusYears(1))) {
|
if (DateUtils.isBefore(seedDate, currentDate.minusYears(1))) {
|
||||||
periodStartDate = currentDate.minusYears(1);
|
periodStartDate = currentDate.minusYears(1);
|
||||||
} else {
|
} else {
|
||||||
periodStartDate = recurrenceStartDate;
|
periodStartDate = recurrenceStartDate;
|
||||||
@@ -294,7 +294,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
|||||||
|
|
||||||
if (tillDate != null) {
|
if (tillDate != null) {
|
||||||
if (endDate != null) {
|
if (endDate != null) {
|
||||||
if (endDate.isAfter(tillDate)) {
|
if (DateUtils.isAfter(endDate, tillDate)) {
|
||||||
// to retrieve meeting dates tillspecified date (tillDate)
|
// to retrieve meeting dates tillspecified date (tillDate)
|
||||||
periodEndDate = tillDate;
|
periodEndDate = tillDate;
|
||||||
}
|
}
|
||||||
@@ -302,7 +302,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
|||||||
// end date is null then fetch meeting dates tillDate
|
// end date is null then fetch meeting dates tillDate
|
||||||
periodEndDate = tillDate;
|
periodEndDate = tillDate;
|
||||||
}
|
}
|
||||||
} else if (endDate == null || endDate.isAfter(currentDate.plusYears(1))) {
|
} else if (endDate == null || DateUtils.isAfter(endDate, currentDate.plusYears(1))) {
|
||||||
periodEndDate = currentDate.plusYears(1);
|
periodEndDate = currentDate.plusYears(1);
|
||||||
}
|
}
|
||||||
return periodEndDate;
|
return periodEndDate;
|
||||||
|
|||||||
+2
-2
@@ -80,8 +80,8 @@ public class InternalClientInformationApiResource implements InitializingBean {
|
|||||||
|
|
||||||
final Client client = clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
|
final Client client = clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
|
||||||
Map<String, Object> auditFields = new HashMap<>(
|
Map<String, Object> auditFields = new HashMap<>(
|
||||||
Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
|
Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDateTime(), LAST_MODIFIED_BY,
|
||||||
client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDate().orElse(null)));
|
client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDateTime()));
|
||||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
return this.toApiJsonSerializer.serialize(settings, auditFields);
|
return this.toApiJsonSerializer.serialize(settings, auditFields);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -36,6 +36,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
|||||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
|
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -116,8 +117,7 @@ public class ClientNonPerson extends AbstractPersistableCustom {
|
|||||||
|
|
||||||
private void validateIncorpValidityTillDate(final Client client, final List<ApiParameterError> dataValidationErrors) {
|
private void validateIncorpValidityTillDate(final Client client, final List<ApiParameterError> dataValidationErrors) {
|
||||||
if (getIncorpValidityTillLocalDate() != null && client.dateOfBirthLocalDate() != null
|
if (getIncorpValidityTillLocalDate() != null && client.dateOfBirthLocalDate() != null
|
||||||
&& client.dateOfBirthLocalDate().isAfter(getIncorpValidityTillLocalDate())) {
|
&& DateUtils.isAfter(client.dateOfBirthLocalDate(), getIncorpValidityTillLocalDate())) {
|
||||||
|
|
||||||
final String defaultUserMessage = "incorpvaliditytill date cannot be after the incorporation date";
|
final String defaultUserMessage = "incorpvaliditytill date cannot be after the incorporation date";
|
||||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.incorpValidityTill.after.incorp.date",
|
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.incorpValidityTill.after.incorp.date",
|
||||||
defaultUserMessage, ClientApiConstants.incorpValidityTillParamName, this.incorpValidityTill);
|
defaultUserMessage, ClientApiConstants.incorpValidityTillParamName, this.incorpValidityTill);
|
||||||
|
|||||||
+3
-3
@@ -99,9 +99,9 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl
|
|||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
.resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME);
|
.resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME);
|
||||||
LocalDate activationDate = client.getActivationLocalDate();
|
LocalDate activationDate = client.getActivationDate();
|
||||||
LocalDate dueDate = clientCharge.getDueLocalDate();
|
LocalDate dueDate = clientCharge.getDueLocalDate();
|
||||||
if (dueDate.isBefore(activationDate)) {
|
if (DateUtils.isBefore(dueDate, activationDate)) {
|
||||||
baseDataValidator.reset().parameter(ClientApiConstants.dueAsOfDateParamName).value(dueDate.format(fmt))
|
baseDataValidator.reset().parameter(ClientApiConstants.dueAsOfDateParamName).value(dueDate.format(fmt))
|
||||||
.failWithCodeNoParameterAddedToErrorCode("dueDate.before.activationDate");
|
.failWithCodeNoParameterAddedToErrorCode("dueDate.before.activationDate");
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl
|
|||||||
if (requiresTransactionDateValidation) {
|
if (requiresTransactionDateValidation) {
|
||||||
validateTransactionDateOnWorkingDay(transactionDate, clientCharge, fmt);
|
validateTransactionDateOnWorkingDay(transactionDate, clientCharge, fmt);
|
||||||
|
|
||||||
if (client.getActivationLocalDate() != null && transactionDate.isBefore(client.getActivationLocalDate())) {
|
if (DateUtils.isBefore(transactionDate, client.getActivationDate())) {
|
||||||
baseDataValidator.reset().parameter(ClientApiConstants.transactionDateParamName).value(transactionDate.format(fmt))
|
baseDataValidator.reset().parameter(ClientApiConstants.transactionDateParamName).value(transactionDate.format(fmt))
|
||||||
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
|||||||
+10
-10
@@ -277,7 +277,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
if (command.hasParameter(ClientApiConstants.submittedOnDateParamName)) {
|
if (command.hasParameter(ClientApiConstants.submittedOnDateParamName)) {
|
||||||
submittedOnDate = command.localDateValueOfParameterNamed(ClientApiConstants.submittedOnDateParamName);
|
submittedOnDate = command.localDateValueOfParameterNamed(ClientApiConstants.submittedOnDateParamName);
|
||||||
}
|
}
|
||||||
if (active && submittedOnDate.isAfter(activationDate)) {
|
if (active && DateUtils.isAfter(submittedOnDate, activationDate)) {
|
||||||
submittedOnDate = activationDate;
|
submittedOnDate = activationDate;
|
||||||
}
|
}
|
||||||
final Long savingsAccountId = null;
|
final Long savingsAccountId = null;
|
||||||
@@ -743,7 +743,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
CommandProcessingResult commandProcessingResult = CommandProcessingResult.empty();
|
CommandProcessingResult commandProcessingResult = CommandProcessingResult.empty();
|
||||||
if (client.isActive() && client.savingsProductId() != null) {
|
if (client.isActive() && client.savingsProductId() != null) {
|
||||||
SavingsAccountDataDTO savingsAccountDataDTO = new SavingsAccountDataDTO(client, null, client.savingsProductId(),
|
SavingsAccountDataDTO savingsAccountDataDTO = new SavingsAccountDataDTO(client, null, client.savingsProductId(),
|
||||||
client.getActivationLocalDate(), client.activatedBy(), fmt);
|
client.getActivationDate(), client.activatedBy(), fmt);
|
||||||
commandProcessingResult = this.savingsApplicationProcessWritePlatformService.createActiveApplication(savingsAccountDataDTO);
|
commandProcessingResult = this.savingsApplicationProcessWritePlatformService.createActiveApplication(savingsAccountDataDTO);
|
||||||
if (commandProcessingResult.getSavingsId() != null) {
|
if (commandProcessingResult.getSavingsId() != null) {
|
||||||
this.savingsRepositoryWrapper.findOneWithNotFoundDetection(commandProcessingResult.getSavingsId());
|
this.savingsRepositoryWrapper.findOneWithNotFoundDetection(commandProcessingResult.getSavingsId());
|
||||||
@@ -851,10 +851,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
throw new InvalidClientStateTransitionException("close", "is.under.transfer", errorMessage);
|
throw new InvalidClientStateTransitionException("close", "is.under.transfer", errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.isNotPending() && client.getActivationLocalDate() != null && client.getActivationLocalDate().isAfter(closureDate)) {
|
if (client.isNotPending() && DateUtils.isAfter(client.getActivationDate(), closureDate)) {
|
||||||
final String errorMessage = "The client closureDate cannot be before the client ActivationDate.";
|
final String errorMessage = "The client closureDate cannot be before the client ActivationDate.";
|
||||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.client.actvation.date", errorMessage,
|
throw new InvalidClientStateTransitionException("close", "date.cannot.before.client.actvation.date", errorMessage,
|
||||||
closureDate, client.getActivationLocalDate());
|
closureDate, client.getActivationDate());
|
||||||
}
|
}
|
||||||
final LegalForm legalForm = LegalForm.fromInt(client.getLegalForm());
|
final LegalForm legalForm = LegalForm.fromInt(client.getLegalForm());
|
||||||
entityDatatableChecksWritePlatformService.runTheCheck(clientId, EntityTables.CLIENT.getName(), StatusEnum.CLOSE.getCode(),
|
entityDatatableChecksWritePlatformService.runTheCheck(clientId, EntityTables.CLIENT.getName(), StatusEnum.CLOSE.getCode(),
|
||||||
@@ -866,7 +866,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
if (loanStatus.isOpen() || loanStatus.isPendingApproval() || loanStatus.isAwaitingDisbursal()) {
|
if (loanStatus.isOpen() || loanStatus.isPendingApproval() || loanStatus.isAwaitingDisbursal()) {
|
||||||
final String errorMessage = "Client cannot be closed because of non-closed loans.";
|
final String errorMessage = "Client cannot be closed because of non-closed loans.";
|
||||||
throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage);
|
throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage);
|
||||||
} else if (loanStatus.isClosed() && loan.getClosedOnDate().isAfter(closureDate)) {
|
} else if (loanStatus.isClosed() && DateUtils.isAfter(loan.getClosedOnDate(), closureDate)) {
|
||||||
final String errorMessage = "The client closureDate cannot be before the loan closedOnDate.";
|
final String errorMessage = "The client closureDate cannot be before the loan closedOnDate.";
|
||||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.loan.closed.date", errorMessage,
|
throw new InvalidClientStateTransitionException("close", "date.cannot.before.loan.closed.date", errorMessage,
|
||||||
closureDate, loan.getClosedOnDate());
|
closureDate, loan.getClosedOnDate());
|
||||||
@@ -976,7 +976,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
||||||
throw new InvalidClientStateTransitionException("rejection", "on.account.not.in.pending.activation.status", errorMessage,
|
throw new InvalidClientStateTransitionException("rejection", "on.account.not.in.pending.activation.status", errorMessage,
|
||||||
rejectionDate, client.getSubmittedOnDate());
|
rejectionDate, client.getSubmittedOnDate());
|
||||||
} else if (client.getSubmittedOnDate().isAfter(rejectionDate)) {
|
} else if (DateUtils.isAfter(client.getSubmittedOnDate(), rejectionDate)) {
|
||||||
final String errorMessage = "The client rejection date cannot be before the client submitted date.";
|
final String errorMessage = "The client rejection date cannot be before the client submitted date.";
|
||||||
throw new InvalidClientStateTransitionException("rejection", "date.cannot.before.client.submitted.date", errorMessage,
|
throw new InvalidClientStateTransitionException("rejection", "date.cannot.before.client.submitted.date", errorMessage,
|
||||||
rejectionDate, client.getSubmittedOnDate());
|
rejectionDate, client.getSubmittedOnDate());
|
||||||
@@ -1008,7 +1008,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
||||||
throw new InvalidClientStateTransitionException("withdrawal", "on.account.not.in.pending.activation.status", errorMessage,
|
throw new InvalidClientStateTransitionException("withdrawal", "on.account.not.in.pending.activation.status", errorMessage,
|
||||||
withdrawalDate, client.getSubmittedOnDate());
|
withdrawalDate, client.getSubmittedOnDate());
|
||||||
} else if (client.getSubmittedOnDate().isAfter(withdrawalDate)) {
|
} else if (DateUtils.isAfter(client.getSubmittedOnDate(), withdrawalDate)) {
|
||||||
final String errorMessage = "The client withdrawal date cannot be before the client submitted date.";
|
final String errorMessage = "The client withdrawal date cannot be before the client submitted date.";
|
||||||
throw new InvalidClientStateTransitionException("withdrawal", "date.cannot.before.client.submitted.date", errorMessage,
|
throw new InvalidClientStateTransitionException("withdrawal", "date.cannot.before.client.submitted.date", errorMessage,
|
||||||
withdrawalDate, client.getSubmittedOnDate());
|
withdrawalDate, client.getSubmittedOnDate());
|
||||||
@@ -1034,7 +1034,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
if (!client.isClosed()) {
|
if (!client.isClosed()) {
|
||||||
final String errorMessage = "only closed clients may be reactivated.";
|
final String errorMessage = "only closed clients may be reactivated.";
|
||||||
throw new InvalidClientStateTransitionException("reactivation", "on.nonclosed.account", errorMessage);
|
throw new InvalidClientStateTransitionException("reactivation", "on.nonclosed.account", errorMessage);
|
||||||
} else if (client.getClosureDate().isAfter(reactivateDate)) {
|
} else if (DateUtils.isAfter(client.getClosureDate(), reactivateDate)) {
|
||||||
final String errorMessage = "The client reactivation date cannot be before the client closed date.";
|
final String errorMessage = "The client reactivation date cannot be before the client closed date.";
|
||||||
throw new InvalidClientStateTransitionException("reactivation", "date.cannot.before.client.closed.date", errorMessage,
|
throw new InvalidClientStateTransitionException("reactivation", "date.cannot.before.client.closed.date", errorMessage,
|
||||||
reactivateDate, client.getClosureDate());
|
reactivateDate, client.getClosureDate());
|
||||||
@@ -1060,7 +1060,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
if (!client.isRejected()) {
|
if (!client.isRejected()) {
|
||||||
final String errorMessage = "only rejected clients may be reactivated.";
|
final String errorMessage = "only rejected clients may be reactivated.";
|
||||||
throw new InvalidClientStateTransitionException("undorejection", "on.nonrejected.account", errorMessage);
|
throw new InvalidClientStateTransitionException("undorejection", "on.nonrejected.account", errorMessage);
|
||||||
} else if (client.getRejectedDate().isAfter(undoRejectDate)) {
|
} else if (DateUtils.isAfter(client.getRejectedDate(), undoRejectDate)) {
|
||||||
final String errorMessage = "The client reactivation date cannot be before the client rejected date.";
|
final String errorMessage = "The client reactivation date cannot be before the client rejected date.";
|
||||||
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.rejected.date", errorMessage,
|
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.rejected.date", errorMessage,
|
||||||
undoRejectDate, client.getRejectedDate());
|
undoRejectDate, client.getRejectedDate());
|
||||||
@@ -1088,7 +1088,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
if (!client.isWithdrawn()) {
|
if (!client.isWithdrawn()) {
|
||||||
final String errorMessage = "only withdrawal clients may be reactivated.";
|
final String errorMessage = "only withdrawal clients may be reactivated.";
|
||||||
throw new InvalidClientStateTransitionException("undoWithdrawal", "on.nonwithdrawal.account", errorMessage);
|
throw new InvalidClientStateTransitionException("undoWithdrawal", "on.nonwithdrawal.account", errorMessage);
|
||||||
} else if (client.getWithdrawalDate().isAfter(undoWithdrawalDate)) {
|
} else if (DateUtils.isAfter(client.getWithdrawalDate(), undoWithdrawalDate)) {
|
||||||
final String errorMessage = "The client reactivation date cannot be before the client withdrawal date.";
|
final String errorMessage = "The client reactivation date cannot be before the client withdrawal date.";
|
||||||
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.withdrawal.date", errorMessage,
|
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.withdrawal.date", errorMessage,
|
||||||
undoWithdrawalDate, client.getWithdrawalDate());
|
undoWithdrawalDate, client.getWithdrawalDate());
|
||||||
|
|||||||
+12
-11
@@ -55,7 +55,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
|||||||
// Get the oldest overdue installment if exists one
|
// Get the oldest overdue installment if exists one
|
||||||
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
|
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
|
||||||
if (!installment.isObligationsMet()) {
|
if (!installment.isObligationsMet()) {
|
||||||
if (installment.getDueDate().isBefore(businessDate)) {
|
if (DateUtils.isBefore(installment.getDueDate(), businessDate)) {
|
||||||
log.debug("Loan Id: {} with installment {} due date {}", loan.getId(), installment.getInstallmentNumber(),
|
log.debug("Loan Id: {} with installment {} due date {}", loan.getId(), installment.getInstallmentNumber(),
|
||||||
installment.getDueDate());
|
installment.getDueDate());
|
||||||
outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount());
|
outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount());
|
||||||
@@ -69,13 +69,13 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
|||||||
|
|
||||||
boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
|
boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
|
||||||
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
||||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
|
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = DateUtils
|
||||||
installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
|
.isEqual(loanTransaction.getTransactionDate(), installment.getFromDate())
|
||||||
|
|| DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getFromDate());
|
||||||
boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
|
boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
|
||||||
&& loanTransaction.getTransactionDate().isBefore(installment.getDueDate());
|
&& DateUtils.isBefore(loanTransaction.getTransactionDate(), installment.getDueDate());
|
||||||
boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
|
boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
|
||||||
&& (loanTransaction.getTransactionDate().isEqual(installment.getDueDate())
|
&& !DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getDueDate());
|
||||||
|| loanTransaction.getTransactionDate().isBefore(installment.getDueDate()));
|
|
||||||
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && (isLoanTransactionIsBeforeNotLastInstallmentDueDate
|
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && (isLoanTransactionIsBeforeNotLastInstallmentDueDate
|
||||||
|| isLoanTransactionIsOnOrBeforeLastInstallmentDueDate)) {
|
|| isLoanTransactionIsOnOrBeforeLastInstallmentDueDate)) {
|
||||||
amountAvailable = amountAvailable.subtract(loanTransaction.getAmount());
|
amountAvailable = amountAvailable.subtract(loanTransaction.getAmount());
|
||||||
@@ -93,11 +93,12 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
|||||||
amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
|
amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
|
||||||
log.debug("Amount available {}", amountAvailable);
|
log.debug("Amount available {}", amountAvailable);
|
||||||
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
||||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
|
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = !DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||||
installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
|
installment.getFromDate());
|
||||||
boolean isLoanTransactionIsBeforeInstallmentDueDate = loanTransaction.getTransactionDate()
|
boolean isLoanTransactionIsBeforeInstallmentDueDate = DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||||
.isBefore(installment.getDueDate());
|
installment.getDueDate());
|
||||||
boolean isLoanTransactionIsBeforeBusinessDate = loanTransaction.getTransactionDate().isBefore(businessDate);
|
boolean isLoanTransactionIsBeforeBusinessDate = DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||||
|
businessDate);
|
||||||
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && isLoanTransactionIsBeforeInstallmentDueDate
|
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && isLoanTransactionIsBeforeInstallmentDueDate
|
||||||
&& isLoanTransactionIsBeforeBusinessDate) {
|
&& isLoanTransactionIsBeforeBusinessDate) {
|
||||||
log.debug("Loan CB Transaction: {} {} {}", loanTransaction.getId(), loanTransaction.getTransactionDate(),
|
log.debug("Loan CB Transaction: {} {} {}", loanTransaction.getId(), loanTransaction.getTransactionDate(),
|
||||||
|
|||||||
+8
-18
@@ -153,7 +153,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
|
|
||||||
final boolean active = command.booleanPrimitiveValueOfParameterNamed(GroupingTypesApiConstants.activeParamName);
|
final boolean active = command.booleanPrimitiveValueOfParameterNamed(GroupingTypesApiConstants.activeParamName);
|
||||||
LocalDate submittedOnDate = DateUtils.getBusinessLocalDate();
|
LocalDate submittedOnDate = DateUtils.getBusinessLocalDate();
|
||||||
if (active && submittedOnDate.isAfter(activationDate)) {
|
if (active && DateUtils.isAfter(submittedOnDate, activationDate)) {
|
||||||
submittedOnDate = activationDate;
|
submittedOnDate = activationDate;
|
||||||
}
|
}
|
||||||
if (command.hasParameter(GroupingTypesApiConstants.submittedOnDateParamName)) {
|
if (command.hasParameter(GroupingTypesApiConstants.submittedOnDateParamName)) {
|
||||||
@@ -616,7 +616,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed because of non-closed loans.";
|
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed because of non-closed loans.";
|
||||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
|
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
|
||||||
errorMessage);
|
errorMessage);
|
||||||
} else if (loanStatus.isClosed() && loan.getClosedOnDate().isAfter(closureDate)) {
|
} else if (loanStatus.isClosed() && DateUtils.isAfter(loan.getClosedOnDate(), closureDate)) {
|
||||||
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName()
|
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName()
|
||||||
+ "closureDate cannot be before the loan closedOnDate.";
|
+ "closureDate cannot be before the loan closedOnDate.";
|
||||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
||||||
@@ -640,7 +640,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
+ " cannot be closed with active savings accounts associated.";
|
+ " cannot be closed with active savings accounts associated.";
|
||||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
||||||
"savings.account.not.closed", errorMessage);
|
"savings.account.not.closed", errorMessage);
|
||||||
} else if (saving.isClosed() && saving.getClosedOnDate().isAfter(closureDate)) {
|
} else if (saving.isClosed() && DateUtils.isAfter(saving.getClosedOnDate(), closureDate)) {
|
||||||
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName()
|
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName()
|
||||||
+ " closureDate cannot be before the loan closedOnDate.";
|
+ " closureDate cannot be before the loan closedOnDate.";
|
||||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
||||||
@@ -906,7 +906,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
|
|
||||||
public void validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(final Office groupOffice, final GroupLevel groupLevel,
|
public void validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(final Office groupOffice, final GroupLevel groupLevel,
|
||||||
final LocalDate activationDate) {
|
final LocalDate activationDate) {
|
||||||
if (activationDate != null && groupOffice.getOpeningLocalDate().isAfter(activationDate)) {
|
if (activationDate != null && DateUtils.isAfter(groupOffice.getOpeningLocalDate(), activationDate)) {
|
||||||
final String levelName = groupLevel.getLevelName();
|
final String levelName = groupLevel.getLevelName();
|
||||||
final String errorMessage = levelName + " activation date should be greater than or equal to the parent Office's creation date "
|
final String errorMessage = levelName + " activation date should be greater than or equal to the parent Office's creation date "
|
||||||
+ activationDate.toString();
|
+ activationDate.toString();
|
||||||
@@ -916,10 +916,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkGroupMembersMeetingSyncWithCenterMeeting(final Long centerId, final Set<Group> groupMembers) {
|
private void checkGroupMembersMeetingSyncWithCenterMeeting(final Long centerId, final Set<Group> groupMembers) {
|
||||||
|
// Get parent(center) calendar
|
||||||
/**
|
|
||||||
* Get parent(center) calendar
|
|
||||||
*/
|
|
||||||
Calendar ceneterCalendar = null;
|
Calendar ceneterCalendar = null;
|
||||||
final CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
final CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||||
centerId, CalendarEntityType.CENTERS.getValue(), CalendarType.COLLECTION.getValue());
|
centerId, CalendarEntityType.CENTERS.getValue(), CalendarType.COLLECTION.getValue());
|
||||||
@@ -928,9 +925,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Group group : groupMembers) {
|
for (final Group group : groupMembers) {
|
||||||
/**
|
// Get child(group) calendar
|
||||||
* Get child(group) calendar
|
|
||||||
*/
|
|
||||||
Calendar groupCalendar = null;
|
Calendar groupCalendar = null;
|
||||||
final CalendarInstance groupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
final CalendarInstance groupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||||
group.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue());
|
group.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue());
|
||||||
@@ -938,19 +933,14 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
groupCalendar = groupCalendarInstance.getCalendar();
|
groupCalendar = groupCalendarInstance.getCalendar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Group shouldn't have a meeting when no meeting attached for center
|
||||||
* Group shouldn't have a meeting when no meeting attached for center
|
|
||||||
*/
|
|
||||||
if (ceneterCalendar == null && groupCalendar != null) {
|
if (ceneterCalendar == null && groupCalendar != null) {
|
||||||
throw new GeneralPlatformDomainRuleException(
|
throw new GeneralPlatformDomainRuleException(
|
||||||
"error.msg.center.associating.group.not.allowed.with.meeting.attached.to.group",
|
"error.msg.center.associating.group.not.allowed.with.meeting.attached.to.group",
|
||||||
"Group with id " + group.getId() + " is already associated with meeting", group.getId());
|
"Group with id " + group.getId() + " is already associated with meeting", group.getId());
|
||||||
}
|
}
|
||||||
/**
|
// Group meeting recurrence should match with center meeting recurrence
|
||||||
* Group meeting recurrence should match with center meeting recurrence
|
|
||||||
*/
|
|
||||||
else if (ceneterCalendar != null && groupCalendar != null) {
|
else if (ceneterCalendar != null && groupCalendar != null) {
|
||||||
|
|
||||||
if (!ceneterCalendar.getRecurrence().equalsIgnoreCase(groupCalendar.getRecurrence())) {
|
if (!ceneterCalendar.getRecurrence().equalsIgnoreCase(groupCalendar.getRecurrence())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.center.associating.group.not.allowed.with.different.meeting",
|
throw new GeneralPlatformDomainRuleException("error.msg.center.associating.group.not.allowed.with.different.meeting",
|
||||||
"Group with id " + group.getId() + " meeting recurrence doesnot matched with center meeting recurrence",
|
"Group with id " + group.getId() + " meeting recurrence doesnot matched with center meeting recurrence",
|
||||||
|
|||||||
+2
-1
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing a InterestRateChart.
|
* Immutable data object representing a InterestRateChart.
|
||||||
@@ -143,7 +144,7 @@ public final class InterestRateChartData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFromDateAfter(final LocalDate compareDate) {
|
public boolean isFromDateAfter(final LocalDate compareDate) {
|
||||||
return (compareDate == null) ? false : this.fromDate.isAfter(compareDate);
|
return compareDate != null && DateUtils.isAfter(this.fromDate, compareDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate endDate() {
|
public LocalDate endDate() {
|
||||||
|
|||||||
+5
-9
@@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants;
|
import org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -115,10 +116,8 @@ public class InterestRateChartDataValidator {
|
|||||||
isPrimaryGroupingByAmount = false;
|
isPrimaryGroupingByAmount = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromDate != null && toDate != null) {
|
if (toDate != null && DateUtils.isAfter(fromDate, toDate)) {
|
||||||
if (fromDate.isAfter(toDate)) {
|
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate chart Slabs - mandatory when creating
|
// validate chart Slabs - mandatory when creating
|
||||||
@@ -177,11 +176,8 @@ public class InterestRateChartDataValidator {
|
|||||||
if (isPrimaryGroupingByAmount == null) {
|
if (isPrimaryGroupingByAmount == null) {
|
||||||
isPrimaryGroupingByAmount = false;
|
isPrimaryGroupingByAmount = false;
|
||||||
}
|
}
|
||||||
|
if (toDate != null && DateUtils.isAfter(fromDate, toDate)) {
|
||||||
if (fromDate != null && toDate != null) {
|
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||||
if (fromDate.isAfter(toDate)) {
|
|
||||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
|
validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
|
||||||
|
|||||||
+2
-5
@@ -312,10 +312,7 @@ public class InterestRateChartSlabFields {
|
|||||||
|
|
||||||
public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) {
|
public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) {
|
||||||
if (obj1 == null || obj2 == null) {
|
if (obj1 == null || obj2 == null) {
|
||||||
if (Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
return Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return obj1.compareTo(obj2) == 0;
|
return obj1.compareTo(obj2) == 0;
|
||||||
}
|
}
|
||||||
@@ -326,7 +323,7 @@ public class InterestRateChartSlabFields {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAmountRangeProvided() {
|
public boolean isAmountRangeProvided() {
|
||||||
return (this.amountRangeFrom == null) ? false : true;
|
return this.amountRangeFrom != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal annualInterestRate() {
|
public BigDecimal annualInterestRate() {
|
||||||
|
|||||||
+4
-4
@@ -88,8 +88,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
|
|||||||
|
|
||||||
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||||
Map<String, Object> auditFields = new HashMap<>(
|
Map<String, Object> auditFields = new HashMap<>(
|
||||||
Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
|
Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDateTime(), LAST_MODIFIED_BY,
|
||||||
loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDate().orElse(null)));
|
loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDateTime()));
|
||||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
||||||
}
|
}
|
||||||
@@ -108,8 +108,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
|
|||||||
|
|
||||||
final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow();
|
final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow();
|
||||||
Map<String, Object> auditFields = new HashMap<>(Map.of(CREATED_BY, transaction.getCreatedBy().orElse(null), CREATED_DATE,
|
Map<String, Object> auditFields = new HashMap<>(Map.of(CREATED_BY, transaction.getCreatedBy().orElse(null), CREATED_DATE,
|
||||||
transaction.getCreatedDate().orElse(null), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null),
|
transaction.getCreatedDateTime(), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE,
|
||||||
LAST_MODIFIED_DATE, transaction.getLastModifiedDate().orElse(null)));
|
transaction.getLastModifiedDateTime()));
|
||||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -369,7 +369,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
final Integer transactionType, Integer installmentNumber) {
|
final Integer transactionType, Integer installmentNumber) {
|
||||||
boolean isAccountTransfer = true;
|
boolean isAccountTransfer = true;
|
||||||
checkClientOrGroupActive(loan);
|
checkClientOrGroupActive(loan);
|
||||||
if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -465,7 +465,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
boolean isAccountTransfer = true;
|
boolean isAccountTransfer = true;
|
||||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||||
checkClientOrGroupActive(loan);
|
checkClientOrGroupActive(loan);
|
||||||
if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -518,7 +518,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId, final boolean isLoanToLoanTransfer) {
|
final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId, final boolean isLoanToLoanTransfer) {
|
||||||
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
||||||
checkClientOrGroupActive(loan);
|
checkClientOrGroupActive(loan);
|
||||||
if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -551,7 +551,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
@Override
|
@Override
|
||||||
public void reverseTransfer(final LoanTransaction loanTransaction) {
|
public void reverseTransfer(final LoanTransaction loanTransaction) {
|
||||||
if (loanTransaction.getLoan().isChargedOff()
|
if (loanTransaction.getLoan().isChargedOff()
|
||||||
&& loanTransaction.getTransactionDate().isBefore(loanTransaction.getLoan().getChargedOffOnDate())) {
|
&& DateUtils.isBefore(loanTransaction.getTransactionDate(), loanTransaction.getLoan().getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date",
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date",
|
||||||
"Loan transaction: " + loanTransaction.getId()
|
"Loan transaction: " + loanTransaction.getId()
|
||||||
+ " reversal is not allowed before or on the date when the loan got charged-off",
|
+ " reversal is not allowed before or on the date when the loan got charged-off",
|
||||||
@@ -614,10 +614,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
Set<LoanCharge> loanCharges = loan.getActiveCharges();
|
Set<LoanCharge> loanCharges = loan.getActiveCharges();
|
||||||
|
|
||||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
if (installment.getDueDate().isAfter(loan.getMaturityDate())) {
|
if (DateUtils.isAfter(installment.getDueDate(), loan.getMaturityDate())) {
|
||||||
accruedTill = DateUtils.getBusinessLocalDate();
|
accruedTill = DateUtils.getBusinessLocalDate();
|
||||||
}
|
}
|
||||||
if (!isOrganisationDateEnabled || organisationStartDate.isBefore(installment.getDueDate())) {
|
if (!isOrganisationDateEnabled || DateUtils.isBefore(organisationStartDate, installment.getDueDate())) {
|
||||||
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate,
|
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate,
|
||||||
repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges,
|
repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges,
|
||||||
installment);
|
installment);
|
||||||
@@ -641,12 +641,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
final LocalDate interestCalculatedFrom, final Long loanProductId, final MonetaryCurrency currency,
|
final LocalDate interestCalculatedFrom, final Long loanProductId, final MonetaryCurrency currency,
|
||||||
final CurrencyData currencyData, final Set<LoanCharge> loanCharges, final LoanRepaymentScheduleInstallment installment) {
|
final CurrencyData currencyData, final Set<LoanCharge> loanCharges, final LoanRepaymentScheduleInstallment installment) {
|
||||||
|
|
||||||
if (!accruedTill.isBefore(installment.getDueDate())
|
if (!DateUtils.isBefore(accruedTill, installment.getDueDate()) || (DateUtils.isAfter(accruedTill, installment.getFromDate())
|
||||||
|| (accruedTill.isAfter(installment.getFromDate()) && !accruedTill.isAfter(installment.getDueDate()))) {
|
&& !DateUtils.isAfter(accruedTill, installment.getDueDate()))) {
|
||||||
BigDecimal dueDateFeeIncome = BigDecimal.ZERO;
|
BigDecimal dueDateFeeIncome = BigDecimal.ZERO;
|
||||||
BigDecimal dueDatePenaltyIncome = BigDecimal.ZERO;
|
BigDecimal dueDatePenaltyIncome = BigDecimal.ZERO;
|
||||||
LocalDate chargesTillDate = installment.getDueDate();
|
LocalDate chargesTillDate = installment.getDueDate();
|
||||||
if (!accruedTill.isAfter(installment.getDueDate())) {
|
if (!DateUtils.isAfter(accruedTill, installment.getDueDate())) {
|
||||||
chargesTillDate = accruedTill;
|
chargesTillDate = accruedTill;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,7 +685,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
@Override
|
@Override
|
||||||
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||||
final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) {
|
final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) {
|
||||||
if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -729,7 +729,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||||
|
|
||||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||||
if (loan.isChargedOff() && transactionDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -768,7 +768,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
@Override
|
@Override
|
||||||
public LoanTransaction foreCloseLoan(Loan loan, final LocalDate foreClosureDate, final String noteText, final ExternalId externalId,
|
public LoanTransaction foreCloseLoan(Loan loan, final LocalDate foreClosureDate, final String noteText, final ExternalId externalId,
|
||||||
Map<String, Object> changes) {
|
Map<String, Object> changes) {
|
||||||
if (loan.isChargedOff() && foreClosureDate.isBefore(loan.getChargedOffOnDate())) {
|
if (loan.isChargedOff() && DateUtils.isBefore(foreClosureDate, loan.getChargedOffOnDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||||
+ loan.getId()
|
+ loan.getId()
|
||||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||||
@@ -785,7 +785,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = null;
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = null;
|
||||||
final LoanRepaymentScheduleInstallment foreCloseDetail = loan.fetchLoanForeclosureDetail(foreClosureDate);
|
final LoanRepaymentScheduleInstallment foreCloseDetail = loan.fetchLoanForeclosureDetail(foreClosureDate);
|
||||||
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()
|
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()
|
||||||
&& (loan.getAccruedTill() == null || !foreClosureDate.isEqual(loan.getAccruedTill()))) {
|
&& (loan.getAccruedTill() == null || !DateUtils.isEqual(foreClosureDate, loan.getAccruedTill()))) {
|
||||||
loan.reverseAccrualsAfter(foreClosureDate);
|
loan.reverseAccrualsAfter(foreClosureDate);
|
||||||
Money[] accruedReceivables = loan.getReceivableIncome(foreClosureDate);
|
Money[] accruedReceivables = loan.getReceivableIncome(foreClosureDate);
|
||||||
Money interestPortion = foreCloseDetail.getInterestCharged(currency).minus(accruedReceivables[0]);
|
Money interestPortion = foreCloseDetail.getInterestCharged(currency).minus(accruedReceivables[0]);
|
||||||
@@ -805,7 +805,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loan.addLoanTransaction(accrualTransaction);
|
loan.addLoanTransaction(accrualTransaction);
|
||||||
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
||||||
for (LoanCharge loanCharge : loan.getActiveCharges()) {
|
for (LoanCharge loanCharge : loan.getActiveCharges()) {
|
||||||
boolean isDue = fromDate.isEqual(loan.getDisbursementDate())
|
boolean isDue = DateUtils.isEqual(fromDate, loan.getDisbursementDate())
|
||||||
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, foreClosureDate)
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, foreClosureDate)
|
||||||
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate);
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate);
|
||||||
if (loanCharge.isActive() && !loanCharge.isPaid() && (isDue || loanCharge.isInstalmentFee())) {
|
if (loanCharge.isActive() && !loanCharge.isPaid() && (isDue || loanCharge.isInstalmentFee())) {
|
||||||
|
|||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.loanaccount.domain;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
|
||||||
|
|
||||||
public class LoanRepaymentDataComparator implements Comparator<LoanTransactionData> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(final LoanTransactionData o1, final LoanTransactionData o2) {
|
|
||||||
return o2.getDate().compareTo(o1.getDate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-4
@@ -29,10 +29,8 @@ public class LoanTermVariationsComparator implements Comparator<LoanTermVariatio
|
|||||||
public int compare(final LoanTermVariations o1, final LoanTermVariations o2) {
|
public int compare(final LoanTermVariations o1, final LoanTermVariations o2) {
|
||||||
int compareResult = 0;
|
int compareResult = 0;
|
||||||
final int comparsion = o1.getTermApplicableFrom().compareTo(o2.getTermApplicableFrom());
|
final int comparsion = o1.getTermApplicableFrom().compareTo(o2.getTermApplicableFrom());
|
||||||
/**
|
// For Terms bearing the same effective date, we sort based on modified date (when available) and new inserted
|
||||||
* For Terms bearing the same effective date, we sort based on modified date (when available) and new inserted
|
// installment
|
||||||
* installment
|
|
||||||
**/
|
|
||||||
if (comparsion == 0) {
|
if (comparsion == 0) {
|
||||||
if (o2.getTermType().isDueDateVariation() || o2.getTermType().isInsertInstallment()) {
|
if (o2.getTermType().isDueDateVariation() || o2.getTermType().isInsertInstallment()) {
|
||||||
compareResult = 1;
|
compareResult = 1;
|
||||||
|
|||||||
+16
-14
@@ -27,6 +27,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
@@ -312,7 +313,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
protected boolean isTransactionInAdvanceOfInstallment(final int installmentIndex,
|
protected boolean isTransactionInAdvanceOfInstallment(final int installmentIndex,
|
||||||
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
||||||
final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex);
|
final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex);
|
||||||
return transactionDate.isBefore(currentInstallment.getDueDate());
|
return DateUtils.isBefore(transactionDate, currentInstallment.getDueDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,7 +326,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
protected boolean isTransactionALateRepaymentOnInstallment(final int installmentIndex,
|
protected boolean isTransactionALateRepaymentOnInstallment(final int installmentIndex,
|
||||||
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
||||||
final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex);
|
final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex);
|
||||||
return transactionDate.isAfter(currentInstallment.getDueDate());
|
return DateUtils.isAfter(transactionDate, currentInstallment.getDueDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recalculateChargeOffTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
private void recalculateChargeOffTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
||||||
@@ -477,7 +478,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
LocalDate pastDueDate = null;
|
LocalDate pastDueDate = null;
|
||||||
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
||||||
pastDueDate = currentInstallment.getDueDate();
|
pastDueDate = currentInstallment.getDueDate();
|
||||||
if (!currentInstallment.isAdditional() && currentInstallment.getDueDate().isAfter(transactionDate)) {
|
if (!currentInstallment.isAdditional() && DateUtils.isAfter(currentInstallment.getDueDate(), transactionDate)) {
|
||||||
currentInstallment.addToCredits(transactionAmount.getAmount());
|
currentInstallment.addToCredits(transactionAmount.getAmount());
|
||||||
currentInstallment.addToPrincipal(transactionDate, transactionAmount);
|
currentInstallment.addToPrincipal(transactionDate, transactionAmount);
|
||||||
if (repaidAmount.isGreaterThanZero()) {
|
if (repaidAmount.isGreaterThanZero()) {
|
||||||
@@ -491,7 +492,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
// If already exists an additional installment just update the due date and
|
// If already exists an additional installment just update the due date and
|
||||||
// principal from the Loan chargeback / CBR transaction
|
// principal from the Loan chargeback / CBR transaction
|
||||||
} else if (currentInstallment.isAdditional()) {
|
} else if (currentInstallment.isAdditional()) {
|
||||||
if (transactionDate.isAfter(currentInstallment.getDueDate())) {
|
if (DateUtils.isAfter(transactionDate, currentInstallment.getDueDate())) {
|
||||||
currentInstallment.updateDueDate(transactionDate);
|
currentInstallment.updateDueDate(transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,18 +670,19 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
if (loanCharge.getAmountOutstanding(currency).isGreaterThanZero() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.getAmountOutstanding(currency).isGreaterThanZero() && !loanCharge.isDueAtDisbursement()) {
|
||||||
if (loanCharge.isInstalmentFee()) {
|
if (loanCharge.isInstalmentFee()) {
|
||||||
LoanInstallmentCharge unpaidLoanChargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge();
|
LoanInstallmentCharge unpaidLoanChargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge();
|
||||||
if (chargePerInstallment == null || chargePerInstallment.getRepaymentInstallment().getDueDate()
|
if (chargePerInstallment == null || DateUtils.isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||||
.isAfter(unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
||||||
installemntCharge = loanCharge;
|
installemntCharge = loanCharge;
|
||||||
chargePerInstallment = unpaidLoanChargePerInstallment;
|
chargePerInstallment = unpaidLoanChargePerInstallment;
|
||||||
}
|
}
|
||||||
} else if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
} else if (earliestUnpaidCharge == null
|
||||||
|
|| DateUtils.isBefore(loanCharge.getDueLocalDate(), earliestUnpaidCharge.getDueLocalDate())) {
|
||||||
earliestUnpaidCharge = loanCharge;
|
earliestUnpaidCharge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (earliestUnpaidCharge == null || (chargePerInstallment != null
|
if (earliestUnpaidCharge == null || (chargePerInstallment != null && DateUtils.isAfter(earliestUnpaidCharge.getDueLocalDate(),
|
||||||
&& earliestUnpaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||||
earliestUnpaidCharge = installemntCharge;
|
earliestUnpaidCharge = installemntCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,20 +793,20 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
if (loanCharge.isInstalmentFee()) {
|
if (loanCharge.isInstalmentFee()) {
|
||||||
LoanInstallmentCharge paidLoanChargePerInstallment = loanCharge
|
LoanInstallmentCharge paidLoanChargePerInstallment = loanCharge
|
||||||
.getLastPaidOrPartiallyPaidInstallmentLoanCharge(currency);
|
.getLastPaidOrPartiallyPaidInstallmentLoanCharge(currency);
|
||||||
if (chargePerInstallment == null
|
if (chargePerInstallment == null || (paidLoanChargePerInstallment != null
|
||||||
|| (paidLoanChargePerInstallment != null && chargePerInstallment.getRepaymentInstallment().getDueDate()
|
&& DateUtils.isBefore(chargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||||
.isBefore(paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||||
installemntCharge = loanCharge;
|
installemntCharge = loanCharge;
|
||||||
chargePerInstallment = paidLoanChargePerInstallment;
|
chargePerInstallment = paidLoanChargePerInstallment;
|
||||||
}
|
}
|
||||||
} else if (latestPaidCharge == null || (loanCharge.isPaidOrPartiallyPaid(currency)
|
} else if (latestPaidCharge == null || (loanCharge.isPaidOrPartiallyPaid(currency)
|
||||||
&& loanCharge.getDueLocalDate().isAfter(latestPaidCharge.getDueLocalDate()))) {
|
&& DateUtils.isAfter(loanCharge.getDueLocalDate(), latestPaidCharge.getDueLocalDate()))) {
|
||||||
latestPaidCharge = loanCharge;
|
latestPaidCharge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (latestPaidCharge == null || (chargePerInstallment != null
|
if (latestPaidCharge == null || (chargePerInstallment != null
|
||||||
&& latestPaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
&& DateUtils.isAfter(latestPaidCharge.getDueLocalDate(), chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||||
latestPaidCharge = installemntCharge;
|
latestPaidCharge = installemntCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -194,7 +194,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
switch (paymentAllocationType.getDueType()) {
|
switch (paymentAllocationType.getDueType()) {
|
||||||
case PAST_DUE -> {
|
case PAST_DUE -> {
|
||||||
currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||||
.filter(e -> loanTransaction.getTransactionDate().isAfter(e.getDueDate()))
|
.filter(e -> loanTransaction.isAfter(e.getDueDate()))
|
||||||
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null);
|
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null);
|
||||||
if (currentInstallment != null) {
|
if (currentInstallment != null) {
|
||||||
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
||||||
@@ -206,7 +206,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
}
|
}
|
||||||
case DUE -> {
|
case DUE -> {
|
||||||
currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
currentInstallment = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||||
.filter(e -> loanTransaction.getTransactionDate().isEqual(e.getDueDate()))
|
.filter(e -> loanTransaction.isOn(e.getDueDate()))
|
||||||
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null);
|
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null);
|
||||||
if (currentInstallment != null) {
|
if (currentInstallment != null) {
|
||||||
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
||||||
@@ -222,14 +222,14 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
List<LoanRepaymentScheduleInstallment> currentInstallments = new ArrayList<>();
|
List<LoanRepaymentScheduleInstallment> currentInstallments = new ArrayList<>();
|
||||||
if (FutureInstallmentAllocationRule.REAMORTIZATION.equals(futureInstallmentAllocationRule)) {
|
if (FutureInstallmentAllocationRule.REAMORTIZATION.equals(futureInstallmentAllocationRule)) {
|
||||||
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||||
.filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate())).toList();
|
.filter(e -> loanTransaction.isBefore(e.getDueDate())).toList();
|
||||||
} else if (FutureInstallmentAllocationRule.NEXT_INSTALLMENT.equals(futureInstallmentAllocationRule)) {
|
} else if (FutureInstallmentAllocationRule.NEXT_INSTALLMENT.equals(futureInstallmentAllocationRule)) {
|
||||||
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||||
.filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate()))
|
.filter(e -> loanTransaction.isBefore(e.getDueDate()))
|
||||||
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList();
|
.min(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList();
|
||||||
} else if (FutureInstallmentAllocationRule.LAST_INSTALLMENT.equals(futureInstallmentAllocationRule)) {
|
} else if (FutureInstallmentAllocationRule.LAST_INSTALLMENT.equals(futureInstallmentAllocationRule)) {
|
||||||
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
currentInstallments = installments.stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||||
.filter(e -> loanTransaction.getTransactionDate().isBefore(e.getDueDate()))
|
.filter(e -> loanTransaction.isBefore(e.getDueDate()))
|
||||||
.max(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList();
|
.max(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).stream().toList();
|
||||||
}
|
}
|
||||||
int numberOfInstallments = currentInstallments.size();
|
int numberOfInstallments = currentInstallments.size();
|
||||||
|
|||||||
+3
-2
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
@@ -102,7 +103,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio
|
|||||||
|
|
||||||
List<LoanCharge> orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending)
|
List<LoanCharge> orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending)
|
||||||
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
||||||
|| !loanCharge.getEffectiveDueDate().isAfter(transactionDate))
|
|| !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate))
|
||||||
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
||||||
Money calculatedPenaltyCharge = Money.zero(currency);
|
Money calculatedPenaltyCharge = Money.zero(currency);
|
||||||
Money calculatedFeeCharge = Money.zero(currency);
|
Money calculatedFeeCharge = Money.zero(currency);
|
||||||
@@ -141,7 +142,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio
|
|||||||
feeChargesPortion = feeChargesPortion.add(subFeePortion);
|
feeChargesPortion = feeChargesPortion.add(subFeePortion);
|
||||||
|
|
||||||
Money subInterestPortion;
|
Money subInterestPortion;
|
||||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) {
|
||||||
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion);
|
||||||
interestPortion = interestPortion.add(subInterestPortion);
|
interestPortion = interestPortion.add(subInterestPortion);
|
||||||
|
|||||||
+3
-4
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
@@ -102,7 +103,7 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio
|
|||||||
|
|
||||||
List<LoanCharge> orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending)
|
List<LoanCharge> orderedLoanChargesByDueDate = charges.stream().filter(LoanCharge::isActive).filter(LoanCharge::isChargePending)
|
||||||
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
||||||
|| !loanCharge.getEffectiveDueDate().isAfter(transactionDate))
|
|| !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate))
|
||||||
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
||||||
Money calculatedPenaltyCharge = Money.zero(currency);
|
Money calculatedPenaltyCharge = Money.zero(currency);
|
||||||
Money calculatedFeeCharge = Money.zero(currency);
|
Money calculatedFeeCharge = Money.zero(currency);
|
||||||
@@ -129,13 +130,11 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio
|
|||||||
penaltyChargesPortion = penaltyChargesPortion.add(subPenaltyPortion);
|
penaltyChargesPortion = penaltyChargesPortion.add(subPenaltyPortion);
|
||||||
|
|
||||||
Money subInterestPortion;
|
Money subInterestPortion;
|
||||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) {
|
||||||
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion);
|
||||||
interestPortion = interestPortion.add(subInterestPortion);
|
interestPortion = interestPortion.add(subInterestPortion);
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
|
||||||
Money subPrincipalPortion = currentInstallment.payPrincipalComponent(transactionDate, transactionAmountRemaining);
|
Money subPrincipalPortion = currentInstallment.payPrincipalComponent(transactionDate, transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(subPrincipalPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(subPrincipalPortion);
|
||||||
principalPortion = principalPortion.add(subPrincipalPortion);
|
principalPortion = principalPortion.add(subPrincipalPortion);
|
||||||
|
|||||||
+2
-3
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
@@ -85,9 +86,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
|
|||||||
final LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex);
|
final LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex);
|
||||||
lastInstallmentDueDate = previousInstallment.getDueDate();
|
lastInstallmentDueDate = previousInstallment.getDueDate();
|
||||||
|
|
||||||
isInAdvance = !(transactionDate.isAfter(lastInstallmentDueDate) || transactionDate.isEqual(lastInstallmentDueDate));
|
return DateUtils.isBefore(transactionDate, lastInstallmentDueDate);
|
||||||
|
|
||||||
return isInAdvance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+4
-5
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
@@ -174,14 +175,12 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
|
|||||||
|
|
||||||
private LoanRepaymentScheduleInstallment nearestInstallment(final LocalDate transactionDate,
|
private LoanRepaymentScheduleInstallment nearestInstallment(final LocalDate transactionDate,
|
||||||
final List<LoanRepaymentScheduleInstallment> installments) {
|
final List<LoanRepaymentScheduleInstallment> installments) {
|
||||||
|
LoanRepaymentScheduleInstallment nearest = installments.get(0); // installments must be sorted by dates
|
||||||
LoanRepaymentScheduleInstallment nearest = installments.get(0);
|
|
||||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
if (installment.getDueDate().isBefore(transactionDate) || installment.getDueDate().isEqual(transactionDate)) {
|
if (DateUtils.isBefore(transactionDate, installment.getDueDate())) {
|
||||||
nearest = installment;
|
|
||||||
} else if (installment.getDueDate().isAfter(transactionDate)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
nearest = installment;
|
||||||
}
|
}
|
||||||
return nearest;
|
return nearest;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -327,7 +327,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
|||||||
if (loan.isApproved() && !loan.isDisbursed()) {
|
if (loan.isApproved() && !loan.isDisbursed()) {
|
||||||
final List<SavingsAccountTransaction> transactions = new ArrayList<>();
|
final List<SavingsAccountTransaction> transactions = new ArrayList<>();
|
||||||
for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) {
|
for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) {
|
||||||
if (!transaction.getTransactionDate().isAfter(loan.getApprovedOnDate())) {
|
if (!DateUtils.isAfter(transaction.getTransactionDate(), loan.getApprovedOnDate())) {
|
||||||
transactions.add(transaction);
|
transactions.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -187,7 +187,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
|||||||
|
|
||||||
private void validateGuarantorSavingsAccountActivationDateWithLoanSubmittedOnDate(final Loan loan,
|
private void validateGuarantorSavingsAccountActivationDateWithLoanSubmittedOnDate(final Loan loan,
|
||||||
final SavingsAccount savingsAccount) {
|
final SavingsAccount savingsAccount) {
|
||||||
if (loan.getSubmittedOnDate().isBefore(savingsAccount.getActivationDate())) {
|
if (DateUtils.isBefore(loan.getSubmittedOnDate(), savingsAccount.getActivationDate())) {
|
||||||
throw new GeneralPlatformDomainRuleException(
|
throw new GeneralPlatformDomainRuleException(
|
||||||
"error.msg.guarantor.saving.account.activation.date.is.on.or.before.loan.submitted.on.date",
|
"error.msg.guarantor.saving.account.activation.date.is.on.or.before.loan.submitted.on.date",
|
||||||
"Guarantor saving account activation date [" + savingsAccount.getActivationDate()
|
"Guarantor saving account activation date [" + savingsAccount.getActivationDate()
|
||||||
|
|||||||
+7
-7
@@ -27,6 +27,7 @@ import java.util.Set;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueHolidayBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueHolidayBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||||
@@ -120,16 +121,15 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
|||||||
// Loop through all loanRepayments
|
// Loop through all loanRepayments
|
||||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
||||||
|
|
||||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
|
|
||||||
// update from date if it's not same as previous installment's due
|
// update from date if it's not same as previous installment's due
|
||||||
// date.
|
// date.
|
||||||
if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) {
|
if (!DateUtils.isEqual(tmpFromDate, loanRepaymentScheduleInstallment.getFromDate())) {
|
||||||
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldDueDate.equals(holiday.getFromDate()) || oldDueDate.isAfter(holiday.getFromDate())) {
|
if (!DateUtils.isBefore(oldDueDate, holiday.getFromDate())) {
|
||||||
// FIXME: AA do we need to apply non-working days.
|
// FIXME: AA do we need to apply non-working days.
|
||||||
// Assuming holiday's repayment reschedule to date cannot be
|
// Assuming holiday's repayment reschedule to date cannot be
|
||||||
// created on a non-working day.
|
// created on a non-working day.
|
||||||
@@ -146,7 +146,7 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
|||||||
LocalDate adjustedRescheduleToDate = null;
|
LocalDate adjustedRescheduleToDate = null;
|
||||||
final LocalDate rescheduleToDate = holiday.getToDate();
|
final LocalDate rescheduleToDate = holiday.getToDate();
|
||||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : loan.getRepaymentScheduleInstallments()) {
|
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : loan.getRepaymentScheduleInstallments()) {
|
||||||
if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
|
if (DateUtils.isEqual(rescheduleToDate, loanRepaymentScheduleInstallment.getDueDate())) {
|
||||||
adjustedRescheduleToDate = rescheduleToDate;
|
adjustedRescheduleToDate = rescheduleToDate;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -160,9 +160,9 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
|||||||
private LocalDate doStandardMonthlyCheck(LocalDate adjustedRescheduleToDate, LocalDate rescheduleToDate,
|
private LocalDate doStandardMonthlyCheck(LocalDate adjustedRescheduleToDate, LocalDate rescheduleToDate,
|
||||||
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||||
// Standard Monthly Loan Holiday check
|
// Standard Monthly Loan Holiday check
|
||||||
if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
LocalDate dueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
&& rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) {
|
if (DateUtils.isAfter(rescheduleToDate, dueDate) && DateUtils.isBefore(rescheduleToDate, dueDate.plusDays(30))) {
|
||||||
adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
adjustedRescheduleToDate = dueDate;
|
||||||
}
|
}
|
||||||
return adjustedRescheduleToDate;
|
return adjustedRescheduleToDate;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user