From d5c611564f7b8c877136f3b3aca647bf7de15fe0 Mon Sep 17 00:00:00 2001 From: Arnold Galovics Date: Thu, 3 Mar 2022 09:56:07 +0100 Subject: [PATCH] FINERACT-849: Switch to EclipseLink --- build.gradle | 12 +- config/spotbugs/exclude.xml | 9 + fineract-provider/build.gradle | 76 ++------- fineract-provider/dependencies.gradle | 5 +- ...tivityAccountWritePlatformServiceImpl.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../service/AccountingProcessorHelper.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- .../ProductToGLAccountMappingHelper.java | 16 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../SynchronousCommandProcessingService.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../service/BulkImportEventListener.java | 2 +- ...mpaignWritePlatformCommandHandlerImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...msCampaignWritePlatformServiceJpaImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 4 +- .../infrastructure/core/config/JPAConfig.java | 115 +++++++++++++ .../core/config/PersistenceConfig.java | 80 --------- .../domain/AbstractPersistableCustom.java | 14 +- ...SelectingPersistenceUnitPostProcessor.java | 49 ++++++ ...yScanningPersistenceUnitPostProcessor.java | 73 ++++++++ .../ExtendedJpaTransactionManager.java} | 39 ++++- .../domain/OrganisationCreditBureau.java | 2 + ...ConfigurationWritePlatformServiceImpl.java | 2 +- ...roductMappingWritePlatformServiceImpl.java | 2 +- .../CreditReportWritePlatformServiceImpl.java | 4 +- ...CreditBureauWritePlatflormServiceImpl.java | 2 +- ...tatableChecksWritePlatformServiceImpl.java | 1 + .../ReportWritePlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../FineractEntityAccessWriteServiceImpl.java | 2 +- ...eRegistrationWritePlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../openjpa/OpenJpaDialect.java | 159 ------------------ .../openjpa/OpenJpaVendorAdapter.java | 134 --------------- ...ortMailingJobWritePlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../service/InteropServiceImpl.java | 2 +- ...tionGeneratorWritePlatformServiceImpl.java | 2 +- ...icationMapperWritePlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../TellerWritePlatformServiceJpaImpl.java | 2 +- ...ngInstructionWritePlatformServiceImpl.java | 6 +- .../AddressWritePlatformServiceImpl.java | 4 +- .../portfolio/calendar/domain/Calendar.java | 5 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../domain/ClientChargeRepositoryWrapper.java | 4 +- .../ClientTransactionRepositoryWrapper.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...FamilyMembersWritePlatformServiceImpl.java | 6 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...CollateralManagementRepositoryWrapper.java | 2 +- ...ralManagementWritePlatformServiceImpl.java | 2 +- .../FloatingRateWritePlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 6 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../portfolio/loanaccount/domain/Loan.java | 23 ++- .../domain/LoanAccountDomainServiceJpa.java | 20 +-- .../loanaccount/domain/LoanCharge.java | 6 +- .../domain/LoanInstallmentCharge.java | 3 + ...nterestRecalcualtionAdditionalDetails.java | 14 ++ .../LoanRepaymentScheduleInstallment.java | 15 +- ...scheduleRequestToTermVariationMapping.java | 17 +- .../loanaccount/domain/LoanTransaction.java | 4 +- ...TransactionToRepaymentScheduleMapping.java | 26 ++- ...RepaymentScheduleTransactionProcessor.java | 8 +- ...RepaymentScheduleTransactionProcessor.java | 12 +- ...RepaymentScheduleTransactionProcessor.java | 8 +- ...RepaymentScheduleTransactionProcessor.java | 12 +- ...RepaymentScheduleTransactionProcessor.java | 8 +- ...RepaymentScheduleTransactionProcessor.java | 8 +- ...RepaymentScheduleTransactionProcessor.java | 24 +-- ...GuarantorFundingTransactionRepository.java | 2 +- .../service/GuarantorDomainServiceImpl.java | 8 +- ...ritePlatformServiceJpaRepositoryIImpl.java | 6 +- .../domain/AbstractLoanScheduleGenerator.java | 17 -- .../domain/LoanRescheduleRequest.java | 3 +- ...heduleRequestWritePlatformServiceImpl.java | 44 ++--- ...WritePlatformServiceJpaRepositoryImpl.java | 19 +-- ...WritePlatformServiceJpaRepositoryImpl.java | 33 ++-- .../loanproduct/domain/LoanProduct.java | 10 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- .../service/PaymentTypeWriteServiceImpl.java | 2 +- .../rate/service/RateWriteServiceImpl.java | 2 +- .../domain/RecurringDepositAccount.java | 2 + .../SavingsAccountDomainServiceJpa.java | 2 +- .../domain/SavingsAccountTransaction.java | 6 +- .../SavingsAccountTransactionTaxDetails.java | 15 +- ...WritePlatformServiceJpaRepositoryImpl.java | 1 + ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 4 +- ...ualMonitoringWritePlatformServiceImpl.java | 2 + ...WritePlatformServiceJpaRepositoryImpl.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- ...WritePlatformServiceJpaRepositoryImpl.java | 12 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...eficiariesTPTWritePlatformServiceImpl.java | 4 +- .../domain/ShareAccountDividendDetails.java | 14 +- .../ShareAccountSchedularServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- .../ShareProductDividendPayOutDetails.java | 4 +- .../ShareProductDividendAssembler.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 8 +- .../portfolio/tax/domain/TaxGroup.java | 5 +- .../tax/domain/TaxGroupMappings.java | 12 ++ .../service/TaxWritePlatformServiceImpl.java | 8 +- ...WritePlatformServiceJpaRepositoryImpl.java | 12 +- .../fineract/spm/service/SpmService.java | 6 +- .../useradministration/domain/AppUser.java | 5 +- .../domain/AppUserClientMapping.java | 11 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 6 +- .../main/resources/META-INF/persistence.xml | 10 +- 129 files changed, 717 insertions(+), 771 deletions(-) create mode 100644 config/spotbugs/exclude.xml create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/PersistenceConfig.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/DatabaseSelectingPersistenceUnitPostProcessor.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/persistence/EntityScanningPersistenceUnitPostProcessor.java rename fineract-provider/src/main/java/org/apache/fineract/infrastructure/{openjpa/OpenJpaTransactionManager.java => core/persistence/ExtendedJpaTransactionManager.java} (53%) delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaDialect.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/openjpa/OpenJpaVendorAdapter.java diff --git a/build.gradle b/build.gradle index d4e75b7e28..537d7d0859 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 0000000000..19a9dc04c2 --- /dev/null +++ b/config/spotbugs/exclude.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle index 4baaa31e0b..8966251aa9 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 - } - - 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) - } - } - } - - 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() +compileJava.doLast { + def mainSS = sourceSets.main + def source = mainSS.java.classesDirectory.get() + copy { + from "src/main/resources/" + into source } - - def resources = project.sourceSets.main.resources.srcDirs.collect { resource -> - resource.toURI().toURL() + 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 } - - 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 461be980c4..99f46690d2 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 528bf88021..4ac2d3a854 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 CommandProcessingResult createFinancialActivityAccountMapping(JsonCommand 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 CommandProcessingResult updateGLAccountActivityMapping(Long financialActi 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 37b46b73bf..a593ea3ef1 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 CommandProcessingResult createGLAccount(final JsonCommand command) { 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 03e524725e..0c1ce6762e 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 @@ private void createDebitJournalEntryForShares(final Office office, final String 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 @@ private void createCreditJournalEntryForShares(final Office office, final String 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 3649246b1d..f9be74ad6b 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 String revertProvisioningJournalEntries(final Date reversalTransactionDat 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 void revertShareAccountJournalEntries(final ArrayList transactionId 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 ca2c2f6d15..73267804e7 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 void saveProductToAccountMapping(final JsonElement element, final String 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 void mergeProductToAccountMappingChanges(final JsonElement element, final 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 void createOrmergeProductToAccountMappingChanges(final JsonElement elemen 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 void updateChargeToIncomeAccountMappings(final JsonCommand command, final allowedAccountTypes, newGLAccountId); } chargeToIncomeAccountMapping.setGlAccount(glAccount); - this.accountMappingRepository.save(chargeToIncomeAccountMapping); + this.accountMappingRepository.saveAndFlush(chargeToIncomeAccountMapping); } } // deleted payment type else { @@ -334,7 +334,7 @@ public void updatePaymentChannelToFundSourceMappings(final JsonCommand command, 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 @@ private void savePaymentChannelToFundSourceMapping(final Long productId, final L 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 @@ private void saveChargeToFundSourceMapping(final Long productId, final Long char } 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 ba226f1a34..94e4bc6570 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 @@ private void revertAndAddJournalEntries(ProvisioningEntryData existingEntryData, requestedEntry.setJournalEntryCreated(Boolean.TRUE); } - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); this.journalEntryWritePlatformService.createProvisioningJournalEntries(requestedEntry); } @@ -210,7 +210,7 @@ private ProvisioningEntry createProvsioningEntry(Date date, boolean addJournalEn .retrieveExistingProvisioningIdDateWithJournals(); revertAndAddJournalEntries(exisProvisioningEntryData, requestedEntry); } else { - this.provisioningEntryRepository.save(requestedEntry); + this.provisioningEntryRepository.saveAndFlush(requestedEntry); } return requestedEntry; } @@ -220,10 +220,10 @@ public CommandProcessingResult reCreateProvisioningEntries(Long provisioningEntr 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 d0a967ef0b..337b2c7aba 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 CommandProcessingResult createAdHocQuery(final JsonCommand command) { 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 cb01262fc3..90db86a824 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 CommandProcessingResult processAndLogCommand(final CommandWrapper wrapper 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 f458187289..4877739c78 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 CommandProcessingResult createAccountNumberFormat(JsonCommand command) { 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 326b763f76..0332a503f6 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 void onApplicationEvent(final BulkImportEvent event) { final Workbook workbook = event.getWorkbook(); final Count count = importHandler.process(workbook, event.getLocale(), event.getDateFormat()); importDocument.update(DateUtils.getLocalDateTimeOfTenant(), count.getSuccessCount(), count.getErrorCount()); - this.importRepository.save(importDocument); + this.importRepository.saveAndFlush(importDocument); final Set 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 313cf3524f..df542106e6 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 CommandProcessingResult create(JsonCommand command) { 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 64c7e38f76..0c412d718f 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 CommandProcessingResult create(final JsonCommand command) { // 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 a18298bb91..77f2096936 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 CommandProcessingResult create(JsonCommand command) { 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 20887d85b4..bbd83ba54c 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 CommandProcessingResult createCodeValue(final JsonCommand command) { 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 79d3f54646..4ddafacd44 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 CommandProcessingResult createCode(final JsonCommand command) { 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 CommandProcessingResult updateCode(final Long codeId, final JsonCommand c 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 0000000000..366b37b714 --- /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 071cbe5205..0000000000 --- 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 be134dcc09..b8e7efe8d5 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.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 @@ protected void setId(final Long id) { } @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 0000000000..ba343f13bc --- /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 0000000000..d42c41acef --- /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 ae9b83d407..c04d6321a8 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 b9ebda9d3e..a2d11369b1 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 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 923a0f5efe..f37a07de7c 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 CommandProcessingResult addCreditBureauConfiguration(Long creditBureauId, 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 4b4a20b7a1..2519d59c8e 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 CommandProcessingResult addCreditBureauLoanProductMapping(Long organisati 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 4ea67c2a3d..1cdd90e5e5 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 CommandProcessingResult getCreditReport(JsonCommand command) { 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 CommandProcessingResult saveCreditReport(Long creditBureauId, String nati } 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 a283744419..724b9310d0 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 CommandProcessingResult addOrganisationCreditBureau(Long creditBureauId, 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 519f190fd6..232675fb21 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 void runTheCheck(final Long entityId, final String entityName, final Long } + @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 35069bee00..80b10dacb6 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 CommandProcessingResult createReport(final JsonCommand command) { 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 e3065f03b2..b84ddf7144 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 Long createDocument(final DocumentCommand documentCommand, final InputStr 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 f6dcce03a1..e7807135d3 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 CommandProcessingResult createEntityToEntityMapping(Long relId, JsonComma 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 27b35cacee..704c6e0bd1 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.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 52296074b7..e4863a272a 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 CommandProcessingResult createHook(final JsonCommand command) { 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 44a95ad717..0000000000 --- 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 37b5c29c11..0000000000 --- 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 819d09c149..dc7725bafa 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 CommandProcessingResult createReportMailingJob(JsonCommand jsonCommand) { 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 8039d3f1fd..c2458c44be 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 CommandProcessingResult create(final JsonCommand command) { // 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 c2f698476b..55d7bab65d 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 InteropIdentifierAccountResponseData registerAccountIdentifier(@NotNull I 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 c78cbe7236..3cad192e0e 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 NotificationGeneratorWritePlatformServiceImpl(NotificationRepository noti @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 0cefb96ef4..e74dcc2762 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 NotificationMapperWritePlatformServiceImpl(NotificationMapperRepository n @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 d45f8af3de..8d1bcf407c 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 TopicSubscriberWritePlatformServiceJpaRepositoryImpl(TopicSubscriberRepos @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 153c08342b..73c0d656c6 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 TopicWritePlatformServiceJpaRepositoryImpl(TopicRepository topicRepositor @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 df4cb859b4..9e3021e8a2 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 CommandProcessingResult createHoliday(final JsonCommand command) { 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 cb964a9245..9954322595 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 CommandProcessingResult createOffice(final JsonCommand command) { 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 3db14f920f..e429a2558b 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 CommandProcessingResult createProvisioningCateogry(JsonCommand command) { 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 CommandProcessingResult updateProvisioningCategory(final Long categoryId, .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 62e43462b9..85f23b9226 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 CommandProcessingResult createProvisioningCriteria(JsonCommand command) { 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 e349a1cd87..b8583924a2 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 CommandProcessingResult createStaff(final JsonCommand command) { 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 259ee4bb98..4460258ca7 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 CommandProcessingResult createTeller(JsonCommand command) { 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 89c392f70d..255a144115 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 CommandProcessingResult create(final JsonCommand command) { 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 0715b0e5ba..b9d052b0d9 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 CommandProcessingResult addClientAddress(final Long clientId, final Long 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 CommandProcessingResult addNewClientAddress(final Client client, final Js } 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 855fe87270..8115ad6442 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.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 2a8052f1b4..cceee59b13 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 CommandProcessingResult createCalendar(final JsonCommand command) { 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 29fcdefdf7..ca76143b4f 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 CommandProcessingResult createCharge(final JsonCommand command) { } 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 3d1fd99bdb..1ff7752479 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 @@ 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 df5f76db1e..5e8aba44eb 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 @@ 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 bd54ef01da..6b36d9d373 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 CommandProcessingResult waiveCharge(Long clientId, Long clientChargeId) { // 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 c5d8f6c52f..6f1c305f47 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 CommandProcessingResult addFamilyMember(final long clientId, final JsonCo 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 CommandProcessingResult addClientFamilyMember(final Client client, final 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 CommandProcessingResult updateFamilyMember(Long familyMemberId, JsonComma // 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 5ab1f56ade..a5f42f9dbf 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 CommandProcessingResult addClientIdentifier(final Long clientId, final Js 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 acda53d9ed..b537c9fdb4 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 CommandProcessingResult createClient(final JsonCommand command) { 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 CommandProcessingResult createClient(final JsonCommand command) { 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 CommandProcessingResult createClient(final JsonCommand command) { 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 04817049f7..e58d6ed131 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 CommandProcessingResult addCollateral(final Long loanId, final JsonComman 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 e899ddd3ac..7089ca117f 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 CollateralManagementRepositoryWrapper(final CollateralManagementDomainRep } 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 8170bfa53f..b7067cceb7 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 CommandProcessingResult addClientCollateralProduct(final JsonCommand comm 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 7413c411e5..fabba549c9 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 CommandProcessingResult createFloatingRate(final JsonCommand command) { 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 323ca5dc96..6b8bff2d11 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 CommandProcessingResult createFund(final JsonCommand command) { 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 CommandProcessingResult updateFund(final Long fundId, final JsonCommand c * 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 956a5e8cfc..7fc544d99a 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 CommandProcessingResult createRole(final JsonCommand command) { 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 3c29453339..6f9cbc854d 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 @@ private CommandProcessingResult createGroupingType(final JsonCommand command, fi 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 a31d88cc89..da096ad57b 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 CommandProcessingResult create(JsonCommand command) { 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 2ccb667721..27813b1276 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.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 void updateLoanSchedule(final LoanScheduleModel modifiedLoanSchedule, App } 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 void updateLoanSchedule(final 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 List generateInstallmentLoanCharges(final LoanChar .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 230d5118b7..2a2aa6f687 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 LoanTransaction makeRepayment(final Loan loan, final CommandProcessingRes 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 @@ private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction 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 @@ private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { @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 LoanTransaction makeRefund(final Long accountId, final CommandProcessingR 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 LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessing 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 947e552e75..6943f44bb2 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 @@ private void updateInstallmentCharges() { 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 eb207c82b2..b690795de1 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 LoanRepaymentScheduleInstallment getInstallment() { 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 7786463bb8..a2b5f4d2cc 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.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 @@ @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 LocalDate getEffectiveDate() { 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 c47ea396a2..911abd484c 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 LoanRepaymentScheduleInstallment(final Loan loan, final Integer installme 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 LoanRepaymentScheduleInstallment(final Loan loan, final Integer installme 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 void setFeeChargesWaived(final BigDecimal newFeeChargesCharged) { 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 721b83f0c9..b4383811c6 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.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 @@ protected LoanRescheduleRequestToTermVariationMapping() { } - 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 953ed31f73..bc1970fac3 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 @@ private boolean updateMapingDetail(final Collection, 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 8b083d101e..95e49dae17 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 void assignGuarantor(final GuarantorFundingDetails guarantorFundingDetail GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null, onHoldTransaction); guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction); - this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction); + this.depositAccountOnHoldTransactionRepository.saveAndFlush(onHoldTransaction); } } @@ -206,8 +206,8 @@ public void releaseGuarantor(final GuarantorFundingDetails guarantorFundingDetai 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 @@ private void completeGuarantorFund(final LoanTransaction loanTransaction) { 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 0d7e451d17..cb71cb78f9 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 @@ private CommandProcessingResult createGuarantor(final Loan loan, final JsonComma } 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 CommandProcessingResult updateGuarantor(final Long loanId, final Long gua } 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 fd008cfb56..af149f7410 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 @@ private void handleRecalculationForNonDueDateTransactions(final MathContext mc, * @param currency * @param scheduleParams * @param lastRestDate - * @param periodStartDateApplicableForInterest * @param detail */ private void handleLatePayments(final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO, @@ -991,15 +990,10 @@ private void updateBalanceBasedOnDisbursement(final LoanApplicationTerms loanApp /** * @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 @@ private LoanTermVariationParams applyLoanTermVariations(final LoanApplicationTer * TODO * @param mc * TODO - * @param periodNumber * @return */ private LoanTermVariationParams applyExceptionLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, @@ -1222,7 +1215,6 @@ private LoanTermVariationParams applyExceptionLoanTermVariations(final LoanAppli * @param scheduleParams * @param interestRates * @param interestRatesForInstallments - * @param periodsApplicableForGrace */ private void applyLoanVariationsForPartialScheduleGenerate(final LoanApplicationTerms loanApplicationTerms, LoanScheduleParams scheduleParams, final Collection interestRates, @@ -1317,13 +1309,6 @@ private Money fetchCompoundedArrears(final LoanApplicationTerms loanApplicationT * 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 @@ private TreeMap mergeVariationsToMap(final LoanScheduleParams * * @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 ad27b786d1..32425bd407 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 1103cbbc91..92daeedcd3 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 CommandProcessingResult create(JsonCommand jsonCommand) { 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 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte 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 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte 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 815d84010a..fe97760878 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.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 CommandProcessingResult submitApplication(final JsonCommand command) { } } - this.loanRepositoryWrapper.save(newLoanApplication); + this.loanRepositoryWrapper.saveAndFlush(newLoanApplication); if (loanProduct.isInterestRecalculationEnabled()) { this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(newLoanApplication); @@ -487,7 +486,7 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { } } 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 CommandProcessingResult submitApplication(final JsonCommand command) { 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 CommandProcessingResult modifyApplication(final Long loanId, final JsonCo // 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 CommandProcessingResult rejectApplication(final Long loanId, final JsonCo 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 CommandProcessingResult applicantWithdrawsFromApplication(final Long loan } 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 @@ private void checkClientOrGroupActive(final Loan loan) { 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 30940fc0c3..83ccfadfe3 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 @@ private void updateRecurringCalendarDatesForInterestRecalculation(final Loan loa 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 @@ private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { 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 CommandProcessingResult adjustLoanTransaction(final Long loanId, final Lo if (paymentDetail != null) { this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); } - this.loanTransactionRepository.save(newTransactionDetail); + this.loanTransactionRepository.saveAndFlush(newTransactionDetail); } /*** @@ -1252,7 +1239,7 @@ public CommandProcessingResult waiveInterestOnLoan(final Long loanId, final Json 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 CommandProcessingResult writeOff(final Long loanId, final JsonCommand com 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 CommandProcessingResult closeLoan(final Long loanId, final JsonCommand co 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 @@ private boolean addCharge(final Loan loan, final Charge chargeDefinition, final 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 @@ private boolean addCharge(final Loan loan, final Charge chargeDefinition, final **/ 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 CommandProcessingResult waiveLoanCharge(final Long loanId, final Long loa 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 LoanTransaction initiateLoanTransfer(final Loan loan, final LocalDate tra 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 LoanTransaction acceptLoanTransfer(final Loan loan, final LocalDate trans loan.reassignLoanOfficer(loanOfficer, transferDate); } - this.loanTransactionRepository.save(newTransferAcceptanceTransaction); + this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction); saveLoanWithDataIntegrityViolationChecks(loan); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); @@ -2272,7 +2259,7 @@ public LoanTransaction withdrawLoanTransfer(final Loan loan, final LocalDate tra 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 c3c2fc5446..cb9f8f93be 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 LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy tran this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate; this.canUseForTopup = canUseForTopup; - this.isEqualAmortization = isEqualAmortization; this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment; if (rates != null) { @@ -1455,11 +1451,7 @@ public boolean canUseForTopup() { } 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 5a414fc61d..eb81e8b702 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 CommandProcessingResult createLoanProduct(final JsonCommand command) { 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 2732c533a7..5f9a1ba3c8 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 CommandProcessingResult createMeeting(final JsonCommand command) { 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 58ae150364..52cdca4444 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 @@ private CommandProcessingResult createClientNote(final JsonCommand command) { } 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 @@ private CommandProcessingResult createGroupNote(final JsonCommand command) { 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 @@ private CommandProcessingResult createLoanNote(final JsonCommand command) { 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 @@ private CommandProcessingResult createLoanTransactionNote(final JsonCommand comm 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 ae48b397ad..03955093d9 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 CommandProcessingResult createPaymentType(JsonCommand command) { 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 2e79540a58..5b67eea5e1 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 CommandProcessingResult createRate(JsonCommand command) { } 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 c861560383..90d078ae2b 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.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 6612b4e508..aee89bee8d 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 @@ private void updateExistingTransactionsDetails(SavingsAccount account, Set } 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 241253f3ab..014ca99679 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 static void updateTaxDetails(final Map taxDetai 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 1f6ce1e3dd..0697b1a3bc 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 @@ @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 void updateAmount(Money amount) { 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 3de6da11f1..75dafe97bd 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.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 8338aeae69..dd3459f76a 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 CommandProcessingResult submitFDApplication(final JsonCommand command) { 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 d8a91eca6e..97e9995c2a 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 CommandProcessingResult create(final JsonCommand command) { 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 CommandProcessingResult update(final Long productId, final JsonCommand co 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 29415d145e..a3bfd19c9f 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.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 83351a7683..ad0731b00d 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 CommandProcessingResult create(final JsonCommand command) { 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 CommandProcessingResult update(final Long productId, final JsonCommand co 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 93c83ef05a..9339f12739 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 CommandProcessingResult holdAmount(final Long savingsId, final JsonComman 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 CommandProcessingResult releaseAmount(final Long savingsId, final Long sa 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 CommandProcessingResult releaseAmount(final Long savingsId, final Long sa .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 CommandProcessingResult blockCredits(final Long savingsId) { .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 CommandProcessingResult unblockCredits(final Long savingsId) { .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 CommandProcessingResult blockDebits(final Long savingsId) { .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 3c0c3349b2..36824d8850 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 CommandProcessingResult submitApplication(final JsonCommand command) { 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 CommandProcessingResult submitApplication(final JsonCommand command) { 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 CommandProcessingResult submitApplication(final JsonCommand command) { 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 CommandProcessingResult submitApplication(final JsonCommand command) { 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 @@ private void generateAccountNumber(final SavingsAccount account) { 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 CommandProcessingResult createActiveApplication(final SavingsAccountDataD } 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 9f6d015a9f..1c5ea249e3 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 CommandProcessingResult create(final JsonCommand command) { 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 90ed9fe6d0..b023b4239e 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 CommandProcessingResult add(JsonCommand command) { 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 CommandProcessingResult update(JsonCommand command) { 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 5427010307..cbb7de6a8b 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 @@ 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 BigDecimal getAmount() { 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 82b905c478..c62dc7a1c1 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 void postDividend(final Long dividendDetailId, final Long savingsId) { 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 6060867843..8211791e29 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 ShareAccountWritePlatformServiceJpaRepositoryImpl(final ShareAccountDataS 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 CommandProcessingResult redeemShares(Long accountId, JsonCommand jsonComm 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 CommandProcessingResult redeemShares(Long accountId, JsonCommand jsonComm 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 CommandProcessingResult closeShareAccount(Long accountId, JsonCommand jso 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 692e628f35..dc87dfd73c 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.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 aea13bbded..74e548a9b7 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 ShareProductDividendPayOutDetails calculateDividends(final Long productId 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 f4c4d2b93c..d6d3511e94 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.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 @@ @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 ShareProductWritePlatformServiceJpaRepositoryImpl(final ShareProductRepos 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 CommandProcessingResult deleteShareProductDividend(final Long PayOutDetai } 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 @@ private void handleDataIntegrityIssues(final JsonCommand command, final Throwabl "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 5f170ac094..1df6b33206 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.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 @@ protected TaxGroup() { 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 84c008085d..608841c350 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 @@ @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 LocalDate endDate() { } 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 0288e0e144..6ccdcf5a1c 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 TaxWritePlatformServiceImpl(final TaxValidator validator, final TaxAssemb 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 CommandProcessingResult updateTaxComponent(final Long id, final JsonComma 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 CommandProcessingResult createTaxGroup(final JsonCommand command) { 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 CommandProcessingResult updateTaxGroup(final Long id, final JsonCommand c 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 f0636c77b2..3cbf99d615 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 void transferClientBetweenGroups(final Group sourceGroup, final Client cl /** 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 CommandProcessingResult proposeAndAcceptClientTransfer(final Long clientI 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 CommandProcessingResult proposeClientTransfer(final Long clientId, final } 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 CommandProcessingResult acceptClientTransfer(final Long clientId, final J 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 CommandProcessingResult withdrawClientTransfer(final Long clientId, final 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 CommandProcessingResult rejectClientTransfer(final Long clientId, final J 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 f789d6eb93..75353b75b7 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.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.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 void deactivateSurvey(final Long id) { 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 void activateSurvey(final Long id) { 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 a88611a134..623c11c22a 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 @@ private Set createAppUserClientMappings(Collection 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 e6cd09eaf6..29de36e6e2 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 @@ @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 AppUserClientMapping() { } - public AppUserClientMapping(Client client) { + public AppUserClientMapping(AppUser appUser, Client client) { + this.appUser = appUser; this.client = client; } @@ -46,6 +51,10 @@ public Client getClient() { 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 1d87f6dffb..10552b830b 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 CommandProcessingResult updateMakerCheckerPermissions(final JsonCommand c 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 9cf788393b..a35bc57400 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 CommandProcessingResult updateRolePermissions(final Long roleId, final Js if (!changedPermissions.isEmpty()) { changes.put("permissions", changedPermissions); - this.roleRepository.save(role); + this.roleRepository.saveAndFlush(role); } return new CommandProcessingResultBuilder() // @@ -265,7 +265,7 @@ public CommandProcessingResult disableRole(Long roleId) { * 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 CommandProcessingResult enableRole(Long roleId) { // 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 214519c6d8..105688157f 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 - - - - +