niteshandClaude Sonnet 5 46f5a1babd
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
feat(deposits): FD in-place renewal, senior-citizen rate persistence, and Payment action
WHAT THIS CHANGES
==================
Three related FD (Fixed Deposit) features, built incrementally in one session:

1. IN-PLACE RENEWAL -- when an FD matures with "Re-Invest Principal and
   Interest", the SAME m_savings_account row is now reused across every
   renewal (account number never changes) instead of closing the account
   and opening a new one. FixedDepositAccount.renewInPlace() does this by
   setting start_interest_calculation_date as a pivot: interest for terms
   before the pivot is never recalculated, only the new term's window is
   computed from there. A new one-to-many audit table m_fd_renewal_history
   records one row per term (renewal_no 0,1,2...) with that term's own
   principal, rate, dates, interest earned, maturity, and status. A
   companion table m_fd_renewal_chart_slab_history archives each closing
   term's full rate-by-tenure chart, captured just before renewInPlace
   overwrites it.

2. SENIOR-CITIZEN RATE -- the CBS Base Interest Rate master
   (m_cbs_base_interest_rate_slab_history) was the only place that ever
   stored a senior-citizen premium. It is now also persisted on
   m_savings_account_interest_rate_slab (new senior_citizen_rate column,
   nullable, added only to this account-level table -- NOT to the shared
   InterestRateChartSlabFields embeddable, so the product-level table
   m_interest_rate_slab is untouched). Applied both at account creation
   (DepositAccountAssembler now prices a new FD off the active CBS base
   version when one exists for that FD type, falling back to the
   product's own chart otherwise) and at renewal (renewInPlace refreshes
   the chart from the same base version).

3. PAYMENT ACTION -- a new manual command, POST
   /fixeddepositaccounts/{id}?command=payment, available whether the FD
   is ACTIVE or MATURED, unlike Close (Matured-only) and Premature Close
   (Active-only, no reinvest). Offers: Transfer to Savings, Re-Invest
   Principal and Interest (via renewInPlace), Re-Invest Principal Only
   (legacy close-and-reopen, now also transfers the leftover interest to
   a chosen savings account instead of stranding it), and a new closure
   type PARTIAL_REINVEST (500) -- part of the matured balance renews in
   place on the same account, the remainder transfers to a savings
   account picked at request time. Withdraw Deposit is deliberately
   excluded from this command. New permission PAYMENT_FIXEDDEPOSITACCOUNT
   plus its CHECKER twin were added in migration 0478.

KEY FILES
=========
- DepositAccountDomainServiceJpa.java: handleFDAccountPayment (new),
  renewInPlace call sites, recordInPlaceRenewal, senior-citizen rate
  matching with unit conversion across days/weeks and months/years
  families.
- FixedDepositAccount.java: renewInPlace, validateRenewalDate,
  isLockedOnDate, fdAccountNumber/renewalCycleNo chain tracking.
- SavingsAccount.java (SHARED with Savings and RD): added
  findLastTransactionBefore -- the interest-posting opening balance for a
  pivot-dated account now seeds from the last transaction strictly before
  the pivot, not the one on it. This fixes a bug where a renewed term
  could accrue zero interest, or double-subtract a same-day withdrawal,
  depending on transaction list order. Also widened
  calculateDateAccountIsLockedUntil to protected so renewInPlace can
  refresh lock-in on each renewed term.
- DepositAccountTransactionDataValidator.java: new validatePayment.
  validateClosing now explicitly rejects PARTIAL_REINVEST (500) so it can
  never reach the Close or Premature-Close handlers, which have no branch
  for it and would otherwise pay the whole balance out in cash. This
  applies to both FD and RD, since they share validateClosing.
- DepositAccountReadPlatformServiceImpl.java: retrieveOneWithClosureTemplate
  (Close and Premature Close, excludes PARTIAL_REINVEST) split from the
  new retrieveOneWithPaymentTemplate (Payment, includes it), sharing one
  private method with a flag. The renewal-history fallback query, for
  chains that predate m_fd_renewal_history, was rewritten to emit the
  exact same column shape as the primary query.
