public String process()

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);
  }