MIFOSX-2152 : corrected transaction scope

This commit is contained in:
pramod
2015-08-18 12:30:35 +05:30
parent b4b7555bc1
commit 8902d2a5cb
6 changed files with 170 additions and 104 deletions
@@ -19,20 +19,20 @@ import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.portfolio.loanaccount.service.LoanAccrualWritePlatformService;
import org.mifosplatform.portfolio.loanaccount.service.LoanAccrualPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccrualAccountingWritePlatformServiceImpl implements AccrualAccountingWritePlatformService {
private final LoanAccrualWritePlatformService loanAccrualWritePlatformService;
private final LoanAccrualPlatformService loanAccrualPlatformService;
private final AccrualAccountingDataValidator accountingDataValidator;
@Autowired
public AccrualAccountingWritePlatformServiceImpl(final LoanAccrualWritePlatformService loanAccrualWritePlatformService,
public AccrualAccountingWritePlatformServiceImpl(final LoanAccrualPlatformService loanAccrualPlatformService,
final AccrualAccountingDataValidator accountingDataValidator) {
this.loanAccrualWritePlatformService = loanAccrualWritePlatformService;
this.loanAccrualPlatformService = loanAccrualPlatformService;
this.accountingDataValidator = accountingDataValidator;
}
@@ -40,7 +40,7 @@ public class AccrualAccountingWritePlatformServiceImpl implements AccrualAccount
public CommandProcessingResult executeLoansPeriodicAccrual(JsonCommand command) {
this.accountingDataValidator.validateLoanPeriodicAccrualData(command.json());
LocalDate tilldate = command.localDateValueOfParameterNamed(accrueTillParamName);
String errorlog = this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate);
String errorlog = this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
if (errorlog.length() > 0) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
@@ -55,7 +55,7 @@ import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
import org.mifosplatform.portfolio.loanaccount.service.LoanAccrualWritePlatformService;
import org.mifosplatform.portfolio.loanaccount.service.LoanAccrualPlatformService;
import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.note.domain.Note;
@@ -85,7 +85,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository;
private final CalendarInstanceRepository calendarInstanceRepository;
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
private final LoanAccrualWritePlatformService accrualWritePlatformService;
private final LoanAccrualPlatformService loanAccrualPlatformService;
private final PlatformSecurityContext context;
private final BusinessEventNotifierService businessEventNotifierService;
@@ -100,7 +100,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository,
final CalendarInstanceRepository calendarInstanceRepository,
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
final LoanAccrualWritePlatformService accrualWritePlatformService, final PlatformSecurityContext context,
final LoanAccrualPlatformService loanAccrualPlatformService, final PlatformSecurityContext context,
final BusinessEventNotifierService businessEventNotifierService) {
this.loanAccountAssembler = loanAccountAssembler;
this.loanRepository = loanRepository;
@@ -116,7 +116,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.applicationCurrencyRepository = applicationCurrencyRepository;
this.calendarInstanceRepository = calendarInstanceRepository;
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
this.accrualWritePlatformService = accrualWritePlatformService;
this.loanAccrualPlatformService = loanAccrualPlatformService;
this.context = context;
this.businessEventNotifierService = businessEventNotifierService;
}
@@ -514,7 +514,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
}
if (!loanScheduleAccrualDatas.isEmpty()) {
String error = this.accrualWritePlatformService.addPeriodicAccruals(accruedTill, loanScheduleAccrualDatas);
String error = this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill, loanScheduleAccrualDatas);
if (error.length() > 0) {
String globalisationMessageCode = "error.msg.accrual.exception";
throw new GeneralPlatformDomainRuleException(globalisationMessageCode, error, error);
@@ -0,0 +1,24 @@
/**
* 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.loanaccount.service;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
public interface LoanAccrualPlatformService {
String addPeriodicAccruals(LocalDate tilldate);
String addPeriodicAccruals(LocalDate tilldate, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas);
void addAccrualAccounting() throws JobExecutionException;
void addPeriodicAccruals() throws JobExecutionException;
}
@@ -0,0 +1,91 @@
/**
* 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.loanaccount.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanAccrualPlatformServiceImpl implements LoanAccrualPlatformService {
private final LoanReadPlatformService loanReadPlatformService;
private final LoanAccrualWritePlatformService loanAccrualWritePlatformService;
@Autowired
public LoanAccrualPlatformServiceImpl(final LoanReadPlatformService loanReadPlatformService,
final LoanAccrualWritePlatformService loanAccrualWritePlatformService) {
this.loanReadPlatformService = loanReadPlatformService;
this.loanAccrualWritePlatformService = loanAccrualWritePlatformService;
}
@Override
@CronTarget(jobName = JobName.ADD_ACCRUAL_ENTRIES)
public void addAccrualAccounting() throws JobExecutionException {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = this.loanReadPlatformService.retriveScheduleAccrualData();
StringBuilder sb = new StringBuilder();
Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new HashMap<>();
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
if (loanDataMap.containsKey(accrualData.getLoanId())) {
loanDataMap.get(accrualData.getLoanId()).add(accrualData);
} else {
Collection<LoanScheduleAccrualData> accrualDatas = new ArrayList<>();
accrualDatas.add(accrualData);
loanDataMap.put(accrualData.getLoanId(), accrualDatas);
}
}
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) {
this.loanAccrualWritePlatformService.addAccrualAccounting(mapEntry.getKey(), mapEntry.getValue(), sb);
}
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
}
@Override
@CronTarget(jobName = JobName.ADD_PERIODIC_ACCRUAL_ENTRIES)
public void addPeriodicAccruals() throws JobExecutionException {
String errors = addPeriodicAccruals(LocalDate.now());
if (errors.length() > 0) { throw new JobExecutionException(errors); }
}
@Override
public String addPeriodicAccruals(final LocalDate tilldate) {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = this.loanReadPlatformService.retrivePeriodicAccrualData(tilldate);
return addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
}
@Override
public String addPeriodicAccruals(final LocalDate tilldate, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) {
StringBuilder sb = new StringBuilder();
Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new HashMap<>();
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
if (loanDataMap.containsKey(accrualData.getLoanId())) {
loanDataMap.get(accrualData.getLoanId()).add(accrualData);
} else {
Collection<LoanScheduleAccrualData> accrualDatas = new ArrayList<>();
accrualDatas.add(accrualData);
loanDataMap.put(accrualData.getLoanId(), accrualDatas);
}
}
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) {
this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate, mapEntry.getKey(), mapEntry.getValue(), sb);
}
return sb.toString();
}
}
@@ -8,18 +8,12 @@ package org.mifosplatform.portfolio.loanaccount.service;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
public interface LoanAccrualWritePlatformService {
void addAccrualAccounting() throws JobExecutionException;
void addAccrualAccounting(Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, StringBuilder sb);
void addPeriodicAccruals() throws JobExecutionException;
String addPeriodicAccruals(LocalDate tilldate);
String addPeriodicAccruals(LocalDate tilldate, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas);
void addPeriodicAccruals(LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, StringBuilder sb);
}
@@ -10,12 +10,10 @@ import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
@@ -24,9 +22,6 @@ import org.joda.time.LocalDate;
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
import org.mifosplatform.portfolio.loanaccount.data.LoanInstallmentChargeData;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
@@ -66,114 +61,76 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
}
@Override
@CronTarget(jobName = JobName.ADD_ACCRUAL_ENTRIES)
public void addAccrualAccounting() throws JobExecutionException {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = this.loanReadPlatformService.retriveScheduleAccrualData();
StringBuilder sb = new StringBuilder();
Set<Long> loansIds = new HashSet<>();
Map<Long, Collection<LoanChargeData>> loanChargeMap = new HashMap<>();
Map<Long, Collection<LoanTransactionData>> loanWaiverTansactions = new HashMap<>();
Map<Long, Collection<LoanSchedulePeriodData>> loanWaiverSchedules = new HashMap<>();
@Transactional
public void addAccrualAccounting(final Long loanId, final Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas,
final StringBuilder sb) {
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1);
Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1);
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
try {
if (!loansIds.contains(accrualData.getLoanId())) {
if (!loanChargeMap.containsKey(accrualData.getLoanId())) {
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService
.retrieveLoanChargesForAccural(accrualData.getLoanId());
loanChargeMap.put(accrualData.getLoanId(), chargeData);
}
if (accrualData.getWaivedInterestIncome() != null && !loanWaiverTansactions.containsKey(accrualData.getLoanId())) {
loanWaiverSchedules.put(accrualData.getLoanId(),
this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId()));
loanWaiverTansactions.put(accrualData.getLoanId(),
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId()));
}
updateCharges(loanChargeMap.get(accrualData.getLoanId()), accrualData, accrualData.getFromDateAsLocaldate(),
accrualData.getDueDateAsLocaldate());
updateInterestIncome(accrualData, loanWaiverTansactions, loanWaiverSchedules, accrualData.getDueDateAsLocaldate());
addAccrualAccounting(accrualData);
if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) {
loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
loanWaiverTansactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
}
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, accrualData.getDueDateAsLocaldate());
addAccrualAccounting(accrualData);
} catch (Exception e) {
loansIds.add(accrualData.getLoanId());
Throwable realCause = e;
if (e.getCause() != null) {
realCause = e.getCause();
}
sb.append("failed to add accural transaction for repayment with id " + accrualData.getRepaymentScheduleId()
+ " with message " + realCause.getMessage());
return;
}
}
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
}
@Override
@CronTarget(jobName = JobName.ADD_PERIODIC_ACCRUAL_ENTRIES)
public void addPeriodicAccruals() throws JobExecutionException {
String errors = addPeriodicAccruals(LocalDate.now());
if (errors.length() > 0) { throw new JobExecutionException(errors); }
}
@Override
public String addPeriodicAccruals(final LocalDate tilldate) {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = this.loanReadPlatformService.retrivePeriodicAccrualData(tilldate);
return addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
}
@Override
public String addPeriodicAccruals(final LocalDate tilldate, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) {
StringBuilder sb = new StringBuilder();
Set<Long> loansIds = new HashSet<>();
@Transactional
public void addPeriodicAccruals(final LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas,
StringBuilder sb) {
boolean firstTime = true;
LocalDate accruredTill = null;
Long lastLoanId = null;
Map<Long, Collection<LoanChargeData>> loanChargeMap = new HashMap<>();
Map<Long, Collection<LoanTransactionData>> loanWaiverTansactions = new HashMap<>();
Map<Long, Collection<LoanSchedulePeriodData>> loanWaiverSchedules = new HashMap<>();
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1);
Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1);
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
try {
if (!loansIds.contains(accrualData.getLoanId())) {
if (accrualData.getWaivedInterestIncome() != null && !loanWaiverTansactions.containsKey(accrualData.getLoanId())) {
loanWaiverSchedules.put(accrualData.getLoanId(),
this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId()));
loanWaiverTansactions.put(accrualData.getLoanId(),
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId()));
}
if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) {
loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
loanWaiverTansactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
}
if (!loanChargeMap.containsKey(accrualData.getLoanId())) {
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService
.retrieveLoanChargesForAccural(accrualData.getLoanId());
loanChargeMap.put(accrualData.getLoanId(), chargeData);
if (accrualData.getDueDateAsLocaldate().isAfter(tilldate)) {
if (accruredTill == null || firstTime) {
accruredTill = accrualData.getAccruedTill();
firstTime = false;
}
if (accrualData.getDueDateAsLocaldate().isAfter(tilldate)) {
if (accruredTill == null || lastLoanId == null || !lastLoanId.equals(accrualData.getLoanId())) {
accruredTill = accrualData.getAccruedTill();
}
if (accruredTill == null || accruredTill.isBefore(tilldate)) {
updateCharges(loanChargeMap.get(accrualData.getLoanId()), accrualData, accrualData.getFromDateAsLocaldate(),
tilldate);
updateInterestIncome(accrualData, loanWaiverTansactions, loanWaiverSchedules, tilldate);
addAccrualTillSpecificDate(tilldate, accrualData);
}
} else {
updateCharges(loanChargeMap.get(accrualData.getLoanId()), accrualData, accrualData.getFromDateAsLocaldate(),
accrualData.getDueDateAsLocaldate());
updateInterestIncome(accrualData, loanWaiverTansactions, loanWaiverSchedules, tilldate);
addAccrualAccounting(accrualData);
accruredTill = accrualData.getDueDateAsLocaldate();
if (accruredTill == null || accruredTill.isBefore(tilldate)) {
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), tilldate);
updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, tilldate);
addAccrualTillSpecificDate(tilldate, accrualData);
}
} else {
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, tilldate);
addAccrualAccounting(accrualData);
accruredTill = accrualData.getDueDateAsLocaldate();
}
} catch (Exception e) {
loansIds.add(accrualData.getLoanId());
Throwable realCause = e;
if (e.getCause() != null) {
realCause = e.getCause();
}
sb.append("failed to add accural transaction for repayment with id " + accrualData.getRepaymentScheduleId()
+ " with message " + realCause.getMessage());
return;
}
lastLoanId = accrualData.getLoanId();
}
return sb.toString();
}
private void addAccrualTillSpecificDate(final LocalDate tilldate, final LoanScheduleAccrualData accrualData) throws Exception {
@@ -476,8 +433,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
}
private void updateInterestIncome(final LoanScheduleAccrualData accrualData,
final Map<Long, Collection<LoanTransactionData>> loanWaiverTansactions,
final Map<Long, Collection<LoanSchedulePeriodData>> loanWaiverSchedules, final LocalDate tilldate) {
final Collection<LoanTransactionData> loanWaiverTansactions, final Collection<LoanSchedulePeriodData> loanSchedulePeriodDatas,
final LocalDate tilldate) {
BigDecimal interestIncome = accrualData.getInterestIncome();
if (accrualData.getWaivedInterestIncome() != null) {
@@ -485,9 +442,8 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
BigDecimal unrecognized = BigDecimal.ZERO;
BigDecimal remainingAmt = BigDecimal.ZERO;
Collection<LoanTransactionData> loanTransactionDatas = new ArrayList<>();
Collection<LoanSchedulePeriodData> loanSchedulePeriodDatas = loanWaiverSchedules.get(accrualData.getLoanId());
for (LoanTransactionData loanTransactionData : loanWaiverTansactions.get(accrualData.getLoanId())) {
for (LoanTransactionData loanTransactionData : loanWaiverTansactions) {
if (!loanTransactionData.dateOf().isAfter(accrualData.getFromDateAsLocaldate())
|| (loanTransactionData.dateOf().isAfter(accrualData.getFromDateAsLocaldate())
&& !loanTransactionData.dateOf().isAfter(accrualData.getDueDateAsLocaldate()) && !loanTransactionData
@@ -531,4 +487,5 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
accrualData.updateAccruableIncome(interestIncome);
}
}