2323import java .util .Collection ;
2424import java .util .HashMap ;
2525import java .util .Map ;
26+ import java .util .Set ;
27+ import java .util .function .Function ;
28+ import java .util .stream .Collectors ;
29+ import java .util .stream .Stream ;
2630import lombok .RequiredArgsConstructor ;
2731import lombok .extern .slf4j .Slf4j ;
2832import org .apache .fineract .accounting .glaccount .domain .GLAccount ;
2933import org .apache .fineract .accounting .glaccount .domain .GLAccountRepository ;
34+ import org .apache .fineract .accounting .glaccount .exception .GLAccountNotFoundException ;
3035import org .apache .fineract .accounting .journalentry .service .JournalEntryWritePlatformService ;
3136import org .apache .fineract .accounting .provisioning .data .LoanProductProvisioningEntryData ;
3237import org .apache .fineract .accounting .provisioning .data .ProvisioningEntryData ;
4853import org .apache .fineract .organisation .monetary .domain .Money ;
4954import org .apache .fineract .organisation .monetary .domain .MoneyHelper ;
5055import org .apache .fineract .organisation .office .domain .Office ;
51- import org .apache .fineract .organisation .office .domain .OfficeRepositoryWrapper ;
56+ import org .apache .fineract .organisation .office .domain .OfficeRepository ;
57+ import org .apache .fineract .organisation .office .exception .OfficeNotFoundException ;
5258import org .apache .fineract .organisation .provisioning .data .ProvisioningCriteriaData ;
5359import org .apache .fineract .organisation .provisioning .domain .ProvisioningCategory ;
5460import org .apache .fineract .organisation .provisioning .domain .ProvisioningCategoryRepository ;
5561import org .apache .fineract .organisation .provisioning .service .ProvisioningCriteriaReadPlatformService ;
5662import org .apache .fineract .portfolio .PortfolioProductType ;
5763import org .apache .fineract .portfolio .loanproduct .domain .LoanProduct ;
5864import org .apache .fineract .portfolio .loanproduct .domain .LoanProductRepository ;
65+ import org .apache .fineract .portfolio .loanproduct .exception .LoanProductNotFoundException ;
5966import org .apache .fineract .useradministration .domain .AppUser ;
6067import org .springframework .dao .DataIntegrityViolationException ;
6168import org .springframework .orm .jpa .JpaSystemException ;
@@ -68,7 +75,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
6875 private final ProvisioningCriteriaReadPlatformService provisioningCriteriaReadPlatformService ;
6976 private final LoanProductRepository loanProductRepository ;
7077 private final GLAccountRepository glAccountRepository ;
71- private final OfficeRepositoryWrapper officeRepositoryWrapper ;
78+ private final OfficeRepository officeRepository ;
7279 private final ProvisioningCategoryRepository provisioningCategoryRepository ;
7380 private final PlatformSecurityContext platformSecurityContext ;
7481 private final ProvisioningEntryRepository provisioningEntryRepository ;
@@ -177,13 +184,43 @@ public CommandProcessingResult reCreateProvisioningEntries(Long provisioningEntr
177184 private Collection <LoanProductProvisioningEntry > generateLoanProvisioningEntry (ProvisioningEntry parent , LocalDate date ) {
178185 Collection <LoanProductProvisioningEntryData > entries = this .provisioningEntriesReadPlatformService
179186 .retrieveLoanProductsProvisioningData (date );
187+ // Collect all referenced IDs upfront and bulk-fetch via findAllById,
188+ // replacing the previous pattern of N x 5 individual repository calls per
189+ // loop iteration (consistent with the optimisation in FINERACT-2561).
190+ Set <Long > productIds = entries .stream ().map (LoanProductProvisioningEntryData ::getProductId ).collect (Collectors .toSet ());
191+ Set <Long > officeIds = entries .stream ().map (LoanProductProvisioningEntryData ::getOfficeId ).collect (Collectors .toSet ());
192+ Set <Long > categoryIds = entries .stream ().map (LoanProductProvisioningEntryData ::getCategoryId ).collect (Collectors .toSet ());
193+ Set <Long > glAccountIds = entries .stream ().flatMap (d -> Stream .of (d .getLiablityAccount (), d .getExpenseAccount ()))
194+ .collect (Collectors .toSet ());
195+
196+ Map <Long , LoanProduct > loanProductMap = loanProductRepository .findAllById (productIds ).stream ()
197+ .collect (Collectors .toMap (LoanProduct ::getId , Function .identity ()));
198+ Map <Long , Office > officeMap = officeRepository .findAllById (officeIds ).stream ()
199+ .collect (Collectors .toMap (Office ::getId , Function .identity ()));
200+ Map <Long , ProvisioningCategory > categoryMap = provisioningCategoryRepository .findAllById (categoryIds ).stream ()
201+ .collect (Collectors .toMap (ProvisioningCategory ::getId , Function .identity ()));
202+ Map <Long , GLAccount > glAccountMap = glAccountRepository .findAllById (glAccountIds ).stream ()
203+ .collect (Collectors .toMap (GLAccount ::getId , Function .identity ()));
204+
180205 Map <Integer , LoanProductProvisioningEntry > provisioningEntries = new HashMap <>();
181206 for (LoanProductProvisioningEntryData data : entries ) {
182- LoanProduct loanProduct = this .loanProductRepository .findById (data .getProductId ()).orElseThrow ();
183- Office office = this .officeRepositoryWrapper .findOneWithNotFoundDetection (data .getOfficeId ());
184- ProvisioningCategory provisioningCategory = provisioningCategoryRepository .findById (data .getCategoryId ()).orElse (null );
185- GLAccount liabilityAccount = glAccountRepository .findById (data .getLiablityAccount ()).orElseThrow ();
186- GLAccount expenseAccount = glAccountRepository .findById (data .getExpenseAccount ()).orElseThrow ();
207+ LoanProduct loanProduct = loanProductMap .get (data .getProductId ());
208+ if (loanProduct == null ) {
209+ throw new LoanProductNotFoundException (data .getProductId ());
210+ }
211+ Office office = officeMap .get (data .getOfficeId ());
212+ if (office == null ) {
213+ throw new OfficeNotFoundException (data .getOfficeId ());
214+ }
215+ GLAccount liabilityAccount = glAccountMap .get (data .getLiablityAccount ());
216+ if (liabilityAccount == null ) {
217+ throw new GLAccountNotFoundException (data .getLiablityAccount ());
218+ }
219+ GLAccount expenseAccount = glAccountMap .get (data .getExpenseAccount ());
220+ if (expenseAccount == null ) {
221+ throw new GLAccountNotFoundException (data .getExpenseAccount ());
222+ }
223+ ProvisioningCategory provisioningCategory = categoryMap .get (data .getCategoryId ());
187224 MonetaryCurrency currency = loanProduct .getPrincipalAmount ().getCurrency ();
188225 Money money = Money .of (currency , data .getBalance ());
189226 Money amountToReserve = money .percentageOf (data .getPercentage (), MoneyHelper .getMathContext ());
0 commit comments