- New: FixedDepositRenewalHistory plus its repository,
  FixedDepositRenewalChartSlabHistory plus its repository,
  PaymentFixedDepositAccountCommandHandler.
- Migrations 0471 through 0478 under tenant/parts, each registered once
  in changelog-tenant.xml.

RD AND SAVINGS IMPACT -- READ THIS IF SOMETHING BREAKS THERE
============================================================
RD and plain Savings share several of the touched files. Verified during
this work:
  - handleRDAccountClosure and RecurringDepositAccount.java were not
    modified.
  - PARTIAL_REINVEST (500) is now rejected by validateClosing for both FD
    and RD close and prematureClose commands, and excluded from their
    template option lists. This was a real regression caught mid-session:
    the enum value briefly leaked into RD's Close dropdown as a working
    looking option that actually paid the whole RD balance out in cash.
    It was found and fixed before this commit.
  - The SavingsAccount.calculateInterestUsing opening-balance change only
    affects accounts where start_interest_calculation_date differs from
    activatedon_date. On the dev DB this was exactly two accounts, both
    FD test accounts created this session. Before deploying, run:
      SELECT deposit_type_enum, COUNT(*) FROM m_savings_account
      WHERE start_interest_calculation_date IS NOT NULL
        AND start_interest_calculation_date <> activatedon_date
      GROUP BY deposit_type_enum;
    Any non-FD rows (100 or 300) there mean a Savings or RD account will
    get a different, corrected interest amount than before. This is
    expected to be rare or zero, but confirm before deploy.
  - DepositAccountAssembler's creation-time base-rate pricing is guarded
    by depositAccountType.isFixedDeposit, so RD account creation is
    unaffected.
  - is_active on InterestRateChart (migration 0474) is read only by
    FixedDepositProduct.activeChart, which only FD's renewInPlace and
    reInvest call. RD's applicableChart path is untouched. Migration 0474
    also retires (is_active = false) any chart whose end_date is already
    past. On the dev DB this retired zero rows; check on the target DB
    before deploy, since there is currently no API to reactivate a
    retired chart.

KNOWN CAVEATS -- NOT YET DONE, FLAGGING RATHER THAN HIDING
============================================================
  - Migrations 0471 through 0477, the DDL ones, have never actually
    executed via Liquibase. They were mirrored by hand directly into the
    dev DB (ADD COLUMN IF NOT EXISTS, CREATE TABLE IF NOT EXISTS) so
    testing could proceed without a full rebuild each time. Liquibase
    will mark them MARK_RAN via preConditions on the dev DB's next real
    run, but their first genuine execution will be on whatever
    environment does not already have these columns and tables, such as
    a fresh QA or production database. Test a migration-from-scratch run
    before relying on this in production.
  - This code has not been compiled. Every new or changed method
    signature, import, and call site was manually cross-checked with
    grep against real declarations, but that is not a substitute for
    gradle actually compiling it. Run a full build before deploying and
    treat any compiler error as expected until confirmed clean.
  - DepositAccountAssembler pricing every new FD off the active CBS base
    rate master, instead of the product's own chart, whenever one exists
    is a real behaviour change affecting all new FD accounts of a type
    that has a base-rate version, not just senior-citizen ones. Flagging
    this for explicit product sign-off, not assuming it in this commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 16:44:11 +05:30
@
2026-06-01 12:18:30 +05:30
2026-04-13 13:26:33 +05:30
2025-12-18 14:37:59 -08:00
2026-04-13 13:26:33 +05:30
2020-10-19 16:18:13 +03:00
2026-04-13 13:26:33 +05:30
2024-02-06 16:00:31 +01:00
2026-04-13 13:26:33 +05:30
2025-12-18 10:27:14 -08:00
2025-12-18 10:27:14 -08:00
2026-07-28 10:43:06 +05:30
2026-04-13 13:26:33 +05:30

Apache Fineract

Build Docker Hub Docker Build Technical Debt Verified DPG

Apache Fineract is an open-source core banking platform providing a flexible, extensible foundation for a wide range of financial services. By making robust banking technology openly available, it lowers barriers for institutions and innovators to reach underserved and unbanked populations.

