Skip to content

Commit e3c708e

Browse files
authored
Merge branch 'apache:develop' into FINERACT-1152-fix-loan-reschedule-end-date-validation
2 parents ca80a71 + 7f3d40d commit e3c708e

342 files changed

Lines changed: 12353 additions & 2572 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,48 @@ Here's how to run the set of relatively fast and independent Fineract tests:
2626
This runs nearly 1,000 tests and completes in a few minutes on decent hardware.
2727
They shouldn't need any special servers/services running.
2828

29+
#### Cucumber E2E tests
30+
31+
The Cucumber E2E tests run against a live Fineract instance instead of starting one for you.
32+
Before running them locally, create the required databases and start Fineract:
33+
34+
```bash
35+
# Create required databases
36+
./gradlew createPGDB -PdbName=fineract_tenants
37+
./gradlew createPGDB -PdbName=fineract_default
38+
39+
# Start Fineract in another terminal
40+
./gradlew bootRun -Dspring.profiles.active=test
41+
```
42+
43+
The default E2E test connection settings live in `fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties`.
44+
By default, the test suite connects to `https://localhost:8443`.
45+
46+
Many E2E tests require seeded test data.
47+
That setup is controlled by the `INITIALIZATION_ENABLED` environment variable, which maps to `fineract-test.initialization.enabled`.
48+
For a fresh database, run the suite from `fineract-e2e-tests-runner` with initialization enabled first:
49+
50+
```bash
51+
cd fineract-e2e-tests-runner
52+
INITIALIZATION_ENABLED=true ../gradlew cucumber
53+
```
54+
55+
After the initialization data already exists, you can run all E2E tests without it:
56+
57+
```bash
58+
cd fineract-e2e-tests-runner
59+
../gradlew cucumber
60+
```
61+
62+
To run a single feature file:
63+
64+
```bash
65+
cd fineract-e2e-tests-runner
66+
../gradlew cucumber -Pcucumber.features="src/test/resources/features/Loan.feature"
67+
```
68+
69+
See [Cucumber E2E Tests](https://fineract.apache.org/docs/current/#testing-cucumber) for more details and additional options.
70+
2971
#### Integration tests
3072

3173
Running tests with external dependencies is a multi-step process with many moving parts.

LICENSE_RELEASE

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,18 @@
208208
======================================
209209

210210
All the source code for the Apache Fineract project is released under the
211-
license above. Additionally, the Apache Fineract source and binary
212-
distribution includes a number of third-party files that are required in
213-
order to the software to function. Unless noted below, these jars
214-
and resource files are also released under the ASF license above.
211+
license above. Additionally, the Apache Fineract source and binary distribution
212+
includes a number of third-party files that are required in order to the
213+
software to function. Unless noted below, these jars and resource files are
214+
also released under the Apache License, Version 2.0.
215215

216216
==================================================
217217
*The exceptions for binary release are as follows:
218218
==================================================
219219

220-
This product bundles third party jars and resource files that are
221-
released under other licenses than the ASF license. You can find
222-
details of all third party licenses in the directory "licenses".
220+
This product bundles third party jars and resource files that are released
221+
under licenses other than the Apache License, Version 2.0 following the ASF 3rd
222+
party license policy. You can find details of all third party licenses in the
223+
"licenses" directory (if the "generateLicenseReport" Gradle task has been run).
223224

224225
******************************************

LICENSE_SOURCE

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,10 @@
208208
======================================
209209

210210
All the source code for the Apache Fineract project is released under the
211-
license above. Additionally, the Apache Fineract source and binary
212-
distribution includes a number of third-party files that are required in
213-
order to the software to function. Unless noted below, these jars
214-
and resource files are also released under the ASF license above.
211+
license above. Additionally, the Apache Fineract source and binary distribution
212+
includes a number of third-party files that are required in order to the
213+
software to function. Unless noted below, these jars and resource files are
214+
also released under the Apache License, Version 2.0.
215215

216216
==================================================
217217
*The exceptions for source release are as follows:

README.md

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Apache Fineract
22

33
<!-- TODO Reactivate when there is a working CI-CD instance: [![Swagger Validation](https://validator.swagger.io/validator?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml)](https://validator.swagger.io/validator/debug?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml) -->
4-
[![Build](https://github.com/apache/fineract/actions/workflows/build-mariadb.yml/badge.svg?branch=develop)](https://github.com/apache/fineract/actions/workflows/build-mariadb.yml)
4+
[![Build](https://github.com/apache/fineract/actions/workflows/build-postgresql.yml/badge.svg?branch=develop)](https://github.com/apache/fineract/actions/workflows/build-postgresql.yml)
55
[![Docker Hub](https://img.shields.io/docker/pulls/apache/fineract.svg?logo=Docker)](https://hub.docker.com/r/apache/fineract)
66
[![Docker Build](https://github.com/apache/fineract/actions/workflows/publish-dockerhub.yml/badge.svg)](https://github.com/apache/fineract/actions/workflows/publish-dockerhub.yml)
77
[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=apache_fineract&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=apache_fineract)
@@ -29,11 +29,11 @@ In the moment you get started writing code, please consult our [CONTRIBUTING](CO
2929

3030
REQUIREMENTS
3131
============
32-
* min. 16GB RAM and 8 core CPU
33-
* `MariaDB >= 12.2` or `PostgreSQL >= 18.0`
34-
* `Java >= 21` (Azul Zulu JVM is tested by our CI on GitHub Actions)
32+
* 16GB RAM and 8 core CPU (minimum hardware for running Fineract -- development and testing may require more)
33+
* PostgreSQL >= 18.0 ([support for other backend databases is deprecated](https://cwiki.apache.org/confluence/display/FINERACT/FSIP-9%3A+Standardize+on+PostgreSQL))
34+
* Java >= 21 (Azul Zulu JVM is tested by our CI on GitHub Actions)
3535

36-
Tomcat (min. v10) is only required, if you wish to deploy the Fineract WAR to a separate external servlet container. You do not need to install Tomcat to run Fineract. We recommend the use of the self-contained JAR, which transparently embeds a servlet container using Spring Boot.
36+
Tomcat (min. v10) is only needed if you wish to deploy the Fineract WAR to a separate external servlet container. You do not need to install Tomcat to run Fineract. We recommend the use of the self-contained JAR, which transparently embeds a servlet container using Spring Boot.
3737

3838

3939
SECURITY
@@ -48,72 +48,73 @@ For details about security during development and deployment, see the documentat
4848
INSTRUCTIONS
4949
============
5050

51-
The following how-to's assume you have Java installed, you cloned the repository (or downloaded and extracted a [specific version](https://github.com/apache/fineract/releases)) and you have a [database server](#database-and-tables) (MariaDB or PostgreSQL) running.
52-
5351
Quick Start
5452
---
5553

56-
This section provides a simplified overview of the setup process. More detailed instructions are available below.
57-
58-
Follow these steps to quickly set up and run Apache Fineract locally:
54+
Follow these steps to quickly set up and run Apache Fineract locally.
5955

6056
### Prerequisites
61-
- Java 21 or higher
62-
- PostgreSQL or MariaDB running locally
6357

64-
### Clone the repository
58+
- Java 21 or higher (Azul Zulu is recommended)
59+
- PostgreSQL running locally, listening on port 5432 with proper permissions (see [below](#database-and-tables) for how to run PostgreSQL in Docker)
60+
6561
```bash
62+
# get code
6663
git clone https://github.com/apache/fineract.git
6764
cd fineract
68-
```
6965

70-
### Create databases
71-
```bash
72-
./gradlew createDB -PdbName=fineract_tenants
73-
./gradlew createDB -PdbName=fineract_default
74-
```
66+
# create dbs
67+
./gradlew createPGDB -PdbName=fineract_tenants
68+
./gradlew createPGDB -PdbName=fineract_default
7569

76-
### Run the application
77-
```bash
70+
# local dev/test env settings
71+
export FINERACT_DEFAULT_TENANTDB_PORT=5432
72+
export FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME=org.postgresql.Driver
73+
export FINERACT_HIKARI_JDBC_URL=jdbc:postgresql://localhost:$FINERACT_DEFAULT_TENANTDB_PORT/fineract_tenants
74+
export POSTGRES_PASSWORD=postgres
75+
export FINERACT_HIKARI_PASSWORD=$POSTGRES_PASSWORD
76+
export FINERACT_DEFAULT_TENANTDB_PWD=$POSTGRES_PASSWORD
77+
78+
# start backend
7879
./gradlew devRun
7980
```
8081

82+
After a minute or two, Fineract will be listening for API requests on port 8443 (by default).
83+
8184
### Verify the application is running
82-
```bash
83-
curl --insecure https://localhost:8443/fineract-provider/actuator/health
84-
```
8585

86-
How to run for local development
87-
---
86+
Confirm Fineract is ready with, for example:
8887

89-
Run the following commands in this order:
9088
```bash
91-
./gradlew createDB -PdbName=fineract_tenants
92-
./gradlew createDB -PdbName=fineract_default
93-
./gradlew devRun
89+
curl --insecure https://localhost:8443/fineract-provider/actuator/health
9490
```
9591

96-
This creates two databases and builds and runs Fineract, which will be listening for API requests on port 8443 (by default) now.
97-
98-
Confirm Fineract is ready with, for example:
92+
Expected response for fresh instance:
9993

100-
```bash
101-
curl --insecure https://localhost:8443/fineract-provider/actuator/health
94+
```json
95+
{"status":"UP","groups":["liveness","readiness"]}
10296
```
10397

10498
To test authenticated endpoints, include credentials in your request:
10599

106100
```bash
107-
curl --location \
101+
# basic auth header uses colon-delimited and base64-encoded default "mifos:password" login
102+
curl --location --insecure \
108103
https://localhost:8443/fineract-provider/api/v1/clients \
109104
--header 'Content-Type: application/json' \
110105
--header 'Fineract-Platform-TenantId: default' \
111106
--header 'Authorization: Basic bWlmb3M6cGFzc3dvcmQ='
112107
```
113108

109+
Expected response for fresh instance:
110+
111+
```json
112+
{"totalFilteredRecords":0,"pageItems":[]}
113+
```
114+
114115
How to run for production
115116
---
116-
Running Fineract to try it out is relatively easy. If you intend to use it in a production environment, be aware that a proper deployment can be complex, costly, and time-consuming. Considerations include: Security, privacy, compliance, performance, service availability, backups, and more. The Fineract project does not provide a comprehensive guide for deploying Fineract in production. You might need skills in enterprise Java applications and more. Alternatively, you could pay a vendor for Fineract deployment and maintenance. You will find tips and tricks for deploying and securing Fineract in our official documentation and in the community-maintained wiki.
117+
Running Fineract _just to try it out_ is relatively easy. If you intend to use it _in a production environment_, be aware that a proper deployment can be complex, costly, and time-consuming. Considerations include: Security, privacy, compliance, performance, service availability, backups, and more. **The Fineract project does not provide a comprehensive guide for deploying Fineract in production.** You might need skills in enterprise Java applications and more. Alternatively, you could pay a vendor for Fineract deployment and maintenance. You will find tips and tricks for [deploying](https://fineract.apache.org/docs/current/#_deployment) and [securing](https://fineract.apache.org/docs/current/#_securing_fineract) Fineract in our official documentation.
117118

118119

119120
How to build the JAR file
@@ -123,7 +124,7 @@ Build a modern, cloud native, fully self contained JAR file:
123124
./gradlew clean bootJar
124125
```
125126
The JAR will be created in the `fineract-provider/build/libs` directory.
126-
As we are not allowed to include a JDBC driver in the built JAR, download a JDBC driver of your choice. For example:
127+
If you use a MariaDB or MySQL (note: both are deprecated), you must download the appropriate JDBC driver since drivers for those databases use incompatible licenses. For example:
127128
```bash
128129
wget https://dlm.mariadb.com/4174416/Connectors/java/connector-java-3.5.2/mariadb-java-client-3.5.2.jar
129130
```
@@ -303,10 +304,10 @@ In case of a large deployment with millions of accounts, the Close of Business D
303304
JMS based messaging is disabled by default. In `docker-compose-postgresql-activemq.yml` an example is shown, where ActiveMQ is enabled. In that configuration one Spring Batch Manager instance and two Spring Batch Worker instances are created.
304305
Spring based events should be disabled and jms based event handling should be enabled. Furthermore, proper broker JMS URL should be configured.
305306

306-
```
307-
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=true
308-
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
309-
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_URL=tcp://activemq:61616
307+
```bash
308+
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=true
309+
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
310+
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_URL=tcp://activemq:61616
310311
```
311312

312313
For additional ActiveMQ related configuration please take a look to the `application.properties` where the supported configuration parameters are listed with their default values.
@@ -326,11 +327,21 @@ DATABASE AND TABLES
326327

327328
You can run the required version of the database server in a container, instead of having to install it, like this:
328329

329-
docker run --name mariadb-12.2 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:12.2.2 --innodb-snapshot-isolation=OFF
330+
```bash
331+
# start postgresql in background
332+
docker run --name postgres -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=postgres -u nobody:nogroup -d postgres:18.3
333+
# stop and destroy container
334+
docker rm -f postgres
335+
```
330336

331-
and stop and destroy it like this:
337+
Similarly, for one of the [deprecated](https://cwiki.apache.org/confluence/display/FINERACT/FSIP-9%3A+Standardize+on+PostgreSQL) database backends:
332338

333-
docker rm -f mariadb-12.2
339+
```bash
340+
# start mariadb in background
341+
docker run --name mariadb-12.2 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:12.2.2 --innodb-snapshot-isolation=OFF
342+
# stop and destroy container
343+
docker rm -f mariadb-12.2
344+
```
334345

335346
Beware that this container database keeps its state inside the container and not on the host filesystem. It is lost when you destroy (rm) this container. This is typically fine for development. See [Caveats: Where to Store Data on the database container documentation](https://hub.docker.com/_/mariadb) regarding how to make it persistent instead of ephemeral.
336347

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ cyclonedxBom {
917917

918918
tasks.withType(org.cyclonedx.gradle.CyclonedxDirectTask).configureEach {
919919
includeMetadataResolution.set(false)
920+
skipConfigs.set(['.*eclipse.*', '.*swt.*'])
920921
}
921922

922923
tasks.register('printSourceSetInformation') {

fineract-accounting/src/main/java/org/apache/fineract/accounting/closure/api/GLClosuresApiResource.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ public class GLClosuresApiResource {
8080
private final OfficeReadPlatformService officeReadPlatformService;
8181

8282
@GET
83-
@Consumes({ MediaType.APPLICATION_JSON })
8483
@Produces({ MediaType.APPLICATION_JSON })
8584
@Operation(summary = "List Accounting closures", description = """
8685
Example Requests:
@@ -95,7 +94,6 @@ public List<GLClosureData> retrieveAllClosures(@QueryParam("officeId") @Paramete
9594

9695
@GET
9796
@Path("{glClosureId}")
98-
@Consumes({ MediaType.APPLICATION_JSON })
9997
@Produces({ MediaType.APPLICATION_JSON })
10098
@Operation(summary = "Retrieve an Accounting Closure", description = """
10199
Example Requests:
@@ -148,7 +146,6 @@ public CommandProcessingResult updateGLClosure(@PathParam("glClosureId") @Parame
148146

149147
@DELETE
150148
@Path("{glClosureId}")
151-
@Consumes({ MediaType.APPLICATION_JSON })
152149
@Produces({ MediaType.APPLICATION_JSON })
153150
@Operation(summary = "Delete an accounting closure", description = "Note: Only the latest accounting closure associated with a branch may be deleted.")
154151
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.DeleteGlClosuresResponse.class)))

fineract-accounting/src/main/java/org/apache/fineract/accounting/financialactivityaccount/api/FinancialActivityAccountsApiResource.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,13 @@ public class FinancialActivityAccountsApiResource {
7676

7777
@GET
7878
@Path("template")
79-
@Consumes({ MediaType.APPLICATION_JSON })
8079
@Produces({ MediaType.APPLICATION_JSON })
8180
public FinancialActivityAccountData retrieveTemplate() {
8281
context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.RESOURCE_NAME_FOR_PERMISSION);
8382
return financialActivityAccountReadPlatformService.getFinancialActivityAccountTemplate();
8483
}
8584

8685
@GET
87-
@Consumes({ MediaType.APPLICATION_JSON })
8886
@Produces({ MediaType.APPLICATION_JSON })
8987
@Operation(summary = "List Financial Activities to Accounts Mappings", description = """
9088
Example Requests:
@@ -97,7 +95,6 @@ public List<FinancialActivityAccountData> retrieveAll() {
9795

9896
@GET
9997
@Path("{mappingId}")
100-
@Consumes({ MediaType.APPLICATION_JSON })
10198
@Produces({ MediaType.APPLICATION_JSON })
10299
@Operation(summary = "Retrieve a Financial Activity to Account Mapping\n", description = """
103100
Example Requests:
@@ -148,7 +145,6 @@ public CommandProcessingResult updateGLAccount(@PathParam("mappingId") @Paramete
148145

149146
@DELETE
150147
@Path("{mappingId}")
151-
@Consumes({ MediaType.APPLICATION_JSON })
152148
@Produces({ MediaType.APPLICATION_JSON })
153149
@Operation(summary = "Delete a Financial Activity to Account Mapping", operationId = "deleteGLAccountMappingFinancialActivityAccount")
154150
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.DeleteFinancialActivityAccountsResponse.class)))

fineract-accounting/src/main/java/org/apache/fineract/accounting/glaccount/api/GLAccountsApiResource.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ public class GLAccountsApiResource {
9292

9393
@GET
9494
@Path("template")
95-
@Consumes({ MediaType.APPLICATION_JSON })
9695
@Produces({ MediaType.APPLICATION_JSON })
9796
@Operation(tags = {
9897
"General Ledger Account" }, summary = "Retrieve GL Accounts Template", description = """
@@ -122,7 +121,6 @@ public GLAccountData retrieveNewAccountDetails(@QueryParam("type") @Parameter(de
122121
}
123122

124123
@GET
125-
@Consumes({ MediaType.APPLICATION_JSON })
126124
@Produces({ MediaType.APPLICATION_JSON })
127125
@Operation(tags = {
128126
"General Ledger Account" }, summary = "List General Ledger Account", description = """
@@ -153,7 +151,6 @@ public List<GLAccountData> retrieveAllAccounts(@QueryParam("type") @Parameter(de
153151

154152
@GET
155153
@Path("{glAccountId}")
156-
@Consumes({ MediaType.APPLICATION_JSON })
157154
@Produces({ MediaType.APPLICATION_JSON })
158155
@Operation(tags = { "General Ledger Account" }, summary = "Retrieve a General Ledger Account", description = """
159156
Example Requests:
@@ -212,7 +209,6 @@ public CommandProcessingResult updateGLAccount(@PathParam("glAccountId") @Parame
212209

213210
@DELETE
214211
@Path("{glAccountId}")
215-
@Consumes({ MediaType.APPLICATION_JSON })
216212
@Produces({ MediaType.APPLICATION_JSON })
217213
@Operation(tags = {
218214
"General Ledger Account" }, summary = "Delete a GL Account", operationId = "deleteGLAccount", description = "Deletes a GL Account")

fineract-accounting/src/main/java/org/apache/fineract/accounting/glaccount/exception/GLAccountInvalidUpdateException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public enum GlAccountInvalidUpdateReason {
3232

3333
public String errorMessage() {
3434
if (name().equalsIgnoreCase("TRANSANCTIONS_LOGGED")) {
35-
return "This Usage of this (detail) GL Account as it already has transactions logged against it";
35+
return "This (detail) GL Account cannot be updated as it already has transactions logged against it";
3636
}
3737
return name();
3838
}

fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ private List<ClassificationToGLAccountData> fetchClassificationMappings(final Po
312312
: productToGLAccountMappingRepository.findAllBuyDownFeeClassificationsMappings(loanProductId,
313313
portfolioProductType.getValue());
314314

315-
productToGLAccountMappingRepository.findAllChargeOffReasonsMappings(loanProductId, portfolioProductType.getValue());
316315
List<ClassificationToGLAccountData> classificationToGLAccountMappers = mappings.isEmpty() ? null : new ArrayList<>();
317316
for (final ProductToGLAccountMapping mapping : mappings) {
318317
final Long glAccountId = mapping.getGlAccount().getId();

0 commit comments

Comments
 (0)