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 ;
@@ -186,13 +193,43 @@ public CommandProcessingResult reCreateProvisioningEntries(Long provisioningEntr
186193 private Collection <LoanProductProvisioningEntry > generateLoanProvisioningEntry (ProvisioningEntry parent , LocalDate date ) {
187194 Collection <LoanProductProvisioningEntryData > entries = this .provisioningEntriesReadPlatformService
188195 .retrieveLoanProductsProvisioningData (date );
196+ // Collect all referenced IDs upfront and bulk-fetch via findAllById,
197+ // replacing the previous pattern of N x 5 individual repository calls per
198+ // loop iteration (consistent with the optimisation in FINERACT-2561).
199+ Set <Long > productIds = entries .stream ().map (LoanProductProvisioningEntryData ::getProductId ).collect (Collectors .toSet ());
200+ Set <Long > officeIds = entries .stream ().map (LoanProductProvisioningEntryData ::getOfficeId ).collect (Collectors .toSet ());
201+ Set <Long > categoryIds = entries .stream ().map (LoanProductProvisioningEntryData ::getCategoryId ).collect (Collectors .toSet ());
202+ Set <Long > glAccountIds = entries .stream ().flatMap (d -> Stream .of (d .getLiablityAccount (), d .getExpenseAccount ()))
203+ .collect (Collectors .toSet ());
204+
205+ Map <Long , LoanProduct > loanProductMap = loanProductRepository .findAllById (productIds ).stream ()
206+ .collect (Collectors .toMap (LoanProduct ::getId , Function .identity ()));
207+ Map <Long , Office > officeMap = officeRepository .findAllById (officeIds ).stream ()
208+ .collect (Collectors .toMap (Office ::getId , Function .identity ()));
209+ Map <Long , ProvisioningCategory > categoryMap = provisioningCategoryRepository .findAllById (categoryIds ).stream ()
210+ .collect (Collectors .toMap (ProvisioningCategory ::getId , Function .identity ()));
211+ Map <Long , GLAccount > glAccountMap = glAccountRepository .findAllById (glAccountIds ).stream ()
212+ .collect (Collectors .toMap (GLAccount ::getId , Function .identity ()));
213+
189214 Map <Integer , LoanProductProvisioningEntry > provisioningEntries = new HashMap <>();
190215 for (LoanProductProvisioningEntryData data : entries ) {
191- LoanProduct loanProduct = this .loanProductRepository .findById (data .getProductId ()).orElseThrow ();
192- Office office = this .officeRepositoryWrapper .findOneWithNotFoundDetection (data .getOfficeId ());
193- ProvisioningCategory provisioningCategory = provisioningCategoryRepository .findById (data .getCategoryId ()).orElse (null );
194- GLAccount liabilityAccount = glAccountRepository .findById (data .getLiablityAccount ()).orElseThrow ();
195- GLAccount expenseAccount = glAccountRepository .findById (data .getExpenseAccount ()).orElseThrow ();
216+ LoanProduct loanProduct = loanProductMap .get (data .getProductId ());
217+ if (loanProduct == null ) {
218+ throw new LoanProductNotFoundException (data .getProductId ());
219+ }
220+ Office office = officeMap .get (data .getOfficeId ());
221+ if (office == null ) {
222+ throw new OfficeNotFoundException (data .getOfficeId ());
223+ }
224+ GLAccount liabilityAccount = glAccountMap .get (data .getLiablityAccount ());
225+ if (liabilityAccount == null ) {
226+ throw new GLAccountNotFoundException (data .getLiablityAccount ());
227+ }
228+ GLAccount expenseAccount = glAccountMap .get (data .getExpenseAccount ());
229+ if (expenseAccount == null ) {
230+ throw new GLAccountNotFoundException (data .getExpenseAccount ());
231+ }
232+ ProvisioningCategory provisioningCategory = categoryMap .get (data .getCategoryId ());
196233 MonetaryCurrency currency = loanProduct .getPrincipalAmount ().getCurrency ();
197234 Money money = Money .of (currency , data .getBalance ());
198235 Money amountToReserve = money .percentageOf (data .getPercentage (), MoneyHelper .getMathContext ());
0 commit comments