Have a look at the documentation, the wiki or at the FAQ, if this README does not answer what you are looking for.

COMMUNITY

If you are interested in contributing to this project, but perhaps don't quite know how and where to get started, please join our developer mailing list, listen into our conversations, chime into threads, or just send us a "Hello!" introduction email; we're a friendly bunch, and look forward to hearing from you. A more informal alternative is the Fineract Slack channel (thank you, Mifos, for supporting the Slack channel!).

For the developer wiki, see Contributor's Zone. Maybe these how-to articles help you to get started.

In any case visit our JIRA Dashboard to find issues to work on, see what others are doing, or open new issues.

In the moment you get started writing code, please consult our CONTRIBUTING guidelines, where you will find more information on subjects like coding style, testing and pull requests.

REQUIREMENTS

  • min. 16GB RAM and 8 core CPU
  • MariaDB >= 11.5.2 or PostgreSQL >= 17.0
  • Java >= 21 (Azul Zulu JVM is tested by our CI on GitHub Actions)

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.

SECURITY

For a list of known vulnerabilities, see Apache Fineract Security Reports.

If you believe you have found a new vulnerability, let us know privately.

For details about security during development and deployment, see the documentation here.

INSTRUCTIONS

The following how-to's assume you have Java installed, you cloned the repository (or downloaded and extracted a specific version) and you have a database server (MariaDB or PostgreSQL) running.

How to run for local development

Run the following commands in this order:

./gradlew createDB -PdbName=fineract_tenants
./gradlew createDB -PdbName=fineract_default
./gradlew devRun

This creates two databases and builds and runs Fineract, which will be listening for API requests on port 8443 (by default) now.

Confirm Fineract is ready with, for example:

curl --insecure https://localhost:8443/fineract-provider/actuator/health

To test authenticated endpoints, include credentials in your request:

curl --location \
  https://localhost:8443/fineract-provider/api/v1/clients \
  --header 'Content-Type: application/json' \
  --header 'Fineract-Platform-TenantId: default' \
  --header 'Authorization: Basic bWlmb3M6cGFzc3dvcmQ='

How to run for production

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.

How to build the JAR file

Build a modern, cloud native, fully self contained JAR file:

./gradlew clean bootJar

The JAR will be created in the fineract-provider/build/libs directory. As we are not allowed to include a JDBC driver in the built JAR, download a JDBC driver of your choice. For example:

wget https://dlm.mariadb.com/4174416/Connectors/java/connector-java-3.5.2/mariadb-java-client-3.5.2.jar

Start the JAR and specify the directory containing the JDBC driver using the loader.path option, for example:

java -Dloader.path=. -jar fineract-provider/build/libs/fineract-provider.jar

This does not require an external Tomcat.

The tenants database connection details are configured via environment variables (as with Docker container), e.g. like this:

export FINERACT_HIKARI_PASSWORD=verysecret
...
java -jar fineract-provider.jar

How to build the WAR file

Build a traditional WAR file:

./gradlew :fineract-war:clean :fineract-war:war

The WAR will be created in the fineract-war/build/libs directory. Afterwards deploy the WAR to your Tomcat Servlet Container.

We recommend using the JAR instead of the WAR file deployment, because it's much easier.

How to run using Docker or Podman

It is possible to do a 'one-touch' installation of Fineract using containers (AKA "Docker"). This includes the database running in the container.

As prerequisites, you must have docker and docker-compose installed on your machine; see Docker Install and Docker Compose Install.

Alternatively, you can also use Podman (e.g. via dnf install podman-docker), and Podman Compose (e.g. via pip3 install podman-compose) instead of Docker.

To run a new Fineract instance on Linux you can simply:

git clone https://github.com/apache/fineract.git
cd fineract
./gradlew :fineract-provider:jibDockerBuild -x test

On Windows, do this instead:

git clone https://github.com/apache/fineract.git --config core.autocrlf=input
cd fineract
gradlew :fineract-provider:jibDockerBuild -x test

Install the Loki log driver and start:

docker plugin install grafana/loki-docker-driver:latest \
  --alias loki --grant-all-permissions
