FINERACT-1932: Fineract modularization - fineract-savings

This commit is contained in:
Jose Alberto Hernandez
2024-01-29 14:14:31 +01:00
committed by Adam Saghy
parent 1f00bb6d33
commit 02cf6749af
213 changed files with 352 additions and 78 deletions
+3 -1
View File
@@ -31,6 +31,7 @@ buildscript {
'fineract-provider',
'fineract-investor',
'fineract-loan',
'fineract-savings',
'integration-tests',
'twofactor-tests',
'oauth2-tests',
@@ -46,7 +47,8 @@ buildscript {
'fineract-core',
'fineract-provider',
'fineract-investor',
'fineract-loan'
'fineract-loan',
'fineract-savings'
].contains(it.name)
}
npmRepository = 'https://npm.pkg.github.com'
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanproduct.exception;
package org.apache.fineract.organisation.monetary.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+1
View File
@@ -27,6 +27,7 @@ dependencies {
implementation(project(path: ':fineract-core'))
implementation(project(path: ':fineract-investor'))
implementation(project(path: ':fineract-loan'))
implementation(project(path: ':fineract-savings'))
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
// Never use "compile" scope, but make all dependencies either 'implementation', 'runtimeOnly' or 'testCompile'.
@@ -21,41 +21,18 @@ package org.apache.fineract.interoperation.data;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.portfolio.note.domain.Note;
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountChargePaidBy;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
@Getter
public class InteropTransactionData extends CommandProcessingResult {
// private final SavingsAccountTransactionEnumData transactionType;
// private final PaymentDetailData paymentDetailData;
// private final BigDecimal outstandingChargeAmount;
// private final boolean reversed;
// private final AccountTransferData transfer;
// private final LocalDate submittedOnDate;
// private final boolean interestedPostedAsOn;
// private final String submittedByUsername;
// // templates
// final Collection<PaymentTypeData> paymentTypeOptions;
// //import fields
// private Long paymentTypeId;
// private String checkNumber;
// private String routingCode;
// private String receiptNumber;
// private String bankNumber;
// private String transactionReference;
// private String statementReference;
// private CreditDebitType creditDebit;
// private TransactionStatus status;
// private String transactionInformation;
// private String addressLine;
@NotNull
private final String accountId;
@NotNull
@@ -75,7 +52,7 @@ public class InteropTransactionData extends CommandProcessingResult {
@NotNull
private final LocalDate valueDateTime;
private final String note;
private String note;
public InteropTransactionData(Long entityId, String accountId, String transactionId, SavingsAccountTransactionType transactionType,
BigDecimal amount, BigDecimal chargeAmount, String currency, BigDecimal accountBalance, LocalDate bookingDateTime,
@@ -117,33 +94,14 @@ public class InteropTransactionData extends CommandProcessingResult {
LocalDate valueDateTime = endOfBalanceLocalDate == null ? bookingDateTime : endOfBalanceLocalDate;
StringBuilder sb = new StringBuilder();
int currLength = 0;
for (Note note : transaction.getNotes()) {
String s = note.getNote();
if (s == null) {
continue;
}
int availableLength = 500 - currLength;
if (availableLength <= 1) {
break;
}
if (currLength > 0) {
sb.append(' ');
availableLength--;
}
if (s.length() > availableLength) {
s = s.substring(availableLength);
}
sb.append(s);
currLength = sb.length();
}
if (currLength == 0) {
sb.append(SavingsEnumerations.transactionType(transactionType).getValue());
}
sb.append(SavingsEnumerations.transactionType(transactionType).getValue());
return new InteropTransactionData(savingsAccount.getId(), savingsAccount.getExternalId().getValue(), transactionId, transactionType,
amount, chargeAmount, currency, runningBalance, bookingDateTime, valueDateTime, sb.toString());
}
public void updateNote(String note) {
this.note = note;
}
}
@@ -22,11 +22,15 @@ import jakarta.validation.constraints.NotNull;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
@Getter
@Setter
public class InteropTransactionsData extends CommandProcessingResult {
List<InteropTransactionData> transactions;
@@ -64,6 +64,7 @@ import org.apache.fineract.interoperation.data.InteropKycResponseData;
import org.apache.fineract.interoperation.data.InteropQuoteRequestData;
import org.apache.fineract.interoperation.data.InteropQuoteResponseData;
import org.apache.fineract.interoperation.data.InteropRequestData;
import org.apache.fineract.interoperation.data.InteropTransactionData;
import org.apache.fineract.interoperation.data.InteropTransactionRequestData;
import org.apache.fineract.interoperation.data.InteropTransactionRequestResponseData;
import org.apache.fineract.interoperation.data.InteropTransactionsData;
@@ -218,7 +219,27 @@ public class InteropServiceImpl implements InteropService {
return (transactionsTo == null || transactionsTo.compareTo(transactionDate) > 0) && (transactionsFrom == null
|| transactionsFrom.compareTo(transactionDate.withHour(23).withMinute(59).withSecond(59)) <= 0);
};
return InteropTransactionsData.build(savingsAccount, transFilter);
InteropTransactionsData interopTransactionsData = InteropTransactionsData.build(savingsAccount, transFilter);
for (InteropTransactionData interopTransactionData : interopTransactionsData.getTransactions()) {
final List<Note> transactionNotes = noteRepository
.findBySavingsTransactionId(Long.valueOf(interopTransactionData.getTransactionId()));
StringBuilder sb = new StringBuilder();
for (final Note note : transactionNotes) {
String s = note.getNote();
if (s == null) {
continue;
}
sb.append(s + " ");
}
if (sb.toString().length() > 0) {
String text = interopTransactionData.getNote() + " " + sb.toString();
if (text.length() > 500) {
text = text.substring(0, 500);
}
interopTransactionData.updateNote(text);
}
}
return interopTransactionsData;
}
@NotNull
@@ -40,6 +40,7 @@ import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.organisation.holiday.domain.Holiday;
import org.apache.fineract.organisation.holiday.domain.HolidayRepository;
import org.apache.fineract.organisation.holiday.domain.HolidayStatusType;
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
import org.apache.fineract.organisation.staff.domain.Staff;
import org.apache.fineract.organisation.staff.domain.StaffRepository;
import org.apache.fineract.organisation.staff.exception.StaffNotFoundException;
@@ -84,7 +85,6 @@ import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.apache.fineract.portfolio.rate.domain.Rate;
@@ -60,6 +60,7 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
@@ -126,7 +127,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultSche
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeApiJsonValidator;
import org.apache.fineract.portfolio.loanproduct.data.LoanOverdueDTO;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
import org.apache.fineract.portfolio.note.domain.Note;
import org.apache.fineract.portfolio.note.domain.NoteRepository;
@@ -40,6 +40,7 @@ import org.apache.fineract.infrastructure.entityaccess.service.FineractEntityAcc
import org.apache.fineract.infrastructure.event.business.domain.loan.product.LoanProductCreateBusinessEvent;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.charge.domain.Charge;
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
@@ -58,7 +59,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductCreditAllocationRule;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductPaymentAllocationRule;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductCannotBeModifiedDueToNonClosedLoansException;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductDateException;
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
@@ -26,6 +26,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificationExecutor<Note> {
@@ -46,4 +48,8 @@ public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificat
List<Note> findBySavingsAccount(SavingsAccount savingAccount);
Note findBySavingsAccountAndId(SavingsAccount savingAccount, Long id);
@Query("select note from Note note where note.savingsTransaction.id = :savingsTransactionId")
List<Note> findBySavingsTransactionId(@Param("savingsTransactionId") Long savingsTransactionId);
}
@@ -39,7 +39,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DataTableValidator;
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl;
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
@@ -66,7 +66,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
private final PlatformSecurityContext context;
private final GenericDataService genericDataService;
private final DatabaseSpecificSQLGenerator sqlGenerator;
private final ReadWriteNonCoreDataServiceImpl datatableService;
private final ReadWriteNonCoreDataService datatableService;
private final DataTableValidator dataTableValidator;
private final JdbcTemplate jdbcTemplate;
@@ -46,6 +46,7 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
import org.apache.fineract.portfolio.charge.domain.Charge;
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
@@ -54,7 +55,6 @@ import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
@@ -44,10 +44,10 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.charge.domain.Charge;
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
import org.apache.fineract.portfolio.shareproducts.data.ShareProductMarketPriceData;
import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
@@ -118,6 +118,24 @@
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationTypeListConverter</class>
<!-- Fineract Savings module -->
<class>org.apache.fineract.interoperation.domain.InteropIdentifier</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestIncentives</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestRateChart</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestRateChartSlab</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChart</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChartSlabs</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestIncentives</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransaction</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountTermAndPreClosure</class>
<class>org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProduct</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccount</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountCharge</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountChargePaidBy</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionTaxDetails</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsOfficerAssignmentHistory</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.weaving" value="static" />
+106
View File
@@ -0,0 +1,106 @@
/**
* 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.
*/
description = 'Fineract Savings'
apply plugin: 'java'
apply plugin: 'eclipse'
compileJava.doLast {
def mainSS = sourceSets.main
def source = mainSS.java.classesDirectory.get()
copy {
from file("src/main/resources/jpa/savings/persistence.xml")
into "${source}/META-INF/"
}
javaexec {
description = 'Performs EclipseLink static weaving of entity classes'
def target = source
main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
args '-persistenceinfo', source, source, target
classpath sourceSets.main.runtimeClasspath
}
delete {
delete "${source}/META-INF/persistence.xml"
}
}
// Configuration for Swagger documentation generation task
// https://github.com/swagger-api/swagger-core/tree/master/modules/swagger-gradle-plugin
import org.apache.tools.ant.filters.ReplaceTokens
configurations {
providedRuntime // needed for Spring Boot executable WAR
providedCompile
compile() {
exclude module: 'hibernate-entitymanager'
exclude module: 'hibernate-validator'
exclude module: 'activation'
exclude module: 'bcmail-jdk14'
exclude module: 'bcprov-jdk14'
exclude module: 'bctsp-jdk14'
exclude module: 'c3p0'
exclude module: 'stax-api'
exclude module: 'jaxb-api'
exclude module: 'jaxb-impl'
exclude module: 'jboss-logging'
exclude module: 'itext-rtf'
exclude module: 'classworlds'
}
runtime
}
apply from: 'dependencies.gradle'
// Configuration for the modernizer plugin
// https://github.com/andygoossens/gradle-modernizer-plugin
modernizer {
ignoreClassNamePatterns = [
'.*AbstractPersistableCustom',
'.*EntityTables',
'.*domain.*'
]
}
// If we are running Gradle within Eclipse to enhance classes with OpenJPA,
// set the classes directory to point to Eclipse's default build directory
if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') {
sourceSets.main.java.outputDir = new File(rootProject.projectDir, "fineract-savings/bin/main")
}
eclipse {
project {
buildCommand([ LaunchConfigHandle: "<project>/.externalToolBuilders/OpenJPA Enhance Builder.launch" ], 'org.eclipse.ui.externaltools.ExternalToolBuilder')
}
}
/* http://stackoverflow.com/questions/19653311/jpa-repository-works-in-idea-and-production-but-not-in-gradle */
sourceSets.main.output.resourcesDir = sourceSets.main.java.classesDirectory
sourceSets.test.output.resourcesDir = sourceSets.test.java.classesDirectory
if (!(project.hasProperty('env') && project.getProperty('env') == 'dev')) {
sourceSets {
test {
java {
exclude '**/core/boot/tests/**'
}
}
}
}
+74
View File
@@ -0,0 +1,74 @@
/**
* 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.
*/
dependencies {
// Never use "compile" scope, but make all dependencies either 'implementation', 'runtimeOnly' or 'testCompile'.
// Note that we never use 'api', because Fineract at least currently is a simple monolithic application ("WAR"), not a library.
// We also (normally should have) no need to ever use 'compileOnly'.
// implementation dependencies are directly used (compiled against) in src/main (and src/test)
//
implementation(project(path: ':fineract-core'))
implementation(
'org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-starter-security',
'jakarta.ws.rs:jakarta.ws.rs-api',
'org.glassfish.jersey.media:jersey-media-multipart',
'com.google.guava:guava',
'com.google.code.gson:gson',
'org.apache.commons:commons-lang3',
'com.jayway.jsonpath:json-path',
'com.github.spotbugs:spotbugs-annotations',
'io.swagger.core.v3:swagger-annotations-jakarta',
'com.squareup.retrofit2:converter-gson',
'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',
'io.github.resilience4j:resilience4j-spring-boot3',
'org.apache.httpcomponents:httpcore',
)
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.mapstruct:mapstruct-processor'
implementation ('org.springframework.boot:spring-boot-starter-data-jpa') {
exclude group: 'org.hibernate'
}
implementation('org.eclipse.persistence:org.eclipse.persistence.jpa') {
exclude group: 'org.eclipse.persistence', module: 'jakarta.persistence'
}
// testCompile dependencies are ONLY used in src/test, not src/main.
// Do NOT repeat dependencies which are ALREADY in implementation or runtimeOnly!
//
testImplementation( 'io.github.classgraph:classgraph' )
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'com.jayway.jsonpath', module: 'json-path'
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
exclude group: 'jakarta.activation'
exclude group: 'javax.activation'
exclude group: 'org.skyscreamer'
}
testImplementation ('org.mockito:mockito-inline')
}

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