diff --git a/build.gradle b/build.gradle index d4e75b7e2..537d7d085 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,8 @@ buildscript { dependencies { classpath 'com.bmuschko:gradle-cargo-plugin:2.9.0' - classpath 'org.apache.openjpa:openjpa:3.2.1' // when upgrading, also change OpenJPA version repeated in fineract-provider/build.gradle! + classpath 'org.eclipse.persistence:eclipselink:2.7.10' + classpath 'jakarta.ws.rs:jakarta.ws.rs-api:2.1.6' classpath('com.google.cloud.tools:jib-layer-filter-extension-gradle:0.1.0') } } @@ -119,7 +120,7 @@ allprojects { // We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things. // We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available. - dependency 'org.apache.openjpa:openjpa:3.2.1' // when upgrading, also change OpenJPA version repeated above in buildscript! + dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10' dependency 'com.google.guava:guava:31.1-jre' dependency 'com.google.code.gson:gson:2.9.0' dependency 'com.google.truth:truth:1.1.3' @@ -415,7 +416,9 @@ configure(project.fineractJavaProjects) { "-Xlint:varargs", "-Xlint:preview", "-Xlint:static", - "-Werror", + // -Werror needs to be disabled because EclipseLink's static weaving doesn't generate warning-free code + // and during an IntelliJ recompilation, it fails + //"-Werror", "-Xmaxwarns", 1500, "-Xmaxerrs", @@ -477,7 +480,7 @@ configure(project.fineractJavaProjects) { licenseMain.dependsOn compileJava processResources.dependsOn compileJava - // If we are running Gradle within Eclipse to enhance classes with OpenJPA, + // If we are running Gradle within Eclipse to enhance classes, // set the classes directory to point to Eclipse's default build directory if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') { sourceSets.main.java.outputDir = file("$projectDir/bin/main") @@ -632,6 +635,7 @@ configure(project.fineractJavaProjects) { spotbugs { reportLevel = 'high' showProgress = false + excludeFilter = file("$rootDir/config/spotbugs/exclude.xml") } // https://github.com/spotbugs/spotbugs-gradle-plugin/issues/242 spotbugsMain { diff --git a/config/spotbugs/exclude.xml b/config/spotbugs/exclude.xml new file mode 100644 index 000000000..19a9dc04c --- /dev/null +++ b/config/spotbugs/exclude.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle index 4baaa31e0..8966251aa 100644 --- a/fineract-provider/build.gradle +++ b/fineract-provider/build.gradle @@ -26,70 +26,21 @@ apply plugin: 'com.gorylenko.gradle-git-properties' apply plugin: 'io.swagger.core.v3.swagger-gradle-plugin' apply plugin: 'com.google.cloud.tools.jib' -// Custom OpenJPA enhancement + compileJava.doLast { - def enhanceIncludes = [ - '**/AbstractPersistableCustom.class', - '**/domain/*.class' - ] - - def classesToEnhance = project.sourceSets.main.output.classesDirs.collectMany { classesDir -> - project.fileTree(classesDir).matching { - enhanceIncludes.forEach { include it } - }.files + def mainSS = sourceSets.main + def source = mainSS.java.classesDirectory.get() + copy { + from "src/main/resources/" + into source } - - String persistenceXml = "META-INF/persistence.xml" - def persistenceXmlFile - - // Check if persistence.xml is in the resource dirs. - project.sourceSets.main.resources.srcDirs.collect { resourceDir -> - def persistenceXmlFileCandidate = project.fileTree(resourceDir).matching { - include persistenceXml - } - - if (!persistenceXmlFileCandidate.isEmpty()) { - if (persistenceXmlFile == null) { - persistenceXmlFile = persistenceXmlFileCandidate.singleFile - } else { - throw new InvalidUserDataException("Multiple persistence.xml files found in path: " + - persistenceXmlFile + ", " + persistenceXmlFileCandidate) - } - } - - // Nothing found. Fallback to plain file. - if (persistenceXmlFile == null) { - persistenceXmlFile = project.file(persistenceXml) - if (!persistenceXmlFile.exists()) { - throw new InvalidUserDataException( - "Could not find valid persistence.xml in path " + this.persistenceXml) - } - } + javaexec { + description = 'Performs EclipseLink static weaving of entity classes' + def target = source + main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave' + args '-persistenceinfo', source, '-classpath', configurations.runtimeClasspath, source, target + classpath configurations.runtimeClasspath } - - org.apache.openjpa.lib.util.Options options = new org.apache.openjpa.lib.util.Options([ - "addDefaultConstructor" : true, - "enforcePropertyRestrictions": true, - "tmpClassLoader" : false, - "propertiesFile" : persistenceXmlFile - ]) - - def classes = project.sourceSets.main.output.classesDirs.collect { it.toURI().toURL() } - - def compileJars = project.configurations.compileClasspath.files.collect { jar -> - jar.toURI().toURL() - } - - def resources = project.sourceSets.main.resources.srcDirs.collect { resource -> - resource.toURI().toURL() - } - - def urls = (classes + compileJars + resources) - - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(new URLClassLoader((URL[])urls, currentClassLoader)); - org.apache.openjpa.enhance.PCEnhancer.run((String []) classesToEnhance, options); - Thread.currentThread().setContextClassLoader(currentClassLoader); } // Configuration for Swagger documentation generation task @@ -151,7 +102,8 @@ apply from: 'dependencies.gradle' modernizer { ignoreClassNamePatterns = [ '.*AbstractPersistableCustom', - '.*EntityTables' + '.*EntityTables', + '.*domain.*' ] } diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle index 461be980c..99f46690d 100644 --- a/fineract-provider/dependencies.gradle +++ b/fineract-provider/dependencies.gradle @@ -89,9 +89,8 @@ dependencies { implementation ('org.springframework.boot:spring-boot-starter-data-jpa') { exclude group: 'org.hibernate' } - implementation ('org.apache.openjpa:openjpa') { - exclude group: 'org.eclipse.persistence' - exclude group: 'org.apache.geronimo.specs' + implementation('org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10') { + exclude group: 'org.eclipse.persistence', module: 'jakarta.persistence' } implementation ('org.quartz-scheduler:quartz') { exclude group: 'com.zaxxer', module: 'HikariCP-java7' diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/service/FinancialActivityAccountWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/service/FinancialActivityAccountWritePlatformServiceImpl.java index 528bf8802..4ac2d3a85 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/service/FinancialActivityAccountWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/service/FinancialActivityAccountWritePlatformServiceImpl.java @@ -74,7 +74,7 @@ public class FinancialActivityAccountWritePlatformServiceImpl implements Financi FinancialActivityAccount financialActivityAccount = FinancialActivityAccount.createNew(glAccount, financialActivityId); validateFinancialActivityAndAccountMapping(financialActivityAccount); - this.financialActivityAccountRepository.save(financialActivityAccount); + this.financialActivityAccountRepository.saveAndFlush(financialActivityAccount); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(financialActivityAccount.getId()) // @@ -122,7 +122,7 @@ public class FinancialActivityAccountWritePlatformServiceImpl implements Financi if (!changes.isEmpty()) { validateFinancialActivityAndAccountMapping(financialActivityAccount); - this.financialActivityAccountRepository.save(financialActivityAccount); + this.financialActivityAccountRepository.saveAndFlush(financialActivityAccount); } return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountWritePlatformServiceJpaRepositoryImpl.java index 37b46b73b..a593ea3ef 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountWritePlatformServiceJpaRepositoryImpl.java @@ -107,7 +107,7 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount glAccount.generateHierarchy(); - this.glAccountRepository.save(glAccount); + this.glAccountRepository.saveAndFlush(glAccount); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(glAccount.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java index 03e524725..0c1ce6762 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java @@ -1098,7 +1098,7 @@ public class AccountingProcessorHelper { final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId, manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId, null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId); - this.glJournalEntryRepository.save(journalEntry); + this.glJournalEntryRepository.saveAndFlush(journalEntry); } private void createCreditJournalEntryForShares(final Office office, final String currencyCode, final GLAccount account, @@ -1117,7 +1117,7 @@ public class AccountingProcessorHelper { final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId, manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId, null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId); - this.glJournalEntryRepository.save(journalEntry); + this.glJournalEntryRepository.saveAndFlush(journalEntry); } public GLAccount getLinkedGLAccountForLoanProduct(final Long loanProductId, final int accountMappingTypeId, final Long paymentTypeId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java index 3649246b1..f9be74ad6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java @@ -412,11 +412,11 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa journalEntry.getShareTransactionId()); } // save the reversal entry - this.glJournalEntryRepository.save(reversalJournalEntry); + this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry); journalEntry.setReversalJournalEntry(reversalJournalEntry); journalEntry.setReversed(true); // save the updated journal entry - this.glJournalEntryRepository.save(journalEntry); + this.glJournalEntryRepository.saveAndFlush(journalEntry); } return reversalTransactionId; @@ -580,11 +580,11 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa journalEntry.getShareTransactionId()); } // save the reversal entry - this.glJournalEntryRepository.save(reversalJournalEntry); + this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry); journalEntry.setReversalJournalEntry(reversalJournalEntry); journalEntry.setReversed(true); // save the updated journal entry - this.glJournalEntryRepository.save(journalEntry); + this.glJournalEntryRepository.saveAndFlush(journalEntry); } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java index ca2c2f6d1..73267804e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java @@ -78,7 +78,7 @@ public class ProductToGLAccountMappingHelper { final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, portfolioProductType.getValue(), placeHolderTypeId); - this.accountMappingRepository.save(accountMapping); + this.accountMappingRepository.saveAndFlush(accountMapping); } public void mergeProductToAccountMappingChanges(final JsonElement element, final String paramName, final Long productId, @@ -97,7 +97,7 @@ public class ProductToGLAccountMappingHelper { final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId); changes.put(paramName, accountId); accountMapping.setGlAccount(glAccount); - this.accountMappingRepository.save(accountMapping); + this.accountMappingRepository.saveAndFlush(accountMapping); } } } @@ -116,12 +116,12 @@ public class ProductToGLAccountMappingHelper { changes.put(paramName, accountId); ProductToGLAccountMapping newAccountMapping = new ProductToGLAccountMapping(glAccount, productId, portfolioProductType.getValue(), accountTypeId); - this.accountMappingRepository.save(newAccountMapping); + this.accountMappingRepository.saveAndFlush(newAccountMapping); } else if (!accountMapping.getGlAccount().getId().equals(accountId)) { final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId); changes.put(paramName, accountId); accountMapping.setGlAccount(glAccount); - this.accountMappingRepository.save(accountMapping); + this.accountMappingRepository.saveAndFlush(accountMapping); } } } @@ -258,7 +258,7 @@ public class ProductToGLAccountMappingHelper { allowedAccountTypes, newGLAccountId); } chargeToIncomeAccountMapping.setGlAccount(glAccount); - this.accountMappingRepository.save(chargeToIncomeAccountMapping); + this.accountMappingRepository.saveAndFlush(chargeToIncomeAccountMapping); } } // deleted payment type else { @@ -334,7 +334,7 @@ public class ProductToGLAccountMappingHelper { if (!newGLAccountId.equals(existingPaymentChannelToFundSourceMapping.getGlAccount().getId())) { final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), newGLAccountId); existingPaymentChannelToFundSourceMapping.setGlAccount(glAccount); - this.accountMappingRepository.save(existingPaymentChannelToFundSourceMapping); + this.accountMappingRepository.saveAndFlush(existingPaymentChannelToFundSourceMapping); } } // deleted payment type else { @@ -364,7 +364,7 @@ public class ProductToGLAccountMappingHelper { final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), paymentTypeSpecificFundAccountId); final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, portfolioProductType.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(), paymentType); - this.accountMappingRepository.save(accountMapping); + this.accountMappingRepository.saveAndFlush(accountMapping); } /** @@ -395,7 +395,7 @@ public class ProductToGLAccountMappingHelper { } final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, portfolioProductType.getValue(), placeHolderAccountType.getValue(), charge); - this.accountMappingRepository.save(accountMapping); + this.accountMappingRepository.saveAndFlush(accountMapping); } private List getAllowedAccountTypesForFeeMapping() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java index ba226f1a3..94e4bc657 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl.java @@ -128,7 +128,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements requestedEntry.setJournalEntryCreated(Boolean.TRUE); } - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); this.journalEntryWritePlatformService.createProvisioningJournalEntries(requestedEntry); } @@ -210,7 +210,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements .retrieveExistingProvisioningIdDateWithJournals(); revertAndAddJournalEntries(exisProvisioningEntryData, requestedEntry); } else { - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); } return requestedEntry; } @@ -220,10 +220,10 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements ProvisioningEntry requestedEntry = this.provisioningEntryRepository.findById(provisioningEntryId) .orElseThrow(() -> new ProvisioningEntryNotfoundException(provisioningEntryId)); requestedEntry.getLoanProductProvisioningEntries().clear(); - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); Collection entries = generateLoanProvisioningEntry(requestedEntry, requestedEntry.getCreatedDate()); requestedEntry.setProvisioningEntries(entries); - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(requestedEntry.getId()).build(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java index d0a967ef0..337b2c7ab 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java @@ -63,7 +63,7 @@ public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePla this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json()); final AdHoc entity = AdHoc.fromJson(command); - this.adHocRepository.save(entity); + this.adHocRepository.saveAndFlush(entity); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java index cb01262fc..90db86a82 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java @@ -152,7 +152,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer public CommandProcessingResult logCommand(CommandSource commandSourceResult) { commandSourceResult.markAsAwaitingApproval(); - commandSourceResult = this.commandSourceRepository.save(commandSourceResult); + commandSourceResult = this.commandSourceRepository.saveAndFlush(commandSourceResult); return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId()) .withEntityId(commandSourceResult.getResourceId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java index f45818728..4877739c7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java @@ -72,7 +72,7 @@ public class AccountNumberFormatWritePlatformServiceJpaRepositoryImpl implements AccountNumberFormat accountNumberFormat = new AccountNumberFormat(entityAccountType, accountNumberPrefixType, prefixCharacter); - this.accountNumberFormatRepository.save(accountNumberFormat); + this.accountNumberFormatRepository.saveAndFlush(accountNumberFormat); return new CommandProcessingResultBuilder() // .withEntityId(accountNumberFormat.getId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportEventListener.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportEventListener.java index 326b763f7..0332a503f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportEventListener.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportEventListener.java @@ -140,7 +140,7 @@ public class BulkImportEventListener implements ApplicationListener modifiedParams = new HashSet<>(); modifiedParams.add("fileName"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java index 313cf3524..df542106e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java @@ -177,7 +177,7 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai emailCampaign.setStretchyReportParamMap(new Gson().toJson(stretchyReportParams)); } - this.emailCampaignRepository.save(emailCampaign); + this.emailCampaignRepository.saveAndFlush(emailCampaign); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailWritePlatformServiceJpaRepositoryImpl.java index 64c7e38f7..0c412d718 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailWritePlatformServiceJpaRepositoryImpl.java @@ -67,7 +67,7 @@ public class EmailWritePlatformServiceJpaRepositoryImpl implements EmailWritePla // TODO: decision to be made on wheter we 'wait' for response or use // 'future/promise' to capture response and update the EmailMessage // table - this.repository.save(message); + this.repository.saveAndFlush(message); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java index a18298bb9..77f209693 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/service/SmsCampaignWritePlatformServiceJpaImpl.java @@ -150,7 +150,7 @@ public class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP throw new GeneralPlatformDomainRuleException("error.msg.campaign.recurrenceStartDate.in.the.past", "Recurrence start date cannot be the past date.", smsCampaign.getRecurrenceStartDate()); } - this.smsCampaignRepository.save(smsCampaign); + this.smsCampaignRepository.saveAndFlush(smsCampaign); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueWritePlatformServiceJpaRepositoryImpl.java index 20887d85b..bbd83ba54 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueWritePlatformServiceJpaRepositoryImpl.java @@ -76,7 +76,7 @@ public class CodeValueWritePlatformServiceJpaRepositoryImpl implements CodeValue final Long codeId = command.entityId(); final Code code = this.codeRepository.findById(codeId).orElseThrow(() -> new CodeNotFoundException(codeId)); final CodeValue codeValue = CodeValue.fromJson(code, command); - this.codeValueRepository.save(codeValue); + this.codeValueRepository.saveAndFlush(codeValue); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java index 79d3f5464..4ddafacd4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java @@ -68,7 +68,7 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf this.fromApiJsonDeserializer.validateForCreate(command.json()); final Code code = Code.fromJson(command); - this.codeRepository.save(code); + this.codeRepository.saveAndFlush(code); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(code.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { @@ -95,7 +95,7 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf final Map changes = code.update(command); if (!changes.isEmpty()) { - this.codeRepository.save(code); + this.codeRepository.saveAndFlush(code); } return new CommandProcessingResultBuilder() // diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java new file mode 100644 index 000000000..366b37b71 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java @@ -0,0 +1,115 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.infrastructure.core.config; + +import java.util.Map; +import org.apache.fineract.infrastructure.core.domain.AuditorAwareImpl; +import org.apache.fineract.infrastructure.core.persistence.DatabaseSelectingPersistenceUnitPostProcessor; +import org.apache.fineract.infrastructure.core.persistence.ExtendedJpaTransactionManager; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver; +import org.apache.fineract.useradministration.domain.AppUser; +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer; +import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Primary; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager; +import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; +import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.jta.JtaTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +@Configuration +@EnableJpaAuditing +@EnableJpaRepositories(basePackages = "org.apache.fineract.**.domain") +public class JPAConfig extends JpaBaseConfiguration { + + private final DatabaseTypeResolver databaseTypeResolver; + + public JPAConfig(RoutingDataSource dataSource, JpaProperties properties, ObjectProvider jtaTransactionManager, + DatabaseTypeResolver databaseTypeResolver) { + super(dataSource, properties, jtaTransactionManager); + this.databaseTypeResolver = databaseTypeResolver; + } + + @Override + @Bean + @Primary + @DependsOn("tenantDatabaseUpgradeService") + public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) { + Map vendorProperties = getVendorProperties(); + customizeVendorProperties(vendorProperties); + return factoryBuilder.dataSource(getDataSource()).packages(getPackagesToScan()).properties(vendorProperties) + .persistenceUnit("jpa-pu").packages("org.apache.fineract").jta(false).build(); + } + + @Override + public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, + ObjectProvider persistenceUnitManager, + ObjectProvider customizers) { + EntityManagerFactoryBuilder builder = super.entityManagerFactoryBuilder(jpaVendorAdapter, persistenceUnitManager, customizers); + builder.setPersistenceUnitPostProcessors(new DatabaseSelectingPersistenceUnitPostProcessor(databaseTypeResolver)); + return builder; + } + + @Override + protected AbstractJpaVendorAdapter createJpaVendorAdapter() { + return new EclipseLinkJpaVendorAdapter(); + } + + @Override + protected Map getVendorProperties() { + return Map.of(PersistenceUnitProperties.WEAVING, "static", PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "true", + PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false"); + } + + @Bean + public AuditorAware auditorAware() { + return new AuditorAwareImpl(); + } + + @Override + @Bean + public PlatformTransactionManager transactionManager(ObjectProvider transactionManagerCustomizers) { + ExtendedJpaTransactionManager transactionManager = new ExtendedJpaTransactionManager(); + transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager)); + return transactionManager; + } + + @Bean + public TransactionTemplate txTemplate(PlatformTransactionManager transactionManager) { + TransactionTemplate tt = new TransactionTemplate(); + tt.setTransactionManager(transactionManager); + return tt; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/PersistenceConfig.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/PersistenceConfig.java deleted file mode 100644 index 071cbe520..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/PersistenceConfig.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.fineract.infrastructure.core.config; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; -import org.apache.fineract.infrastructure.core.domain.AuditorAwareImpl; -import org.apache.fineract.infrastructure.openjpa.OpenJpaTransactionManager; -import org.apache.fineract.infrastructure.openjpa.OpenJpaVendorAdapter; -import org.apache.fineract.useradministration.domain.AppUser; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; -import org.springframework.data.domain.AuditorAware; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.transaction.support.TransactionTemplate; - -@Configuration -@EnableJpaAuditing -@EnableJpaRepositories(basePackages = "org.apache.fineract.**.domain") -public class PersistenceConfig { - - @Autowired - DataSource routingDataSource; - - @Bean - @DependsOn("tenantDatabaseUpgradeService") - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); - em.setDataSource(routingDataSource); - // NOTE: very important to set this explicitly when building Docker images with Jib; otherwise complains about - // duplicate resources - em.setPersistenceXmlLocation("classpath:META-INF/persistence.xml"); - em.setJpaVendorAdapter(new OpenJpaVendorAdapter()); - em.setPersistenceUnitName("jpa-pu"); - em.afterPropertiesSet(); - return em; - } - - @Bean - public OpenJpaTransactionManager transactionManager(EntityManagerFactory emf) { - OpenJpaTransactionManager jtm = new OpenJpaTransactionManager(); - jtm.setEntityManagerFactory(emf); - return jtm; - } - - @Bean - public TransactionTemplate txTemplate(JpaTransactionManager jtm) { - TransactionTemplate tt = new TransactionTemplate(); - tt.setTransactionManager(jtm); - return tt; - } - - @Bean - public AuditorAware auditorAware() { - return new AuditorAwareImpl(); - } - -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractPersistableCustom.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractPersistableCustom.java index be134dcc0..b8e7efe8d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractPersistableCustom.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/AbstractPersistableCustom.java @@ -23,6 +23,8 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; +import javax.persistence.PostLoad; +import javax.persistence.PrePersist; import javax.persistence.Transient; import org.springframework.data.domain.Persistable; @@ -45,6 +47,9 @@ public abstract class AbstractPersistableCustom implements Persistable, Se @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Transient + private boolean isNew = true; + @Override public Long getId() { return id; @@ -55,8 +60,13 @@ public abstract class AbstractPersistableCustom implements Persistable, Se } @Override - @Transient // DATAJPA-622 public boolean isNew() { - return null == this.id; + return isNew; + } + + @PrePersist + @PostLoad + void markNotNew() { + this.isNew = false; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/DatabaseSelectingPersistenceUnitPostProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/DatabaseSelectingPersistenceUnitPostProcessor.java new file mode 100644 index 000000000..ba343f13b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/DatabaseSelectingPersistenceUnitPostProcessor.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.core.persistence; + +import java.util.Map; +import org.apache.fineract.infrastructure.core.service.database.DatabaseType; +import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver; +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.eclipse.persistence.config.TargetDatabase; +import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo; +import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor; + +public class DatabaseSelectingPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor { + + private static final Map TARGET_DATABASE_MAP = Map.of(DatabaseType.MYSQL, TargetDatabase.MySQL, + DatabaseType.POSTGRESQL, TargetDatabase.PostgreSQL); + + private final DatabaseTypeResolver databaseTypeResolver; + + public DatabaseSelectingPersistenceUnitPostProcessor(DatabaseTypeResolver databaseTypeResolver) { + this.databaseTypeResolver = databaseTypeResolver; + } + + @Override + public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) { + DatabaseType databaseType = databaseTypeResolver.databaseType(); + String targetDatabase = TARGET_DATABASE_MAP.get(databaseType); + if (targetDatabase == null) { + throw new IllegalStateException("Unsupported database: " + databaseType); + } + pui.addProperty(PersistenceUnitProperties.TARGET_DATABASE, targetDatabase); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/EntityScanningPersistenceUnitPostProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/EntityScanningPersistenceUnitPostProcessor.java new file mode 100644 index 000000000..d42c41ace --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/EntityScanningPersistenceUnitPostProcessor.java @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.core.persistence; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.persistence.Entity; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo; +import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor; + +public class EntityScanningPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor, InitializingBean { + + private static final Logger LOG = LoggerFactory.getLogger(EntityScanningPersistenceUnitPostProcessor.class); + + private List packages; + private final Set> persistentClasses = new HashSet<>(); + + @Override + public void afterPropertiesSet() throws Exception { + if (CollectionUtils.isEmpty(packages)) { + throw new IllegalArgumentException("packages must be set"); + } + LOG.debug("Looking for @Entity in {} ", packages); + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); + + scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class)); + + for (String p : packages) { + for (BeanDefinition bd : scanner.findCandidateComponents(p)) { + persistentClasses.add(Class.forName(bd.getBeanClassName())); + } + } + + if (persistentClasses.isEmpty()) { + throw new IllegalArgumentException("No class annotated with @Entity found in: " + packages); + } + } + + @Override + public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo persistenceUnitInfo) { + for (Class c : persistentClasses) { + persistenceUnitInfo.addManagedClassName(c.getName()); + } + } + + public void setPackages(List packages) { + this.packages = packages; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaTransactionManager.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/ExtendedJpaTransactionManager.java similarity index 53% rename from fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaTransactionManager.java rename to fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/ExtendedJpaTransactionManager.java index ae9b83d40..c04d6321a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaTransactionManager.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/ExtendedJpaTransactionManager.java @@ -16,27 +16,52 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.infrastructure.openjpa; +package org.apache.fineract.infrastructure.core.persistence; import javax.persistence.EntityManager; +import javax.persistence.FlushModeType; import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport; import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.support.DefaultTransactionStatus; import org.springframework.transaction.support.TransactionSynchronizationManager; -public class OpenJpaTransactionManager extends JpaTransactionManager { +public class ExtendedJpaTransactionManager extends JpaTransactionManager { + + @Override + protected void doBegin(Object transaction, TransactionDefinition definition) { + super.doBegin(transaction, definition); + if (isReadOnlyTx(transaction)) { + EntityManager entityManager = getCurrentEntityManager(); + if (entityManager != null) { + entityManager.setFlushMode(FlushModeType.COMMIT); + } + } + + } @Override protected void doCommit(DefaultTransactionStatus status) { - JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) status.getTransaction(); - if (txObject.isReadOnly()) { - EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(obtainEntityManagerFactory()); - if (holder != null) { - EntityManager entityManager = holder.getEntityManager(); + if (isReadOnlyTx(status.getTransaction())) { + EntityManager entityManager = getCurrentEntityManager(); + if (entityManager != null) { entityManager.clear(); } } super.doCommit(status); } + + private boolean isReadOnlyTx(Object transaction) { + JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) transaction; + return txObject.isReadOnly(); + } + + private EntityManager getCurrentEntityManager() { + EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(obtainEntityManagerFactory()); + if (holder != null) { + return holder.getEntityManager(); + } + return null; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/OrganisationCreditBureau.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/OrganisationCreditBureau.java index b9ebda9d3..a2d11369b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/OrganisationCreditBureau.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/OrganisationCreditBureau.java @@ -23,6 +23,7 @@ import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; @@ -36,6 +37,7 @@ public class OrganisationCreditBureau extends AbstractPersistableCustom { private String alias; @OneToOne + @JoinColumn(name = "creditbureau_id", nullable = false) private CreditBureau creditbureau; @Column(name = "is_active") diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java index 923a0f5ef..f37a07de7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java @@ -69,7 +69,7 @@ public class CreditBureauConfigurationWritePlatformServiceImpl implements Credit final CreditBureauConfiguration cb_config = CreditBureauConfiguration.fromJson(command, orgcb); - this.creditBureauConfigurationRepository.save(cb_config); + this.creditBureauConfigurationRepository.saveAndFlush(cb_config); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(cb_config.getId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauLoanProductMappingWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauLoanProductMappingWritePlatformServiceImpl.java index 4b4a20b7a..2519d59c8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauLoanProductMappingWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauLoanProductMappingWritePlatformServiceImpl.java @@ -74,7 +74,7 @@ public class CreditBureauLoanProductMappingWritePlatformServiceImpl implements C final CreditBureauLoanProductMapping cb_lp = CreditBureauLoanProductMapping.fromJson(command, orgcb, lp); - this.creditBureauLoanProductMappingRepository.save(cb_lp); + this.creditBureauLoanProductMappingRepository.saveAndFlush(cb_lp); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(cb_lp.getId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java index 4ea67c2a3..1cdd90e5e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java @@ -110,7 +110,7 @@ public class CreditReportWritePlatformServiceImpl implements CreditReportWritePl throw new PlatformApiDataValidationException("creditBureau.has.not.been.Integrated", "creditBureau.has.not.been.Integrated", dataValidationErrors); - } catch (final DataIntegrityViolationException dve) { + } catch (final JpaSystemException | DataIntegrityViolationException dve) { handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException ee) { @@ -189,7 +189,7 @@ public class CreditReportWritePlatformServiceImpl implements CreditReportWritePl } return new CommandProcessingResultBuilder().withEntityId(creditReport.getId()).build(); - } catch (final DataIntegrityViolationException dve) { + } catch (final JpaSystemException | DataIntegrityViolationException dve) { handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException ee) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/OrganisationCreditBureauWritePlatflormServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/OrganisationCreditBureauWritePlatflormServiceImpl.java index a28374441..724b9310d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/OrganisationCreditBureauWritePlatflormServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/OrganisationCreditBureauWritePlatflormServiceImpl.java @@ -62,7 +62,7 @@ public class OrganisationCreditBureauWritePlatflormServiceImpl implements Organi final OrganisationCreditBureau organisationCreditBureau = OrganisationCreditBureau.fromJson(command, creditBureau); - this.organisationCreditBureauRepository.save(organisationCreditBureau); + this.organisationCreditBureauRepository.saveAndFlush(organisationCreditBureau); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(organisationCreditBureau.getId()) .build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java index 519f190fd..232675fb2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java @@ -182,6 +182,7 @@ public class EntityDatatableChecksWritePlatformServiceImpl implements EntityData } + @Transactional(readOnly = true) @Override public void runTheCheckForProduct(final Long entityId, final String entityName, final Long statusCode, String foreignKeyColumn, long productId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReportWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReportWritePlatformServiceImpl.java index 35069bee0..80b10dacb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReportWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReportWritePlatformServiceImpl.java @@ -92,7 +92,7 @@ public class ReportWritePlatformServiceImpl implements ReportWritePlatformServic final Set reportParameterUsages = assembleSetOfReportParameterUsages(report, command); report.update(reportParameterUsages); - this.reportRepository.save(report); + this.reportRepository.saveAndFlush(report); final Permission permission = new Permission("report", report.getReportName(), "READ"); this.permissionRepository.save(permission); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java index e3065f03b..b84ddf714 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java @@ -77,7 +77,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(), documentCommand.getDescription(), fileLocation, contentRepository.getStorageType()); - this.documentRepository.save(document); + this.documentRepository.saveAndFlush(document); return document.getId(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java index f6dcce03a..e7807135d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/entityaccess/service/FineractEntityAccessWriteServiceImpl.java @@ -107,7 +107,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate); - this.fineractEntityToEntityMappingRepository.save(newMap); + this.fineractEntityToEntityMappingRepository.saveAndFlush(newMap); return new CommandProcessingResultBuilder().withEntityId(newMap.getId()).withCommandId(command.commandId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java index 27b35cace..704c6e0bd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java @@ -19,6 +19,7 @@ package org.apache.fineract.infrastructure.gcm.service; import java.util.Date; +import javax.persistence.EntityExistsException; import javax.persistence.PersistenceException; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; @@ -28,7 +29,6 @@ import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationRepositor import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; -import org.apache.openjpa.persistence.EntityExistsException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.orm.jpa.JpaSystemException; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/service/HookWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/service/HookWritePlatformServiceJpaRepositoryImpl.java index 52296074b..e4863a272 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/service/HookWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/hooks/service/HookWritePlatformServiceJpaRepositoryImpl.java @@ -119,7 +119,7 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements HookWritePlatf validateHookRules(template, config, allEvents); - this.hookRepository.save(hook); + this.hookRepository.saveAndFlush(hook); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(hook.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaDialect.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaDialect.java deleted file mode 100644 index 44a95ad71..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaDialect.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.infrastructure.openjpa; - -import java.sql.Connection; -import java.sql.SQLException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; -import org.apache.commons.logging.LogFactory; -import org.apache.openjpa.persistence.FetchPlan; -import org.apache.openjpa.persistence.OpenJPAEntityManager; -import org.apache.openjpa.persistence.OpenJPAPersistence; -import org.apache.openjpa.persistence.jdbc.IsolationLevel; -import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan; -import org.springframework.jdbc.datasource.ConnectionHandle; -import org.springframework.jdbc.datasource.ConnectionHolder; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.orm.jpa.DefaultJpaDialect; -import org.springframework.transaction.SavepointManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; - -/** - * {@link org.springframework.orm.jpa.JpaDialect} implementation for Apache OpenJPA. Developed and tested against - * OpenJPA 2.2. - * - * @author Costin Leau - * @author Juergen Hoeller - * @since 2.0 - */ -public class OpenJpaDialect extends DefaultJpaDialect { - - @Override - public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) - throws PersistenceException, SQLException, TransactionException { - - OpenJPAEntityManager openJpaEntityManager = getOpenJPAEntityManager(entityManager); - - if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { - // Pass custom isolation level on to OpenJPA's JDBCFetchPlan - // configuration - FetchPlan fetchPlan = openJpaEntityManager.getFetchPlan(); - if (fetchPlan instanceof JDBCFetchPlan) { - IsolationLevel isolation = IsolationLevel.fromConnectionConstant(definition.getIsolationLevel()); - ((JDBCFetchPlan) fetchPlan).setIsolation(isolation); - } - } - - entityManager.getTransaction().begin(); - - if (!definition.isReadOnly()) { - // Like with EclipseLink, make sure to start the logic transaction - // early so that other - // participants using the connection (such as JdbcTemplate) run in a - // transaction. - openJpaEntityManager.beginStore(); - } - - // Custom implementation for OpenJPA savepoint handling - return new OpenJpaTransactionData(openJpaEntityManager); - } - - @Override - public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) throws PersistenceException, SQLException { - - return new OpenJpaConnectionHandle(getOpenJPAEntityManager(entityManager)); - } - - /** - * Return the OpenJPA-specific variant of {@code EntityManager}. - * - * @param em - * the generic {@code EntityManager} instance - * @return the OpenJPA-specific variant of {@code EntityManager} - */ - protected OpenJPAEntityManager getOpenJPAEntityManager(EntityManager em) { - return OpenJPAPersistence.cast(em); - } - - /** - * Transaction data Object exposed from {@code beginTransaction}, implementing the {@link SavepointManager} - * interface. - */ - private static class OpenJpaTransactionData implements SavepointManager { - - private final OpenJPAEntityManager entityManager; - - private int savepointCounter = 0; - - OpenJpaTransactionData(OpenJPAEntityManager entityManager) { - this.entityManager = entityManager; - } - - @Override - public Object createSavepoint() throws TransactionException { - this.savepointCounter++; - String savepointName = ConnectionHolder.SAVEPOINT_NAME_PREFIX + this.savepointCounter; - this.entityManager.setSavepoint(savepointName); - return savepointName; - } - - @Override - public void rollbackToSavepoint(Object savepoint) throws TransactionException { - this.entityManager.rollbackToSavepoint((String) savepoint); - } - - @Override - public void releaseSavepoint(Object savepoint) throws TransactionException { - try { - this.entityManager.releaseSavepoint((String) savepoint); - } catch (Throwable ex) { - LogFactory.getLog(OpenJpaTransactionData.class).debug("Could not explicitly release OpenJPA savepoint", ex); - } - } - } - - /** - * {@link ConnectionHandle} implementation that fetches a new OpenJPA-provided Connection for every - * {@code getConnection} call and closes the Connection on {@code releaseConnection}. This is necessary because - * OpenJPA requires the fetched Connection to be closed before continuing EntityManager work. - * - * @see org.apache.openjpa.persistence.OpenJPAEntityManager#getConnection() - */ - private static class OpenJpaConnectionHandle implements ConnectionHandle { - - private final OpenJPAEntityManager entityManager; - - OpenJpaConnectionHandle(OpenJPAEntityManager entityManager) { - this.entityManager = entityManager; - } - - @Override - public Connection getConnection() { - return (Connection) this.entityManager.getConnection(); - } - - @Override - public void releaseConnection(Connection con) { - JdbcUtils.closeConnection(con); - } - } - -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaVendorAdapter.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaVendorAdapter.java deleted file mode 100644 index 37b5c29c1..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaVendorAdapter.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.infrastructure.openjpa; - -import java.util.HashMap; -import java.util.Map; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.spi.PersistenceProvider; -import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; -import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; -import org.apache.openjpa.persistence.PersistenceProviderImpl; -import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; -import org.springframework.orm.jpa.vendor.Database; - -/** - * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Apache OpenJPA. Developed and tested against - * OpenJPA 2.2. - * - *

- * Exposes OpenJPA's persistence provider and EntityManager extension interface, and supports - * {@link AbstractJpaVendorAdapter}'s common configuration settings. - * - * @author Costin Leau - * @author Juergen Hoeller - * @since 2.0 - * @see org.apache.openjpa.persistence.PersistenceProviderImpl - * @see org.apache.openjpa.persistence.OpenJPAEntityManager - */ -public class OpenJpaVendorAdapter extends AbstractJpaVendorAdapter { - - private final PersistenceProvider persistenceProvider = new PersistenceProviderImpl(); - - private final OpenJpaDialect jpaDialect = new OpenJpaDialect(); - - @Override - public PersistenceProvider getPersistenceProvider() { - return this.persistenceProvider; - } - - @Override - public String getPersistenceProviderRootPackage() { - return "org.apache.openjpa"; - } - - @Override - public Map getJpaPropertyMap() { - Map jpaProperties = new HashMap(); - - if (getDatabasePlatform() != null) { - jpaProperties.put("openjpa.jdbc.DBDictionary", getDatabasePlatform()); - } else if (getDatabase() != null) { - String databaseDictonary = determineDatabaseDictionary(getDatabase()); - if (databaseDictonary != null) { - jpaProperties.put("openjpa.jdbc.DBDictionary", databaseDictonary); - } - } - - if (isGenerateDdl()) { - jpaProperties.put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)"); - } - if (isShowSql()) { - // Taken from the OpenJPA 0.9.6 docs ("Standard OpenJPA Log - // Configuration + All SQL Statements") - jpaProperties.put("openjpa.Log", "DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"); - } - - return jpaProperties; - } - - /** - * Determine the OpenJPA database dictionary name for the given database. - * - * @param database - * the specified database - * @return the OpenJPA database dictionary name, or {@code null} if none found - */ - protected String determineDatabaseDictionary(Database database) { - switch (database) { - case DB2: - return "db2"; - case DERBY: - return "derby"; - case HSQL: - return "hsql(SimulateLocking=true)"; - case INFORMIX: - return "informix"; - case MYSQL: - return "mysql"; - case ORACLE: - return "oracle"; - case POSTGRESQL: - return "postgres"; - case SQL_SERVER: - return "sqlserver"; - case SYBASE: - return "sybase"; - default: - return null; - } - } - - @Override - public OpenJpaDialect getJpaDialect() { - return this.jpaDialect; - } - - @Override - public Class getEntityManagerFactoryInterface() { - return OpenJPAEntityManagerFactorySPI.class; - } - - @Override - public Class getEntityManagerInterface() { - return OpenJPAEntityManagerSPI.class; - } - -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobWritePlatformServiceImpl.java index 819d09c14..dc7725baf 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobWritePlatformServiceImpl.java @@ -124,7 +124,7 @@ public class ReportMailingJobWritePlatformServiceImpl implements ReportMailingJo final ReportMailingJob reportMailingJob = ReportMailingJob.newInstance(jsonCommand, stretchyReport, appUser); // save entity - this.reportMailingJobRepository.save(reportMailingJob); + this.reportMailingJobRepository.saveAndFlush(reportMailingJob); return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(reportMailingJob.getId()) .build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsWritePlatformServiceJpaRepositoryImpl.java index 8039d3f1f..c2458c44b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsWritePlatformServiceJpaRepositoryImpl.java @@ -67,7 +67,7 @@ public class SmsWritePlatformServiceJpaRepositoryImpl implements SmsWritePlatfor // TODO: decision to be made on wheter we 'wait' for response or use // 'future/promise' to capture response and update the SmsMessage // table - this.repository.save(message); + this.repository.saveAndFlush(message); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java index c2f698476..55d7bab65 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java @@ -288,7 +288,7 @@ public class InteropServiceImpl implements InteropService { InteropIdentifier identifier = new InteropIdentifier(savingsAccount, request.getIdType(), request.getIdValue(), request.getSubIdOrType(), createdBy.getUsername(), DateUtils.getDateOfTenant()); - identifierRepository.save(identifier); + identifierRepository.saveAndFlush(identifier); return InteropIdentifierAccountResponseData.build(identifier.getId(), savingsAccount.getExternalId()); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java index c78cbe723..3cad192e0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java @@ -35,7 +35,7 @@ public class NotificationGeneratorWritePlatformServiceImpl implements Notificati @Override public Long create(Notification notification) { - this.notificationRepository.save(notification); + this.notificationRepository.saveAndFlush(notification); return notification.getId(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformServiceImpl.java index 0cefb96ef..e74dcc276 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformServiceImpl.java @@ -35,7 +35,7 @@ public class NotificationMapperWritePlatformServiceImpl implements NotificationM @Override public Long create(NotificationMapper notificationMapper) { - this.notificationMapperRepository.save(notificationMapper); + this.notificationMapperRepository.saveAndFlush(notificationMapper); return notificationMapper.getId(); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicSubscriberWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicSubscriberWritePlatformServiceJpaRepositoryImpl.java index d45f8af3d..8d1bcf407 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicSubscriberWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicSubscriberWritePlatformServiceJpaRepositoryImpl.java @@ -35,7 +35,7 @@ public class TopicSubscriberWritePlatformServiceJpaRepositoryImpl implements Top @Override public Long create(TopicSubscriber topicSubscriber) { - topicSubscriberRepository.save(topicSubscriber); + topicSubscriberRepository.saveAndFlush(topicSubscriber); return topicSubscriber.getId(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicWritePlatformServiceJpaRepositoryImpl.java index 153c08342..73c0d656c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicWritePlatformServiceJpaRepositoryImpl.java @@ -35,7 +35,7 @@ public class TopicWritePlatformServiceJpaRepositoryImpl implements TopicWritePla @Override public Long create(Topic topic) { - topicRepository.save(topic); + topicRepository.saveAndFlush(topic); return topic.getId(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java index df4cb859b..9e3021e8a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java @@ -91,7 +91,7 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit final Holiday holiday = Holiday.createNew(offices, command); - this.holidayRepository.save(holiday); + this.holidayRepository.saveAndFlush(holiday); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(holiday.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/office/service/OfficeWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/office/service/OfficeWritePlatformServiceJpaRepositoryImpl.java index cb964a924..995432259 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/office/service/OfficeWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/office/service/OfficeWritePlatformServiceJpaRepositoryImpl.java @@ -98,7 +98,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP final Office office = Office.fromJson(parent, command); // pre save to generate id for use in office hierarchy - this.officeRepositoryWrapper.save(office); + this.officeRepositoryWrapper.saveAndFlush(office); office.generateHierarchy(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl.java index 3db14f920..e429a2558 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl.java @@ -63,7 +63,7 @@ public class ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl implement try { this.fromApiJsonDeserializer.validateForCreate(command.json()); final ProvisioningCategory provisioningCategory = ProvisioningCategory.fromJson(command); - this.provisioningCategoryRepository.save(provisioningCategory); + this.provisioningCategoryRepository.saveAndFlush(provisioningCategory); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCategory.getId()) .build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { @@ -98,7 +98,7 @@ public class ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl implement .orElseThrow(() -> new ProvisioningCategoryNotFoundException(categoryId)); final Map changes = provisioningCategoryForUpdate.update(command); if (!changes.isEmpty()) { - this.provisioningCategoryRepository.save(provisioningCategoryForUpdate); + this.provisioningCategoryRepository.saveAndFlush(provisioningCategoryForUpdate); } return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(categoryId).with(changes).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl.java index 62e43462b..85f23b922 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/provisioning/service/ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl.java @@ -83,7 +83,7 @@ public class ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl implement try { this.fromApiJsonDeserializer.validateForCreate(command.json()); ProvisioningCriteria provisioningCriteria = provisioningCriteriaAssembler.fromParsedJson(command.parsedJson()); - this.provisioningCriteriaRepository.save(provisioningCriteria); + this.provisioningCriteriaRepository.saveAndFlush(provisioningCriteria); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCriteria.getId()) .build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java index e349a1cd8..b8583924a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java @@ -69,7 +69,7 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements StaffWritePla final Office staffOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); final Staff staff = Staff.fromJson(staffOffice, command); - this.staffRepository.save(staff); + this.staffRepository.saveAndFlush(staff); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java index 259ee4bb9..4460258ca 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java @@ -113,7 +113,7 @@ public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformSer final Teller teller = Teller.fromJson(tellerOffice, command); // pre save to generate id for use in office hierarchy - this.tellerRepositoryWrapper.save(teller); + this.tellerRepositoryWrapper.saveAndFlush(teller); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java index 89c392f70..255a14411 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionWritePlatformServiceImpl.java @@ -125,16 +125,16 @@ public class StandingInstructionWritePlatformServiceImpl implements StandingInst if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) { final AccountTransferDetails standingInstruction = this.standingInstructionAssembler .assembleSavingsToSavingsTransfer(command); - this.accountTransferDetailRepository.save(standingInstruction); + this.accountTransferDetailRepository.saveAndFlush(standingInstruction); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); } else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) { final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command); - this.accountTransferDetailRepository.save(standingInstruction); + this.accountTransferDetailRepository.saveAndFlush(standingInstruction); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); } else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) { final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command); - this.accountTransferDetailRepository.save(standingInstruction); + this.accountTransferDetailRepository.saveAndFlush(standingInstruction); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java index 0715b0e5b..b9d052b0d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java @@ -100,7 +100,7 @@ public class AddressWritePlatformServiceImpl implements AddressWritePlatformServ final boolean isActive = command.booleanPrimitiveValueOfParameterNamed("isActive"); final ClientAddress clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); - this.clientAddressRepository.save(clientAddressobj); + this.clientAddressRepository.saveAndFlush(clientAddressobj); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientAddressobj.getId()).build(); } @@ -152,7 +152,7 @@ public class AddressWritePlatformServiceImpl implements AddressWritePlatformServ } clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); - this.clientAddressRepository.save(clientAddressobj); + this.clientAddressRepository.saveAndFlush(clientAddressobj); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java index 855fe8727..8115ad644 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java @@ -31,10 +31,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; @@ -98,8 +98,7 @@ public class Calendar extends AbstractAuditableCustom { @Temporal(TemporalType.TIME) private Date meetingtime; - @OneToMany(fetch = FetchType.EAGER) - @JoinColumn(name = "calendar_id") + @OneToMany(mappedBy = "calendar", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) private Set calendarHistory = new HashSet<>(); protected Calendar() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java index 2a8052f1b..cceee59b1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java @@ -153,7 +153,7 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr throw new PlatformApiDataValidationException(dataValidationErrors); } - this.calendarRepository.save(newCalendar); + this.calendarRepository.saveAndFlush(newCalendar); final CalendarInstance newCalendarInstance = CalendarInstance.from(newCalendar, entityId, entityTypeId); this.calendarInstanceRepository.save(newCalendarInstance); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java index 29fcdefdf..ca76143b4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java @@ -122,7 +122,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP } final Charge charge = Charge.fromJson(command, glAccount, taxGroup, paymentType); - this.chargeRepository.save(charge); + this.chargeRepository.saveAndFlush(charge); // check if the office specific products are enabled. If yes, then // save this savings product against a specific office diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientChargeRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientChargeRepositoryWrapper.java index 3d1fd99bd..1ff775247 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientChargeRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientChargeRepositoryWrapper.java @@ -21,9 +21,9 @@ package org.apache.fineract.portfolio.client.domain; import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; -@Repository +@Service public class ClientChargeRepositoryWrapper { private final ClientChargeRepository repository; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransactionRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransactionRepositoryWrapper.java index df5f76db1..5e8aba44e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransactionRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransactionRepositoryWrapper.java @@ -21,9 +21,9 @@ package org.apache.fineract.portfolio.client.domain; import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.apache.fineract.portfolio.client.exception.ClientTransactionNotFoundException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; -@Repository +@Service public class ClientTransactionRepositoryWrapper { private final ClientTransactionRepository repository; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java index bd54ef01d..6b36d9d37 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java @@ -218,7 +218,7 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client // create Waiver Transaction ClientTransaction clientTransaction = ClientTransaction.waiver(client, client.getOffice(), transactionDate, waivedAmount, clientCharge.getCurrency().getCode(), getAppUserIfPresent()); - this.clientTransactionRepository.save(clientTransaction); + this.clientTransactionRepository.saveAndFlush(clientTransaction); // update charge paid by associations final ClientChargePaidBy chargePaidBy = ClientChargePaidBy.instance(clientTransaction, clientCharge, waivedAmount.getAmount()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java index c5d8f6c52..6f1c305f4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java @@ -145,7 +145,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily ClientFamilyMembers clientFamilyMembers = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, mobileNumber, age, isDependent, relationship, maritalStatus, gender, dateOfBirth, profession); - this.clientFamilyRepository.save(clientFamilyMembers); + this.clientFamilyRepository.saveAndFlush(clientFamilyMembers); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientFamilyMembers.getId()).build(); @@ -257,7 +257,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily familyMember = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, mobileNumber, age, isDependent, relationship, maritalStatus, gender, dateOfBirth, profession); - this.clientFamilyRepository.save(familyMember); + this.clientFamilyRepository.saveAndFlush(familyMember); } @@ -370,7 +370,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily // middleName, lastName, qualification, relationship, maritalStatus, // gender, dateOfBirth, profession); - this.clientFamilyRepository.save(clientFamilyMember); + this.clientFamilyRepository.saveAndFlush(clientFamilyMember); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientFamilyMember.getId()).build(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientIdentifierWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientIdentifierWritePlatformServiceJpaRepositoryImpl.java index 5ab1f56ad..a5f42f9db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientIdentifierWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientIdentifierWritePlatformServiceJpaRepositoryImpl.java @@ -90,7 +90,7 @@ public class ClientIdentifierWritePlatformServiceJpaRepositoryImpl implements Cl final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command); - this.clientIdentifierRepository.save(clientIdentifier); + this.clientIdentifierRepository.saveAndFlush(clientIdentifier); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index acda53d9e..b537c9fdb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -294,7 +294,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender, clientType, clientClassification, legalFormValue, command); - this.clientRepository.save(newClient); + this.clientRepository.saveAndFlush(newClient); boolean rollbackTransaction = false; if (newClient.isActive()) { validateParentGroupRulesBeforeClientActivation(newClient); @@ -303,7 +303,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); } - this.clientRepository.save(newClient); + this.clientRepository.saveAndFlush(newClient); if (newClient.isActive()) { this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEvents.CLIENTS_ACTIVATE, constructEntityMap(BusinessEntity.CLIENT, newClient)); @@ -311,14 +311,14 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP if (newClient.isAccountNumberRequiresAutoGeneration()) { AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.CLIENT); newClient.updateAccountNo(accountNumberGenerator.generate(newClient, accountNumberFormat)); - this.clientRepository.save(newClient); + this.clientRepository.saveAndFlush(newClient); } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); CommandProcessingResult result = openSavingsAccount(newClient, fmt); if (result.getSavingsId() != null) { - this.clientRepository.save(newClient); + this.clientRepository.saveAndFlush(newClient); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/service/CollateralWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/service/CollateralWritePlatformServiceJpaRepositoryImpl.java index 04817049f..e58d6ed13 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/service/CollateralWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/service/CollateralWritePlatformServiceJpaRepositoryImpl.java @@ -95,7 +95,7 @@ public class CollateralWritePlatformServiceJpaRepositoryImpl implements Collater LoanCollateralCannotBeCreatedReason.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loan.getId()); } - this.collateralRepository.save(collateral); + this.collateralRepository.saveAndFlush(collateral); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java index e899ddd3a..7089ca117 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java @@ -34,7 +34,7 @@ public class CollateralManagementRepositoryWrapper { } public CollateralManagementDomain create(CollateralManagementDomain collateralData) { - return this.collateralManagementDomainRepository.save(collateralData); + return this.collateralManagementDomainRepository.saveAndFlush(collateralData); } public CollateralManagementDomain getCollateral(Long collateralId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java index 8170bfa53..b7067cceb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java @@ -73,7 +73,7 @@ public class ClientCollateralManagementWritePlatformServiceImpl implements Clien final CollateralManagementDomain collateralManagementData = this.collateralManagementRepositoryWrapper.getCollateral(collateralId); final ClientCollateralManagement clientCollateralManagement = ClientCollateralManagement.createNew(quantity, client, collateralManagementData); - this.clientCollateralManagementRepositoryWrapper.save(clientCollateralManagement); + this.clientCollateralManagementRepositoryWrapper.saveAndFlush(clientCollateralManagement); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withClientId(command.getClientId()) .withEntityId(clientCollateralManagement.getId()).build(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java index 7413c411e..fabba549c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java @@ -61,7 +61,7 @@ public class FloatingRateWritePlatformServiceImpl implements FloatingRateWritePl this.fromApiJsonDeserializer.validateForCreate(command.json()); final AppUser currentUser = this.context.authenticatedUser(); final FloatingRate newFloatingRate = FloatingRate.createNew(currentUser, command); - this.floatingRateRepository.save(newFloatingRate); + this.floatingRateRepository.saveAndFlush(newFloatingRate); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(newFloatingRate.getId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java index 323ca5dc9..6b8bff2d1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java @@ -68,7 +68,7 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf final Fund fund = Fund.fromJson(command); - this.fundRepository.save(fund); + this.fundRepository.saveAndFlush(fund); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(fund.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { @@ -113,11 +113,11 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf * Guaranteed to throw an exception no matter what the data integrity issue is. */ private void handleFundDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve) { - if (realCause.getMessage().contains("fund_externalid_org")) { + if (realCause.getMessage().contains("m_fund_external_id_key")) { final String externalId = command.stringValueOfParameterNamed("externalId"); throw new PlatformDataIntegrityException("error.msg.fund.duplicate.externalId", "A fund with external id '" + externalId + "' already exists", "externalId", externalId); - } else if (realCause.getMessage().contains("fund_name_org")) { + } else if (realCause.getMessage().contains("m_fund_external_id_name")) { final String name = command.stringValueOfParameterNamed("name"); throw new PlatformDataIntegrityException("error.msg.fund.duplicate.name", "A fund with name '" + name + "' already exists", "name", name); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupRolesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupRolesWritePlatformServiceJpaRepositoryImpl.java index 956a5e8cf..7fc544d99 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupRolesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupRolesWritePlatformServiceJpaRepositoryImpl.java @@ -86,7 +86,7 @@ public class GroupRolesWritePlatformServiceJpaRepositoryImpl implements GroupRol throw new ClientNotInGroupException(clientId, command.getGroupId()); } final GroupRole groupRole = GroupRole.createGroupRole(group, client, role); - this.groupRoleRepository.save(groupRole); + this.groupRoleRepository.saveAndFlush(groupRole); return new CommandProcessingResultBuilder().withClientId(client.getId()).withGroupId(group.getId()) .withEntityId(groupRole.getId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java index 3c2945333..6f9cbc854 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java @@ -201,7 +201,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group boolean rollbackTransaction = false; if (newGroup.isActive()) { - this.groupRepository.save(newGroup); + this.groupRepository.saveAndFlush(newGroup); // validate Group creation rules for Group if (newGroup.isGroup()) { validateGroupRulesBeforeActivation(newGroup); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl.java index a31d88cc8..da096ad57 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl.java @@ -76,7 +76,7 @@ public class InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl implemen final InterestRateChartSlab interestRateChartSlab = this.interestRateChartSlabAssembler.assembleFrom(command); - this.chartSlabRepository.save(interestRateChartSlab); + this.chartSlabRepository.saveAndFlush(interestRateChartSlab); final Long interestRateChartId = interestRateChartSlab.getId(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 2ccb66772..27813b127 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -44,6 +44,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -1245,8 +1246,17 @@ public class Loan extends AbstractPersistableCustom { } public void updateLoanSchedule(final Collection installments, AppUser currentUser) { - this.repaymentScheduleInstallments.clear(); + List existingInstallments = new ArrayList<>(this.repaymentScheduleInstallments); + repaymentScheduleInstallments.clear(); for (final LoanRepaymentScheduleInstallment installment : installments) { + LoanRepaymentScheduleInstallment existingInstallment = findByInstallmentNumber(existingInstallments, + installment.getInstallmentNumber()); + if (existingInstallment != null) { + Set existingCharges = existingInstallment.getInstallmentCharges(); + installment.getInstallmentCharges().addAll(existingCharges); + existingCharges.forEach(c -> c.setInstallment(installment)); + existingInstallment.getInstallmentCharges().clear(); + } addLoanRepaymentScheduleInstallment(installment); } updateLoanScheduleDependentDerivedFields(); @@ -1255,6 +1265,16 @@ public class Loan extends AbstractPersistableCustom { } + private LoanRepaymentScheduleInstallment findByInstallmentNumber(Collection installments, + Integer installmentNumber) { + for (LoanRepaymentScheduleInstallment installment : installments) { + if (Objects.equals(installment.getInstallmentNumber(), installmentNumber)) { + return installment; + } + } + return null; + } + /** * method updates accrual derived fields on installments and reverse the unprocessed transactions */ @@ -4984,6 +5004,7 @@ public class Loan extends AbstractPersistableCustom { .getAmount(); } final LoanInstallmentCharge loanInstallmentCharge = new LoanInstallmentCharge(amount, loanCharge, installment); + installment.getInstallmentCharges().add(loanInstallmentCharge); loanChargePerInstallments.add(loanInstallmentCharge); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 230d5118b..2a2aa6f68 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -286,8 +286,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) { try { - LoanTransaction loanTransaction = this.loanTransactionRepository.save(newRepaymentTransaction); - + this.loanTransactionRepository.saveAndFlush(newRepaymentTransaction); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); final List dataValidationErrors = new ArrayList<>(); @@ -305,12 +304,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { try { - List installments = loan.getRepaymentScheduleInstallments(); - for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getId() == null) { - this.repaymentScheduleInstallmentRepository.save(installment); - } - } this.loanRepositoryWrapper.saveAndFlush(loan); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); @@ -329,12 +322,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { @Override public void saveLoanWithDataIntegrityViolationChecks(final Loan loan) { try { - List installments = loan.getRepaymentScheduleInstallments(); - for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getId() == null) { - this.repaymentScheduleInstallmentRepository.save(installment); - } - } this.loanRepositoryWrapper.save(loan); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); @@ -462,7 +449,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction); - this.loanRepositoryWrapper.save(loan); + this.loanRepositoryWrapper.saveAndFlush(loan); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText); @@ -659,8 +646,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { loan.makeRefundForActiveLoan(newRefundTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); - this.loanTransactionRepository.save(newRefundTransaction); - this.loanRepositoryWrapper.save(loan); + this.loanTransactionRepository.saveAndFlush(newRefundTransaction); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java index 947e552e7..6943f44bb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java @@ -543,9 +543,11 @@ public class LoanCharge extends AbstractPersistableCustom { for (final LoanInstallmentCharge chargePerInstallment : oldChargeInstallments) { if (index == loanChargePerInstallmentArray.length) { remove.add(chargePerInstallment); - chargePerInstallment.updateInstallment(null); + chargePerInstallment.getInstallment().getInstallmentCharges().remove(chargePerInstallment); } else { - chargePerInstallment.copyFrom(loanChargePerInstallmentArray[index++]); + LoanInstallmentCharge newLoanInstallmentCharge = loanChargePerInstallmentArray[index++]; + newLoanInstallmentCharge.getInstallment().getInstallmentCharges().remove(newLoanInstallmentCharge); + chargePerInstallment.copyFrom(newLoanInstallmentCharge); } } this.loanInstallmentCharge.removeAll(remove); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInstallmentCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInstallmentCharge.java index eb207c82b..b690795de 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInstallmentCharge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInstallmentCharge.java @@ -319,4 +319,7 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom implements return this.installment; } + public void setInstallment(LoanRepaymentScheduleInstallment installment) { + this.installment = installment; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInterestRecalcualtionAdditionalDetails.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInterestRecalcualtionAdditionalDetails.java index 7786463bb..a2b5f4d2c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInterestRecalcualtionAdditionalDetails.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanInterestRecalcualtionAdditionalDetails.java @@ -24,6 +24,8 @@ import java.time.ZoneId; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -34,6 +36,10 @@ import org.apache.fineract.infrastructure.core.service.DateUtils; @Table(name = "m_loan_interest_recalculation_additional_details") public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersistableCustom { + @ManyToOne(optional = false) + @JoinColumn(name = "loan_repayment_schedule_id", nullable = false) + private LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment; + @Temporal(TemporalType.DATE) @Column(name = "effective_date") private Date effectiveDate; @@ -59,4 +65,12 @@ public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersista public BigDecimal getAmount() { return this.amount; } + + public LoanRepaymentScheduleInstallment getLoanRepaymentScheduleInstallment() { + return loanRepaymentScheduleInstallment; + } + + public void setLoanRepaymentScheduleInstallment(LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) { + this.loanRepaymentScheduleInstallment = loanRepaymentScheduleInstallment; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java index c47ea396a..911abd484 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java @@ -134,13 +134,15 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus @Column(name = "recalculated_interest_component", nullable = false) private boolean recalculatedInterestComponent; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "loan_repayment_schedule_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRepaymentScheduleInstallment") private Set loanCompoundingDetails = new HashSet<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRepaymentScheduleInstallment") private Set postDatedChecks; + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "installment") + private Set installmentCharges = new HashSet<>(); + LoanRepaymentScheduleInstallment() { this.installmentNumber = null; this.fromDate = null; @@ -162,6 +164,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus this.penaltyCharges = defaultToNullIfZero(penaltyCharges); this.obligationsMet = false; this.recalculatedInterestComponent = recalculatedInterestComponent; + if (compoundingDetails != null) { + compoundingDetails.forEach(cd -> cd.setLoanRepaymentScheduleInstallment(this)); + } this.loanCompoundingDetails = compoundingDetails; this.rescheduleInterestPortion = rescheduleInterestPortion; } @@ -180,6 +185,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus this.penaltyCharges = defaultToNullIfZero(penaltyCharges); this.obligationsMet = false; this.recalculatedInterestComponent = recalculatedInterestComponent; + if (compoundingDetails != null) { + compoundingDetails.forEach(cd -> cd.setLoanRepaymentScheduleInstallment(this)); + } this.loanCompoundingDetails = compoundingDetails; } @@ -861,4 +869,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus this.feeChargesWaived = newFeeChargesCharged; } + public Set getInstallmentCharges() { + return installmentCharges; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRescheduleRequestToTermVariationMapping.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRescheduleRequestToTermVariationMapping.java index 721b83f0c..b4383811c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRescheduleRequestToTermVariationMapping.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRescheduleRequestToTermVariationMapping.java @@ -24,11 +24,16 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; @Entity @Table(name = "m_loan_reschedule_request_term_variations_mapping") public class LoanRescheduleRequestToTermVariationMapping extends AbstractPersistableCustom { + @ManyToOne(optional = false, cascade = CascadeType.ALL) + @JoinColumn(name = "loan_reschedule_request_id", nullable = false) + private LoanRescheduleRequest loanRescheduleRequest; + @ManyToOne(optional = false, cascade = CascadeType.PERSIST) @JoinColumn(name = "loan_term_variations_id", nullable = false) private LoanTermVariations loanTermVariations; @@ -37,16 +42,22 @@ public class LoanRescheduleRequestToTermVariationMapping extends AbstractPersist } - private LoanRescheduleRequestToTermVariationMapping(final LoanTermVariations loanTermVariations) { + private LoanRescheduleRequestToTermVariationMapping(final LoanRescheduleRequest loanRescheduleRequest, + final LoanTermVariations loanTermVariations) { + this.loanRescheduleRequest = loanRescheduleRequest; this.loanTermVariations = loanTermVariations; } - public static LoanRescheduleRequestToTermVariationMapping createNew(final LoanTermVariations loanTermVariation) { - return new LoanRescheduleRequestToTermVariationMapping(loanTermVariation); + public static LoanRescheduleRequestToTermVariationMapping createNew(final LoanRescheduleRequest loanRescheduleRequest, + final LoanTermVariations loanTermVariation) { + return new LoanRescheduleRequestToTermVariationMapping(loanRescheduleRequest, loanTermVariation); } public LoanTermVariations getLoanTermVariations() { return this.loanTermVariations; } + public LoanRescheduleRequest getLoanRescheduleRequest() { + return loanRescheduleRequest; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java index 953ed31f7..bc1970fac 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java @@ -133,8 +133,7 @@ public class LoanTransaction extends AbstractPersistableCustom { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "loanTransaction") private Set loanCollateralManagementSet = new HashSet<>(); - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "loan_transaction_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanTransaction") private Set loanTransactionToRepaymentScheduleMappings = new HashSet<>(); protected LoanTransaction() { @@ -793,6 +792,7 @@ public class LoanTransaction extends AbstractPersistableCustom { } } if (!isMappingUpdated) { + updatedrepaymentScheduleMapping.setLoanTransaction(this); this.loanTransactionToRepaymentScheduleMappings.add(updatedrepaymentScheduleMapping); retainMappings.add(updatedrepaymentScheduleMapping); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionToRepaymentScheduleMapping.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionToRepaymentScheduleMapping.java index 2eeaf6dcc..185df2790 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionToRepaymentScheduleMapping.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionToRepaymentScheduleMapping.java @@ -33,6 +33,10 @@ import org.apache.fineract.organisation.monetary.domain.Money; @Table(name = "m_loan_transaction_repayment_schedule_mapping") public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistableCustom { + @ManyToOne(optional = false, cascade = CascadeType.PERSIST) + @JoinColumn(name = "loan_transaction_id", nullable = false) + private LoanTransaction loanTransaction; + @ManyToOne(optional = false, cascade = CascadeType.PERSIST) @JoinColumn(name = "loan_repayment_schedule_id", nullable = false) private LoanRepaymentScheduleInstallment installment; @@ -56,9 +60,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab } - private LoanTransactionToRepaymentScheduleMapping(final LoanRepaymentScheduleInstallment installment, final BigDecimal principalPortion, - final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, - final BigDecimal amount) { + private LoanTransactionToRepaymentScheduleMapping(final LoanTransaction loanTransaction, + final LoanRepaymentScheduleInstallment installment, final BigDecimal principalPortion, final BigDecimal interestPortion, + final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal amount) { + this.loanTransaction = loanTransaction; this.installment = installment; this.principalPortion = principalPortion; this.interestPortion = interestPortion; @@ -67,9 +72,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab this.amount = amount; } - public static LoanTransactionToRepaymentScheduleMapping createFrom(final LoanRepaymentScheduleInstallment installment, - final Money principalPortion, final Money interestPortion, final Money feeChargesPortion, final Money penaltyChargesPortion) { - return new LoanTransactionToRepaymentScheduleMapping(installment, defaultToNullIfZero(principalPortion), + public static LoanTransactionToRepaymentScheduleMapping createFrom(final LoanTransaction loanTransaction, + final LoanRepaymentScheduleInstallment installment, final Money principalPortion, final Money interestPortion, + final Money feeChargesPortion, final Money penaltyChargesPortion) { + return new LoanTransactionToRepaymentScheduleMapping(loanTransaction, installment, defaultToNullIfZero(principalPortion), defaultToNullIfZero(interestPortion), defaultToNullIfZero(feeChargesPortion), defaultToNullIfZero(penaltyChargesPortion), defaultToNullIfZero(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion))); } @@ -138,6 +144,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab return Money.of(currency, this.penaltyChargesPortion); } + public LoanTransaction getLoanTransaction() { + return loanTransaction; + } + public BigDecimal getPrincipalPortion() { return this.principalPortion; } @@ -153,4 +163,8 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab public BigDecimal getPenaltyChargesPortion() { return this.penaltyChargesPortion; } + + public void setLoanTransaction(LoanTransaction loanTransaction) { + this.loanTransaction = loanTransaction; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/CreocoreLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/CreocoreLoanRepaymentScheduleTransactionProcessor.java index 40e66a947..f097a86b7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/CreocoreLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/CreocoreLoanRepaymentScheduleTransactionProcessor.java @@ -131,8 +131,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); return transactionAmountRemaining; @@ -175,8 +175,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL } loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/EarlyPaymentLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/EarlyPaymentLoanRepaymentScheduleTransactionProcessor.java index 10db11b2c..932f650f5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/EarlyPaymentLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/EarlyPaymentLoanRepaymentScheduleTransactionProcessor.java @@ -84,8 +84,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; @@ -153,8 +153,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -195,8 +195,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/FineractStyleLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/FineractStyleLoanRepaymentScheduleTransactionProcessor.java index c73e06e8b..901f03853 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/FineractStyleLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/FineractStyleLoanRepaymentScheduleTransactionProcessor.java @@ -129,8 +129,8 @@ public class FineractStyleLoanRepaymentScheduleTransactionProcessor extends Abst loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -172,8 +172,8 @@ public class FineractStyleLoanRepaymentScheduleTransactionProcessor extends Abst } loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java index acbed3504..495c52ee3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java @@ -132,8 +132,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -193,8 +193,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -237,8 +237,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java index aa75d446f..fa4245b31 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java @@ -118,8 +118,8 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -158,8 +158,8 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java index 128d0e560..51208eb75 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor.java @@ -118,8 +118,8 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); } if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; @@ -161,8 +161,8 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java index 3623329b0..b2ee29627 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/RBILoanRepaymentScheduleTransactionProcessor.java @@ -93,8 +93,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe final Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); loanTransaction.updateComponents(principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion); if (interestWaivedPortion.isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestWaivedPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion)); } } else if (loanTransaction.isChargePayment()) { final Money principalPortion = Money.zero(currency); @@ -108,8 +108,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe } loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } } else { @@ -133,8 +133,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe final Money principalPortion = Money.zero(currency); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, installment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } } } @@ -159,8 +159,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe } if (!isMappingUpdated && principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion) .isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, installment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } } } @@ -237,8 +237,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } @@ -290,8 +290,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { - transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, - interestPortion, feeChargesPortion, penaltyChargesPortion)); + transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment, + principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion)); } return transactionAmountRemaining; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingTransactionRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingTransactionRepository.java index 1635ce7f1..525ecf129 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingTransactionRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingTransactionRepository.java @@ -27,7 +27,7 @@ import org.springframework.data.repository.query.Param; public interface GuarantorFundingTransactionRepository extends JpaRepository, JpaSpecificationExecutor { - @Query("select ft from GuarantorFundingTransaction ft where ft.loanTransaction.id in (:loanTransactions)") + @Query("select ft from GuarantorFundingTransaction ft where ft.loanTransaction.id in :loanTransactions") List fetchGuarantorFundingTransactions(@Param("loanTransactions") List loanTransactions); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java index 8b083d101..95e49dae1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorDomainServiceImpl.java @@ -185,7 +185,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService { GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null, onHoldTransaction); guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction); - this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction); + this.depositAccountOnHoldTransactionRepository.saveAndFlush(onHoldTransaction); } } @@ -206,8 +206,8 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService { guarantorFundingDetails.releaseFunds(amoutForWithdraw); guarantorFundingDetails.withdrawFunds(amoutForWithdraw); guarantorFundingDetails.getLoanAccount().updateGuaranteeAmount(amoutForWithdraw.negate()); - this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction); - this.guarantorFundingRepository.save(guarantorFundingDetails); + this.depositAccountOnHoldTransactionRepository.saveAndFlush(onHoldTransaction); + this.guarantorFundingRepository.saveAndFlush(guarantorFundingDetails); } } @@ -482,7 +482,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService { calculateAndRelaseGuarantorFunds(guarantorList, guarantorGuarantee, amountForRelease, loanTransaction, accountOnHoldTransactions); this.depositAccountOnHoldTransactionRepository.saveAll(accountOnHoldTransactions); - this.guarantorFundingRepository.save(guarantorFundingDetails); + this.guarantorFundingRepository.saveAndFlush(guarantorFundingDetails); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java index 0d7e451d1..cb71cb78f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java @@ -174,9 +174,9 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto } if (accountAssociations != null) { - this.accountAssociationsRepository.save(accountAssociations); + this.accountAssociationsRepository.saveAndFlush(accountAssociations); } - this.guarantorRepository.save(guarantor); + this.guarantorRepository.saveAndFlush(guarantor); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantor.getOfficeId()) .withEntityId(guarantor.getId()).withLoanId(loan.getId()).build(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { @@ -245,7 +245,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto } if (!changesOnly.isEmpty()) { - this.guarantorRepository.save(guarantorForUpdate); + this.guarantorRepository.saveAndFlush(guarantorForUpdate); } return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantorForUpdate.getOfficeId()) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index fd008cfb5..af149f741 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -930,7 +930,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener * @param currency * @param scheduleParams * @param lastRestDate - * @param periodStartDateApplicableForInterest * @param detail */ private void handleLatePayments(final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO, @@ -991,15 +990,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener /** * @param loanApplicationTerms * @param scheduleParams - * @param priviousScheduledDueDate * @param previousRepaymentDate * @param scheduledDueDate * @param interestRatesForInstallments * @param mc - * @param paymentPeriodsInOneYearCalculator - * @param interestRates - * @param periodsApplicableForGrace - * @param scheduleDateForReversal * @return */ private LoanTermVariationParams applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, @@ -1139,7 +1133,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener * TODO * @param mc * TODO - * @param periodNumber * @return */ private LoanTermVariationParams applyExceptionLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, @@ -1222,7 +1215,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener * @param scheduleParams * @param interestRates * @param interestRatesForInstallments - * @param periodsApplicableForGrace */ private void applyLoanVariationsForPartialScheduleGenerate(final LoanApplicationTerms loanApplicationTerms, LoanScheduleParams scheduleParams, final Collection interestRates, @@ -1317,13 +1309,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener * Method calculates interest on not paid outstanding principal and interest (if compounding is enabled) till * current date and adds new repayment schedule detail * - * @param compoundingMap - * TODO - * @param loanCharges - * TODO - * @param principalPortioMap - * TODO - * */ private Money addInterestOnlyRepaymentScheduleForCurrentdate(final MathContext mc, final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO, final MonetaryCurrency currency, final Collection periods, @@ -1869,8 +1854,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener * * @param firstRepaymentdate * TODO - * @param boolean1 - * @param localDate */ private LocalDate calculateInterestStartDateForPeriod(final LoanApplicationTerms loanApplicationTerms, LocalDate periodStartDate, final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanRescheduleRequest.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanRescheduleRequest.java index ad27b786d..32425bd40 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanRescheduleRequest.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanRescheduleRequest.java @@ -95,8 +95,7 @@ public class LoanRescheduleRequest extends AbstractPersistableCustom { @JoinColumn(name = "rejected_by_user_id") private AppUser rejectedByUser; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "loan_reschedule_request_id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRescheduleRequest") private Set loanRescheduleRequestToTermVariationMappings = new HashSet<>(); /** diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index 1103cbbc9..92daeedcd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -284,8 +284,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche decimalValue, dueDate, endDate, emi); // create a new entry in the m_loan_reschedule_request table - this.loanRescheduleRequestRepository.save(loanRescheduleRequest); - this.loanRepositoryWrapper.save(loan); + + this.loanRescheduleRequestRepository.saveAndFlush(loanRescheduleRequest); return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(loanRescheduleRequest.getId()) .withLoanId(loan.getId()).withClientId(loan.getClientId()).withOfficeId(loan.getOfficeId()) @@ -316,7 +316,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche for (LoanRepaymentScheduleInstallment installment : installments) { if (installment.getDueDate().isEqual(rescheduleFromLocDate) || installment.getDueDate().isEqual(endDateLocDate) || (installment.getDueDate().isAfter(rescheduleFromLocDate) && installment.getDueDate().isBefore(endDateLocDate))) { - createLoanTermVariations(termType, loan, + createLoanTermVariations(loanRescheduleRequest, termType, loan, Date.from(installment.getDueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(installment.getDueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()), loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent); @@ -330,51 +330,57 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche if (rescheduleFromDate != null && adjustedDueDate != null) { LoanTermVariations parent = null; final Integer termType = LoanTermVariationType.DUE_DATE.getValue(); - createLoanTermVariations(termType, loan, rescheduleFromDate, adjustedDueDate, loanRescheduleRequestToTermVariationMappings, - isActive, isSpecificToInstallment, decimalValue, parent); + createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, adjustedDueDate, + loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, decimalValue, parent); } if (rescheduleFromDate != null && interestRate != null) { LoanTermVariations parent = null; final Integer termType = LoanTermVariationType.INTEREST_RATE_FROM_INSTALLMENT.getValue(); - createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, - isSpecificToInstallment, interestRate, parent); + createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate, + loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, interestRate, parent); } if (rescheduleFromDate != null && graceOnPrincipal != null) { final Integer termType = LoanTermVariationType.GRACE_ON_PRINCIPAL.getValue(); LoanTermVariations parent = null; - parent = createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, - isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal), parent); + parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate, + loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal), + parent); BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal); - createLoanTermVariations(LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate, - loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent); + createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, + rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, + extraTermsBasedOnGracePeriods, parent); } if (rescheduleFromDate != null && graceOnInterest != null) { LoanTermVariations parent = null; final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue(); - createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, - isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest), parent); + createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate, + loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest), + parent); } if (rescheduleFromDate != null && extraTerms != null) { LoanTermVariations parent = null; final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(); - createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, - isSpecificToInstallment, BigDecimal.valueOf(extraTerms), parent); + createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate, + loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms), + parent); } loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings); } - private LoanTermVariations createLoanTermVariations(final Integer termType, final Loan loan, Date rescheduleFromDate, - Date adjustedDueDate, List loanRescheduleRequestToTermVariationMappings, - final Boolean isActive, final boolean isSpecificToInstallment, final BigDecimal decimalValue, LoanTermVariations parent) { + private LoanTermVariations createLoanTermVariations(LoanRescheduleRequest loanRescheduleRequest, final Integer termType, + final Loan loan, Date rescheduleFromDate, Date adjustedDueDate, + List loanRescheduleRequestToTermVariationMappings, final Boolean isActive, + final boolean isSpecificToInstallment, final BigDecimal decimalValue, LoanTermVariations parent) { LoanTermVariations loanTermVariation = new LoanTermVariations(termType, rescheduleFromDate, decimalValue, adjustedDueDate, isSpecificToInstallment, loan, loan.status().getValue(), isActive, parent); - loanRescheduleRequestToTermVariationMappings.add(LoanRescheduleRequestToTermVariationMapping.createNew(loanTermVariation)); + loanRescheduleRequestToTermVariationMappings + .add(LoanRescheduleRequestToTermVariationMapping.createNew(loanRescheduleRequest, loanTermVariation)); return loanTermVariation; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 815d84010..fe9776087 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -105,7 +105,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine; -import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; @@ -392,7 +391,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } } - this.loanRepositoryWrapper.save(newLoanApplication); + this.loanRepositoryWrapper.saveAndFlush(newLoanApplication); if (loanProduct.isInterestRecalculationEnabled()) { this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(newLoanApplication); @@ -487,7 +486,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } } else { // for applications other than GLIM newLoanApplication.updateAccountNo(this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat)); - this.loanRepositoryWrapper.save(newLoanApplication); + this.loanRepositoryWrapper.saveAndFlush(newLoanApplication); } } @@ -582,6 +581,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa command.arrayOfParameterNamed(LoanApiConstants.datatables)); } + loanRepositoryWrapper.flush(); + this.entityDatatableChecksWritePlatformService.runTheCheckForProduct(newLoanApplication.getId(), EntityTables.LOAN.getName(), StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), newLoanApplication.productId()); @@ -1224,7 +1225,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa // updating loan interest recalculation details throwing null // pointer exception after saveAndFlush // http://stackoverflow.com/questions/17151757/hibernate-cascade-update-gives-null-pointer/17334374#17334374 - this.loanRepositoryWrapper.save(existingLoanApplication); + this.loanRepositoryWrapper.saveAndFlush(existingLoanApplication); if (productRelatedDetail.isInterestRecalculationEnabled()) { this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication); @@ -1616,7 +1617,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final Map changes = loan.loanApplicationRejection(currentUser, command, defaultLoanLifecycleStateMachine()); if (!changes.isEmpty()) { - this.loanRepositoryWrapper.save(loan); + this.loanRepositoryWrapper.saveAndFlush(loan); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -1668,7 +1669,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } if (!changes.isEmpty()) { - this.loanRepositoryWrapper.save(loan); + this.loanRepositoryWrapper.saveAndFlush(loan); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { @@ -1737,12 +1738,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { try { - List installments = loan.getRepaymentScheduleInstallments(); - for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getId() == null) { - this.repaymentScheduleInstallmentRepository.save(installment); - } - } this.loanRepositoryWrapper.saveAndFlush(loan); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 30940fc0c..83ccfadfe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -667,13 +667,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { try { - List installments = loan.getRepaymentScheduleInstallments(); - for (LoanRepaymentScheduleInstallment installment : installments) { - // installment.setPostDatedChecksToNull(); - if (installment.getId() == null) { - this.repaymentScheduleInstallmentRepository.save(installment); - } - } this.loanRepositoryWrapper.saveAndFlush(loan); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); @@ -691,12 +684,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private void saveLoanWithDataIntegrityViolationChecks(final Loan loan) { try { - List installments = loan.getRepaymentScheduleInstallments(); - for (LoanRepaymentScheduleInstallment installment : installments) { - if (installment.getId() == null) { - this.repaymentScheduleInstallmentRepository.save(installment); - } - } this.loanRepositoryWrapper.save(loan); } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); @@ -1145,7 +1132,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (paymentDetail != null) { this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); } - this.loanTransactionRepository.save(newTransactionDetail); + this.loanTransactionRepository.saveAndFlush(newTransactionDetail); } /*** @@ -1252,7 +1239,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); - this.loanTransactionRepository.save(waiveInterestTransaction); + this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction); /*** * TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the @@ -1328,7 +1315,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final ChangedTransactionDetail changedTransactionDetail = loan.closeAsWrittenOff(command, defaultLoanLifecycleStateMachine(), changes, existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO); LoanTransaction writeoff = changedTransactionDetail.getNewTransactionMappings().remove(0L); - this.loanTransactionRepository.save(writeoff); + this.loanTransactionRepository.saveAndFlush(writeoff); for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { this.loanTransactionRepository.save(mapEntry.getValue()); this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); @@ -1383,7 +1370,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L); if (possibleClosingTransaction != null) { - this.loanTransactionRepository.save(possibleClosingTransaction); + this.loanTransactionRepository.saveAndFlush(possibleClosingTransaction); } for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { this.loanTransactionRepository.save(mapEntry.getValue()); @@ -1682,7 +1669,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.addLoanCharge(loanCharge); - this.loanChargeRepository.save(loanCharge); + this.loanChargeRepository.saveAndFlush(loanCharge); /** * we want to apply charge transactions only for those loans charges that are applied when a loan is active and @@ -1690,7 +1677,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf **/ if (loan.status().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null, currentUser); - this.loanTransactionRepository.save(applyLoanChargeTransaction); + this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction); } boolean isAppliedOnBackDate = false; if (loanCharge.getDueLocalDate() == null || DateUtils.getLocalDateOfTenant().isAfter(loanCharge.getDueLocalDate())) { @@ -1952,7 +1939,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge, currentUser); - this.loanTransactionRepository.save(waiveTransaction); + this.loanTransactionRepository.saveAndFlush(waiveTransaction); saveLoanWithDataIntegrityViolationChecks(loan); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); @@ -2214,7 +2201,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.addLoanTransaction(newTransferTransaction); loan.setLoanStatus(LoanStatus.TRANSFER_IN_PROGRESS.getValue()); - this.loanTransactionRepository.save(newTransferTransaction); + this.loanTransactionRepository.saveAndFlush(newTransferTransaction); saveLoanWithDataIntegrityViolationChecks(loan); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); @@ -2246,7 +2233,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.reassignLoanOfficer(loanOfficer, transferDate); } - this.loanTransactionRepository.save(newTransferAcceptanceTransaction); + this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction); saveLoanWithDataIntegrityViolationChecks(loan); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); @@ -2272,7 +2259,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.addLoanTransaction(newTransferAcceptanceTransaction); loan.setLoanStatus(LoanStatus.ACTIVE.getValue()); - this.loanTransactionRepository.save(newTransferAcceptanceTransaction); + this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction); saveLoanWithDataIntegrityViolationChecks(loan); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java index c3c2fc544..cb9f8f93b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java @@ -185,9 +185,6 @@ public class LoanProduct extends AbstractPersistableCustom { @Column(name = "can_use_for_topup", nullable = false) private boolean canUseForTopup = false; - @Column(name = "is_equal_amortization", nullable = false) - private boolean isEqualAmortization = false; - @Column(name = "fixed_principal_percentage_per_installment", scale = 2, precision = 5, nullable = true) private BigDecimal fixedPrincipalPercentagePerInstallment; @@ -690,7 +687,6 @@ public class LoanProduct extends AbstractPersistableCustom { this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate; this.canUseForTopup = canUseForTopup; - this.isEqualAmortization = isEqualAmortization; this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment; if (rates != null) { @@ -1455,11 +1451,7 @@ public class LoanProduct extends AbstractPersistableCustom { } public boolean isEqualAmortization() { - return isEqualAmortization; - } - - public void setEqualAmortization(boolean isEqualAmortization) { - this.isEqualAmortization = isEqualAmortization; + return loanProductRelatedDetail.isEqualAmortization(); } public List getRates() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java index 5a414fc61..eb81e8b70 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java @@ -141,7 +141,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro this.aprCalculator, floatingRate, rates); loanproduct.updateLoanProductInRelatedClasses(); - this.loanProductRepository.save(loanproduct); + this.loanProductRepository.saveAndFlush(loanproduct); // save accounting mappings this.accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/service/MeetingWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/service/MeetingWritePlatformServiceJpaRepositoryImpl.java index 2732c533a..5f9a1ba3c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/service/MeetingWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/meeting/service/MeetingWritePlatformServiceJpaRepositoryImpl.java @@ -130,7 +130,7 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit newMeeting.associateClientsAttendance(clientsAttendance); } // save meeting details - this.meetingRepositoryWrapper.save(newMeeting); + this.meetingRepositoryWrapper.saveAndFlush(newMeeting); final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null; return new CommandProcessingResultBuilder() // .withEntityId(newMeeting.getId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java index 58ae15036..52cdca444 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java @@ -78,7 +78,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf } final Note newNote = Note.clientNoteFromJson(client, command); - this.noteRepository.save(newNote); + this.noteRepository.saveAndFlush(newNote); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // @@ -105,7 +105,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf final Group group = this.groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId)); final Note newNote = Note.groupNoteFromJson(group, command); - this.noteRepository.save(newNote); + this.noteRepository.saveAndFlush(newNote); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // @@ -123,7 +123,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf final String note = command.stringValueOfParameterNamed("note"); final Note newNote = Note.loanNote(loan, note); - this.noteRepository.save(newNote); + this.noteRepository.saveAndFlush(newNote); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // @@ -145,7 +145,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf final String note = command.stringValueOfParameterNamed("note"); final Note newNote = Note.loanTransactionNote(loan, loanTransaction, note); - this.noteRepository.save(newNote); + this.noteRepository.saveAndFlush(newNote); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/service/PaymentTypeWriteServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/service/PaymentTypeWriteServiceImpl.java index ae48b397a..03955093d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/service/PaymentTypeWriteServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymenttype/service/PaymentTypeWriteServiceImpl.java @@ -58,7 +58,7 @@ public class PaymentTypeWriteServiceImpl implements PaymentTypeWriteService { Long position = command.longValueOfParameterNamed(PaymentTypeApiResourceConstants.POSITION); PaymentType newPaymentType = PaymentType.create(name, description, isCashPayment, position); - this.repository.save(newPaymentType); + this.repository.saveAndFlush(newPaymentType); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(newPaymentType.getId()).build(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateWriteServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateWriteServiceImpl.java index 2e79540a5..5b67eea5e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateWriteServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateWriteServiceImpl.java @@ -78,7 +78,7 @@ public class RateWriteServiceImpl implements RateWriteService { } final Rate rate = Rate.fromJson(command, approveUser); - this.rateRepository.save(rate); + this.rateRepository.saveAndFlush(rate); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(rate.getId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java index c86156038..90d078ae2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java @@ -43,6 +43,7 @@ import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.OneToMany; import javax.persistence.OneToOne; +import javax.persistence.OrderBy; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; @@ -86,6 +87,7 @@ public class RecurringDepositAccount extends SavingsAccount { @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "account") private DepositAccountInterestRateChart chart; + @OrderBy(value = "installmentNumber, id") @OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval = true, fetch = FetchType.LAZY) private List depositScheduleInstallments = new ArrayList<>(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java index 6612b4e50..aee89bee8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java @@ -238,7 +238,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi } private Long saveTransactionToGenerateTransactionId(final SavingsAccountTransaction transaction) { - this.savingsAccountTransactionRepository.save(transaction); + this.savingsAccountTransactionRepository.saveAndFlush(transaction); return transaction.getId(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java index 241253f3a..014ca9967 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java @@ -121,8 +121,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { @Column(name = "is_loan_disbursement", length = 1, nullable = true) private boolean isLoanDisbursement; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "savings_transaction_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "savingsAccountTransaction") private List taxDetails = new ArrayList<>(); @Column(name = "release_id_of_hold_amount", length = 20) @@ -276,7 +275,8 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { final SavingsAccountTransaction accountTransaction) { if (taxDetails != null) { for (Map.Entry mapEntry : taxDetails.entrySet()) { - accountTransaction.getTaxDetails().add(new SavingsAccountTransactionTaxDetails(mapEntry.getKey(), mapEntry.getValue())); + accountTransaction.getTaxDetails() + .add(new SavingsAccountTransactionTaxDetails(accountTransaction, mapEntry.getKey(), mapEntry.getValue())); } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionTaxDetails.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionTaxDetails.java index 1f6ce1e3d..0697b1a3b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionTaxDetails.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionTaxDetails.java @@ -32,6 +32,10 @@ import org.apache.fineract.portfolio.tax.domain.TaxComponent; @Table(name = "m_savings_account_transaction_tax_details") public class SavingsAccountTransactionTaxDetails extends AbstractPersistableCustom { + @ManyToOne + @JoinColumn(name = "savings_transaction_id", nullable = false) + private SavingsAccountTransaction savingsAccountTransaction; + @ManyToOne @JoinColumn(name = "tax_component_id", nullable = false) private TaxComponent taxComponent; @@ -41,7 +45,9 @@ public class SavingsAccountTransactionTaxDetails extends AbstractPersistableCust protected SavingsAccountTransactionTaxDetails() {} - public SavingsAccountTransactionTaxDetails(final TaxComponent taxComponent, final BigDecimal amount) { + public SavingsAccountTransactionTaxDetails(final SavingsAccountTransaction savingsAccountTransaction, final TaxComponent taxComponent, + final BigDecimal amount) { + this.savingsAccountTransaction = savingsAccountTransaction; this.taxComponent = taxComponent; this.amount = amount; } @@ -58,4 +64,11 @@ public class SavingsAccountTransactionTaxDetails extends AbstractPersistableCust this.amount = amount.getAmount(); } + public SavingsAccountTransaction getSavingsAccountTransaction() { + return savingsAccountTransaction; + } + + public void setSavingsAccountTransaction(SavingsAccountTransaction savingsAccountTransaction) { + this.savingsAccountTransaction = savingsAccountTransaction; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java index 3de6da11f..75dafe97b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java @@ -120,6 +120,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service +@Transactional public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements DepositAccountWritePlatformService { private static final Logger LOG = LoggerFactory.getLogger(DepositAccountWritePlatformServiceJpaRepositoryImpl.class); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index 8338aeae6..dd3459f76 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -210,7 +210,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth); - this.fixedDepositAccountRepository.save(account); + this.fixedDepositAccountRepository.saveAndFlush(account); if (account.isAccountNumberRequiresAutoGeneration()) { AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.CLIENT); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/FixedDepositProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/FixedDepositProductWritePlatformServiceJpaRepositoryImpl.java index d8a91eca6..97e9995c2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/FixedDepositProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/FixedDepositProductWritePlatformServiceJpaRepositoryImpl.java @@ -89,7 +89,7 @@ public class FixedDepositProductWritePlatformServiceJpaRepositoryImpl implements final FixedDepositProduct product = this.depositProductAssembler.assembleFixedDepositProduct(command); - this.fixedDepositProductRepository.save(product); + this.fixedDepositProductRepository.saveAndFlush(product); // save accounting mappings this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command, @@ -152,7 +152,7 @@ public class FixedDepositProductWritePlatformServiceJpaRepositoryImpl implements changes.putAll(accountingMappingChanges); if (!changes.isEmpty()) { - this.fixedDepositProductRepository.save(product); + this.fixedDepositProductRepository.saveAndFlush(product); } return new CommandProcessingResultBuilder() // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java index 29415d145..a3bfd19c9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java @@ -26,8 +26,10 @@ import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy; import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service +@Transactional public class GroupSavingsIndividualMonitoringWritePlatformServiceImpl implements GroupSavingsIndividualMonitoringWritePlatformService { private final PlatformSecurityContext context; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/RecurringDepositProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/RecurringDepositProductWritePlatformServiceJpaRepositoryImpl.java index 83351a768..ad0731b00 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/RecurringDepositProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/RecurringDepositProductWritePlatformServiceJpaRepositoryImpl.java @@ -89,7 +89,7 @@ public class RecurringDepositProductWritePlatformServiceJpaRepositoryImpl implem final RecurringDepositProduct product = this.depositProductAssembler.assembleRecurringDepositProduct(command); - this.recurringDepositProductRepository.save(product); + this.recurringDepositProductRepository.saveAndFlush(product); // save accounting mappings this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command, @@ -152,7 +152,7 @@ public class RecurringDepositProductWritePlatformServiceJpaRepositoryImpl implem changes.putAll(accountingMappingChanges); if (!changes.isEmpty()) { - this.recurringDepositProductRepository.save(product); + this.recurringDepositProductRepository.saveAndFlush(product); } return new CommandProcessingResultBuilder() // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index 93c83ef05..9339f1273 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -1809,7 +1809,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transacton.getTransactionLocalDate(), account); - this.savingsAccountTransactionRepository.save(transacton); + this.savingsAccountTransactionRepository.saveAndFlush(transacton); if (backdatedTxnsAllowedTill) { // Check again whether transactions are modified @@ -1840,7 +1840,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transaction.getTransactionLocalDate(), account); account.releaseOnHoldAmount(transaction.getAmount()); - this.savingsAccountTransactionRepository.save(transaction); + this.savingsAccountTransactionRepository.saveAndFlush(transaction); holdTransaction.updateReleaseId(transaction.getId()); if (backdatedTxnsAllowedTill) { @@ -1853,6 +1853,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(account.getId()).build(); } + @Transactional @Override public CommandProcessingResult blockCredits(final Long savingsId) { this.context.authenticatedUser(); @@ -1869,6 +1870,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build(); } + @Transactional @Override public CommandProcessingResult unblockCredits(final Long savingsId) { this.context.authenticatedUser(); @@ -1885,6 +1887,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build(); } + @Transactional @Override public CommandProcessingResult blockDebits(final Long savingsId) { this.context.authenticatedUser(); @@ -1901,6 +1904,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build(); } + @Transactional @Override public CommandProcessingResult unblockDebits(final Long savingsId) { this.context.authenticatedUser(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index 3c0c3349b..36824d885 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -251,7 +251,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl Long.valueOf(1), true, SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(), applicationId); account.setGsim(gsimAccount); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); } else { // Parent-empty table @@ -260,7 +260,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl gsimWritePlatformService.addGSIMAccountInfo(accountNumber, group, BigDecimal.ZERO, Long.valueOf(1), true, SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(), applicationId); account.setGsim(gsimRepository.findOneByAccountNumber(accountNumber)); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); } } else { if (gsimRepository.count() != 0) { @@ -270,7 +270,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl account.updateAccountNo(accountNumber); this.gsimWritePlatformService.incrementChildAccountCount(gsimAccount); account.setGsim(gsimAccount); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); } else { // Child-empty table @@ -281,7 +281,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl gsimWritePlatformService.addGSIMAccountInfo(accountNumber, group, BigDecimal.ZERO, Long.valueOf(1), true, SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(), applicationId); account.setGsim(gsimAccount); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); } // reset isAcceptingChild when processing last // application of GSIM @@ -331,7 +331,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.SAVINGS); account.updateAccountNo(this.accountNumberGenerator.generate(account, accountNumberFormat)); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); } } @@ -748,7 +748,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl } this.savingsAccountWritePlatformService.processPostActiveActions(account, savingsAccountDataDTO.getFmt(), existingTransactionIds, existingReversedTransactionIds); - this.savingAccountRepository.save(account); + this.savingAccountRepository.saveAndFlush(account); generateAccountNumber(account); // post journal entries for activation charges diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductWritePlatformServiceJpaRepositoryImpl.java index 9f6d015a9..1c5ea249e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductWritePlatformServiceJpaRepositoryImpl.java @@ -115,7 +115,7 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi final SavingsProduct product = this.savingsProductAssembler.assemble(command); - this.savingProductRepository.save(product); + this.savingProductRepository.saveAndFlush(product); // save accounting mappings this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java index 90ed9fe6d..b023b4239 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java @@ -112,7 +112,7 @@ public class SelfBeneficiariesTPTWritePlatformServiceImpl implements SelfBenefic AppUser user = this.context.authenticatedUser(); SelfBeneficiariesTPT beneficiary = new SelfBeneficiariesTPT(user.getId(), name, officeId, clientId, accountId, accountType, transferLimit); - this.repository.save(beneficiary); + this.repository.saveAndFlush(beneficiary); return new CommandProcessingResultBuilder().withEntityId(beneficiary.getId()).build(); } catch (DataAccessException dae) { handleDataIntegrityIssues(command, dae); @@ -136,7 +136,7 @@ public class SelfBeneficiariesTPTWritePlatformServiceImpl implements SelfBenefic Map changes = beneficiary.update(name, transferLimit); if (!changes.isEmpty()) { try { - this.repository.save(beneficiary); + this.repository.saveAndFlush(beneficiary); return new CommandProcessingResultBuilder() // .withEntityId(beneficiary.getId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountDividendDetails.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountDividendDetails.java index 542701030..cbb7de6a8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountDividendDetails.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountDividendDetails.java @@ -21,8 +21,11 @@ package org.apache.fineract.portfolio.shareaccounts.domain; import java.math.BigDecimal; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividendPayOutDetails; @Entity @Table(name = "m_share_account_dividend_details") @@ -40,13 +43,19 @@ public class ShareAccountDividendDetails extends AbstractPersistableCustom { @Column(name = "savings_transaction_id") private Long savingsTransactionId; + @ManyToOne + @JoinColumn(name = "dividend_pay_out_id", nullable = false) + private ShareProductDividendPayOutDetails productDividentPayOutDetails; + protected ShareAccountDividendDetails() { } - public ShareAccountDividendDetails(final Long shareAccountId, final BigDecimal amount) { + public ShareAccountDividendDetails(final Long shareAccountId, final BigDecimal amount, + final ShareProductDividendPayOutDetails productDividentPayOutDetails) { this.shareAccountId = shareAccountId; this.amount = amount; + this.productDividentPayOutDetails = productDividentPayOutDetails; this.status = ShareAccountDividendStatusType.INITIATED.getValue(); } @@ -59,4 +68,7 @@ public class ShareAccountDividendDetails extends AbstractPersistableCustom { return this.amount; } + public ShareProductDividendPayOutDetails getProductDividentPayOutDetails() { + return productDividentPayOutDetails; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountSchedularServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountSchedularServiceImpl.java index 82b905c47..c62dc7a1c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountSchedularServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountSchedularServiceImpl.java @@ -54,7 +54,7 @@ public class ShareAccountSchedularServiceImpl implements ShareAccountSchedularSe SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountDomainService.handleDividendPayout(savingsAccount, DateUtils.getLocalDateOfTenant(), shareAccountDividendDetails.getAmount(), false); shareAccountDividendDetails.update(ShareAccountDividendStatusType.POSTED.getValue(), savingsAccountTransaction.getId()); - this.shareAccountDividendRepository.save(shareAccountDividendDetails); + this.shareAccountDividendRepository.saveAndFlush(shareAccountDividendDetails); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java index 606086784..8211791e2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java @@ -101,7 +101,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA public CommandProcessingResult createShareAccount(JsonCommand jsonCommand) { try { ShareAccount account = this.accountDataSerializer.validateAndCreate(jsonCommand); - this.shareAccountRepository.save(account); + this.shareAccountRepository.saveAndFlush(account); generateAccountNumber(account); journalEntryWritePlatformService.createJournalEntriesForShares( populateJournalEntries(account, account.getPendingForApprovalSharePurchaseTransactions())); @@ -462,7 +462,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA ShareAccount account = this.shareAccountRepository.findOneWithNotFoundDetection(accountId); Map changes = this.accountDataSerializer.validateAndRedeemShares(jsonCommand, account); if (!changes.isEmpty()) { - this.shareAccountRepository.save(account); + this.shareAccountRepository.saveAndFlush(account); ShareAccountTransaction transaction = (ShareAccountTransaction) changes .get(ShareAccountApiConstants.requestedshares_paramname); // after saving, entity will have different object. So need to @@ -472,7 +472,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA ShareProduct shareProduct = account.getShareProduct(); // remove the redeem shares from total subscribed shares shareProduct.removeSubscribedShares(redeemShares); - this.shareProductRepository.save(shareProduct); + this.shareProductRepository.saveAndFlush(shareProduct); Set transactions = new HashSet<>(); transactions.add(transaction); @@ -498,7 +498,7 @@ public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA ShareAccount account = this.shareAccountRepository.findOneWithNotFoundDetection(accountId); Map changes = this.accountDataSerializer.validateAndClose(jsonCommand, account); if (!changes.isEmpty()) { - this.shareAccountRepository.save(account); + this.shareAccountRepository.saveAndFlush(account); final String noteText = jsonCommand.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.shareNote(account, noteText); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProductDividendPayOutDetails.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProductDividendPayOutDetails.java index 692e628f3..dc87dfd73 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProductDividendPayOutDetails.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProductDividendPayOutDetails.java @@ -27,7 +27,6 @@ import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; @@ -57,8 +56,7 @@ public class ShareProductDividendPayOutDetails extends AbstractAuditableCustom { @Column(name = "status", nullable = false) private Integer status; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "dividend_pay_out_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "productDividentPayOutDetails") private List accountDividendDetails = new ArrayList<>(); protected ShareProductDividendPayOutDetails() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java index aea13bbde..74e548a9b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java @@ -85,7 +85,7 @@ public class ShareProductDividendAssembler { double amountForAccount = numberOfShareDaysPerAccount * amountPerShareDay; final Money accountAmount = Money.of(currency, BigDecimal.valueOf(amountForAccount)); ShareAccountDividendDetails dividendDetails = new ShareAccountDividendDetails(accountData.getId(), - accountAmount.getAmount()); + accountAmount.getAmount(), productDividendPayOutDetails); productDividendPayOutDetails.getAccountDividendDetails().add(dividendDetails); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java index f4c4d2b93..d6d3511e9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java @@ -42,6 +42,8 @@ import org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividentPa import org.apache.fineract.portfolio.shareproducts.domain.ShareProductRepositoryWrapper; import org.apache.fineract.portfolio.shareproducts.exception.DividentProcessingException; import org.apache.fineract.portfolio.shareproducts.serialization.ShareProductDataSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.orm.jpa.JpaSystemException; @@ -50,6 +52,8 @@ import org.springframework.stereotype.Service; @Service public class ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareProductWritePlatformService { + private static final Logger LOG = LoggerFactory.getLogger(ShareProductWritePlatformServiceJpaRepositoryImpl.class); + private final ShareProductRepositoryWrapper repository; private final ShareProductDataSerializer serializer; private final FromJsonHelper fromApiJsonHelper; @@ -78,7 +82,7 @@ public class ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP public CommandProcessingResult createShareProduct(JsonCommand jsonCommand) { try { ShareProduct product = this.serializer.validateAndCreate(jsonCommand); - this.repository.save(product); + this.repository.saveAndFlush(product); // save accounting mappings this.accountMappingWritePlatformService.createShareProductToGLAccountMapping(product.getId(), jsonCommand); @@ -199,6 +203,7 @@ public class ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP } private void handleDataIntegrityIssues(final Exception e) { + LOG.error("Unknown data integrity issue with resource", e); throw new PlatformDataIntegrityException("error.msg.shareproduct.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); } @@ -211,6 +216,7 @@ public class ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP "Share Product with name `" + name + "` already exists", "name", name); } + LOG.error("Unknown data integrity issue with resource", dve); throw new PlatformDataIntegrityException("error.msg.shareproduct.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java index 5f170ac09..1df6b3320 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java @@ -28,7 +28,6 @@ import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; import org.apache.commons.lang3.StringUtils; @@ -44,8 +43,7 @@ public class TaxGroup extends AbstractAuditableCustom { @Column(name = "name", length = 100) private String name; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "tax_group_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "taxGroup") private Set taxGroupMappings = new HashSet<>(); protected TaxGroup() { @@ -55,6 +53,7 @@ public class TaxGroup extends AbstractAuditableCustom { private TaxGroup(final String name, final Set taxGroupMappings) { this.name = name; this.taxGroupMappings = taxGroupMappings; + taxGroupMappings.forEach(m -> m.setTaxGroup(this)); } public static TaxGroup createTaxGroup(final String name, final Set taxGroupMappings) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java index 84c008085..608841c35 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java @@ -39,6 +39,10 @@ import org.apache.fineract.portfolio.tax.api.TaxApiConstants; @Table(name = "m_tax_group_mappings") public class TaxGroupMappings extends AbstractAuditableCustom { + @ManyToOne + @JoinColumn(name = "tax_group_id", nullable = false) + private TaxGroup taxGroup; + @ManyToOne @JoinColumn(name = "tax_component_id", nullable = false) private TaxComponent taxComponent; @@ -118,4 +122,12 @@ public class TaxGroupMappings extends AbstractAuditableCustom { } return endDate; } + + public void setTaxGroup(TaxGroup taxGroup) { + this.taxGroup = taxGroup; + } + + public TaxGroup getTaxGroup() { + return taxGroup; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java index 0288e0e14..6ccdcf5a1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java @@ -60,7 +60,7 @@ public class TaxWritePlatformServiceImpl implements TaxWritePlatformService { public CommandProcessingResult createTaxComponent(final JsonCommand command) { this.validator.validateForTaxComponentCreate(command.json()); TaxComponent taxComponent = this.taxAssembler.assembleTaxComponentFrom(command); - this.taxComponentRepository.save(taxComponent); + this.taxComponentRepository.saveAndFlush(taxComponent); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(taxComponent.getId()) // @@ -74,7 +74,7 @@ public class TaxWritePlatformServiceImpl implements TaxWritePlatformService { this.validator.validateStartDate(taxComponent.startDate(), command); Map changes = taxComponent.update(command); this.validator.validateTaxComponentForUpdate(taxComponent); - this.taxComponentRepository.save(taxComponent); + this.taxComponentRepository.saveAndFlush(taxComponent); return new CommandProcessingResultBuilder() // .withEntityId(id) // .with(changes).build(); @@ -85,7 +85,7 @@ public class TaxWritePlatformServiceImpl implements TaxWritePlatformService { this.validator.validateForTaxGroupCreate(command.json()); final TaxGroup taxGroup = this.taxAssembler.assembleTaxGroupFrom(command); this.validator.validateTaxGroup(taxGroup); - this.taxGroupRepository.save(taxGroup); + this.taxGroupRepository.saveAndFlush(taxGroup); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(taxGroup.getId()) // @@ -101,7 +101,7 @@ public class TaxWritePlatformServiceImpl implements TaxWritePlatformService { this.validator.validateTaxGroupEndDateAndTaxComponent(taxGroup, groupMappings); Map changes = taxGroup.update(command, groupMappings); this.validator.validateTaxGroup(taxGroup); - this.taxGroupRepository.save(taxGroup); + this.taxGroupRepository.saveAndFlush(taxGroup); return new CommandProcessingResultBuilder() // .withEntityId(id) // .with(changes).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java index f0636c77b..3cbf99d61 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java @@ -211,7 +211,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr /** map all JLG loans for this client to the destinationGroup **/ for (final CalendarInstance calendarInstance : activeLoanCalendarInstances) { calendarInstance.updateCalendar(destinationGroupCalendar); - this.calendarInstanceRepository.save(calendarInstance); + this.calendarInstanceRepository.saveAndFlush(calendarInstance); } // reschedule all JLG Loans to follow new Calendar this.loanWritePlatformService.applyMeetingDateChanges(destinationGroupCalendar, activeLoanCalendarInstances); @@ -282,7 +282,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr handleClientTransferLifecycleEvent(client, office, TransferEventType.PROPOSAL, jsonCommand); this.clientRepositoryWrapper.saveAndFlush(client); handleClientTransferLifecycleEvent(client, client.getTransferToOffice(), TransferEventType.ACCEPTANCE, jsonCommand); - this.clientRepositoryWrapper.save(client); + this.clientRepositoryWrapper.saveAndFlush(client); return new CommandProcessingResultBuilder() // .withClientId(clientId) // @@ -315,7 +315,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr } handleClientTransferLifecycleEvent(client, office, TransferEventType.PROPOSAL, jsonCommand); - this.clientRepositoryWrapper.save(client); + this.clientRepositoryWrapper.saveAndFlush(client); return new CommandProcessingResultBuilder() // .withClientId(clientId) // .withEntityId(clientId) // @@ -340,7 +340,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId, true); validateClientAwaitingTransferAcceptance(client); handleClientTransferLifecycleEvent(client, client.getTransferToOffice(), TransferEventType.ACCEPTANCE, jsonCommand); - this.clientRepositoryWrapper.save(client); + this.clientRepositoryWrapper.saveAndFlush(client); return new CommandProcessingResultBuilder() // .withClientId(clientId) // @@ -356,7 +356,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); validateClientAwaitingTransferAcceptanceOnHold(client); handleClientTransferLifecycleEvent(client, client.getOffice(), TransferEventType.WITHDRAWAL, jsonCommand); - this.clientRepositoryWrapper.save(client); + this.clientRepositoryWrapper.saveAndFlush(client); return new CommandProcessingResultBuilder() // .withClientId(clientId) // .withEntityId(clientId) // @@ -370,7 +370,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr this.transfersDataValidator.validateForRejectClientTransfer(jsonCommand.json()); final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); handleClientTransferLifecycleEvent(client, client.getOffice(), TransferEventType.REJECTION, jsonCommand); - this.clientRepositoryWrapper.save(client); + this.clientRepositoryWrapper.saveAndFlush(client); return new CommandProcessingResultBuilder() // .withClientId(clientId) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java b/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java index f789d6eb9..75353b75b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java @@ -26,6 +26,7 @@ import java.time.temporal.ChronoUnit; import java.util.Calendar; import java.util.Date; import java.util.List; +import javax.persistence.EntityExistsException; import javax.persistence.PersistenceException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.service.DateUtils; @@ -34,7 +35,6 @@ import org.apache.fineract.spm.domain.Survey; import org.apache.fineract.spm.domain.SurveyRepository; import org.apache.fineract.spm.domain.SurveyValidator; import org.apache.fineract.spm.exception.SurveyNotFoundException; -import org.apache.openjpa.persistence.EntityExistsException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.orm.jpa.JpaSystemException; @@ -126,7 +126,7 @@ public class SpmService { final ZonedDateTime dateTime = getStartOfToday().minus(1, ChronoUnit.MILLIS); survey.setValidTo(Date.from(dateTime.toInstant())); - this.surveyRepository.save(survey); + this.surveyRepository.saveAndFlush(survey); } public void activateSurvey(final Long id) { @@ -140,7 +140,7 @@ public class SpmService { survey.setValidFrom(Date.from(validFrom.atStartOfDay(ZoneId.systemDefault()).toInstant())); survey.setValidTo(cal.getTime()); - this.surveyRepository.save(survey); + this.surveyRepository.saveAndFlush(survey); } public static ZonedDateTime getStartOfToday() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUser.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUser.java index a88611a13..623c11c22 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUser.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUser.java @@ -119,8 +119,7 @@ public class AppUser extends AbstractPersistableCustom implements PlatformUser { @Column(name = "is_self_service_user", nullable = false) private boolean isSelfServiceUser; - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) - @JoinColumn(name = "appuser_id", referencedColumnName = "id", nullable = false) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "appUser") private Set appUserClientMappings = new HashSet<>(); @Column(name = "cannot_change_password", nullable = true) @@ -706,7 +705,7 @@ public class AppUser extends AbstractPersistableCustom implements PlatformUser { if (clients != null && clients.size() > 0) { newAppUserClientMappings = new HashSet<>(); for (Client client : clients) { - newAppUserClientMappings.add(new AppUserClientMapping(client)); + newAppUserClientMappings.add(new AppUserClientMapping(this, client)); } } return newAppUserClientMappings; diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUserClientMapping.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUserClientMapping.java index e6cd09eaf..29de36e6e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUserClientMapping.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/domain/AppUserClientMapping.java @@ -30,6 +30,10 @@ import org.apache.fineract.portfolio.client.domain.Client; @Table(name = "m_selfservice_user_client_mapping") public class AppUserClientMapping extends AbstractPersistableCustom { + @ManyToOne(optional = false, cascade = CascadeType.ALL) + @JoinColumn(name = "appuser_id", nullable = false) + private AppUser appUser; + @ManyToOne(optional = false, cascade = CascadeType.PERSIST) @JoinColumn(name = "client_id", nullable = false) private Client client; @@ -38,7 +42,8 @@ public class AppUserClientMapping extends AbstractPersistableCustom { } - public AppUserClientMapping(Client client) { + public AppUserClientMapping(AppUser appUser, Client client) { + this.appUser = appUser; this.client = client; } @@ -46,6 +51,10 @@ public class AppUserClientMapping extends AbstractPersistableCustom { return this.client; } + public AppUser getAppUser() { + return appUser; + } + @Override public boolean equals(Object obj) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionWritePlatformServiceJpaRepositoryImpl.java index 1d87f6dff..10552b830 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionWritePlatformServiceJpaRepositoryImpl.java @@ -77,7 +77,7 @@ public class PermissionWritePlatformServiceJpaRepositoryImpl implements Permissi final boolean changed = permission.enableMakerChecker(isSelected); if (changed) { changedPermissions.put(permissionCode, isSelected); - this.permissionRepository.save(permission); + this.permissionRepository.saveAndFlush(permission); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java index 9cf788393..a35bc5740 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java @@ -187,7 +187,7 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf if (!changedPermissions.isEmpty()) { changes.put("permissions", changedPermissions); - this.roleRepository.save(role); + this.roleRepository.saveAndFlush(role); } return new CommandProcessingResultBuilder() // @@ -265,7 +265,7 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf * Disabling the role */ role.disableRole(); - this.roleRepository.save(role); + this.roleRepository.saveAndFlush(role); return new CommandProcessingResultBuilder().withEntityId(roleId).build(); } catch (final JpaSystemException | DataIntegrityViolationException e) { @@ -288,7 +288,7 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf // if(!role.isEnabled()){throw new RoleNotFoundException(roleId);} role.enableRole(); - this.roleRepository.save(role); + this.roleRepository.saveAndFlush(role); return new CommandProcessingResultBuilder().withEntityId(roleId).build(); } catch (final JpaSystemException | DataIntegrityViolationException e) { diff --git a/fineract-provider/src/main/resources/META-INF/persistence.xml b/fineract-provider/src/main/resources/META-INF/persistence.xml index 214519c6d..105688157 100644 --- a/fineract-provider/src/main/resources/META-INF/persistence.xml +++ b/fineract-provider/src/main/resources/META-INF/persistence.xml @@ -25,13 +25,13 @@ xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> + + - org.apache.openjpa.persistence.PersistenceProviderImpl + org.eclipse.persistence.jpa.PersistenceProvider + false - - - - +