public String process()

in service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/InterestCalculator.java [243:336]


  public String process(final DividendDistributionCommand dividendDistributionCommand) {
    final Optional<ProductDefinitionEntity> optionalProductDefinition =
        this.productDefinitionRepository.findByIdentifier(dividendDistributionCommand.productDefinition());
    if (optionalProductDefinition.isPresent()) {
      final ProductDefinitionEntity productDefinitionEntity = optionalProductDefinition.get();
      if (productDefinitionEntity.getActive()) {
        final BigDecimal rate = BigDecimal.valueOf(dividendDistributionCommand.rate());
        final TermEntity term = this.termRepository.findByProductDefinition(productDefinitionEntity);
        final List<String> dateRanges = this.dateRanges(dividendDistributionCommand.dueDate(), term.getInterestPayable());

        final List<ProductInstanceEntity> productInstanceEntities =
            this.productInstanceRepository.findByProductDefinition(productDefinitionEntity);
        productInstanceEntities.forEach((ProductInstanceEntity productInstanceEntity) -> {
          if (productInstanceEntity.getState().equals(ACTIVE)) {

            final Account account =
                this.accountingService.findAccount(productInstanceEntity.getAccountIdentifier());

            final LocalDate startDate = dividendDistributionCommand.dueDate().plusDays(1);
            final LocalDate now = LocalDate.now(Clock.systemUTC());

            final String findCurrentEntries = DateConverter.toIsoString(startDate) + ".." + DateConverter.toIsoString(now);
            final List<AccountEntry> currentAccountEntries =
                this.accountingService.fetchEntries(account.getIdentifier(), findCurrentEntries, Sort.Direction.ASC.name());

            final BalanceHolder balanceHolder;
            if (currentAccountEntries.isEmpty()) {
              balanceHolder = new BalanceHolder(BigDecimal.valueOf(account.getBalance()));
            } else {
              final AccountEntry accountEntry = currentAccountEntries.get(0);
              balanceHolder = new BalanceHolder(BigDecimal.valueOf(accountEntry.getBalance()).subtract(BigDecimal.valueOf(accountEntry.getAmount())));
            }

            final DividendHolder dividendHolder = new DividendHolder();
            dateRanges.forEach(dateRange -> {
              final List<AccountEntry> accountEntries =
                  this.accountingService.fetchEntries(account.getIdentifier(), dateRange, Sort.Direction.DESC.name());
              if (!accountEntries.isEmpty()) {
                balanceHolder.setBalance(BigDecimal.valueOf(accountEntries.get(0).getBalance()));
              }

              final BigDecimal currentBalance = balanceHolder.getBalance();
              dividendHolder.addAmount(
                  accruedInterest(currentBalance, rate, 12, dividendDistributionCommand.dueDate().lengthOfYear())
              );
            });

            if (dividendHolder.getAmount().compareTo(BigDecimal.ZERO) > 0) {

              final String roundedAmount =
                  dividendHolder.getAmount()
                      .setScale(2, BigDecimal.ROUND_HALF_EVEN).toString();

              final JournalEntry cashToExpenseJournalEntry = new JournalEntry();
              cashToExpenseJournalEntry.setTransactionIdentifier(RandomStringUtils.randomAlphanumeric(32));
              cashToExpenseJournalEntry.setTransactionDate(DateConverter.toIsoString(now));
              cashToExpenseJournalEntry.setTransactionType("INTR");
              cashToExpenseJournalEntry.setClerk(UserContextHolder.checkedGetUser());
              cashToExpenseJournalEntry.setNote("Dividend distribution.");

              final Debtor cashDebtor = new Debtor();
              cashDebtor.setAccountNumber(productDefinitionEntity.getCashAccountIdentifier());
              cashDebtor.setAmount(roundedAmount);
              cashToExpenseJournalEntry.setDebtors(Sets.newHashSet(cashDebtor));

              final Creditor expenseCreditor = new Creditor();
              expenseCreditor.setAccountNumber(productDefinitionEntity.getExpenseAccountIdentifier());
              expenseCreditor.setAmount(roundedAmount);
              cashToExpenseJournalEntry.setCreditors(Sets.newHashSet(expenseCreditor));

              this.accountingService.post(cashToExpenseJournalEntry);

              this.payoutInterest(
                  productDefinitionEntity.getExpenseAccountIdentifier(),
                  account.getIdentifier(),
                  roundedAmount
              );
            }
          }
        });
      }
      final DividendDistributionEntity dividendDistributionEntity = new DividendDistributionEntity();

      dividendDistributionEntity.setProductDefinition(productDefinitionEntity);
      dividendDistributionEntity.setDueDate(Date.valueOf(dividendDistributionCommand.dueDate()));
      dividendDistributionEntity.setRate(dividendDistributionCommand.rate());
      dividendDistributionEntity.setCreatedOn(LocalDateTime.now(Clock.systemUTC()));
      dividendDistributionEntity.setCreatedBy(UserContextHolder.checkedGetUser());

      this.dividendDistributionRepository.save(dividendDistributionEntity);
    }

    return dividendDistributionCommand.productDefinition();
  }