FINERACT-1983: Date handling improvements - general
This commit is contained in:
+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.infrastructure.core.data.EnumOptionData;
|
||||
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.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
@@ -502,12 +503,9 @@ public class AccountingProcessorHelper {
|
||||
* @param 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.getClosingDate().isAfter(transactionDate)
|
||||
|| latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
||||
if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) {
|
||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
||||
null, null);
|
||||
}
|
||||
|
||||
+2
-3
@@ -175,8 +175,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
|
||||
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
||||
|
||||
params.add(new Object[] { Boolean.TRUE, runningBalance, officeRunningBalance,
|
||||
platformSecurityContext.authenticatedUser().getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
|
||||
entryData.getId() });
|
||||
platformSecurityContext.authenticatedUser().getId(), DateUtils.getAuditOffsetDateTime(), entryData.getId() });
|
||||
batchIndex++;
|
||||
if (batchIndex == batchUpdateSize || index == entryDataList.size() - 1) {
|
||||
this.jdbcTemplate.batchUpdate(sql, params);
|
||||
@@ -213,7 +212,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
|
||||
for (JournalEntryData entryData : entryDataList) {
|
||||
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
||||
params.add(new Object[] { runningBalance, platformSecurityContext.authenticatedUser().getId(),
|
||||
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), entryData.getId() });
|
||||
DateUtils.getAuditOffsetDateTime(), entryData.getId() });
|
||||
}
|
||||
this.jdbcTemplate.batchUpdate(sql, params);
|
||||
}
|
||||
|
||||
+5
-9
@@ -314,9 +314,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
final LocalDate journalEntriesTransactionDate = journalEntries.get(0).getTransactionDate();
|
||||
final GLClosure latestGLClosureByBranch = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
|
||||
if (latestGLClosureByBranch != null) {
|
||||
if (latestGLClosureByBranch.getClosingDate().isAfter(journalEntriesTransactionDate)
|
||||
|| latestGLClosureByBranch.getClosingDate().compareTo(journalEntriesTransactionDate) == 0 ? Boolean.TRUE
|
||||
: Boolean.FALSE) {
|
||||
if (!DateUtils.isBefore(latestGLClosureByBranch.getClosingDate(), journalEntriesTransactionDate)) {
|
||||
final String accountName = null;
|
||||
final String accountGLCode = null;
|
||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED,
|
||||
@@ -555,24 +553,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
}
|
||||
|
||||
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();
|
||||
// shouldn't be in the future
|
||||
final LocalDate todaysDate = DateUtils.getBusinessLocalDate();
|
||||
if (transactionDate.isAfter(todaysDate)) {
|
||||
if (DateUtils.isDateInTheFuture(transactionDate)) {
|
||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.FUTURE_DATE, transactionDate, null, null);
|
||||
}
|
||||
// shouldn't be before an accounting closure
|
||||
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(command.getOfficeId());
|
||||
if (latestGLClosure != null) {
|
||||
if (latestGLClosure.getClosingDate().isAfter(transactionDate)
|
||||
|| latestGLClosure.getClosingDate().compareTo(transactionDate) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
||||
if (!DateUtils.isBefore(latestGLClosure.getClosingDate(), transactionDate)) {
|
||||
throw new JournalEntryInvalidException(GlJournalEntryInvalidReason.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(),
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/*** check if credits and debits are valid **/
|
||||
// check if credits and debits are valid
|
||||
final SingleDebitOrCreditEntryCommand[] credits = command.getCredits();
|
||||
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.CommandProcessingResultBuilder;
|
||||
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.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
@@ -107,7 +108,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
|
||||
private void validateForCreateJournalEntry(ProvisioningEntryData existingEntry, ProvisioningEntry requested) {
|
||||
LocalDate existingDate = existingEntry.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class LoanAccountLock {
|
||||
public LoanAccountLock(Long loanId, LockOwner lockOwner, LocalDate lockPlacedOnCobBusinessDate) {
|
||||
this.loanId = loanId;
|
||||
this.lockOwner = lockOwner;
|
||||
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
||||
this.lockPlacedOn = DateUtils.getAuditOffsetDateTime();
|
||||
this.lockPlacedOnCobBusinessDate = lockPlacedOnCobBusinessDate;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,6 @@ public class LoanAccountLock {
|
||||
|
||||
public void setNewLockOwner(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();
|
||||
sw.start();
|
||||
List<LoanCOBPartition> loanCOBPartitions = new ArrayList<>(retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays,
|
||||
businessDate, isCatchUp != null ? isCatchUp : false, partitionSize));
|
||||
List<LoanCOBPartition> loanCOBPartitions = new ArrayList<>(
|
||||
retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, businessDate, isCatchUp != null && isCatchUp, partitionSize));
|
||||
sw.stop();
|
||||
// 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 = ?
|
||||
""", accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
|
||||
ps.setString(1, lockOwner.name());
|
||||
ps.setObject(2, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
||||
ps.setObject(2, DateUtils.getAuditOffsetDateTime());
|
||||
ps.setLong(3, id);
|
||||
});
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class LoanLockingServiceImpl implements LoanLockingService {
|
||||
ps.setLong(1, loanId);
|
||||
ps.setLong(2, 1);
|
||||
ps.setString(3, lockOwner.name());
|
||||
ps.setObject(4, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
||||
ps.setObject(4, DateUtils.getAuditOffsetDateTime());
|
||||
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.core.config.TaskExecutorConstant;
|
||||
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.jobs.data.JobParameterDTO;
|
||||
import org.apache.fineract.infrastructure.jobs.domain.JobParameterRepository;
|
||||
@@ -73,7 +74,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ
|
||||
LocalDate oldestCOBProcessedDate = !loanIdAndLastClosedBusinessDate.isEmpty()
|
||||
? loanIdAndLastClosedBusinessDate.get(0).getLastClosedBusinessDate()
|
||||
: cobBusinessDate;
|
||||
if (oldestCOBProcessedDate.isBefore(cobBusinessDate)) {
|
||||
if (DateUtils.isBefore(oldestCOBProcessedDate, cobBusinessDate)) {
|
||||
executeLoanCOBDayByDayUntilCOBBusinessDate(oldestCOBProcessedDate, cobBusinessDate);
|
||||
}
|
||||
} catch (NoSuchJobException e) {
|
||||
@@ -92,7 +93,7 @@ public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorServ
|
||||
Job job = jobLocator.getJob(LoanCOBConstant.JOB_NAME);
|
||||
ScheduledJobDetail scheduledJobDetail = scheduledJobDetailRepository.findByJobName(LoanCOBConstant.JOB_HUMAN_READABLE_NAME);
|
||||
LocalDate executingBusinessDate = oldestCOBProcessedDate.plusDays(1);
|
||||
while (!executingBusinessDate.isAfter(cobBusinessDate)) {
|
||||
while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) {
|
||||
JobParameterDTO jobParameterDTO = new JobParameterDTO(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME,
|
||||
executingBusinessDate.format(DateTimeFormatter.ISO_DATE));
|
||||
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.PlatformRequestBodyItemLimitValidationException;
|
||||
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.jobs.data.JobParameterDTO;
|
||||
import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository;
|
||||
@@ -112,7 +113,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
|
||||
List<LoanIdAndLastClosedBusinessDate> loansToBeProcessed = getLoansToBeProcessed(loanIds, cobBusinessDate);
|
||||
LocalDate executingBusinessDate = getOldestCOBBusinessDate(loansToBeProcessed).plusDays(1);
|
||||
if (!loansToBeProcessed.isEmpty()) {
|
||||
while (!executingBusinessDate.isAfter(cobBusinessDate)) {
|
||||
while (!DateUtils.isAfter(executingBusinessDate, cobBusinessDate)) {
|
||||
execute(getLoanIdsToBeProcessed(loansToBeProcessed, executingBusinessDate), jobName, executingBusinessDate);
|
||||
executingBusinessDate = executingBusinessDate.plusDays(1);
|
||||
}
|
||||
@@ -123,7 +124,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
|
||||
List<Long> loanIdsToBeProcessed = new ArrayList<>();
|
||||
loansToBeProcessed.forEach(loan -> {
|
||||
if (loan.getLastClosedBusinessDate() != null) {
|
||||
if (loan.getLastClosedBusinessDate().isBefore(executingBusinessDate)) {
|
||||
if (DateUtils.isBefore(loan.getLastClosedBusinessDate(), executingBusinessDate)) {
|
||||
loanIdsToBeProcessed.add(loan.getId());
|
||||
}
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class ImportDocument extends AbstractPersistableCustom {
|
||||
final Boolean completed = Boolean.FALSE;
|
||||
final Integer successCount = 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,
|
||||
failureCount);
|
||||
|
||||
+1
-2
@@ -145,8 +145,7 @@ public final class ImportHandlerUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalDate localDate = LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
return localDate;
|
||||
return LocalDate.ofInstant(c.getDateCellValue().toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
}
|
||||
|
||||
public static Boolean readAsBoolean(int colIndex, Row row) {
|
||||
|
||||
+1
-2
@@ -101,8 +101,7 @@ public class SharedProductsSheetPopulator extends AbstractWorkbookPopulator {
|
||||
if (marketDataSet != null && !marketDataSet.isEmpty()) {
|
||||
LocalDate currentDate = DateUtils.getBusinessLocalDate();
|
||||
for (ShareProductMarketPriceData data : marketDataSet) {
|
||||
LocalDate futureDate = data.getFromDate();
|
||||
if (currentDate.isAfter(futureDate)) {
|
||||
if (DateUtils.isBefore(data.getFromDate(), currentDate)) {
|
||||
marketValue = data.getShareValue();
|
||||
}
|
||||
}
|
||||
|
||||
+9
-27
@@ -160,7 +160,7 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
||||
final Locale locale = command.extractLocale();
|
||||
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 (command.hasParameter(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) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
|
||||
|
||||
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) {
|
||||
|
||||
if (isActive()) {
|
||||
// handle errors if already activated
|
||||
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) {
|
||||
|
||||
if (!isClosed()) {
|
||||
// handle errors if already activated
|
||||
final String defaultUserMessage = "Cannot reactivate campaign. Campaign must be in closed state.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.must.be.closed", defaultUserMessage,
|
||||
EmailCampaignValidator.statusParamName, EmailCampaignStatus.fromInt(this.status).getCode());
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
@@ -352,55 +349,45 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
||||
|
||||
if (getSubmittedOnDate() != null && DateUtils.isDateInTheFuture(getSubmittedOnDate())) {
|
||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
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 ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (getApprovedOnDate() != null && isDateInTheFuture(getApprovedOnDate())) {
|
||||
|
||||
if (DateUtils.isDateInTheFuture(getApprovedOnDate())) {
|
||||
final String defaultUserMessage = "Activation date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
||||
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.activationDate.in.the.future",
|
||||
defaultUserMessage, EmailCampaignValidator.activationDateParamName, getApprovedOnDate());
|
||||
|
||||
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 ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.after.activation.date",
|
||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
||||
|
||||
if (DateUtils.isDateInTheFuture(getSubmittedOnDate())) {
|
||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.submittedOnDate.in.the.future",
|
||||
defaultUserMessage, EmailCampaignValidator.submittedOnDateParamName, this.submittedOnDate);
|
||||
@@ -411,7 +398,7 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
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 ApiParameterError error = ApiParameterError.parameterError("error.msg.campaign.closureDate.in.the.future",
|
||||
defaultUserMessage, EmailCampaignValidator.closureDateParamName, this.closureDate);
|
||||
@@ -419,9 +406,4 @@ public class EmailCampaign extends AbstractPersistableCustom {
|
||||
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.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
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.data.CommandProcessingResult;
|
||||
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.serialization.FromJsonHelper;
|
||||
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.domain.Report;
|
||||
import org.apache.fineract.infrastructure.dataqueries.domain.ReportParameterUsage;
|
||||
@@ -98,7 +95,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult create(JsonCommand command) {
|
||||
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
|
||||
this.emailCampaignValidator.validateCreate(command.json());
|
||||
@@ -286,24 +282,21 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
||||
if (emailCampaign.isDirect()) {
|
||||
insertDirectCampaignIntoEmailOutboundTable(emailCampaign.getParamValue(), emailCampaign.getEmailSubject(),
|
||||
emailCampaign.getEmailMessage(), emailCampaign.getCampaignName(), emailCampaign.getId());
|
||||
} else {
|
||||
if (emailCampaign.isSchedule()) {
|
||||
|
||||
/**
|
||||
* 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 nextTriggerDateWithTime;
|
||||
if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) {
|
||||
nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(),
|
||||
emailCampaign.getRecurrenceStartDate(), DateUtils.getLocalDateTimeOfTenant());
|
||||
} else {
|
||||
nextTriggerDateWithTime = emailCampaign.getRecurrenceStartDate();
|
||||
}
|
||||
|
||||
emailCampaign.setNextTriggerDate(nextTriggerDateWithTime);
|
||||
this.emailCampaignRepository.saveAndFlush(emailCampaign);
|
||||
} else 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;
|
||||
LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate();
|
||||
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) {
|
||||
nextTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate,
|
||||
tenantDateTime);
|
||||
} else {
|
||||
nextTriggerDateWithTime = recurrenceStartDate;
|
||||
}
|
||||
|
||||
emailCampaign.setNextTriggerDate(nextTriggerDateWithTime);
|
||||
this.emailCampaignRepository.saveAndFlush(emailCampaign);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -420,7 +413,6 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult reactivateEmailCampaign(final Long campaignId, JsonCommand command) {
|
||||
|
||||
this.emailCampaignValidator.validateActivation(command.json());
|
||||
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
@@ -433,23 +425,18 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
|
||||
final LocalDate reactivationDate = command.localDateValueOfParameterNamed("activationDate");
|
||||
emailCampaign.reactivate(currentUser, fmt, reactivationDate);
|
||||
if (emailCampaign.isSchedule()) {
|
||||
|
||||
/**
|
||||
* if recurrence start date is in the future calculate next trigger date if not use recurrence start date us
|
||||
* next trigger date when activating
|
||||
*/
|
||||
// if recurrence start date is in the past, calculate next trigger date, otherwise use recurrence start date
|
||||
// as next trigger date when activating
|
||||
LocalDateTime nextTriggerDate = null;
|
||||
if (emailCampaign.getRecurrenceStartDate().isBefore(tenantDateTime())) {
|
||||
nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getRecurrenceStartDate(),
|
||||
DateUtils.getLocalDateTimeOfTenant());
|
||||
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
LocalDateTime recurrenceStartDate = emailCampaign.getRecurrenceStartDate();
|
||||
if (DateUtils.isBefore(recurrenceStartDate, tenantDateTime)) {
|
||||
nextTriggerDate = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), recurrenceStartDate, tenantDateTime);
|
||||
} else {
|
||||
nextTriggerDate = emailCampaign.getRecurrenceStartDate();
|
||||
nextTriggerDate = recurrenceStartDate;
|
||||
}
|
||||
// to get time of tenant
|
||||
final LocalDateTime getTime = emailCampaign.getRecurrenceStartDate();
|
||||
|
||||
final String dateString = nextTriggerDate.toString() + " " + getTime.getHour() + ":" + getTime.getMinute() + ":"
|
||||
+ getTime.getSecond();
|
||||
final String dateString = nextTriggerDate.toString() + " " + recurrenceStartDate.getHour() + ":"
|
||||
+ recurrenceStartDate.getMinute() + ":" + recurrenceStartDate.getSecond();
|
||||
final DateTimeFormatter simpleDateFormat = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient()
|
||||
.appendPattern("yyyy-MM-dd HH:mm:ss").toFormatter();
|
||||
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",
|
||||
"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 nextRunDateTime = reportMailingJob.getNextRunDateTime();
|
||||
|
||||
if (nextRunDateTime != null && nextRunDateTime.isBefore(localDateTimeOftenant)) {
|
||||
if (nextRunDateTime != null && DateUtils.isBefore(nextRunDateTime, localDateTimeOftenant)) {
|
||||
final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat
|
||||
.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.service.EmailCampaignReadPlatformService;
|
||||
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.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
@@ -69,11 +68,11 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet {
|
||||
.retrieveAllScheduleActiveCampaign();
|
||||
if (emailCampaignDataCollection != null) {
|
||||
for (EmailCampaignData emailCampaignData : emailCampaignDataCollection) {
|
||||
LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime();
|
||||
LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant();
|
||||
LocalDateTime nextTriggerDate = emailCampaignData.getNextTriggerDate().toLocalDateTime();
|
||||
|
||||
log.debug("tenant time {} trigger time {}", tenantDateNow, nextTriggerDate);
|
||||
if (nextTriggerDate.isBefore(tenantDateNow)) {
|
||||
if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) {
|
||||
insertDirectCampaignIntoEmailOutboundTable(emailCampaignData.getParamValue(), emailCampaignData.getEmailSubject(),
|
||||
emailCampaignData.getEmailMessage(), emailCampaignData.getCampaignName(), emailCampaignData.getId());
|
||||
updateTriggerDates(emailCampaignData.getId());
|
||||
@@ -115,13 +114,12 @@ public class UpdateEmailOutboundWithCampaignMessageTasklet implements Tasklet {
|
||||
.orElseThrow(() -> new EmailCampaignNotFound(campaignId));
|
||||
LocalDateTime nextTriggerDate = emailCampaign.getNextTriggerDate();
|
||||
emailCampaign.setLastTriggerDate(nextTriggerDate);
|
||||
LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(),
|
||||
emailCampaign.getNextTriggerDate(), nextTriggerDate);
|
||||
if (newTriggerDateWithTime.isBefore(DateUtils.getLocalDateTimeOfTenant())) {
|
||||
newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), emailCampaign.getNextTriggerDate(),
|
||||
DateUtils.getLocalDateTimeOfTenant());
|
||||
LocalDateTime newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate,
|
||||
nextTriggerDate);
|
||||
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
if (DateUtils.isBefore(newTriggerDateWithTime, tenantDateTime)) {
|
||||
newTriggerDateWithTime = CalendarUtils.getNextRecurringDate(emailCampaign.getRecurrence(), nextTriggerDate, tenantDateTime);
|
||||
}
|
||||
|
||||
emailCampaign.setNextTriggerDate(newTriggerDateWithTime);
|
||||
emailCampaignRepository.saveAndFlush(emailCampaign);
|
||||
}
|
||||
|
||||
+6
-8
@@ -23,7 +23,6 @@ import java.util.Collection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.SmsCampaignTriggerType;
|
||||
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());
|
||||
if (!CollectionUtils.isEmpty(smsCampaignDataCollection)) {
|
||||
for (SmsCampaign smsCampaign : smsCampaignDataCollection) {
|
||||
LocalDateTime tenantDateNow = TenantDateTimeUtil.tenantDateTime();
|
||||
LocalDateTime tenantDateNow = DateUtils.getLocalDateTimeOfTenant();
|
||||
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
||||
|
||||
log.debug("tenant time {} trigger time {} {}", tenantDateNow, nextTriggerDate,
|
||||
JobName.UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE.name());
|
||||
if (nextTriggerDate.isBefore(tenantDateNow)) {
|
||||
if (DateUtils.isBefore(nextTriggerDate, tenantDateNow)) {
|
||||
smsCampaignWritePlatformService.insertDirectCampaignIntoSmsOutboundTable(smsCampaign);
|
||||
updateTriggerDates(smsCampaign.getId());
|
||||
}
|
||||
@@ -70,11 +69,10 @@ public class UpdateSmsOutboundWithCampaignMessageTasklet implements Tasklet {
|
||||
.orElseThrow(() -> new SmsCampaignNotFound(campaignId));
|
||||
LocalDateTime nextTriggerDate = smsCampaign.getNextTriggerDate();
|
||||
smsCampaign.setLastTriggerDate(nextTriggerDate);
|
||||
LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(),
|
||||
nextTriggerDate);
|
||||
if (nextRuntime.isBefore(DateUtils.getLocalDateTimeOfTenant())) {
|
||||
nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), smsCampaign.getNextTriggerDate(),
|
||||
DateUtils.getLocalDateTimeOfTenant());
|
||||
LocalDateTime nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, nextTriggerDate);
|
||||
LocalDateTime tenantDateTime = DateUtils.getLocalDateTimeOfTenant();
|
||||
if (DateUtils.isBefore(nextRuntime, tenantDateTime)) {
|
||||
nextRuntime = CalendarUtils.getNextRecurringDate(smsCampaign.getRecurrence(), nextTriggerDate, tenantDateTime);
|
||||
}
|
||||
|
||||
smsCampaign.setNextTriggerDate(nextRuntime);
|
||||
|
||||
+3
-6
@@ -18,10 +18,10 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.domain;
|
||||
|
||||
import static org.apache.fineract.useradministration.service.AppUserConstants.ADMIN_USER_ID;
|
||||
|
||||
import java.util.Optional;
|
||||
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.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
@@ -29,9 +29,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class AuditorAwareImpl implements AuditorAware<Long> {
|
||||
|
||||
@Autowired
|
||||
private AppUserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public Optional<Long> getCurrentAuditor() {
|
||||
Optional<Long> currentUserId;
|
||||
@@ -50,6 +47,6 @@ public class AuditorAwareImpl implements AuditorAware<Long> {
|
||||
}
|
||||
|
||||
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 getExpiryDate = creditBureauToken.getExpires();
|
||||
|
||||
if (getExpiryDate.isBefore(current)) {
|
||||
if (DateUtils.isBefore(getExpiryDate, current)) {
|
||||
this.tokenRepositoryWrapper.delete(creditBureauToken);
|
||||
creditBureauToken = null;
|
||||
}
|
||||
|
||||
+3
-5
@@ -33,6 +33,7 @@ import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
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.exception.FineractEntityToEntityMappingDateException;
|
||||
|
||||
@@ -69,7 +70,6 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public Map<String, Object> updateMap(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
if (command.isChangeInLongParameterNamed(FineractEntityApiResourceConstants.fromEnityType, this.fromId)) {
|
||||
@@ -95,10 +95,8 @@ public class FineractEntityToEntityMapping extends AbstractPersistableCustom {
|
||||
actualChanges.put(FineractEntityApiResourceConstants.endDate, valueAsInput);
|
||||
this.endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
||||
}
|
||||
if (startDate != null && endDate != null) {
|
||||
if (endDate.isBefore(startDate)) {
|
||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||
}
|
||||
if (endDate != null && DateUtils.isBefore(endDate, startDate)) {
|
||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||
}
|
||||
|
||||
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.CommandProcessingResultBuilder;
|
||||
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.data.FineractEntityDataValidator;
|
||||
import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccess;
|
||||
@@ -86,9 +87,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult createEntityToEntityMapping(Long relId, JsonCommand command) {
|
||||
|
||||
try {
|
||||
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
final FineractEntityRelation mapId = this.fineractEntityRelationRepositoryWrapper.findOneWithNotFoundDetection(relId);
|
||||
@@ -99,10 +98,8 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
||||
final LocalDate endDate = command.localDateValueOfParameterNamed(FineractEntityApiResourceConstants.endDate);
|
||||
|
||||
fromApiJsonDeserializer.checkForEntity(relId.toString(), fromId, toId);
|
||||
if (startDate != null && endDate != null) {
|
||||
if (endDate.isBefore(startDate)) {
|
||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||
}
|
||||
if (endDate != null && DateUtils.isBefore(endDate, startDate)) {
|
||||
throw new FineractEntityToEntityMappingDateException(startDate.toString(), endDate.toString());
|
||||
}
|
||||
|
||||
final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate);
|
||||
@@ -123,9 +120,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult updateEntityToEntityMapping(Long mapId, JsonCommand command) {
|
||||
|
||||
try {
|
||||
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
|
||||
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 ")
|
||||
.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);
|
||||
|
||||
@@ -82,8 +82,7 @@ public class UpdateNpaTasklet implements Tasklet {
|
||||
.append(fromPart).append(wherePart);
|
||||
}
|
||||
|
||||
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(),
|
||||
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
|
||||
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(), DateUtils.getAuditOffsetDateTime());
|
||||
|
||||
log.debug("{}: Records affected by updateNPA: {}", ThreadLocalContextUtil.getTenant().getName(), result);
|
||||
return RepeatStatus.FINISHED;
|
||||
|
||||
+2
-9
@@ -67,19 +67,12 @@ public class TFAccessToken extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
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() {
|
||||
return new AccessTokenData().setToken(this.token).setValidFrom(getValidFrom().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);
|
||||
|
||||
if (DateUtils.getLocalDateOfTenant().isAfter(passwordExpirationDate)) {
|
||||
if (DateUtils.isBeforeTenantDate(passwordExpirationDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
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.SavingsAccountTransaction;
|
||||
|
||||
@@ -41,7 +42,7 @@ public class InteropTransactionsData extends CommandProcessingResult {
|
||||
}
|
||||
|
||||
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());
|
||||
}).map(InteropTransactionData::build).collect(Collectors.toList());
|
||||
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.exception.PlatformDataIntegrityException;
|
||||
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.organisation.holiday.api.HolidayApiConstants;
|
||||
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) {
|
||||
|
||||
String defaultUserMessage = "";
|
||||
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
if (DateUtils.isBefore(toDate, fromDate)) {
|
||||
defaultUserMessage = "To Date date cannot be before the From Date.";
|
||||
throw new HolidayDateException("to.date.cannot.be.before.from.date", defaultUserMessage, fromDate.toString(),
|
||||
toDate.toString());
|
||||
}
|
||||
if (repaymentsRescheduledTo != null) {
|
||||
if ((repaymentsRescheduledTo.isEqual(fromDate) || repaymentsRescheduledTo.isEqual(toDate)
|
||||
|| (repaymentsRescheduledTo.isAfter(fromDate) && repaymentsRescheduledTo.isBefore(toDate)))) {
|
||||
|
||||
if (!DateUtils.isBefore(repaymentsRescheduledTo, fromDate) && !DateUtils.isAfter(repaymentsRescheduledTo, toDate)) {
|
||||
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",
|
||||
defaultUserMessage, repaymentsRescheduledTo.toString());
|
||||
@@ -235,13 +233,12 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
|
||||
// validate repaymentsRescheduledTo date
|
||||
// 1. should be within a 30 days date range.
|
||||
// 2. Alternative date should not be an exist holiday.//TBD
|
||||
// 3. Holiday should not be on an repaymentsRescheduledTo date of
|
||||
// another holiday.//TBD
|
||||
// 3. Holiday should not be on an repaymentsRescheduledTo date of another holiday.//TBD
|
||||
|
||||
// restricting repaymentsRescheduledTo date to be within 30 days
|
||||
// range
|
||||
// before or after from date and to date.
|
||||
if (repaymentsRescheduledTo.isBefore(fromDate.minusDays(30)) || repaymentsRescheduledTo.isAfter(toDate.plusDays(30))) {
|
||||
// restricting repaymentsRescheduledTo date to be within 30 days range before or after from date and to
|
||||
// date.
|
||||
if (DateUtils.isBefore(repaymentsRescheduledTo, fromDate.minusDays(30))
|
||||
|| DateUtils.isAfter(repaymentsRescheduledTo, toDate.plusDays(30))) {
|
||||
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(),
|
||||
toDate.toString(), repaymentsRescheduledTo.toString());
|
||||
|
||||
+15
-21
@@ -20,10 +20,10 @@ package org.apache.fineract.organisation.teller.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
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.organisation.teller.domain.Cashier;
|
||||
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) {
|
||||
|
||||
final Integer offset = null;
|
||||
final Integer limit = null;
|
||||
final String orderBy = null;
|
||||
@@ -64,7 +63,7 @@ public class CashierTransactionDataValidator {
|
||||
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
|
||||
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.tellerManagementReadPlatformService
|
||||
.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();
|
||||
}
|
||||
}
|
||||
@@ -81,16 +80,12 @@ public class CashierTransactionDataValidator {
|
||||
final LocalDate endDate = cashier.getEndDate();
|
||||
final LocalDate tellerFromDate = teller.getStartDate();
|
||||
final LocalDate tellerEndDate = teller.getEndDate();
|
||||
/**
|
||||
* to validate cashier date range in range of teller date range
|
||||
*/
|
||||
if (fromDate.isBefore(tellerFromDate) || endDate.isBefore(tellerFromDate)
|
||||
|| (tellerEndDate != null && (fromDate.isAfter(tellerEndDate) || endDate.isAfter(tellerEndDate)))) {
|
||||
// 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)))) {
|
||||
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
|
||||
+ "' 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 '"
|
||||
@@ -98,8 +93,8 @@ public class CashierTransactionDataValidator {
|
||||
if (!cashier.getIsFullDay()) {
|
||||
String startTime = cashier.getStartTime();
|
||||
String endTime = cashier.getEndTime();
|
||||
sql = sql + " AND ( Time(c.start_time) BETWEEN TIME(?) and TIME('" + endTime + "') or Time(c.end_time) BETWEEN TIME('"
|
||||
+ startTime + "') and TIME('" + endTime + "')) ";
|
||||
sql = sql + " AND ( Time(c.start_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime
|
||||
+ "') or Time(c.end_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime + "')) ";
|
||||
}
|
||||
int count = this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR
|
||||
if (count > 0) {
|
||||
@@ -108,13 +103,13 @@ public class CashierTransactionDataValidator {
|
||||
}
|
||||
|
||||
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) {
|
||||
String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND "
|
||||
+ " (case when c.full_day then '" + localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date " + " else ('"
|
||||
+ localDateTime.toLocalDate() + "' BETWEEN c.start_date AND c.end_date and " + " TIME('"
|
||||
+ ZonedDateTime.of(localDateTime, DateUtils.getDateTimeZoneOfTenant())
|
||||
+ "') BETWEEN TIME(c.start_time) AND TIME(c.end_time) ) end)";
|
||||
String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND (case when c.full_day then '"
|
||||
+ tenantDate + "' BETWEEN c.start_date AND c.end_date else ('" + tenantDate
|
||||
+ "' BETWEEN c.start_date AND c.end_date and TIME('" + tenantDateTime
|
||||
+ "') BETWEEN TIME(c.start_time) AND TIME(c.end_time)) end)";
|
||||
try {
|
||||
Long cashierId = this.jdbcTemplate.queryForObject(sql, Long.class); // NOSONAR
|
||||
validateSettleCashAndCashOutTransactions(cashierId, currencyCode, transactionAmount);
|
||||
@@ -122,6 +117,5 @@ public class CashierTransactionDataValidator {
|
||||
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.PlatformApiDataValidationException;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -113,7 +114,7 @@ public final class TellerCommandFromApiJsonDeserializer {
|
||||
final String status = this.fromApiJsonHelper.extractStringNamed(STATUS, element);
|
||||
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());
|
||||
}
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
+2
-2
@@ -75,12 +75,12 @@ public class ExecuteStandingInstructionsTasklet implements Tasklet {
|
||||
LocalDate startDate = data.validFrom();
|
||||
if (frequencyType.isMonthly()) {
|
||||
startDate = startDate.withDayOfMonth(data.recurrenceOnDay());
|
||||
if (startDate.isBefore(data.validFrom())) {
|
||||
if (DateUtils.isBefore(startDate, data.validFrom())) {
|
||||
startDate = startDate.plusMonths(1);
|
||||
}
|
||||
} else if (frequencyType.isYearly()) {
|
||||
startDate = startDate.withDayOfMonth(data.recurrenceOnDay()).withMonth(data.recurrenceOnMonth());
|
||||
if (startDate.isBefore(data.validFrom())) {
|
||||
if (DateUtils.isBefore(startDate, data.validFrom())) {
|
||||
startDate = startDate.plusYears(1);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -536,8 +536,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(fromLoanAccountId).getPaidInAdvance();
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
|
||||
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE
|
||||
: Boolean.FALSE || transactionAmount.floatValue() > overpaid.floatValue()) {
|
||||
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 || transactionAmount.floatValue() > overpaid.floatValue()) {
|
||||
if (overpaid == null) {
|
||||
overpaid = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
+3
-3
@@ -279,7 +279,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
periodStartDate = fromDate;
|
||||
} else {
|
||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||
if (seedDate.isBefore(currentDate.minusYears(1))) {
|
||||
if (DateUtils.isBefore(seedDate, currentDate.minusYears(1))) {
|
||||
periodStartDate = currentDate.minusYears(1);
|
||||
} else {
|
||||
periodStartDate = recurrenceStartDate;
|
||||
@@ -294,7 +294,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
|
||||
if (tillDate != null) {
|
||||
if (endDate != null) {
|
||||
if (endDate.isAfter(tillDate)) {
|
||||
if (DateUtils.isAfter(endDate, tillDate)) {
|
||||
// to retrieve meeting dates tillspecified date (tillDate)
|
||||
periodEndDate = tillDate;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
// end date is null then fetch meeting dates 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);
|
||||
}
|
||||
return periodEndDate;
|
||||
|
||||
+2
-2
@@ -80,8 +80,8 @@ public class InternalClientInformationApiResource implements InitializingBean {
|
||||
|
||||
final Client client = clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
|
||||
Map<String, Object> auditFields = new HashMap<>(
|
||||
Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
|
||||
client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDate().orElse(null)));
|
||||
Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDateTime(), LAST_MODIFIED_BY,
|
||||
client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDateTime()));
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
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.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
|
||||
|
||||
@Entity
|
||||
@@ -116,8 +117,7 @@ public class ClientNonPerson extends AbstractPersistableCustom {
|
||||
|
||||
private void validateIncorpValidityTillDate(final Client client, final List<ApiParameterError> dataValidationErrors) {
|
||||
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 ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.incorpValidityTill.after.incorp.date",
|
||||
defaultUserMessage, ClientApiConstants.incorpValidityTillParamName, this.incorpValidityTill);
|
||||
|
||||
+3
-3
@@ -99,9 +99,9 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME);
|
||||
LocalDate activationDate = client.getActivationLocalDate();
|
||||
LocalDate activationDate = client.getActivationDate();
|
||||
LocalDate dueDate = clientCharge.getDueLocalDate();
|
||||
if (dueDate.isBefore(activationDate)) {
|
||||
if (DateUtils.isBefore(dueDate, activationDate)) {
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.dueAsOfDateParamName).value(dueDate.format(fmt))
|
||||
.failWithCodeNoParameterAddedToErrorCode("dueDate.before.activationDate");
|
||||
|
||||
@@ -275,7 +275,7 @@ public class ClientChargeWritePlatformServiceImpl implements ClientChargeWritePl
|
||||
if (requiresTransactionDateValidation) {
|
||||
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))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
|
||||
+10
-10
@@ -277,7 +277,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (command.hasParameter(ClientApiConstants.submittedOnDateParamName)) {
|
||||
submittedOnDate = command.localDateValueOfParameterNamed(ClientApiConstants.submittedOnDateParamName);
|
||||
}
|
||||
if (active && submittedOnDate.isAfter(activationDate)) {
|
||||
if (active && DateUtils.isAfter(submittedOnDate, activationDate)) {
|
||||
submittedOnDate = activationDate;
|
||||
}
|
||||
final Long savingsAccountId = null;
|
||||
@@ -743,7 +743,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
CommandProcessingResult commandProcessingResult = CommandProcessingResult.empty();
|
||||
if (client.isActive() && client.savingsProductId() != null) {
|
||||
SavingsAccountDataDTO savingsAccountDataDTO = new SavingsAccountDataDTO(client, null, client.savingsProductId(),
|
||||
client.getActivationLocalDate(), client.activatedBy(), fmt);
|
||||
client.getActivationDate(), client.activatedBy(), fmt);
|
||||
commandProcessingResult = this.savingsApplicationProcessWritePlatformService.createActiveApplication(savingsAccountDataDTO);
|
||||
if (commandProcessingResult.getSavingsId() != null) {
|
||||
this.savingsRepositoryWrapper.findOneWithNotFoundDetection(commandProcessingResult.getSavingsId());
|
||||
@@ -851,10 +851,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.client.actvation.date", errorMessage,
|
||||
closureDate, client.getActivationLocalDate());
|
||||
closureDate, client.getActivationDate());
|
||||
}
|
||||
final LegalForm legalForm = LegalForm.fromInt(client.getLegalForm());
|
||||
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()) {
|
||||
final String errorMessage = "Client cannot be closed because of non-closed loans.";
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("close", "date.cannot.before.loan.closed.date", errorMessage,
|
||||
closureDate, loan.getClosedOnDate());
|
||||
@@ -976,7 +976,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
||||
throw new InvalidClientStateTransitionException("rejection", "on.account.not.in.pending.activation.status", errorMessage,
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("rejection", "date.cannot.before.client.submitted.date", errorMessage,
|
||||
rejectionDate, client.getSubmittedOnDate());
|
||||
@@ -1008,7 +1008,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
final String errorMessage = "Only clients pending activation may be withdrawn.";
|
||||
throw new InvalidClientStateTransitionException("withdrawal", "on.account.not.in.pending.activation.status", errorMessage,
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("withdrawal", "date.cannot.before.client.submitted.date", errorMessage,
|
||||
withdrawalDate, client.getSubmittedOnDate());
|
||||
@@ -1034,7 +1034,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (!client.isClosed()) {
|
||||
final String errorMessage = "only closed clients may be reactivated.";
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("reactivation", "date.cannot.before.client.closed.date", errorMessage,
|
||||
reactivateDate, client.getClosureDate());
|
||||
@@ -1060,7 +1060,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (!client.isRejected()) {
|
||||
final String errorMessage = "only rejected clients may be reactivated.";
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.rejected.date", errorMessage,
|
||||
undoRejectDate, client.getRejectedDate());
|
||||
@@ -1088,7 +1088,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (!client.isWithdrawn()) {
|
||||
final String errorMessage = "only withdrawal clients may be reactivated.";
|
||||
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.";
|
||||
throw new InvalidClientStateTransitionException("reopened", "date.cannot.before.client.withdrawal.date", errorMessage,
|
||||
undoWithdrawalDate, client.getWithdrawalDate());
|
||||
|
||||
+12
-11
@@ -55,7 +55,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
||||
// Get the oldest overdue installment if exists one
|
||||
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
|
||||
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(),
|
||||
installment.getDueDate());
|
||||
outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount());
|
||||
@@ -69,13 +69,13 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
||||
|
||||
boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
|
||||
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
|
||||
installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
|
||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = DateUtils
|
||||
.isEqual(loanTransaction.getTransactionDate(), installment.getFromDate())
|
||||
|| DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getFromDate());
|
||||
boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
|
||||
&& loanTransaction.getTransactionDate().isBefore(installment.getDueDate());
|
||||
&& DateUtils.isBefore(loanTransaction.getTransactionDate(), installment.getDueDate());
|
||||
boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
|
||||
&& (loanTransaction.getTransactionDate().isEqual(installment.getDueDate())
|
||||
|| loanTransaction.getTransactionDate().isBefore(installment.getDueDate()));
|
||||
&& !DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getDueDate());
|
||||
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && (isLoanTransactionIsBeforeNotLastInstallmentDueDate
|
||||
|| isLoanTransactionIsOnOrBeforeLastInstallmentDueDate)) {
|
||||
amountAvailable = amountAvailable.subtract(loanTransaction.getAmount());
|
||||
@@ -93,11 +93,12 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
|
||||
amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
|
||||
log.debug("Amount available {}", amountAvailable);
|
||||
for (LoanTransaction loanTransaction : chargebackTransactions) {
|
||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
|
||||
installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
|
||||
boolean isLoanTransactionIsBeforeInstallmentDueDate = loanTransaction.getTransactionDate()
|
||||
.isBefore(installment.getDueDate());
|
||||
boolean isLoanTransactionIsBeforeBusinessDate = loanTransaction.getTransactionDate().isBefore(businessDate);
|
||||
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = !DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||
installment.getFromDate());
|
||||
boolean isLoanTransactionIsBeforeInstallmentDueDate = DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||
installment.getDueDate());
|
||||
boolean isLoanTransactionIsBeforeBusinessDate = DateUtils.isBefore(loanTransaction.getTransactionDate(),
|
||||
businessDate);
|
||||
if (isLoanTransactionIsOnOrAfterInstallmentFromDate && isLoanTransactionIsBeforeInstallmentDueDate
|
||||
&& isLoanTransactionIsBeforeBusinessDate) {
|
||||
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);
|
||||
LocalDate submittedOnDate = DateUtils.getBusinessLocalDate();
|
||||
if (active && submittedOnDate.isAfter(activationDate)) {
|
||||
if (active && DateUtils.isAfter(submittedOnDate, activationDate)) {
|
||||
submittedOnDate = activationDate;
|
||||
}
|
||||
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.";
|
||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
|
||||
errorMessage);
|
||||
} else if (loanStatus.isClosed() && loan.getClosedOnDate().isAfter(closureDate)) {
|
||||
} else if (loanStatus.isClosed() && DateUtils.isAfter(loan.getClosedOnDate(), closureDate)) {
|
||||
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName()
|
||||
+ "closureDate cannot be before the loan closedOnDate.";
|
||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
||||
@@ -640,7 +640,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
+ " cannot be closed with active savings accounts associated.";
|
||||
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
|
||||
"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()
|
||||
+ " closureDate cannot be before the loan closedOnDate.";
|
||||
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,
|
||||
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 errorMessage = levelName + " activation date should be greater than or equal to the parent Office's creation date "
|
||||
+ activationDate.toString();
|
||||
@@ -916,10 +916,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
}
|
||||
|
||||
private void checkGroupMembersMeetingSyncWithCenterMeeting(final Long centerId, final Set<Group> groupMembers) {
|
||||
|
||||
/**
|
||||
* Get parent(center) calendar
|
||||
*/
|
||||
// Get parent(center) calendar
|
||||
Calendar ceneterCalendar = null;
|
||||
final CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||
centerId, CalendarEntityType.CENTERS.getValue(), CalendarType.COLLECTION.getValue());
|
||||
@@ -928,9 +925,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
}
|
||||
|
||||
for (final Group group : groupMembers) {
|
||||
/**
|
||||
* Get child(group) calendar
|
||||
*/
|
||||
// Get child(group) calendar
|
||||
Calendar groupCalendar = null;
|
||||
final CalendarInstance groupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||
group.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue());
|
||||
@@ -938,19 +933,14 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
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) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"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 meeting recurrence should match with center meeting recurrence
|
||||
*/
|
||||
// Group meeting recurrence should match with center meeting recurrence
|
||||
else if (ceneterCalendar != null && groupCalendar != null) {
|
||||
|
||||
if (!ceneterCalendar.getRecurrence().equalsIgnoreCase(groupCalendar.getRecurrence())) {
|
||||
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",
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a InterestRateChart.
|
||||
@@ -143,7 +144,7 @@ public final class InterestRateChartData {
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
+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.PlatformApiDataValidationException;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -115,10 +116,8 @@ public class InterestRateChartDataValidator {
|
||||
isPrimaryGroupingByAmount = false;
|
||||
}
|
||||
|
||||
if (fromDate != null && toDate != null) {
|
||||
if (fromDate.isAfter(toDate)) {
|
||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||
}
|
||||
if (toDate != null && DateUtils.isAfter(fromDate, toDate)) {
|
||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||
}
|
||||
|
||||
// validate chart Slabs - mandatory when creating
|
||||
@@ -177,11 +176,8 @@ public class InterestRateChartDataValidator {
|
||||
if (isPrimaryGroupingByAmount == null) {
|
||||
isPrimaryGroupingByAmount = false;
|
||||
}
|
||||
|
||||
if (fromDate != null && toDate != null) {
|
||||
if (fromDate.isAfter(toDate)) {
|
||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||
}
|
||||
if (toDate != null && DateUtils.isAfter(fromDate, toDate)) {
|
||||
baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
|
||||
}
|
||||
|
||||
validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
|
||||
|
||||
+2
-5
@@ -312,10 +312,7 @@ public class InterestRateChartSlabFields {
|
||||
|
||||
public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) {
|
||||
if (obj1 == null || obj2 == null) {
|
||||
if (Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0 ? Boolean.TRUE : Boolean.FALSE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Objects.compare(obj1, obj2, Comparator.nullsFirst(Comparator.naturalOrder())) == 0;
|
||||
}
|
||||
return obj1.compareTo(obj2) == 0;
|
||||
}
|
||||
@@ -326,7 +323,7 @@ public class InterestRateChartSlabFields {
|
||||
}
|
||||
|
||||
public boolean isAmountRangeProvided() {
|
||||
return (this.amountRangeFrom == null) ? false : true;
|
||||
return this.amountRangeFrom != null;
|
||||
}
|
||||
|
||||
public BigDecimal annualInterestRate() {
|
||||
|
||||
+4
-4
@@ -88,8 +88,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
|
||||
|
||||
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||
Map<String, Object> auditFields = new HashMap<>(
|
||||
Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
|
||||
loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDate().orElse(null)));
|
||||
Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDateTime(), LAST_MODIFIED_BY,
|
||||
loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDateTime()));
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
||||
}
|
||||
@@ -108,8 +108,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
|
||||
|
||||
final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow();
|
||||
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),
|
||||
LAST_MODIFIED_DATE, transaction.getLastModifiedDate().orElse(null)));
|
||||
transaction.getCreatedDateTime(), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE,
|
||||
transaction.getLastModifiedDateTime()));
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
|
||||
}
|
||||
|
||||
+14
-14
@@ -369,7 +369,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final Integer transactionType, Integer installmentNumber) {
|
||||
boolean isAccountTransfer = true;
|
||||
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: "
|
||||
+ loan.getId()
|
||||
+ " 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;
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
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: "
|
||||
+ loan.getId()
|
||||
+ " 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 Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
||||
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: "
|
||||
+ loan.getId()
|
||||
+ " 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
|
||||
public void reverseTransfer(final LoanTransaction loanTransaction) {
|
||||
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",
|
||||
"Loan transaction: " + loanTransaction.getId()
|
||||
+ " 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();
|
||||
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (installment.getDueDate().isAfter(loan.getMaturityDate())) {
|
||||
if (DateUtils.isAfter(installment.getDueDate(), loan.getMaturityDate())) {
|
||||
accruedTill = DateUtils.getBusinessLocalDate();
|
||||
}
|
||||
if (!isOrganisationDateEnabled || organisationStartDate.isBefore(installment.getDueDate())) {
|
||||
if (!isOrganisationDateEnabled || DateUtils.isBefore(organisationStartDate, installment.getDueDate())) {
|
||||
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate,
|
||||
repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges,
|
||||
installment);
|
||||
@@ -641,12 +641,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final LocalDate interestCalculatedFrom, final Long loanProductId, final MonetaryCurrency currency,
|
||||
final CurrencyData currencyData, final Set<LoanCharge> loanCharges, final LoanRepaymentScheduleInstallment installment) {
|
||||
|
||||
if (!accruedTill.isBefore(installment.getDueDate())
|
||||
|| (accruedTill.isAfter(installment.getFromDate()) && !accruedTill.isAfter(installment.getDueDate()))) {
|
||||
if (!DateUtils.isBefore(accruedTill, installment.getDueDate()) || (DateUtils.isAfter(accruedTill, installment.getFromDate())
|
||||
&& !DateUtils.isAfter(accruedTill, installment.getDueDate()))) {
|
||||
BigDecimal dueDateFeeIncome = BigDecimal.ZERO;
|
||||
BigDecimal dueDatePenaltyIncome = BigDecimal.ZERO;
|
||||
LocalDate chargesTillDate = installment.getDueDate();
|
||||
if (!accruedTill.isAfter(installment.getDueDate())) {
|
||||
if (!DateUtils.isAfter(accruedTill, installment.getDueDate())) {
|
||||
chargesTillDate = accruedTill;
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Override
|
||||
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
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: "
|
||||
+ loan.getId()
|
||||
+ " 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 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: "
|
||||
+ loan.getId()
|
||||
+ " 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
|
||||
public LoanTransaction foreCloseLoan(Loan loan, final LocalDate foreClosureDate, final String noteText, final ExternalId externalId,
|
||||
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: "
|
||||
+ loan.getId()
|
||||
+ " 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 LoanRepaymentScheduleInstallment foreCloseDetail = loan.fetchLoanForeclosureDetail(foreClosureDate);
|
||||
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()
|
||||
&& (loan.getAccruedTill() == null || !foreClosureDate.isEqual(loan.getAccruedTill()))) {
|
||||
&& (loan.getAccruedTill() == null || !DateUtils.isEqual(foreClosureDate, loan.getAccruedTill()))) {
|
||||
loan.reverseAccrualsAfter(foreClosureDate);
|
||||
Money[] accruedReceivables = loan.getReceivableIncome(foreClosureDate);
|
||||
Money interestPortion = foreCloseDetail.getInterestCharged(currency).minus(accruedReceivables[0]);
|
||||
@@ -805,7 +805,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loan.addLoanTransaction(accrualTransaction);
|
||||
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
||||
for (LoanCharge loanCharge : loan.getActiveCharges()) {
|
||||
boolean isDue = fromDate.isEqual(loan.getDisbursementDate())
|
||||
boolean isDue = DateUtils.isEqual(fromDate, loan.getDisbursementDate())
|
||||
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, foreClosureDate)
|
||||
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate);
|
||||
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) {
|
||||
int compareResult = 0;
|
||||
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
|
||||
* installment
|
||||
**/
|
||||
// For Terms bearing the same effective date, we sort based on modified date (when available) and new inserted
|
||||
// installment
|
||||
if (comparsion == 0) {
|
||||
if (o2.getTermType().isDueDateVariation() || o2.getTermType().isInsertInstallment()) {
|
||||
compareResult = 1;
|
||||
|
||||
+16
-14
@@ -27,6 +27,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
@@ -312,7 +313,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
protected boolean isTransactionInAdvanceOfInstallment(final int installmentIndex,
|
||||
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
||||
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,
|
||||
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate) {
|
||||
final LoanRepaymentScheduleInstallment currentInstallment = installments.get(installmentIndex);
|
||||
return transactionDate.isAfter(currentInstallment.getDueDate());
|
||||
return DateUtils.isAfter(transactionDate, currentInstallment.getDueDate());
|
||||
}
|
||||
|
||||
private void recalculateChargeOffTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
||||
@@ -477,7 +478,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
LocalDate pastDueDate = null;
|
||||
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
||||
pastDueDate = currentInstallment.getDueDate();
|
||||
if (!currentInstallment.isAdditional() && currentInstallment.getDueDate().isAfter(transactionDate)) {
|
||||
if (!currentInstallment.isAdditional() && DateUtils.isAfter(currentInstallment.getDueDate(), transactionDate)) {
|
||||
currentInstallment.addToCredits(transactionAmount.getAmount());
|
||||
currentInstallment.addToPrincipal(transactionDate, transactionAmount);
|
||||
if (repaidAmount.isGreaterThanZero()) {
|
||||
@@ -491,7 +492,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
// If already exists an additional installment just update the due date and
|
||||
// principal from the Loan chargeback / CBR transaction
|
||||
} else if (currentInstallment.isAdditional()) {
|
||||
if (transactionDate.isAfter(currentInstallment.getDueDate())) {
|
||||
if (DateUtils.isAfter(transactionDate, currentInstallment.getDueDate())) {
|
||||
currentInstallment.updateDueDate(transactionDate);
|
||||
}
|
||||
|
||||
@@ -669,18 +670,19 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
if (loanCharge.getAmountOutstanding(currency).isGreaterThanZero() && !loanCharge.isDueAtDisbursement()) {
|
||||
if (loanCharge.isInstalmentFee()) {
|
||||
LoanInstallmentCharge unpaidLoanChargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge();
|
||||
if (chargePerInstallment == null || chargePerInstallment.getRepaymentInstallment().getDueDate()
|
||||
.isAfter(unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
||||
if (chargePerInstallment == null || DateUtils.isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||
unpaidLoanChargePerInstallment.getRepaymentInstallment().getDueDate())) {
|
||||
installemntCharge = loanCharge;
|
||||
chargePerInstallment = unpaidLoanChargePerInstallment;
|
||||
}
|
||||
} else if (earliestUnpaidCharge == null || loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
||||
} else if (earliestUnpaidCharge == null
|
||||
|| DateUtils.isBefore(loanCharge.getDueLocalDate(), earliestUnpaidCharge.getDueLocalDate())) {
|
||||
earliestUnpaidCharge = loanCharge;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (earliestUnpaidCharge == null || (chargePerInstallment != null
|
||||
&& earliestUnpaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
if (earliestUnpaidCharge == null || (chargePerInstallment != null && DateUtils.isAfter(earliestUnpaidCharge.getDueLocalDate(),
|
||||
chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
earliestUnpaidCharge = installemntCharge;
|
||||
}
|
||||
|
||||
@@ -791,20 +793,20 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
if (loanCharge.isInstalmentFee()) {
|
||||
LoanInstallmentCharge paidLoanChargePerInstallment = loanCharge
|
||||
.getLastPaidOrPartiallyPaidInstallmentLoanCharge(currency);
|
||||
if (chargePerInstallment == null
|
||||
|| (paidLoanChargePerInstallment != null && chargePerInstallment.getRepaymentInstallment().getDueDate()
|
||||
.isBefore(paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
if (chargePerInstallment == null || (paidLoanChargePerInstallment != null
|
||||
&& DateUtils.isBefore(chargePerInstallment.getRepaymentInstallment().getDueDate(),
|
||||
paidLoanChargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
installemntCharge = loanCharge;
|
||||
chargePerInstallment = paidLoanChargePerInstallment;
|
||||
}
|
||||
} else if (latestPaidCharge == null || (loanCharge.isPaidOrPartiallyPaid(currency)
|
||||
&& loanCharge.getDueLocalDate().isAfter(latestPaidCharge.getDueLocalDate()))) {
|
||||
&& DateUtils.isAfter(loanCharge.getDueLocalDate(), latestPaidCharge.getDueLocalDate()))) {
|
||||
latestPaidCharge = loanCharge;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (latestPaidCharge == null || (chargePerInstallment != null
|
||||
&& latestPaidCharge.getDueLocalDate().isAfter(chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
&& DateUtils.isAfter(latestPaidCharge.getDueLocalDate(), chargePerInstallment.getRepaymentInstallment().getDueDate()))) {
|
||||
latestPaidCharge = installemntCharge;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -194,7 +194,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
switch (paymentAllocationType.getDueType()) {
|
||||
case PAST_DUE -> {
|
||||
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);
|
||||
if (currentInstallment != null) {
|
||||
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
||||
@@ -206,7 +206,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
}
|
||||
case DUE -> {
|
||||
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);
|
||||
if (currentInstallment != null) {
|
||||
LoanTransactionToRepaymentScheduleMapping loanTransactionToRepaymentScheduleMapping = getTransactionMapping(
|
||||
@@ -222,14 +222,14 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
List<LoanRepaymentScheduleInstallment> currentInstallments = new ArrayList<>();
|
||||
if (FutureInstallmentAllocationRule.REAMORTIZATION.equals(futureInstallmentAllocationRule)) {
|
||||
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)) {
|
||||
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();
|
||||
} else if (FutureInstallmentAllocationRule.LAST_INSTALLMENT.equals(futureInstallmentAllocationRule)) {
|
||||
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();
|
||||
}
|
||||
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.util.List;
|
||||
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.Money;
|
||||
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)
|
||||
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
||||
|| !loanCharge.getEffectiveDueDate().isAfter(transactionDate))
|
||||
|| !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate))
|
||||
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
||||
Money calculatedPenaltyCharge = Money.zero(currency);
|
||||
Money calculatedFeeCharge = Money.zero(currency);
|
||||
@@ -141,7 +142,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio
|
||||
feeChargesPortion = feeChargesPortion.add(subFeePortion);
|
||||
|
||||
Money subInterestPortion;
|
||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
||||
if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) {
|
||||
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
||||
transactionAmountRemaining = transactionAmountRemaining.minus(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.util.List;
|
||||
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.Money;
|
||||
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)
|
||||
.filter(loanCharge -> loanCharge.getEffectiveDueDate() == null
|
||||
|| !loanCharge.getEffectiveDueDate().isAfter(transactionDate))
|
||||
|| !DateUtils.isAfter(loanCharge.getEffectiveDueDate(), transactionDate))
|
||||
.sorted(LoanChargeEffectiveDueDateComparator.INSTANCE).toList();
|
||||
Money calculatedPenaltyCharge = Money.zero(currency);
|
||||
Money calculatedFeeCharge = Money.zero(currency);
|
||||
@@ -129,13 +130,11 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio
|
||||
penaltyChargesPortion = penaltyChargesPortion.add(subPenaltyPortion);
|
||||
|
||||
Money subInterestPortion;
|
||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
||||
if (ignoreDueDateCheck || !DateUtils.isBefore(transactionDate, currentInstallment.getDueDate())) {
|
||||
subInterestPortion = currentInstallment.payInterestComponent(transactionDate, transactionAmountRemaining);
|
||||
transactionAmountRemaining = transactionAmountRemaining.minus(subInterestPortion);
|
||||
interestPortion = interestPortion.add(subInterestPortion);
|
||||
}
|
||||
|
||||
if (ignoreDueDateCheck || !transactionDate.isBefore(currentInstallment.getDueDate())) {
|
||||
Money subPrincipalPortion = currentInstallment.payPrincipalComponent(transactionDate, transactionAmountRemaining);
|
||||
transactionAmountRemaining = transactionAmountRemaining.minus(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.util.List;
|
||||
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.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
@@ -85,9 +86,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
|
||||
final LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex);
|
||||
lastInstallmentDueDate = previousInstallment.getDueDate();
|
||||
|
||||
isInAdvance = !(transactionDate.isAfter(lastInstallmentDueDate) || transactionDate.isEqual(lastInstallmentDueDate));
|
||||
|
||||
return isInAdvance;
|
||||
return DateUtils.isBefore(transactionDate, lastInstallmentDueDate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-5
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.im
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
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.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
@@ -174,14 +175,12 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
|
||||
|
||||
private LoanRepaymentScheduleInstallment nearestInstallment(final LocalDate transactionDate,
|
||||
final List<LoanRepaymentScheduleInstallment> installments) {
|
||||
|
||||
LoanRepaymentScheduleInstallment nearest = installments.get(0);
|
||||
LoanRepaymentScheduleInstallment nearest = installments.get(0); // installments must be sorted by dates
|
||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (installment.getDueDate().isBefore(transactionDate) || installment.getDueDate().isEqual(transactionDate)) {
|
||||
nearest = installment;
|
||||
} else if (installment.getDueDate().isAfter(transactionDate)) {
|
||||
if (DateUtils.isBefore(transactionDate, installment.getDueDate())) {
|
||||
break;
|
||||
}
|
||||
nearest = installment;
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
+1
-1
@@ -327,7 +327,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
if (loan.isApproved() && !loan.isDisbursed()) {
|
||||
final List<SavingsAccountTransaction> transactions = new ArrayList<>();
|
||||
for (final SavingsAccountTransaction transaction : savingsAccount.getTransactions()) {
|
||||
if (!transaction.getTransactionDate().isAfter(loan.getApprovedOnDate())) {
|
||||
if (!DateUtils.isAfter(transaction.getTransactionDate(), loan.getApprovedOnDate())) {
|
||||
transactions.add(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
|
||||
|
||||
private void validateGuarantorSavingsAccountActivationDateWithLoanSubmittedOnDate(final Loan loan,
|
||||
final SavingsAccount savingsAccount) {
|
||||
if (loan.getSubmittedOnDate().isBefore(savingsAccount.getActivationDate())) {
|
||||
if (DateUtils.isBefore(loan.getSubmittedOnDate(), savingsAccount.getActivationDate())) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.guarantor.saving.account.activation.date.is.on.or.before.loan.submitted.on.date",
|
||||
"Guarantor saving account activation date [" + savingsAccount.getActivationDate()
|
||||
|
||||
+7
-7
@@ -27,6 +27,7 @@ import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
@@ -120,16 +121,15 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
||||
// Loop through all loanRepayments
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
||||
|
||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||
|
||||
// update from date if it's not same as previous installment's due
|
||||
// date.
|
||||
if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) {
|
||||
if (!DateUtils.isEqual(tmpFromDate, loanRepaymentScheduleInstallment.getFromDate())) {
|
||||
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.
|
||||
// Assuming holiday's repayment reschedule to date cannot be
|
||||
// created on a non-working day.
|
||||
@@ -146,7 +146,7 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
||||
LocalDate adjustedRescheduleToDate = null;
|
||||
final LocalDate rescheduleToDate = holiday.getToDate();
|
||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : loan.getRepaymentScheduleInstallments()) {
|
||||
if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
if (DateUtils.isEqual(rescheduleToDate, loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
adjustedRescheduleToDate = rescheduleToDate;
|
||||
break;
|
||||
} else {
|
||||
@@ -160,9 +160,9 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
||||
private LocalDate doStandardMonthlyCheck(LocalDate adjustedRescheduleToDate, LocalDate rescheduleToDate,
|
||||
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||
// Standard Monthly Loan Holiday check
|
||||
if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
||||
&& rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) {
|
||||
adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||
LocalDate dueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||
if (DateUtils.isAfter(rescheduleToDate, dueDate) && DateUtils.isBefore(rescheduleToDate, dueDate.plusDays(30))) {
|
||||
adjustedRescheduleToDate = dueDate;
|
||||
}
|
||||
return adjustedRescheduleToDate;
|
||||
}
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet {
|
||||
.retrieveInstallmentLoanCharges(chargeData.getId(), true);
|
||||
PortfolioAccountData portfolioAccountData = null;
|
||||
for (final LoanInstallmentChargeData installmentChargeData : chargePerInstallments) {
|
||||
if (!installmentChargeData.getDueDate().isAfter(DateUtils.getBusinessLocalDate())) {
|
||||
if (!DateUtils.isDateInTheFuture(installmentChargeData.getDueDate())) {
|
||||
if (portfolioAccountData == null) {
|
||||
portfolioAccountData = accountAssociationsReadPlatformService
|
||||
.retriveLoanLinkedAssociation(chargeData.getLoanId());
|
||||
@@ -79,7 +79,7 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet {
|
||||
transferFeeCharge(accountTransferDTO, errors);
|
||||
}
|
||||
}
|
||||
} else if (chargeData.getDueDate() != null && !chargeData.getDueDate().isAfter(DateUtils.getBusinessLocalDate())) {
|
||||
} else if (chargeData.getDueDate() != null && !DateUtils.isDateInTheFuture(chargeData.getDueDate())) {
|
||||
final PortfolioAccountData portfolioAccountData = accountAssociationsReadPlatformService
|
||||
.retriveLoanLinkedAssociation(chargeData.getLoanId());
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
|
||||
+66
-69
@@ -204,7 +204,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
|
||||
applyLoanVariationsForPartialScheduleGenerate(loanApplicationTerms, scheduleParams, interestRates,
|
||||
interestRatesForInstallments);
|
||||
if (!firstRepaymentdate.isAfter(scheduleParams.getActualRepaymentDate())) {
|
||||
if (!DateUtils.isAfter(firstRepaymentdate, scheduleParams.getActualRepaymentDate())) {
|
||||
isFirstRepayment = false;
|
||||
}
|
||||
}
|
||||
@@ -243,7 +243,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
continue;
|
||||
}
|
||||
|
||||
if (scheduleParams.getPeriodStartDate().isAfter(scheduledDueDate)) {
|
||||
if (DateUtils.isAfter(scheduleParams.getPeriodStartDate(), scheduledDueDate)) {
|
||||
throw new ScheduleDateException("Due date can't be before period start date", scheduledDueDate);
|
||||
}
|
||||
|
||||
@@ -254,8 +254,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
// this block is to generate the schedule till the specified
|
||||
// date(used for calculating preclosure)
|
||||
boolean isCompletePeriod = true;
|
||||
if (scheduleParams.getScheduleTillDate() != null && !scheduledDueDate.isBefore(scheduleParams.getScheduleTillDate())) {
|
||||
if (!scheduledDueDate.isEqual(scheduleParams.getScheduleTillDate())) {
|
||||
if (scheduleParams.getScheduleTillDate() != null
|
||||
&& !DateUtils.isBefore(scheduledDueDate, scheduleParams.getScheduleTillDate())) {
|
||||
if (!DateUtils.isEqual(scheduledDueDate, scheduleParams.getScheduleTillDate())) {
|
||||
isCompletePeriod = false;
|
||||
}
|
||||
scheduledDueDate = scheduleParams.getScheduleTillDate();
|
||||
@@ -420,7 +421,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
currentDate = scheduleParams.getScheduleTillDate();
|
||||
}
|
||||
if (scheduleParams.applyInterestRecalculation() && scheduleParams.getLatePaymentMap().size() > 0
|
||||
&& currentDate.isAfter(scheduleParams.getPeriodStartDate())) {
|
||||
&& DateUtils.isAfter(currentDate, scheduleParams.getPeriodStartDate())) {
|
||||
Money totalInterest = addInterestOnlyRepaymentScheduleForCurrentdate(mc, loanApplicationTerms, holidayDetailDTO, currency,
|
||||
periods, currentDate, loanRepaymentScheduleTransactionProcessor, transactions, loanCharges, scheduleParams);
|
||||
scheduleParams.addTotalCumulativeInterest(totalInterest);
|
||||
@@ -449,7 +450,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Map<LocalDate, Money> periodCompoundingDetails = compoundingDetails.get(loanScheduleModelPeriod.periodFromDate());
|
||||
if (periodCompoundingDetails != null) {
|
||||
for (Map.Entry<LocalDate, Money> entry : periodCompoundingDetails.entrySet()) {
|
||||
if (entry.getValue().isGreaterThanZero() && !entry.getKey().isAfter(loanScheduleModelPeriod.periodDueDate())) {
|
||||
if (entry.getValue().isGreaterThanZero()
|
||||
&& !DateUtils.isAfter(entry.getKey(), loanScheduleModelPeriod.periodDueDate())) {
|
||||
LocalDate effectiveDate = entry.getKey();
|
||||
if (loanApplicationTerms.allowCompoundingOnEod()) {
|
||||
effectiveDate = effectiveDate.minusDays(1);
|
||||
@@ -734,7 +736,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
}
|
||||
boolean updateLatePaymentMap = false;
|
||||
final LocalDate transactionDate = detail.getTransactionDate();
|
||||
if (transactionDate.isBefore(scheduledDueDate)) {
|
||||
if (DateUtils.isBefore(transactionDate, scheduledDueDate)) {
|
||||
if (scheduleParams.getLoanRepaymentScheduleTransactionProcessor() != null && scheduleParams
|
||||
.getLoanRepaymentScheduleTransactionProcessor().isInterestFirstRepaymentScheduleTransactionProcessor()) {
|
||||
if (detail.getTransaction().isWaiver()) {
|
||||
@@ -748,8 +750,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
processTransactions.clear();
|
||||
currentTransactions.addAll(createCurrentTransactionList(detail));
|
||||
|
||||
if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.isFirstPeriod()) {
|
||||
|
||||
if (!DateUtils.isEqual(transactionDate, scheduleParams.getPeriodStartDate()) || scheduleParams.isFirstPeriod()) {
|
||||
int periodDays = Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(), transactionDate));
|
||||
// calculates period start date for interest
|
||||
// calculation as per the configuration
|
||||
@@ -842,7 +843,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
if (loanApplicationTerms.getPreClosureInterestCalculationStrategy().calculateTillRestFrequencyEnabled()) {
|
||||
LocalDate applicableDate = getNextRestScheduleDate(transactionDate.minusDays(1), loanApplicationTerms,
|
||||
holidayDetailDTO);
|
||||
checkForOutstanding = transactionDate.isEqual(applicableDate);
|
||||
checkForOutstanding = DateUtils.isEqual(transactionDate, applicableDate);
|
||||
|
||||
}
|
||||
// reduces actual outstanding balance
|
||||
@@ -878,7 +879,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
} else if (scheduleParams.getLoanRepaymentScheduleTransactionProcessor() != null) {
|
||||
LocalDate applicableDate = getNextRestScheduleDate(transactionDate.minusDays(1), loanApplicationTerms,
|
||||
holidayDetailDTO);
|
||||
if (applicableDate.isBefore(scheduledDueDate)) {
|
||||
if (DateUtils.isBefore(applicableDate, scheduledDueDate)) {
|
||||
List<LoanTransaction> currentTransactions = createCurrentTransactionList(detail);
|
||||
Money unprocessed = scheduleParams.getLoanRepaymentScheduleTransactionProcessor()
|
||||
.handleRepaymentSchedule(currentTransactions, currency, scheduleParams.getInstallments(), loanCharges);
|
||||
@@ -937,7 +938,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
}
|
||||
|
||||
}
|
||||
if (arrears.isGreaterThanZero() && applicableDate.isBefore(lastRestDate)) {
|
||||
if (arrears.isGreaterThanZero() && DateUtils.isBefore(applicableDate, lastRestDate)) {
|
||||
handleLatePayments(loanApplicationTerms, holidayDetailDTO, currency, scheduleParams, lastRestDate, detail);
|
||||
}
|
||||
}
|
||||
@@ -991,15 +992,15 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
final BigDecimal chargesDueAtTimeOfDisbursement, LoanScheduleParams scheduleParams,
|
||||
final Collection<LoanScheduleModelPeriod> periods, final LocalDate scheduledDueDate) {
|
||||
for (Map.Entry<LocalDate, Money> disburseDetail : scheduleParams.getDisburseDetailMap().entrySet()) {
|
||||
if (disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate())
|
||||
&& !disburseDetail.getKey().isAfter(scheduledDueDate)) {
|
||||
if (DateUtils.isAfter(disburseDetail.getKey(), scheduleParams.getPeriodStartDate())
|
||||
&& !DateUtils.isAfter(disburseDetail.getKey(), scheduledDueDate)) {
|
||||
// validation check for amount not exceeds specified max
|
||||
// amount as per the configuration
|
||||
if (loanApplicationTerms.getMaxOutstandingBalance() != null && scheduleParams.getOutstandingBalance()
|
||||
.plus(disburseDetail.getValue()).isGreaterThan(loanApplicationTerms.getMaxOutstandingBalance())) {
|
||||
String errorMsg = "Outstanding balance must not exceed the amount: " + loanApplicationTerms.getMaxOutstandingBalance();
|
||||
throw new MultiDisbursementOutstandingAmoutException(errorMsg,
|
||||
loanApplicationTerms.getMaxOutstandingBalance().getAmount(), disburseDetail.getValue());
|
||||
Money maxOutstandingBalance = loanApplicationTerms.getMaxOutstandingBalance();
|
||||
if (scheduleParams.getOutstandingBalance().plus(disburseDetail.getValue()).isGreaterThan(maxOutstandingBalance)) {
|
||||
String errorMsg = "Outstanding balance must not exceed the amount: " + maxOutstandingBalance;
|
||||
throw new MultiDisbursementOutstandingAmoutException(errorMsg, maxOutstandingBalance.getAmount(),
|
||||
disburseDetail.getValue());
|
||||
}
|
||||
|
||||
// creates and add disbursement detail to the repayments
|
||||
@@ -1045,7 +1046,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
// due date changes should be applied only for that dueDate
|
||||
if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) {
|
||||
LoanTermVariationsData loanTermVariationsData = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
|
||||
if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) {
|
||||
if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) {
|
||||
modifiedScheduledDueDate = loanTermVariationsData.getDateValue();
|
||||
if (!loanTermVariationsData.isSpecificToInstallment()) {
|
||||
scheduleParams.setActualRepaymentDate(modifiedScheduledDueDate);
|
||||
@@ -1097,7 +1098,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
loanTermVariationsData.setProcessed(true);
|
||||
break;
|
||||
case DELETE_INSTALLMENT:
|
||||
if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) {
|
||||
if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) {
|
||||
skipPeriod = true;
|
||||
loanTermVariationsData.setProcessed(true);
|
||||
}
|
||||
@@ -1205,7 +1206,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
variationsData.add(loanTermVariationsData);
|
||||
break;
|
||||
case DELETE_INSTALLMENT:
|
||||
if (loanTermVariationsData.getTermVariationApplicableFrom().isEqual(modifiedScheduledDueDate)) {
|
||||
if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) {
|
||||
skipPeriod = true;
|
||||
variationsData.add(loanTermVariationsData);
|
||||
}
|
||||
@@ -1363,7 +1364,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Money outstanding = params.getOutstandingBalanceAsPerRest();
|
||||
Money totalInterest = Money.zero(currency);
|
||||
Money totalCumulativeInterest = Money.zero(currency);
|
||||
double interestCalculationGraceOnRepaymentPeriodFraction = Double.valueOf(0);
|
||||
double interestCalculationGraceOnRepaymentPeriodFraction = 0;
|
||||
int periodNumberTemp = 1;
|
||||
LocalDate lastRestDate = getNextRestScheduleDate(currentDate.minusDays(1), loanApplicationTerms, holidayDetailDTO);
|
||||
Collection<LoanTermVariationsData> applicableVariations = loanApplicationTerms.getLoanTermVariations().getInterestRateChanges();
|
||||
@@ -1371,10 +1372,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
LocalDate additionalPeriodsStartDate = params.getPeriodStartDate();
|
||||
|
||||
do {
|
||||
|
||||
params.setActualRepaymentDate(this.scheduledDateGenerator.generateNextRepaymentDate(params.getActualRepaymentDate(),
|
||||
loanApplicationTerms, isFirstRepayment));
|
||||
if (params.getActualRepaymentDate().isAfter(currentDate)) {
|
||||
if (DateUtils.isAfter(params.getActualRepaymentDate(), currentDate)) {
|
||||
params.setActualRepaymentDate(currentDate);
|
||||
}
|
||||
|
||||
@@ -1391,7 +1391,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
LocalDate transactionDate = detail.getTransactionDate();
|
||||
List<LoanTransaction> currentTransactions = createCurrentTransactionList(detail);
|
||||
|
||||
if (!params.getPeriodStartDate().isEqual(transactionDate)) {
|
||||
if (!DateUtils.isEqual(transactionDate, params.getPeriodStartDate())) {
|
||||
PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
|
||||
this.paymentPeriodsInOneYearCalculator, interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
|
||||
totalInterest.zero(), totalInterest.zero(), totalInterest.zero(), outstanding, loanApplicationTerms,
|
||||
@@ -1447,15 +1447,13 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Money uncompounded = params.getUnCompoundedAmount();
|
||||
Money compounded = uncompounded.zero();
|
||||
for (Map.Entry<LocalDate, Money> mapEntry : params.getCompoundingMap().entrySet()) {
|
||||
if (mapEntry.getKey().isAfter(params.getPeriodStartDate())) {
|
||||
if (DateUtils.isAfter(mapEntry.getKey(), params.getPeriodStartDate())) {
|
||||
compounded = compounded.plus(mapEntry.getValue());
|
||||
}
|
||||
}
|
||||
if (compounded.isGreaterThanZero() && startDate.isEqual(additionalPeriodsStartDate)) {
|
||||
params.setCompoundedInLastInstallment(uncompoundedFromLastInstallment);// uncompounded
|
||||
// in
|
||||
// last
|
||||
// installment
|
||||
if (compounded.isGreaterThanZero() && DateUtils.isEqual(startDate, additionalPeriodsStartDate)) {
|
||||
// uncompounded in last installment
|
||||
params.setCompoundedInLastInstallment(uncompoundedFromLastInstallment);
|
||||
additionalPeriodsStartDate = additionalPeriodsStartDate.plusDays(1);
|
||||
}
|
||||
Money compoundedForThisPeriod = compounded.minus(uncompounded);
|
||||
@@ -1466,14 +1464,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
compoundingDate = compoundingDate.minusDays(1);
|
||||
}
|
||||
compoundingDate = getNextCompoundScheduleDate(compoundingDate, loanApplicationTerms, holidayDetailDTO);
|
||||
if (compoundingDate.isEqual(params.getActualRepaymentDate())) {
|
||||
if (DateUtils.isEqual(compoundingDate, params.getActualRepaymentDate())) {
|
||||
params.getCompoundingMap().put(compoundingDate, uncompoundedForThisPeriod);
|
||||
params.setUnCompoundedAmount(uncompoundedForThisPeriod.zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
params.setPeriodStartDate(params.getActualRepaymentDate());
|
||||
} while (params.getActualRepaymentDate().isBefore(currentDate) && !outstanding.isZero());
|
||||
} while (DateUtils.isBefore(params.getActualRepaymentDate(), currentDate) && !outstanding.isZero());
|
||||
|
||||
if (totalInterest.isGreaterThanZero()) {
|
||||
LoanScheduleModelRepaymentPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(params.getInstalmentNumber(),
|
||||
@@ -1503,7 +1501,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Collection<RecalculationDetail> applicableTransactions = new ArrayList<>();
|
||||
if (applyInterestRecalculation && !Objects.isNull(transactions)) {
|
||||
for (RecalculationDetail detail : transactions) {
|
||||
if (!detail.getTransactionDate().isAfter(repaymentDate)) {
|
||||
if (!DateUtils.isBefore(repaymentDate, detail.getTransactionDate())) {
|
||||
applicableTransactions.add(detail);
|
||||
}
|
||||
}
|
||||
@@ -1574,7 +1572,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
List<LocalDate> removeFromprincipalPortionMap = new ArrayList<>();
|
||||
Money outstandingBalance = outstandingBalanceAsPerRest;
|
||||
for (Map.Entry<LocalDate, Money> principal : principalPortionMap.entrySet()) {
|
||||
if (!principal.getKey().isAfter(scheduledDueDate)) {
|
||||
if (!DateUtils.isAfter(principal.getKey(), scheduledDueDate)) {
|
||||
if (addMapDetails) {
|
||||
outstandingBalance = outstandingBalance.plus(principal.getValue());
|
||||
} else {
|
||||
@@ -1610,11 +1608,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Money appliedOnPrincipalVariationMap = Money.zero(currency);
|
||||
Map<LocalDate, Money> temp = new HashMap<>();
|
||||
for (LocalDate date : latePaymentCompoundingMap.keySet()) {
|
||||
if (date.isBefore(lastRestDate)) {
|
||||
if (DateUtils.isBefore(date, lastRestDate)) {
|
||||
Money money = latePaymentCompoundingMap.get(date);
|
||||
appliedOnPrincipalVariationMap = appliedOnPrincipalVariationMap.plus(money);
|
||||
if (appliedOnPrincipalVariationMap.isLessThan(compoundedPortion)) {
|
||||
if (date.isBefore(applicableDate)) {
|
||||
if (DateUtils.isBefore(date, applicableDate)) {
|
||||
updateMapWithAmount(principalVariationMap, money.negated(), date);
|
||||
updateMapWithAmount(principalVariationMap, money, applicableDate);
|
||||
}
|
||||
@@ -1648,14 +1646,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
Money totalCompoundingAmount = Money.zero(currency);
|
||||
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
||||
if (loanRepaymentScheduleInstallment.isNotFullyPaidOff()
|
||||
&& !loanRepaymentScheduleInstallment.getDueDate().isAfter(scheduledDueDate)
|
||||
&& !DateUtils.isAfter(loanRepaymentScheduleInstallment.getDueDate(), scheduledDueDate)
|
||||
&& !loanRepaymentScheduleInstallment.isRecalculatedInterestComponent()) {
|
||||
LocalDate principalEffectiveDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||
if (applyRestFrequencyForPrincipal) {
|
||||
principalEffectiveDate = getNextRestScheduleDate(loanRepaymentScheduleInstallment.getDueDate().minusDays(1),
|
||||
loanApplicationTerms, holidayDetailDTO);
|
||||
}
|
||||
if (principalEffectiveDate.isBefore(currentDate)) {
|
||||
if (DateUtils.isBefore(principalEffectiveDate, currentDate)) {
|
||||
updateMapWithAmount(latePaymentMap, loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency),
|
||||
principalEffectiveDate);
|
||||
totalCompoundingAmount = totalCompoundingAmount
|
||||
@@ -1679,10 +1677,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : params.getInstallments()) {
|
||||
if (params.getCompoundingDateVariations().containsKey(loanRepaymentScheduleInstallment.getFromDate())) {
|
||||
lastInstallmentIsPastDate = params.applyInterestRecalculation()
|
||||
&& loanRepaymentScheduleInstallment.getDueDate().isBefore(DateUtils.getBusinessLocalDate());
|
||||
&& DateUtils.isBeforeBusinessDate(loanRepaymentScheduleInstallment.getDueDate());
|
||||
} else {
|
||||
final boolean isPastDate = params.applyInterestRecalculation()
|
||||
&& loanRepaymentScheduleInstallment.getDueDate().isBefore(DateUtils.getBusinessLocalDate());
|
||||
&& DateUtils.isBeforeBusinessDate(loanRepaymentScheduleInstallment.getDueDate());
|
||||
boolean periodHasCompoundingDate = false;
|
||||
Money amountCharged = Money.zero(currency);
|
||||
if (loanApplicationTerms.getInterestRecalculationCompoundingMethod() != null) {
|
||||
@@ -1697,7 +1695,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
holidayDetailDTO);
|
||||
final LocalDate restDate = getNextRestScheduleDate(scheduledDueDate.minusDays(1), loanApplicationTerms,
|
||||
holidayDetailDTO);
|
||||
if (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
if (!DateUtils.isAfter(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
Money amountCompoundedFromLastPeriod = params.getCompoundedInLastInstallment();
|
||||
if (amountCompoundedFromLastPeriod.isZero()) {
|
||||
amountCompoundedFromLastPeriod = params.getUnCompoundedAmount();
|
||||
@@ -1705,12 +1703,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
totalCompoundedAmount = totalCompoundedAmount.minus(amountCompoundedFromLastPeriod);
|
||||
periodHasCompoundingDate = true;
|
||||
}
|
||||
while (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
if (compoundingEffectiveDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
while (!DateUtils.isAfter(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
if (DateUtils.isEqual(compoundingEffectiveDate, loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
Money amountToBeCompounding = amountCharged.minus(totalCompoundedAmount);
|
||||
updateMapWithAmount(compoundingMap, amountToBeCompounding, compoundingEffectiveDate);
|
||||
totalCompoundedAmount = totalCompoundedAmount.plus(amountToBeCompounding);
|
||||
|
||||
} else if (compoundingMap.containsKey(compoundingEffectiveDate)) {
|
||||
Money compounedAmount = compoundingMap.get(compoundingEffectiveDate);
|
||||
totalCompoundedAmount = totalCompoundedAmount.plus(compounedAmount);
|
||||
@@ -1738,7 +1735,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
params.getCompoundingDateVariations().put(loanRepaymentScheduleInstallment.getFromDate(),
|
||||
new TreeMap<>(params.getCompoundingMap()));
|
||||
for (Map.Entry<LocalDate, Money> mapEntry : params.getCompoundingMap().entrySet()) {
|
||||
if (!mapEntry.getKey().isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
if (!DateUtils.isAfter(mapEntry.getKey(), loanRepaymentScheduleInstallment.getDueDate())) {
|
||||
updateMapWithAmount(params.getPrincipalPortionMap(), mapEntry.getValue().negated(), mapEntry.getKey());
|
||||
}
|
||||
}
|
||||
@@ -1805,7 +1802,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
private void adjustCompoundedAmountWithPaidDetail(final Map<LocalDate, Money> principalPortionMap, final LocalDate lastRestDate,
|
||||
final LocalDate amountApplicableDate, final LoanTransaction transaction, final LoanApplicationTerms loanApplicationTerms,
|
||||
final MonetaryCurrency currency) {
|
||||
if (!amountApplicableDate.isEqual(lastRestDate)) {
|
||||
if (!DateUtils.isEqual(amountApplicableDate, lastRestDate)) {
|
||||
Money compoundedIncome = fetchCompoundedArrears(loanApplicationTerms, currency, transaction);
|
||||
updateMapWithAmount(principalPortionMap, compoundedIncome, amountApplicableDate);
|
||||
updateMapWithAmount(principalPortionMap, compoundedIncome.negated(), lastRestDate);
|
||||
@@ -1820,17 +1817,18 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
LocalDate lastCompoundingDate = startDate;
|
||||
LocalDate compoundingDate = startDate;
|
||||
boolean addUncompounded = true;
|
||||
while (compoundingDate.isBefore(endDate)) {
|
||||
while (DateUtils.isBefore(compoundingDate, endDate)) {
|
||||
if (loanApplicationTerms.allowCompoundingOnEod()) {
|
||||
compoundingDate = compoundingDate.minusDays(1);
|
||||
}
|
||||
compoundingDate = getNextCompoundScheduleDate(compoundingDate, loanApplicationTerms, holidayDetailDTO);
|
||||
|
||||
if (compoundingDate.isBefore(endDate)) {
|
||||
if (DateUtils.isBefore(compoundingDate, endDate)) {
|
||||
boolean isFirst = DateUtils.isEqual(startDate, lastCompoundingDate);
|
||||
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(lastCompoundingDate, compoundingDate, charges, currency,
|
||||
null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate));
|
||||
null, loanApplicationTerms.getPrincipal(), null, false, isFirst);
|
||||
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(lastCompoundingDate, compoundingDate, charges,
|
||||
currency, null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate));
|
||||
currency, null, loanApplicationTerms.getPrincipal(), null, false, isFirst);
|
||||
Money compoundAmount = feeChargesForInstallment.plus(penaltyChargesForInstallment);
|
||||
if (addUncompounded) {
|
||||
compoundAmount = compoundAmount.plus(scheduleParams.getUnCompoundedAmount());
|
||||
@@ -1904,16 +1902,15 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate,
|
||||
final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled, final LocalDate expectedDisbursementDate) {
|
||||
LocalDate periodStartDateApplicableForInterest = periodStartDate;
|
||||
if (periodStartDate.isBefore(idealDisbursementDate) || firstRepaymentdate.isAfter(periodStartDate)) {
|
||||
if (DateUtils.isBefore(periodStartDate, idealDisbursementDate) || DateUtils.isBefore(periodStartDate, firstRepaymentdate)) {
|
||||
if (loanApplicationTerms.getInterestChargedFromLocalDate() != null) {
|
||||
if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())
|
||||
|| loanApplicationTerms.getInterestChargedFromLocalDate().isAfter(periodStartDate)) {
|
||||
if (DateUtils.isEqual(periodStartDate, loanApplicationTerms.getExpectedDisbursementDate())
|
||||
|| DateUtils.isBefore(periodStartDate, loanApplicationTerms.getInterestChargedFromLocalDate())) {
|
||||
periodStartDateApplicableForInterest = loanApplicationTerms.getInterestChargedFromLocalDate();
|
||||
}
|
||||
} else if (loanApplicationTerms.getInterestChargedFromLocalDate() == null
|
||||
&& isInterestChargedFromDateSameAsDisbursalDateEnabled) {
|
||||
} else if (isInterestChargedFromDateSameAsDisbursalDateEnabled) {
|
||||
periodStartDateApplicableForInterest = expectedDisbursementDate;
|
||||
} else if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())) {
|
||||
} else if (DateUtils.isEqual(periodStartDate, loanApplicationTerms.getExpectedDisbursementDate())) {
|
||||
periodStartDateApplicableForInterest = idealDisbursementDate;
|
||||
}
|
||||
}
|
||||
@@ -1969,7 +1966,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
if (disbursementData.disbursementDate().equals(disbursementDate)) {
|
||||
principal = principal.add(disbursementData.getPrincipal());
|
||||
} else if (!excludePastUndisbursed || disbursementData.isDisbursed()
|
||||
|| !disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) {
|
||||
|| !DateUtils.isBeforeBusinessDate(disbursementData.disbursementDate())) {
|
||||
/*
|
||||
* JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there
|
||||
* were no duplicate disbursal dates and 'put' each amount into the map keyed by date
|
||||
@@ -2294,7 +2291,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
// this will generate the next schedule due date and allows to
|
||||
// process the installment only if recalculate from date is
|
||||
// greater than due date
|
||||
if (installment.getDueDate().isAfter(lastInstallmentDate)) {
|
||||
if (DateUtils.isAfter(installment.getDueDate(), lastInstallmentDate)) {
|
||||
if (totalCumulativePrincipal.isGreaterThanOrEqualTo(loanApplicationTerms.getTotalDisbursedAmount())) {
|
||||
break;
|
||||
}
|
||||
@@ -2305,7 +2302,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
do {
|
||||
actualRepaymentDate = this.scheduledDateGenerator.generateNextRepaymentDate(actualRepaymentDate,
|
||||
loanApplicationTerms, isFirstRepayment);
|
||||
if (actualRepaymentDate.isAfter(rescheduleFrom) || actualRepaymentDate.isEqual(rescheduleFrom)) {
|
||||
if (!DateUtils.isBefore(actualRepaymentDate, rescheduleFrom)) {
|
||||
actualRepaymentDate = lastInstallmentDate;
|
||||
}
|
||||
isFirstRepayment = false;
|
||||
@@ -2324,14 +2321,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDueDateVariation && !lastInstallmentDate.isEqual(installment.getDueDate())
|
||||
&& !installment.getDueDate().equals(modifiedLastInstDate)) {
|
||||
if (hasDueDateVariation && !DateUtils.isEqual(lastInstallmentDate, installment.getDueDate())
|
||||
&& !DateUtils.isEqual(modifiedLastInstDate, installment.getDueDate())) {
|
||||
lastInstallmentDate = prevLastInstDate;
|
||||
actualRepaymentDate = lastInstallmentDate;
|
||||
if (modifiedLastInstDate != null) {
|
||||
loanApplicationTerms.getLoanTermVariations().previousDueDateVariation();
|
||||
}
|
||||
} else if (installment.getDueDate().equals(modifiedLastInstDate)) {
|
||||
} else if (DateUtils.isEqual(modifiedLastInstDate, installment.getDueDate())) {
|
||||
actualRepaymentDate = modifiedLastInstDate;
|
||||
lastInstallmentDate = actualRepaymentDate;
|
||||
dueDateVariationsDataList.add(variation1);
|
||||
@@ -2356,8 +2353,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
}
|
||||
|
||||
for (Map.Entry<LocalDate, Money> disburseDetail : disburseDetailMap.entrySet()) {
|
||||
if (disburseDetail.getKey().isAfter(installment.getFromDate())
|
||||
&& !disburseDetail.getKey().isAfter(installment.getDueDate())) {
|
||||
if (DateUtils.isAfter(disburseDetail.getKey(), installment.getFromDate())
|
||||
&& !DateUtils.isAfter(disburseDetail.getKey(), installment.getDueDate())) {
|
||||
// creates and add disbursement detail to the repayments
|
||||
// period
|
||||
final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod
|
||||
@@ -2429,7 +2426,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
// recalculatedInterestComponent installment shouldn't be
|
||||
// considered while calculating fixed EMI amounts
|
||||
int period = periodNumber;
|
||||
if (!lastInstallmentDate.isEqual(installment.getDueDate())) {
|
||||
if (!DateUtils.isEqual(lastInstallmentDate, installment.getDueDate())) {
|
||||
period--;
|
||||
}
|
||||
reducePrincipal = fetchEarlyPaidAmount(installment.getPrincipal(currency), principalPortionCalculated, reducePrincipal,
|
||||
@@ -2513,7 +2510,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
int lastInterestAvilablePeriod = 0;
|
||||
int processedPeriod = 0;
|
||||
for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) {
|
||||
if (installment.getDueDate().isBefore(rescheduleFrom)) {
|
||||
if (DateUtils.isBefore(installment.getDueDate(), rescheduleFrom)) {
|
||||
newRepaymentScheduleInstallments.add(installment);
|
||||
if (installment.getInterestCharged(currency).isGreaterThanZero()) {
|
||||
lastInterestAvilablePeriod = installment.getInstallmentNumber();
|
||||
@@ -2614,7 +2611,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
}
|
||||
compoundingDateVariations.put(installment.getFromDate(), compoundingMap);
|
||||
if (totalCompounded.isGreaterThanZero()) {
|
||||
final boolean isPastDate = installment.getDueDate().isBefore(DateUtils.getBusinessLocalDate());
|
||||
final boolean isPastDate = DateUtils.isBeforeBusinessDate(installment.getDueDate());
|
||||
final LocalDate restDate = getNextRestScheduleDate(installment.getDueDate().minusDays(1), loanApplicationTerms,
|
||||
holidayDetailDTO);
|
||||
if (isPastDate) {
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
@@ -89,7 +90,7 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS
|
||||
|
||||
for (Map.Entry<LocalDate, Money> principal : principalVariation.entrySet()) {
|
||||
|
||||
if (!principal.getKey().isAfter(periodEndDate)) {
|
||||
if (!DateUtils.isAfter(principal.getKey(), periodEndDate)) {
|
||||
int interestForDays = Math.toIntExact(ChronoUnit.DAYS.between(interestStartDate, principal.getKey()));
|
||||
if (interestForDays > 0) {
|
||||
final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator,
|
||||
|
||||
+14
-14
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import net.fortuna.ical4j.model.Recur;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.service.HolidayUtil;
|
||||
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
|
||||
@@ -92,7 +93,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
seedDate = currentCalendar.getStartDateLocalDate();
|
||||
reccuringString = currentCalendar.getRecurrence();
|
||||
} else {
|
||||
seedDate = calendarHistory.getStartDateLocalDate();
|
||||
seedDate = calendarHistory.getStartDate();
|
||||
reccuringString = calendarHistory.getRecurrence();
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
holidayDetailDTO.getHolidays())) != null) {
|
||||
if (applicableHolidayForNewAdjustedDate.getReScheduleType().isResheduleToNextRepaymentDate()) {
|
||||
LocalDate nextRepaymentPeriodDueDate = adjustedDateDetailsDTO.getChangedActualRepaymentDate();
|
||||
while (!nextRepaymentPeriodDueDate.isAfter(adjustedDateDetailsDTO.getChangedScheduleDate())) {
|
||||
while (!DateUtils.isAfter(nextRepaymentPeriodDueDate, adjustedDateDetailsDTO.getChangedScheduleDate())) {
|
||||
nextRepaymentPeriodDueDate = generateNextRepaymentDate(nextRepaymentPeriodDueDate, loanApplicationTerms,
|
||||
isFirstRepayment);
|
||||
}
|
||||
@@ -208,14 +209,13 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
.getRepaymentRescheduleType(holidayDetailDTO.getWorkingDays());
|
||||
|
||||
if (repaymentRescheduleType.isMoveToNextRepaymentDay()) {
|
||||
while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(),
|
||||
adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())
|
||||
|| adjustedDateDetailsDTO.getChangedScheduleDate()
|
||||
.isAfter(adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())) {
|
||||
final LocalDate nextRepaymentPeriodDueDate = generateNextRepaymentDate(
|
||||
adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(), loanApplicationTerms, isFirstRepayment);
|
||||
adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate);
|
||||
LocalDate nextRepaymentPeriodDueDate = adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate();
|
||||
while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), nextRepaymentPeriodDueDate)
|
||||
|| DateUtils.isAfter(adjustedDateDetailsDTO.getChangedScheduleDate(), nextRepaymentPeriodDueDate)) {
|
||||
nextRepaymentPeriodDueDate = generateNextRepaymentDate(nextRepaymentPeriodDueDate, loanApplicationTerms,
|
||||
isFirstRepayment);
|
||||
}
|
||||
adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate);
|
||||
}
|
||||
WorkingDaysUtil.updateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO.getWorkingDays());
|
||||
}
|
||||
@@ -260,7 +260,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
isScheduledDate = (weekDiff % repaidEvery) == 0;
|
||||
if (isScheduledDate) {
|
||||
LocalDate modifiedDate = startDate.plusWeeks(weekDiff);
|
||||
isScheduledDate = modifiedDate.isEqual(date);
|
||||
isScheduledDate = DateUtils.isEqual(modifiedDate, date);
|
||||
}
|
||||
break;
|
||||
case MONTHS:
|
||||
@@ -268,7 +268,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
isScheduledDate = (monthDiff % repaidEvery) == 0;
|
||||
if (isScheduledDate) {
|
||||
LocalDate modifiedDate = startDate.plusMonths(monthDiff);
|
||||
isScheduledDate = modifiedDate.isEqual(date);
|
||||
isScheduledDate = DateUtils.isEqual(modifiedDate, date);
|
||||
}
|
||||
break;
|
||||
case YEARS:
|
||||
@@ -276,7 +276,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
isScheduledDate = (yearDiff % repaidEvery) == 0;
|
||||
if (isScheduledDate) {
|
||||
LocalDate modifiedDate = startDate.plusYears(yearDiff);
|
||||
isScheduledDate = modifiedDate.isEqual(date);
|
||||
isScheduledDate = DateUtils.isEqual(modifiedDate, date);
|
||||
}
|
||||
break;
|
||||
case INVALID:
|
||||
@@ -332,7 +332,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
|
||||
LocalDate generatedDate = loanApplicationTerms.getExpectedDisbursementDate();
|
||||
boolean isFirstRepayment = true;
|
||||
while (!generatedDate.isAfter(lastRepaymentDate)) {
|
||||
while (!DateUtils.isAfter(generatedDate, lastRepaymentDate)) {
|
||||
generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment);
|
||||
isFirstRepayment = false;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
|
||||
isFirstRepayment = false;
|
||||
}
|
||||
LocalDate adjustedDate = generatedDate;
|
||||
while (!adjustedDate.isAfter(lastRepaymentDate)) {
|
||||
while (!DateUtils.isAfter(adjustedDate, lastRepaymentDate)) {
|
||||
generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment);
|
||||
adjustedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
|
||||
isFirstRepayment = false;
|
||||
|
||||
+21
-29
@@ -431,7 +431,7 @@ public class LoanScheduleAssembler {
|
||||
LoanTermVariationsData loanTermVariation = new LoanTermVariationsData(
|
||||
LoanEnumerations.loanVariationType(LoanTermVariationType.INTEREST_RATE), periodData.getFromDateAsLocalDate(),
|
||||
periodData.getInterestRate(), dateValue, isSpecificToInstallment);
|
||||
if (!interestRateStartDate.isBefore(periodData.getFromDateAsLocalDate())) {
|
||||
if (!DateUtils.isBefore(interestRateStartDate, periodData.getFromDateAsLocalDate())) {
|
||||
interestRateStartDate = periodData.getFromDateAsLocalDate();
|
||||
annualNominalInterestRate = periodData.getInterestRate();
|
||||
}
|
||||
@@ -753,7 +753,7 @@ public class LoanScheduleAssembler {
|
||||
LocalDate lastDate = loan.getExpectedDisbursedOnLocalDate();
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
dueDates.add(installment.getDueDate());
|
||||
if (lastDate.isBefore(installment.getDueDate())) {
|
||||
if (DateUtils.isBefore(lastDate, installment.getDueDate())) {
|
||||
lastDate = installment.getDueDate();
|
||||
}
|
||||
if (graceOnPrincipal.equals(installment.getInstallmentNumber())) {
|
||||
@@ -781,14 +781,14 @@ public class LoanScheduleAssembler {
|
||||
} else {
|
||||
dueDates.add(termVariations.fetchTermApplicaDate());
|
||||
}
|
||||
if (!graceApplicable.isBefore(termVariations.fetchTermApplicaDate())) {
|
||||
if (!DateUtils.isBefore(graceApplicable, termVariations.fetchTermApplicaDate())) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.insert.not.allowed.before.grace.period", "Loan schedule insert request invalid");
|
||||
}
|
||||
if (termVariations.fetchTermApplicaDate().isAfter(lastDate)) {
|
||||
if (DateUtils.isAfter(termVariations.fetchTermApplicaDate(), lastDate)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.insert.not.allowed.after.last.period.date", "Loan schedule insert request invalid");
|
||||
} else if (termVariations.fetchTermApplicaDate().isBefore(loan.getExpectedDisbursedOnLocalDate())) {
|
||||
} else if (DateUtils.isBefore(termVariations.fetchTermApplicaDate(), loan.getExpectedDisbursedOnLocalDate())) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.insert.not.allowed.before.disbursement.date", "Loan schedule insert request invalid");
|
||||
}
|
||||
@@ -800,14 +800,13 @@ public class LoanScheduleAssembler {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("variable.schedule.remove.date.invalid",
|
||||
"Loan schedule remove request invalid");
|
||||
}
|
||||
if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) {
|
||||
if (DateUtils.isEqual(lastDate, termVariations.fetchTermApplicaDate())) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.delete.not.allowed.for.last.period.date", "Loan schedule remove request invalid");
|
||||
}
|
||||
break;
|
||||
case DUE_DATE:
|
||||
if (dueDates.contains(termVariations.fetchTermApplicaDate())) {
|
||||
|
||||
if (overlappings.contains(termVariations.fetchTermApplicaDate())) {
|
||||
overlappings.remove(termVariations.fetchTermApplicaDate());
|
||||
} else {
|
||||
@@ -822,17 +821,17 @@ public class LoanScheduleAssembler {
|
||||
} else {
|
||||
dueDates.add(termVariations.fetchDateValue());
|
||||
}
|
||||
if (termVariations.fetchDateValue().isBefore(loan.getExpectedDisbursedOnLocalDate())) {
|
||||
if (DateUtils.isBefore(termVariations.fetchDateValue(), loan.getExpectedDisbursedOnLocalDate())) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.insert.not.allowed.before.disbursement.date", "Loan schedule insert request invalid");
|
||||
}
|
||||
if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) {
|
||||
if (DateUtils.isEqual(lastDate, termVariations.fetchTermApplicaDate())) {
|
||||
lastDate = termVariations.fetchDateValue();
|
||||
}
|
||||
break;
|
||||
case PRINCIPAL_AMOUNT:
|
||||
case EMI_AMOUNT:
|
||||
if (!graceApplicable.isBefore(termVariations.fetchTermApplicaDate())) {
|
||||
if (!DateUtils.isBefore(graceApplicable, termVariations.fetchTermApplicaDate())) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.amount.update.not.allowed.before.grace.period", "Loan schedule modify request invalid");
|
||||
}
|
||||
@@ -840,7 +839,7 @@ public class LoanScheduleAssembler {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.amount.update.from.date.invalid", "Loan schedule modify request invalid");
|
||||
}
|
||||
if (termVariations.fetchTermApplicaDate().isEqual(lastDate)) {
|
||||
if (DateUtils.isEqual(termVariations.fetchTermApplicaDate(), lastDate)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"variable.schedule.amount.update.not.allowed.for.last.period", "Loan schedule modify request invalid");
|
||||
}
|
||||
@@ -941,7 +940,7 @@ public class LoanScheduleAssembler {
|
||||
}
|
||||
if (dueDateVariations.containsKey(loanTermVariations.fetchTermApplicaDate())) {
|
||||
LoanTermVariations existingVariation = dueDateVariations.get(loanTermVariations.fetchTermApplicaDate());
|
||||
if (existingVariation.fetchTermApplicaDate().isEqual(loanTermVariations.fetchDateValue())) {
|
||||
if (DateUtils.isEqual(existingVariation.fetchTermApplicaDate(), loanTermVariations.fetchDateValue())) {
|
||||
variations.remove(existingVariation);
|
||||
} else {
|
||||
existingVariation.setTermApplicableFrom(loanTermVariations.getDateValue());
|
||||
@@ -1086,21 +1085,16 @@ public class LoanScheduleAssembler {
|
||||
final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType,
|
||||
final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar, final LocalDate submittedOnDate,
|
||||
final RepaymentStartDateType repaymentStartDateType) {
|
||||
|
||||
LocalDate derivedFirstRepayment = null;
|
||||
|
||||
final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = RepaymentStartDateType.DISBURSEMENT_DATE.equals(
|
||||
repaymentStartDateType) ? expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment) : submittedOnDate;
|
||||
|
||||
if (calendar != null) {
|
||||
|
||||
final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
|
||||
derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate,
|
||||
refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType,
|
||||
minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate, repaymentStartDateType);
|
||||
|
||||
} /*** Individual or group account, or JLG not linked to a meeting ***/
|
||||
else {
|
||||
derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, expectedDisbursementDate,
|
||||
repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate,
|
||||
repaymentStartDateType);
|
||||
} else { // Individual or group account, or JLG not linked to a meeting
|
||||
LocalDate dateBasedOnRepaymentFrequency;
|
||||
// Derive the first repayment date as greater date among
|
||||
// (disbursement date + plus frequency) or
|
||||
@@ -1121,16 +1115,15 @@ public class LoanScheduleAssembler {
|
||||
? expectedDisbursementDate.plusMonths(repaymentEvery)
|
||||
: submittedOnDate.plusMonths(repaymentEvery);
|
||||
|
||||
} /** yearly loan **/
|
||||
else {
|
||||
} else { // yearly loan
|
||||
dateBasedOnRepaymentFrequency = RepaymentStartDateType.DISBURSEMENT_DATE.equals(repaymentStartDateType)
|
||||
? expectedDisbursementDate.plusYears(repaymentEvery)
|
||||
: submittedOnDate.plusYears(repaymentEvery);
|
||||
|
||||
}
|
||||
derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment)
|
||||
? dateBasedOnRepaymentFrequency
|
||||
: dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment;
|
||||
derivedFirstRepayment = DateUtils.isAfter(dateBasedOnRepaymentFrequency,
|
||||
dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) ? dateBasedOnRepaymentFrequency
|
||||
: dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment;
|
||||
}
|
||||
|
||||
return derivedFirstRepayment;
|
||||
@@ -1148,7 +1141,7 @@ public class LoanScheduleAssembler {
|
||||
final LocalDate minimumFirstRepaymentDate = RepaymentStartDateType.DISBURSEMENT_DATE.equals(repaymentStartDateType)
|
||||
? expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment)
|
||||
: submittedOnDate;
|
||||
return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment
|
||||
return DateUtils.isBefore(minimumFirstRepaymentDate, derivedFirstRepayment) ? derivedFirstRepayment
|
||||
: deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, derivedFirstRepayment,
|
||||
repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar, submittedOnDate,
|
||||
repaymentStartDateType);
|
||||
@@ -1156,9 +1149,8 @@ public class LoanScheduleAssembler {
|
||||
|
||||
private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDate disbursalDate, final LocalDate firstRepaymentDate,
|
||||
final Integer minimumDaysBetweenDisbursalAndFirstRepayment) {
|
||||
|
||||
final LocalDate minimumFirstRepaymentDate = disbursalDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
|
||||
if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) {
|
||||
if (DateUtils.isBefore(firstRepaymentDate, minimumFirstRepaymentDate)) {
|
||||
throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(disbursalDate, firstRepaymentDate,
|
||||
minimumDaysBetweenDisbursalAndFirstRepayment);
|
||||
}
|
||||
|
||||
+4
-4
@@ -168,7 +168,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
||||
if (currentInstallment.isNotFullyPaidOff()) {
|
||||
if (!currentInstallment.getDueDate().isAfter(today)) {
|
||||
if (!DateUtils.isAfter(currentInstallment.getDueDate(), today)) {
|
||||
totalPrincipal = totalPrincipal.plus(currentInstallment.getPrincipalOutstanding(currency));
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
LoanScheduleData scheduleDate = model.toData();
|
||||
Collection<LoanSchedulePeriodData> periodDatas = scheduleDate.getPeriods();
|
||||
for (LoanSchedulePeriodData periodData : periodDatas) {
|
||||
if ((periodData.getDueDate().isEqual(today) || periodData.getDueDate().isAfter(today)) && isNewPaymentRequired) {
|
||||
if (isNewPaymentRequired && !DateUtils.isBefore(periodData.getDueDate(), today)) {
|
||||
LoanSchedulePeriodData loanSchedulePeriodData = LoanSchedulePeriodData.repaymentOnlyPeriod(periodData.getPeriod(),
|
||||
periodData.getFromDate(), periodData.getDueDate(), totalPrincipal.getAmount(),
|
||||
periodData.getPrincipalLoanBalanceOutstanding(), interestDue.getAmount(),
|
||||
@@ -199,7 +199,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
totalPrincipal.plus(interestDue).getAmount());
|
||||
futureInstallments.add(loanSchedulePeriodData);
|
||||
isNewPaymentRequired = false;
|
||||
} else if (periodData.getDueDate().isAfter(today)) {
|
||||
} else if (DateUtils.isAfter(periodData.getDueDate(), today)) {
|
||||
futureInstallments.add(periodData);
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (loanDisbursementDetails != null
|
||||
&& !loanDisbursementDetails.expectedDisbursementDateAsLocalDate().isAfter(installment.getDueDate())) {
|
||||
&& !DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), installment.getDueDate())) {
|
||||
outstanding = outstanding.plus(loanDisbursementDetails.principal());
|
||||
principal = principal.plus(loanDisbursementDetails.principal());
|
||||
if (disbursementItr.hasNext()) {
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule
|
||||
final BigDecimal penaltyCharges = repaymentScheduleInstallment.getPenaltyChargesCharged(currency).getAmount();
|
||||
|
||||
Map<String, Object> oldDates = null;
|
||||
OffsetDateTime createdOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
||||
OffsetDateTime createdOnDate = DateUtils.getAuditOffsetDateTime();
|
||||
LocalDateTime oldCreatedOnDate = null;
|
||||
LocalDateTime oldLastModifiedOnDate = null;
|
||||
if (repaymentScheduleInstallment.getCreatedDate().isPresent()) {
|
||||
@@ -89,7 +89,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule
|
||||
final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy()
|
||||
.orElse(platformSecurityContext.authenticatedUser().getId());
|
||||
|
||||
OffsetDateTime lastModifiedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
|
||||
OffsetDateTime lastModifiedOnDate = DateUtils.getAuditOffsetDateTime();
|
||||
if (repaymentScheduleInstallment.getLastModifiedDate().isPresent()) {
|
||||
lastModifiedOnDate = repaymentScheduleInstallment.getLastModifiedDate().get();
|
||||
} else if (repaymentScheduleInstallment.getId() != null && oldDates == null) {
|
||||
|
||||
+6
-5
@@ -38,6 +38,7 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||
@@ -105,7 +106,7 @@ public class LoanRescheduleRequestDataValidator {
|
||||
jsonElement);
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull();
|
||||
|
||||
if (submittedOnDate != null && loan.getDisbursementDate().isAfter(submittedOnDate)) {
|
||||
if (submittedOnDate != null && DateUtils.isAfter(loan.getDisbursementDate(), submittedOnDate)) {
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName)
|
||||
.failWithCode("before.loan.disbursement.date", "Submission date cannot be before the loan disbursement date");
|
||||
}
|
||||
@@ -161,7 +162,7 @@ public class LoanRescheduleRequestDataValidator {
|
||||
final LocalDate adjustedDueDate = this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.adjustedDueDateParamName,
|
||||
jsonElement);
|
||||
|
||||
if (adjustedDueDate != null && rescheduleFromDate != null && adjustedDueDate.isBefore(rescheduleFromDate)) {
|
||||
if (adjustedDueDate != null && DateUtils.isBefore(adjustedDueDate, rescheduleFromDate)) {
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).failWithCode(
|
||||
"adjustedDueDate.before.rescheduleFromDate", "Adjusted due date cannot be before the reschedule from date");
|
||||
}
|
||||
@@ -212,7 +213,7 @@ public class LoanRescheduleRequestDataValidator {
|
||||
LocalDate rescheduleFromDate = installment.getFromDate();
|
||||
Collection<LoanCharge> charges = loan.getLoanCharges();
|
||||
for (LoanCharge loanCharge : charges) {
|
||||
if (loanCharge.isOverdueInstallmentCharge() && loanCharge.getDueLocalDate().isAfter(rescheduleFromDate)) {
|
||||
if (loanCharge.isOverdueInstallmentCharge() && DateUtils.isAfter(loanCharge.getDueLocalDate(), rescheduleFromDate)) {
|
||||
dataValidatorBuilder.failWithCodeNoParameterAddedToErrorCode("not.allowed.due.to.overdue.charges");
|
||||
break;
|
||||
}
|
||||
@@ -247,7 +248,7 @@ public class LoanRescheduleRequestDataValidator {
|
||||
jsonElement);
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam).value(approvedOnDate).notNull();
|
||||
|
||||
if (approvedOnDate != null && loanRescheduleRequest.getSubmittedOnDate().isAfter(approvedOnDate)) {
|
||||
if (approvedOnDate != null && DateUtils.isAfter(loanRescheduleRequest.getSubmittedOnDate(), approvedOnDate)) {
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam).failWithCode("before.submission.date",
|
||||
"Approval date cannot be before the request submission date.");
|
||||
}
|
||||
@@ -319,7 +320,7 @@ public class LoanRescheduleRequestDataValidator {
|
||||
jsonElement);
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam).value(rejectedOnDate).notNull();
|
||||
|
||||
if (rejectedOnDate != null && loanRescheduleRequest.getSubmittedOnDate().isAfter(rejectedOnDate)) {
|
||||
if (rejectedOnDate != null && DateUtils.isAfter(loanRescheduleRequest.getSubmittedOnDate(), rejectedOnDate)) {
|
||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam).failWithCode("before.submission.date",
|
||||
"Rejection date cannot be before the request submission date.");
|
||||
}
|
||||
|
||||
+3
-2
@@ -24,6 +24,7 @@ import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
@@ -113,10 +114,10 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
|
||||
}
|
||||
|
||||
for (LoanTermVariationsData loanTermVariation : loanApplicationTerms.getLoanTermVariations().getDueDateVariation()) {
|
||||
if (rescheduleFromDate.isBefore(loanTermVariation.getTermVariationApplicableFrom())) {
|
||||
if (DateUtils.isBefore(rescheduleFromDate, loanTermVariation.getTermVariationApplicableFrom())) {
|
||||
LocalDate applicableDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(rescheduleFromDate,
|
||||
loanApplicationTerms, false);
|
||||
if (loanTermVariation.getTermVariationApplicableFrom().equals(applicableDate)) {
|
||||
if (DateUtils.isEqual(loanTermVariation.getTermVariationApplicableFrom(), applicableDate)) {
|
||||
LocalDate adjustedDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(adjustedApplicableDate,
|
||||
loanApplicationTerms, false);
|
||||
loanTermVariation.setApplicableFromDate(adjustedDate);
|
||||
|
||||
+5
-5
@@ -272,12 +272,12 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (installment.getDueDate().isEqual(rescheduleFromLocDate) || installment.getDueDate().isEqual(endDateLocDate)
|
||||
|| (installment.getDueDate().isAfter(rescheduleFromLocDate) && installment.getDueDate().isBefore(endDateLocDate))) {
|
||||
if (!DateUtils.isBefore(installment.getDueDate(), rescheduleFromLocDate)
|
||||
&& !DateUtils.isAfter(installment.getDueDate(), endDateLocDate)) {
|
||||
createLoanTermVariations(loanRescheduleRequest, termType, loan, installment.getDueDate(), installment.getDueDate(),
|
||||
loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
|
||||
}
|
||||
if (installment.getDueDate().isAfter(endDateLocDate)) {
|
||||
if (DateUtils.isAfter(installment.getDueDate(), endDateLocDate)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -394,8 +394,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
activeLoanTermVariation.markAsInactive();
|
||||
rescheduleFromDate = activeLoanTermVariation.fetchTermApplicaDate();
|
||||
dueDateVariationInCurrentRequest.setTermApplicableFrom(rescheduleFromDate);
|
||||
} else if (!activeLoanTermVariation.fetchTermApplicaDate().isBefore(fromScheduleDate)) {
|
||||
while (currentScheduleDate.isBefore(activeLoanTermVariation.fetchTermApplicaDate())) {
|
||||
} else if (!DateUtils.isBefore(activeLoanTermVariation.fetchTermApplicaDate(), fromScheduleDate)) {
|
||||
while (DateUtils.isBefore(currentScheduleDate, activeLoanTermVariation.fetchTermApplicaDate())) {
|
||||
currentScheduleDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(currentScheduleDate,
|
||||
loanApplicationTerms, false);
|
||||
modifiedScheduleDate = DEFAULT_SCHEDULED_DATE_GENERATOR.generateNextRepaymentDate(modifiedScheduleDate,
|
||||
|
||||
+2
-2
@@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -166,8 +167,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper {
|
||||
|
||||
private void validateRepaymentsStartingFromDateIsAfterDisbursementDate(final List<ApiParameterError> dataValidationErrors,
|
||||
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate) {
|
||||
if (expectedDisbursementDate != null && repaymentsStartingFromDate != null
|
||||
&& expectedDisbursementDate.isAfter(repaymentsStartingFromDate)) {
|
||||
if (repaymentsStartingFromDate != null && DateUtils.isAfter(expectedDisbursementDate, repaymentsStartingFromDate)) {
|
||||
final ApiParameterError error = ApiParameterError.parameterError(
|
||||
"validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date",
|
||||
"The parameter expectedDisbursementDate has a date which falls after the date for repaymentsStartingFromDate.",
|
||||
|
||||
+4
-3
@@ -41,6 +41,7 @@ import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
|
||||
@@ -1182,7 +1183,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
if (jsonObject2.has(LoanApiConstants.expectedDisbursementDateParameterName)) {
|
||||
LocalDate date2 = this.fromApiJsonHelper.extractLocalDateNamed(
|
||||
LoanApiConstants.expectedDisbursementDateParameterName, jsonObject2, dateFormat, locale);
|
||||
if (date1.isAfter(date2)) {
|
||||
if (DateUtils.isAfter(date1, date2)) {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.disbursementDataParameterName)
|
||||
.failWithCode(LoanApiConstants.DISBURSEMENT_DATES_NOT_IN_ORDER);
|
||||
}
|
||||
@@ -1196,7 +1197,6 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
|
||||
public void validateLoanMultiDisbursementDate(final JsonElement element, final DataValidatorBuilder baseDataValidator,
|
||||
LocalDate expectedDisbursement, BigDecimal totalPrincipal) {
|
||||
|
||||
this.validateDisbursementsAreDatewiseOrdered(element, baseDataValidator);
|
||||
|
||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||
@@ -1228,7 +1228,8 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
if (i == 0 && expectedDisbursementDate != null && !expectedDisbursement.equals(expectedDisbursementDate)) {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName)
|
||||
.failWithCode(LoanApiConstants.DISBURSEMENT_DATE_START_WITH_ERROR);
|
||||
} else if (i > 0 && expectedDisbursementDate != null && expectedDisbursementDate.isBefore(expectedDisbursement)) {
|
||||
} else if (i > 0 && expectedDisbursementDate != null
|
||||
&& DateUtils.isBefore(expectedDisbursementDate, expectedDisbursement)) {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.disbursementDataParameterName)
|
||||
.failWithCode(LoanApiConstants.DISBURSEMENT_DATE_BEFORE_ERROR);
|
||||
}
|
||||
|
||||
+22
-20
@@ -35,6 +35,7 @@ import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlat
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||
@@ -114,12 +115,12 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
loanWaiverTransactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
|
||||
}
|
||||
|
||||
if (accrualData.getDueDateAsLocaldate().isAfter(tillDate)) {
|
||||
if (DateUtils.isAfter(accrualData.getDueDateAsLocaldate(), tillDate)) {
|
||||
if (accruedTill == null || firstTime) {
|
||||
accruedTill = accrualData.getAccruedTill();
|
||||
firstTime = false;
|
||||
}
|
||||
if (accruedTill == null || accruedTill.isBefore(tillDate)) {
|
||||
if (accruedTill == null || DateUtils.isBefore(accruedTill, tillDate)) {
|
||||
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), tillDate);
|
||||
updateInterestIncome(accrualData, loanWaiverTransactionData, loanWaiverScheduleData, tillDate);
|
||||
addAccrualTillSpecificDate(tillDate, accrualData);
|
||||
@@ -135,9 +136,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
|
||||
private void addAccrualTillSpecificDate(final LocalDate tillDate, final LoanScheduleAccrualData accrualData) {
|
||||
LocalDate interestStartDate = accrualData.getFromDateAsLocaldate();
|
||||
if (accrualData.getInterestCalculatedFrom() != null
|
||||
&& accrualData.getFromDateAsLocaldate().isBefore(accrualData.getInterestCalculatedFrom())) {
|
||||
if (accrualData.getInterestCalculatedFrom().isBefore(accrualData.getDueDateAsLocaldate())) {
|
||||
if (DateUtils.isBefore(accrualData.getFromDateAsLocaldate(), accrualData.getInterestCalculatedFrom())) {
|
||||
if (DateUtils.isBefore(accrualData.getInterestCalculatedFrom(), accrualData.getDueDateAsLocaldate())) {
|
||||
interestStartDate = accrualData.getInterestCalculatedFrom();
|
||||
} else {
|
||||
interestStartDate = accrualData.getDueDateAsLocaldate();
|
||||
@@ -146,8 +146,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
|
||||
int totalNumberOfDays = Math.toIntExact(ChronoUnit.DAYS.between(interestStartDate, accrualData.getDueDateAsLocaldate()));
|
||||
LocalDate startDate = accrualData.getFromDateAsLocaldate();
|
||||
if (accrualData.getInterestCalculatedFrom() != null && startDate.isBefore(accrualData.getInterestCalculatedFrom())) {
|
||||
if (accrualData.getInterestCalculatedFrom().isBefore(tillDate)) {
|
||||
if (DateUtils.isBefore(startDate, accrualData.getInterestCalculatedFrom())) {
|
||||
if (DateUtils.isBefore(accrualData.getInterestCalculatedFrom(), tillDate)) {
|
||||
startDate = accrualData.getInterestCalculatedFrom();
|
||||
} else {
|
||||
startDate = tillDate;
|
||||
@@ -291,7 +291,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
scheduleAccrualData.getRepaymentScheduleId());
|
||||
|
||||
String updateLoan = "UPDATE m_loan SET accrued_till=?, last_modified_by=?, last_modified_on_utc=? WHERE id=?";
|
||||
this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
|
||||
this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getAuditOffsetDateTime(),
|
||||
scheduleAccrualData.getLoanId());
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAccrualTransactionCreatedBusinessEvent(loanTransaction));
|
||||
@@ -380,9 +380,10 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
LocalDate scheduleEndDate = accrualData.getDueDateAsLocaldate();
|
||||
for (LoanChargeData loanCharge : chargesData) {
|
||||
BigDecimal chargeAmount = BigDecimal.ZERO;
|
||||
if (((accrualData.getInstallmentNumber() == 1 && loanCharge.getSubmittedOnDate().isEqual(startDate)
|
||||
&& loanCharge.getDueDate().isEqual(startDate)) || loanCharge.getDueDate().isAfter(startDate))
|
||||
&& !loanCharge.getSubmittedOnDate().isAfter(endDate) && !loanCharge.getDueDate().isAfter(scheduleEndDate)) {
|
||||
if (((accrualData.getInstallmentNumber() == 1 && DateUtils.isEqual(startDate, loanCharge.getSubmittedOnDate())
|
||||
&& DateUtils.isEqual(startDate, loanCharge.getDueDate())) || DateUtils.isBefore(startDate, loanCharge.getDueDate()))
|
||||
&& !DateUtils.isBefore(endDate, loanCharge.getSubmittedOnDate())
|
||||
&& !DateUtils.isBefore(scheduleEndDate, loanCharge.getDueDate())) {
|
||||
chargeAmount = loanCharge.getAmount();
|
||||
if (loanCharge.getAmountUnrecognized() != null) {
|
||||
chargeAmount = chargeAmount.subtract(loanCharge.getAmountUnrecognized());
|
||||
@@ -424,7 +425,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
for (LoanChargeData loanCharge : chargesData) {
|
||||
BigDecimal chargeAmount = BigDecimal.ZERO;
|
||||
if (loanCharge.getDueDate() == null) {
|
||||
if (loanCharge.isInstallmentFee() && accrualData.getDueDateAsLocaldate().isEqual(endDate)) {
|
||||
if (loanCharge.isInstallmentFee() && DateUtils.isEqual(endDate, accrualData.getDueDateAsLocaldate())) {
|
||||
Collection<LoanInstallmentChargeData> installmentData = loanCharge.getInstallmentChargeData();
|
||||
for (LoanInstallmentChargeData installmentChargeData : installmentData) {
|
||||
|
||||
@@ -452,8 +453,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (((accrualData.getInstallmentNumber() == 1 && loanCharge.getDueDate().isEqual(startDate))
|
||||
|| loanCharge.getDueDate().isAfter(startDate)) && !loanCharge.getDueDate().isAfter(endDate)) {
|
||||
} else if (((accrualData.getInstallmentNumber() == 1 && DateUtils.isEqual(loanCharge.getDueDate(), startDate))
|
||||
|| DateUtils.isAfter(loanCharge.getDueDate(), startDate)) && !DateUtils.isAfter(loanCharge.getDueDate(), endDate)) {
|
||||
chargeAmount = loanCharge.getAmount();
|
||||
if (loanCharge.getAmountUnrecognized() != null) {
|
||||
chargeAmount = chargeAmount.subtract(loanCharge.getAmountUnrecognized());
|
||||
@@ -501,22 +502,23 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
|
||||
Collection<LoanTransactionData> loanTransactionDatas = new ArrayList<>();
|
||||
|
||||
for (LoanTransactionData loanTransactionData : loanWaiverTransactions) {
|
||||
if (!loanTransactionData.getDate().isAfter(accrualData.getFromDateAsLocaldate())
|
||||
|| (loanTransactionData.getDate().isAfter(accrualData.getFromDateAsLocaldate())
|
||||
&& !loanTransactionData.getDate().isAfter(accrualData.getDueDateAsLocaldate())
|
||||
&& !loanTransactionData.getDate().isAfter(tillDate))) {
|
||||
LocalDate transactionDate = loanTransactionData.getDate();
|
||||
if (!DateUtils.isAfter(transactionDate, accrualData.getFromDateAsLocaldate())
|
||||
|| (DateUtils.isAfter(transactionDate, accrualData.getFromDateAsLocaldate())
|
||||
&& !DateUtils.isAfter(transactionDate, accrualData.getDueDateAsLocaldate())
|
||||
&& !DateUtils.isAfter(transactionDate, tillDate))) {
|
||||
loanTransactionDatas.add(loanTransactionData);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<LoanTransactionData> iterator = loanTransactionDatas.iterator();
|
||||
for (LoanSchedulePeriodData loanSchedulePeriodData : loanSchedulePeriodDataList) {
|
||||
if (recognized.compareTo(BigDecimal.ZERO) <= 0 && unrecognized.compareTo(BigDecimal.ZERO) <= 0 && iterator.hasNext()) {
|
||||
if (MathUtil.isLessThanOrEqualZero(recognized) && MathUtil.isLessThanOrEqualZero(unrecognized) && iterator.hasNext()) {
|
||||
LoanTransactionData loanTransactionData = iterator.next();
|
||||
recognized = recognized.add(loanTransactionData.getInterestPortion());
|
||||
unrecognized = unrecognized.add(loanTransactionData.getUnrecognizedIncomePortion());
|
||||
}
|
||||
if (loanSchedulePeriodData.getDueDate().isBefore(accrualData.getDueDateAsLocaldate())) {
|
||||
if (DateUtils.isBefore(loanSchedulePeriodData.getDueDate(), accrualData.getDueDateAsLocaldate())) {
|
||||
remainingAmt = remainingAmt.add(loanSchedulePeriodData.getInterestWaived());
|
||||
if (recognized.compareTo(remainingAmt) > 0) {
|
||||
recognized = recognized.subtract(remainingAmt);
|
||||
|
||||
+9
-8
@@ -53,6 +53,7 @@ import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRu
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
|
||||
@@ -287,7 +288,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
"Topup on loan with multi-tranche disbursal and without interest recalculation is not supported.");
|
||||
}
|
||||
final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate();
|
||||
if (!newLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) {
|
||||
if (!DateUtils.isAfter(newLoanApplication.getSubmittedOnDate(), disbursalDateOfLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date",
|
||||
"Submitted date of this loan application " + newLoanApplication.getSubmittedOnDate()
|
||||
@@ -298,7 +299,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
"loanIdToClose is invalid, Currency code is different.");
|
||||
}
|
||||
final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
|
||||
if (newLoanApplication.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) {
|
||||
if (DateUtils.isBefore(newLoanApplication.getDisbursementDate(), lastUserTransactionOnLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||
"Disbursal date of this loan application " + newLoanApplication.getDisbursementDate()
|
||||
@@ -867,7 +868,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
"Topup on loan with multi-tranche disbursal and without interest recalculation is not supported.");
|
||||
}
|
||||
final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate();
|
||||
if (!existingLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) {
|
||||
if (!DateUtils.isAfter(existingLoanApplication.getSubmittedOnDate(), disbursalDateOfLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date",
|
||||
"Submitted date of this loan application " + existingLoanApplication.getSubmittedOnDate()
|
||||
@@ -878,7 +879,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
"loanIdToClose is invalid, Currency code is different.");
|
||||
}
|
||||
final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
|
||||
if (existingLoanApplication.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) {
|
||||
if (DateUtils.isBefore(existingLoanApplication.getDisbursementDate(), lastUserTransactionOnLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||
"Disbursal date of this loan application " + existingLoanApplication.getDisbursementDate()
|
||||
@@ -1380,7 +1381,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
}
|
||||
|
||||
final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
|
||||
if (loan.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) {
|
||||
if (DateUtils.isBefore(loan.getDisbursementDate(), lastUserTransactionOnLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||
"Disbursal date of this loan application " + loan.getDisbursementDate()
|
||||
@@ -1634,19 +1635,19 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final LocalDate submittedOnDate = loan.getSubmittedOnDate();
|
||||
|
||||
String defaultUserMessage = "";
|
||||
if (startDate != null && submittedOnDate.isBefore(startDate)) {
|
||||
if (DateUtils.isBefore(submittedOnDate, startDate)) {
|
||||
defaultUserMessage = "submittedOnDate cannot be before the loan product startDate.";
|
||||
throw new LoanApplicationDateException("submitted.on.date.cannot.be.before.the.loan.product.start.date", defaultUserMessage,
|
||||
submittedOnDate.toString(), startDate.toString());
|
||||
}
|
||||
|
||||
if (closeDate != null && submittedOnDate.isAfter(closeDate)) {
|
||||
if (closeDate != null && DateUtils.isAfter(submittedOnDate, closeDate)) {
|
||||
defaultUserMessage = "submittedOnDate cannot be after the loan product closeDate.";
|
||||
throw new LoanApplicationDateException("submitted.on.date.cannot.be.after.the.loan.product.close.date", defaultUserMessage,
|
||||
submittedOnDate.toString(), closeDate.toString());
|
||||
}
|
||||
|
||||
if (expectedFirstRepaymentOnDate != null && submittedOnDate.isAfter(expectedFirstRepaymentOnDate)) {
|
||||
if (expectedFirstRepaymentOnDate != null && DateUtils.isAfter(submittedOnDate, expectedFirstRepaymentOnDate)) {
|
||||
defaultUserMessage = "submittedOnDate cannot be after the loans expectedFirstRepaymentOnDate.";
|
||||
throw new LoanApplicationDateException("submitted.on.date.cannot.be.after.the.loan.expected.first.repayment.date",
|
||||
defaultUserMessage, submittedOnDate.toString(), expectedFirstRepaymentOnDate.toString());
|
||||
|
||||
+5
-4
@@ -32,6 +32,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
||||
@@ -145,12 +146,12 @@ public class LoanArrearsAgingServiceImpl implements LoanArrearsAgingService {
|
||||
LocalDate businessDate = DateUtils.getBusinessLocalDate();
|
||||
LocalDate overDueSince = businessDate;
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (installment.getDueDate().isBefore(businessDate)) {
|
||||
if (DateUtils.isBefore(installment.getDueDate(), businessDate)) {
|
||||
principalOverdue = principalOverdue.add(installment.getPrincipalOutstanding(loan.getCurrency()).getAmount());
|
||||
interestOverdue = interestOverdue.add(installment.getInterestOutstanding(loan.getCurrency()).getAmount());
|
||||
feeOverdue = feeOverdue.add(installment.getFeeChargesOutstanding(loan.getCurrency()).getAmount());
|
||||
penaltyOverdue = penaltyOverdue.add(installment.getPenaltyChargesOutstanding(loan.getCurrency()).getAmount());
|
||||
if (installment.isNotFullyPaidOff() && overDueSince.isAfter(installment.getDueDate())) {
|
||||
if (installment.isNotFullyPaidOff() && DateUtils.isAfter(overDueSince, installment.getDueDate())) {
|
||||
overDueSince = installment.getDueDate();
|
||||
}
|
||||
}
|
||||
@@ -208,8 +209,8 @@ public class LoanArrearsAgingServiceImpl implements LoanArrearsAgingService {
|
||||
.add(loanSchedulePeriodData.getFeeChargesDue().subtract(loanSchedulePeriodData.getFeeChargesPaid()));
|
||||
penaltyOverdue = penaltyOverdue
|
||||
.add(loanSchedulePeriodData.getPenaltyChargesDue().subtract(loanSchedulePeriodData.getPenaltyChargesPaid()));
|
||||
if (overDueSince.isAfter(loanSchedulePeriodData.getDueDate()) && loanSchedulePeriodData.getPrincipalDue()
|
||||
.subtract(loanSchedulePeriodData.getPrincipalPaid()).compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (DateUtils.isAfter(overDueSince, loanSchedulePeriodData.getDueDate()) && MathUtil
|
||||
.isGreaterThan(loanSchedulePeriodData.getPrincipalDue(), loanSchedulePeriodData.getPrincipalPaid())) {
|
||||
overDueSince = loanSchedulePeriodData.getDueDate();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -65,8 +65,7 @@ public class LoanCalculateRepaymentPastDueService {
|
||||
List<LoanRepaymentScheduleInstallment> loanRepayments = loan.getRepaymentScheduleInstallments();
|
||||
LocalDate currentBusinessDate = DateUtils.getBusinessLocalDate();
|
||||
return loanRepayments.stream()
|
||||
.filter((repayment) -> (!repayment.isObligationsMet()
|
||||
&& (repayment.getDueDate().isBefore(currentBusinessDate) || repayment.getDueDate().isEqual(currentBusinessDate))))
|
||||
.filter(repayment -> (!repayment.isObligationsMet() && !DateUtils.isAfter(repayment.getDueDate(), currentBusinessDate)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
@@ -301,7 +302,7 @@ public class LoanChargeAssembler {
|
||||
if (chargeDefinition.getChargeTimeType().equals(ChargeTimeType.SPECIFIED_DUE_DATE.getValue()) && loan.isMultiDisburmentLoan()) {
|
||||
amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!loanDisbursementDetails.expectedDisbursementDate().isAfter(dueDate)) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), dueDate)) {
|
||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal());
|
||||
}
|
||||
}
|
||||
|
||||
+16
-21
@@ -164,13 +164,12 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
|
||||
private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) {
|
||||
return e.getFromDate().isBefore(loanCharge.getDueDate()) && !loanCharge.getDueDate().isAfter(e.getDueDate());
|
||||
return DateUtils.isAfter(loanCharge.getDueDate(), e.getFromDate()) && !DateUtils.isAfter(loanCharge.getDueDate(), e.getDueDate());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) {
|
||||
|
||||
this.loanChargeApiJsonValidator.validateAddLoanCharge(command.json());
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
@@ -213,7 +212,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
validateAddLoanCharge(loan, chargeDefinition, loanCharge);
|
||||
addCharge(loan, chargeDefinition, loanCharge);
|
||||
isAppliedOnBackDate = true;
|
||||
if (recalculateFrom.isAfter(disbursementDetail.expectedDisbursementDateAsLocalDate())) {
|
||||
if (DateUtils.isAfter(recalculateFrom, disbursementDetail.expectedDisbursementDateAsLocalDate())) {
|
||||
recalculateFrom = disbursementDetail.expectedDisbursementDateAsLocalDate();
|
||||
}
|
||||
needToGenerateNewExternalId = true;
|
||||
@@ -231,7 +230,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
validateAddLoanCharge(loan, chargeDefinition, loanCharge);
|
||||
isAppliedOnBackDate = addCharge(loan, chargeDefinition, loanCharge);
|
||||
if (loanCharge.getDueLocalDate() == null || recalculateFrom.isAfter(loanCharge.getDueLocalDate())) {
|
||||
if (loanCharge.getDueLocalDate() == null || DateUtils.isAfter(recalculateFrom, loanCharge.getDueLocalDate())) {
|
||||
isAppliedOnBackDate = true;
|
||||
recalculateFrom = loanCharge.getDueLocalDate();
|
||||
}
|
||||
@@ -366,8 +365,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
throw new LoanChargeWaiveCannotBeReversedException(
|
||||
LoanChargeWaiveCannotBeReversedException.LoanChargeWaiveCannotUndoReason.LOAN_INACTIVE, loanCharge.getId());
|
||||
}
|
||||
if (loan.isChargedOff() && (loanTransaction.getTransactionDate().isBefore(loan.getChargedOffOnDate())
|
||||
|| loanTransaction.getTransactionDate().isEqual(loan.getChargedOffOnDate()))) {
|
||||
if (loan.isChargedOff() && !DateUtils.isAfter(loanTransaction.getTransactionDate(), loan.getChargedOffOnDate())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date",
|
||||
"Undo Loan transaction: " + loanTransaction.getId()
|
||||
+ " is not allowed before or on the date when the loan got charged-off",
|
||||
@@ -743,17 +741,17 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
overdueInstallment.getPeriodNumber(), command);
|
||||
loan = overdueDTO.getLoan();
|
||||
runInterestRecalculation = runInterestRecalculation || overdueDTO.isRunInterestRecalculation();
|
||||
if (recalculateFrom.isAfter(overdueDTO.getRecalculateFrom())) {
|
||||
if (DateUtils.isAfter(recalculateFrom, overdueDTO.getRecalculateFrom())) {
|
||||
recalculateFrom = overdueDTO.getRecalculateFrom();
|
||||
}
|
||||
if (lastChargeDate == null || overdueDTO.getLastChargeAppliedDate().isAfter(lastChargeDate)) {
|
||||
if (lastChargeDate == null || DateUtils.isAfter(overdueDTO.getLastChargeAppliedDate(), lastChargeDate)) {
|
||||
lastChargeDate = overdueDTO.getLastChargeAppliedDate();
|
||||
}
|
||||
}
|
||||
if (loan != null) {
|
||||
boolean reprocessRequired = true;
|
||||
LocalDate recalculatedTill = loan.fetchInterestRecalculateFromDate();
|
||||
if (recalculateFrom.isAfter(recalculatedTill)) {
|
||||
if (DateUtils.isAfter(recalculateFrom, recalculatedTill)) {
|
||||
recalculateFrom = recalculatedTill;
|
||||
}
|
||||
|
||||
@@ -946,12 +944,11 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null,
|
||||
chargeDefinition.getName());
|
||||
} else if (loanCharge.getDueLocalDate() != null
|
||||
&& loanCharge.getDueLocalDate().isBefore(loan.getLastUserTransactionForChargeCalc())) {
|
||||
&& DateUtils.isBefore(loanCharge.getDueLocalDate(), loan.getLastUserTransactionForChargeCalc())) {
|
||||
final String defaultUserMessage = "charge with date before last transaction date can not be added to loan.";
|
||||
throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.before.last.transaction.date", defaultUserMessage, null,
|
||||
chargeDefinition.getName());
|
||||
} else if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
|
||||
if (loanCharge.isInstalmentFee() && loan.getStatus().isActive()) {
|
||||
final String defaultUserMessage = "installment charge addition not allowed after disbursement";
|
||||
throw new LoanChargeCannotBeAddedException("loanCharge", "installment.charge", defaultUserMessage, null,
|
||||
@@ -986,7 +983,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
if (!loan.isInterestBearing() && loanCharge.isSpecifiedDueDate()) {
|
||||
LoanRepaymentScheduleInstallment latestRepaymentScheduleInstalment = loan.getRepaymentScheduleInstallments()
|
||||
.get(loan.getLoanRepaymentScheduleInstallmentsSize() - 1);
|
||||
if (loanCharge.getDueDate().isAfter(latestRepaymentScheduleInstalment.getDueDate())) {
|
||||
if (DateUtils.isAfter(loanCharge.getDueDate(), latestRepaymentScheduleInstalment.getDueDate())) {
|
||||
if (latestRepaymentScheduleInstalment.isAdditional()) {
|
||||
latestRepaymentScheduleInstalment.updateDueDate(loanCharge.getDueDate());
|
||||
} else {
|
||||
@@ -1003,15 +1000,13 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
loanCharge = this.loanChargeRepository.saveAndFlush(loanCharge);
|
||||
|
||||
/**
|
||||
* we want to apply charge transactions only for those loans charges that are applied when a loan is active and
|
||||
* the loan product uses Upfront Accruals
|
||||
**/
|
||||
// we want to apply charge transactions only for those loans charges that are applied when a loan is active and
|
||||
// the loan product uses Upfront Accruals
|
||||
if (loan.getStatus().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null);
|
||||
this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
|
||||
}
|
||||
return loanCharge.getDueLocalDate() == null || DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate());
|
||||
return DateUtils.isBeforeBusinessDate(loanCharge.getDueLocalDate());
|
||||
}
|
||||
|
||||
private LoanOverdueDTO applyChargeToOverdueLoanInstallment(final Loan loan, final Long loanChargeId, final Integer periodNumber,
|
||||
@@ -1037,7 +1032,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
if (feeFrequency == null) {
|
||||
scheduleDates.put(frequencyNumber++, startDate.minusDays(diff));
|
||||
} else {
|
||||
while (!startDate.isAfter(DateUtils.getBusinessLocalDate())) {
|
||||
while (!DateUtils.isDateInTheFuture(startDate)) {
|
||||
scheduleDates.put(frequencyNumber++, startDate.minusDays(diff));
|
||||
|
||||
startDate = scheduledDateGenerator.getRepaymentPeriodDate(PeriodFrequencyType.fromInt(feeFrequency),
|
||||
@@ -1070,10 +1065,10 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
boolean isAppliedOnBackDate = addCharge(loan, chargeDefinition, loanCharge);
|
||||
runInterestRecalculation = runInterestRecalculation || isAppliedOnBackDate;
|
||||
if (entry.getValue().isBefore(recalculateFrom)) {
|
||||
if (DateUtils.isBefore(entry.getValue(), recalculateFrom)) {
|
||||
recalculateFrom = entry.getValue();
|
||||
}
|
||||
if (entry.getValue().isAfter(lastChargeAppliedDate)) {
|
||||
if (DateUtils.isAfter(entry.getValue(), lastChargeAppliedDate)) {
|
||||
lastChargeAppliedDate = entry.getValue();
|
||||
}
|
||||
}
|
||||
@@ -1088,7 +1083,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
if (lastChargeDate != null) {
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
LoanRepaymentScheduleInstallment lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size());
|
||||
if (lastChargeDate.isAfter(lastInstallment.getDueDate())) {
|
||||
if (DateUtils.isAfter(lastChargeDate, lastInstallment.getDueDate())) {
|
||||
if (lastInstallment.isRecalculatedInterestComponent()) {
|
||||
installments.remove(lastInstallment);
|
||||
lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size());
|
||||
|
||||
+8
-7
@@ -1223,8 +1223,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
||||
disbursementPeriodIds.add(data.getId());
|
||||
} else if (data.isDueForDisbursement(fromDate, dueDate) && !disbursementPeriodIds.contains(data.getId())) {
|
||||
if (!excludePastUndisbursed || data.isDisbursed()
|
||||
|| !data.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) {
|
||||
if (!excludePastUndisbursed || data.isDisbursed() || !DateUtils.isBeforeBusinessDate(data.disbursementDate())) {
|
||||
principal = principal.add(data.getPrincipal());
|
||||
LoanSchedulePeriodData periodData;
|
||||
if (data.getChargeAmount() == null) {
|
||||
@@ -2385,12 +2384,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
final Collection<InterestRatePeriodData> intRates = this.floatingRatesReadPlatformService
|
||||
.retrieveInterestRatePeriods(loanData.getLoanProductId());
|
||||
for (final InterestRatePeriodData rate : intRates) {
|
||||
if (loanData.getTimeline() != null && rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) > 0
|
||||
&& loanData.isFloatingInterestRate()) {
|
||||
if (loanData.getTimeline() == null) {
|
||||
continue;
|
||||
}
|
||||
boolean isAfterDisbursement = DateUtils.isAfter(rate.getFromDate(), loanData.getTimeline().getDisbursementDate());
|
||||
if (isAfterDisbursement && loanData.isFloatingInterestRate()) {
|
||||
updateInterestRatePeriodData(rate, loanData);
|
||||
intRatePeriodData.add(rate);
|
||||
} else if (loanData.getTimeline() != null
|
||||
&& rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) <= 0) {
|
||||
} else if (!isAfterDisbursement) {
|
||||
updateInterestRatePeriodData(rate, loanData);
|
||||
intRatePeriodData.add(rate);
|
||||
break;
|
||||
@@ -2416,7 +2417,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
}
|
||||
rate.setEffectiveInterestRate(effectiveInterestRate);
|
||||
|
||||
if (loan.getTimeline() != null && rate.getFromDate().compareTo(loan.getTimeline().getDisbursementDate()) < 0) {
|
||||
if (loan.getTimeline() != null && DateUtils.isBefore(rate.getFromDate(), loan.getTimeline().getDisbursementDate())) {
|
||||
rate.setFromDate(loan.getTimeline().getDisbursementDate());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -281,7 +281,7 @@ public class LoanUtilService {
|
||||
isSkipRepaymentOnFirstMonth = isLoanRepaymentsSyncWithMeeting(loan.group(), historyList.get(0).getCalendar());
|
||||
}
|
||||
calculatedRepaymentsStartingFromDate = CalendarUtils.getNextRepaymentMeetingDate(historyList.get(0).getRecurrence(),
|
||||
historyList.get(0).getStartDateLocalDate(), actualDisbursementDate, repayEvery, frequency, workingDays,
|
||||
historyList.get(0).getStartDate(), actualDisbursementDate, repayEvery, frequency, workingDays,
|
||||
isSkipRepaymentOnFirstMonth, numberOfDays);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-19
@@ -291,7 +291,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||
|
||||
if (loan.isChargedOff() && actualDisbursementDate.isBefore(loan.getChargedOffOnDate())) {
|
||||
if (loan.isChargedOff() && DateUtils.isBefore(actualDisbursementDate, loan.getChargedOffOnDate())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||
+ loanId
|
||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||
@@ -405,7 +405,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
"Loan to be closed with this topup is not active.");
|
||||
}
|
||||
final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
|
||||
if (loan.getDisbursementDate().isBefore(lastUserTransactionOnLoanToClose)) {
|
||||
if (DateUtils.isBefore(loan.getDisbursementDate(), lastUserTransactionOnLoanToClose)) {
|
||||
throw new GeneralPlatformDomainRuleException(
|
||||
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||
"Disbursal date of this loan application " + loan.getDisbursementDate()
|
||||
@@ -1131,7 +1131,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LocalDate recalculateFrom = null;
|
||||
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
recalculateFrom = transactionToAdjust.getTransactionDate().isAfter(transactionDate) ? transactionDate
|
||||
recalculateFrom = DateUtils.isAfter(transactionToAdjust.getTransactionDate(), transactionDate) ? transactionDate
|
||||
: transactionToAdjust.getTransactionDate();
|
||||
}
|
||||
|
||||
@@ -1149,11 +1149,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
|
||||
}
|
||||
|
||||
/***
|
||||
/*
|
||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
||||
* time being, not a major issue for now as this loop is entered only in edge cases (when a adjustment is made
|
||||
* before the latest payment recorded against the loan)
|
||||
***/
|
||||
*/
|
||||
if (changedTransactionDetail != null) {
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
||||
@@ -1446,7 +1446,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
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: "
|
||||
+ loanId
|
||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||
@@ -1512,7 +1512,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
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: "
|
||||
+ loanId
|
||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||
@@ -2598,8 +2598,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private void checkIfLoanIsPaidInAdvance(final Long loanId, final BigDecimal transactionAmount) {
|
||||
BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance();
|
||||
|
||||
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE
|
||||
: Boolean.FALSE || transactionAmount.floatValue() > overpaid.floatValue()) {
|
||||
if (overpaid == null || overpaid.compareTo(BigDecimal.ZERO) == 0 || transactionAmount.floatValue() > overpaid.floatValue()) {
|
||||
if (overpaid == null) {
|
||||
overpaid = BigDecimal.ZERO;
|
||||
}
|
||||
@@ -2685,7 +2684,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
String noteText = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParamName, element);
|
||||
LoanRescheduleRequest loanRescheduleRequest = null;
|
||||
for (LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!loanDisbursementDetails.expectedDisbursementDateAsLocalDate().isAfter(transactionDate)
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), transactionDate)
|
||||
&& loanDisbursementDetails.actualDisbursementDate() == null) {
|
||||
final String defaultUserMessage = "The loan with undisbursed tranche before foreclosure cannot be foreclosed.";
|
||||
throw new LoanForeclosureException("loan.with.undisbursed.tranche.before.foreclosure.cannot.be.foreclosured",
|
||||
@@ -2732,12 +2731,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.is.already.charged.off",
|
||||
"Loan: " + loanId + " is already charged-off", loanId);
|
||||
}
|
||||
if (transactionDate.isBefore(loan.getLastUserTransactionDate())) {
|
||||
if (DateUtils.isBefore(transactionDate, loan.getLastUserTransactionDate())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.charge.off.is.before.than.the.last.user.transaction",
|
||||
"Loan: " + loanId + " charge-off cannot be executed. User transaction was found after the charge-off transaction date!",
|
||||
loanId);
|
||||
}
|
||||
if (transactionDate.isAfter(DateUtils.getBusinessLocalDate())) {
|
||||
if (DateUtils.isDateInTheFuture(transactionDate)) {
|
||||
final String errorMessage = "The transaction date cannot be in the future.";
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.cannot.be.a.future.date", errorMessage,
|
||||
transactionDate);
|
||||
@@ -2848,27 +2847,23 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final String errorMessage = "tranches.should.be.disbursed.more.than.one.to.undo.last.disbursal";
|
||||
throw new LoanMultiDisbursementException(errorMessage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void syncExpectedDateWithActualDisbursementDate(final Loan loan, LocalDate actualDisbursementDate) {
|
||||
if (!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)) {
|
||||
throw new DateMismatchException(actualDisbursementDate, loan.getExpectedDisbursedOnLocalDate());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void validateTransactionsForTransfer(final Loan loan, final LocalDate transferDate) {
|
||||
|
||||
for (LoanTransaction transaction : loan.getLoanTransactions()) {
|
||||
if ((transaction.getTransactionDate().isEqual(transferDate) && transaction.getSubmittedOnDate().isEqual(transferDate))
|
||||
|| transaction.getTransactionDate().isAfter(transferDate)) {
|
||||
if ((DateUtils.isEqual(transferDate, transaction.getTransactionDate())
|
||||
&& DateUtils.isEqual(transferDate, transaction.getSubmittedOnDate()))
|
||||
|| DateUtils.isBefore(transferDate, transaction.getTransactionDate())) {
|
||||
throw new GeneralPlatformDomainRuleException(TransferApiConstants.transferClientLoanException,
|
||||
TransferApiConstants.transferClientLoanExceptionMessage, transaction.getCreatedDateTime().toLocalDate(),
|
||||
transferDate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -369,7 +369,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final boolean enableInstallmentLevelDelinquency = rs.getBoolean("enableInstallmentLevelDelinquency");
|
||||
|
||||
String status = "";
|
||||
if (closeDate != null && closeDate.isBefore(DateUtils.getBusinessLocalDate())) {
|
||||
if (closeDate != null && DateUtils.isBeforeBusinessDate(closeDate)) {
|
||||
status = "loanProduct.inActive";
|
||||
} else {
|
||||
status = "loanProduct.active";
|
||||
|
||||
+3
-4
@@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.entityaccess.domain.FineractEntityAccessType;
|
||||
import org.apache.fineract.infrastructure.entityaccess.service.FineractEntityAccessUtil;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.product.LoanProductCreateBusinessEvent;
|
||||
@@ -369,10 +370,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
|
||||
final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate");
|
||||
|
||||
if (startDate != null && closeDate != null) {
|
||||
if (closeDate.isBefore(startDate)) {
|
||||
throw new LoanProductDateException(startDate.toString(), closeDate.toString());
|
||||
}
|
||||
if (closeDate != null && DateUtils.isBefore(closeDate, startDate)) {
|
||||
throw new LoanProductDateException(startDate.toString(), closeDate.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -167,7 +167,7 @@ public class Meeting extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public boolean isMeetingDateBefore(final LocalDate newStartDate) {
|
||||
return this.meetingDate != null && newStartDate != null && getMeetingDateLocalDate().isBefore(newStartDate) ? true : false;
|
||||
return this.meetingDate != null && DateUtils.isBefore(getMeetingDateLocalDate(), newStartDate);
|
||||
}
|
||||
|
||||
private static boolean isValidMeetingDate(final CalendarInstance calendarInstance, final LocalDate meetingDate,
|
||||
@@ -181,7 +181,7 @@ public class Meeting extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private boolean isMeetingDateAfter(final LocalDate date) {
|
||||
return getMeetingDateLocalDate().isAfter(date);
|
||||
return DateUtils.isAfter(getMeetingDateLocalDate(), date);
|
||||
}
|
||||
|
||||
public Collection<ClientAttendance> getClientsAttendance() {
|
||||
|
||||
+12
-12
@@ -36,18 +36,18 @@ public class SearchConditions {
|
||||
this.searchQuery = searchQueryParam;
|
||||
this.searchResource = searchResource;
|
||||
this.exactMatch = exactMatch;
|
||||
this.clientSearch = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTS.name().toLowerCase())) ? true : false;
|
||||
this.groupSearch = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.GROUPS.name().toLowerCase())) ? true : false;
|
||||
this.loanSeach = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.LOANS.name().toLowerCase())) ? true : false;
|
||||
this.savingSeach = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SAVINGS.name().toLowerCase())) ? true : false;
|
||||
this.shareSeach = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SHARES.name().toLowerCase())) ? true : false;
|
||||
this.clientIdentifierSearch = (null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTIDENTIFIERS.name().toLowerCase())) ? true : false;
|
||||
this.clientSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTS.name().toLowerCase());
|
||||
this.groupSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.GROUPS.name().toLowerCase());
|
||||
this.loanSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.LOANS.name().toLowerCase());
|
||||
this.savingSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SAVINGS.name().toLowerCase());
|
||||
this.shareSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SHARES.name().toLowerCase());
|
||||
this.clientIdentifierSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTIDENTIFIERS.name().toLowerCase());
|
||||
}
|
||||
|
||||
public SearchConditions(final String searchQueryParam, final String searchResource, final Boolean clientSearch,
|
||||
|
||||
+1
-3
@@ -54,10 +54,8 @@ public class AccountEntityServiceForSavingsImpl implements AccountEntityService
|
||||
|
||||
@Override
|
||||
public void validateSelfUserAccountMapping(Long accountId) {
|
||||
|
||||
if (!this.appuserSavingsMapperReadService.isSavingsMappedToUser(accountId, this.context.getAuthenticatedUserIfPresent().getId())) {
|
||||
if (!this.appuserSavingsMapperReadService.isSavingsMappedToUser(accountId, this.context.authenticatedUser().getId())) {
|
||||
throw new SavingsAccountNotFoundException(accountId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -53,9 +53,8 @@ public class AccountEntityServiceForShareAccountsImpl implements AccountEntitySe
|
||||
@Override
|
||||
public void validateSelfUserAccountMapping(Long accountId) {
|
||||
if (!this.appUserShareAccountsMapperReadPlatformService.isShareAccountsMappedToUser(accountId,
|
||||
this.context.getAuthenticatedUserIfPresent().getId())) {
|
||||
this.context.authenticatedUser().getId())) {
|
||||
throw new ShareAccountNotFoundException(accountId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -36,6 +36,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
@@ -209,7 +210,7 @@ public class ShareAccount extends AbstractPersistableCustom {
|
||||
|
||||
public boolean setSubmittedDate(final LocalDate submittedDate) {
|
||||
boolean toReturn = false;
|
||||
if (this.submittedDate.compareTo(submittedDate) == 0 ? Boolean.FALSE : Boolean.TRUE) {
|
||||
if (!DateUtils.isEqual(submittedDate, this.submittedDate)) {
|
||||
this.submittedDate = submittedDate;
|
||||
toReturn = true;
|
||||
}
|
||||
@@ -218,7 +219,7 @@ public class ShareAccount extends AbstractPersistableCustom {
|
||||
|
||||
public boolean setApprovedDate(final LocalDate approvedDate) {
|
||||
boolean toReturn = false;
|
||||
if (this.approvedDate.compareTo(approvedDate) == 0 ? Boolean.FALSE : Boolean.TRUE) {
|
||||
if (!DateUtils.isEqual(approvedDate, this.approvedDate)) {
|
||||
this.approvedDate = approvedDate;
|
||||
toReturn = true;
|
||||
}
|
||||
@@ -514,11 +515,11 @@ public class ShareAccount extends AbstractPersistableCustom {
|
||||
public ShareAccountTransaction getShareAccountTransaction(final ShareAccountTransaction transaction) {
|
||||
ShareAccountTransaction returnTrans = null;
|
||||
for (ShareAccountTransaction tran : this.shareAccountTransactions) {
|
||||
if (tran.getPurchasedDate().compareTo(transaction.getPurchasedDate()) == 0 ? Boolean.TRUE
|
||||
: Boolean.FALSE && tran.getTotalShares().equals(transaction.getTotalShares())
|
||||
&& tran.getPurchasePrice().compareTo(transaction.getPurchasePrice()) == 0 ? Boolean.TRUE
|
||||
: Boolean.FALSE && tran.getTransactionStatus().equals(transaction.getTransactionStatus())
|
||||
&& tran.getTransactionType().equals(transaction.getTransactionType())) {
|
||||
if (DateUtils.isEqual(tran.getPurchasedDate(), transaction.getPurchasedDate())
|
||||
&& tran.getTotalShares().equals(transaction.getTotalShares())
|
||||
&& tran.getPurchasePrice().compareTo(transaction.getPurchasePrice()) == 0
|
||||
&& tran.getTransactionStatus().equals(transaction.getTransactionStatus())
|
||||
&& tran.getTransactionType().equals(transaction.getTransactionType())) {
|
||||
returnTrans = tran;
|
||||
break;
|
||||
}
|
||||
|
||||
+9
-9
@@ -469,7 +469,7 @@ public class ShareAccountDataSerializer {
|
||||
}
|
||||
LocalDate approvedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.approveddate_paramname, element);
|
||||
final LocalDate submittalDate = account.getSubmittedDate();
|
||||
if (approvedDate != null && approvedDate.isBefore(submittalDate)) {
|
||||
if (approvedDate != null && DateUtils.isBefore(approvedDate, submittalDate)) {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonCommand.dateFormat())
|
||||
.withLocale(jsonCommand.extractLocale());
|
||||
final String submittalDateAsString = formatter.format(submittalDate);
|
||||
@@ -610,7 +610,7 @@ public class ShareAccountDataSerializer {
|
||||
LocalDate activatedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.activatedate_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(activatedDate).notNull();
|
||||
final LocalDate approvedDate = account.getApprovedDate();
|
||||
if (activatedDate != null && activatedDate.isBefore(approvedDate)) {
|
||||
if (activatedDate != null && DateUtils.isBefore(activatedDate, approvedDate)) {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonCommand.dateFormat())
|
||||
.withLocale(jsonCommand.extractLocale());
|
||||
final String submittalDateAsString = formatter.format(approvedDate);
|
||||
@@ -710,7 +710,7 @@ public class ShareAccountDataSerializer {
|
||||
for (ShareAccountTransaction transaction : transactions) {
|
||||
if (!transaction.isChargeTransaction()) {
|
||||
LocalDate transactionDate = transaction.getPurchasedDate();
|
||||
if (requestedDate.isBefore(transactionDate)) {
|
||||
if (DateUtils.isBefore(requestedDate, transactionDate)) {
|
||||
isTransactionBeforeExistingTransactions = true;
|
||||
break;
|
||||
}
|
||||
@@ -867,7 +867,7 @@ public class ShareAccountDataSerializer {
|
||||
for (ShareAccountTransaction transaction : transactions) {
|
||||
if (!transaction.isChargeTransaction() && transaction.isActive()) {
|
||||
LocalDate transactionDate = transaction.getPurchasedDate();
|
||||
if (requestedDate.isBefore(transactionDate)) {
|
||||
if (DateUtils.isBefore(requestedDate, transactionDate)) {
|
||||
isTransactionBeforeExistingTransactions = true;
|
||||
break;
|
||||
}
|
||||
@@ -908,8 +908,8 @@ public class ShareAccountDataSerializer {
|
||||
if (lockinPeriod == null && periodType == null) {
|
||||
return;
|
||||
}
|
||||
Long totalSharesCanBeRedeemed = Long.valueOf(0);
|
||||
Long totalSharesPurchasedBeforeRedeem = Long.valueOf(0);
|
||||
Long totalSharesCanBeRedeemed = 0L;
|
||||
Long totalSharesPurchasedBeforeRedeem = 0L;
|
||||
boolean isPurchaseTransactionExist = false;
|
||||
|
||||
Set<ShareAccountTransaction> transactions = account.getShareAccountTransactions();
|
||||
@@ -917,7 +917,7 @@ public class ShareAccountDataSerializer {
|
||||
if (transaction.isActive() && !transaction.isChargeTransaction()) {
|
||||
LocalDate purchaseDate = transaction.getPurchasedDate();
|
||||
LocalDate lockinDate = deriveLockinPeriodDuration(lockinPeriod, periodType, purchaseDate);
|
||||
if (!lockinDate.isAfter(redeemDate)) {
|
||||
if (!DateUtils.isAfter(lockinDate, redeemDate)) {
|
||||
if (transaction.isPurchasTransaction()) {
|
||||
totalSharesCanBeRedeemed += transaction.getTotalShares();
|
||||
} else if (transaction.isRedeemTransaction()) {
|
||||
@@ -925,7 +925,7 @@ public class ShareAccountDataSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
if (!purchaseDate.isAfter(redeemDate)) {
|
||||
if (!DateUtils.isAfter(purchaseDate, redeemDate)) {
|
||||
isPurchaseTransactionExist = true;
|
||||
if (transaction.isPurchasTransaction()) {
|
||||
totalSharesPurchasedBeforeRedeem += transaction.getTotalShares();
|
||||
@@ -1022,7 +1022,7 @@ public class ShareAccountDataSerializer {
|
||||
for (ShareAccountTransaction transaction : transactions) {
|
||||
if (!transaction.isChargeTransaction()) {
|
||||
LocalDate transactionDate = transaction.getPurchasedDate();
|
||||
if (closedDate.isBefore(transactionDate)) {
|
||||
if (DateUtils.isBefore(closedDate, transactionDate)) {
|
||||
isTransactionBeforeExistingTransactions = true;
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-2
@@ -140,8 +140,8 @@ public class ShareAccountReadPlatformServiceImpl implements ShareAccountReadPlat
|
||||
if (marketDataSet != null && !marketDataSet.isEmpty()) {
|
||||
LocalDate currentDate = DateUtils.getBusinessLocalDate();
|
||||
for (ShareProductMarketPriceData data : marketDataSet) {
|
||||
LocalDate futureDate = data.getFromDate();
|
||||
if (currentDate.isAfter(futureDate)) {
|
||||
LocalDate fromDate = data.getFromDate();
|
||||
if (DateUtils.isBefore(fromDate, currentDate)) {
|
||||
marketValue = data.getShareValue();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
|
||||
|
||||
private Map<String, Object> populateJournalEntries(final ShareAccount account, final Set<ShareAccountTransaction> transactions) {
|
||||
final Map<String, Object> accountingBridgeData = new HashMap<>();
|
||||
Boolean cashBasedAccounting = account.getShareProduct().getAccountingType() == 2 ? Boolean.TRUE : Boolean.FALSE;
|
||||
Boolean cashBasedAccounting = account.getShareProduct().getAccountingType() == 2;
|
||||
accountingBridgeData.put("cashBasedAccountingEnabled", cashBasedAccounting);
|
||||
accountingBridgeData.put("accrualBasedAccountingEnabled", Boolean.FALSE);
|
||||
accountingBridgeData.put("shareAccountId", account.getId());
|
||||
|
||||
+5
-5
@@ -237,7 +237,7 @@ public class ShareProduct extends AbstractAuditableCustom {
|
||||
|
||||
public boolean setUnitPrice(BigDecimal unitPrice) {
|
||||
boolean returnValue = false;
|
||||
if (this.unitPrice.compareTo(unitPrice) == 0 ? Boolean.FALSE : Boolean.TRUE) {
|
||||
if (this.unitPrice.compareTo(unitPrice) != 0) {
|
||||
this.unitPrice = unitPrice;
|
||||
returnValue = true;
|
||||
}
|
||||
@@ -353,7 +353,7 @@ public class ShareProduct extends AbstractAuditableCustom {
|
||||
|
||||
public boolean setshareCapitalValue(BigDecimal shareCapitalValue) {
|
||||
boolean updated = false;
|
||||
if (this.shareCapital == null || this.shareCapital.compareTo(shareCapitalValue) == 0 ? Boolean.FALSE : Boolean.TRUE) {
|
||||
if (this.shareCapital == null || this.shareCapital.compareTo(shareCapitalValue) != 0) {
|
||||
this.shareCapital = shareCapitalValue;
|
||||
updated = true;
|
||||
}
|
||||
@@ -395,8 +395,8 @@ public class ShareProduct extends AbstractAuditableCustom {
|
||||
BigDecimal marketValue = this.unitPrice;
|
||||
if (this.marketPrice != null && !this.marketPrice.isEmpty()) {
|
||||
for (ShareProductMarketPrice data : this.marketPrice) {
|
||||
LocalDate futureDate = data.getStartDate();
|
||||
if (currentDate.compareTo(futureDate) == 0 ? Boolean.TRUE : Boolean.FALSE || currentDate.isAfter(futureDate)) {
|
||||
LocalDate startDate = data.getStartDate();
|
||||
if (!DateUtils.isAfter(startDate, currentDate)) {
|
||||
marketValue = data.getPrice();
|
||||
}
|
||||
}
|
||||
@@ -406,7 +406,7 @@ public class ShareProduct extends AbstractAuditableCustom {
|
||||
|
||||
public void addSubscribedShares(final Long subscribedShares) {
|
||||
if (this.totalSubscribedShares == null) {
|
||||
this.totalSubscribedShares = Long.valueOf(0);
|
||||
this.totalSubscribedShares = 0L;
|
||||
}
|
||||
this.totalSubscribedShares += subscribedShares;
|
||||
}
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.products.service.ShareProductReadPlatformService;
|
||||
@@ -106,7 +107,7 @@ public class ShareProductDividendAssembler {
|
||||
if (status.isApproved() && !type.isChargePayment()) {
|
||||
|
||||
LocalDate shareStartDate = purchasedSharesData.getPurchasedDate();
|
||||
if (shareStartDate.isBefore(lastDividendPostDate)) {
|
||||
if (DateUtils.isBefore(shareStartDate, lastDividendPostDate)) {
|
||||
shareStartDate = lastDividendPostDate;
|
||||
}
|
||||
int numberOfPurchseDays = Math.toIntExact(ChronoUnit.DAYS.between(shareStartDate, postingDate));
|
||||
|
||||
+2
-2
@@ -282,7 +282,7 @@ public class TaxValidator {
|
||||
for (TaxGroupMappings mapping : groupMappings) {
|
||||
if (mapping.getId() != null) {
|
||||
TaxGroupMappings existing = taxGroup.findOneBy(mapping);
|
||||
if (existing.endDate() != null && mapping.endDate() != null && !existing.endDate().isEqual(mapping.endDate())) {
|
||||
if (existing.endDate() != null && mapping.endDate() != null && !DateUtils.isEqual(existing.endDate(), mapping.endDate())) {
|
||||
baseDataValidator.reset().parameter(TaxApiConstants.endDateParamName)
|
||||
.failWithCode("can.not.modify.end.date.once.updated");
|
||||
} else {
|
||||
@@ -335,7 +335,7 @@ public class TaxValidator {
|
||||
if (groupMappingsOne.getTaxComponent().equals(groupMappings.getTaxComponent())) {
|
||||
if (groupMappingsOne.endDate() == null && groupMappings.endDate() == null) {
|
||||
baseDataValidator.reset().parameter(COMPONENT).failWithCode(DATES_ARE_OVERLAPPING);
|
||||
} else if (groupMappingsOne.startDate().isAfter(groupMappings.startDate())) {
|
||||
} else if (DateUtils.isAfter(groupMappingsOne.startDate(), groupMappings.startDate())) {
|
||||
baseDataValidator.reset().parameter(COMPONENT_START_DATE).value(groupMappingsOne.startDate())
|
||||
.validateDateAfter(groupMappings.endDate());
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class PurgeProcessedCommandsTaskletTest {
|
||||
// then
|
||||
verify(repository, times(1)).deleteOlderEventsWithStatus(Mockito.any(), Mockito.any());
|
||||
verify(repository).deleteOlderEventsWithStatus(Mockito.any(), dateCriteriaCaptor.capture());
|
||||
OffsetDateTime expectedDateForPurgeCriteriaTest = DateUtils.getOffsetDateTimeOfTenant().minusDays(2);
|
||||
OffsetDateTime expectedDateForPurgeCriteriaTest = DateUtils.getAuditOffsetDateTime().minusDays(2);
|
||||
OffsetDateTime actualDateForPurgeCriteria = dateCriteriaCaptor.getValue();
|
||||
assertTrue(expectedDateForPurgeCriteriaTest.toEpochSecond() - actualDateForPurgeCriteria.toEpochSecond() <= 1);
|
||||
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
||||
|
||||
+65
@@ -26,10 +26,13 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
||||
@@ -170,6 +173,68 @@ public class LoanTest {
|
||||
assertEquals(loanTransaction2, userTransaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link Loan#getLastUserTransaction()} where there are user transactions
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionComparator() {
|
||||
final Loan loan = new Loan();
|
||||
LocalDate today = LocalDate.of(2023, 10, 12);
|
||||
OffsetDateTime now = DateUtils.getAuditOffsetDateTime();
|
||||
|
||||
LoanTransaction lt1 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt1, "id", 1L);
|
||||
ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT.getValue());
|
||||
ReflectionTestUtils.setField(lt1, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt1, "createdDate", now);
|
||||
LoanTransaction lt2 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt2, "id", 2L);
|
||||
ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt2, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt2, "createdDate", now);
|
||||
LoanTransaction lt3 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt3, "id", 3L);
|
||||
ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT.getValue());
|
||||
ReflectionTestUtils.setField(lt3, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt3, "createdDate", now);
|
||||
ReflectionTestUtils.setField(lt3, "reversed", true);
|
||||
LoanTransaction lt4 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt4, "id", 4L);
|
||||
ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST.getValue());
|
||||
ReflectionTestUtils.setField(lt4, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt4, "createdDate", now);
|
||||
LoanTransaction lt5 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt5, "id", 5L);
|
||||
ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING.getValue());
|
||||
ReflectionTestUtils.setField(lt5, "dateOf", today);
|
||||
ReflectionTestUtils.setField(lt5, "createdDate", now);
|
||||
LoanTransaction lt6 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt6, "dateOf", today.minusDays(2));
|
||||
LoanTransaction lt7 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt7, "id", 7L);
|
||||
ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt7, "dateOf", today.minusDays(2));
|
||||
LoanTransaction lt8 = new LoanTransaction();
|
||||
ReflectionTestUtils.setField(lt8, "id", 8L);
|
||||
ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
ReflectionTestUtils.setField(lt8, "dateOf", today.minusDays(2));
|
||||
ReflectionTestUtils.setField(lt8, "createdDate", now.minusMinutes(2));
|
||||
|
||||
List<LoanTransaction> transactions = Arrays.asList(lt1, lt2, lt3, lt4, lt5, lt6, lt7, lt8);
|
||||
transactions.sort(LoanTransactionComparator.INSTANCE);
|
||||
|
||||
assertEquals(8L, transactions.get(0).getId());
|
||||
assertEquals(7L, transactions.get(1).getId());
|
||||
assertNull(transactions.get(2).getId());
|
||||
assertEquals(today.minusDays(2), transactions.get(2).getTransactionDate());
|
||||
assertEquals(5L, transactions.get(3).getId());
|
||||
assertEquals(4L, transactions.get(4).getId());
|
||||
assertEquals(1L, transactions.get(5).getId());
|
||||
assertEquals(2L, transactions.get(6).getId());
|
||||
assertEquals(3L, transactions.get(7).getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new loan charge.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user