docker compose -f docker-compose-development.yml up -d

The Fineract (back-end) should be running at https://localhost:8443/fineract-provider/ now. Wait for https://localhost:8443/fineract-provider/actuator/health to return {"status":"UP"}. You must go to https://localhost:8443 and remember to accept the self-signed SSL certificate of the API once in your browser.

Docker Hub has a pre-built container image of this project, built continuously.

You must specify the MySQL tenants database JDBC URL by passing it to the fineract container via environment variables; please consult the docker-compose.yml for exact details how to specify those.

The logfiles and the Java Flight Recorder output are available in PROJECT_ROOT/build/fineract/logs. If you use IntelliJ then you can double-click on the .jfr file and open it with the IDE. You can also download Azul Mission Control to analyze the Java Flight Recorder file.

NOTE: If you have issues with the file permissions and Docker Compose then you might need to change the variable values for FINERACT_USER and FINERACT_GROUP in PROJECT_ROOT/config/docker/env/fineract-common.env. You can find out what values you need to put there with the following commands:

id -u ${USER}
id -g ${GROUP}

Please make sure that you are not checking in your changed values. The defaults should work for most people.

How to run on Kubernetes

General Clusters

You can also run Fineract using containers on a Kubernetes cluster. Make sure you set up and connect to your Kubernetes cluster. You can follow this guide to set up a Kubernetes cluster on GKE. Make sure to replace apache-fineract-cn with apache-fineract

Now e.g. from your Google Cloud shell, run the following commands:

git clone https://github.com/apache/fineract.git
cd fineract/kubernetes
./kubectl-startup.sh

To shutdown and reset your Cluster, run:

./kubectl-shutdown.sh

Using Minikube

Alternatively, you can run fineract on a local kubernetes cluster using minikube. As prerequisite you must have minikube and kubectl installed on your machine; see Minikube & Kubectl install.

To run a new Fineract instance on Minikube you can simply:

git clone https://github.com/apache/fineract.git
cd fineract/kubernetes
minikube start
./kubectl-startup.sh

Wait for all pods to be ready:

kubectl get pods -w

Once all pods are running, access the Mifos web application:

minikube service mifos-community

This opens the Mifos X web application in your browser. The nginx reverse proxy in the mifos-community pod forwards API requests to the fineract-server backend.

Default credentials:

  • Username: mifos
  • Password: password

You can also access the Fineract API directly:

minikube service fineract-server --url --https

Fineract is now running at the printed URL, which you can check e.g. using:

http --verify=no --timeout 240 --check-status get $(minikube service fineract-server --url --https)/fineract-provider/actuator/health

To check the status of your containers on your local minikube Kubernetes cluster, run:

minikube dashboard

You can check Fineract logs using:

kubectl logs deployment/fineract-server

You can check Mifos web app logs using:

kubectl logs deployment/mifos-community

To shutdown and reset your cluster, run:

./kubectl-shutdown.sh

How to enable External Message Broker (ActiveMQ or Apache Kafka)

There are two use-cases where external message broker is needed:

  • External Business Events / Reliable Event Framework
  • Executing Partitioned Spring Batch Jobs

External Events are business events, e.g.: ClientCreated, which might be important for third party systems. Apache Fineract supports ActiveMQ (or other JMS compliant brokers) and Apache Kafka endpoints for sending out Business Events. By default, they are not emitted.

In case of a large deployment with millions of accounts, the Close of Business Day Spring Batch job may run several hours. In order to speed up this task, remote partitioning of the job is supported. The Manager node partitions breaks up the COB job into smaller pieces (sub tasks), which then can be executed on multiple Worker nodes in parallel. The worker nodes are notified either by ActiveMQ or Kafka regarding their new sub tasks.

ActiveMQ

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. Spring based events should be disabled and jms based event handling should be enabled. Furthermore, proper broker JMS URL should be configured.

      FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=true
      FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
      FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_URL=tcp://activemq:61616

For additional ActiveMQ related configuration please take a look to the application.properties where the supported configuration parameters are listed with their default values.

Kafka

