based on meeting start date change reschedule future repayments of all attached loans

This commit is contained in:
ashok-conflux
2013-06-26 19:11:32 +05:30
parent 5fa55031c1
commit 1a694096af
15 changed files with 265 additions and 51 deletions
@@ -0,0 +1 @@
INSERT INTO `c_configuration` (`name`, `enabled`) VALUES ('reschedule-future-repayments', 1);
@@ -9,4 +9,5 @@ public interface ConfigurationDomainService {
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
boolean isAmazonS3Enabled();
boolean isRescheduleFutureRepaymentsEnabled();
}
@@ -44,4 +44,13 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
public boolean isAmazonS3Enabled(){
return this.globalConfigurationRepository.findOneByName("amazon-S3").isEnabled();
}
@Override
public boolean isRescheduleFutureRepaymentsEnabled() {
final String rescheduleRepaymentsConfigurationProperty = "reschedule-future-repayments";
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByName(rescheduleRepaymentsConfigurationProperty);
if (property == null) { throw new GlobalConfigurationPropertyNotFoundException(rescheduleRepaymentsConfigurationProperty); }
return property.isEnabled();
}
}
@@ -21,6 +21,9 @@ import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.portfolio.calendar.CalendarConstants.CALENDAR_SUPPORTED_PARAMETERS;
import org.mifosplatform.portfolio.calendar.exception.CalendarDateException;
import org.mifosplatform.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
import org.mifosplatform.useradministration.domain.AppUser;
@Entity
@@ -147,13 +150,19 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
final String localeAsInput = command.locale();
final String startDateParamName = CALENDAR_SUPPORTED_PARAMETERS.START_DATE.getValue();
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartDateLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
actualChanges.put(startDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
this.startDate = newValue.toDate();
if(isStartDateBefore(newValue)){
actualChanges.put(startDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
this.startDate = newValue.toDate();
}else{
//new meeting start date should be greater than existing meeting start date
final String defaultUserMessage = "New meeting start on or after date cannot be a date before existing meeting start date";
throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newValue, getStartDateLocalDate());
}
}
final String endDateParamName = CALENDAR_SUPPORTED_PARAMETERS.END_DATE.getValue();
@@ -174,13 +183,21 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
this.duration = newValue;
}
//Do not allow to change calendar type
//TODO: AA Instead of throwing an exception, do not allow meeting calendar type to update.
final String typeParamName = CALENDAR_SUPPORTED_PARAMETERS.TYPE_ID.getValue();
if (command.isChangeInIntegerSansLocaleParameterNamed(typeParamName, this.typeId)) {
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(typeParamName);
final String defaultUserMessage = "Meeting calendar type update is not supported";
final String oldMeeingType = CalendarType.fromInt(this.typeId).name();
final String newMeetingType = CalendarType.fromInt(newValue).name();
throw new CalendarParameterUpdateNotSupportedException("meeting.type", defaultUserMessage, newMeetingType, oldMeeingType);
/*final Integer newValue = command.integerValueSansLocaleOfParameterNamed(typeParamName);
actualChanges.put(typeParamName, newValue);
this.typeId = newValue;
this.typeId = newValue;*/
}
final String repeatingParamName = CALENDAR_SUPPORTED_PARAMETERS.REPEATING.getValue();
if (command.isChangeInBooleanParameterNamed(repeatingParamName, this.repeating)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(repeatingParamName);
@@ -188,9 +205,25 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
this.repeating = newValue;
}
//FIXME: AA Construct recurrence rule in API rather than getting it from UI
final String recurrenceParamName = CALENDAR_SUPPORTED_PARAMETERS.RECURRENCE.getValue();
if (command.isChangeInStringParameterNamed(recurrenceParamName, this.recurrence)) {
final String newValue = command.stringValueOfParameterNamed(recurrenceParamName);
//FIXME: AA - Is this restriction required only for collection type meetings or for all?.
//Do not allow to change meeting frequency
if(!CalendarHelper.isFrequencySame(this.recurrence, newValue)){
final String defaultUserMessage = "Update of meeting frequency is not supported";
throw new CalendarParameterUpdateNotSupportedException("meeting.frequency", defaultUserMessage);
}
//Do not allow to change meeting interval
if(!CalendarHelper.isIntervalSame(this.recurrence, newValue)){
final String defaultUserMessage = "Update of meeting interval is not supported";
throw new CalendarParameterUpdateNotSupportedException("meeting.interval", defaultUserMessage);
}
actualChanges.put(recurrenceParamName, newValue);
this.recurrence = StringUtils.defaultIfEmpty(newValue, null);
}
@@ -283,4 +316,8 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
return endDateLocalDate;
}
public boolean isStartDateBefore(final LocalDate newStartDate) {
if (this.startDate != null && newStartDate != null && getStartDateLocalDate().isBefore(newStartDate)) { return true; }
return false;
}
}
@@ -20,4 +20,6 @@ public interface CalendarInstanceRepository extends JpaRepository<CalendarInstan
@Query("from CalendarInstance ci where ci.entityId = :loanId and ci.entityTypeId = :entityTypeId")
CalendarInstance findCalendarInstaneByLoanId(@Param("loanId") Long loanId, @Param("entityTypeId") Integer entityTypeId);
Collection<CalendarInstance> findByCalendarIdAndEntityTypeId(Long calendarId, Integer entityTypeId);
}
@@ -0,0 +1,18 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.calendar.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when Calendar resources are not found.
*/
public class CalendarDateException extends AbstractPlatformDomainRuleException {
public CalendarDateException(String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
super("error.msg.calendar." + postFix , defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,18 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.calendar.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when Calendar resources are not found.
*/
public class CalendarParameterUpdateNotSupportedException extends AbstractPlatformDomainRuleException {
public CalendarParameterUpdateNotSupportedException(String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
super("error.msg.calendar.update.of." + postFix + ".is.not.supported", defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -221,6 +221,7 @@ public class CalendarCommandFromApiJsonDeserializer extends AbstractFromApiJsonD
CALENDAR_SUPPORTED_PARAMETERS.DURATION.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.DURATION.getValue()).value(duration).ignoreIfNull();
}
//TODO: AA do not allow to change calendar type.
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.TYPE_ID.getValue(), element)) {
final Integer typeId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CALENDAR_SUPPORTED_PARAMETERS.TYPE_ID.getValue(),
element);
@@ -33,27 +33,30 @@ import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class CalendarHelper {
public static LocalDate getNextRecurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate startDate) {
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
if (recur == null) { return null; }
return getNextRecurringDate(recur, seedDate, startDate);
}
private static LocalDate getNextRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate startDate) {
final DateTime periodStart = new DateTime(startDate.toDate());
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//Date format in iCal4J is hard coded
final String seedDateStr = df.format(seedDate.toDateTimeAtStartOfDay().toDate());
Date seed = null;
try {
seed = new Date(seedDateStr, "yyyy-MM-dd");
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final Date seed = convertToiCal4JCompatibleDate(seedDate);
final Date nextRecDate = recur.getNextDate(seed, periodStart);
return nextRecDate == null ? null : new LocalDate(nextRecDate);
}
private static Date convertToiCal4JCompatibleDate(final LocalDate inputDate){
// Date format in iCal4J is hard coded
Date formattedDate = null;
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String seedDateStr = df.format(inputDate.toDateTimeAtStartOfDay().toDate());
try {
formattedDate = new Date(seedDateStr, "yyyy-MM-dd");
} catch (ParseException e) {
e.printStackTrace();
}
return formattedDate;
}
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) {
@@ -79,16 +82,14 @@ public class CalendarHelper {
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
return getRecurringDates(recur, seedDate, periodStartDate,
periodEndDate, maxCount);
}
private static Collection<LocalDate> getRecurringDates(final Recur recur, final LocalDate seedDate, final LocalDate periodStartDate,
final LocalDate periodEndDate, final int maxCount) {
if (recur == null) { return null; }
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String seedDateStr = df.format(seedDate.toDateTimeAtStartOfDay().toDate());
Date seed = null;
try {
seed = new Date(seedDateStr, "yyyy-MM-dd");
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final Date seed = convertToiCal4JCompatibleDate(seedDate);
final DateTime periodStart = new DateTime(periodStartDate.toDate());
final DateTime periodEnd = new DateTime(periodEndDate.toDate());
@@ -207,7 +208,15 @@ public class CalendarHelper {
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date){
final Collection<LocalDate> recurDate = getRecurringDates(recurringRule, seedDate, date, date.plusDays(1), 1);
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
if (recur == null) { return false; }
return isValidRedurringDate(recur, seedDate, date);
}
public static boolean isValidRedurringDate(final Recur recur, final LocalDate seedDate, final LocalDate date){
final Collection<LocalDate> recurDate = getRecurringDates(recur, seedDate, date, date.plusDays(1), 1);
return (recurDate == null || recurDate.isEmpty()) ? false : true;
}
@@ -287,22 +296,50 @@ public class CalendarHelper {
if(recur.getFrequency().equals(Recur.DAILY)){
recur.setFrequency(frequency);
}
final DateTime periodStart = new DateTime(startDate.toDate());
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//Date format in iCal4J is hard coded
final String seedDateStr = df.format(seedDate.toDateTimeAtStartOfDay().toDate());
Date seed = null;
try {
seed = new Date(seedDateStr, "yyyy-MM-dd");
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final Date nextRecDate = recur.getNextDate(seed, periodStart);
final LocalDate firstRepaymentDate = nextRecDate == null ? null : new LocalDate(nextRecDate);
final LocalDate firstRepaymentDate = getNextRecurringDate(recur, seedDate, startDate);
return firstRepaymentDate;
}
public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency){
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
if (recur == null) { return null; }
if(isValidRedurringDate(recur, seedDate, oldRepaymentDate)){
return oldRepaymentDate;
}
/* Recurring dates should follow loanRepaymentInterval.
e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have interval of 2,
to generate right set of meeting dates reset interval same as loan repayment interval.
*/
recur.setInterval(loanRepaymentInterval);
/*Recurring dates should follow loanRepayment frequency.
//e.g. daily meeting frequency should support all loan products with any type of frequency.
to generate right set of meeting dates reset frequency same as loan repayment frequency.
*/
if(recur.getFrequency().equals(Recur.DAILY)){
recur.setFrequency(frequency);
}
final LocalDate newRepaymentDate = getNextRecurringDate(recur, seedDate, oldRepaymentDate);
return newRepaymentDate;
}
public static boolean isFrequencySame(final String oldRRule, final String newRRule) {
Recur oldRecur = getICalRecur(oldRRule);
Recur newRecur = getICalRecur(newRRule);
if (oldRecur == null || oldRecur.getFrequency() == null || newRecur == null || newRecur.getFrequency() == null) { return false; }
return oldRecur.getFrequency().equals(newRecur.getFrequency());
}
public static boolean isIntervalSame(final String oldRRule, final String newRRule) {
Recur oldRecur = getICalRecur(oldRRule);
Recur newRecur = getICalRecur(newRRule);
if (oldRecur == null || oldRecur.getFrequency() == null || newRecur == null || newRecur.getFrequency() == null) { return false; }
return (oldRecur.getInterval() == newRecur.getInterval());
}
}
@@ -5,19 +5,24 @@
*/
package org.mifosplatform.portfolio.calendar.service;
import java.util.Collection;
import java.util.Map;
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository;
import org.mifosplatform.portfolio.calendar.domain.CalendarRepository;
import org.mifosplatform.portfolio.calendar.exception.CalendarNotFoundException;
import org.mifosplatform.portfolio.calendar.serialization.CalendarCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWritePlatformService {
@@ -25,14 +30,18 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
private final CalendarRepository calendarRepository;
private final CalendarCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final CalendarInstanceRepository calendarInstanceRepository;
private final LoanWritePlatformService loanWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
@Autowired
public CalendarWritePlatformServiceJpaRepositoryImpl(final CalendarRepository calendarRepository,
final CalendarCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final CalendarInstanceRepository calendarInstanceRepository) {
final CalendarInstanceRepository calendarInstanceRepository, final LoanWritePlatformService loanWritePlatformService, final ConfigurationDomainService configurationDomainService) {
this.calendarRepository = calendarRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.calendarInstanceRepository = calendarInstanceRepository;
this.loanWritePlatformService = loanWritePlatformService;
this.configurationDomainService = configurationDomainService;
}
@Override
@@ -66,6 +75,18 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
if (!changes.isEmpty()) {
this.calendarRepository.saveAndFlush(calendarForUpdate);
if(this.configurationDomainService.isRescheduleFutureRepaymentsEnabled()){
//In this approach loans following this meeting calendar will be affected immediately.
//get all calendar instances following this meeting calendar and calendar entity type is loan
final Collection<CalendarInstance> loanCalendarInstances = this.calendarInstanceRepository.findByCalendarIdAndEntityTypeId(calendarId, CalendarEntityType.LOANS.getValue());
if (!CollectionUtils.isEmpty(loanCalendarInstances)) {
// update all loans which are following this meeting calendar
this.loanWritePlatformService.updateRepaymentsSchedule(calendarForUpdate, loanCalendarInstances);
//
}
}
}
return new CommandProcessingResultBuilder() //
@@ -51,6 +51,7 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeAddedException;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.collateral.data.CollateralData;
@@ -190,7 +191,6 @@ public class Loan extends AbstractPersistable<Long> {
@JoinColumn(name = "disbursedon_userid", nullable = true)
private AppUser disbursedBy;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "closedon_date")
private Date closedOnDate;
@@ -2325,4 +2325,28 @@ public class Loan extends AbstractPersistable<Long> {
return this.closedOnDate;
}
public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule) {
//update repayment dates of repayment schedule installaments
LocalDate tmpFromDate = this.getDisbursementDate();//first repayment's from date is same as disbursement date.
LocalDate newRepaymentDate = null;
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
//FIXME: AA this won't update repayment dates before current date.
if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) {
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
// reset repayment date with new meeting date
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate, loanRepaymentInterval, frequency);
loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate);
//reset from date to get actual daysInPeriod
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
tmpFromDate = newRepaymentDate;//update with new repayment date
}else{
tmpFromDate = oldDueDate;
}
}
}
}
@@ -35,11 +35,11 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
@Temporal(TemporalType.DATE)
@Column(name = "fromdate", nullable = true)
private final Date fromDate;
private Date fromDate;
@Temporal(TemporalType.DATE)
@Column(name = "duedate", nullable = false)
private final Date dueDate;
private Date dueDate;
@Column(name = "principal_amount", scale = 6, precision = 19, nullable = true)
private BigDecimal principal;
@@ -521,4 +521,16 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
this.obligationsMetOnDate = transactionDate.toDate();
}
}
public void updateDueDate(final LocalDate newDueDate){
if(newDueDate != null){
this.dueDate = newDueDate.toDate();
}
}
public void updateFromDate(final LocalDate newFromDate){
if(newFromDate != null){
this.fromDate = newFromDate.toDate();
}
}
}
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.loanaccount.domain;
import java.util.Collection;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -19,4 +20,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>,
@Query("from Loan loan where loan.client.id = :clientId")
List<Loan> findLoanByClientId(@Param("clientId") Long clientId);
@Query("from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes")
List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids, @Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes);
}
@@ -5,10 +5,13 @@
*/
package org.mifosplatform.portfolio.loanaccount.service;
import java.util.Collection;
import java.util.Map;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
@@ -47,4 +50,6 @@ public interface LoanWritePlatformService {
CommandProcessingResult bulkLoanReassignment(JsonCommand command);
CommandProcessingResult removeLoanOfficer(Long loanId, JsonCommand command);
void updateRepaymentsSchedule(Calendar calendar, Collection<CalendarInstance> loanCalendarInstances);
}
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.loanaccount.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -55,6 +56,7 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus;
import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.mifosplatform.portfolio.loanaccount.domain.LoanType;
import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
@@ -982,4 +984,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
existingTransactionIds, existingReversedTransactionIds);
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
}
@Override
public void updateRepaymentsSchedule(final Calendar calendar, Collection<CalendarInstance> loanCalendarInstances) {
final Collection<Integer> loanStatuses = new ArrayList<Integer>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
final Collection<Integer> loanTypes = new ArrayList<Integer>(Arrays.asList(LoanType.GROUP.getValue(), LoanType.JLG.getValue()));
final Collection<Long> loanIds = new ArrayList<Long>(loanCalendarInstances.size());
//loop through loanCalendarInstances to get loan ids
for (CalendarInstance calendarInstance : loanCalendarInstances) {
loanIds.add(calendarInstance.getEntityId());
}
final List<Loan> loans = this.loanRepository.findByIdsAndLoanStatusAndLoanType(loanIds, loanStatuses, loanTypes);
//loop through each loan to reschedule the repayment dates
for (Loan loan : loans) {
if(loan != null){
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence());
this.loanRepository.save(loan);
}
}
}
}