FINERACT-849: Switch to EclipseLink

This commit is contained in:
Arnold Galovics
2022-03-10 09:33:01 +01:00
committed by Aleksandar Vidakovic
parent 7f8148e166
commit d5c611564f
129 changed files with 717 additions and 771 deletions
+8 -4
View File
@@ -45,7 +45,8 @@ buildscript {
dependencies { dependencies {
classpath 'com.bmuschko:gradle-cargo-plugin:2.9.0' 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') 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 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. // 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.guava:guava:31.1-jre'
dependency 'com.google.code.gson:gson:2.9.0' dependency 'com.google.code.gson:gson:2.9.0'
dependency 'com.google.truth:truth:1.1.3' dependency 'com.google.truth:truth:1.1.3'
@@ -415,7 +416,9 @@ configure(project.fineractJavaProjects) {
"-Xlint:varargs", "-Xlint:varargs",
"-Xlint:preview", "-Xlint:preview",
"-Xlint:static", "-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", "-Xmaxwarns",
1500, 1500,
"-Xmaxerrs", "-Xmaxerrs",
@@ -477,7 +480,7 @@ configure(project.fineractJavaProjects) {
licenseMain.dependsOn compileJava licenseMain.dependsOn compileJava
processResources.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 // set the classes directory to point to Eclipse's default build directory
if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') { if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') {
sourceSets.main.java.outputDir = file("$projectDir/bin/main") sourceSets.main.java.outputDir = file("$projectDir/bin/main")
@@ -632,6 +635,7 @@ configure(project.fineractJavaProjects) {
spotbugs { spotbugs {
reportLevel = 'high' reportLevel = 'high'
showProgress = false showProgress = false
excludeFilter = file("$rootDir/config/spotbugs/exclude.xml")
} }
// https://github.com/spotbugs/spotbugs-gradle-plugin/issues/242 // https://github.com/spotbugs/spotbugs-gradle-plugin/issues/242
spotbugsMain { spotbugsMain {
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter
xmlns="https://github.com/spotbugs/filter/3.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
<Match>
<Package name="~.*\.domain"/>
</Match>
</FindBugsFilter>
+14 -62
View File
@@ -26,70 +26,21 @@ apply plugin: 'com.gorylenko.gradle-git-properties'
apply plugin: 'io.swagger.core.v3.swagger-gradle-plugin' apply plugin: 'io.swagger.core.v3.swagger-gradle-plugin'
apply plugin: 'com.google.cloud.tools.jib' apply plugin: 'com.google.cloud.tools.jib'
// Custom OpenJPA enhancement
compileJava.doLast { compileJava.doLast {
def enhanceIncludes = [ def mainSS = sourceSets.main
'**/AbstractPersistableCustom.class', def source = mainSS.java.classesDirectory.get()
'**/domain/*.class' copy {
] from "src/main/resources/"
into source
def classesToEnhance = project.sourceSets.main.output.classesDirs.collectMany { classesDir ->
project.fileTree(classesDir).matching {
enhanceIncludes.forEach { include it }
}.files
} }
javaexec {
String persistenceXml = "META-INF/persistence.xml" description = 'Performs EclipseLink static weaving of entity classes'
def persistenceXmlFile def target = source
main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
// Check if persistence.xml is in the resource dirs. args '-persistenceinfo', source, '-classpath', configurations.runtimeClasspath, source, target
project.sourceSets.main.resources.srcDirs.collect { resourceDir -> classpath configurations.runtimeClasspath
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()
}
def resources = project.sourceSets.main.resources.srcDirs.collect { resource ->
resource.toURI().toURL()
}
def urls = (classes + compileJars + resources)
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new URLClassLoader((URL[])urls, currentClassLoader));
org.apache.openjpa.enhance.PCEnhancer.run((String []) classesToEnhance, options);
Thread.currentThread().setContextClassLoader(currentClassLoader);
} }
// Configuration for Swagger documentation generation task // Configuration for Swagger documentation generation task
@@ -151,7 +102,8 @@ apply from: 'dependencies.gradle'
modernizer { modernizer {
ignoreClassNamePatterns = [ ignoreClassNamePatterns = [
'.*AbstractPersistableCustom', '.*AbstractPersistableCustom',
'.*EntityTables' '.*EntityTables',
'.*domain.*'
] ]
} }
+2 -3
View File
@@ -89,9 +89,8 @@ dependencies {
implementation ('org.springframework.boot:spring-boot-starter-data-jpa') { implementation ('org.springframework.boot:spring-boot-starter-data-jpa') {
exclude group: 'org.hibernate' exclude group: 'org.hibernate'
} }
implementation ('org.apache.openjpa:openjpa') { implementation('org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10') {
exclude group: 'org.eclipse.persistence' exclude group: 'org.eclipse.persistence', module: 'jakarta.persistence'
exclude group: 'org.apache.geronimo.specs'
} }
implementation ('org.quartz-scheduler:quartz') { implementation ('org.quartz-scheduler:quartz') {
exclude group: 'com.zaxxer', module: 'HikariCP-java7' exclude group: 'com.zaxxer', module: 'HikariCP-java7'
@@ -74,7 +74,7 @@ public class FinancialActivityAccountWritePlatformServiceImpl implements Financi
FinancialActivityAccount financialActivityAccount = FinancialActivityAccount.createNew(glAccount, financialActivityId); FinancialActivityAccount financialActivityAccount = FinancialActivityAccount.createNew(glAccount, financialActivityId);
validateFinancialActivityAndAccountMapping(financialActivityAccount); validateFinancialActivityAndAccountMapping(financialActivityAccount);
this.financialActivityAccountRepository.save(financialActivityAccount); this.financialActivityAccountRepository.saveAndFlush(financialActivityAccount);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
.withEntityId(financialActivityAccount.getId()) // .withEntityId(financialActivityAccount.getId()) //
@@ -122,7 +122,7 @@ public class FinancialActivityAccountWritePlatformServiceImpl implements Financi
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
validateFinancialActivityAndAccountMapping(financialActivityAccount); validateFinancialActivityAndAccountMapping(financialActivityAccount);
this.financialActivityAccountRepository.save(financialActivityAccount); this.financialActivityAccountRepository.saveAndFlush(financialActivityAccount);
} }
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -107,7 +107,7 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
glAccount.generateHierarchy(); glAccount.generateHierarchy();
this.glAccountRepository.save(glAccount); this.glAccountRepository.saveAndFlush(glAccount);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(glAccount.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(glAccount.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -1098,7 +1098,7 @@ public class AccountingProcessorHelper {
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId, final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId, manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId,
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId); 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, private void createCreditJournalEntryForShares(final Office office, final String currencyCode, final GLAccount account,
@@ -1117,7 +1117,7 @@ public class AccountingProcessorHelper {
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId, final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId, manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId,
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId); 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) { public GLAccount getLinkedGLAccountForLoanProduct(final Long loanProductId, final int accountMappingTypeId, final Long paymentTypeId) {
@@ -412,11 +412,11 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
journalEntry.getShareTransactionId()); journalEntry.getShareTransactionId());
} }
// save the reversal entry // save the reversal entry
this.glJournalEntryRepository.save(reversalJournalEntry); this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
journalEntry.setReversalJournalEntry(reversalJournalEntry); journalEntry.setReversalJournalEntry(reversalJournalEntry);
journalEntry.setReversed(true); journalEntry.setReversed(true);
// save the updated journal entry // save the updated journal entry
this.glJournalEntryRepository.save(journalEntry); this.glJournalEntryRepository.saveAndFlush(journalEntry);
} }
return reversalTransactionId; return reversalTransactionId;
@@ -580,11 +580,11 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
journalEntry.getShareTransactionId()); journalEntry.getShareTransactionId());
} }
// save the reversal entry // save the reversal entry
this.glJournalEntryRepository.save(reversalJournalEntry); this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
journalEntry.setReversalJournalEntry(reversalJournalEntry); journalEntry.setReversalJournalEntry(reversalJournalEntry);
journalEntry.setReversed(true); journalEntry.setReversed(true);
// save the updated journal entry // save the updated journal entry
this.glJournalEntryRepository.save(journalEntry); this.glJournalEntryRepository.saveAndFlush(journalEntry);
} }
} }
} }
@@ -78,7 +78,7 @@ public class ProductToGLAccountMappingHelper {
final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
portfolioProductType.getValue(), placeHolderTypeId); portfolioProductType.getValue(), placeHolderTypeId);
this.accountMappingRepository.save(accountMapping); this.accountMappingRepository.saveAndFlush(accountMapping);
} }
public void mergeProductToAccountMappingChanges(final JsonElement element, final String paramName, final Long productId, public void mergeProductToAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
@@ -97,7 +97,7 @@ public class ProductToGLAccountMappingHelper {
final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId); final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId);
changes.put(paramName, accountId); changes.put(paramName, accountId);
accountMapping.setGlAccount(glAccount); accountMapping.setGlAccount(glAccount);
this.accountMappingRepository.save(accountMapping); this.accountMappingRepository.saveAndFlush(accountMapping);
} }
} }
} }
@@ -116,12 +116,12 @@ public class ProductToGLAccountMappingHelper {
changes.put(paramName, accountId); changes.put(paramName, accountId);
ProductToGLAccountMapping newAccountMapping = new ProductToGLAccountMapping(glAccount, productId, ProductToGLAccountMapping newAccountMapping = new ProductToGLAccountMapping(glAccount, productId,
portfolioProductType.getValue(), accountTypeId); portfolioProductType.getValue(), accountTypeId);
this.accountMappingRepository.save(newAccountMapping); this.accountMappingRepository.saveAndFlush(newAccountMapping);
} else if (!accountMapping.getGlAccount().getId().equals(accountId)) { } else if (!accountMapping.getGlAccount().getId().equals(accountId)) {
final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId); final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId);
changes.put(paramName, accountId); changes.put(paramName, accountId);
accountMapping.setGlAccount(glAccount); accountMapping.setGlAccount(glAccount);
this.accountMappingRepository.save(accountMapping); this.accountMappingRepository.saveAndFlush(accountMapping);
} }
} }
} }
@@ -258,7 +258,7 @@ public class ProductToGLAccountMappingHelper {
allowedAccountTypes, newGLAccountId); allowedAccountTypes, newGLAccountId);
} }
chargeToIncomeAccountMapping.setGlAccount(glAccount); chargeToIncomeAccountMapping.setGlAccount(glAccount);
this.accountMappingRepository.save(chargeToIncomeAccountMapping); this.accountMappingRepository.saveAndFlush(chargeToIncomeAccountMapping);
} }
} // deleted payment type } // deleted payment type
else { else {
@@ -334,7 +334,7 @@ public class ProductToGLAccountMappingHelper {
if (!newGLAccountId.equals(existingPaymentChannelToFundSourceMapping.getGlAccount().getId())) { if (!newGLAccountId.equals(existingPaymentChannelToFundSourceMapping.getGlAccount().getId())) {
final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), newGLAccountId); final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), newGLAccountId);
existingPaymentChannelToFundSourceMapping.setGlAccount(glAccount); existingPaymentChannelToFundSourceMapping.setGlAccount(glAccount);
this.accountMappingRepository.save(existingPaymentChannelToFundSourceMapping); this.accountMappingRepository.saveAndFlush(existingPaymentChannelToFundSourceMapping);
} }
} // deleted payment type } // deleted payment type
else { else {
@@ -364,7 +364,7 @@ public class ProductToGLAccountMappingHelper {
final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), paymentTypeSpecificFundAccountId); final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), paymentTypeSpecificFundAccountId);
final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
portfolioProductType.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(), paymentType); portfolioProductType.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(), paymentType);
this.accountMappingRepository.save(accountMapping); this.accountMappingRepository.saveAndFlush(accountMapping);
} }
/** /**
@@ -395,7 +395,7 @@ public class ProductToGLAccountMappingHelper {
} }
final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId, final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
portfolioProductType.getValue(), placeHolderAccountType.getValue(), charge); portfolioProductType.getValue(), placeHolderAccountType.getValue(), charge);
this.accountMappingRepository.save(accountMapping); this.accountMappingRepository.saveAndFlush(accountMapping);
} }
private List<GLAccountType> getAllowedAccountTypesForFeeMapping() { private List<GLAccountType> getAllowedAccountTypesForFeeMapping() {
@@ -128,7 +128,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
requestedEntry.setJournalEntryCreated(Boolean.TRUE); requestedEntry.setJournalEntryCreated(Boolean.TRUE);
} }
this.provisioningEntryRepository.save(requestedEntry); this.provisioningEntryRepository.saveAndFlush(requestedEntry);
this.journalEntryWritePlatformService.createProvisioningJournalEntries(requestedEntry); this.journalEntryWritePlatformService.createProvisioningJournalEntries(requestedEntry);
} }
@@ -210,7 +210,7 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
.retrieveExistingProvisioningIdDateWithJournals(); .retrieveExistingProvisioningIdDateWithJournals();
revertAndAddJournalEntries(exisProvisioningEntryData, requestedEntry); revertAndAddJournalEntries(exisProvisioningEntryData, requestedEntry);
} else { } else {
this.provisioningEntryRepository.save(requestedEntry); this.provisioningEntryRepository.saveAndFlush(requestedEntry);
} }
return requestedEntry; return requestedEntry;
} }
@@ -220,10 +220,10 @@ public class ProvisioningEntriesWritePlatformServiceJpaRepositoryImpl implements
ProvisioningEntry requestedEntry = this.provisioningEntryRepository.findById(provisioningEntryId) ProvisioningEntry requestedEntry = this.provisioningEntryRepository.findById(provisioningEntryId)
.orElseThrow(() -> new ProvisioningEntryNotfoundException(provisioningEntryId)); .orElseThrow(() -> new ProvisioningEntryNotfoundException(provisioningEntryId));
requestedEntry.getLoanProductProvisioningEntries().clear(); requestedEntry.getLoanProductProvisioningEntries().clear();
this.provisioningEntryRepository.save(requestedEntry); this.provisioningEntryRepository.saveAndFlush(requestedEntry);
Collection<LoanProductProvisioningEntry> entries = generateLoanProvisioningEntry(requestedEntry, requestedEntry.getCreatedDate()); Collection<LoanProductProvisioningEntry> entries = generateLoanProvisioningEntry(requestedEntry, requestedEntry.getCreatedDate());
requestedEntry.setProvisioningEntries(entries); requestedEntry.setProvisioningEntries(entries);
this.provisioningEntryRepository.save(requestedEntry); this.provisioningEntryRepository.saveAndFlush(requestedEntry);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(requestedEntry.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(requestedEntry.getId()).build();
} }
@@ -63,7 +63,7 @@ public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePla
this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json()); this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json());
final AdHoc entity = AdHoc.fromJson(command); final AdHoc entity = AdHoc.fromJson(command);
this.adHocRepository.save(entity); this.adHocRepository.saveAndFlush(entity);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -152,7 +152,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
public CommandProcessingResult logCommand(CommandSource commandSourceResult) { public CommandProcessingResult logCommand(CommandSource commandSourceResult) {
commandSourceResult.markAsAwaitingApproval(); commandSourceResult.markAsAwaitingApproval();
commandSourceResult = this.commandSourceRepository.save(commandSourceResult); commandSourceResult = this.commandSourceRepository.saveAndFlush(commandSourceResult);
return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId()) return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId())
.withEntityId(commandSourceResult.getResourceId()).build(); .withEntityId(commandSourceResult.getResourceId()).build();
@@ -72,7 +72,7 @@ public class AccountNumberFormatWritePlatformServiceJpaRepositoryImpl implements
AccountNumberFormat accountNumberFormat = new AccountNumberFormat(entityAccountType, accountNumberPrefixType, prefixCharacter); AccountNumberFormat accountNumberFormat = new AccountNumberFormat(entityAccountType, accountNumberPrefixType, prefixCharacter);
this.accountNumberFormatRepository.save(accountNumberFormat); this.accountNumberFormatRepository.saveAndFlush(accountNumberFormat);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(accountNumberFormat.getId()) // .withEntityId(accountNumberFormat.getId()) //
@@ -140,7 +140,7 @@ public class BulkImportEventListener implements ApplicationListener<BulkImportEv
final Workbook workbook = event.getWorkbook(); final Workbook workbook = event.getWorkbook();
final Count count = importHandler.process(workbook, event.getLocale(), event.getDateFormat()); final Count count = importHandler.process(workbook, event.getLocale(), event.getDateFormat());
importDocument.update(DateUtils.getLocalDateTimeOfTenant(), count.getSuccessCount(), count.getErrorCount()); importDocument.update(DateUtils.getLocalDateTimeOfTenant(), count.getSuccessCount(), count.getErrorCount());
this.importRepository.save(importDocument); this.importRepository.saveAndFlush(importDocument);
final Set<String> modifiedParams = new HashSet<>(); final Set<String> modifiedParams = new HashSet<>();
modifiedParams.add("fileName"); modifiedParams.add("fileName");
@@ -177,7 +177,7 @@ public class EmailCampaignWritePlatformCommandHandlerImpl implements EmailCampai
emailCampaign.setStretchyReportParamMap(new Gson().toJson(stretchyReportParams)); emailCampaign.setStretchyReportParamMap(new Gson().toJson(stretchyReportParams));
} }
this.emailCampaignRepository.save(emailCampaign); this.emailCampaignRepository.saveAndFlush(emailCampaign);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -67,7 +67,7 @@ public class EmailWritePlatformServiceJpaRepositoryImpl implements EmailWritePla
// TODO: decision to be made on wheter we 'wait' for response or use // TODO: decision to be made on wheter we 'wait' for response or use
// 'future/promise' to capture response and update the EmailMessage // 'future/promise' to capture response and update the EmailMessage
// table // table
this.repository.save(message); this.repository.saveAndFlush(message);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -150,7 +150,7 @@ public class SmsCampaignWritePlatformServiceJpaImpl implements SmsCampaignWriteP
throw new GeneralPlatformDomainRuleException("error.msg.campaign.recurrenceStartDate.in.the.past", throw new GeneralPlatformDomainRuleException("error.msg.campaign.recurrenceStartDate.in.the.past",
"Recurrence start date cannot be the past date.", smsCampaign.getRecurrenceStartDate()); "Recurrence start date cannot be the past date.", smsCampaign.getRecurrenceStartDate());
} }
this.smsCampaignRepository.save(smsCampaign); this.smsCampaignRepository.saveAndFlush(smsCampaign);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -76,7 +76,7 @@ public class CodeValueWritePlatformServiceJpaRepositoryImpl implements CodeValue
final Long codeId = command.entityId(); final Long codeId = command.entityId();
final Code code = this.codeRepository.findById(codeId).orElseThrow(() -> new CodeNotFoundException(codeId)); final Code code = this.codeRepository.findById(codeId).orElseThrow(() -> new CodeNotFoundException(codeId));
final CodeValue codeValue = CodeValue.fromJson(code, command); final CodeValue codeValue = CodeValue.fromJson(code, command);
this.codeValueRepository.save(codeValue); this.codeValueRepository.saveAndFlush(codeValue);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -68,7 +68,7 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
final Code code = Code.fromJson(command); final Code code = Code.fromJson(command);
this.codeRepository.save(code); this.codeRepository.saveAndFlush(code);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(code.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(code.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -95,7 +95,7 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf
final Map<String, Object> changes = code.update(command); final Map<String, Object> changes = code.update(command);
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
this.codeRepository.save(code); this.codeRepository.saveAndFlush(code);
} }
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
@@ -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> jtaTransactionManager,
DatabaseTypeResolver databaseTypeResolver) {
super(dataSource, properties, jtaTransactionManager);
this.databaseTypeResolver = databaseTypeResolver;
}
@Override
@Bean
@Primary
@DependsOn("tenantDatabaseUpgradeService")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
Map<String, Object> 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> persistenceUnitManager,
ObjectProvider<EntityManagerFactoryBuilderCustomizer> 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<String, Object> getVendorProperties() {
return Map.of(PersistenceUnitProperties.WEAVING, "static", PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "true",
PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
}
@Bean
public AuditorAware<AppUser> auditorAware() {
return new AuditorAwareImpl();
}
@Override
@Bean
public PlatformTransactionManager transactionManager(ObjectProvider<TransactionManagerCustomizers> 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;
}
}
@@ -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<AppUser> auditorAware() {
return new AuditorAwareImpl();
}
}
@@ -23,6 +23,8 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.springframework.data.domain.Persistable; import org.springframework.data.domain.Persistable;
@@ -45,6 +47,9 @@ public abstract class AbstractPersistableCustom implements Persistable<Long>, Se
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Transient
private boolean isNew = true;
@Override @Override
public Long getId() { public Long getId() {
return id; return id;
@@ -55,8 +60,13 @@ public abstract class AbstractPersistableCustom implements Persistable<Long>, Se
} }
@Override @Override
@Transient // DATAJPA-622
public boolean isNew() { public boolean isNew() {
return null == this.id; return isNew;
}
@PrePersist
@PostLoad
void markNotNew() {
this.isNew = false;
} }
} }
@@ -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<DatabaseType, String> 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);
}
}
@@ -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<String> packages;
private final Set<Class<?>> 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<String> packages) {
this.packages = packages;
}
}
@@ -16,27 +16,52 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.openjpa; package org.apache.fineract.infrastructure.core.persistence;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport; import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionStatus; import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager; 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 @Override
protected void doCommit(DefaultTransactionStatus status) { protected void doCommit(DefaultTransactionStatus status) {
JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) status.getTransaction(); if (isReadOnlyTx(status.getTransaction())) {
if (txObject.isReadOnly()) { EntityManager entityManager = getCurrentEntityManager();
EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(obtainEntityManagerFactory()); if (entityManager != null) {
if (holder != null) {
EntityManager entityManager = holder.getEntityManager();
entityManager.clear(); entityManager.clear();
} }
} }
super.doCommit(status); 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;
}
} }
@@ -23,6 +23,7 @@ import java.util.List;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
@@ -36,6 +37,7 @@ public class OrganisationCreditBureau extends AbstractPersistableCustom {
private String alias; private String alias;
@OneToOne @OneToOne
@JoinColumn(name = "creditbureau_id", nullable = false)
private CreditBureau creditbureau; private CreditBureau creditbureau;
@Column(name = "is_active") @Column(name = "is_active")
@@ -69,7 +69,7 @@ public class CreditBureauConfigurationWritePlatformServiceImpl implements Credit
final CreditBureauConfiguration cb_config = CreditBureauConfiguration.fromJson(command, orgcb); 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(cb_config.getId()).build();
@@ -74,7 +74,7 @@ public class CreditBureauLoanProductMappingWritePlatformServiceImpl implements C
final CreditBureauLoanProductMapping cb_lp = CreditBureauLoanProductMapping.fromJson(command, orgcb, lp); 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(cb_lp.getId()).build();
@@ -110,7 +110,7 @@ public class CreditReportWritePlatformServiceImpl implements CreditReportWritePl
throw new PlatformApiDataValidationException("creditBureau.has.not.been.Integrated", "creditBureau.has.not.been.Integrated", throw new PlatformApiDataValidationException("creditBureau.has.not.been.Integrated", "creditBureau.has.not.been.Integrated",
dataValidationErrors); dataValidationErrors);
} catch (final DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
return CommandProcessingResult.empty(); return CommandProcessingResult.empty();
} catch (final PersistenceException ee) { } catch (final PersistenceException ee) {
@@ -189,7 +189,7 @@ public class CreditReportWritePlatformServiceImpl implements CreditReportWritePl
} }
return new CommandProcessingResultBuilder().withEntityId(creditReport.getId()).build(); return new CommandProcessingResultBuilder().withEntityId(creditReport.getId()).build();
} catch (final DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
return CommandProcessingResult.empty(); return CommandProcessingResult.empty();
} catch (final PersistenceException ee) { } catch (final PersistenceException ee) {
@@ -62,7 +62,7 @@ public class OrganisationCreditBureauWritePlatflormServiceImpl implements Organi
final OrganisationCreditBureau organisationCreditBureau = OrganisationCreditBureau.fromJson(command, creditBureau); final OrganisationCreditBureau organisationCreditBureau = OrganisationCreditBureau.fromJson(command, creditBureau);
this.organisationCreditBureauRepository.save(organisationCreditBureau); this.organisationCreditBureauRepository.saveAndFlush(organisationCreditBureau);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(organisationCreditBureau.getId()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(organisationCreditBureau.getId())
.build(); .build();
@@ -182,6 +182,7 @@ public class EntityDatatableChecksWritePlatformServiceImpl implements EntityData
} }
@Transactional(readOnly = true)
@Override @Override
public void runTheCheckForProduct(final Long entityId, final String entityName, final Long statusCode, String foreignKeyColumn, public void runTheCheckForProduct(final Long entityId, final String entityName, final Long statusCode, String foreignKeyColumn,
long productId) { long productId) {
@@ -92,7 +92,7 @@ public class ReportWritePlatformServiceImpl implements ReportWritePlatformServic
final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command); final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command);
report.update(reportParameterUsages); report.update(reportParameterUsages);
this.reportRepository.save(report); this.reportRepository.saveAndFlush(report);
final Permission permission = new Permission("report", report.getReportName(), "READ"); final Permission permission = new Permission("report", report.getReportName(), "READ");
this.permissionRepository.save(permission); this.permissionRepository.save(permission);
@@ -77,7 +77,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr
documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(), documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(),
documentCommand.getDescription(), fileLocation, contentRepository.getStorageType()); documentCommand.getDescription(), fileLocation, contentRepository.getStorageType());
this.documentRepository.save(document); this.documentRepository.saveAndFlush(document);
return document.getId(); return document.getId();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -107,7 +107,7 @@ public class FineractEntityAccessWriteServiceImpl implements FineractEntityAcces
final FineractEntityToEntityMapping newMap = FineractEntityToEntityMapping.newMap(mapId, fromId, toId, startDate, endDate); 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(); return new CommandProcessingResultBuilder().withEntityId(newMap.getId()).withCommandId(command.commandId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.gcm.service; package org.apache.fineract.infrastructure.gcm.service;
import java.util.Date; import java.util.Date;
import javax.persistence.EntityExistsException;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
@@ -28,7 +29,6 @@ import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationRepositor
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.openjpa.persistence.EntityExistsException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException; import org.springframework.orm.jpa.JpaSystemException;
@@ -119,7 +119,7 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements HookWritePlatf
validateHookRules(template, config, allEvents); validateHookRules(template, config, allEvents);
this.hookRepository.save(hook); this.hookRepository.saveAndFlush(hook);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(hook.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(hook.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -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);
}
}
}
@@ -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.
*
* <p>
* 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<String, Object> getJpaPropertyMap() {
Map<String, Object> jpaProperties = new HashMap<String, Object>();
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<? extends EntityManagerFactory> getEntityManagerFactoryInterface() {
return OpenJPAEntityManagerFactorySPI.class;
}
@Override
public Class<? extends EntityManager> getEntityManagerInterface() {
return OpenJPAEntityManagerSPI.class;
}
}
@@ -124,7 +124,7 @@ public class ReportMailingJobWritePlatformServiceImpl implements ReportMailingJo
final ReportMailingJob reportMailingJob = ReportMailingJob.newInstance(jsonCommand, stretchyReport, appUser); final ReportMailingJob reportMailingJob = ReportMailingJob.newInstance(jsonCommand, stretchyReport, appUser);
// save entity // save entity
this.reportMailingJobRepository.save(reportMailingJob); this.reportMailingJobRepository.saveAndFlush(reportMailingJob);
return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(reportMailingJob.getId()) return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(reportMailingJob.getId())
.build(); .build();
@@ -67,7 +67,7 @@ public class SmsWritePlatformServiceJpaRepositoryImpl implements SmsWritePlatfor
// TODO: decision to be made on wheter we 'wait' for response or use // TODO: decision to be made on wheter we 'wait' for response or use
// 'future/promise' to capture response and update the SmsMessage // 'future/promise' to capture response and update the SmsMessage
// table // table
this.repository.save(message); this.repository.saveAndFlush(message);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -288,7 +288,7 @@ public class InteropServiceImpl implements InteropService {
InteropIdentifier identifier = new InteropIdentifier(savingsAccount, request.getIdType(), request.getIdValue(), InteropIdentifier identifier = new InteropIdentifier(savingsAccount, request.getIdType(), request.getIdValue(),
request.getSubIdOrType(), createdBy.getUsername(), DateUtils.getDateOfTenant()); request.getSubIdOrType(), createdBy.getUsername(), DateUtils.getDateOfTenant());
identifierRepository.save(identifier); identifierRepository.saveAndFlush(identifier);
return InteropIdentifierAccountResponseData.build(identifier.getId(), savingsAccount.getExternalId()); return InteropIdentifierAccountResponseData.build(identifier.getId(), savingsAccount.getExternalId());
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -35,7 +35,7 @@ public class NotificationGeneratorWritePlatformServiceImpl implements Notificati
@Override @Override
public Long create(Notification notification) { public Long create(Notification notification) {
this.notificationRepository.save(notification); this.notificationRepository.saveAndFlush(notification);
return notification.getId(); return notification.getId();
} }
} }
@@ -35,7 +35,7 @@ public class NotificationMapperWritePlatformServiceImpl implements NotificationM
@Override @Override
public Long create(NotificationMapper notificationMapper) { public Long create(NotificationMapper notificationMapper) {
this.notificationMapperRepository.save(notificationMapper); this.notificationMapperRepository.saveAndFlush(notificationMapper);
return notificationMapper.getId(); return notificationMapper.getId();
} }
} }
@@ -35,7 +35,7 @@ public class TopicSubscriberWritePlatformServiceJpaRepositoryImpl implements Top
@Override @Override
public Long create(TopicSubscriber topicSubscriber) { public Long create(TopicSubscriber topicSubscriber) {
topicSubscriberRepository.save(topicSubscriber); topicSubscriberRepository.saveAndFlush(topicSubscriber);
return topicSubscriber.getId(); return topicSubscriber.getId();
} }
@@ -35,7 +35,7 @@ public class TopicWritePlatformServiceJpaRepositoryImpl implements TopicWritePla
@Override @Override
public Long create(Topic topic) { public Long create(Topic topic) {
topicRepository.save(topic); topicRepository.saveAndFlush(topic);
return topic.getId(); return topic.getId();
} }
@@ -91,7 +91,7 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
final Holiday holiday = Holiday.createNew(offices, 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(holiday.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -98,7 +98,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
final Office office = Office.fromJson(parent, command); final Office office = Office.fromJson(parent, command);
// pre save to generate id for use in office hierarchy // pre save to generate id for use in office hierarchy
this.officeRepositoryWrapper.save(office); this.officeRepositoryWrapper.saveAndFlush(office);
office.generateHierarchy(); office.generateHierarchy();
@@ -63,7 +63,7 @@ public class ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl implement
try { try {
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
final ProvisioningCategory provisioningCategory = ProvisioningCategory.fromJson(command); final ProvisioningCategory provisioningCategory = ProvisioningCategory.fromJson(command);
this.provisioningCategoryRepository.save(provisioningCategory); this.provisioningCategoryRepository.saveAndFlush(provisioningCategory);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCategory.getId()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCategory.getId())
.build(); .build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -98,7 +98,7 @@ public class ProvisioningCategoryWritePlatformServiceJpaRepositoryImpl implement
.orElseThrow(() -> new ProvisioningCategoryNotFoundException(categoryId)); .orElseThrow(() -> new ProvisioningCategoryNotFoundException(categoryId));
final Map<String, Object> changes = provisioningCategoryForUpdate.update(command); final Map<String, Object> changes = provisioningCategoryForUpdate.update(command);
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
this.provisioningCategoryRepository.save(provisioningCategoryForUpdate); this.provisioningCategoryRepository.saveAndFlush(provisioningCategoryForUpdate);
} }
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(categoryId).with(changes).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(categoryId).with(changes).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -83,7 +83,7 @@ public class ProvisioningCriteriaWritePlatformServiceJpaRepositoryImpl implement
try { try {
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
ProvisioningCriteria provisioningCriteria = provisioningCriteriaAssembler.fromParsedJson(command.parsedJson()); ProvisioningCriteria provisioningCriteria = provisioningCriteriaAssembler.fromParsedJson(command.parsedJson());
this.provisioningCriteriaRepository.save(provisioningCriteria); this.provisioningCriteriaRepository.saveAndFlush(provisioningCriteria);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCriteria.getId()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(provisioningCriteria.getId())
.build(); .build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -69,7 +69,7 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements StaffWritePla
final Office staffOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); final Office staffOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId);
final Staff staff = Staff.fromJson(staffOffice, command); final Staff staff = Staff.fromJson(staffOffice, command);
this.staffRepository.save(staff); this.staffRepository.saveAndFlush(staff);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -113,7 +113,7 @@ public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformSer
final Teller teller = Teller.fromJson(tellerOffice, command); final Teller teller = Teller.fromJson(tellerOffice, command);
// pre save to generate id for use in office hierarchy // pre save to generate id for use in office hierarchy
this.tellerRepositoryWrapper.save(teller); this.tellerRepositoryWrapper.saveAndFlush(teller);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -125,16 +125,16 @@ public class StandingInstructionWritePlatformServiceImpl implements StandingInst
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) { if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler final AccountTransferDetails standingInstruction = this.standingInstructionAssembler
.assembleSavingsToSavingsTransfer(command); .assembleSavingsToSavingsTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction); this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) { } else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command); final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction); this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) { } else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command); final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction); this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId(); standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
} }
@@ -100,7 +100,7 @@ public class AddressWritePlatformServiceImpl implements AddressWritePlatformServ
final boolean isActive = command.booleanPrimitiveValueOfParameterNamed("isActive"); final boolean isActive = command.booleanPrimitiveValueOfParameterNamed("isActive");
final ClientAddress clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientAddressobj.getId()).build();
} }
@@ -152,7 +152,7 @@ public class AddressWritePlatformServiceImpl implements AddressWritePlatformServ
} }
clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj);
this.clientAddressRepository.save(clientAddressobj); this.clientAddressRepository.saveAndFlush(clientAddressobj);
} }
} }
@@ -31,10 +31,10 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
@@ -98,8 +98,7 @@ public class Calendar extends AbstractAuditableCustom {
@Temporal(TemporalType.TIME) @Temporal(TemporalType.TIME)
private Date meetingtime; private Date meetingtime;
@OneToMany(fetch = FetchType.EAGER) @OneToMany(mappedBy = "calendar", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "calendar_id")
private Set<CalendarHistory> calendarHistory = new HashSet<>(); private Set<CalendarHistory> calendarHistory = new HashSet<>();
protected Calendar() { protected Calendar() {
@@ -153,7 +153,7 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
throw new PlatformApiDataValidationException(dataValidationErrors); throw new PlatformApiDataValidationException(dataValidationErrors);
} }
this.calendarRepository.save(newCalendar); this.calendarRepository.saveAndFlush(newCalendar);
final CalendarInstance newCalendarInstance = CalendarInstance.from(newCalendar, entityId, entityTypeId); final CalendarInstance newCalendarInstance = CalendarInstance.from(newCalendar, entityId, entityTypeId);
this.calendarInstanceRepository.save(newCalendarInstance); this.calendarInstanceRepository.save(newCalendarInstance);
@@ -122,7 +122,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
} }
final Charge charge = Charge.fromJson(command, glAccount, taxGroup, paymentType); 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 // check if the office specific products are enabled. If yes, then
// save this savings product against a specific office // save this savings product against a specific office
@@ -21,9 +21,9 @@ package org.apache.fineract.portfolio.client.domain;
import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper;
import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException; import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;
@Repository @Service
public class ClientChargeRepositoryWrapper { public class ClientChargeRepositoryWrapper {
private final ClientChargeRepository repository; private final ClientChargeRepository repository;
@@ -21,9 +21,9 @@ package org.apache.fineract.portfolio.client.domain;
import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.apache.fineract.organisation.office.domain.OrganisationCurrencyRepositoryWrapper;
import org.apache.fineract.portfolio.client.exception.ClientTransactionNotFoundException; import org.apache.fineract.portfolio.client.exception.ClientTransactionNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;
@Repository @Service
public class ClientTransactionRepositoryWrapper { public class ClientTransactionRepositoryWrapper {
private final ClientTransactionRepository repository; private final ClientTransactionRepository repository;
@@ -218,7 +218,7 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
// create Waiver Transaction // create Waiver Transaction
ClientTransaction clientTransaction = ClientTransaction.waiver(client, client.getOffice(), transactionDate, waivedAmount, ClientTransaction clientTransaction = ClientTransaction.waiver(client, client.getOffice(), transactionDate, waivedAmount,
clientCharge.getCurrency().getCode(), getAppUserIfPresent()); clientCharge.getCurrency().getCode(), getAppUserIfPresent());
this.clientTransactionRepository.save(clientTransaction); this.clientTransactionRepository.saveAndFlush(clientTransaction);
// update charge paid by associations // update charge paid by associations
final ClientChargePaidBy chargePaidBy = ClientChargePaidBy.instance(clientTransaction, clientCharge, waivedAmount.getAmount()); final ClientChargePaidBy chargePaidBy = ClientChargePaidBy.instance(clientTransaction, clientCharge, waivedAmount.getAmount());
@@ -145,7 +145,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily
ClientFamilyMembers clientFamilyMembers = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, ClientFamilyMembers clientFamilyMembers = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification,
mobileNumber, age, isDependent, relationship, maritalStatus, gender, dateOfBirth, profession); 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientFamilyMembers.getId()).build();
@@ -257,7 +257,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily
familyMember = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, mobileNumber, age, familyMember = ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, mobileNumber, age,
isDependent, relationship, maritalStatus, gender, dateOfBirth, profession); isDependent, relationship, maritalStatus, gender, dateOfBirth, profession);
this.clientFamilyRepository.save(familyMember); this.clientFamilyRepository.saveAndFlush(familyMember);
} }
@@ -370,7 +370,7 @@ public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamily
// middleName, lastName, qualification, relationship, maritalStatus, // middleName, lastName, qualification, relationship, maritalStatus,
// gender, dateOfBirth, profession); // gender, dateOfBirth, profession);
this.clientFamilyRepository.save(clientFamilyMember); this.clientFamilyRepository.saveAndFlush(clientFamilyMember);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientFamilyMember.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(clientFamilyMember.getId()).build();
} }
@@ -90,7 +90,7 @@ public class ClientIdentifierWritePlatformServiceJpaRepositoryImpl implements Cl
final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command); final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command);
this.clientIdentifierRepository.save(clientIdentifier); this.clientIdentifierRepository.saveAndFlush(clientIdentifier);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -294,7 +294,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender, final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender,
clientType, clientClassification, legalFormValue, command); clientType, clientClassification, legalFormValue, command);
this.clientRepository.save(newClient); this.clientRepository.saveAndFlush(newClient);
boolean rollbackTransaction = false; boolean rollbackTransaction = false;
if (newClient.isActive()) { if (newClient.isActive()) {
validateParentGroupRulesBeforeClientActivation(newClient); validateParentGroupRulesBeforeClientActivation(newClient);
@@ -303,7 +303,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
} }
this.clientRepository.save(newClient); this.clientRepository.saveAndFlush(newClient);
if (newClient.isActive()) { if (newClient.isActive()) {
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEvents.CLIENTS_ACTIVATE, this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEvents.CLIENTS_ACTIVATE,
constructEntityMap(BusinessEntity.CLIENT, newClient)); constructEntityMap(BusinessEntity.CLIENT, newClient));
@@ -311,14 +311,14 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
if (newClient.isAccountNumberRequiresAutoGeneration()) { if (newClient.isAccountNumberRequiresAutoGeneration()) {
AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.CLIENT); AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.CLIENT);
newClient.updateAccountNo(accountNumberGenerator.generate(newClient, accountNumberFormat)); newClient.updateAccountNo(accountNumberGenerator.generate(newClient, accountNumberFormat));
this.clientRepository.save(newClient); this.clientRepository.saveAndFlush(newClient);
} }
final Locale locale = command.extractLocale(); final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale); final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
CommandProcessingResult result = openSavingsAccount(newClient, fmt); CommandProcessingResult result = openSavingsAccount(newClient, fmt);
if (result.getSavingsId() != null) { if (result.getSavingsId() != null) {
this.clientRepository.save(newClient); this.clientRepository.saveAndFlush(newClient);
} }
@@ -95,7 +95,7 @@ public class CollateralWritePlatformServiceJpaRepositoryImpl implements Collater
LoanCollateralCannotBeCreatedReason.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loan.getId()); LoanCollateralCannotBeCreatedReason.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loan.getId());
} }
this.collateralRepository.save(collateral); this.collateralRepository.saveAndFlush(collateral);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -34,7 +34,7 @@ public class CollateralManagementRepositoryWrapper {
} }
public CollateralManagementDomain create(CollateralManagementDomain collateralData) { public CollateralManagementDomain create(CollateralManagementDomain collateralData) {
return this.collateralManagementDomainRepository.save(collateralData); return this.collateralManagementDomainRepository.saveAndFlush(collateralData);
} }
public CollateralManagementDomain getCollateral(Long collateralId) { public CollateralManagementDomain getCollateral(Long collateralId) {
@@ -73,7 +73,7 @@ public class ClientCollateralManagementWritePlatformServiceImpl implements Clien
final CollateralManagementDomain collateralManagementData = this.collateralManagementRepositoryWrapper.getCollateral(collateralId); final CollateralManagementDomain collateralManagementData = this.collateralManagementRepositoryWrapper.getCollateral(collateralId);
final ClientCollateralManagement clientCollateralManagement = ClientCollateralManagement.createNew(quantity, client, final ClientCollateralManagement clientCollateralManagement = ClientCollateralManagement.createNew(quantity, client,
collateralManagementData); collateralManagementData);
this.clientCollateralManagementRepositoryWrapper.save(clientCollateralManagement); this.clientCollateralManagementRepositoryWrapper.saveAndFlush(clientCollateralManagement);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withClientId(command.getClientId()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withClientId(command.getClientId())
.withEntityId(clientCollateralManagement.getId()).build(); .withEntityId(clientCollateralManagement.getId()).build();
} }
@@ -61,7 +61,7 @@ public class FloatingRateWritePlatformServiceImpl implements FloatingRateWritePl
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
final AppUser currentUser = this.context.authenticatedUser(); final AppUser currentUser = this.context.authenticatedUser();
final FloatingRate newFloatingRate = FloatingRate.createNew(currentUser, command); final FloatingRate newFloatingRate = FloatingRate.createNew(currentUser, command);
this.floatingRateRepository.save(newFloatingRate); this.floatingRateRepository.saveAndFlush(newFloatingRate);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
.withEntityId(newFloatingRate.getId()) // .withEntityId(newFloatingRate.getId()) //
@@ -68,7 +68,7 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf
final Fund fund = Fund.fromJson(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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(fund.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -113,11 +113,11 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf
* Guaranteed to throw an exception no matter what the data integrity issue is. * 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) { 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"); final String externalId = command.stringValueOfParameterNamed("externalId");
throw new PlatformDataIntegrityException("error.msg.fund.duplicate.externalId", throw new PlatformDataIntegrityException("error.msg.fund.duplicate.externalId",
"A fund with external id '" + externalId + "' already exists", "externalId", 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"); final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.fund.duplicate.name", "A fund with name '" + name + "' already exists", throw new PlatformDataIntegrityException("error.msg.fund.duplicate.name", "A fund with name '" + name + "' already exists",
"name", name); "name", name);
@@ -86,7 +86,7 @@ public class GroupRolesWritePlatformServiceJpaRepositoryImpl implements GroupRol
throw new ClientNotInGroupException(clientId, command.getGroupId()); throw new ClientNotInGroupException(clientId, command.getGroupId());
} }
final GroupRole groupRole = GroupRole.createGroupRole(group, client, role); 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()) return new CommandProcessingResultBuilder().withClientId(client.getId()).withGroupId(group.getId())
.withEntityId(groupRole.getId()).build(); .withEntityId(groupRole.getId()).build();
@@ -201,7 +201,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
boolean rollbackTransaction = false; boolean rollbackTransaction = false;
if (newGroup.isActive()) { if (newGroup.isActive()) {
this.groupRepository.save(newGroup); this.groupRepository.saveAndFlush(newGroup);
// validate Group creation rules for Group // validate Group creation rules for Group
if (newGroup.isGroup()) { if (newGroup.isGroup()) {
validateGroupRulesBeforeActivation(newGroup); validateGroupRulesBeforeActivation(newGroup);
@@ -76,7 +76,7 @@ public class InterestRateChartSlabWritePlatformServiceJpaRepositoryImpl implemen
final InterestRateChartSlab interestRateChartSlab = this.interestRateChartSlabAssembler.assembleFrom(command); final InterestRateChartSlab interestRateChartSlab = this.interestRateChartSlabAssembler.assembleFrom(command);
this.chartSlabRepository.save(interestRateChartSlab); this.chartSlabRepository.saveAndFlush(interestRateChartSlab);
final Long interestRateChartId = interestRateChartSlab.getId(); final Long interestRateChartId = interestRateChartSlab.getId();
@@ -44,6 +44,7 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
@@ -1245,8 +1246,17 @@ public class Loan extends AbstractPersistableCustom {
} }
public void updateLoanSchedule(final Collection<LoanRepaymentScheduleInstallment> installments, AppUser currentUser) { public void updateLoanSchedule(final Collection<LoanRepaymentScheduleInstallment> installments, AppUser currentUser) {
this.repaymentScheduleInstallments.clear(); List<LoanRepaymentScheduleInstallment> existingInstallments = new ArrayList<>(this.repaymentScheduleInstallments);
repaymentScheduleInstallments.clear();
for (final LoanRepaymentScheduleInstallment installment : installments) { for (final LoanRepaymentScheduleInstallment installment : installments) {
LoanRepaymentScheduleInstallment existingInstallment = findByInstallmentNumber(existingInstallments,
installment.getInstallmentNumber());
if (existingInstallment != null) {
Set<LoanInstallmentCharge> existingCharges = existingInstallment.getInstallmentCharges();
installment.getInstallmentCharges().addAll(existingCharges);
existingCharges.forEach(c -> c.setInstallment(installment));
existingInstallment.getInstallmentCharges().clear();
}
addLoanRepaymentScheduleInstallment(installment); addLoanRepaymentScheduleInstallment(installment);
} }
updateLoanScheduleDependentDerivedFields(); updateLoanScheduleDependentDerivedFields();
@@ -1255,6 +1265,16 @@ public class Loan extends AbstractPersistableCustom {
} }
private LoanRepaymentScheduleInstallment findByInstallmentNumber(Collection<LoanRepaymentScheduleInstallment> 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 * method updates accrual derived fields on installments and reverse the unprocessed transactions
*/ */
@@ -4984,6 +5004,7 @@ public class Loan extends AbstractPersistableCustom {
.getAmount(); .getAmount();
} }
final LoanInstallmentCharge loanInstallmentCharge = new LoanInstallmentCharge(amount, loanCharge, installment); final LoanInstallmentCharge loanInstallmentCharge = new LoanInstallmentCharge(amount, loanCharge, installment);
installment.getInstallmentCharges().add(loanInstallmentCharge);
loanChargePerInstallments.add(loanInstallmentCharge); loanChargePerInstallments.add(loanInstallmentCharge);
} }
} }
@@ -286,8 +286,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) { private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) {
try { try {
LoanTransaction loanTransaction = this.loanTransactionRepository.save(newRepaymentTransaction); this.loanTransactionRepository.saveAndFlush(newRepaymentTransaction);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
@@ -305,12 +304,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
try { try {
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
if (installment.getId() == null) {
this.repaymentScheduleInstallmentRepository.save(installment);
}
}
this.loanRepositoryWrapper.saveAndFlush(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
@@ -329,12 +322,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
@Override @Override
public void saveLoanWithDataIntegrityViolationChecks(final Loan loan) { public void saveLoanWithDataIntegrityViolationChecks(final Loan loan) {
try { try {
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
if (installment.getId() == null) {
this.repaymentScheduleInstallmentRepository.save(installment);
}
}
this.loanRepositoryWrapper.save(loan); this.loanRepositoryWrapper.save(loan);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
@@ -462,7 +449,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay);
saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction); saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction);
this.loanRepositoryWrapper.save(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
if (StringUtils.isNotBlank(noteText)) { if (StringUtils.isNotBlank(noteText)) {
final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText); final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText);
@@ -659,8 +646,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
loan.makeRefundForActiveLoan(newRefundTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds, loan.makeRefundForActiveLoan(newRefundTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds,
existingReversedTransactionIds, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); existingReversedTransactionIds, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay);
this.loanTransactionRepository.save(newRefundTransaction); this.loanTransactionRepository.saveAndFlush(newRefundTransaction);
this.loanRepositoryWrapper.save(loan);
if (StringUtils.isNotBlank(noteText)) { if (StringUtils.isNotBlank(noteText)) {
final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText); final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText);
@@ -543,9 +543,11 @@ public class LoanCharge extends AbstractPersistableCustom {
for (final LoanInstallmentCharge chargePerInstallment : oldChargeInstallments) { for (final LoanInstallmentCharge chargePerInstallment : oldChargeInstallments) {
if (index == loanChargePerInstallmentArray.length) { if (index == loanChargePerInstallmentArray.length) {
remove.add(chargePerInstallment); remove.add(chargePerInstallment);
chargePerInstallment.updateInstallment(null); chargePerInstallment.getInstallment().getInstallmentCharges().remove(chargePerInstallment);
} else { } else {
chargePerInstallment.copyFrom(loanChargePerInstallmentArray[index++]); LoanInstallmentCharge newLoanInstallmentCharge = loanChargePerInstallmentArray[index++];
newLoanInstallmentCharge.getInstallment().getInstallmentCharges().remove(newLoanInstallmentCharge);
chargePerInstallment.copyFrom(newLoanInstallmentCharge);
} }
} }
this.loanInstallmentCharge.removeAll(remove); this.loanInstallmentCharge.removeAll(remove);
@@ -319,4 +319,7 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom implements
return this.installment; return this.installment;
} }
public void setInstallment(LoanRepaymentScheduleInstallment installment) {
this.installment = installment;
}
} }
@@ -24,6 +24,8 @@ import java.time.ZoneId;
import java.util.Date; import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
@@ -34,6 +36,10 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
@Table(name = "m_loan_interest_recalculation_additional_details") @Table(name = "m_loan_interest_recalculation_additional_details")
public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersistableCustom { public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersistableCustom {
@ManyToOne(optional = false)
@JoinColumn(name = "loan_repayment_schedule_id", nullable = false)
private LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment;
@Temporal(TemporalType.DATE) @Temporal(TemporalType.DATE)
@Column(name = "effective_date") @Column(name = "effective_date")
private Date effectiveDate; private Date effectiveDate;
@@ -59,4 +65,12 @@ public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersista
public BigDecimal getAmount() { public BigDecimal getAmount() {
return this.amount; return this.amount;
} }
public LoanRepaymentScheduleInstallment getLoanRepaymentScheduleInstallment() {
return loanRepaymentScheduleInstallment;
}
public void setLoanRepaymentScheduleInstallment(LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
this.loanRepaymentScheduleInstallment = loanRepaymentScheduleInstallment;
}
} }
@@ -134,13 +134,15 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
@Column(name = "recalculated_interest_component", nullable = false) @Column(name = "recalculated_interest_component", nullable = false)
private boolean recalculatedInterestComponent; private boolean recalculatedInterestComponent;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRepaymentScheduleInstallment")
@JoinColumn(name = "loan_repayment_schedule_id", referencedColumnName = "id", nullable = false)
private Set<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails = new HashSet<>(); private Set<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails = new HashSet<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRepaymentScheduleInstallment") @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRepaymentScheduleInstallment")
private Set<PostDatedChecks> postDatedChecks; private Set<PostDatedChecks> postDatedChecks;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "installment")
private Set<LoanInstallmentCharge> installmentCharges = new HashSet<>();
LoanRepaymentScheduleInstallment() { LoanRepaymentScheduleInstallment() {
this.installmentNumber = null; this.installmentNumber = null;
this.fromDate = null; this.fromDate = null;
@@ -162,6 +164,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
this.penaltyCharges = defaultToNullIfZero(penaltyCharges); this.penaltyCharges = defaultToNullIfZero(penaltyCharges);
this.obligationsMet = false; this.obligationsMet = false;
this.recalculatedInterestComponent = recalculatedInterestComponent; this.recalculatedInterestComponent = recalculatedInterestComponent;
if (compoundingDetails != null) {
compoundingDetails.forEach(cd -> cd.setLoanRepaymentScheduleInstallment(this));
}
this.loanCompoundingDetails = compoundingDetails; this.loanCompoundingDetails = compoundingDetails;
this.rescheduleInterestPortion = rescheduleInterestPortion; this.rescheduleInterestPortion = rescheduleInterestPortion;
} }
@@ -180,6 +185,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
this.penaltyCharges = defaultToNullIfZero(penaltyCharges); this.penaltyCharges = defaultToNullIfZero(penaltyCharges);
this.obligationsMet = false; this.obligationsMet = false;
this.recalculatedInterestComponent = recalculatedInterestComponent; this.recalculatedInterestComponent = recalculatedInterestComponent;
if (compoundingDetails != null) {
compoundingDetails.forEach(cd -> cd.setLoanRepaymentScheduleInstallment(this));
}
this.loanCompoundingDetails = compoundingDetails; this.loanCompoundingDetails = compoundingDetails;
} }
@@ -861,4 +869,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
this.feeChargesWaived = newFeeChargesCharged; this.feeChargesWaived = newFeeChargesCharged;
} }
public Set<LoanInstallmentCharge> getInstallmentCharges() {
return installmentCharges;
}
} }
@@ -24,11 +24,16 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
@Entity @Entity
@Table(name = "m_loan_reschedule_request_term_variations_mapping") @Table(name = "m_loan_reschedule_request_term_variations_mapping")
public class LoanRescheduleRequestToTermVariationMapping extends AbstractPersistableCustom { 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) @ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@JoinColumn(name = "loan_term_variations_id", nullable = false) @JoinColumn(name = "loan_term_variations_id", nullable = false)
private LoanTermVariations loanTermVariations; private LoanTermVariations loanTermVariations;
@@ -37,16 +42,22 @@ public class LoanRescheduleRequestToTermVariationMapping extends AbstractPersist
} }
private LoanRescheduleRequestToTermVariationMapping(final LoanTermVariations loanTermVariations) { private LoanRescheduleRequestToTermVariationMapping(final LoanRescheduleRequest loanRescheduleRequest,
final LoanTermVariations loanTermVariations) {
this.loanRescheduleRequest = loanRescheduleRequest;
this.loanTermVariations = loanTermVariations; this.loanTermVariations = loanTermVariations;
} }
public static LoanRescheduleRequestToTermVariationMapping createNew(final LoanTermVariations loanTermVariation) { public static LoanRescheduleRequestToTermVariationMapping createNew(final LoanRescheduleRequest loanRescheduleRequest,
return new LoanRescheduleRequestToTermVariationMapping(loanTermVariation); final LoanTermVariations loanTermVariation) {
return new LoanRescheduleRequestToTermVariationMapping(loanRescheduleRequest, loanTermVariation);
} }
public LoanTermVariations getLoanTermVariations() { public LoanTermVariations getLoanTermVariations() {
return this.loanTermVariations; return this.loanTermVariations;
} }
public LoanRescheduleRequest getLoanRescheduleRequest() {
return loanRescheduleRequest;
}
} }
@@ -133,8 +133,7 @@ public class LoanTransaction extends AbstractPersistableCustom {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "loanTransaction") @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "loanTransaction")
private Set<LoanCollateralManagement> loanCollateralManagementSet = new HashSet<>(); private Set<LoanCollateralManagement> loanCollateralManagementSet = new HashSet<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanTransaction")
@JoinColumn(name = "loan_transaction_id", referencedColumnName = "id", nullable = false)
private Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = new HashSet<>(); private Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = new HashSet<>();
protected LoanTransaction() { protected LoanTransaction() {
@@ -793,6 +792,7 @@ public class LoanTransaction extends AbstractPersistableCustom {
} }
} }
if (!isMappingUpdated) { if (!isMappingUpdated) {
updatedrepaymentScheduleMapping.setLoanTransaction(this);
this.loanTransactionToRepaymentScheduleMappings.add(updatedrepaymentScheduleMapping); this.loanTransactionToRepaymentScheduleMappings.add(updatedrepaymentScheduleMapping);
retainMappings.add(updatedrepaymentScheduleMapping); retainMappings.add(updatedrepaymentScheduleMapping);
} }
@@ -33,6 +33,10 @@ import org.apache.fineract.organisation.monetary.domain.Money;
@Table(name = "m_loan_transaction_repayment_schedule_mapping") @Table(name = "m_loan_transaction_repayment_schedule_mapping")
public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistableCustom { public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistableCustom {
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@JoinColumn(name = "loan_transaction_id", nullable = false)
private LoanTransaction loanTransaction;
@ManyToOne(optional = false, cascade = CascadeType.PERSIST) @ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@JoinColumn(name = "loan_repayment_schedule_id", nullable = false) @JoinColumn(name = "loan_repayment_schedule_id", nullable = false)
private LoanRepaymentScheduleInstallment installment; private LoanRepaymentScheduleInstallment installment;
@@ -56,9 +60,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab
} }
private LoanTransactionToRepaymentScheduleMapping(final LoanRepaymentScheduleInstallment installment, final BigDecimal principalPortion, private LoanTransactionToRepaymentScheduleMapping(final LoanTransaction loanTransaction,
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final LoanRepaymentScheduleInstallment installment, final BigDecimal principalPortion, final BigDecimal interestPortion,
final BigDecimal amount) { final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal amount) {
this.loanTransaction = loanTransaction;
this.installment = installment; this.installment = installment;
this.principalPortion = principalPortion; this.principalPortion = principalPortion;
this.interestPortion = interestPortion; this.interestPortion = interestPortion;
@@ -67,9 +72,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab
this.amount = amount; this.amount = amount;
} }
public static LoanTransactionToRepaymentScheduleMapping createFrom(final LoanRepaymentScheduleInstallment installment, public static LoanTransactionToRepaymentScheduleMapping createFrom(final LoanTransaction loanTransaction,
final Money principalPortion, final Money interestPortion, final Money feeChargesPortion, final Money penaltyChargesPortion) { final LoanRepaymentScheduleInstallment installment, final Money principalPortion, final Money interestPortion,
return new LoanTransactionToRepaymentScheduleMapping(installment, defaultToNullIfZero(principalPortion), final Money feeChargesPortion, final Money penaltyChargesPortion) {
return new LoanTransactionToRepaymentScheduleMapping(loanTransaction, installment, defaultToNullIfZero(principalPortion),
defaultToNullIfZero(interestPortion), defaultToNullIfZero(feeChargesPortion), defaultToNullIfZero(penaltyChargesPortion), defaultToNullIfZero(interestPortion), defaultToNullIfZero(feeChargesPortion), defaultToNullIfZero(penaltyChargesPortion),
defaultToNullIfZero(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion))); defaultToNullIfZero(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion)));
} }
@@ -138,6 +144,10 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab
return Money.of(currency, this.penaltyChargesPortion); return Money.of(currency, this.penaltyChargesPortion);
} }
public LoanTransaction getLoanTransaction() {
return loanTransaction;
}
public BigDecimal getPrincipalPortion() { public BigDecimal getPrincipalPortion() {
return this.principalPortion; return this.principalPortion;
} }
@@ -153,4 +163,8 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab
public BigDecimal getPenaltyChargesPortion() { public BigDecimal getPenaltyChargesPortion() {
return this.penaltyChargesPortion; return this.penaltyChargesPortion;
} }
public void setLoanTransaction(LoanTransaction loanTransaction) {
this.loanTransaction = loanTransaction;
}
} }
@@ -131,8 +131,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
return transactionAmountRemaining; return transactionAmountRemaining;
@@ -175,8 +175,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractL
} }
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -84,8 +84,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
@@ -153,8 +153,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -195,8 +195,8 @@ public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends Abstr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -129,8 +129,8 @@ public class FineractStyleLoanRepaymentScheduleTransactionProcessor extends Abst
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -172,8 +172,8 @@ public class FineractStyleLoanRepaymentScheduleTransactionProcessor extends Abst
} }
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -132,8 +132,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -193,8 +193,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -237,8 +237,8 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -118,8 +118,8 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -158,8 +158,8 @@ public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -118,8 +118,8 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
} }
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
@@ -161,8 +161,8 @@ public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionPr
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -93,8 +93,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
final Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); final Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency());
loanTransaction.updateComponents(principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion);
if (interestWaivedPortion.isGreaterThanZero()) { if (interestWaivedPortion.isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestWaivedPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestWaivedPortion, feeChargesPortion, penaltyChargesPortion));
} }
} else if (loanTransaction.isChargePayment()) { } else if (loanTransaction.isChargePayment()) {
final Money principalPortion = Money.zero(currency); final Money principalPortion = Money.zero(currency);
@@ -108,8 +108,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
} }
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
} else { } else {
@@ -133,8 +133,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
final Money principalPortion = Money.zero(currency); final Money principalPortion = Money.zero(currency);
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, installment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
} }
} }
@@ -159,8 +159,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
} }
if (!isMappingUpdated && principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion) if (!isMappingUpdated && principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion)
.isGreaterThanZero()) { .isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(installment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, installment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
} }
} }
@@ -237,8 +237,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -290,8 +290,8 @@ public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRe
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) { if (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero()) {
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(currentInstallment, principalPortion, transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(loanTransaction, currentInstallment,
interestPortion, feeChargesPortion, penaltyChargesPortion)); principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion));
} }
return transactionAmountRemaining; return transactionAmountRemaining;
} }
@@ -27,7 +27,7 @@ import org.springframework.data.repository.query.Param;
public interface GuarantorFundingTransactionRepository public interface GuarantorFundingTransactionRepository
extends JpaRepository<GuarantorFundingTransaction, Long>, JpaSpecificationExecutor<GuarantorFundingTransaction> { extends JpaRepository<GuarantorFundingTransaction, Long>, JpaSpecificationExecutor<GuarantorFundingTransaction> {
@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<GuarantorFundingTransaction> fetchGuarantorFundingTransactions(@Param("loanTransactions") List<Long> loanTransactions); List<GuarantorFundingTransaction> fetchGuarantorFundingTransactions(@Param("loanTransactions") List<Long> loanTransactions);
} }
@@ -185,7 +185,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null, GuarantorFundingTransaction guarantorFundingTransaction = new GuarantorFundingTransaction(guarantorFundingDetails, null,
onHoldTransaction); onHoldTransaction);
guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction); guarantorFundingDetails.addGuarantorFundingTransactions(guarantorFundingTransaction);
this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction); this.depositAccountOnHoldTransactionRepository.saveAndFlush(onHoldTransaction);
} }
} }
@@ -206,8 +206,8 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
guarantorFundingDetails.releaseFunds(amoutForWithdraw); guarantorFundingDetails.releaseFunds(amoutForWithdraw);
guarantorFundingDetails.withdrawFunds(amoutForWithdraw); guarantorFundingDetails.withdrawFunds(amoutForWithdraw);
guarantorFundingDetails.getLoanAccount().updateGuaranteeAmount(amoutForWithdraw.negate()); guarantorFundingDetails.getLoanAccount().updateGuaranteeAmount(amoutForWithdraw.negate());
this.depositAccountOnHoldTransactionRepository.save(onHoldTransaction); this.depositAccountOnHoldTransactionRepository.saveAndFlush(onHoldTransaction);
this.guarantorFundingRepository.save(guarantorFundingDetails); this.guarantorFundingRepository.saveAndFlush(guarantorFundingDetails);
} }
} }
@@ -482,7 +482,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
calculateAndRelaseGuarantorFunds(guarantorList, guarantorGuarantee, amountForRelease, loanTransaction, calculateAndRelaseGuarantorFunds(guarantorList, guarantorGuarantee, amountForRelease, loanTransaction,
accountOnHoldTransactions); accountOnHoldTransactions);
this.depositAccountOnHoldTransactionRepository.saveAll(accountOnHoldTransactions); this.depositAccountOnHoldTransactionRepository.saveAll(accountOnHoldTransactions);
this.guarantorFundingRepository.save(guarantorFundingDetails); this.guarantorFundingRepository.saveAndFlush(guarantorFundingDetails);
} }
} }
@@ -174,9 +174,9 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
} }
if (accountAssociations != null) { 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()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantor.getOfficeId())
.withEntityId(guarantor.getId()).withLoanId(loan.getId()).build(); .withEntityId(guarantor.getId()).withLoanId(loan.getId()).build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) { } catch (final JpaSystemException | DataIntegrityViolationException dve) {
@@ -245,7 +245,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto
} }
if (!changesOnly.isEmpty()) { if (!changesOnly.isEmpty()) {
this.guarantorRepository.save(guarantorForUpdate); this.guarantorRepository.saveAndFlush(guarantorForUpdate);
} }
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantorForUpdate.getOfficeId()) return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(guarantorForUpdate.getOfficeId())
@@ -930,7 +930,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
* @param currency * @param currency
* @param scheduleParams * @param scheduleParams
* @param lastRestDate * @param lastRestDate
* @param periodStartDateApplicableForInterest
* @param detail * @param detail
*/ */
private void handleLatePayments(final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO, private void handleLatePayments(final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO,
@@ -991,15 +990,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
/** /**
* @param loanApplicationTerms * @param loanApplicationTerms
* @param scheduleParams * @param scheduleParams
* @param priviousScheduledDueDate
* @param previousRepaymentDate * @param previousRepaymentDate
* @param scheduledDueDate * @param scheduledDueDate
* @param interestRatesForInstallments * @param interestRatesForInstallments
* @param mc * @param mc
* @param paymentPeriodsInOneYearCalculator
* @param interestRates
* @param periodsApplicableForGrace
* @param scheduleDateForReversal
* @return * @return
*/ */
private LoanTermVariationParams applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, private LoanTermVariationParams applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms,
@@ -1139,7 +1133,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
* TODO * TODO
* @param mc * @param mc
* TODO * TODO
* @param periodNumber
* @return * @return
*/ */
private LoanTermVariationParams applyExceptionLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, private LoanTermVariationParams applyExceptionLoanTermVariations(final LoanApplicationTerms loanApplicationTerms,
@@ -1222,7 +1215,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
* @param scheduleParams * @param scheduleParams
* @param interestRates * @param interestRates
* @param interestRatesForInstallments * @param interestRatesForInstallments
* @param periodsApplicableForGrace
*/ */
private void applyLoanVariationsForPartialScheduleGenerate(final LoanApplicationTerms loanApplicationTerms, private void applyLoanVariationsForPartialScheduleGenerate(final LoanApplicationTerms loanApplicationTerms,
LoanScheduleParams scheduleParams, final Collection<LoanTermVariationsData> interestRates, LoanScheduleParams scheduleParams, final Collection<LoanTermVariationsData> interestRates,
@@ -1317,13 +1309,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
* Method calculates interest on not paid outstanding principal and interest (if compounding is enabled) till * Method calculates interest on not paid outstanding principal and interest (if compounding is enabled) till
* current date and adds new repayment schedule detail * 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, private Money addInterestOnlyRepaymentScheduleForCurrentdate(final MathContext mc, final LoanApplicationTerms loanApplicationTerms,
final HolidayDetailDTO holidayDetailDTO, final MonetaryCurrency currency, final Collection<LoanScheduleModelPeriod> periods, final HolidayDetailDTO holidayDetailDTO, final MonetaryCurrency currency, final Collection<LoanScheduleModelPeriod> periods,
@@ -1869,8 +1854,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
* *
* @param firstRepaymentdate * @param firstRepaymentdate
* TODO * TODO
* @param boolean1
* @param localDate
*/ */
private LocalDate calculateInterestStartDateForPeriod(final LoanApplicationTerms loanApplicationTerms, LocalDate periodStartDate, private LocalDate calculateInterestStartDateForPeriod(final LoanApplicationTerms loanApplicationTerms, LocalDate periodStartDate,
final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate, final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate,
@@ -95,8 +95,7 @@ public class LoanRescheduleRequest extends AbstractPersistableCustom {
@JoinColumn(name = "rejected_by_user_id") @JoinColumn(name = "rejected_by_user_id")
private AppUser rejectedByUser; private AppUser rejectedByUser;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "loanRescheduleRequest")
@JoinColumn(name = "loan_reschedule_request_id", nullable = false)
private Set<LoanRescheduleRequestToTermVariationMapping> loanRescheduleRequestToTermVariationMappings = new HashSet<>(); private Set<LoanRescheduleRequestToTermVariationMapping> loanRescheduleRequestToTermVariationMappings = new HashSet<>();
/** /**
@@ -284,8 +284,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
decimalValue, dueDate, endDate, emi); decimalValue, dueDate, endDate, emi);
// create a new entry in the m_loan_reschedule_request table // 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()) return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(loanRescheduleRequest.getId())
.withLoanId(loan.getId()).withClientId(loan.getClientId()).withOfficeId(loan.getOfficeId()) .withLoanId(loan.getId()).withClientId(loan.getClientId()).withOfficeId(loan.getOfficeId())
@@ -316,7 +316,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
for (LoanRepaymentScheduleInstallment installment : installments) { for (LoanRepaymentScheduleInstallment installment : installments) {
if (installment.getDueDate().isEqual(rescheduleFromLocDate) || installment.getDueDate().isEqual(endDateLocDate) if (installment.getDueDate().isEqual(rescheduleFromLocDate) || installment.getDueDate().isEqual(endDateLocDate)
|| (installment.getDueDate().isAfter(rescheduleFromLocDate) && installment.getDueDate().isBefore(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()),
Date.from(installment.getDueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(installment.getDueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent); loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
@@ -330,51 +330,57 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
if (rescheduleFromDate != null && adjustedDueDate != null) { if (rescheduleFromDate != null && adjustedDueDate != null) {
LoanTermVariations parent = null; LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.DUE_DATE.getValue(); final Integer termType = LoanTermVariationType.DUE_DATE.getValue();
createLoanTermVariations(termType, loan, rescheduleFromDate, adjustedDueDate, loanRescheduleRequestToTermVariationMappings, createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, adjustedDueDate,
isActive, isSpecificToInstallment, decimalValue, parent); loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, decimalValue, parent);
} }
if (rescheduleFromDate != null && interestRate != null) { if (rescheduleFromDate != null && interestRate != null) {
LoanTermVariations parent = null; LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.INTEREST_RATE_FROM_INSTALLMENT.getValue(); final Integer termType = LoanTermVariationType.INTEREST_RATE_FROM_INSTALLMENT.getValue();
createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
isSpecificToInstallment, interestRate, parent); loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, interestRate, parent);
} }
if (rescheduleFromDate != null && graceOnPrincipal != null) { if (rescheduleFromDate != null && graceOnPrincipal != null) {
final Integer termType = LoanTermVariationType.GRACE_ON_PRINCIPAL.getValue(); final Integer termType = LoanTermVariationType.GRACE_ON_PRINCIPAL.getValue();
LoanTermVariations parent = null; LoanTermVariations parent = null;
parent = createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal), parent); loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal); BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
createLoanTermVariations(LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate, createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent); rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
extraTermsBasedOnGracePeriods, parent);
} }
if (rescheduleFromDate != null && graceOnInterest != null) { if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null; LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue(); final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest), parent); loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
parent);
} }
if (rescheduleFromDate != null && extraTerms != null) { if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null; LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(); final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
createLoanTermVariations(termType, loan, rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
isSpecificToInstallment, BigDecimal.valueOf(extraTerms), parent); loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
parent);
} }
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings); loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
} }
private LoanTermVariations createLoanTermVariations(final Integer termType, final Loan loan, Date rescheduleFromDate, private LoanTermVariations createLoanTermVariations(LoanRescheduleRequest loanRescheduleRequest, final Integer termType,
Date adjustedDueDate, List<LoanRescheduleRequestToTermVariationMapping> loanRescheduleRequestToTermVariationMappings, final Loan loan, Date rescheduleFromDate, Date adjustedDueDate,
final Boolean isActive, final boolean isSpecificToInstallment, final BigDecimal decimalValue, LoanTermVariations parent) { List<LoanRescheduleRequestToTermVariationMapping> loanRescheduleRequestToTermVariationMappings, final Boolean isActive,
final boolean isSpecificToInstallment, final BigDecimal decimalValue, LoanTermVariations parent) {
LoanTermVariations loanTermVariation = new LoanTermVariations(termType, rescheduleFromDate, decimalValue, adjustedDueDate, LoanTermVariations loanTermVariation = new LoanTermVariations(termType, rescheduleFromDate, decimalValue, adjustedDueDate,
isSpecificToInstallment, loan, loan.status().getValue(), isActive, parent); isSpecificToInstallment, loan, loan.status().getValue(), isActive, parent);
loanRescheduleRequestToTermVariationMappings.add(LoanRescheduleRequestToTermVariationMapping.createNew(loanTermVariation)); loanRescheduleRequestToTermVariationMappings
.add(LoanRescheduleRequestToTermVariationMapping.createNew(loanRescheduleRequest, loanTermVariation));
return loanTermVariation; return loanTermVariation;
} }
@@ -105,7 +105,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine; 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.LoanRepaymentScheduleInstallmentRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
@@ -392,7 +391,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
} }
} }
this.loanRepositoryWrapper.save(newLoanApplication); this.loanRepositoryWrapper.saveAndFlush(newLoanApplication);
if (loanProduct.isInterestRecalculationEnabled()) { if (loanProduct.isInterestRecalculationEnabled()) {
this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(newLoanApplication); this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(newLoanApplication);
@@ -487,7 +486,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
} }
} else { // for applications other than GLIM } else { // for applications other than GLIM
newLoanApplication.updateAccountNo(this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat)); newLoanApplication.updateAccountNo(this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat));
this.loanRepositoryWrapper.save(newLoanApplication); this.loanRepositoryWrapper.saveAndFlush(newLoanApplication);
} }
} }
@@ -582,6 +581,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
command.arrayOfParameterNamed(LoanApiConstants.datatables)); command.arrayOfParameterNamed(LoanApiConstants.datatables));
} }
loanRepositoryWrapper.flush();
this.entityDatatableChecksWritePlatformService.runTheCheckForProduct(newLoanApplication.getId(), EntityTables.LOAN.getName(), this.entityDatatableChecksWritePlatformService.runTheCheckForProduct(newLoanApplication.getId(), EntityTables.LOAN.getName(),
StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(),
newLoanApplication.productId()); newLoanApplication.productId());
@@ -1224,7 +1225,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
// updating loan interest recalculation details throwing null // updating loan interest recalculation details throwing null
// pointer exception after saveAndFlush // pointer exception after saveAndFlush
// http://stackoverflow.com/questions/17151757/hibernate-cascade-update-gives-null-pointer/17334374#17334374 // http://stackoverflow.com/questions/17151757/hibernate-cascade-update-gives-null-pointer/17334374#17334374
this.loanRepositoryWrapper.save(existingLoanApplication); this.loanRepositoryWrapper.saveAndFlush(existingLoanApplication);
if (productRelatedDetail.isInterestRecalculationEnabled()) { if (productRelatedDetail.isInterestRecalculationEnabled()) {
this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication); this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication);
@@ -1616,7 +1617,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final Map<String, Object> changes = loan.loanApplicationRejection(currentUser, command, defaultLoanLifecycleStateMachine()); final Map<String, Object> changes = loan.loanApplicationRejection(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
this.loanRepositoryWrapper.save(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
final String noteText = command.stringValueOfParameterNamed("note"); final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) { if (StringUtils.isNotBlank(noteText)) {
@@ -1668,7 +1669,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
} }
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
this.loanRepositoryWrapper.save(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
final String noteText = command.stringValueOfParameterNamed("note"); final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) { if (StringUtils.isNotBlank(noteText)) {
@@ -1737,12 +1738,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
try { try {
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
if (installment.getId() == null) {
this.repaymentScheduleInstallmentRepository.save(installment);
}
}
this.loanRepositoryWrapper.saveAndFlush(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
@@ -667,13 +667,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
try { try {
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
// installment.setPostDatedChecksToNull();
if (installment.getId() == null) {
this.repaymentScheduleInstallmentRepository.save(installment);
}
}
this.loanRepositoryWrapper.saveAndFlush(loan); this.loanRepositoryWrapper.saveAndFlush(loan);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
@@ -691,12 +684,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private void saveLoanWithDataIntegrityViolationChecks(final Loan loan) { private void saveLoanWithDataIntegrityViolationChecks(final Loan loan) {
try { try {
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
if (installment.getId() == null) {
this.repaymentScheduleInstallmentRepository.save(installment);
}
}
this.loanRepositoryWrapper.save(loan); this.loanRepositoryWrapper.save(loan);
} catch (final JpaSystemException | DataIntegrityViolationException e) { } catch (final JpaSystemException | DataIntegrityViolationException e) {
final Throwable realCause = e.getCause(); final Throwable realCause = e.getCause();
@@ -1145,7 +1132,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
if (paymentDetail != null) { if (paymentDetail != null) {
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
} }
this.loanTransactionRepository.save(newTransactionDetail); this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
} }
/*** /***
@@ -1252,7 +1239,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO,
currentUser); currentUser);
this.loanTransactionRepository.save(waiveInterestTransaction); this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
/*** /***
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the * TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
@@ -1328,7 +1315,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final ChangedTransactionDetail changedTransactionDetail = loan.closeAsWrittenOff(command, defaultLoanLifecycleStateMachine(), final ChangedTransactionDetail changedTransactionDetail = loan.closeAsWrittenOff(command, defaultLoanLifecycleStateMachine(),
changes, existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO); changes, existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO);
LoanTransaction writeoff = changedTransactionDetail.getNewTransactionMappings().remove(0L); LoanTransaction writeoff = changedTransactionDetail.getNewTransactionMappings().remove(0L);
this.loanTransactionRepository.save(writeoff); this.loanTransactionRepository.saveAndFlush(writeoff);
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
this.loanTransactionRepository.save(mapEntry.getValue()); this.loanTransactionRepository.save(mapEntry.getValue());
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
@@ -1383,7 +1370,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser);
final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L); final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L);
if (possibleClosingTransaction != null) { if (possibleClosingTransaction != null) {
this.loanTransactionRepository.save(possibleClosingTransaction); this.loanTransactionRepository.saveAndFlush(possibleClosingTransaction);
} }
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
this.loanTransactionRepository.save(mapEntry.getValue()); this.loanTransactionRepository.save(mapEntry.getValue());
@@ -1682,7 +1669,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.addLoanCharge(loanCharge); 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 * we want to apply charge transactions only for those loans charges that are applied when a loan is active and
@@ -1690,7 +1677,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
**/ **/
if (loan.status().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { if (loan.status().isActive() && loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null, currentUser); final LoanTransaction applyLoanChargeTransaction = loan.handleChargeAppliedTransaction(loanCharge, null, currentUser);
this.loanTransactionRepository.save(applyLoanChargeTransaction); this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
} }
boolean isAppliedOnBackDate = false; boolean isAppliedOnBackDate = false;
if (loanCharge.getDueLocalDate() == null || DateUtils.getLocalDateOfTenant().isAfter(loanCharge.getDueLocalDate())) { if (loanCharge.getDueLocalDate() == null || DateUtils.getLocalDateOfTenant().isAfter(loanCharge.getDueLocalDate())) {
@@ -1952,7 +1939,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge, existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge,
currentUser); currentUser);
this.loanTransactionRepository.save(waiveTransaction); this.loanTransactionRepository.saveAndFlush(waiveTransaction);
saveLoanWithDataIntegrityViolationChecks(loan); saveLoanWithDataIntegrityViolationChecks(loan);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
@@ -2214,7 +2201,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.addLoanTransaction(newTransferTransaction); loan.addLoanTransaction(newTransferTransaction);
loan.setLoanStatus(LoanStatus.TRANSFER_IN_PROGRESS.getValue()); loan.setLoanStatus(LoanStatus.TRANSFER_IN_PROGRESS.getValue());
this.loanTransactionRepository.save(newTransferTransaction); this.loanTransactionRepository.saveAndFlush(newTransferTransaction);
saveLoanWithDataIntegrityViolationChecks(loan); saveLoanWithDataIntegrityViolationChecks(loan);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
@@ -2246,7 +2233,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.reassignLoanOfficer(loanOfficer, transferDate); loan.reassignLoanOfficer(loanOfficer, transferDate);
} }
this.loanTransactionRepository.save(newTransferAcceptanceTransaction); this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
saveLoanWithDataIntegrityViolationChecks(loan); saveLoanWithDataIntegrityViolationChecks(loan);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
@@ -2272,7 +2259,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.addLoanTransaction(newTransferAcceptanceTransaction); loan.addLoanTransaction(newTransferAcceptanceTransaction);
loan.setLoanStatus(LoanStatus.ACTIVE.getValue()); loan.setLoanStatus(LoanStatus.ACTIVE.getValue());
this.loanTransactionRepository.save(newTransferAcceptanceTransaction); this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
saveLoanWithDataIntegrityViolationChecks(loan); saveLoanWithDataIntegrityViolationChecks(loan);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
@@ -185,9 +185,6 @@ public class LoanProduct extends AbstractPersistableCustom {
@Column(name = "can_use_for_topup", nullable = false) @Column(name = "can_use_for_topup", nullable = false)
private boolean canUseForTopup = 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) @Column(name = "fixed_principal_percentage_per_installment", scale = 2, precision = 5, nullable = true)
private BigDecimal fixedPrincipalPercentagePerInstallment; private BigDecimal fixedPrincipalPercentagePerInstallment;
@@ -690,7 +687,6 @@ public class LoanProduct extends AbstractPersistableCustom {
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate; this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate;
this.canUseForTopup = canUseForTopup; this.canUseForTopup = canUseForTopup;
this.isEqualAmortization = isEqualAmortization;
this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment; this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment;
if (rates != null) { if (rates != null) {
@@ -1455,11 +1451,7 @@ public class LoanProduct extends AbstractPersistableCustom {
} }
public boolean isEqualAmortization() { public boolean isEqualAmortization() {
return isEqualAmortization; return loanProductRelatedDetail.isEqualAmortization();
}
public void setEqualAmortization(boolean isEqualAmortization) {
this.isEqualAmortization = isEqualAmortization;
} }
public List<Rate> getRates() { public List<Rate> getRates() {
@@ -141,7 +141,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
this.aprCalculator, floatingRate, rates); this.aprCalculator, floatingRate, rates);
loanproduct.updateLoanProductInRelatedClasses(); loanproduct.updateLoanProductInRelatedClasses();
this.loanProductRepository.save(loanproduct); this.loanProductRepository.saveAndFlush(loanproduct);
// save accounting mappings // save accounting mappings
this.accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command); this.accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command);
@@ -130,7 +130,7 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
newMeeting.associateClientsAttendance(clientsAttendance); newMeeting.associateClientsAttendance(clientsAttendance);
} }
// save meeting details // save meeting details
this.meetingRepositoryWrapper.save(newMeeting); this.meetingRepositoryWrapper.saveAndFlush(newMeeting);
final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null; final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null;
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(newMeeting.getId()) // .withEntityId(newMeeting.getId()) //
@@ -78,7 +78,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
} }
final Note newNote = Note.clientNoteFromJson(client, command); final Note newNote = Note.clientNoteFromJson(client, command);
this.noteRepository.save(newNote); this.noteRepository.saveAndFlush(newNote);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -105,7 +105,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
final Group group = this.groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId)); final Group group = this.groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId));
final Note newNote = Note.groupNoteFromJson(group, command); final Note newNote = Note.groupNoteFromJson(group, command);
this.noteRepository.save(newNote); this.noteRepository.saveAndFlush(newNote);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -123,7 +123,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
final String note = command.stringValueOfParameterNamed("note"); final String note = command.stringValueOfParameterNamed("note");
final Note newNote = Note.loanNote(loan, note); final Note newNote = Note.loanNote(loan, note);
this.noteRepository.save(newNote); this.noteRepository.saveAndFlush(newNote);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -145,7 +145,7 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
final String note = command.stringValueOfParameterNamed("note"); final String note = command.stringValueOfParameterNamed("note");
final Note newNote = Note.loanTransactionNote(loan, loanTransaction, note); final Note newNote = Note.loanTransactionNote(loan, loanTransaction, note);
this.noteRepository.save(newNote); this.noteRepository.saveAndFlush(newNote);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -58,7 +58,7 @@ public class PaymentTypeWriteServiceImpl implements PaymentTypeWriteService {
Long position = command.longValueOfParameterNamed(PaymentTypeApiResourceConstants.POSITION); Long position = command.longValueOfParameterNamed(PaymentTypeApiResourceConstants.POSITION);
PaymentType newPaymentType = PaymentType.create(name, description, isCashPayment, 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(newPaymentType.getId()).build();
} }
@@ -78,7 +78,7 @@ public class RateWriteServiceImpl implements RateWriteService {
} }
final Rate rate = Rate.fromJson(command, approveUser); 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(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(rate.getId()).build();

Some files were not shown because too many files have changed in this diff Show More