minor changes to batch jobs code

This commit is contained in:
Vishwas Babu A J
2013-07-13 20:03:29 +05:30
parent bb12ed1c45
commit aa8a6873e0
17 changed files with 354 additions and 293 deletions
@@ -0,0 +1,20 @@
RENAME TABLE `scheduled_jobs` TO `job`;
RENAME TABLE `scheduled_job_runhistory` TO `job_run_history`;
ALTER TABLE `job`
ALTER `job_name` DROP DEFAULT,
ALTER `job_display_name` DROP DEFAULT;
ALTER TABLE `job`
CHANGE COLUMN `job_name` `name` VARCHAR(50) NOT NULL,
CHANGE COLUMN `job_display_name` `display_name` VARCHAR(50) NOT NULL;
ALTER TABLE `job`
CHANGE COLUMN `job_initializing_errorlog` `initializing_errorlog` TEXT NULL;
ALTER TABLE `job_run_history`
ALTER `triggertype` DROP DEFAULT;
ALTER TABLE `job_run_history`
CHANGE COLUMN `errormessage` `error_message` VARCHAR(500) NULL DEFAULT NULL,
CHANGE COLUMN `triggertype` `trigger_type` VARCHAR(25) NOT NULL,
CHANGE COLUMN `errorlog` `error_log` TEXT NULL;
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.annotation;
package org.mifosplatform.infrastructure.jobs.annotation;
import java.io.IOException;
import java.lang.annotation.Annotation;
@@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -38,11 +39,11 @@ public class CronMethodParser {
public static final int METHOD_INDEX = 1;
public static String[] findTargetMethodDetails(String attriuteValue) throws IOException {
if (!targetMethosMap.containsKey(attriuteValue)) {
findAnnotationMethods(CronTargetMethod.class, CRON_ANNOTATION_ATTRIBUTE_NAME);
public static String[] findTargetMethodDetails(String attributeValue) throws IOException {
if (!targetMethosMap.containsKey(attributeValue)) {
findAnnotationMethods(CronTarget.class, CRON_ANNOTATION_ATTRIBUTE_NAME);
}
return targetMethosMap.get(attriuteValue);
return targetMethosMap.get(attributeValue);
}
/**
@@ -61,13 +62,20 @@ public class CronMethodParser {
if (metadataSet != null && metadataSet.size() > 0) {
for (MethodMetadata metadata : metadataSet) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(annotationClass.getName());
String attributeValue = (String) attributes.get(attributeName);
JobName attributeValue = (JobName) attributes.get(attributeName);
String className = metadata.getDeclaringClassName();
if (attributeValue == null || attributeValue.trim().length() < 1) {
attributeValue = className.substring(className.lastIndexOf(".") + 1);
}
/**
* TODO: Vishwas, have commented out this piece of code,
* check its need with Pramod
**/
/**
* if (attributeValue == null ||
* attributeValue.trim().length() < 1) { attributeValue
* = className.substring(className.lastIndexOf(".") +
* 1); }
**/
String[] mapVal = { className, metadata.getMethodName() };
targetMethosMap.put(attributeValue, mapVal);
targetMethosMap.put(attributeValue.toString(), mapVal);
}
}
}
@@ -1,10 +1,12 @@
package org.mifosplatform.scheduledjobs.annotation;
package org.mifosplatform.infrastructure.jobs.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.mifosplatform.infrastructure.jobs.service.JobName;
/**
* Annotation that marks a method to be picked while scheduling a cron jobs.
*
@@ -12,7 +14,7 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CronTargetMethod {
public @interface CronTarget {
String jobName() default "";
JobName jobName();
}
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.domain;
package org.mifosplatform.infrastructure.jobs.domain;
import java.util.Date;
@@ -11,13 +11,13 @@ import javax.persistence.TemporalType;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "scheduled_jobs")
public class ScheduledJobDetails extends AbstractPersistable<Long> {
@Table(name = "job")
public class ScheduledJobDetail extends AbstractPersistable<Long> {
@Column(name = "job_name")
@Column(name = "name")
private String jobName;
@Column(name = "job_display_name")
@Column(name = "display_name")
private String jobDisplayName;
@Column(name = "cron_expression")
@@ -44,17 +44,17 @@ public class ScheduledJobDetails extends AbstractPersistable<Long> {
@Column(name = "trigger_key")
private String triggerKey;
@Column(name = "job_initializing_errorlog")
@Column(name = "initializing_errorlog")
private String errorLog;
@Column(name = "is_active")
private boolean activeSchedular;
public ScheduledJobDetails() {
public ScheduledJobDetail() {
}
public ScheduledJobDetails(final String jobName, final String jobDisplayName, final String croneExpression, Date createTime,
public ScheduledJobDetail(final String jobName, final String jobDisplayName, final String croneExpression, Date createTime,
final Short taskPriority, final String groupName, final Date previousRunStartTime, final Date nextRunTime,
final String triggKey, final String errorLog, final boolean activeSchedular) {
this.jobName = jobName;
@@ -0,0 +1,14 @@
package org.mifosplatform.infrastructure.jobs.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ScheduledJobDetailRepository extends JpaRepository<ScheduledJobDetail, Long>,
JpaSpecificationExecutor<ScheduledJobDetail> {
@Query("from ScheduledJobDetail jobDetail where jobDetail.triggerKey = :triggerKey")
ScheduledJobDetail findByTriggerKey(@Param("triggerKey") String triggerKey);
}
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.domain;
package org.mifosplatform.infrastructure.jobs.domain;
import java.util.Date;
@@ -13,12 +13,12 @@ import javax.persistence.TemporalType;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "scheduled_job_runhistory")
@Table(name = "job_run_history")
public class ScheduledJobRunHistory extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "job_id")
private ScheduledJobDetails scheduledJobDetails;
private ScheduledJobDetail scheduledJobDetail;
@Column(name = "version")
private Long version;
@@ -34,22 +34,22 @@ public class ScheduledJobRunHistory extends AbstractPersistable<Long> {
@Column(name = "status")
private String status;
@Column(name = "errormessage")
@Column(name = "error_message")
private String errorMessage;
@Column(name = "triggertype")
@Column(name = "trigger_type")
private String triggerType;
@Column(name = "errorlog")
@Column(name = "error_log")
private String errorLog;
public ScheduledJobRunHistory() {
}
public ScheduledJobRunHistory(final ScheduledJobDetails scheduledJobDetails, final Long version, final Date startTime,
public ScheduledJobRunHistory(final ScheduledJobDetail scheduledJobDetail, final Long version, final Date startTime,
final Date endTime, final String status, final String errorMessage, final String triggerType, final String errorLog) {
this.scheduledJobDetails = scheduledJobDetails;
this.scheduledJobDetail = scheduledJobDetail;
this.version = version;
this.startTime = startTime;
this.endTime = endTime;
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.domain;
package org.mifosplatform.infrastructure.jobs.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -8,7 +8,7 @@ import org.springframework.data.repository.query.Param;
public interface ScheduledJobRunHistoryRepository extends JpaRepository<ScheduledJobRunHistory, Long>,
JpaSpecificationExecutor<ScheduledJobRunHistory> {
@Query("select max(sjrh.version) from ScheduledJobRunHistory sjrh where sjrh.scheduledJobDetails.triggerKey = :triggerKey")
@Query("select max(sjrh.version) from ScheduledJobRunHistory sjrh where sjrh.scheduledJobDetail.triggerKey = :triggerKey")
Long findMaxVersionByTriggerKey(@Param("triggerKey") String triggerKey);
}
@@ -0,0 +1,19 @@
package org.mifosplatform.infrastructure.jobs.service;
public enum JobName {
UPDATE_LOAN_SUMMARY("Update loan Summary"), UPDATE_LOAN_ARREARS_AGEING("Update Loan Arrears Ageing"), UPDATE_LOAN_PAID_IN_ADVANCE(
"Update Loan Paid In Advance"), APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"), APPLY_HOLIDAYS_TO_LOANS(
"Apply Holidays To Loans");
private final String name;
JobName(final String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.service;
package org.mifosplatform.infrastructure.jobs.service;
import java.util.List;
import java.util.TimeZone;
@@ -7,9 +7,9 @@ import javax.annotation.PostConstruct;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.infrastructure.jobs.annotation.CronMethodParser;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
import org.mifosplatform.scheduledjobs.annotation.CronMethodParser;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobDetails;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
@@ -54,8 +54,8 @@ public class JobRegisterService {
List<MifosPlatformTenant> allTenants = this.tenantDetailsService.findAllTenants();
for (MifosPlatformTenant tenant : allTenants) {
ThreadLocalContextUtil.setTenant(tenant);
List<ScheduledJobDetails> scheduledJobDetails = this.schedularService.getScheduledJobDetails();
for (ScheduledJobDetails jobDetails : scheduledJobDetails) {
List<ScheduledJobDetail> scheduledJobDetails = this.schedularService.getScheduledJobDetails();
for (ScheduledJobDetail jobDetails : scheduledJobDetails) {
if (jobDetails.isActiveSchedular()) {
scheduleJob(jobDetails);
this.schedularService.saveOrUpdate(jobDetails);
@@ -76,7 +76,7 @@ public class JobRegisterService {
}
public void rescheduleJob(ScheduledJobDetails scheduledJobDetails) {
public void rescheduleJob(ScheduledJobDetail scheduledJobDetails) {
try {
String triggerIdentity = scheduledJobDetails.getTriggerKey();
String[] triggerKeyIds = triggerIdentity.split(SchedularServiceConstants.TRIGGER_KEY_SEPERATOR);
@@ -95,7 +95,7 @@ public class JobRegisterService {
}
}
private void scheduleJob(ScheduledJobDetails scheduledJobDetails) {
private void scheduleJob(ScheduledJobDetail scheduledJobDetails) {
try {
JobDetail jobDetail = createJobDetail(scheduledJobDetails);
Trigger trigger = createTrigger(scheduledJobDetails, jobDetail);
@@ -109,7 +109,7 @@ public class JobRegisterService {
}
}
private JobDetail createJobDetail(ScheduledJobDetails scheduledJobDetails) throws Exception {
private JobDetail createJobDetail(ScheduledJobDetail scheduledJobDetails) throws Exception {
MifosPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
String[] jobDetails = CronMethodParser.findTargetMethodDetails(scheduledJobDetails.getJobName());
String[] beanNames = this.applicationContext.getBeanNamesForType(Class.forName(jobDetails[CronMethodParser.CLASS_INDEX]));
@@ -134,7 +134,7 @@ public class JobRegisterService {
* @param scheduledJobDetails
* @return
*/
private Trigger createTrigger(ScheduledJobDetails scheduledJobDetails, JobDetail jobDetail) {
private Trigger createTrigger(ScheduledJobDetail scheduledJobDetails, JobDetail jobDetail) {
MifosPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setName(scheduledJobDetails.getJobName() + "Trigger-" + tenant.getId());
@@ -0,0 +1,20 @@
package org.mifosplatform.infrastructure.jobs.service;
import java.util.List;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
public interface SchedularService {
public List<ScheduledJobDetail> getScheduledJobDetails();
public ScheduledJobDetail getByTriggerKey(String triggerKey);
public void saveOrUpdate(ScheduledJobDetail scheduledJobDetails);
public void saveOrUpdate(ScheduledJobDetail scheduledJobDetails, ScheduledJobRunHistory scheduledJobRunHistory);
public Long getMaxVersionBy(String triggerKey);
}
@@ -1,4 +1,4 @@
package org.mifosplatform.scheduledjobs.service;
package org.mifosplatform.infrastructure.jobs.service;
public interface SchedularServiceConstants {
@@ -1,11 +1,11 @@
package org.mifosplatform.scheduledjobs.service;
package org.mifosplatform.infrastructure.jobs.service;
import java.util.List;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobDetails;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobDetailsRepository;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobRunHistory;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobRunHistoryRepository;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetailRepository;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -13,36 +13,36 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class SchedularServiceJpaRepositoryImpl implements SchedularService {
private final ScheduledJobDetailsRepository scheduledJobDetailsRepository;
private final ScheduledJobDetailRepository scheduledJobDetailsRepository;
private final ScheduledJobRunHistoryRepository scheduledJobRunHistoryRepository;
@Autowired
public SchedularServiceJpaRepositoryImpl(final ScheduledJobDetailsRepository scheduledJobDetailsRepository,
public SchedularServiceJpaRepositoryImpl(final ScheduledJobDetailRepository scheduledJobDetailsRepository,
final ScheduledJobRunHistoryRepository scheduledJobRunHistoryRepository) {
this.scheduledJobDetailsRepository = scheduledJobDetailsRepository;
this.scheduledJobRunHistoryRepository = scheduledJobRunHistoryRepository;
}
@Override
public List<ScheduledJobDetails> getScheduledJobDetails() {
public List<ScheduledJobDetail> getScheduledJobDetails() {
return scheduledJobDetailsRepository.findAll();
}
@Override
public ScheduledJobDetails getByTriggerKey(final String triggerKey) {
public ScheduledJobDetail getByTriggerKey(final String triggerKey) {
return scheduledJobDetailsRepository.findByTriggerKey(triggerKey);
}
@Transactional
@Override
public void saveOrUpdate(final ScheduledJobDetails scheduledJobDetails) {
public void saveOrUpdate(final ScheduledJobDetail scheduledJobDetails) {
this.scheduledJobDetailsRepository.save(scheduledJobDetails);
}
@Transactional
@Override
public void saveOrUpdate(final ScheduledJobDetails scheduledJobDetails, final ScheduledJobRunHistory scheduledJobRunHistory) {
public void saveOrUpdate(final ScheduledJobDetail scheduledJobDetails, final ScheduledJobRunHistory scheduledJobRunHistory) {
this.scheduledJobDetailsRepository.save(scheduledJobDetails);
this.scheduledJobRunHistoryRepository.save(scheduledJobRunHistory);
}
@@ -1,12 +1,12 @@
package org.mifosplatform.scheduledjobs.service;
package org.mifosplatform.infrastructure.jobs.service;
import java.util.Date;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobDetails;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobRunHistory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
@@ -60,7 +60,7 @@ public class SchedulerJobListener implements JobListener {
Trigger trigger = context.getTrigger();
TriggerKey key = trigger.getKey();
String triggerKey = key.getName() + SchedularServiceConstants.TRIGGER_KEY_SEPERATOR + key.getGroup();
final ScheduledJobDetails scheduledJobDetails = schedularService.getByTriggerKey(triggerKey);
final ScheduledJobDetail scheduledJobDetails = schedularService.getByTriggerKey(triggerKey);
Long version = schedularService.getMaxVersionBy(triggerKey) + 1;
String status = SchedularServiceConstants.STATUS_SUCCESS;
String errorMessage = null;
@@ -21,6 +21,8 @@ import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomain
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.holiday.domain.Holiday;
import org.mifosplatform.organisation.holiday.domain.HolidayRepository;
@@ -75,7 +77,6 @@ import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
import org.mifosplatform.scheduledjobs.annotation.CronTargetMethod;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -113,8 +114,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final JournalEntryWritePlatformService journalEntryWritePlatformService, final LoanSummaryWrapper loanSummaryWrapper,
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
final LoanScheduleGeneratorFactory loanScheduleFactory, final CalendarInstanceRepository calendarInstanceRepository,
final PaymentDetailWritePlatformService paymentDetailWritePlatformService,
final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService) {
final PaymentDetailWritePlatformService paymentDetailWritePlatformService, final HolidayRepository holidayRepository,
final ConfigurationDomainService configurationDomainService) {
this.context = context;
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
this.loanAssembler = loanAssembler;
@@ -149,15 +150,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateDisbursement(command.json());
final Loan loan = retrieveLoanBy(loanId);
// validate actual disbursement date against meeting date
// validate actual disbursement date against meeting date
final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByLoanId(loan.getId(),
CalendarEntityType.LOANS.getValue());
if(loan.isSyncDisbursementWithMeeting()){
if (loan.isSyncDisbursementWithMeeting()) {
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
this.loanEventApiJsonValidator.validateDisbursementDateWithMeetingDate(actualDisbursementDate, calendarInstance);
this.loanEventApiJsonValidator.validateDisbursementDateWithMeetingDate(actualDisbursementDate, calendarInstance);
}
final MonetaryCurrency currency = loan.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
@@ -168,12 +169,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
//Recalculate first repayment date based in actual disbursement date.
// Recalculate first repayment date based in actual disbursement date.
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
final LocalDate firstRepaymentMeetingDate = getFirstRepaymentMeetingDate(actualDisbursementDate, loan, calendarInstance);
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), actualDisbursementDate.toDate());
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
actualDisbursementDate.toDate());
updateLoanCounters(loan, actualDisbursementDate);
loan.disburse(this.loanScheduleFactory, currentUser, command, applicationCurrency, existingTransactionIds,
@@ -202,39 +204,33 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
.build();
}
private LocalDate getFirstRepaymentMeetingDate(
final LocalDate actualDisbursementDate, final Loan loan,
final CalendarInstance calendarInstance) {
final Calendar calendar = (calendarInstance == null) ? null
: calendarInstance.getCalendar();
LocalDate firstRepaymentMeetingDate = null;
if (calendar != null) {// sync repayments
private LocalDate getFirstRepaymentMeetingDate(final LocalDate actualDisbursementDate, final Loan loan,
final CalendarInstance calendarInstance) {
final Calendar calendar = (calendarInstance == null) ? null : calendarInstance.getCalendar();
LocalDate firstRepaymentMeetingDate = null;
if (calendar != null) {// sync repayments
// TODO: AA - user provided first repayment date takes precedence
// over recalculated meeting date
if (loan.getExpectedFirstRepaymentOnDate() == null) {
// FIXME: AA - Possibility of having next meeting date
// immediately after disbursement date,
// need to have minimum number of days gap between disbursement
// and first repayment date.
final LoanProductRelatedDetail repaymentScheduleDetails = loan.repaymentScheduleDetail();
if (repaymentScheduleDetails != null) {// Not expecting to be
// null
final Integer repayEvery = repaymentScheduleDetails.getRepayEvery();
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentScheduleDetails
.getRepaymentPeriodFrequencyType());
firstRepaymentMeetingDate = CalendarHelper.getFirstRepaymentMeetingDate(calendar, actualDisbursementDate, repayEvery,
frequency);
}
}
}
return firstRepaymentMeetingDate;
}
// TODO: AA - user provided first repayment date takes precedence over recalculated meeting date
if (loan.getExpectedFirstRepaymentOnDate() == null) {
// FIXME: AA - Possibility of having next meeting date
// immediately after disbursement date,
// need to have minimum number of days gap between disbursement
// and first repayment date.
final LoanProductRelatedDetail repaymentScheduleDetails = loan
.repaymentScheduleDetail();
if (repaymentScheduleDetails != null) {// Not expecting to be
// null
final Integer repayEvery = repaymentScheduleDetails
.getRepayEvery();
final String frequency = CalendarHelper
.getMeetingFrequencyFromPeriodFrequencyType(repaymentScheduleDetails
.getRepaymentPeriodFrequencyType());
firstRepaymentMeetingDate = CalendarHelper
.getFirstRepaymentMeetingDate(calendar,
actualDisbursementDate, repayEvery,
frequency);
}
}
}
return firstRepaymentMeetingDate;
}
/****
* TODO Vishwas: Pair with Ashok and re-factor collection sheet code-base
*****/
@@ -259,9 +255,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
// Bulk disbursement should happen on meeting date (mostly from collection sheet).
//FIXME: AA - this should be first meeting date based on disbursement date and next available meeting dates
//assuming repayment schedule won't regenerate because expected disbursement and actual disbursement happens on same date
// Bulk disbursement should happen on meeting date (mostly from
// collection sheet).
// FIXME: AA - this should be first meeting date based on
// disbursement date and next available meeting dates
// assuming repayment schedule won't regenerate because expected
// disbursement and actual disbursement happens on same date
final LocalDate firstRepaymentOnDate = null;
final boolean isHolidayEnabled = false;
final List<Holiday> holidays = null;
@@ -358,15 +357,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private CommandProcessingResultBuilder saveLoanRepayment(final Long loanId, final PaymentDetail paymentDetail,
final BigDecimal transactionAmount, final LocalDate transactionDate, final String noteText) {
final Loan loan = retrieveLoanBy(loanId);
//TODO: Is it required to validate transaction date with meeting dates if repayments is synced with meeting?
/*if(loan.isSyncDisbursementWithMeeting()){
// validate actual disbursement date against meeting date
CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByLoanId(loan.getId(),
CalendarEntityType.LOANS.getValue());
this.loanEventApiJsonValidator.validateRepaymentDateWithMeetingDate(transactionDate, calendarInstance);
}*/
// TODO: Is it required to validate transaction date with meeting dates
// if repayments is synced with meeting?
/*
* if(loan.isSyncDisbursementWithMeeting()){ // validate actual
* disbursement date against meeting date CalendarInstance
* calendarInstance =
* this.calendarInstanceRepository.findCalendarInstaneByLoanId
* (loan.getId(), CalendarEntityType.LOANS.getValue());
* this.loanEventApiJsonValidator
* .validateRepaymentDateWithMeetingDate(transactionDate,
* calendarInstance); }
*/
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
@@ -1008,29 +1012,30 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
@Transactional
@Override
public void updateRepaymentsSchedule(final Calendar calendar, Collection<CalendarInstance> loanCalendarInstances) {
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
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
// 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);
List<Holiday> holidays = null;
//loop through each loan to reschedule the repayment dates
// loop through each loan to reschedule the repayment dates
for (Loan loan : loans) {
if(loan != null){
if (loan != null) {
holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate());
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled, holidays);
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
holidays);
this.loanRepository.save(loan);
}
}
}
private void removeLoanCycle(final Loan loan) {
final List<Loan> loansToUpdate;
if (loan.isGroupLoan()) {
@@ -1059,7 +1064,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.updateLoanProductLoanCounter(null);
}
private void updateLoanCounters(final Loan loan, final LocalDate actualDisbursementDate) {
if (loan.isGroupLoan()) {
@@ -1105,7 +1110,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final boolean includeInBorrowerCycle = loan.loanProduct().isIncludeInBorrowerCycle();
for (final Loan loanToUpdate : loansToUpdateForLoanCounter) {
//Update client loan counter if loan product includeInBorrowerCycle is true
// Update client loan counter if loan product includeInBorrowerCycle
// is true
if (includeInBorrowerCycle) {
Integer currentLoanCounter = loanToUpdate.getCurrentLoanCounter();
if (newLoanCounter > currentLoanCounter) {
@@ -1154,7 +1160,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
return maxLoanProductLoanCounter;
}
private void updateLoanCycleCounter(final List<Loan> loansToUpdate, final Loan loan) {
final Integer currentLoancounter = loan.getCurrentLoanCounter();
@@ -1176,11 +1182,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
this.loanRepository.save(loansToUpdate);
}
@Transactional
@Override
@CronTargetMethod(jobName="Apply Holidays To Loans")
public void applyHolidaysToLoans() {
@CronTarget(jobName = JobName.APPLY_HOLIDAYS_TO_LOANS)
public void applyHolidaysToLoans() {
final Collection<Integer> loanStatuses = new ArrayList<Integer>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
@@ -1198,10 +1204,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
// get all loans
List<Loan> loans = new ArrayList<Loan>();
//get all individual and jlg loans
// get all individual and jlg loans
loans.addAll(this.loanRepository.findByClientOfficeIdsAndLoanStatus(officeIds, loanStatuses));
//FIXME: optimize to get all client and group loans belongs to a office id
//get all group loans
// FIXME: optimize to get all client and group loans belongs to a
// office id
// get all group loans
loans.addAll(this.loanRepository.findByGroupOfficeIdsAndLoanStatus(officeIds, loanStatuses));
for (Loan loan : loans) {
@@ -1210,7 +1217,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
this.loanRepository.save(loans);
holiday.processed();
}
}
this.holidayRepository.save(holidays);
}
}
@@ -1,14 +0,0 @@
package org.mifosplatform.scheduledjobs.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ScheduledJobDetailsRepository extends JpaRepository<ScheduledJobDetails, Long>,
JpaSpecificationExecutor<ScheduledJobDetails> {
@Query("from ScheduledJobDetails jobDetails where jobDetails.triggerKey = :triggerKey")
ScheduledJobDetails findByTriggerKey(@Param("triggerKey") String triggerKey);
}
@@ -1,20 +0,0 @@
package org.mifosplatform.scheduledjobs.service;
import java.util.List;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobDetails;
import org.mifosplatform.scheduledjobs.domain.ScheduledJobRunHistory;
public interface SchedularService {
public List<ScheduledJobDetails> getScheduledJobDetails();
public ScheduledJobDetails getByTriggerKey(String triggerKey);
public void saveOrUpdate(ScheduledJobDetails scheduledJobDetails);
public void saveOrUpdate(ScheduledJobDetails scheduledJobDetails, ScheduledJobRunHistory scheduledJobRunHistory);
public Long getMaxVersionBy(String triggerKey);
}
@@ -9,8 +9,9 @@ import java.util.List;
import org.mifosplatform.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.mifosplatform.scheduledjobs.annotation.CronTargetMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,171 +35,175 @@ public class ScheduledJobRunnerServiceImpl implements ScheduledJobRunnerService
@Transactional
@Override
@CronTargetMethod(jobName="Update loan Summary")
@CronTarget(jobName = JobName.UPDATE_LOAN_SUMMARY)
public void updateLoanSummaryDetails() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
StringBuilder updateSqlBuilder = new StringBuilder(900);
updateSqlBuilder.append("update m_loan ");
updateSqlBuilder.append("join (");
updateSqlBuilder.append("SELECT ml.id AS loanId,");
updateSqlBuilder.append("SUM(mr.principal_amount) as principal_disbursed_derived, ");
updateSqlBuilder.append("SUM(IFNULL(mr.principal_completed_derived,0)) as principal_repaid_derived, ");
updateSqlBuilder.append("SUM(IFNULL(mr.principal_writtenoff_derived,0)) as principal_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_amount,0)) as interest_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_completed_derived,0)) as interest_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_waived_derived,0)) as interest_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_writtenoff_derived,0)) as interest_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_amount,0)) as fee_charges_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) as fee_charges_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_waived_derived,0)) as fee_charges_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_writtenoff_derived,0)) as fee_charges_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_amount,0)) as penalty_charges_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_completed_derived,0)) as penalty_charges_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_waived_derived,0)) as penalty_charges_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_writtenoff_derived,0)) as penalty_charges_writtenoff_derived ");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append("INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append("WHERE ml.disbursedon_date is not null ");
updateSqlBuilder.append("GROUP BY ml.id ");
updateSqlBuilder.append(") x on x.loanId = m_loan.id ");
StringBuilder updateSqlBuilder = new StringBuilder(900);
updateSqlBuilder.append("update m_loan ");
updateSqlBuilder.append("join (");
updateSqlBuilder.append("SELECT ml.id AS loanId,");
updateSqlBuilder.append("SUM(mr.principal_amount) as principal_disbursed_derived, ");
updateSqlBuilder.append("SUM(IFNULL(mr.principal_completed_derived,0)) as principal_repaid_derived, ");
updateSqlBuilder.append("SUM(IFNULL(mr.principal_writtenoff_derived,0)) as principal_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_amount,0)) as interest_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_completed_derived,0)) as interest_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_waived_derived,0)) as interest_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.interest_writtenoff_derived,0)) as interest_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_amount,0)) as fee_charges_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) as fee_charges_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_waived_derived,0)) as fee_charges_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.fee_charges_writtenoff_derived,0)) as fee_charges_writtenoff_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_amount,0)) as penalty_charges_charged_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_completed_derived,0)) as penalty_charges_repaid_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_waived_derived,0)) as penalty_charges_waived_derived,");
updateSqlBuilder.append("SUM(IFNULL(mr.penalty_charges_writtenoff_derived,0)) as penalty_charges_writtenoff_derived ");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append("INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append("WHERE ml.disbursedon_date is not null ");
updateSqlBuilder.append("GROUP BY ml.id ");
updateSqlBuilder.append(") x on x.loanId = m_loan.id ");
updateSqlBuilder.append("SET m_loan.principal_disbursed_derived = x.principal_disbursed_derived,");
updateSqlBuilder.append("m_loan.principal_repaid_derived = x.principal_repaid_derived,");
updateSqlBuilder.append("m_loan.principal_writtenoff_derived = x.principal_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.principal_outstanding_derived = (x.principal_disbursed_derived - (x.principal_repaid_derived + x.principal_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.interest_charged_derived = x.interest_charged_derived,");
updateSqlBuilder.append("m_loan.interest_repaid_derived = x.interest_repaid_derived,");
updateSqlBuilder.append("m_loan.interest_waived_derived = x.interest_waived_derived,");
updateSqlBuilder.append("m_loan.interest_writtenoff_derived = x.interest_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.interest_outstanding_derived = (x.interest_charged_derived - (x.interest_repaid_derived + x.interest_waived_derived + x.interest_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.fee_charges_charged_derived = x.fee_charges_charged_derived,");
updateSqlBuilder.append("m_loan.fee_charges_repaid_derived = x.fee_charges_repaid_derived,");
updateSqlBuilder.append("m_loan.fee_charges_waived_derived = x.fee_charges_waived_derived,");
updateSqlBuilder.append("m_loan.fee_charges_writtenoff_derived = x.fee_charges_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.fee_charges_outstanding_derived = (x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.penalty_charges_charged_derived = x.penalty_charges_charged_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_repaid_derived = x.penalty_charges_repaid_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_waived_derived = x.penalty_charges_waived_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_writtenoff_derived = x.penalty_charges_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.penalty_charges_outstanding_derived = (x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived)),");
updateSqlBuilder
.append("m_loan.total_expected_repayment_derived = (x.principal_disbursed_derived + x.interest_charged_derived + x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
updateSqlBuilder
.append("m_loan.total_repayment_derived = (x.principal_repaid_derived + x.interest_repaid_derived + x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
updateSqlBuilder
.append("m_loan.total_expected_costofloan_derived = (x.interest_charged_derived + x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
updateSqlBuilder
.append("m_loan.total_costofloan_derived = (x.interest_repaid_derived + x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
updateSqlBuilder
.append("m_loan.total_waived_derived = (x.interest_waived_derived + x.fee_charges_waived_derived + x.penalty_charges_waived_derived),");
updateSqlBuilder
.append("m_loan.total_writtenoff_derived = (x.interest_writtenoff_derived + x.fee_charges_writtenoff_derived + x.penalty_charges_writtenoff_derived),");
updateSqlBuilder.append("m_loan.total_outstanding_derived=");
updateSqlBuilder.append(" (x.principal_disbursed_derived - (x.principal_repaid_derived + x.principal_writtenoff_derived)) + ");
updateSqlBuilder
.append(" (x.interest_charged_derived - (x.interest_repaid_derived + x.interest_waived_derived + x.interest_writtenoff_derived)) +");
updateSqlBuilder
.append(" (x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)) +");
updateSqlBuilder
.append(" (x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived))");
updateSqlBuilder.append("SET m_loan.principal_disbursed_derived = x.principal_disbursed_derived,");
updateSqlBuilder.append("m_loan.principal_repaid_derived = x.principal_repaid_derived,");
updateSqlBuilder.append("m_loan.principal_writtenoff_derived = x.principal_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.principal_outstanding_derived = (x.principal_disbursed_derived - (x.principal_repaid_derived + x.principal_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.interest_charged_derived = x.interest_charged_derived,");
updateSqlBuilder.append("m_loan.interest_repaid_derived = x.interest_repaid_derived,");
updateSqlBuilder.append("m_loan.interest_waived_derived = x.interest_waived_derived,");
updateSqlBuilder.append("m_loan.interest_writtenoff_derived = x.interest_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.interest_outstanding_derived = (x.interest_charged_derived - (x.interest_repaid_derived + x.interest_waived_derived + x.interest_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.fee_charges_charged_derived = x.fee_charges_charged_derived,");
updateSqlBuilder.append("m_loan.fee_charges_repaid_derived = x.fee_charges_repaid_derived,");
updateSqlBuilder.append("m_loan.fee_charges_waived_derived = x.fee_charges_waived_derived,");
updateSqlBuilder.append("m_loan.fee_charges_writtenoff_derived = x.fee_charges_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.fee_charges_outstanding_derived = (x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)),");
updateSqlBuilder.append("m_loan.penalty_charges_charged_derived = x.penalty_charges_charged_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_repaid_derived = x.penalty_charges_repaid_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_waived_derived = x.penalty_charges_waived_derived,");
updateSqlBuilder.append("m_loan.penalty_charges_writtenoff_derived = x.penalty_charges_writtenoff_derived,");
updateSqlBuilder
.append("m_loan.penalty_charges_outstanding_derived = (x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived)),");
updateSqlBuilder
.append("m_loan.total_expected_repayment_derived = (x.principal_disbursed_derived + x.interest_charged_derived + x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
updateSqlBuilder
.append("m_loan.total_repayment_derived = (x.principal_repaid_derived + x.interest_repaid_derived + x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
updateSqlBuilder
.append("m_loan.total_expected_costofloan_derived = (x.interest_charged_derived + x.fee_charges_charged_derived + x.penalty_charges_charged_derived),");
updateSqlBuilder
.append("m_loan.total_costofloan_derived = (x.interest_repaid_derived + x.fee_charges_repaid_derived + x.penalty_charges_repaid_derived),");
updateSqlBuilder
.append("m_loan.total_waived_derived = (x.interest_waived_derived + x.fee_charges_waived_derived + x.penalty_charges_waived_derived),");
updateSqlBuilder
.append("m_loan.total_writtenoff_derived = (x.interest_writtenoff_derived + x.fee_charges_writtenoff_derived + x.penalty_charges_writtenoff_derived),");
updateSqlBuilder.append("m_loan.total_outstanding_derived=");
updateSqlBuilder.append(" (x.principal_disbursed_derived - (x.principal_repaid_derived + x.principal_writtenoff_derived)) + ");
updateSqlBuilder
.append(" (x.interest_charged_derived - (x.interest_repaid_derived + x.interest_waived_derived + x.interest_writtenoff_derived)) +");
updateSqlBuilder
.append(" (x.fee_charges_charged_derived - (x.fee_charges_repaid_derived + x.fee_charges_waived_derived + x.fee_charges_writtenoff_derived)) +");
updateSqlBuilder
.append(" (x.penalty_charges_charged_derived - (x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived + x.penalty_charges_writtenoff_derived))");
int result = jdbcTemplate.update(updateSqlBuilder.toString());
int result = jdbcTemplate.update(updateSqlBuilder.toString());
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
}
@Transactional
@Override
@CronTargetMethod(jobName="Update Loan Arrears Ageing")
@CronTarget(jobName = JobName.UPDATE_LOAN_ARREARS_AGEING)
public void updateLoanArrearsAgeingDetails() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
jdbcTemplate.execute("truncate table m_loan_arrears_aging");
jdbcTemplate.execute("truncate table m_loan_arrears_aging");
StringBuilder updateSqlBuilder = new StringBuilder(900);
StringBuilder updateSqlBuilder = new StringBuilder(900);
updateSqlBuilder
.append("INSERT INTO m_loan_arrears_aging(`loan_id`,`principal_overdue_derived`,`interest_overdue_derived`,`fee_charges_overdue_derived`,`penalty_charges_overdue_derived`,`total_overdue_derived`,`overdue_since_date_derived`)");
updateSqlBuilder.append("select ml.id as loanId,");
updateSqlBuilder
.append("SUM((ifnull(mr.principal_amount,0) - ifnull(mr.principal_completed_derived, 0))) as principal_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.interest_amount,0) - ifnull(mr.interest_completed_derived, 0))) as interest_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.fee_charges_amount,0) - ifnull(mr.fee_charges_completed_derived, 0))) as fee_charges_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.penalty_charges_amount,0) - ifnull(mr.penalty_charges_completed_derived, 0))) as penalty_charges_overdue_derived,");
updateSqlBuilder.append("SUM((ifnull(mr.principal_amount,0) - ifnull(mr.principal_completed_derived, 0))) +");
updateSqlBuilder.append("SUM((ifnull(mr.interest_amount,0) - ifnull(mr.interest_completed_derived, 0))) +");
updateSqlBuilder.append("SUM((ifnull(mr.fee_charges_amount,0) - ifnull(mr.fee_charges_completed_derived, 0))) +");
updateSqlBuilder
.append("SUM((ifnull(mr.penalty_charges_amount,0) - ifnull(mr.penalty_charges_completed_derived, 0))) as total_overdue_derived,");
updateSqlBuilder.append("MIN(mr.duedate) as overdue_since_date_derived ");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append(" INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append(" WHERE ml.loan_status_id = 300 "); // active
updateSqlBuilder.append(" and mr.completed_derived is false ");
updateSqlBuilder.append(" and mr.duedate < CURDATE() ");
updateSqlBuilder.append(" GROUP BY ml.id");
updateSqlBuilder
.append("INSERT INTO m_loan_arrears_aging(`loan_id`,`principal_overdue_derived`,`interest_overdue_derived`,`fee_charges_overdue_derived`,`penalty_charges_overdue_derived`,`total_overdue_derived`,`overdue_since_date_derived`)");
updateSqlBuilder.append("select ml.id as loanId,");
updateSqlBuilder
.append("SUM((ifnull(mr.principal_amount,0) - ifnull(mr.principal_completed_derived, 0))) as principal_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.interest_amount,0) - ifnull(mr.interest_completed_derived, 0))) as interest_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.fee_charges_amount,0) - ifnull(mr.fee_charges_completed_derived, 0))) as fee_charges_overdue_derived,");
updateSqlBuilder
.append("SUM((ifnull(mr.penalty_charges_amount,0) - ifnull(mr.penalty_charges_completed_derived, 0))) as penalty_charges_overdue_derived,");
updateSqlBuilder.append("SUM((ifnull(mr.principal_amount,0) - ifnull(mr.principal_completed_derived, 0))) +");
updateSqlBuilder.append("SUM((ifnull(mr.interest_amount,0) - ifnull(mr.interest_completed_derived, 0))) +");
updateSqlBuilder.append("SUM((ifnull(mr.fee_charges_amount,0) - ifnull(mr.fee_charges_completed_derived, 0))) +");
updateSqlBuilder
.append("SUM((ifnull(mr.penalty_charges_amount,0) - ifnull(mr.penalty_charges_completed_derived, 0))) as total_overdue_derived,");
updateSqlBuilder.append("MIN(mr.duedate) as overdue_since_date_derived ");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append(" INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append(" WHERE ml.loan_status_id = 300 "); // active
updateSqlBuilder.append(" and mr.completed_derived is false ");
updateSqlBuilder.append(" and mr.duedate < CURDATE() ");
updateSqlBuilder.append(" GROUP BY ml.id");
int result = jdbcTemplate.update(updateSqlBuilder.toString());
int result = jdbcTemplate.update(updateSqlBuilder.toString());
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
}
@Transactional
@Override
@CronTargetMethod(jobName="Update Loan Paid In Advance")
@CronTarget(jobName = JobName.UPDATE_LOAN_PAID_IN_ADVANCE)
public void updateLoanPaidInAdvance() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
jdbcTemplate.execute("truncate table m_loan_paid_in_advance");
jdbcTemplate.execute("truncate table m_loan_paid_in_advance");
StringBuilder updateSqlBuilder = new StringBuilder(900);
StringBuilder updateSqlBuilder = new StringBuilder(900);
updateSqlBuilder.append("INSERT INTO m_loan_paid_in_advance(loan_id, principal_in_advance_derived, interest_in_advance_derived, fee_charges_in_advance_derived, penalty_charges_in_advance_derived, total_in_advance_derived)");
updateSqlBuilder.append(" select ml.id as loanId,");
updateSqlBuilder.append(" SUM(ifnull(mr.principal_completed_derived, 0)) as principal_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.interest_completed_derived, 0)) as interest_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) as fee_charges_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.penalty_charges_completed_derived, 0)) as penalty_charges_in_advance_derived,");
updateSqlBuilder.append(" (SUM(ifnull(mr.principal_completed_derived, 0)) + SUM(ifnull(mr.interest_completed_derived, 0)) + SUM(ifnull(mr.fee_charges_completed_derived, 0)) + SUM(ifnull(mr.penalty_charges_completed_derived, 0))) as total_in_advance_derived");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append(" INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append(" WHERE ml.loan_status_id = 300 ");
updateSqlBuilder.append(" and mr.duedate >= CURDATE() ");
updateSqlBuilder.append(" GROUP BY ml.id");
updateSqlBuilder.append(" HAVING (SUM(ifnull(mr.principal_completed_derived, 0)) + SUM(ifnull(mr.interest_completed_derived, 0)) +");
updateSqlBuilder.append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) + SUM(ifnull(mr.penalty_charges_completed_derived, 0))) > 0.0");
int result = jdbcTemplate.update(updateSqlBuilder.toString());
updateSqlBuilder
.append("INSERT INTO m_loan_paid_in_advance(loan_id, principal_in_advance_derived, interest_in_advance_derived, fee_charges_in_advance_derived, penalty_charges_in_advance_derived, total_in_advance_derived)");
updateSqlBuilder.append(" select ml.id as loanId,");
updateSqlBuilder.append(" SUM(ifnull(mr.principal_completed_derived, 0)) as principal_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.interest_completed_derived, 0)) as interest_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) as fee_charges_in_advance_derived,");
updateSqlBuilder.append(" SUM(ifnull(mr.penalty_charges_completed_derived, 0)) as penalty_charges_in_advance_derived,");
updateSqlBuilder
.append(" (SUM(ifnull(mr.principal_completed_derived, 0)) + SUM(ifnull(mr.interest_completed_derived, 0)) + SUM(ifnull(mr.fee_charges_completed_derived, 0)) + SUM(ifnull(mr.penalty_charges_completed_derived, 0))) as total_in_advance_derived");
updateSqlBuilder.append(" FROM m_loan ml ");
updateSqlBuilder.append(" INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id ");
updateSqlBuilder.append(" WHERE ml.loan_status_id = 300 ");
updateSqlBuilder.append(" and mr.duedate >= CURDATE() ");
updateSqlBuilder.append(" GROUP BY ml.id");
updateSqlBuilder
.append(" HAVING (SUM(ifnull(mr.principal_completed_derived, 0)) + SUM(ifnull(mr.interest_completed_derived, 0)) +");
updateSqlBuilder
.append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) + SUM(ifnull(mr.penalty_charges_completed_derived, 0))) > 0.0");
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
int result = jdbcTemplate.update(updateSqlBuilder.toString());
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + result);
}
@Transactional
@Override
@CronTargetMethod(jobName="Apply Annual Fee For Savings")
@CronTarget(jobName = JobName.APPLY_ANNUAL_FEE_FOR_SAVINGS)
public void applyAnnualFeeForSavings() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
String sql = "SELECT ms.id as savingsAccountId FROM m_savings_account ms WHERE ms.annual_fee_next_due_date <= NOW() ";
List<Long> savingsIds = jdbcTemplate.queryForList(sql, Long.class);
String sql = "SELECT ms.id as savingsAccountId FROM m_savings_account ms WHERE ms.annual_fee_next_due_date <= NOW() ";
List<Long> savingsIds = jdbcTemplate.queryForList(sql, Long.class);
for (Long savingsId : savingsIds) {
this.savingsAccountWritePlatformService.applyAnnualFee(savingsId);
}
for (Long savingsId : savingsIds) {
this.savingsAccountWritePlatformService.applyAnnualFee(savingsId);
}
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + savingsIds.size());
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + savingsIds.size());
}
}