Merge pull request #1471 from pramodn02/performanceissues

MIFOSX-2166: changed transaction scope to loan level instead of repay…
This commit is contained in:
Vishwas Babu A J
2015-08-25 17:16:36 +05:30
3 changed files with 74 additions and 90 deletions
@@ -48,7 +48,15 @@ public class LoanAccrualPlatformServiceImpl implements LoanAccrualPlatformServic
} }
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) { for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) {
this.loanAccrualWritePlatformService.addAccrualAccounting(mapEntry.getKey(), mapEntry.getValue(), sb); try {
this.loanAccrualWritePlatformService.addAccrualAccounting(mapEntry.getKey(), mapEntry.getValue());
} catch (Exception e) {
Throwable realCause = e;
if (e.getCause() != null) {
realCause = e.getCause();
}
sb.append("failed to add accural transaction for loan " + mapEntry.getKey() + " with message " + realCause.getMessage());
}
} }
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); } if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
@@ -82,7 +90,15 @@ public class LoanAccrualPlatformServiceImpl implements LoanAccrualPlatformServic
} }
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) { for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : loanDataMap.entrySet()) {
this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate, mapEntry.getKey(), mapEntry.getValue(), sb); try {
this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate, mapEntry.getKey(), mapEntry.getValue());
} catch (Exception e) {
Throwable realCause = e;
if (e.getCause() != null) {
realCause = e.getCause();
}
sb.append("failed to add accural transaction for loan " + mapEntry.getKey() + " with message " + realCause.getMessage());
}
} }
return sb.toString(); return sb.toString();
@@ -12,8 +12,8 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
public interface LoanAccrualWritePlatformService { public interface LoanAccrualWritePlatformService {
void addAccrualAccounting(Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, StringBuilder sb); void addAccrualAccounting(Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws Exception;
void addPeriodicAccruals(LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, StringBuilder sb); void addPeriodicAccruals(LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws Exception;
} }
@@ -32,11 +32,8 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanSchedulePer
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations; import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service @Service
public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlatformService { public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlatformService {
@@ -46,89 +43,67 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final DataSource dataSource; private final DataSource dataSource;
private final JournalEntryWritePlatformService journalEntryWritePlatformService; private final JournalEntryWritePlatformService journalEntryWritePlatformService;
private final JpaTransactionManager transactionManager;
@Autowired @Autowired
public LoanAccrualWritePlatformServiceImpl(final RoutingDataSource dataSource, final LoanReadPlatformService loanReadPlatformService, public LoanAccrualWritePlatformServiceImpl(final RoutingDataSource dataSource, final LoanReadPlatformService loanReadPlatformService,
final JournalEntryWritePlatformService journalEntryWritePlatformService, final JpaTransactionManager transactionManager, final JournalEntryWritePlatformService journalEntryWritePlatformService,
final LoanChargeReadPlatformService loanChargeReadPlatformService) { final LoanChargeReadPlatformService loanChargeReadPlatformService) {
this.loanReadPlatformService = loanReadPlatformService; this.loanReadPlatformService = loanReadPlatformService;
this.dataSource = dataSource; this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(this.dataSource); this.jdbcTemplate = new JdbcTemplate(this.dataSource);
this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.journalEntryWritePlatformService = journalEntryWritePlatformService;
this.transactionManager = transactionManager;
this.loanChargeReadPlatformService = loanChargeReadPlatformService; this.loanChargeReadPlatformService = loanChargeReadPlatformService;
} }
@Override @Override
@Transactional @Transactional
public void addAccrualAccounting(final Long loanId, final Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, public void addAccrualAccounting(final Long loanId, final Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas)
final StringBuilder sb) { throws Exception {
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId); Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1); Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1);
Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1); Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1);
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) { for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
try { if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) {
if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) { loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId()); loanWaiverTansactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(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) {
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;
} }
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, accrualData.getDueDateAsLocaldate());
addAccrualAccounting(accrualData);
} }
} }
@Override @Override
@Transactional @Transactional
public void addPeriodicAccruals(final LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, public void addPeriodicAccruals(final LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas)
StringBuilder sb) { throws Exception {
boolean firstTime = true; boolean firstTime = true;
LocalDate accruredTill = null; LocalDate accruredTill = null;
Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId); Collection<LoanChargeData> chargeData = this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1); Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new ArrayList<>(1);
Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1); Collection<LoanTransactionData> loanWaiverTansactionData = new ArrayList<>(1);
for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) { for (final LoanScheduleAccrualData accrualData : loanScheduleAccrualDatas) {
try { if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) {
if (accrualData.getWaivedInterestIncome() != null && loanWaiverScheduleData.isEmpty()) { loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
loanWaiverScheduleData = this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId()); loanWaiverTansactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
loanWaiverTansactionData = this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId()); }
}
if (accrualData.getDueDateAsLocaldate().isAfter(tilldate)) { if (accrualData.getDueDateAsLocaldate().isAfter(tilldate)) {
if (accruredTill == null || firstTime) { if (accruredTill == null || firstTime) {
accruredTill = accrualData.getAccruedTill(); accruredTill = accrualData.getAccruedTill();
firstTime = false; firstTime = false;
} }
if (accruredTill == null || accruredTill.isBefore(tilldate)) { if (accruredTill == null || accruredTill.isBefore(tilldate)) {
updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), 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); updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, tilldate);
addAccrualAccounting(accrualData); addAccrualTillSpecificDate(tilldate, accrualData);
accruredTill = accrualData.getDueDateAsLocaldate();
} }
} catch (Exception e) { } else {
Throwable realCause = e; updateCharges(chargeData, accrualData, accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
if (e.getCause() != null) { updateInterestIncome(accrualData, loanWaiverTansactionData, loanWaiverScheduleData, tilldate);
realCause = e.getCause(); addAccrualAccounting(accrualData);
} accruredTill = accrualData.getDueDateAsLocaldate();
sb.append("failed to add accural transaction for repayment with id " + accrualData.getRepaymentScheduleId()
+ " with message " + realCause.getMessage());
return;
} }
} }
} }
@@ -265,41 +240,34 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
private void addAccrualAccounting(LoanScheduleAccrualData scheduleAccrualData, BigDecimal amount, BigDecimal interestportion, private void addAccrualAccounting(LoanScheduleAccrualData scheduleAccrualData, BigDecimal amount, BigDecimal interestportion,
BigDecimal totalAccInterest, BigDecimal feeportion, BigDecimal totalAccFee, BigDecimal penaltyportion, BigDecimal totalAccInterest, BigDecimal feeportion, BigDecimal totalAccFee, BigDecimal penaltyportion,
BigDecimal totalAccPenalty, final LocalDate accruedTill) throws Exception { BigDecimal totalAccPenalty, final LocalDate accruedTill) throws Exception {
TransactionStatus transactionStatus = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); String transactionSql = "INSERT INTO m_loan_transaction (loan_id,office_id,is_reversed,transaction_type_enum,transaction_date,amount,interest_portion_derived,"
try { + "fee_charges_portion_derived,penalty_charges_portion_derived, submitted_on_date) VALUES (?, ?, 0, ?, ?, ?, ?, ?, ?, ?)";
String transactionSql = "INSERT INTO m_loan_transaction (loan_id,office_id,is_reversed,transaction_type_enum,transaction_date,amount,interest_portion_derived," this.jdbcTemplate.update(transactionSql, scheduleAccrualData.getLoanId(), scheduleAccrualData.getOfficeId(),
+ "fee_charges_portion_derived,penalty_charges_portion_derived, submitted_on_date) VALUES (?, ?, 0, ?, ?, ?, ?, ?, ?, ?)"; LoanTransactionType.ACCRUAL.getValue(), accruedTill.toDate(), amount, interestportion, feeportion, penaltyportion,
this.jdbcTemplate.update(transactionSql, scheduleAccrualData.getLoanId(), scheduleAccrualData.getOfficeId(), DateUtils.getDateOfTenant());
LoanTransactionType.ACCRUAL.getValue(), accruedTill.toDate(), amount, interestportion, feeportion, penaltyportion, @SuppressWarnings("deprecation")
DateUtils.getDateOfTenant()); final Long transactonId = this.jdbcTemplate.queryForLong("SELECT LAST_INSERT_ID()");
@SuppressWarnings("deprecation")
final Long transactonId = this.jdbcTemplate.queryForLong("SELECT LAST_INSERT_ID()");
Map<LoanChargeData, BigDecimal> applicableCharges = scheduleAccrualData.getApplicableCharges(); Map<LoanChargeData, BigDecimal> applicableCharges = scheduleAccrualData.getApplicableCharges();
String chargespaidSql = "INSERT INTO m_loan_charge_paid_by (loan_transaction_id, loan_charge_id, amount,installment_number) VALUES (?,?,?,?)"; String chargespaidSql = "INSERT INTO m_loan_charge_paid_by (loan_transaction_id, loan_charge_id, amount,installment_number) VALUES (?,?,?,?)";
for (Map.Entry<LoanChargeData, BigDecimal> entry : applicableCharges.entrySet()) { for (Map.Entry<LoanChargeData, BigDecimal> entry : applicableCharges.entrySet()) {
LoanChargeData chargeData = entry.getKey(); LoanChargeData chargeData = entry.getKey();
this.jdbcTemplate.update(chargespaidSql, transactonId, chargeData.getId(), entry.getValue(), this.jdbcTemplate.update(chargespaidSql, transactonId, chargeData.getId(), entry.getValue(),
scheduleAccrualData.getInstallmentNumber()); scheduleAccrualData.getInstallmentNumber());
}
Map<String, Object> transactionMap = toMapData(transactonId, amount, interestportion, feeportion, penaltyportion,
scheduleAccrualData, accruedTill);
String repaymetUpdatesql = "UPDATE m_loan_repayment_schedule SET accrual_interest_derived=?, accrual_fee_charges_derived=?, "
+ "accrual_penalty_charges_derived=? WHERE id=?";
this.jdbcTemplate.update(repaymetUpdatesql, totalAccInterest, totalAccFee, totalAccPenalty,
scheduleAccrualData.getRepaymentScheduleId());
String updateLoan = "UPDATE m_loan SET accrued_till=? WHERE id=?";
this.jdbcTemplate.update(updateLoan, accruedTill.toDate(), scheduleAccrualData.getLoanId());
final Map<String, Object> accountingBridgeData = deriveAccountingBridgeData(scheduleAccrualData, transactionMap);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
} catch (Exception e) {
this.transactionManager.rollback(transactionStatus);
throw e;
} }
this.transactionManager.commit(transactionStatus);
Map<String, Object> transactionMap = toMapData(transactonId, amount, interestportion, feeportion, penaltyportion,
scheduleAccrualData, accruedTill);
String repaymetUpdatesql = "UPDATE m_loan_repayment_schedule SET accrual_interest_derived=?, accrual_fee_charges_derived=?, "
+ "accrual_penalty_charges_derived=? WHERE id=?";
this.jdbcTemplate.update(repaymetUpdatesql, totalAccInterest, totalAccFee, totalAccPenalty,
scheduleAccrualData.getRepaymentScheduleId());
String updateLoan = "UPDATE m_loan SET accrued_till=? WHERE id=?";
this.jdbcTemplate.update(updateLoan, accruedTill.toDate(), scheduleAccrualData.getLoanId());
final Map<String, Object> accountingBridgeData = deriveAccountingBridgeData(scheduleAccrualData, transactionMap);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
} }
public Map<String, Object> deriveAccountingBridgeData(final LoanScheduleAccrualData loanScheduleAccrualData, public Map<String, Object> deriveAccountingBridgeData(final LoanScheduleAccrualData loanScheduleAccrualData,