This is an automated email from the ASF dual-hosted git repository.
vorburger pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 1b1e80b Log errors from cron jobs individually and with cause
(FINERACT-858)
1b1e80b is described below
commit 1b1e80b6b1e084d30c19fa339fe7342366c43c76
Author: Michael Vorburger <[email protected]>
AuthorDate: Mon Mar 9 00:29:18 2020 +0100
Log errors from cron jobs individually and with cause (FINERACT-858)
instead of current huge JobExecutionException message (without cause)
---
.../AccrualAccountingWritePlatformServiceImpl.java | 8 +-
.../exception/MultiException.java} | 32 ++--
.../infrastructure/jobs/annotation/CronTarget.java | 2 -
.../jobs/exception/JobExecutionException.java | 8 +-
.../infrastructure/jobs/service/JobName.java | 42 +++---
...tandingInstructionWritePlatformServiceImpl.java | 45 +++---
.../domain/LoanAccountDomainServiceJpa.java | 40 ++---
.../service/LoanAccrualPlatformService.java | 5 +-
.../service/LoanAccrualPlatformServiceImpl.java | 53 ++++---
.../loanaccount/service/LoanSchedularService.java | 4 -
.../service/LoanSchedularServiceImpl.java | 155 ++++++++------------
.../LoanWritePlatformServiceJpaRepositoryImpl.java | 162 ++++++++++-----------
.../service/RecalculateInterestPoster.java | 78 +++-------
...countWritePlatformServiceJpaRepositoryImpl.java | 37 ++---
.../service/SavingsSchedularServiceImpl.java | 40 +++--
.../service/ScheduledJobRunnerServiceImpl.java | 119 +++++++--------
16 files changed, 373 insertions(+), 457 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
index 7f42124..a745840 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
@@ -29,6 +29,7 @@ import
org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
import
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import
org.apache.fineract.portfolio.loanaccount.service.LoanAccrualPlatformService;
import org.joda.time.LocalDate;
@@ -52,12 +53,13 @@ public class AccrualAccountingWritePlatformServiceImpl
implements AccrualAccount
public CommandProcessingResult executeLoansPeriodicAccrual(JsonCommand
command) {
this.accountingDataValidator.validateLoanPeriodicAccrualData(command.json());
LocalDate tilldate =
command.localDateValueOfParameterNamed(accrueTillParamName);
- String errorlog =
this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
- if (errorlog.length() > 0) {
+ try {
+ this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
+ } catch (MultiException e) {
final List<ApiParameterError> dataValidationErrors = new
ArrayList<>();
final DataValidatorBuilder baseDataValidator = new
DataValidatorBuilder(dataValidationErrors)
.resource(PERIODIC_ACCRUAL_ACCOUNTING_RESOURCE_NAME);
-
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(PERIODIC_ACCRUAL_ACCOUNTING_EXECUTION_ERROR_CODE,
errorlog);
+
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(PERIODIC_ACCRUAL_ACCOUNTING_EXECUTION_ERROR_CODE,
e.getMessage());
throw new PlatformApiDataValidationException(dataValidationErrors);
}
return CommandProcessingResult.empty();
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
similarity index 50%
copy from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
copy to
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
index 1d5596d..79ba28b 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/exception/MultiException.java
@@ -16,22 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.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.apache.fineract.infrastructure.jobs.service.JobName;
+package org.apache.fineract.infrastructure.core.exception;
/**
- * Annotation that marks a method to be picked while scheduling a cron jobs.
+ * Exception with multiple root causes.
+ *
+ * Intended to be used in places where N operations are performed in a loop
over something,
+ * each of which could fail, but where we don't want to fail immediately but
continue, and
+ * then fail at end.
*
+ * <p>The failures MUST each be logged within the loop, as they occur; this
exception is
+ * only thrown to propagate the failure, but will not contain and re-log the
details.
+ *
+ * @author Michael Vorburger.ch <[email protected]>
*/
+public class MultiException extends Exception {
+
+ private final int n;
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface CronTarget {
+ public MultiException(int n) {
+ super(n + "x failures occured here (details have been previously
logged");
+ this.n = n;
+ }
- JobName jobName();
+ public int getCausesSize() {
+ return n;
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
index 1d5596d..16aba6e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/annotation/CronTarget.java
@@ -26,9 +26,7 @@ import
org.apache.fineract.infrastructure.jobs.service.JobName;
/**
* Annotation that marks a method to be picked while scheduling a cron jobs.
- *
*/
-
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CronTarget {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
index 3ebc87b..c66b9d6 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/JobExecutionException.java
@@ -18,9 +18,11 @@
*/
package org.apache.fineract.infrastructure.jobs.exception;
-public class JobExecutionException extends Exception {
+import org.apache.fineract.infrastructure.core.exception.MultiException;
- public JobExecutionException(final String msg) {
- super(msg);
+public class JobExecutionException extends MultiException {
+
+ public JobExecutionException(int n) {
+ super(n);
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
index 999e296..cebba45 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
@@ -20,27 +20,27 @@ package org.apache.fineract.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"), //
- 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"), //
- APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue
loans"), //
- EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"), //
- ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"), //
- UPDATE_NPA("Update Non Performing Assets"), //
- UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity
details"), //
- TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"), //
- ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"), //
- RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
- GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
- GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
- POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"), //
- UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"), //
+ 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"),
+ 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"),
+ APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"),
+ EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"),
+ ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"),
+ UPDATE_NPA("Update Non Performing Assets"),
+ UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity
details"),
+ TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"),
+ ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"),
+ RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"),
+ GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"),
+ GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"),
+ POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"),
+ UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"),
ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add
Accrual Transactions For Loans With Income Posted As Transactions"),
EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs"),
UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE("Update SMS Outbound with
Campaign Message"),
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
index 657e26d..dac87a2 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java
@@ -167,10 +167,10 @@ public class StandingInstructionWritePlatformServiceImpl
implements StandingInst
AccountTransferStandingInstruction standingInstructionsForUpdate =
this.standingInstructionRepository.findById(id)
.orElseThrow(() -> new
StandingInstructionNotFoundException(id));
final Map<String, Object> actualChanges =
standingInstructionsForUpdate.update(command);
- return new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(id) //
- .with(actualChanges) //
+ return new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(id)
+ .with(actualChanges)
.build();
}
@@ -182,9 +182,9 @@ public class StandingInstructionWritePlatformServiceImpl
implements StandingInst
final Map<String, Object> actualChanges = new HashMap<>();
actualChanges.put(statusParamName,
StandingInstructionStatus.DELETED.getValue());
- return new CommandProcessingResultBuilder() //
- .withEntityId(id) //
- .with(actualChanges) //
+ return new CommandProcessingResultBuilder()
+ .withEntityId(id)
+ .with(actualChanges)
.build();
}
@@ -237,8 +237,8 @@ public class StandingInstructionWritePlatformServiceImpl
implements StandingInst
final boolean isExceptionForBalanceCheck = false;
AccountTransferDTO accountTransferDTO = new
AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
data.toAccountType(), data.fromAccount().accountId(),
data.toAccount().accountId(), data.name()
- + " Standing instruction trasfer ", null,
null, null, null, data.toTransferType(), null, null, data
- .transferType().getValue(), null, null, null,
null, null, fromSavingsAccount,
+ + " Standing instruction trasfer ", null, null, null,
null, data.toTransferType(), null, null, data
+ .transferType().getValue(), null, null, null, null,
null, fromSavingsAccount,
isRegularTransaction, isExceptionForBalanceCheck);
final boolean transferCompleted = transferAmount(sb,
accountTransferDTO, data.getId());
@@ -249,14 +249,13 @@ public class StandingInstructionWritePlatformServiceImpl
implements StandingInst
}
}
- if (sb.length() > 0) { throw new JobExecutionException(sb.toString());
}
-
+ if (sb.length() > 0) {
+ logger.error("executeStandingInstructions (transferAmount)
encountered failure/s: {}", sb.toString());
+ // This is a bit of a hack (related to
https://issues.apache.org/jira/browse/FINERACT-858) and could be improved..
+ throw new JobExecutionException(123456789);
+ }
}
- /**
- * @param sb
- * @param accountTransferDTO
- */
private boolean transferAmount(final StringBuilder sb, final
AccountTransferDTO accountTransferDTO, final Long instructionId) {
boolean transferCompleted = true;
StringBuffer errorLog = new StringBuffer();
@@ -266,23 +265,23 @@ public class StandingInstructionWritePlatformServiceImpl
implements StandingInst
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} catch (final PlatformApiDataValidationException e) {
sb.append("Validation exception while trasfering funds for
standing Instruction id").append(instructionId).append(" from ")
- .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
- .append("--------");
+ .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
+ .append("--------");
errorLog.append("Validation exception while trasfering funds " +
e.getDefaultUserMessage());
} catch (final InsufficientAccountBalanceException e) {
sb.append("InsufficientAccountBalance Exception while trasfering
funds for standing Instruction id").append(instructionId)
- .append(" from
").append(accountTransferDTO.getFromAccountId()).append(" to ")
-
.append(accountTransferDTO.getToAccountId()).append("--------");
+ .append(" from
").append(accountTransferDTO.getFromAccountId()).append(" to ")
+ .append(accountTransferDTO.getToAccountId()).append("--------");
errorLog.append("InsufficientAccountBalance Exception ");
} catch (final AbstractPlatformServiceUnavailableException e) {
sb.append("Platform exception while trasfering funds for standing
Instruction id").append(instructionId).append(" from ")
- .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
- .append("--------");
+ .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
+ .append("--------");
errorLog.append("Platform exception while trasfering funds " +
e.getDefaultUserMessage());
} catch (Exception e) {
sb.append("Exception while trasfering funds for standing
Instruction id").append(instructionId).append(" from ")
- .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
- .append("--------");
+ .append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
+ .append("--------");
errorLog.append("Exception while trasfering funds " +
e.getMessage());
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index af4eb32..f288b6d 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -35,6 +35,7 @@ import
org.apache.fineract.infrastructure.core.data.ApiParameterError;
import
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
import
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -227,10 +228,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
// disable all active standing orders linked to this loan if status
changes to closed
disableStandingInstructionsLinkedToClosedLoan(loan);
- builderResult.withEntityId(newRepaymentTransaction.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()); //
+ builderResult.withEntityId(newRepaymentTransaction.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId());
return newRepaymentTransaction;
}
@@ -244,7 +245,7 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
final DataValidatorBuilder baseDataValidator = new
DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
if
(realCause.getMessage().toLowerCase().contains("external_id_unique")) {
baseDataValidator.reset().parameter("externalId").value(newRepaymentTransaction.getExternalId())
- .failWithCode("value.must.be.unique");
+ .failWithCode("value.must.be.unique");
}
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
@@ -412,10 +413,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
postJournalEntries(loan, existingTransactionIds,
existingReversedTransactionIds, isAccountTransfer);
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_REFUND,
constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION,
newRefundTransaction));
- builderResult.withEntityId(newRefundTransaction.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()); //
+ builderResult.withEntityId(newRefundTransaction.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId());
return newRefundTransaction;
}
@@ -509,10 +510,11 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
}
if (!loanScheduleAccrualDatas.isEmpty()) {
- String error =
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill,
loanScheduleAccrualDatas);
- if (error.length() > 0) {
+ try {
+
this.loanAccrualPlatformService.addPeriodicAccruals(accruedTill,
loanScheduleAccrualDatas);
+ } catch (MultiException e) {
String globalisationMessageCode =
"error.msg.accrual.exception";
- throw new
GeneralPlatformDomainRuleException(globalisationMessageCode, error, error);
+ throw new
GeneralPlatformDomainRuleException(globalisationMessageCode, e.getMessage());
}
}
}
@@ -543,10 +545,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
LoanScheduleAccrualData accrualData = new
LoanScheduleAccrualData(loanId, officeId, installment.getInstallmentNumber(),
accrualStartDate, repaymentFrequency, repayEvery,
installment.getDueDate(), installment.getFromDate(),
installment.getId(), loanProductId,
installment.getInterestCharged(currency).getAmount(), installment
- .getFeeChargesCharged(currency).getAmount(),
installment.getPenaltyChargesCharged(currency).getAmount(),
+ .getFeeChargesCharged(currency).getAmount(),
installment.getPenaltyChargesCharged(currency).getAmount(),
installment.getInterestAccrued(currency).getAmount(),
installment.getFeeAccrued(currency).getAmount(), installment
- .getPenaltyAccrued(currency).getAmount(),
currencyData, interestCalculatedFrom, installment
- .getInterestWaived(currency).getAmount());
+ .getPenaltyAccrued(currency).getAmount(), currencyData,
interestCalculatedFrom, installment
+ .getInterestWaived(currency).getAmount());
loanScheduleAccrualDatas.add(accrualData);
}
@@ -604,10 +606,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_REFUND,
constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION,
newRefundTransaction));
- builderResult.withEntityId(newRefundTransaction.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()); //
+ builderResult.withEntityId(newRefundTransaction.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId());
return newRefundTransaction;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
index d3311f0..edcbf94 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
@@ -19,15 +19,16 @@
package org.apache.fineract.portfolio.loanaccount.service;
import java.util.Collection;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.joda.time.LocalDate;
public interface LoanAccrualPlatformService {
- String addPeriodicAccruals(LocalDate tilldate);
+ void addPeriodicAccruals(LocalDate tilldate) throws MultiException;
- String addPeriodicAccruals(LocalDate tilldate,
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas);
+ void addPeriodicAccruals(LocalDate tilldate,
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws
MultiException;
void addAccrualAccounting() throws JobExecutionException;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
index af990ca..284b692 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
@@ -22,17 +22,22 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import org.apache.fineract.infrastructure.core.exception.MultiException;
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanAccrualPlatformServiceImpl implements
LoanAccrualPlatformService {
+ private final static Logger LOG =
LoggerFactory.getLogger(LoanAccrualPlatformServiceImpl.class);
+
private final LoanReadPlatformService loanReadPlatformService;
private final LoanAccrualWritePlatformService
loanAccrualWritePlatformService;
@@ -47,7 +52,6 @@ public class LoanAccrualPlatformServiceImpl implements
LoanAccrualPlatformServic
@CronTarget(jobName = JobName.ADD_ACCRUAL_ENTRIES)
public void addAccrualAccounting() throws JobExecutionException {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas =
this.loanReadPlatformService.retriveScheduleAccrualData();
- StringBuilder sb = new StringBuilder();
Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new
HashMap<>();
for (final LoanScheduleAccrualData accrualData :
loanScheduleAccrualDatas) {
if (loanDataMap.containsKey(accrualData.getLoanId())) {
@@ -59,37 +63,36 @@ public class LoanAccrualPlatformServiceImpl implements
LoanAccrualPlatformServic
}
}
+ int errors = 0;
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry :
loanDataMap.entrySet()) {
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());
+ LOG.error("Failed to add accural transaction for loan {}",
mapEntry.getKey(), e);
+ ++errors;
}
}
-
- if (sb.length() > 0) { throw new JobExecutionException(sb.toString());
}
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
@Override
@CronTarget(jobName = JobName.ADD_PERIODIC_ACCRUAL_ENTRIES)
public void addPeriodicAccruals() throws JobExecutionException {
- String errors = addPeriodicAccruals(LocalDate.now());
- if (errors.length() > 0) { throw new JobExecutionException(errors); }
+ try {
+ addPeriodicAccruals(LocalDate.now());
+ } catch (MultiException e) {
+ throw new JobExecutionException(e.getCausesSize());
+ }
}
@Override
- public String addPeriodicAccruals(final LocalDate tilldate) {
+ public void addPeriodicAccruals(final LocalDate tilldate) throws
MultiException {
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas =
this.loanReadPlatformService.retrivePeriodicAccrualData(tilldate);
- return addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
+ addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
}
@Override
- public String addPeriodicAccruals(final LocalDate tilldate,
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) {
- StringBuilder sb = new StringBuilder();
+ public void addPeriodicAccruals(final LocalDate tilldate,
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws
MultiException {
Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new
HashMap<>();
for (final LoanScheduleAccrualData accrualData :
loanScheduleAccrualDatas) {
if (loanDataMap.containsKey(accrualData.getLoanId())) {
@@ -101,19 +104,16 @@ public class LoanAccrualPlatformServiceImpl implements
LoanAccrualPlatformServic
}
}
+ int errors = 0;
for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry :
loanDataMap.entrySet()) {
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());
+ LOG.error("Failed to add accural transaction for loan {}",
mapEntry.getKey(), e);
+ ++errors;
}
}
-
- return sb.toString();
+ if (errors > 0) { throw new MultiException(errors); }
}
@Override
@@ -121,19 +121,16 @@ public class LoanAccrualPlatformServiceImpl implements
LoanAccrualPlatformServic
public void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions()
throws JobExecutionException {
Collection<Long> loanIds =
this.loanReadPlatformService.retrieveLoanIdsWithPendingIncomePostingTransactions();
if(loanIds != null && loanIds.size() > 0){
- StringBuilder sb = new StringBuilder();
+ int errors = 0;
for (Long loanId : loanIds) {
try {
this.loanAccrualWritePlatformService.addIncomeAndAccrualTransactions(loanId);
} catch (Exception e) {
- Throwable realCause = e;
- if (e.getCause() != null) {
- realCause = e.getCause();
- }
- sb.append("failed to add income and accrual transaction
for loan " + loanId + " with message " + realCause.getMessage());
+ LOG.error("Failed to add income and accrual transaction
for loan {}", loanId, e);
+ ++errors;
}
}
- if (sb.length() > 0) { throw new
JobExecutionException(sb.toString()); }
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
index 25b1728..b6bfa29 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularService.java
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
import java.util.Map;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
-import org.apache.fineract.organisation.office.data.OfficeData;
public interface LoanSchedularService {
@@ -29,8 +28,5 @@ public interface LoanSchedularService {
void recalculateInterest() throws JobExecutionException;
- void recalculateInterest(final OfficeData office, final int
threadPoolSize, final int batchSize);
-
void recalculateInterest(@SuppressWarnings("unused") final Map<String,
String> jobParameters);
-
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
index f56bded..b8d36f6 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanSchedularServiceImpl.java
@@ -55,6 +55,7 @@ import org.springframework.util.CollectionUtils;
public class LoanSchedularServiceImpl implements LoanSchedularService {
private final static Logger logger =
LoggerFactory.getLogger(LoanSchedularServiceImpl.class);
+
private final ConfigurationDomainService configurationDomainService;
private final LoanReadPlatformService loanReadPlatformService;
private final LoanWritePlatformService loanWritePlatformService;
@@ -63,9 +64,9 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
@Autowired
public LoanSchedularServiceImpl(final ConfigurationDomainService
configurationDomainService,
- final LoanReadPlatformService
loanReadPlatformService, final LoanWritePlatformService
loanWritePlatformService,
- final OfficeReadPlatformService
officeReadPlatformService,
- final ApplicationContext
applicationContext) {
+ final LoanReadPlatformService loanReadPlatformService, final
LoanWritePlatformService loanWritePlatformService,
+ final OfficeReadPlatformService officeReadPlatformService,
+ final ApplicationContext applicationContext) {
this.configurationDomainService = configurationDomainService;
this.loanReadPlatformService = loanReadPlatformService;
this.loanWritePlatformService = loanWritePlatformService;
@@ -83,7 +84,6 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
.retrieveAllLoansWithOverdueInstallments(penaltyWaitPeriodValue,backdatePenalties);
if (!overdueLoanScheduledInstallments.isEmpty()) {
- final StringBuilder sb = new StringBuilder();
final Map<Long, Collection<OverdueLoanScheduleData>>
overdueScheduleData = new HashMap<>();
for (final OverdueLoanScheduleData overdueInstallment :
overdueLoanScheduledInstallments) {
if
(overdueScheduleData.containsKey(overdueInstallment.getLoanId())) {
@@ -95,6 +95,7 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
}
}
+ int numberOfErrors = 0;
for (final Long loanId : overdueScheduleData.keySet()) {
try {
this.loanWritePlatformService.applyOverdueChargesForLoan(loanId,
overdueScheduleData.get(loanId));
@@ -102,28 +103,18 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
} catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors();
for (final ApiParameterError error : errors) {
- logger.error("Apply Charges due for overdue loans
failed for account:" + loanId + " with message "
- + error.getDeveloperMessage());
- sb.append("Apply Charges due for overdue loans failed
for account:").append(loanId).append(" with message ")
- .append(error.getDeveloperMessage());
+ logger.error("Apply Charges due for overdue loans
failed for account {} with message: {}", loanId, error.getDeveloperMessage(),
e);
+ ++numberOfErrors;
}
- } catch (final AbstractPlatformDomainRuleException ex) {
- logger.error("Apply Charges due for overdue loans failed
for account:" + loanId + " with message "
- + ex.getDefaultUserMessage());
- sb.append("Apply Charges due for overdue loans failed for
account:").append(loanId).append(" with message ")
- .append(ex.getDefaultUserMessage());
+ } catch (final AbstractPlatformDomainRuleException e) {
+ logger.error("Apply Charges due for overdue loans failed
for account {} with message: {}", loanId, e.getDefaultUserMessage(), e);
+ ++numberOfErrors;
} catch (Exception e) {
- Throwable realCause = e;
- if (e.getCause() != null) {
- realCause = e.getCause();
- }
- logger.error("Apply Charges due for overdue loans failed
for account:" + loanId + " with message "
- + realCause.getMessage());
- sb.append("Apply Charges due for overdue loans failed for
account:").append(loanId).append(" with message ")
- .append(realCause.getMessage());
+ logger.error("Apply Charges due for overdue loans failed
for account {}", loanId, e);
+ ++numberOfErrors;
}
}
- if (sb.length() > 0) { throw new
JobExecutionException(sb.toString()); }
+ if (numberOfErrors > 0) { throw new
JobExecutionException(numberOfErrors); }
}
}
@@ -138,64 +129,44 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
.fetchLoansForInterestRecalculation();
int i = 0;
if (!loanIds.isEmpty()) {
- final StringBuilder sb = new StringBuilder();
+ int errors = 0;
for (Long loanId : loanIds) {
- logger.info("Loan ID " + loanId);
+ logger.info("recalculateInterest: Loan ID = {}", loanId);
Integer numberOfRetries = 0;
while (numberOfRetries <= maxNumberOfRetries) {
try {
- this.loanWritePlatformService
- .recalculateInterest(loanId);
+
this.loanWritePlatformService.recalculateInterest(loanId);
numberOfRetries = maxNumberOfRetries + 1;
} catch (CannotAcquireLockException
| ObjectOptimisticLockingFailureException
exception) {
- logger.info("Recalulate interest job has been retried
"
- + numberOfRetries + " time(s)");
- /***
- * Fail if the transaction has been retired for
- * maxNumberOfRetries
- **/
+ logger.info("Recalulate interest job has been retried
{} time(s)", numberOfRetries);
+ // Fail if the transaction has been retried for
maxNumberOfRetries
if (numberOfRetries >= maxNumberOfRetries) {
- logger.warn("Recalulate interest job has been
retried for the max allowed attempts of "
- + numberOfRetries
- + " and will be rolled back");
- sb.append("Recalulate interest job has been
retried for the max allowed attempts of "
- + numberOfRetries
- + " and will be rolled back");
+ logger.error("Recalulate interest job has been
retried for the max allowed attempts of {} and will be rolled back",
numberOfRetries);
+ ++errors;
break;
}
- /***
- * Else sleep for a random time (between 1 to 10
- * seconds) and continue
- **/
+ // Else sleep for a random time (between 1 to 10
seconds) and continue
try {
Random random = new Random();
- int randomNum = random
- .nextInt(maxIntervalBetweenRetries + 1);
+ int randomNum =
random.nextInt(maxIntervalBetweenRetries + 1);
Thread.sleep(1000 + (randomNum * 1000));
numberOfRetries = numberOfRetries + 1;
} catch (InterruptedException e) {
- sb.append("Interest recalculation for loans failed
" + exception.getMessage()) ;
+ logger.error("Interest recalculation for loans
retry failed due to InterruptedException", e) ;
+ ++errors;
break;
}
} catch (Exception e) {
- Throwable realCause = e;
- if (e.getCause() != null) {
- realCause = e.getCause();
- }
- logger.error("Interest recalculation for loans failed
for account:" + loanId + " with message "
- + realCause.getMessage());
- sb.append("Interest recalculation for loans failed for
account:").append(loanId).append(" with message ")
- .append(realCause.getMessage());
+ logger.error("Interest recalculation for loans failed
for account {}", loanId, e);
numberOfRetries = maxNumberOfRetries + 1;
+ ++errors;
}
i++;
}
- logger.info("Loans count " + i);
- }
- if (sb.length() > 0) {
- throw new JobExecutionException(sb.toString());
+ logger.info("recalculateInterest: Loans count {}", i);
}
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
}
@@ -203,64 +174,63 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
@Override
@CronTarget(jobName = JobName.RECALCULATE_INTEREST_FOR_LOAN)
public void recalculateInterest(Map<String, String> jobParameters) {
- //gets the officeId
+ // gets the officeId
final String officeId = jobParameters.get("officeId");
- logger.info(officeId);
- Long officeIdLong=Long.valueOf(officeId);
- //gets the Office object
+ logger.info("recalculateInterest: officeId={}", officeId);
+ Long officeIdLong = Long.valueOf(officeId);
+
+ // gets the Office object
final OfficeData office =
this.officeReadPlatformService.retrieveOffice(officeIdLong);
- if(office == null)
+ if(office == null) {
throw new OfficeNotFoundException(officeIdLong);
+ }
final int
threadPoolSize=Integer.parseInt(jobParameters.get("thread-pool-size"));
final int batchSize=Integer.parseInt(jobParameters.get("batch-size"));
recalculateInterest(office,threadPoolSize,batchSize);
}
- @Override
- public void recalculateInterest(OfficeData office, int threadPoolSize, int
batchSize) {
+ private void recalculateInterest(OfficeData office, int threadPoolSize,
int batchSize) {
final int pageSize = batchSize * threadPoolSize;
- //initialise the executor service with fetched configurations
+ // initialise the executor service with fetched configurations
final ExecutorService executorService =
Executors.newFixedThreadPool(threadPoolSize);
Long maxLoanIdInList = 0L;
final String officeHierarchy = office.getHierarchy() + "%";
- //Get the loanIds from service
+ // get the loanIds from service
List<Long> loanIds =
Collections.synchronizedList(this.loanReadPlatformService
.fetchLoansForInterestRecalculation(pageSize, maxLoanIdInList,
officeHierarchy));
-
// gets the loanIds data set iteratively and call addAccuruals for
that paginated dataset
do {
int totalFilteredRecords = loanIds.size();
logger.info("Starting accrual - total filtered records - " +
totalFilteredRecords);
- recalculateInterest(loanIds, threadPoolSize, batchSize,
- executorService);
+ recalculateInterest(loanIds, threadPoolSize, batchSize,
executorService);
maxLoanIdInList+= pageSize+1;
loanIds = Collections.synchronizedList(this.loanReadPlatformService
.fetchLoansForInterestRecalculation(pageSize,
maxLoanIdInList, officeHierarchy));
} while (!CollectionUtils.isEmpty(loanIds));
- //shutdown the executor when done
+ // shutdown the executor when done
executorService.shutdownNow();
}
private void recalculateInterest(List<Long> loanIds,
- int threadPoolSize, int batchSize, final
ExecutorService executorService) {
- //StringBuilder sb = new StringBuilder();
+ int threadPoolSize, int batchSize, final ExecutorService
executorService) {
- List<Callable<Object>> posters = new ArrayList<Callable<Object>>();
+ List<Callable<Void>> posters = new ArrayList<>();
int fromIndex = 0;
// get the size of current paginated dataset
int size = loanIds.size();
- //calculate the batch size
- double toGetCeilValue = (double) (size / threadPoolSize);
+ // calculate the batch size
+ double toGetCeilValue = size / threadPoolSize;
batchSize = (int) Math.ceil(toGetCeilValue);
- if(batchSize == 0)
+ if(batchSize == 0) {
return;
+ }
int toIndex = (batchSize > size - 1)? size : batchSize ;
while(toIndex < size && loanIds.get(toIndex -
1).equals(loanIds.get(toIndex))) {
@@ -274,27 +244,30 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
RecalculateInterestPoster poster = (RecalculateInterestPoster)
this.applicationContext.getBean("recalculateInterestPoster");
poster.setLoanIds(subList);
poster.setLoanWritePlatformService(loanWritePlatformService);
- posters.add(Executors.callable(poster));
- if(lastBatch)
+ posters.add(poster);
+ if(lastBatch) {
break;
- if(toIndex + batchSize > size - 1)
+ }
+ if(toIndex + batchSize > size - 1) {
lastBatch = true;
+ }
fromIndex = fromIndex + (toIndex - fromIndex);
toIndex = (toIndex + batchSize > size - 1)? size : toIndex +
batchSize;
while(toIndex < size && loanIds.get(toIndex -
1).equals(loanIds.get(toIndex))) {
- toIndex ++;
+ toIndex++;
}
}
try {
- List<Future<Object>> responses =
executorService.invokeAll(posters);
+ List<Future<Void>> responses = executorService.invokeAll(posters);
checkCompletion(responses);
} catch (InterruptedException e1) {
logger.error("Interrupted while recalculateInterest", e1);
}
}
- //break the lists into sub lists
- public <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
+
+ // break the lists into sub lists
+ private <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
int size = list.size();
if (fromIndex >= size || toIndex <= 0 || fromIndex >= toIndex) {
return Collections.emptyList();
@@ -305,30 +278,28 @@ public class LoanSchedularServiceImpl implements
LoanSchedularService {
return list.subList(fromIndex, toIndex);
}
- //checks the execution of task by each thread in the executor service
- private void checkCompletion(List<Future<Object>> responses) {
+
+ // checks the execution of task by each thread in the executor service
+ private void checkCompletion(List<Future<Void>> responses) {
try {
- for(Future f : responses) {
+ for(Future<Void> f : responses) {
f.get();
}
boolean allThreadsExecuted = false;
int noOfThreadsExecuted = 0;
- for (Future<Object> future : responses) {
+ for (Future<Void> future : responses) {
if (future.isDone()) {
noOfThreadsExecuted++;
}
}
allThreadsExecuted = noOfThreadsExecuted == responses.size();
- if(!allThreadsExecuted)
+ if(!allThreadsExecuted) {
logger.error("All threads could not execute.");
+ }
} catch (InterruptedException e1) {
logger.error("Interrupted while posting IR entries", e1);
} catch (ExecutionException e2) {
logger.error("Execution exception while posting IR entries", e2);
}
}
-
-
-
-
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index d8bf85c..94cb93b 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -194,7 +194,7 @@ import
org.springframework.transaction.annotation.Transactional;
@Service
public class LoanWritePlatformServiceJpaRepositoryImpl implements
LoanWritePlatformService {
- private final static Logger logger =
LoggerFactory.getLogger(LoanWritePlatformServiceJpaRepositoryImpl.class);
+ private final static Logger LOG =
LoggerFactory.getLogger(LoanWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final LoanEventApiJsonValidator loanEventApiJsonValidator;
@@ -393,11 +393,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
throw new GeneralPlatformDomainRuleException(
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
"Disbursal date of this loan application
"+loan.getDisbursementDate()
- +" should be after last transaction date
of loan to be closed "+ lastUserTransactionOnLoanToClose);
+ +" should be after last transaction date of loan
to be closed "+ lastUserTransactionOnLoanToClose);
}
BigDecimal loanOutstanding =
this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(loanIdToClose,
- actualDisbursementDate).getAmount();
+ actualDisbursementDate).getAmount();
final BigDecimal firstDisbursalAmount =
loan.getFirstDisbursalAmount();
if(loanOutstanding.compareTo(firstDisbursalAmount) > 0){
throw new
GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
@@ -621,9 +621,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
final LocalDate nextPossibleRepaymentDate = null;
final Date rescheduledRepaymentDate = null;
- for (int i = 0; i < disbursalCommand.length; i++) {
- final SingleDisbursalCommand singleLoanDisbursalCommand =
disbursalCommand[i];
-
+ for (final SingleDisbursalCommand singleLoanDisbursalCommand :
disbursalCommand) {
final Loan loan =
this.loanAssembler.assembleFrom(singleLoanDisbursalCommand.getLoanId());
final LocalDate actualDisbursementDate =
command.localDateValueOfParameterNamed("actualDisbursementDate");
@@ -896,7 +894,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
constructEntityMap(BUSINESS_ENTITY.LOAN_ADJUSTED_TRANSACTION,
transactionToAdjust));
if
(this.accountTransfersReadPlatformService.isAccountTransfer(transactionId,
PortfolioAccountType.LOAN)) { throw new PlatformServiceUnavailableException(
"error.msg.loan.transfer.transaction.update.not.allowed",
"Loan transaction:" + transactionId
- + " update not allowed as it involves in account
transfer", transactionId); }
+ + " update not allowed as it involves in account transfer",
transactionId); }
if (loan.isClosedWrittenOff()) { throw new
PlatformServiceUnavailableException("error.msg.loan.written.off.update.not.allowed",
"Loan transaction:" + transactionId + " update not allowed as
loan status is written off", transactionId); }
@@ -995,7 +993,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
if (!transactionIds.isEmpty()) {
this.accountTransfersWritePlatformService
-
.reverseTransfersWithFromAccountTransactions(transactionIds,
PortfolioAccountType.LOAN);
+ .reverseTransfersWithFromAccountTransactions(transactionIds,
PortfolioAccountType.LOAN);
loan.updateLoanSummarAndStatus();
}
@@ -1008,14 +1006,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
}
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_ADJUST_TRANSACTION,
entityMap);
- return new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(transactionId) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
- .with(changes) //
+ return new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(transactionId)
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
+ .with(changes)
.build();
}
@@ -1095,14 +1093,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
this.loanAccountDomainService.recalculateAccruals(loan);
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_WAIVE_INTEREST,
constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION,
waiveInterestTransaction));
- return new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(waiveInterestTransaction.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
- .with(changes) //
+ return new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(waiveInterestTransaction.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
+ .with(changes)
.build();
}
@@ -1165,14 +1163,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
this.loanAccountDomainService.recalculateAccruals(loan);
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_WRITTEN_OFF,
constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION,
writeoff));
- return new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(writeoff.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
- .with(changes) //
+ return new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(writeoff.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
+ .with(changes)
.build();
}
@@ -1237,24 +1235,24 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
CommandProcessingResult result = null;
if (possibleClosingTransaction != null) {
- result = new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(possibleClosingTransaction.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
- .with(changes) //
+ result = new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(possibleClosingTransaction.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
+ .with(changes)
.build();
} else {
- result = new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(loanId) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
- .with(changes) //
+ result = new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(loanId)
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
+ .with(changes)
.build();
}
@@ -1332,14 +1330,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
final Charge chargeDefinition =
this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
if (loan.isDisbursed() && chargeDefinition.isDisbursementCharge()) {
- validateAddingNewChargeAllowed(loanDisburseDetails); // validates
- // whether any
- // pending
- //
disbursements
- // are
- // available
to
- // apply this
- // charge
+ // validates whether any pending disbursements are available to
apply this charge
+ validateAddingNewChargeAllowed(loanDisburseDetails);
}
final List<Long> existingTransactionIds = new
ArrayList<>(loan.findExistingTransactionIds());
final List<Long> existingReversedTransactionIds = new
ArrayList<>(loan.findExistingReversedTransactionIds());
@@ -1410,13 +1402,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
}
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_ADD_CHARGE,
constructEntityMap(BUSINESS_ENTITY.LOAN_CHARGE, loanCharge));
- return new CommandProcessingResultBuilder() //
- .withCommandId(command.commandId()) //
- .withEntityId(loanCharge.getId()) //
- .withOfficeId(loan.getOfficeId()) //
- .withClientId(loan.getClientId()) //
- .withGroupId(loan.getGroupId()) //
- .withLoanId(loanId) //
+ return new CommandProcessingResultBuilder()
+ .withCommandId(command.commandId())
+ .withEntityId(loanCharge.getId())
+ .withOfficeId(loan.getOfficeId())
+ .withClientId(loan.getClientId())
+ .withGroupId(loan.getGroupId())
+ .withLoanId(loanId)
.build();
}
@@ -1782,7 +1774,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
final Collection<LoanChargeData> chargeDatas =
this.loanChargeReadPlatformService.retrieveLoanChargesForFeePayment(
ChargePaymentMode.ACCOUNT_TRANSFER.getValue(),
LoanStatus.ACTIVE.getValue());
final boolean isRegularTransaction = true;
- final StringBuilder sb = new StringBuilder();
+ int errors = 0;
if (chargeDatas != null) {
for (final LoanChargeData chargeData : chargeDatas) {
if (chargeData.isInstallmentFee()) {
@@ -1803,7 +1795,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
installmentChargeData.getInstallmentNumber(),
AccountTransferType.CHARGE_PAYMENT.getValue(), null,
null, null, null, null,
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
- transferFeeCharge(sb, accountTransferDTO);
+ if (!transferFeeCharge(accountTransferDTO)) {
+ ++errors;
+ }
}
}
} else if (chargeData.getDueDate() != null &&
!chargeData.getDueDate().isAfter(DateUtils.getLocalDateOfTenant())) {
@@ -1817,27 +1811,25 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
LoanTransactionType.CHARGE_PAYMENT.getValue(),
chargeData.getId(), null,
AccountTransferType.CHARGE_PAYMENT.getValue(),
null, null, null, null, null, fromSavingsAccount,
isRegularTransaction, isExceptionForBalanceCheck);
- transferFeeCharge(sb, accountTransferDTO);
+ if (!transferFeeCharge(accountTransferDTO)) {
+ ++errors;
+ }
}
}
}
- if (sb.length() > 0) { throw new JobExecutionException(sb.toString());
}
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
- /**
- * @param sb
- * @param accountTransferDTO
- */
- private void transferFeeCharge(final StringBuilder sb, final
AccountTransferDTO accountTransferDTO) {
+ private boolean transferFeeCharge(final AccountTransferDTO
accountTransferDTO) {
try {
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
+ return true;
} catch (final PlatformApiDataValidationException e) {
- sb.append("Validation exception while paying charge
").append(accountTransferDTO.getChargeId()).append(" for loan id:")
-
.append(accountTransferDTO.getToAccountId()).append("--------");
+ LOG.error("Validation exception while paying charge {} for loan id
{}", accountTransferDTO.getChargeId(), accountTransferDTO.getToAccountId(), e);
+ return false;
} catch (final InsufficientAccountBalanceException e) {
- sb.append("InsufficientAccountBalance Exception while paying
charge ").append(accountTransferDTO.getChargeId())
- .append("for loan
id:").append(accountTransferDTO.getToAccountId()).append("--------");
-
+ LOG.error("InsufficientAccountBalanceException while paying charge
{} for loan id {}", accountTransferDTO.getChargeId(),
accountTransferDTO.getToAccountId(), e);
+ return false;
}
}
@@ -2517,7 +2509,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
final List<Long> existingReversedTransactionIds = new ArrayList<>();
if (!loan.isClosedWrittenOff()) { throw new
PlatformServiceUnavailableException(
"error.msg.loan.status.not.written.off.update.not.allowed",
"Loan :" + loanId
- + " update not allowed as loan status is not written
off", loanId); }
+ + " update not allowed as loan status is not written off",
loanId); }
LocalDate recalculateFrom = null;
LoanTransaction writeOffTransaction = loan.findWriteOffTransaction();
this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_WRITTEN_OFF,
@@ -2883,7 +2875,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
BigDecimal overpaid =
this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance();
if (overpaid == null || overpaid.equals(new BigDecimal(0)) ||
transactionAmount.floatValue() > overpaid.floatValue()) {
- if (overpaid == null) overpaid = BigDecimal.ZERO;
+ if (overpaid == null) {
+ overpaid = BigDecimal.ZERO;
+ }
throw new
InvalidPaidInAdvanceAmountException(overpaid.toPlainString());
}
}
@@ -3005,12 +2999,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl
implements LoanWritePlatf
}
private void syncExpectedDateWithActualDisbursementDate(final Loan loan,
LocalDate actualDisbursementDate){
-
if(!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)){
- throw new DateMismatchException(actualDisbursementDate,
- loan.getExpectedDisbursedOnLocalDate());
- }
+
if(!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)){
+ throw new DateMismatchException(actualDisbursementDate,
+ loan.getExpectedDisbursedOnLocalDate());
+ }
- }
+ }
private void validateTransactionsForTransfer(final Loan loan, final
LocalDate transferDate) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
index f3dfab8..b084c60 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/RecalculateInterestPoster.java
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
import java.util.Collection;
import java.util.Random;
+import java.util.concurrent.Callable;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.slf4j.Logger;
@@ -29,41 +30,25 @@ import org.springframework.dao.CannotAcquireLockException;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Component;
-
@Component
-
@Scope("prototype")
+public class RecalculateInterestPoster implements Callable<Void> {
-public class RecalculateInterestPoster implements Runnable {
-
-
-
- private final static Logger logger = LoggerFactory.getLogger(" recalculate
interest poster");
+ private final static Logger logger =
LoggerFactory.getLogger(RecalculateInterestPoster.class);
private Collection<Long> loanIds;
-
private LoanWritePlatformService loanWritePlatformService;
-
public void setLoanIds(final Collection<Long> loanIds) {
-
this.loanIds = loanIds;
-
}
-
-
public void setLoanWritePlatformService(final LoanWritePlatformService
loanWritePlatformService) {
-
this.loanWritePlatformService = loanWritePlatformService;
-
}
-
-
@Override
- public void run() {
-
+ public Void call() throws JobExecutionException {
Integer maxNumberOfRetries = ThreadLocalContextUtil.getTenant()
.getConnection().getMaxRetriesOnDeadlock();
Integer maxIntervalBetweenRetries = ThreadLocalContextUtil.getTenant()
@@ -71,72 +56,45 @@ public class RecalculateInterestPoster implements Runnable {
int i = 0;
if (!loanIds.isEmpty()) {
- final StringBuilder sb = new StringBuilder();
+ int errors = 0;
for (Long loanId : loanIds) {
logger.info("Loan ID " + loanId);
Integer numberOfRetries = 0;
while (numberOfRetries <= maxNumberOfRetries) {
try {
- this.loanWritePlatformService
- .recalculateInterest(loanId);
+
this.loanWritePlatformService.recalculateInterest(loanId);
numberOfRetries = maxNumberOfRetries + 1;
} catch (CannotAcquireLockException
| ObjectOptimisticLockingFailureException
exception) {
- logger.info("Recalulate interest job has been retried
"
- + numberOfRetries + " time(s)");
- /***
- * Fail if the transaction has been retired for
- * maxNumberOfRetries
- **/
+ logger.info("Recalulate interest job has been retried
time(s)", numberOfRetries);
+ // Fail if the transaction has been retired for
maxNumberOfRetries
if (numberOfRetries >= maxNumberOfRetries) {
- logger.warn("Recalulate interest job has been
retried for the max allowed attempts of "
- + numberOfRetries
- + " and will be rolled back");
- sb.append("Recalulate interest job has been
retried for the max allowed attempts of "
- + numberOfRetries
- + " and will be rolled back");
+ logger.error("Recalulate interest job has been
retried for the max allowed attempts of {} and will be rolled back",
numberOfRetries);
+ ++errors;
break;
}
- /***
- * Else sleep for a random time (between 1 to 10
- * seconds) and continue
- **/
+ // Else sleep for a random time (between 1 to 10
seconds) and continue
try {
Random random = new Random();
- int randomNum = random
- .nextInt(maxIntervalBetweenRetries + 1);
+ int randomNum =
random.nextInt(maxIntervalBetweenRetries + 1);
Thread.sleep(1000 + (randomNum * 1000));
numberOfRetries = numberOfRetries + 1;
} catch (InterruptedException e) {
- sb.append("Interest recalculation for loans failed
" + exception.getMessage()) ;
+ logger.error("Interest recalculation for loans
retry failed due to InterruptedException", e) ;
+ ++errors;
break;
}
} catch (Exception e) {
- Throwable realCause = e;
- if (e.getCause() != null) {
- realCause = e.getCause();
- }
- logger.error("Interest recalculation for loans failed
for account:" + loanId + " with message " + realCause.getMessage(), e);
- sb.append("Interest recalculation for loans failed for
account:").append(loanId).append(" with message ")
- .append(realCause.getMessage());
+ logger.error("Interest recalculation for loans failed
for account {}", loanId, e);
numberOfRetries = maxNumberOfRetries + 1;
+ ++errors;
}
i++;
}
logger.info("Loans count " + i);
}
- if (sb.length() > 0) {
- try {
- throw new JobExecutionException(sb.toString());
- } catch (JobExecutionException e) {
- logger.info("JobExecutionException occured :", e);
- }
- }
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
-
-
+ return null;
}
-
-
-
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
index 23841e2..d5c23eb 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -112,6 +112,8 @@ import
org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -119,6 +121,8 @@ import
org.springframework.transaction.annotation.Transactional;
@Service
public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements
DepositAccountWritePlatformService {
+ private final static Logger LOG =
LoggerFactory.getLogger(DepositAccountWritePlatformServiceJpaRepositoryImpl.class);
+
private final PlatformSecurityContext context;
private final SavingsAccountRepositoryWrapper
savingAccountRepositoryWrapper;
private final SavingsAccountTransactionRepository
savingsAccountTransactionRepository;
@@ -571,21 +575,20 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
@Override
@CronTarget(jobName = JobName.TRANSFER_INTEREST_TO_SAVINGS)
public void transferInterestToSavings() throws JobExecutionException {
+ int errors = 0;
Collection<AccountTransferDTO> accountTrasferData =
this.depositAccountReadPlatformService.retrieveDataForInterestTransfer();
- StringBuilder sb = new StringBuilder(200);
for (AccountTransferDTO accountTransferDTO : accountTrasferData) {
try {
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} catch (final PlatformApiDataValidationException e) {
- sb.append("Validation exception while trasfering Interest form
").append(accountTransferDTO.getFromAccountId())
- .append(" to
").append(accountTransferDTO.getToAccountId()).append("--------");
+ LOG.error("Validation exception while trasfering Interest from
{} to {}", accountTransferDTO.getFromAccountId(),
accountTransferDTO.getToAccountId(), e);
+ ++errors;
} catch (final InsufficientAccountBalanceException e) {
- sb.append("InsufficientAccountBalance Exception while
trasfering Interest form ")
-
.append(accountTransferDTO.getFromAccountId()).append(" to
").append(accountTransferDTO.getToAccountId())
- .append("--------");
+ LOG.error("InsufficientAccountBalanceException while
trasfering Interest from {} to {} ", accountTransferDTO.getFromAccountId(),
accountTransferDTO.getToAccountId(), e);
+ ++errors;
}
}
- if (sb.length() > 0) { throw new JobExecutionException(sb.toString());
}
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
@Override
@@ -615,8 +618,8 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if (!allowAccountTransferModification
&&
this.accountTransfersReadPlatformService.isAccountTransfer(transactionId,
PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
-
"error.msg.recurring.deposit.account.transfer.transaction.update.not.allowed",
"Recurring deposit account transaction:"
- + transactionId + " update not allowed as it involves
in account transfer", transactionId); }
+
"error.msg.recurring.deposit.account.transfer.transaction.update.not.allowed",
"Recurring deposit account transaction:"
+ + transactionId + " update not allowed as it
involves in account transfer", transactionId); }
final LocalDate today = DateUtils.getLocalDateOfTenant();
final MathContext mc = MathContext.DECIMAL64;
@@ -689,12 +692,12 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
.findOneByIdAndSavingsAccountId(transactionId, savingsId);
if (savingsAccountTransaction == null) { throw new
SavingsAccountTransactionNotFoundException(savingsId, transactionId); }
- if (!(savingsAccountTransaction.isDeposit() ||
savingsAccountTransaction.isWithdrawal()) ||
savingsAccountTransaction.isReversed()) { throw new
TransactionUpdateNotAllowedException(
+ if ((!savingsAccountTransaction.isDeposit() &&
!savingsAccountTransaction.isWithdrawal()) ||
savingsAccountTransaction.isReversed()) { throw new
TransactionUpdateNotAllowedException(
savingsId, transactionId); }
if
(this.accountTransfersReadPlatformService.isAccountTransfer(transactionId,
PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
"error.msg.saving.account.transfer.transaction.update.not.allowed", "Deposit
account transaction:" + transactionId
- + " update not allowed as it involves in account
transfer", transactionId); }
+ + " update not allowed as it involves in account transfer",
transactionId); }
final LocalDate today = DateUtils.getLocalDateOfTenant();
@@ -1071,14 +1074,14 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
&&
this.holidayRepository.isHoliday(savingsAccount.officeId(),
savingsAccountCharge.getDueLocalDate())) {
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
+
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
if
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
&&
!this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate()))
{
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
+
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -1126,14 +1129,14 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
&&
this.holidayRepository.isHoliday(savingsAccount.officeId(),
savingsAccountCharge.getDueLocalDate())) {
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
+
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.on.holiday");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
if
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
&&
!this.workingDaysRepository.isWorkingDay(savingsAccountCharge.getDueLocalDate()))
{
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(savingsAccountCharge.getDueLocalDate().toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
+
.failWithCodeNoParameterAddedToErrorCode("charge.due.date.is.a.nonworking.day");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -1253,14 +1256,14 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if
(!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
&&
this.holidayRepository.isHoliday(savingsAccountCharge.savingsAccount().officeId(),
transactionDate)) {
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
+
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
if
(!this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled()
&& !this.workingDaysRepository.isWorkingDay(transactionDate)) {
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
-
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
+
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
if (!dataValidationErrors.isEmpty()) { throw new
PlatformApiDataValidationException(dataValidationErrors); }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
index 6b624f1..0e3cc7f 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.portfolio.savings.service;
+import static
org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType.ACTIVE;
+
import java.util.List;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
@@ -26,8 +28,9 @@ import
org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
import
org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
-import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -36,6 +39,8 @@ import org.springframework.stereotype.Service;
@Service
public class SavingsSchedularServiceImpl implements SavingsSchedularService {
+ private final static Logger LOG =
LoggerFactory.getLogger(SavingsSchedularServiceImpl.class);
+
private final SavingsAccountAssembler savingAccountAssembler;
private final SavingsAccountWritePlatformService
savingsAccountWritePlatformService;
private final SavingsAccountReadPlatformService
savingAccountReadPlatformService;
@@ -51,63 +56,54 @@ public class SavingsSchedularServiceImpl implements
SavingsSchedularService {
this.savingsAccountRepository = savingsAccountRepository;
}
- @CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
@Override
+ @CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
public void postInterestForAccounts() throws JobExecutionException {
int page = 0;
Integer initialSize = 500;
Integer totalPageSize = 0;
- StringBuffer sb = new StringBuffer();
+ int errors = 0;
do {
PageRequest pageRequest = PageRequest.of(page, initialSize);
- Page<SavingsAccount> savingsAccounts =
this.savingsAccountRepository.findByStatus(SavingsAccountStatusType.ACTIVE.getValue(),
- pageRequest);
+ Page<SavingsAccount> savingsAccounts =
this.savingsAccountRepository.findByStatus(ACTIVE.getValue(), pageRequest);
for (SavingsAccount savingsAccount : savingsAccounts.getContent())
{
try {
this.savingAccountAssembler.assignSavingAccountHelpers(savingsAccount);
boolean postInterestAsOn = false;
LocalDate transactionDate = null;
-
this.savingsAccountWritePlatformService.postInterest(savingsAccount,
postInterestAsOn,
- transactionDate);
+
this.savingsAccountWritePlatformService.postInterest(savingsAccount,
postInterestAsOn, transactionDate);
} catch (Exception e) {
- Throwable realCause = e;
- if (e.getCause() != null) {
- realCause = e.getCause();
- }
- sb.append("failed to post interest for Savings with id " +
savingsAccount.getId() + " with message "
- + realCause.getMessage());
+ LOG.error("Failed to post interest for Savings with id
{}", savingsAccount.getId(), e);
+ ++errors;
}
}
page++;
totalPageSize = savingsAccounts.getTotalPages();
} while (page < totalPageSize);
- if (sb.length() > 0) { throw new JobExecutionException(sb.toString());
}
+ if (errors > 0) { throw new JobExecutionException(errors); }
}
- @CronTarget(jobName = JobName.UPDATE_SAVINGS_DORMANT_ACCOUNTS)
@Override
+ @CronTarget(jobName = JobName.UPDATE_SAVINGS_DORMANT_ACCOUNTS)
public void updateSavingsDormancyStatus() throws JobExecutionException {
- final LocalDate tenantLocalDate = DateUtils.getLocalDateOfTenant();
+ LocalDate tenantLocalDate = DateUtils.getLocalDateOfTenant();
- final List<Long> savingsPendingInactive =
this.savingAccountReadPlatformService
-
.retrieveSavingsIdsPendingInactive(tenantLocalDate);
+ List<Long> savingsPendingInactive =
savingAccountReadPlatformService.retrieveSavingsIdsPendingInactive(tenantLocalDate);
if(null != savingsPendingInactive && savingsPendingInactive.size() >
0){
for(Long savingsId : savingsPendingInactive){
this.savingsAccountWritePlatformService.setSubStatusInactive(savingsId);
}
}
- final List<Long> savingsPendingDormant =
this.savingAccountReadPlatformService
- .retrieveSavingsIdsPendingDormant(tenantLocalDate);
+ List<Long> savingsPendingDormant =
savingAccountReadPlatformService.retrieveSavingsIdsPendingDormant(tenantLocalDate);
if(null != savingsPendingDormant && savingsPendingDormant.size() > 0){
for(Long savingsId : savingsPendingDormant){
this.savingsAccountWritePlatformService.setSubStatusDormant(savingsId);
}
}
- final List<Long> savingsPendingEscheat =
this.savingAccountReadPlatformService
- .retrieveSavingsIdsPendingEscheat(tenantLocalDate);
+ List<Long> savingsPendingEscheat =
savingAccountReadPlatformService.retrieveSavingsIdsPendingEscheat(tenantLocalDate);
if(null != savingsPendingEscheat && savingsPendingEscheat.size() > 0){
for(Long savingsId : savingsPendingEscheat){
this.savingsAccountWritePlatformService.escheat(savingsId);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
index 036ab7b..3f9f60d 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/scheduledjobs/service/ScheduledJobRunnerServiceImpl.java
@@ -62,6 +62,7 @@ import org.springframework.util.CollectionUtils;
public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService {
private final static Logger logger =
LoggerFactory.getLogger(ScheduledJobRunnerServiceImpl.class);
+
private final DateTimeFormatter formatter =
DateTimeFormat.forPattern("yyyy-MM-dd");
private final DateTimeFormatter formatterWithTime =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
@@ -111,9 +112,9 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
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)) + IFNULL((select
SUM(lc.amount) from m_loan_charge lc where lc.loan_id=ml.id and lc.is_active=1
and lc.charge_time_enum=1),0) as fee_charges_charged_derived,");
+ .append("SUM(IFNULL(mr.fee_charges_amount,0)) + IFNULL((select
SUM(lc.amount) from m_loan_charge lc where lc.loan_id=ml.id and lc.is_active=1
and lc.charge_time_enum=1),0) as fee_charges_charged_derived,");
updateSqlBuilder
- .append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) +
IFNULL((select SUM(lc.amount_paid_derived) from m_loan_charge lc where
lc.loan_id=ml.id and lc.is_active=1 and lc.charge_time_enum=1),0) as
fee_charges_repaid_derived,");
+ .append("SUM(IFNULL(mr.fee_charges_completed_derived,0)) +
IFNULL((select SUM(lc.amount_paid_derived) from m_loan_charge lc where
lc.loan_id=ml.id and lc.is_active=1 and lc.charge_time_enum=1),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,");
@@ -130,45 +131,45 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
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)),");
+ .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)),");
+ .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)),");
+ .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)),");
+ .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),");
+ .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),");
+ .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),");
+ .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),");
+ .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),");
+ .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),");
+ .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)) +");
+ .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)) +");
+ .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))");
+ .append(" (x.penalty_charges_charged_derived -
(x.penalty_charges_repaid_derived + x.penalty_charges_waived_derived +
x.penalty_charges_writtenoff_derived))");
final int result = jdbcTemplate.update(updateSqlBuilder.toString());
@@ -187,23 +188,23 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
final 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)");
+ .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");
+ .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)) +");
+ .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");
+ .append(" SUM(ifnull(mr.fee_charges_completed_derived, 0)) +
SUM(ifnull(mr.penalty_charges_completed_derived, 0))) > 0.0");
final int result = jdbcTemplate.update(updateSqlBuilder.toString());
@@ -238,31 +239,21 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
@Override
@CronTarget(jobName = JobName.PAY_DUE_SAVINGS_CHARGES)
public void applyDueChargesForSavings() throws JobExecutionException {
- final Collection<SavingsAccountAnnualFeeData> chargesDueData =
this.savingsAccountChargeReadPlatformService
- .retrieveChargesWithDue();
- final StringBuilder errorMsg = new StringBuilder();
-
+ final Collection<SavingsAccountAnnualFeeData> chargesDueData =
this.savingsAccountChargeReadPlatformService.retrieveChargesWithDue();
+ int numberOfErrors = 0;
for (final SavingsAccountAnnualFeeData savingsAccountReference :
chargesDueData) {
try {
-
this.savingsAccountWritePlatformService.applyChargeDue(savingsAccountReference.getId(),
- savingsAccountReference.getAccountId());
+
this.savingsAccountWritePlatformService.applyChargeDue(savingsAccountReference.getId(),
savingsAccountReference.getAccountId());
} catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors();
for (final ApiParameterError error : errors) {
- logger.error("Apply Charges due for savings failed for
account:" + savingsAccountReference.getAccountNo()
- + " with message " + error.getDeveloperMessage());
- errorMsg.append("Apply Charges due for savings failed for
account:").append(savingsAccountReference.getAccountNo())
- .append(" with message
").append(error.getDeveloperMessage());
+ logger.error("Apply Charges due for savings failed for
account {} with message: {}", savingsAccountReference.getAccountNo(),
error.getDeveloperMessage(), e);
+ ++numberOfErrors;
}
}
}
-
- logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Savings
accounts affected by update: " + chargesDueData.size());
-
- /*
- * throw exception if any charge payment fails.
- */
- if (errorMsg.length() > 0) { throw new
JobExecutionException(errorMsg.toString()); }
+ logger.info("{}: Savings accounts affected by update: {}",
ThreadLocalContextUtil.getTenant().getName(), chargesDueData.size());
+ if (numberOfErrors > 0) { throw new
JobExecutionException(numberOfErrors); }
}
@Transactional
@@ -279,7 +270,7 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
resetNPASqlBuilder.append("set loan.is_npa = 0 ");
resetNPASqlBuilder.append("where loan.loan_status_id = 300 and
mpl.account_moves_out_of_npa_only_on_arrears_completion = 0 ");
resetNPASqlBuilder
- .append("or
(mpl.account_moves_out_of_npa_only_on_arrears_completion = 1 and
laa.overdue_since_date_derived is null)");
+ .append("or (mpl.account_moves_out_of_npa_only_on_arrears_completion =
1 and laa.overdue_since_date_derived is null)");
jdbcTemplate.update(resetNPASqlBuilder.toString());
@@ -383,65 +374,62 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
@Override
@CronTarget(jobName = JobName.POST_DIVIDENTS_FOR_SHARES)
public void postDividends() throws JobExecutionException {
+ int numberOfErrors = 0;
List<Map<String, Object>> dividendDetails =
this.shareAccountDividendReadPlatformService.retriveDividendDetailsForPostDividents();
- StringBuilder errorMsg = new StringBuilder();
for (Map<String, Object> dividendMap : dividendDetails) {
Long id = null ;
Long savingsId = null ;
- if(dividendMap.get("id") instanceof BigInteger) { //Drizzle is
returning BigInteger
- id = ((BigInteger)dividendMap.get("id")).longValue() ;
- savingsId =
((BigInteger)dividendMap.get("savingsAccountId")).longValue() ;
- }else { //MySQL connector is returning Long
- id = (Long) dividendMap.get("id") ;
- savingsId = (Long) dividendMap.get("savingsAccountId") ;
+ if (dividendMap.get("id") instanceof BigInteger) {
+ // Drizzle is returningBigInteger
+ id = ((BigInteger) dividendMap.get("id")).longValue();
+ savingsId = ((BigInteger)
dividendMap.get("savingsAccountId")).longValue();
+ } else { // MySQL connector is returning Long
+ id = (Long) dividendMap.get("id");
+ savingsId = (Long) dividendMap.get("savingsAccountId");
}
try {
this.shareAccountSchedularService.postDividend(id, savingsId);
} catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors();
for (final ApiParameterError error : errors) {
- logger.error("Post Dividends to savings failed for
Divident detail Id:" + id + " and savings Id: " + savingsId
- + " with message " + error.getDeveloperMessage());
- errorMsg.append("Post Dividends to savings failed for
Divident detail Id:").append(id).append(" and savings Id:")
- .append(savingsId).append(" with message
").append(error.getDeveloperMessage());
+ logger.error("Post Dividends to savings failed due to
ApiParameterError for Divident detail Id: {} and savings Id: {} with message:
", id, savingsId, error.getDeveloperMessage(), e);
+ ++numberOfErrors;
}
} catch (final Exception e) {
- logger.error("Post Dividends to savings failed for Divident
detail Id:" + id + " and savings Id: " + savingsId
- + " with message " + e.getLocalizedMessage());
- errorMsg.append("Post Dividends to savings failed for Divident
detail Id:").append(id).append(" and savings Id:")
- .append(savingsId).append(" with message
").append(e.getLocalizedMessage());
+ logger.error("Post Dividends to savings failed for Divident
detail Id: {} and savings Id: {}", id, savingsId, e);
+ ++numberOfErrors;
}
}
- if (errorMsg.length() > 0) { throw new
JobExecutionException(errorMsg.toString()); }
+ if (numberOfErrors > 0) { throw new
JobExecutionException(numberOfErrors); }
}
+ @Override
@CronTarget(jobName = JobName.UPDATE_TRAIL_BALANCE_DETAILS)
public void updateTrialBalanceDetails() throws JobExecutionException {
final JdbcTemplate jdbcTemplate = new
JdbcTemplate(this.dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
final StringBuilder tbGapSqlBuilder = new StringBuilder(500);
tbGapSqlBuilder.append("select distinct(je.transaction_date) ")
- .append("from acc_gl_journal_entry je ")
- .append("where je.transaction_date > (select
IFNULL(MAX(created_date),'2010-01-01') from m_trial_balance)");
+ .append("from acc_gl_journal_entry je ")
+ .append("where je.transaction_date > (select
IFNULL(MAX(created_date),'2010-01-01') from m_trial_balance)");
final List<Date> tbGaps =
jdbcTemplate.queryForList(tbGapSqlBuilder.toString(), Date.class);
for(Date tbGap : tbGaps) {
LocalDate convDate = new DateTime(tbGap).toLocalDate();
int days = Days.daysBetween(convDate,
DateUtils.getLocalDateOfTenant()).getDays();
- if(days < 1)
+ if(days < 1) {
continue;
+ }
final String formattedDate = new
SimpleDateFormat("yyyy-MM-dd").format(tbGap);
final StringBuilder sqlBuilder = new StringBuilder(600);
sqlBuilder.append("Insert Into m_trial_balance(office_id,
account_id, Amount, entry_date, created_date,closing_balance) ")
- .append("Select je.office_id, je.account_id,
sum(if(je.type_enum=1, (-1) * je.amount, je.amount)) ")
- .append("as Amount, Date(je.entry_date) as 'Entry_Date',
je.transaction_date as 'Created_Date',sum(je.amount) as closing_balance ")
- .append("from acc_gl_journal_entry je WHERE
je.transaction_date = ? ")
- .append("group by je.account_id, je.office_id,
je.transaction_date, Date(je.entry_date)");
-
- final int result = jdbcTemplate.update(sqlBuilder.toString(), new
Object[] {
- formattedDate
- });
+ .append("Select je.office_id, je.account_id,
sum(if(je.type_enum=1, (-1) * je.amount, je.amount)) ")
+ .append("as Amount, Date(je.entry_date) as 'Entry_Date',
je.transaction_date as 'Created_Date',sum(je.amount) as closing_balance ")
+ .append("from acc_gl_journal_entry je WHERE je.transaction_date =
? ")
+ .append("group by je.account_id, je.office_id,
je.transaction_date, Date(je.entry_date)");
+
+ final int result = jdbcTemplate.update(sqlBuilder.toString(),
formattedDate);
logger.info(ThreadLocalContextUtil.getTenant().getName() + ":
Results affected by update: " + result);
}
@@ -459,8 +447,9 @@ public class ScheduledJobRunnerServiceImpl implements
ScheduledJobRunnerService
List<BigDecimal> closingBalanceData =
jdbcTemplate.queryForList(closingBalanceQuery, new Object[] {officeId,
accountId}, BigDecimal.class);
List<TrialBalance> tbRows =
this.trialBalanceRepositoryWrapper.findNewByOfficeAndAccount(officeId,
accountId);
BigDecimal closingBalance = null;
- if(!CollectionUtils.isEmpty(closingBalanceData))
+ if(!CollectionUtils.isEmpty(closingBalanceData)) {
closingBalance = closingBalanceData.get(0);
+ }
if(CollectionUtils.isEmpty(closingBalanceData)) {
closingBalance = BigDecimal.ZERO;
for(TrialBalance row : tbRows) {