Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository;
import org.apache.fineract.accounting.glaccount.exception.GLAccountNotFoundException;
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
import org.apache.fineract.accounting.provisioning.data.LoanProductProvisioningEntryData;
import org.apache.fineract.accounting.provisioning.data.ProvisioningEntryData;
Expand All @@ -48,14 +53,16 @@
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
import org.apache.fineract.organisation.office.domain.OfficeRepository;
import org.apache.fineract.organisation.office.exception.OfficeNotFoundException;
import org.apache.fineract.organisation.provisioning.data.ProvisioningCriteriaData;
import org.apache.fineract.organisation.provisioning.domain.ProvisioningCategory;
import org.apache.fineract.organisation.provisioning.domain.ProvisioningCategoryRepository;
import org.apache.fineract.organisation.provisioning.service.ProvisioningCriteriaReadPlatformService;
import org.apache.fineract.portfolio.PortfolioProductType;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
Expand All @@ -68,7 +75,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
private final ProvisioningCriteriaReadPlatformService provisioningCriteriaReadPlatformService;
private final LoanProductRepository loanProductRepository;
private final GLAccountRepository glAccountRepository;
private final OfficeRepositoryWrapper officeRepositoryWrapper;
private final OfficeRepository officeRepository;
private final ProvisioningCategoryRepository provisioningCategoryRepository;
private final PlatformSecurityContext platformSecurityContext;
private final ProvisioningEntryRepository provisioningEntryRepository;
Expand Down Expand Up @@ -177,13 +184,43 @@ public CommandProcessingResult reCreateProvisioningEntries(Long provisioningEntr
private Collection<LoanProductProvisioningEntry> generateLoanProvisioningEntry(ProvisioningEntry parent, LocalDate date) {
Collection<LoanProductProvisioningEntryData> entries = this.provisioningEntriesReadPlatformService
.retrieveLoanProductsProvisioningData(date);
// Collect all referenced IDs upfront and bulk-fetch via findAllById,
// replacing the previous pattern of N x 5 individual repository calls per
// loop iteration (consistent with the optimisation in FINERACT-2561).
Set<Long> productIds = entries.stream().map(LoanProductProvisioningEntryData::getProductId).collect(Collectors.toSet());
Set<Long> officeIds = entries.stream().map(LoanProductProvisioningEntryData::getOfficeId).collect(Collectors.toSet());
Set<Long> categoryIds = entries.stream().map(LoanProductProvisioningEntryData::getCategoryId).collect(Collectors.toSet());
Set<Long> glAccountIds = entries.stream().flatMap(d -> Stream.of(d.getLiablityAccount(), d.getExpenseAccount()))
.collect(Collectors.toSet());

Map<Long, LoanProduct> loanProductMap = loanProductRepository.findAllById(productIds).stream()
.collect(Collectors.toMap(LoanProduct::getId, Function.identity()));
Map<Long, Office> officeMap = officeRepository.findAllById(officeIds).stream()
.collect(Collectors.toMap(Office::getId, Function.identity()));
Map<Long, ProvisioningCategory> categoryMap = provisioningCategoryRepository.findAllById(categoryIds).stream()
.collect(Collectors.toMap(ProvisioningCategory::getId, Function.identity()));
Map<Long, GLAccount> glAccountMap = glAccountRepository.findAllById(glAccountIds).stream()
.collect(Collectors.toMap(GLAccount::getId, Function.identity()));

Map<Integer, LoanProductProvisioningEntry> provisioningEntries = new HashMap<>();
for (LoanProductProvisioningEntryData data : entries) {
LoanProduct loanProduct = this.loanProductRepository.findById(data.getProductId()).orElseThrow();
Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(data.getOfficeId());
ProvisioningCategory provisioningCategory = provisioningCategoryRepository.findById(data.getCategoryId()).orElse(null);
GLAccount liabilityAccount = glAccountRepository.findById(data.getLiablityAccount()).orElseThrow();
GLAccount expenseAccount = glAccountRepository.findById(data.getExpenseAccount()).orElseThrow();
LoanProduct loanProduct = loanProductMap.get(data.getProductId());
if (loanProduct == null) {
throw new LoanProductNotFoundException(data.getProductId());
}
Office office = officeMap.get(data.getOfficeId());
if (office == null) {
throw new OfficeNotFoundException(data.getOfficeId());
}
GLAccount liabilityAccount = glAccountMap.get(data.getLiablityAccount());
if (liabilityAccount == null) {
throw new GLAccountNotFoundException(data.getLiablityAccount());
}
GLAccount expenseAccount = glAccountMap.get(data.getExpenseAccount());
if (expenseAccount == null) {
throw new GLAccountNotFoundException(data.getExpenseAccount());
}
ProvisioningCategory provisioningCategory = categoryMap.get(data.getCategoryId());
MonetaryCurrency currency = loanProduct.getPrincipalAmount().getCurrency();
Money money = Money.of(currency, data.getBalance());
Money amountToReserve = money.percentageOf(data.getPercentage(), MoneyHelper.getMathContext());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
import org.apache.fineract.organisation.office.domain.OfficeRepository;
import org.apache.fineract.organisation.provisioning.domain.ProvisioningCategoryRepository;
import org.apache.fineract.organisation.provisioning.service.ProvisioningCriteriaReadPlatformService;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
Expand All @@ -56,12 +56,12 @@ public ProvisioningEntriesReadPlatformService provisioningEntriesReadPlatformSer
public ProvisioningEntriesWritePlatformService provisioningEntriesWritePlatformService(
ProvisioningEntriesReadPlatformService provisioningEntriesReadPlatformService,
ProvisioningCriteriaReadPlatformService provisioningCriteriaReadPlatformService, LoanProductRepository loanProductRepository,
GLAccountRepository glAccountRepository, OfficeRepositoryWrapper officeRepositoryWrapper,
GLAccountRepository glAccountRepository, OfficeRepository officeRepository,
ProvisioningCategoryRepository provisioningCategoryRepository, PlatformSecurityContext platformSecurityContext,
ProvisioningEntryRepository provisioningEntryRepository, JournalEntryWritePlatformService journalEntryWritePlatformService,
ProvisioningEntriesDefinitionJsonDeserializer fromApiJsonDeserializer, FromJsonHelper fromApiJsonHelper) {
return new ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl(provisioningEntriesReadPlatformService,
provisioningCriteriaReadPlatformService, loanProductRepository, glAccountRepository, officeRepositoryWrapper,
provisioningCriteriaReadPlatformService, loanProductRepository, glAccountRepository, officeRepository,
provisioningCategoryRepository, platformSecurityContext, provisioningEntryRepository, journalEntryWritePlatformService,
fromApiJsonDeserializer, fromApiJsonHelper) {};
}
Expand Down
Loading