in service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/InterestCalculator.java [98:178]
public String process(final AccrualCommand accrualCommand) {
final LocalDate accrualDate = accrualCommand.dueDate();
final List<ProductDefinitionEntity> productDefinitions = this.productDefinitionRepository.findAll();
productDefinitions.forEach(productDefinitionEntity -> {
if (this.accruableProduct(productDefinitionEntity)) {
final ArrayList<Double> accruedValues = new ArrayList<>();
final TermEntity term = this.termRepository.findByProductDefinition(productDefinitionEntity);
final List<ProductInstanceEntity> productInstances =
this.productInstanceRepository.findByProductDefinition(productDefinitionEntity);
productInstances.forEach(productInstanceEntity -> {
if (productInstanceEntity.getState().equals(ACTIVE)) {
final Account account = this.accountingService.findAccount(productInstanceEntity.getAccountIdentifier());
if (account.getBalance() > 0.00D) {
final BigDecimal balance = BigDecimal.valueOf(account.getBalance());
final BigDecimal rate = BigDecimal.valueOf(productDefinitionEntity.getInterest())
.divide(BigDecimal.valueOf(100), INTEREST_PRECISION, BigDecimal.ROUND_HALF_EVEN);
final BigDecimal accruedInterest =
accruedInterest(balance, rate,
this.periodOfInterestPayable(term.getInterestPayable()), accrualDate.lengthOfYear());
if (accruedInterest.compareTo(BigDecimal.ZERO) > 0) {
final Double doubleValue =
accruedInterest.setScale(5, BigDecimal.ROUND_HALF_EVEN).doubleValue();
accruedValues.add(doubleValue);
final Optional<AccruedInterestEntity> optionalAccruedInterest =
this.accruedInterestRepository.findByCustomerAccountIdentifier(account.getIdentifier());
if (optionalAccruedInterest.isPresent()) {
final AccruedInterestEntity accruedInterestEntity = optionalAccruedInterest.get();
accruedInterestEntity.setAmount(accruedInterestEntity.getAmount() + doubleValue);
this.accruedInterestRepository.save(accruedInterestEntity);
} else {
final AccruedInterestEntity accruedInterestEntity = new AccruedInterestEntity();
accruedInterestEntity.setAccrueAccountIdentifier(productDefinitionEntity.getAccrueAccountIdentifier());
accruedInterestEntity.setCustomerAccountIdentifier(account.getIdentifier());
accruedInterestEntity.setAmount(doubleValue);
this.accruedInterestRepository.save(accruedInterestEntity);
}
}
}
}
});
final String roundedAmount =
BigDecimal.valueOf(accruedValues.parallelStream().reduce(0.00D, Double::sum))
.setScale(2, BigDecimal.ROUND_HALF_EVEN).toString();
final JournalEntry cashToAccrueJournalEntry = new JournalEntry();
cashToAccrueJournalEntry.setTransactionIdentifier(RandomStringUtils.randomAlphanumeric(32));
cashToAccrueJournalEntry.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
cashToAccrueJournalEntry.setTransactionType("INTR");
cashToAccrueJournalEntry.setClerk(UserContextHolder.checkedGetUser());
cashToAccrueJournalEntry.setNote("Daily accrual for product " + productDefinitionEntity.getIdentifier() + ".");
final Debtor cashDebtor = new Debtor();
cashDebtor.setAccountNumber(productDefinitionEntity.getCashAccountIdentifier());
cashDebtor.setAmount(roundedAmount);
cashToAccrueJournalEntry.setDebtors(Sets.newHashSet(cashDebtor));
final Creditor accrueCreditor = new Creditor();
accrueCreditor.setAccountNumber(productDefinitionEntity.getAccrueAccountIdentifier());
accrueCreditor.setAmount(roundedAmount);
cashToAccrueJournalEntry.setCreditors(Sets.newHashSet(accrueCreditor));
this.accountingService.post(cashToAccrueJournalEntry);
}
});
return DateConverter.toIsoString(accrualDate);
}