From b43a9472e3b1ccf621f68c89307f1d4ee68daa99 Mon Sep 17 00:00:00 2001 From: andrew-dzak Date: Wed, 13 Nov 2013 17:04:07 +0100 Subject: [PATCH] mifosx-746 fixes --- .../infrastructure/jobs/service/JobName.java | 2 +- .../charge/domain/ChargeTimeType.java | 14 +- ...ChargeDropdownReadPlatformServiceImpl.java | 16 +-- .../charge/service/ChargeEnumerations.java | 3 + .../loanaccount/domain/LoanCharge.java | 2 +- .../data/OverdueLoanScheduleData.java | 65 +++++++++ .../service/LoanReadPlatformService.java | 7 +- .../service/LoanReadPlatformServiceImpl.java | 73 +++++++--- .../service/LoanWritePlatformService.java | 10 +- ...WritePlatformServiceJpaRepositoryImpl.java | 129 ++++++++++++++---- 10 files changed, 252 insertions(+), 69 deletions(-) mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/jobs/service/JobName.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java create mode 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/OverdueLoanScheduleData.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformService.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java mode change 100644 => 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/jobs/service/JobName.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/jobs/service/JobName.java old mode 100644 new mode 100755 index 9ad925a08..a1393c73a --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/jobs/service/JobName.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/jobs/service/JobName.java @@ -6,7 +6,7 @@ public enum JobName { "Update Loan Paid In Advance"), APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"), APPLY_HOLIDAYS_TO_LOANS( "Apply Holidays To Loans"), POST_INTEREST_FOR_SAVINGS("Post Interest For Savings"), TRANSFER_FEE_CHARGE_FOR_LOANS( "Transfer Fee For Loans From Savings"), ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances"), PAY_DUE_SAVINGS_CHARGES( - "Pay Due Savings Charges"); + "Pay Due Savings Charges"),APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"); private final String name; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java old mode 100644 new mode 100755 index d1482d0a8..3f8d11749 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java @@ -17,7 +17,8 @@ public enum ChargeTimeType { WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings MONTHLY_FEE(7, "chargeTimeType.monthlyFee"), // only for savings - INSTALMENT_FEE(8, "chargeTimeType.instalmentFee");// only for loan charges + INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"),// only for loan charges + OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"); // only for loan charges private final Integer value; private final String code; @@ -37,7 +38,7 @@ public enum ChargeTimeType { public static Object[] validLoanValues() { return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), - ChargeTimeType.INSTALMENT_FEE.getValue() }; + ChargeTimeType.INSTALMENT_FEE.getValue(),ChargeTimeType.OVERDUE_INSTALLMENT.getValue() }; } public static Object[] validSavingsValues() { @@ -74,6 +75,9 @@ public enum ChargeTimeType { case 8: chargeTimeType = INSTALMENT_FEE; break; + case 9: + chargeTimeType = OVERDUE_INSTALLMENT; + break; default: chargeTimeType = INVALID; break; @@ -114,8 +118,12 @@ public enum ChargeTimeType { return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue()); } + public boolean isOverdueInstallment(){ + return this.value.equals(ChargeTimeType.OVERDUE_INSTALLMENT.getValue()); + } + public boolean isAllowedLoanChargeTime() { - return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee(); + return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee() || isOverdueInstallment(); } public boolean isAllowedSavingsChargeTime() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java old mode 100644 new mode 100755 index 648219dc6..d8bcd7ca6 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java @@ -5,14 +5,6 @@ */ package org.mifosplatform.portfolio.charge.service; -import static org.mifosplatform.portfolio.charge.service.ChargeEnumerations.chargeCalculationType; -import static org.mifosplatform.portfolio.charge.service.ChargeEnumerations.chargePaymentMode; -import static org.mifosplatform.portfolio.charge.service.ChargeEnumerations.chargeTimeType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.portfolio.charge.domain.ChargeAppliesTo; import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType; @@ -20,6 +12,12 @@ import org.mifosplatform.portfolio.charge.domain.ChargePaymentMode; import org.mifosplatform.portfolio.charge.domain.ChargeTimeType; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.mifosplatform.portfolio.charge.service.ChargeEnumerations.*; + @Service public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownReadPlatformService { @@ -69,7 +67,7 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead @Override public List retrieveLoanCollectionTimeTypes() { - return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT), chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE),chargeTimeType(ChargeTimeType.INSTALMENT_FEE)); + return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT), chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE),chargeTimeType(ChargeTimeType.INSTALMENT_FEE),chargeTimeType(ChargeTimeType.OVERDUE_INSTALLMENT)); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java old mode 100644 new mode 100755 index 95ba5e3da..c3a6daaaf --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java @@ -46,6 +46,9 @@ public class ChargeEnumerations { case INSTALMENT_FEE: optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(), ChargeTimeType.INSTALMENT_FEE.getCode(), "Instalment Fee"); break; + case OVERDUE_INSTALLMENT: + optionData = new EnumOptionData(ChargeTimeType.OVERDUE_INSTALLMENT.getValue().longValue(),ChargeTimeType.OVERDUE_INSTALLMENT.getCode(),"overdue fees") ; + break; default: optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid"); break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java index 784f886d2..a106265d5 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java @@ -172,7 +172,7 @@ public class LoanCharge extends AbstractPersistable { this.chargeTime = chargeTime.getValue(); } - if (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE)) { + if (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE) || ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.OVERDUE_INSTALLMENT) ) { if (dueDate == null) { final String defaultUserMessage = "Loan charge is missing due date."; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/OverdueLoanScheduleData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/OverdueLoanScheduleData.java new file mode 100755 index 000000000..a7fccd9c6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/OverdueLoanScheduleData.java @@ -0,0 +1,65 @@ +package org.mifosplatform.portfolio.loanaccount.loanschedule.data; + +import java.math.BigDecimal; + +/** + * Created with IntelliJ IDEA. + * User: andrew + * Date: 13-11-13 + * Time: 11:53 + * To change this template use File | Settings | File Templates. + */ +public class OverdueLoanScheduleData { + private final Long loanId; + private final Long chargeId; + private final String locale; + private final BigDecimal amount; + private final String dateFormat; + private final String dueDate; + + + + public OverdueLoanScheduleData(Long loanId, Long chargeId, String dueDate, BigDecimal amount, String dateFormat, String locale) { + this.loanId = loanId; + this.chargeId = chargeId; + this.dueDate = dueDate; + this.amount = amount; + this.dateFormat = dateFormat; + this.locale = locale; + } + + public Long getLoanId() { + return this.loanId; + } + + public Long getChargeId() { + return this.chargeId; + } + + public String getDueDate() { + return this.dueDate; + } + + public BigDecimal getAmount() { + return this.amount; + } + + public String getDateFormat() { + return this.dateFormat; + } + + public String getLocale() { + return this.locale; + } + + @Override + public String toString() { + return "{" + + "chargeId:" + chargeId + + ", locale:'" + locale + '\'' + + ", amount:" + amount + + ", dateFormat:'" + dateFormat + '\'' + + ", dueDate:'" + dueDate + '\'' + + '}'; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformService.java old mode 100644 new mode 100755 index 4c50e001d..4e84280dc --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -5,8 +5,6 @@ */ package org.mifosplatform.portfolio.loanaccount.service; -import java.util.Collection; - import org.mifosplatform.infrastructure.core.service.Page; import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.portfolio.calendar.data.CalendarData; @@ -15,6 +13,9 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; import org.mifosplatform.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; +import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData; + +import java.util.Collection; public interface LoanReadPlatformService { @@ -53,4 +54,6 @@ public interface LoanReadPlatformService { Page retrieveAll(SearchParameters searchParameters); Collection retrieveAllowedLoanOfficers(Long selectedOfficeId, boolean staffInSelectedOfficeOnly); + + Collection retrieveAllOverdueLoans(); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java old mode 100644 new mode 100755 index 36e84da35..643b4f6ac --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -5,13 +5,6 @@ */ package org.mifosplatform.portfolio.loanaccount.service; -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - import org.apache.commons.lang.StringUtils; import org.joda.time.Days; import org.joda.time.LocalDate; @@ -47,23 +40,13 @@ import org.mifosplatform.portfolio.group.data.GroupGeneralData; import org.mifosplatform.portfolio.group.data.GroupRoleData; import org.mifosplatform.portfolio.group.service.GroupReadPlatformService; import org.mifosplatform.portfolio.group.service.SearchParameters; -import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; -import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; -import org.mifosplatform.portfolio.loanaccount.data.LoanApplicationTimelineData; -import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData; -import org.mifosplatform.portfolio.loanaccount.data.LoanSummaryData; -import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; -import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData; -import org.mifosplatform.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; -import org.mifosplatform.portfolio.loanaccount.domain.Loan; -import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType; +import org.mifosplatform.portfolio.loanaccount.data.*; +import org.mifosplatform.portfolio.loanaccount.domain.*; import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException; import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; +import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData; import org.mifosplatform.portfolio.loanproduct.service.LoanDropdownReadPlatformService; @@ -81,6 +64,13 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + @Service public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { @@ -688,6 +678,39 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { feeChargesDueAtDisbursementCharged, syncDisbursementWithMeeting, loanCounter, loanProductCounter); } } + private static final class OverdueLoanSchedule implements RowMapper{ + + public String schema(){ + return " ls.loan_id as loanId, ls.installment as period, ls.fromdate as fromDate, ls.duedate as dueDate, ls.obligations_met_on_date as obligationsMetOnDate, ls.completed_derived as complete," + + " ls.principal_amount as principalDue, ls.principal_completed_derived as principalPaid, ls.principal_writtenoff_derived as principalWrittenOff, " + + " ls.interest_amount as interestDue, ls.interest_completed_derived as interestPaid, ls.interest_waived_derived as interestWaived, ls.interest_writtenoff_derived as interestWrittenOff, " + + " ls.fee_charges_amount as feeChargesDue, ls.fee_charges_completed_derived as feeChargesPaid, ls.fee_charges_waived_derived as feeChargesWaived, ls.fee_charges_writtenoff_derived as feeChargesWrittenOff, " + + " ls.penalty_charges_amount as penaltyChargesDue, ls.penalty_charges_completed_derived as penaltyChargesPaid, ls.penalty_charges_waived_derived as penaltyChargesWaived, ls.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff, " + + " ls.total_paid_in_advance_derived as totalPaidInAdvanceForPeriod, ls.total_paid_late_derived as totalPaidLateForPeriod, " + + " mc.amount,mc.id as chargeId " + + " from m_loan_repayment_schedule ls " + + " inner join m_loan ml on ml.id = ls.loan_id " + + " join m_product_loan_charge plc on plc.product_loan_id = ml.product_id " + + " join m_charge mc on mc.id = plc.charge_id "; + + } + + @Override + public OverdueLoanScheduleData mapRow(ResultSet rs, int rowNum) throws SQLException { + final Long chargeId = rs.getLong("chargeId"); + final Long loanId = rs.getLong("loanId"); + final BigDecimal amount = rs.getBigDecimal("amount"); + final String dateFormat = "yyyy-MM-dd"; + final String dueDate = rs.getString("dueDate"); + final String locale = "en_GB"; + + + OverdueLoanScheduleData overdueLoanScheduleData = new OverdueLoanScheduleData(loanId,chargeId,dueDate, + amount,dateFormat,locale) ; + + return overdueLoanScheduleData; + } + } private static final class LoanScheduleResultSetExtractor implements ResultSetExtractor { @@ -1105,4 +1128,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { return allowedLoanOfficers; } + @Override + public Collection retrieveAllOverdueLoans() { + final OverdueLoanSchedule rm = new OverdueLoanSchedule(); + final String sql = "select " + rm.schema() + + " where CURDATE() > ls.duedate "+ + " and ls.completed_derived <> 1 and mc.charge_applies_to_enum =1 "+ + " and mc.charge_time_enum = 9 and ml.loan_status_id = 300 "+ + " and plc.charge_id not in (SELECT charge_id from m_loan_charge as mlc where mlc.loan_id = ml.id and mlc.charge_id = plc.charge_id and mlc.due_for_collection_as_of_date > fromdate AND mlc.due_for_collection_as_of_date <= duedate) "; + return this.jdbcTemplate.query(sql,rm,new Object[] {}); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java old mode 100644 new mode 100755 index 607e80e7f..7c9870675 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java @@ -5,9 +5,6 @@ */ package org.mifosplatform.portfolio.loanaccount.service; -import java.util.Collection; -import java.util.Map; - import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; @@ -20,6 +17,9 @@ import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDi import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; +import java.util.Collection; +import java.util.Map; + public interface LoanWritePlatformService { CommandProcessingResult disburseLoan(Long loanId, JsonCommand command); @@ -72,4 +72,8 @@ public interface LoanWritePlatformService { void transferFeeCharges() throws JobExecutionException; + void applyChargeForOverdueLoans() throws JobExecutionException; + + + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java old mode 100644 new mode 100755 index d724fefc5..d09f5ec6b --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -5,17 +5,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.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - +import com.google.gson.JsonElement; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; @@ -29,6 +19,7 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformServiceUnavailableException; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.jobs.annotation.CronTarget; import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException; import org.mifosplatform.infrastructure.jobs.service.JobName; @@ -58,15 +49,11 @@ import org.mifosplatform.portfolio.calendar.service.CalendarUtils; import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.ChargePaymentMode; import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; -import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeDeletedException; +import org.mifosplatform.portfolio.charge.exception.*; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeDeletedException.LOAN_CHARGE_CANNOT_BE_DELETED_REASON; -import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBePayedException; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBePayedException.LOAN_CHARGE_CANNOT_BE_PAYED_REASON; -import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeUpdatedException; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeUpdatedException.LOAN_CHARGE_CANNOT_BE_UPDATED_REASON; -import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON; -import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException; import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.exception.ClientNotActiveException; import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; @@ -78,23 +65,12 @@ import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.data.LoanInstallmentChargeData; -import org.mifosplatform.portfolio.loanaccount.domain.ChangedTransactionDetail; -import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; -import org.mifosplatform.portfolio.loanaccount.domain.Loan; -import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService; -import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; -import org.mifosplatform.portfolio.loanaccount.domain.LoanInstallmentCharge; -import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository; -import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; -import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; -import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; -import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType; +import org.mifosplatform.portfolio.loanaccount.domain.*; import org.mifosplatform.portfolio.loanaccount.exception.LoanDisbursalException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException; import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException; +import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator; import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer; @@ -109,14 +85,23 @@ import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService; import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException; import org.mifosplatform.useradministration.domain.AppUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import java.math.BigDecimal; +import java.util.*; + + @Service public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatformService { + private final static Logger logger = LoggerFactory.getLogger(LoanWritePlatformServiceJpaRepositoryImpl.class); + + private final PlatformSecurityContext context; private final LoanEventApiJsonValidator loanEventApiJsonValidator; @@ -141,6 +126,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final AccountTransfersReadPlatformService accountTransfersReadPlatformService; private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService; private final LoanChargeReadPlatformService LoanChargeReadPlatformService; + private final LoanReadPlatformService loanReadPlatformService; + private final FromJsonHelper fromApiJsonHelper; + @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -158,7 +146,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final AccountTransfersWritePlatformService accountTransfersWritePlatformService, final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, - final LoanChargeReadPlatformService loanChargeReadPlatformService) { + final LoanChargeReadPlatformService loanChargeReadPlatformService,final LoanReadPlatformService loanReadPlatformService, + final FromJsonHelper fromApiJsonHelper ) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; this.loanAssembler = loanAssembler; @@ -182,6 +171,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.accountTransfersReadPlatformService = accountTransfersReadPlatformService; this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService; this.LoanChargeReadPlatformService = loanChargeReadPlatformService; + this.loanReadPlatformService = loanReadPlatformService; + this.fromApiJsonHelper = fromApiJsonHelper; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -1607,4 +1598,82 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } } + @Override + @CronTarget(jobName = JobName.APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT) + public void applyChargeForOverdueLoans() throws JobExecutionException { + final Collection overdueLoanScheduleData = this.loanReadPlatformService.retrieveAllOverdueLoans(); + if(!overdueLoanScheduleData.isEmpty()) { + for(OverdueLoanScheduleData overdueLoanScheduleData1 : overdueLoanScheduleData){ + try{ + + final JsonElement parsedCommand = fromApiJsonHelper.parse(overdueLoanScheduleData1.toString()); + + final JsonCommand command = JsonCommand.from(overdueLoanScheduleData1.toString(),parsedCommand,this.fromApiJsonHelper,null,null, + null,null,null,overdueLoanScheduleData1.getLoanId(),null,null,null,null,null,null,null); + this.applyChargeToOverdueLoanInstallment(overdueLoanScheduleData1.getLoanId(),overdueLoanScheduleData1.getChargeId(),command); + + }catch(final PlatformApiDataValidationException e){ + final List errors = e.getErrors(); + for (final ApiParameterError error : errors) { + logger.error("Apply Charges due for overdue loans failed for account:" + overdueLoanScheduleData1.getLoanId() + " with message " + + error.getDeveloperMessage()); + } + } + } + } + } + + @Transactional + public void applyChargeToOverdueLoanInstallment(Long loanId, Long loanChargeId,JsonCommand command) { + final Loan loan = this.loanAssembler.assembleFrom(loanId); + checkClientOrGroupActive(loan); + + final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(loanChargeId); + + final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command); + + if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) { + final String errorMessage = "Charge and Loan must have the same currency."; + throw new InvalidCurrencyException("loanCharge", "attach.to.loan", errorMessage); + } + if (loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) { + final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService.retriveLoanAssociation(loanId); + if (portfolioAccountData == null) { + final String errorMessage = loanCharge.name() + "Charge requires linked savings account for payment"; + throw new LinkedAccountRequiredException("loanCharge.add", errorMessage, loanCharge.name()); + } + } + + final List existingTransactionIds = new ArrayList(); + final List existingReversedTransactionIds = new ArrayList(); + this.loanChargeRepository.save(loanCharge); + + final ChangedTransactionDetail changedTransactionDetail = loan.addLoanCharge(loanCharge, existingTransactionIds, + existingReversedTransactionIds); + + // we want to apply charge transactions only for those loans charges + // that are applied when a loan is active + if (loan.status().isActive()) { + final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null); + this.loanTransactionRepository.save(applyLoanChargeTransaction); + /*** + * 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 payment is made before the + * latest payment recorded against the loan) + ***/ + this.loanRepository.saveAndFlush(loan); + if (changedTransactionDetail != null) { + for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { + this.loanTransactionRepository.save(mapEntry.getValue()); + this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); + } + } + + + // we post Journal entries only for loans in active status + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); + } + } } \ No newline at end of file