Kafka support is also disabled by default. In docker-compose-postgresql-kafka.yml an example is shown, where self-hosted Kafka is enabled for both External Events and Spring Batch Remote Job execution.

During the development Fineract was tested with PLAINTEXT Kafka brokers without authentication and with AWS MSK using IAM authentication. The extra JAR file required for IAM authentication is already added to the classpath. An example MSK setup can be found in docker-compose-postgresql-kafka-msk.yml.

The full list of supported Kafka related properties is documented in the Fineract Platform documentation.

DATABASE AND TABLES

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

docker run --name mariadb-11.5 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:11.5.2

and stop and destroy it like this:

docker rm -f mariadb-11.5

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 regarding how to make it persistent instead of ephemeral.

MySQL/MariaDB and UTC timezone

With release 1.8.0 we introduced improved date time handling in Fineract. Date time is stored in UTC, and UTC timezone enforced even on the JDBC driver, e. g. for MySQL:

serverTimezone=UTC&useLegacyDatetimeCode=false&sessionVariables=time_zone='-00:00'

If you use MySQL as Fineract database, the following configuration is highly recommended:

  • Run the application in UTC (the default command line in our Docker image has the necessary parameters already set)
  • Run the MySQL database server in UTC (if you use managed services like AWS RDS, then this should be the default anyway, but it would be good to double-check)

In case Fineract and MySQL do not run in UTC, MySQL might save date time values differently from PostgreSQL

Example scenario: If the Fineract instance runs in timezone: GMT+2, and the local date time is 2022-08-11 17:15 ...

  • ... then PostgreSQL saves the LocalDateTime as is: 2022-08-11 17:15
  • ... and MySQL saves the LocalDateTime in UTC: 2022-08-11 15:15
  • ... but when we read the date time from PostgreSQL or from MySQL, both systems give us the same value: 2022-08-11 17:15 GMT+2

If a previously used Fineract instance didn't run in UTC (backward compatibility), all prior dates will be read wrongly by MySQL. This can cause issues, when you run the database migration scripts.

Recommendation: Shift all dates in your database by the timezone offset that your Fineract instance used.

CONNECTION POOL CONFIGURATION

Please check application.properties to see which connection pool settings can be tweaked. The associated environment variables are prefixed with FINERACT_HIKARI_*. You can find more information about specific connection pool settings at the HikariCP Github repository.

NOTE: We keep backwards compatibility until one of the next releases to ensure that things are working as expected. Environment variables prefixed fineract_tenants_* can still be used to configure the database connection, but we strongly encourage using FINERACT_HIKARI_* with more options.

RELEASES

Official releases are created quarterly, at the end of each quarter. Our documented release procedure follows the ASF release policy.

See https://cwiki.apache.org/confluence/display/FINERACT/Fineract+Releases for an archive of historical release notes along with JIRA issues relevant to each release.

See https://github.com/apache/fineract/releases for a list of PRs and contributors for each release.

EOL/unsupported releases are archived.

Versioned build products created from the develop branch will include -SNAPSHOT. See related settings near version and gitVersioning in build.gradle for details.

LICENSE

This project is licensed under Apache License Version 2.0.

The Connector/J JDBC Driver client library from MariaDB is licensed under the LGPL. The library is often used in development when running integration tests that use the Liquibase library. That JDBC driver is however not distributed with the Fineract product and is not required to use the product. If you are a developer and object to using the LGPL licensed Connector/J JDBC driver, simply do not run the integration tests that use the Liquibase library and use another JDBC driver. As discussed in LEGAL-462, this project therefore complies with the Apache Software Foundation third-party license policy.

PLATFORM API

Fineract does not provide a UI, but provides an API. Running Fineract locally, the Swagger documentation can be accessed under https://localhost:8443/fineract-provider/swagger-ui/index.html. A live version can be accessed via this Sandbox (not hosted by us).

Apache Fineract supports client code generation using Swagger Codegen based on the OpenAPI Specification. For more instructions on how to generate client code, check this section of the Fineract documentation. This video documents the use of the Swagger-UI.

S
Description
No description provided
Readme
159 MiB
Languages
Java 68.6%
Gherkin 28.6%
HTML 2.5%