Compare commits
500
Commits
@@ -0,0 +1,17 @@
|
||||
github:
|
||||
description: "Apache Fineract"
|
||||
homepage: https://fineract.apache.org
|
||||
labels:
|
||||
- apache
|
||||
- banking
|
||||
- finance
|
||||
- fintech
|
||||
- group-lending
|
||||
- group-savings
|
||||
- java
|
||||
- lending
|
||||
- loans
|
||||
- microfinance
|
||||
- savings
|
||||
- social-impact
|
||||
- tech4good
|
||||
@@ -1,35 +1,31 @@
|
||||
name: Fineract Docker build - MariaDB
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
IMAGE_NAME: fineract
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build the image
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber
|
||||
- name: Start the stack
|
||||
run: docker compose up -d
|
||||
- name: Wait for stack to come up
|
||||
run: sleep 500
|
||||
run: docker compose -f docker-compose.yml up -d
|
||||
- name: Check the stack
|
||||
run: docker ps
|
||||
- name: Check health
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
- name: Check info
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
name: Fineract Docker build - PostgreSQL
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
IMAGE_NAME: fineract
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build the image
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber
|
||||
- name: Start the Standalone Stack
|
||||
run: docker compose -f docker-compose-postgresql.yml up -d
|
||||
- name: Wait for stack to come up
|
||||
run: sleep 500
|
||||
- name: Check the stack
|
||||
run: docker ps
|
||||
- name: Check health
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
- name: Check info
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
name: Fineract Documentation build
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Congfigure vega-cli
|
||||
run: npm i -g vega-cli --unsafe
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142
|
||||
uses: gradle/wrapper-validation-action@f9c9c575b8b21b6485636a91ffecd10e558c62f6
|
||||
- name: Install additional software
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ghostscript graphviz -y
|
||||
|
||||
- name: Documentation build
|
||||
run: ./gradlew --no-daemon --console=plain doc
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Fineract Build Progressive Loan Embeddable Jar & Test with a Sample Application
|
||||
on: [push, pull_request]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build Embeddable Jar
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:shadowJar
|
||||
- name: Pick up the JAR filename
|
||||
run: |
|
||||
EMBEDDABLE_JAR_FILE=(`ls fineract-progressive-loan-embeddable-schedule-generator/build/libs/*-all.jar | head -n 1`)
|
||||
echo "EMBEDDABLE_JAR_FILE=$EMBEDDABLE_JAR_FILE" >> $GITHUB_ENV
|
||||
- name: Run unit tests
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:test
|
||||
- name: Build Sample Application
|
||||
run: |
|
||||
mkdir sample-app
|
||||
javac -cp $EMBEDDABLE_JAR_FILE -d sample-app fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java
|
||||
env:
|
||||
EMBEDDABLE_JAR_FILE: ${{ env.EMBEDDABLE_JAR_FILE }}
|
||||
- name: Run Schedule Generator Sample Application
|
||||
run: |
|
||||
java -cp $EMBEDDABLE_JAR_FILE:sample-app Main
|
||||
java -cp $EMBEDDABLE_JAR_FILE:sample-app Main 25
|
||||
env:
|
||||
EMBEDDABLE_JAR_FILE: ${{ env.EMBEDDABLE_JAR_FILE }}
|
||||
- name: Archive test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
build/reports/
|
||||
fineract-progressive-loan-embeddable-schedule-generator/build/reports/
|
||||
@@ -1,51 +1,42 @@
|
||||
name: Fineract Build & Test - MariaDB
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
services:
|
||||
mariad:
|
||||
image: mariadb:11.2
|
||||
image: mariadb:11.5.2
|
||||
ports:
|
||||
- 3306:3306
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: mysql
|
||||
options: --health-cmd="healthcheck.sh --su-mysql --connect --innodb_initialized" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
mock-oauth2-server:
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.1
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.10
|
||||
ports:
|
||||
- 9000:9000
|
||||
env:
|
||||
SERVER_PORT: 9000
|
||||
JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": "NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", "tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": "fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'
|
||||
|
||||
env:
|
||||
TZ: Asia/Kolkata
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
|
||||
- name: Setup Gradle and Validate Wrapper
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Congfigure vega-cli
|
||||
run: npm i -g vega-cli --unsafe
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142
|
||||
validate-wrappers: true
|
||||
- name: Verify MariaDB connection
|
||||
run: |
|
||||
while ! mysqladmin ping -h"127.0.0.1" -P3306 ; do
|
||||
@@ -66,11 +57,6 @@ jobs:
|
||||
sleep 10
|
||||
docker exec localstack awslocal s3api create-bucket --bucket fineract-reports
|
||||
echo "LocalStack initialization complete"
|
||||
- name: Install additional software
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ghostscript graphviz -y
|
||||
|
||||
- name: Build & Test
|
||||
env:
|
||||
AWS_ENDPOINT_URL: http://localhost:4566
|
||||
@@ -85,10 +71,9 @@ jobs:
|
||||
./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -x :fineract-e2e-tests-runner:test
|
||||
./gradlew --no-daemon --console=plain :twofactor-tests:test
|
||||
./gradlew --no-daemon --console=plain :oauth2-tests:test
|
||||
|
||||
- name: Archive test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
@@ -96,10 +81,9 @@ jobs:
|
||||
integration-tests/build/reports/
|
||||
twofactor-tests/build/reports/
|
||||
oauth2-tests/build/reports/
|
||||
|
||||
- name: Archive server logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: server-logs
|
||||
path: |
|
||||
|
||||
@@ -1,51 +1,42 @@
|
||||
name: Fineract Build & Test - MySQL
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
services:
|
||||
mariad:
|
||||
image: mysql:8.3
|
||||
image: mysql:9.1
|
||||
ports:
|
||||
- 3306:3306
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: mysql
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
mock-oauth2-server:
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.1
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.10
|
||||
ports:
|
||||
- 9000:9000
|
||||
env:
|
||||
SERVER_PORT: 9000
|
||||
JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": "NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", "tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": "fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'
|
||||
|
||||
env:
|
||||
TZ: Asia/Kolkata
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
|
||||
- name: Setup Gradle and Validate Wrapper
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Congfigure vega-cli
|
||||
run: npm i -g vega-cli --unsafe
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142
|
||||
validate-wrappers: true
|
||||
- name: Verify MariaDB connection
|
||||
run: |
|
||||
while ! mysqladmin ping -h"127.0.0.1" -P3306 ; do
|
||||
@@ -66,11 +57,6 @@ jobs:
|
||||
sleep 10
|
||||
docker exec localstack awslocal s3api create-bucket --bucket fineract-reports
|
||||
echo "LocalStack initialization complete"
|
||||
- name: Install additional software
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ghostscript graphviz -y
|
||||
|
||||
- name: Build & Test
|
||||
env:
|
||||
AWS_ENDPOINT_URL: http://localhost:4566
|
||||
@@ -85,10 +71,9 @@ jobs:
|
||||
./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test -PdbType=mysql
|
||||
./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=mysql
|
||||
./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=mysql
|
||||
|
||||
- name: Archive test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
@@ -96,10 +81,9 @@ jobs:
|
||||
integration-tests/build/reports/
|
||||
twofactor-tests/build/reports/
|
||||
oauth2-tests/build/reports/
|
||||
|
||||
- name: Archive server logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: server-logs
|
||||
path: |
|
||||
|
||||
@@ -1,52 +1,43 @@
|
||||
name: Fineract Build & Test - PostgreSQL
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:16.1
|
||||
image: postgres:17.4
|
||||
ports:
|
||||
- 5432:5432
|
||||
env:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: postgres
|
||||
options: --health-cmd="pg_isready -q -d postgres -U root" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
mock-oauth2-server:
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.1
|
||||
image: ghcr.io/navikt/mock-oauth2-server:2.1.10
|
||||
ports:
|
||||
- 9000:9000
|
||||
env:
|
||||
SERVER_PORT: 9000
|
||||
JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": "NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", "tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": "fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'
|
||||
|
||||
env:
|
||||
TZ: Asia/Kolkata
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
|
||||
- name: Setup Gradle and Validate Wrapper
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Congfigure vega-cli
|
||||
run: npm i -g vega-cli --unsafe
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142
|
||||
validate-wrappers: true
|
||||
- name: Verify PostgreSQL connection
|
||||
run: |
|
||||
while ! pg_isready -d postgres -U root -h 127.0.0.1 -p 5432 ; do
|
||||
@@ -67,11 +58,6 @@ jobs:
|
||||
sleep 10
|
||||
docker exec localstack awslocal s3api create-bucket --bucket fineract-reports
|
||||
echo "LocalStack initialization complete"
|
||||
- name: Install additional software
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ghostscript graphviz -y
|
||||
|
||||
- name: Build & Test
|
||||
env:
|
||||
AWS_ENDPOINT_URL: http://localhost:4566
|
||||
@@ -86,10 +72,9 @@ jobs:
|
||||
./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test -PdbType=postgresql
|
||||
./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=postgresql
|
||||
./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=postgresql
|
||||
|
||||
- name: Archive test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
@@ -97,10 +82,9 @@ jobs:
|
||||
integration-tests/build/reports/
|
||||
twofactor-tests/build/reports/
|
||||
oauth2-tests/build/reports/
|
||||
|
||||
- name: Archive server logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: server-logs
|
||||
path: |
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
name: Fineract Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
IMAGE_NAME: fineract
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build the image
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber
|
||||
- name: Start the Fineract stack
|
||||
run: docker compose -f docker-compose-postgresql.yml up -d
|
||||
- name: Wait for stack to come up
|
||||
run: sleep 400
|
||||
run: docker compose -f docker-compose-postgresql-test-activemq.yml up -d
|
||||
- name: Check the stack
|
||||
run: docker ps
|
||||
- name: Check health Manager
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
- name: Execute tests
|
||||
env:
|
||||
BASE_URL: https://localhost:8443
|
||||
TEST_USERNAME: mifos
|
||||
TEST_PASSWORD: password
|
||||
TEST_STRONG_PASSWORD: A1b2c3d4e5f$
|
||||
TEST_TENANT_ID: default
|
||||
INITIALIZATION_ENABLED: true
|
||||
EVENT_VERIFICATION_ENABLED: false
|
||||
run: ./gradlew --no-daemon --console=plain fineract-e2e-tests-runner:cucumber --tags 'not @Skip' allureReport
|
||||
EVENT_VERIFICATION_ENABLED: true
|
||||
ACTIVEMQ_BROKER_URL: tcp://localhost:61616
|
||||
ACTIVEMQ_TOPIC_NAME: events
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-e2e-tests-runner:cucumber --tags 'not @Skip' allureReport
|
||||
|
||||
@@ -1,36 +1,52 @@
|
||||
name: Fineract Publish to DockerHub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
tags:
|
||||
- 1.*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout Source Code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Get Git Hashes
|
||||
run: |
|
||||
echo "short_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "long_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
id: git_hashes
|
||||
|
||||
- name: Build the Apache Fineract image
|
||||
run: |
|
||||
./gradlew --no-daemon --console=plain :fineract-provider:jib -x test -x cucumber -Djib.to.auth.username=${{secrets.DOCKERHUB_USER}} -Djib.to.auth.password=${{secrets.DOCKERHUB_TOKEN}} -Djib.from.platforms=linux/amd64,linux/arm64 -Djib.to.image=apache/fineract -Djib.to.tags=${{ steps.extract_branch.outputs.branch }}
|
||||
TAGS=${{ steps.extract_branch.outputs.branch }}
|
||||
if [ "${{ steps.extract_branch.outputs.branch }}" == "develop" ]; then
|
||||
TAGS="$TAGS,${{ steps.git_hashes.outputs.short_hash }},${{ steps.git_hashes.outputs.long_hash }}"
|
||||
fi
|
||||
./gradlew --no-daemon --console=plain :fineract-provider:jib -x test -x cucumber \
|
||||
-Djib.to.auth.username=${{secrets.DOCKERHUB_USER}} \
|
||||
-Djib.to.auth.password=${{secrets.DOCKERHUB_TOKEN}} \
|
||||
-Djib.from.platforms=linux/amd64,linux/arm64 \
|
||||
-Djib.to.image=apache/fineract \
|
||||
-Djib.to.tags=$TAGS
|
||||
|
||||
@@ -1,41 +1,37 @@
|
||||
name: Fineract ActiveMQ Smoke
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
IMAGE_NAME: fineract
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build the image
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber
|
||||
- name: Start the ActiveMQ Stack
|
||||
run: docker compose -f docker-compose-postgresql-activemq.yml up --scale fineract-worker=1 -d
|
||||
- name: Wait for stack to come up
|
||||
run: sleep 500
|
||||
- name: Check the stack
|
||||
run: docker ps
|
||||
- name: Check health Manager
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
- name: Check health Worker1
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
|
||||
- name: Check info Manager
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
- name: Check info Worker1
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
- name: Run Smoke Test with Remote COB
|
||||
run: ./gradlew --no-daemon --console=plain :integration-tests:cleanTest :integration-tests:test --tests "org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater" -PcargoDisabled
|
||||
|
||||
@@ -1,41 +1,37 @@
|
||||
name: Fineract Kafka Smoke
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
IMAGE_NAME: fineract
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
- name: Build the image
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber
|
||||
- name: Start the Kafka Stack
|
||||
run: docker compose -f docker-compose-postgresql-kafka.yml up --scale fineract-worker=1 -d
|
||||
- name: Wait for stack to come up
|
||||
run: sleep 500
|
||||
- name: Check the stack
|
||||
run: docker ps
|
||||
- name: Check health Manager
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
|
||||
- name: Check health Worker1
|
||||
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
|
||||
run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
|
||||
- name: Check info Manager
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
- name: Check info Worker1
|
||||
run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc --chars) > 100 ))
|
||||
- name: Run Smoke Test with Remote COB
|
||||
run: ./gradlew --no-daemon --console=plain :integration-tests:cleanTest :integration-tests:test --tests "org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater" -PcargoDisabled
|
||||
|
||||
@@ -3,13 +3,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
TZ: Asia/Kolkata
|
||||
SONAR_ORGANIZATION: ${{ secrets.SONAR_ORGANIZATION }}
|
||||
@@ -17,19 +15,23 @@ jobs:
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
JAVA_BINARIES: .
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142
|
||||
- name: Sonarqube
|
||||
run: ./gradlew --no-daemon --console=plain -Dsonar.verbose=true -Dsonar.login=$SONAR_TOKEN -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.organization=$SONAR_ORGANIZATION -Dsonar.projectKey=$SONAR_PROJECT_KEY --info --stacktrace sonarqube
|
||||
- name: Setup Gradle and Validate Wrapper
|
||||
uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
|
||||
with:
|
||||
validate-wrappers: true
|
||||
- name: Build
|
||||
run: ./gradlew --no-daemon --console=plain :fineract-provider:build -x test -x cucumber
|
||||
- name: Sonar
|
||||
run: ./gradlew --no-daemon --console=plain -Dsonar.verbose=true -Dsonar.token=$SONAR_TOKEN -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.organization=$SONAR_ORGANIZATION -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.java.binaries=$JAVA_BINARIES --info --stacktrace sonar
|
||||
|
||||
@@ -7,7 +7,6 @@ on:
|
||||
- cron: "0 0 * * *"
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
@@ -15,7 +14,7 @@ jobs:
|
||||
pull-requests: write # for actions/stale to close stale PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
|
||||
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# stale-issue-message: 'Stale issue message'
|
||||
|
||||
@@ -30,3 +30,6 @@ fineract-provider/src/main/generated/
|
||||
|
||||
**/out/
|
||||
gradleExp/
|
||||
|
||||
.run/
|
||||
.java-version
|
||||
@@ -1,6 +1,10 @@
|
||||
Apache Fineract: A Platform for Microfinance
|
||||
============
|
||||
[](https://validator.swagger.io/validator/debug?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml) [](https://github.com/apache/fineract/actions/workflows/build.yml) [](https://hub.docker.com/r/apache/fineract) [](https://hub.docker.com/r/apache/fineract/builds) [](https://sonarcloud.io/summary/new_code?id=apache_fineract)
|
||||
<!-- TODO Reactivate when there is a working CI-CD instance: [](https://validator.swagger.io/validator/debug?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml) -->
|
||||
[](https://github.com/apache/fineract/actions/workflows/build-mariadb.yml)
|
||||
[](https://hub.docker.com/r/apache/fineract)
|
||||
[](https://github.com/apache/fineract/actions/workflows/publish-dockerhub.yml)
|
||||
[](https://sonarcloud.io/summary/new_code?id=apache_fineract)
|
||||
|
||||
</b>
|
||||
|
||||
@@ -22,15 +26,15 @@ If you are interested in contributing to this project, but perhaps don't quite k
|
||||
REQUIREMENTS
|
||||
============
|
||||
* `Java >= 17` (Azul Zulu JVM is tested by our CI on GitHub Actions)
|
||||
* MariaDB `11.2`
|
||||
* MariaDB `11.5.2`
|
||||
|
||||
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.2 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:11.2
|
||||
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.2
|
||||
docker rm -f mariadb-11.5
|
||||
|
||||
<br>Beware that this database 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) re. how to make it persistent instead of ephemeral.<br>
|
||||
|
||||
@@ -75,11 +79,9 @@ Run the following commands:
|
||||
============
|
||||
1. Clone the repository or download and extract the archive file to your local directory.
|
||||
2. Run `./gradlew clean bootJar` to build a modern cloud native fully self contained JAR file which will be created at `fineract-provider/build/libs` directory.
|
||||
3. 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://downloads.mariadb.com/Connectors/java/connector-java-3.3.2/mariadb-java-client-3.3.2.jar`
|
||||
3. 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`
|
||||
4. Start the jar and pass the directory where you have downloaded the JDBC driver as loader.path, for example: `java -Dloader.path=. -jar fineract-provider/build/libs/fineract-provider.jar` (does not require external Tomcat)
|
||||
|
||||
NOTE: we cannot upgrade to version 3.0.x of the MariaDB driver just yet; have to wait until 3.0.4 is out for a bug fix.
|
||||
|
||||
The tenants database connection details are configured [via environment variables (as with Docker container)](#instructions-to-run-using-docker-and-docker-compose), e.g. like this:
|
||||
|
||||
export FINERACT_HIKARI_PASSWORD=verysecret
|
||||
@@ -142,15 +144,54 @@ We recommend using the JAR instead of the WAR file deployment, because it's much
|
||||
Note that with the 1.4 release the tenants database pool configuration changed from Tomcat DBCP in XML to an embedded Hikari, configured by environment variables, see above.
|
||||
|
||||
|
||||
INSTRUCTIONS: How to execute Integration Tests
|
||||
INSTRUCTIONS: How to run tests
|
||||
============
|
||||
> Note that if this is the first time to access MySQL DB, then you may need to reset your password.
|
||||
|
||||
Run the following commands:
|
||||
1. `./gradlew createDB -PdbName=fineract_tenants`
|
||||
1. `./gradlew createDB -PdbName=fineract_default`
|
||||
1. `./gradlew clean test`
|
||||
Unit tests
|
||||
----------
|
||||
|
||||
Here's how to run the set of relatviely fast and indepedent Fineract tests:
|
||||
|
||||
```bash
|
||||
./gradlew test -x :twofactor-tests:test -x :oauth2-tests:test -x :integration-tests:test
|
||||
```
|
||||
|
||||
This runs nearly 1,000 tests and completes in a few minutes on decent hardware.
|
||||
They shouldn't need any special servers/services running.
|
||||
|
||||
Integration tests
|
||||
-----------------
|
||||
|
||||
Running tests with external dependencies yourself is a multi-step process with many moving parts.
|
||||
Sometimes there are arbitrary failures and the prerequisite setup can be daunting.
|
||||
A full local integration test run (on a developer workstation) covering every possible test using every external service and every supported relational database engine could take an entire day, and that's assuming everything is properly configured and runs as expected.
|
||||
|
||||
Right now we depend on GitHub to know if "the build" is passing (it's actually multiple builds).
|
||||
The authoritative source of truth for what commands/services/tests to run, how, and when are the files in `.github/workflows/`.
|
||||
Output from runs based on those configuration files appears at <https://github.com/apache/fineract/actions>.
|
||||
|
||||
Note these builds are run in [short-lived virtual machines](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners), so locally reproducing the same may require additional effort, such as these extra clean-up procedures:
|
||||
|
||||
```bash
|
||||
# Destroy anything untracked by git.
|
||||
# ⚠️ This may delete something important, e.g. a finely-tuned IDE configuration.
|
||||
git clean --force -dx
|
||||
|
||||
# Destroy various caches and configs.
|
||||
# ⚠️ This may delete gibibytes of cached data, making the next build very slow.
|
||||
rm -rf ~/.gradle ~/.m2 /tmp/cargo*
|
||||
|
||||
# Destroy any Java containers left running.
|
||||
# 💚 This is generally very safe to run between builds.
|
||||
ps auxwww | grep [c]argo | awk '{ print $2 }' | xargs -r kill
|
||||
```
|
||||
|
||||
Testing within IDEs
|
||||
-----------------
|
||||
|
||||
See the next section for testing in Eclipse.
|
||||
|
||||
See <https://fineract-academy.com> for testing in IntelliJ.
|
||||
|
||||
INSTRUCTIONS: How to run and debug in Eclipse IDE
|
||||
============
|
||||
@@ -218,6 +259,21 @@ id -u ${GROUP}
|
||||
|
||||
Please make sure that you are not checking in your changed values. The defaults should normally work for most people.
|
||||
|
||||
INSTRUCTIONS: How to build documentation
|
||||
===================================================
|
||||
|
||||
Run the following command:
|
||||
|
||||
```bash
|
||||
./gradlew doc
|
||||
```
|
||||
|
||||
Some dependencies are required (e.g. Ghostscript, Graphviz), see `.github/workflows/build-documentation.yml` for hints.
|
||||
|
||||
Additionally, IDEs such as IntelliJ are useful for editing the AsciiDoc source files while providing a live rendered preview.
|
||||
|
||||
HTML rendered from the AsciiDoc source files is also available online at <https://fineract.apache.org/docs/current/>.
|
||||
|
||||
Connection pool configuration
|
||||
=============================
|
||||
|
||||
@@ -448,7 +504,7 @@ Apache Fineract / Mifos X Demo (November 2016) - <https://www.youtube.com/watch?
|
||||
We use Swagger-UI to generate and maintain our API documentation, you can see the demo video [here](https://www.youtube.com/watch?v=FlVd-0YAo6c) or a live version
|
||||
[here](https://sandbox.mifos.community/fineract-provider/swagger-ui/index.html). If you interested to know more about Swagger-UI you can check their [website](https://swagger.io/).
|
||||
|
||||
<br>GORVENANCE AND POLICIES
|
||||
<br>GOVERNANCE AND POLICIES
|
||||
=======================
|
||||
|
||||
[Becoming a Committer](https://cwiki.apache.org/confluence/display/FINERACT/Becoming+a+Committer)
|
||||
|
||||
+127
-46
@@ -19,7 +19,7 @@
|
||||
// TODO: this is work in progress, please follow FINERACT-1171
|
||||
buildscript {
|
||||
ext {
|
||||
jacocoVersion = '0.8.11'
|
||||
jacocoVersion = '0.8.12'
|
||||
retrofitVersion = '2.9.0'
|
||||
okhttpVersion = '4.9.3'
|
||||
oltuVersion = '1.0.1'
|
||||
@@ -46,7 +46,8 @@ buildscript {
|
||||
'fineract-avro-schemas',
|
||||
'fineract-e2e-tests-core',
|
||||
'fineract-e2e-tests-runner',
|
||||
'fineract-progressive-loan'
|
||||
'fineract-progressive-loan',
|
||||
'fineract-progressive-loan-embeddable-schedule-generator'
|
||||
].contains(it.name)
|
||||
}
|
||||
fineractPublishProjects = subprojects.findAll{
|
||||
@@ -66,7 +67,8 @@ buildscript {
|
||||
'fineract-report',
|
||||
'fineract-branch',
|
||||
'fineract-document',
|
||||
'fineract-progressive-loan'
|
||||
'fineract-progressive-loan',
|
||||
'fineract-progressive-loan-embeddable-schedule-generator'
|
||||
].contains(it.name)
|
||||
}
|
||||
npmRepository = 'https://npm.pkg.github.com'
|
||||
@@ -77,42 +79,39 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath 'com.bmuschko:gradle-cargo-plugin:2.9.0'
|
||||
classpath 'org.eclipse.persistence:eclipselink:4.0.0'
|
||||
classpath 'org.eclipse.persistence:eclipselink:4.0.2'
|
||||
classpath 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
|
||||
classpath 'com.google.cloud.tools:jib-layer-filter-extension-gradle:0.3.0'
|
||||
classpath 'org.apache.commons:commons-lang3:3.14.0'
|
||||
classpath 'org.apache.commons:commons-lang3:3.17.0'
|
||||
classpath 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.22'
|
||||
classpath 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
||||
classpath 'jakarta.servlet:jakarta.servlet-api:6.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'me.qoomon.git-versioning' version '6.4.3'
|
||||
id 'me.qoomon.git-versioning' version '6.4.4'
|
||||
id "org.barfuin.gradle.taskinfo" version "2.2.0"
|
||||
id 'com.adarshr.test-logger' version '4.0.0'
|
||||
id 'com.diffplug.spotless' version '6.25.0' apply false
|
||||
id 'org.nosphere.apache.rat' version '0.8.1' apply false
|
||||
id 'com.github.hierynomus.license' version '0.16.1' apply false
|
||||
id 'com.github.jk1.dependency-license-report' version '2.5' apply false
|
||||
id 'com.github.jk1.dependency-license-report' version '2.9' apply false
|
||||
id 'org.zeroturnaround.gradle.jrebel' version '1.2.0' apply false
|
||||
id 'org.springframework.boot' version '3.2.6' apply false
|
||||
id 'net.ltgt.errorprone' version '3.1.0' apply false
|
||||
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.19' apply false
|
||||
id 'com.gorylenko.gradle-git-properties' version '2.4.1' apply false
|
||||
id 'org.springframework.boot' version '3.4.4' apply false
|
||||
id 'net.ltgt.errorprone' version '4.1.0' apply false
|
||||
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.23' apply false
|
||||
id 'com.gorylenko.gradle-git-properties' version '2.4.2' apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '3.3.2' apply false
|
||||
id 'org.asciidoctor.jvm.pdf' version '3.3.2' apply false
|
||||
id 'org.asciidoctor.jvm.epub' version '3.3.2' apply false
|
||||
// id 'org.asciidoctor.jvm.revealjs' version '3.3.2' apply false
|
||||
// id 'org.asciidoctor.jvm.gems' version '3.3.2' apply false
|
||||
id 'org.asciidoctor.kindlegen.base' version '3.2.0' apply false
|
||||
id 'com.google.cloud.tools.jib' version '3.4.2' apply false
|
||||
id 'org.sonarqube' version '4.4.1.3373'
|
||||
id 'com.github.andygoossens.modernizer' version '1.9.0' apply false
|
||||
id 'com.google.cloud.tools.jib' version '3.4.4' apply false
|
||||
id 'org.sonarqube' version '6.0.1.5171'
|
||||
id 'com.github.andygoossens.modernizer' version '1.10.0' apply false
|
||||
// TODO: upgrade to 6.0.4
|
||||
id 'com.github.spotbugs' version '5.2.5' apply false
|
||||
id 'com.github.spotbugs' version '6.0.26' apply false
|
||||
id 'se.thinkcode.cucumber-runner' version '0.0.11' apply false
|
||||
id "com.github.davidmc24.gradle.plugin.avro-base" version "1.9.1" apply false
|
||||
id 'org.openapi.generator' version '7.2.0' apply false
|
||||
id 'org.openapi.generator' version '7.8.0' apply false
|
||||
id 'com.gradleup.shadow' version '8.3.5' apply false
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.release.gradle"
|
||||
@@ -151,11 +150,39 @@ allprojects {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations {
|
||||
api {
|
||||
canBeResolved = true
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.adarshr.test-logger'
|
||||
apply plugin: 'com.diffplug.spotless'
|
||||
apply plugin: 'com.github.hierynomus.license'
|
||||
apply plugin: 'net.ltgt.errorprone'
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.errorprone {
|
||||
disableWarningsInGeneratedCode = true
|
||||
disable(
|
||||
"CanIgnoreReturnValueSuggester",
|
||||
"SameNameButDifferent", // Until errorprone recognizes Lombok
|
||||
"MultiVariableDeclaration", // Until errorprone recognizes Lombok
|
||||
"UnnecessaryDefaultInEnumSwitch", // FINERACT-1911
|
||||
"AssertEqualsArgumentOrderChecker",
|
||||
"RemoveUnusedImports" // For generated code
|
||||
)
|
||||
error(
|
||||
"DefaultCharset",
|
||||
"StringSplitter",
|
||||
"MutablePublicArray",
|
||||
"EqualsGetClass",
|
||||
"FutureReturnValueIgnored"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'org.nosphere.apache.rat'
|
||||
apply plugin: 'project-report'
|
||||
apply plugin: 'com.github.jk1.dependency-license-report'
|
||||
|
||||
// Configuration for the sonarqube plugin is now in GitHub Actions
|
||||
@@ -173,7 +200,7 @@ allprojects {
|
||||
|
||||
groovyGradle {
|
||||
target '*.gradle', '**/*.gradle'
|
||||
targetExclude '**/build/**'
|
||||
targetExclude '**/build/**', '/**/build.gradle' // TODO: temporary disabled on build.gradle until someone fix this issue: https://github.com/diffplug/spotless/issues/1807
|
||||
greclipse()
|
||||
indentWithSpaces(4)
|
||||
endWithNewline()
|
||||
@@ -222,7 +249,6 @@ allprojects {
|
||||
'**/licenses/**',
|
||||
'**/*.md',
|
||||
'**/*.adoc',
|
||||
'**/.asciidoctorconfig',
|
||||
'**/*.puml',
|
||||
'**/*.github/**',
|
||||
'**/MANIFEST.MF',
|
||||
@@ -299,7 +325,9 @@ allprojects {
|
||||
'**/images/diag-*.svg',
|
||||
'**/*.avsc',
|
||||
"**/generated/**/*MapperImpl.java",
|
||||
'**/META-INF/fineract-test.config'
|
||||
'**/META-INF/fineract-test.config',
|
||||
// Apache-specific GitHub metadata settings file
|
||||
'/.asf.yaml'
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -325,10 +353,49 @@ configure(project.fineractJavaProjects) {
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
tasks.withType(ProcessResources) {
|
||||
destinationDir = layout.buildDirectory.dir('classes/java/main').get().asFile
|
||||
}
|
||||
|
||||
// Add performance optimizations
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
cacheDynamicVersionsFor 0, 'seconds'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.incremental = true
|
||||
options.fork = true
|
||||
outputs.cacheIf { true }
|
||||
options.compilerArgs << '-parameters'
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
options.compilerArgs << '-Xlint:deprecation'
|
||||
if (project.hasProperty('warnings') && project.warnings.contains('fail')) {
|
||||
options.compilerArgs << '-Werror'
|
||||
}
|
||||
if (project.hasProperty('warnings') && project.warnings.contains('none')) {
|
||||
options.compilerArgs << '-nowarn'
|
||||
}
|
||||
if (project.plugins.hasPlugin('org.springframework.boot')) {
|
||||
options.generatedSourceOutputDirectory = file("$buildDir/generated/sources/annotationProcessor/java/main")
|
||||
}
|
||||
options.generatedSourceOutputDirectory = file("$buildDir/generated/sources/annotationProcessor/java/main")
|
||||
}
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'checkstyle'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'net.ltgt.errorprone'
|
||||
apply plugin: 'com.github.spotbugs'
|
||||
apply plugin: 'com.github.andygoossens.modernizer'
|
||||
apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
|
||||
@@ -336,9 +403,9 @@ configure(project.fineractJavaProjects) {
|
||||
group = 'org.apache.fineract'
|
||||
|
||||
/* define the valid syntax level for source files */
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
/* define binary compatibility version */
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
// sourceCompatibility = JavaVersion.VERSION_17
|
||||
// /* define binary compatibility version */
|
||||
// targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
/* http://stackoverflow.com/questions/19653311/jpa-repository-works-in-idea-and-production-but-not-in-gradle */
|
||||
sourceSets.main.output.resourcesDir = sourceSets.main.java.classesDirectory
|
||||
@@ -354,7 +421,6 @@ configure(project.fineractJavaProjects) {
|
||||
}
|
||||
|
||||
configurations {
|
||||
implementation.setCanBeResolved(true)
|
||||
api.setCanBeResolved(true)
|
||||
}
|
||||
tasks.withType(Copy) {
|
||||
@@ -362,10 +428,8 @@ configure(project.fineractJavaProjects) {
|
||||
}
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs += [
|
||||
"-Xlint:unchecked",
|
||||
"-Xlint:cast",
|
||||
"-Xlint:auxiliaryclass",
|
||||
"-Xlint:deprecation",
|
||||
"-Xlint:dep-ann",
|
||||
"-Xlint:divzero",
|
||||
"-Xlint:empty",
|
||||
@@ -399,6 +463,10 @@ configure(project.fineractJavaProjects) {
|
||||
options.deprecation = true
|
||||
}
|
||||
|
||||
check {
|
||||
dependsOn(rat, licenseMain, licenseTest)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
spotbugsPlugins 'jp.skypencil.findbugs.slf4j:bug-pattern:1.5.0@jar'
|
||||
}
|
||||
@@ -455,7 +523,7 @@ configure(project.fineractJavaProjects) {
|
||||
// Configuration for the Checkstyle plugin
|
||||
// https://docs.gradle.org/current/userguide/checkstyle_plugin.html
|
||||
dependencies {
|
||||
checkstyle 'com.puppycrawl.tools:checkstyle:10.14.2'
|
||||
checkstyle 'com.puppycrawl.tools:checkstyle:10.20.1'
|
||||
checkstyle 'com.github.sevntu-checkstyle:sevntu-checks:1.44.1'
|
||||
}
|
||||
|
||||
@@ -470,21 +538,22 @@ configure(project.fineractJavaProjects) {
|
||||
reports {
|
||||
html.required = true
|
||||
xml.required = true
|
||||
html.destination file("${buildDir}/code-coverage")
|
||||
html.outputLocation = layout.buildDirectory.dir('code-coverage')
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration for the errorprone plugin
|
||||
// https://github.com/tbroyer/gradle-errorprone-plugin
|
||||
dependencies {
|
||||
errorprone "com.google.errorprone:error_prone_core:2.26.1"
|
||||
errorprone "com.google.errorprone:error_prone_core:2.35.1"
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.errorprone {
|
||||
enabled = project.gradle.startParameter.taskNames.contains('build') || project.gradle.startParameter.taskNames.contains('check')
|
||||
disableWarningsInGeneratedCode = true
|
||||
excludedPaths = ".*/build/.*"
|
||||
if (project.path == ':fineract-client') {
|
||||
excludedPaths = '.*/build/generated/java/src/main/java/.*'
|
||||
}
|
||||
disable(
|
||||
// TODO Remove disabled checks from this list, by fixing remaining usages
|
||||
"UnusedVariable",
|
||||
@@ -608,9 +677,10 @@ configure(project.fineractJavaProjects) {
|
||||
'org.bouncycastle:bcpkix-jdk15to18',
|
||||
'org.bouncycastle:bcprov-jdk15to18',
|
||||
'org.awaitility:awaitility',
|
||||
'com.google.truth:truth',
|
||||
'com.google.truth.extensions:truth-java8-extension'
|
||||
)
|
||||
|
||||
testCompileOnly 'org.projectlombok:lombok'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok'
|
||||
}
|
||||
|
||||
test {
|
||||
@@ -667,6 +737,19 @@ configure(project.fineractJavaProjects) {
|
||||
'java/util/Optional.get:()Ljava/lang/Object;' // Disable forcing the usage of Optional.orElseThrow(java.util.function.Supplier<? extends X>)
|
||||
]
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.encoding = 'UTF-8'
|
||||
// Disable strict checking to prevent build failures on invalid javadoc
|
||||
options.addBooleanOption('html5', true)
|
||||
// Add this if you're using Java 17 records or other modern features
|
||||
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) {
|
||||
options.addBooleanOption('html5', true)
|
||||
}
|
||||
// Ignore any errors during javadoc generation
|
||||
failOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
configure(project.fineractCustomProjects) {
|
||||
@@ -708,14 +791,12 @@ configure(project.fineractCustomProjects) {
|
||||
'org.bouncycastle:bcpkix-jdk15to18',
|
||||
'org.bouncycastle:bcprov-jdk15to18',
|
||||
'org.awaitility:awaitility',
|
||||
'com.google.truth:truth',
|
||||
'com.google.truth.extensions:truth-java8-extension',
|
||||
'io.github.classgraph:classgraph',
|
||||
'io.cucumber:cucumber-core',
|
||||
'io.cucumber:cucumber-java:7.16.1',
|
||||
'io.cucumber:cucumber-java8:7.16.1',
|
||||
'io.cucumber:cucumber-junit-platform-engine:7.16.1',
|
||||
'io.cucumber:cucumber-spring:7.16.1',
|
||||
'io.cucumber:cucumber-java:7.20.1',
|
||||
'io.cucumber:cucumber-java8:7.20.1',
|
||||
'io.cucumber:cucumber-junit-platform-engine:7.20.1',
|
||||
'io.cucumber:cucumber-spring:7.20.1',
|
||||
)
|
||||
|
||||
testCompileOnly('org.projectlombok:lombok')
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import static org.slf4j.LoggerFactory.*
|
||||
|
||||
plugins {
|
||||
id 'io.spring.dependency-management' version '1.1.4'
|
||||
id 'io.spring.dependency-management' version '1.1.6'
|
||||
id 'groovy'
|
||||
id 'java-gradle-plugin'
|
||||
id 'groovy-gradle-plugin'
|
||||
|
||||
@@ -23,19 +23,19 @@ apply plugin: 'io.spring.dependency-management'
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.squareup.okhttp3:okhttp-bom:4.12.0'
|
||||
mavenBom 'org.slf4j:slf4j-bom:2.0.12'
|
||||
mavenBom 'io.micrometer:micrometer-bom:1.12.2'
|
||||
mavenBom 'org.springframework:spring-framework-bom:6.1.3'
|
||||
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.2.6'
|
||||
mavenBom 'io.awspring.cloud:spring-cloud-aws-dependencies:3.1.0'
|
||||
mavenBom 'io.opentelemetry:opentelemetry-bom:1.34.1'
|
||||
mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.9.24'
|
||||
mavenBom 'org.junit:junit-bom:5.10.2'
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.16.1'
|
||||
mavenBom 'io.cucumber:cucumber-bom:7.15.0'
|
||||
mavenBom 'io.netty:netty-bom:4.1.110.Final'
|
||||
mavenBom 'org.mockito:mockito-bom:5.10.0'
|
||||
mavenBom 'software.amazon.awssdk:bom:2.23.18'
|
||||
mavenBom 'org.slf4j:slf4j-bom:2.0.17'
|
||||
mavenBom 'io.micrometer:micrometer-bom:1.13.6'
|
||||
mavenBom 'org.springframework:spring-framework-bom:6.2.5'
|
||||
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.4.4'
|
||||
mavenBom 'io.awspring.cloud:spring-cloud-aws-dependencies:3.2.1'
|
||||
mavenBom 'io.opentelemetry:opentelemetry-bom:1.44.1'
|
||||
mavenBom 'org.jetbrains.kotlin:kotlin-bom:2.0.21'
|
||||
mavenBom 'org.junit:junit-bom:5.11.3'
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.18.3'
|
||||
mavenBom 'io.cucumber:cucumber-bom:7.20.1'
|
||||
mavenBom 'io.netty:netty-bom:4.1.119.Final'
|
||||
mavenBom 'org.mockito:mockito-bom:5.14.2'
|
||||
mavenBom 'software.amazon.awssdk:bom:2.29.9'
|
||||
mavenBom 'io.github.resilience4j:resilience4j-bom:2.2.0'
|
||||
}
|
||||
|
||||
@@ -44,40 +44,38 @@ dependencyManagement {
|
||||
// We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
|
||||
// We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.
|
||||
|
||||
dependency 'ch.qos.logback:logback-core:1.5.3'
|
||||
dependency 'ch.qos.logback:logback-classic:1.5.3'
|
||||
dependency 'ch.qos.logback:logback-core:1.5.17'
|
||||
dependency 'ch.qos.logback:logback-classic:1.5.17'
|
||||
dependency 'ch.qos.logback.contrib:logback-json-classic:0.1.5'
|
||||
dependency 'ch.qos.logback.contrib:logback-jackson:0.1.5'
|
||||
dependency 'org.codehaus.janino:janino:3.1.11'
|
||||
dependency 'org.codehaus.janino:janino:3.1.12'
|
||||
|
||||
|
||||
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.0'
|
||||
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.2'
|
||||
dependency 'com.google.guava:guava:32.0.0-jre'
|
||||
dependency 'com.google.code.gson:gson:2.10.1'
|
||||
dependency 'com.google.truth:truth:1.4.0'
|
||||
dependency 'com.google.truth.extensions:truth-java8-extension:1.4.0'
|
||||
dependency 'com.google.googlejavaformat:google-java-format:1.19.2'
|
||||
dependency 'com.google.code.gson:gson:2.11.0'
|
||||
dependency 'com.google.googlejavaformat:google-java-format:1.24.0'
|
||||
dependency 'org.apache.commons:commons-collections4:4.4'
|
||||
dependency ('software.amazon.msk:aws-msk-iam-auth:2.0.3') {
|
||||
dependency ('software.amazon.msk:aws-msk-iam-auth:2.2.0') {
|
||||
exclude 'commons-logging:commons-logging:'
|
||||
}
|
||||
dependency ('org.apache.commons:commons-email:1.6.0') {
|
||||
exclude 'com.sun.mail:javax.mail'
|
||||
exclude 'javax.activation:activation'
|
||||
}
|
||||
dependency 'commons-io:commons-io:2.15.1'
|
||||
dependency 'com.github.librepdf:openpdf:2.0.0'
|
||||
dependency ('org.mnode.ical4j:ical4j:3.2.14') {
|
||||
dependency 'commons-io:commons-io:2.17.0'
|
||||
dependency 'com.github.librepdf:openpdf:2.0.3'
|
||||
dependency ('org.mnode.ical4j:ical4j:3.2.19') {
|
||||
exclude 'com.sun.mail:javax.mail'
|
||||
exclude 'org.codehaus.groovy:groovy'
|
||||
}
|
||||
dependency 'org.apache.commons:commons-csv:1.10.0'
|
||||
dependency 'org.quartz-scheduler:quartz:2.3.2'
|
||||
dependency 'org.apache.commons:commons-csv:1.12.0'
|
||||
dependency 'org.quartz-scheduler:quartz:2.5.0'
|
||||
dependency 'org.ehcache:ehcache:3.10.8'
|
||||
dependency 'com.github.spullara.mustache.java:compiler:0.9.11'
|
||||
dependency 'com.github.spullara.mustache.java:compiler:0.9.14'
|
||||
dependency 'com.jayway.jsonpath:json-path:2.9.0'
|
||||
dependency 'org.apache.tika:tika-core:2.9.1'
|
||||
dependency ('org.apache.tika:tika-parser-microsoft-module:2.9.2') {
|
||||
dependency 'org.apache.tika:tika-core:2.9.3'
|
||||
dependency ('org.apache.tika:tika-parser-microsoft-module:2.9.3') {
|
||||
exclude 'org.bouncycastle:bcprov-jdk15on'
|
||||
exclude 'org.bouncycastle:bcmail-jdk15on'
|
||||
exclude 'org.bouncycastle:bcprov-jdk18on'
|
||||
@@ -94,7 +92,7 @@ dependencyManagement {
|
||||
exclude 'org.apache.commons:commons-compress'
|
||||
exclude 'xml-apis:xml-apis'
|
||||
}
|
||||
dependency ('org.apache.tika:tika-parser-miscoffice-module:2.9.2') {
|
||||
dependency ('org.apache.tika:tika-parser-miscoffice-module:2.9.3') {
|
||||
exclude 'org.bouncycastle:bcprov-jdk15on'
|
||||
exclude 'org.bouncycastle:bcmail-jdk15on'
|
||||
exclude 'org.bouncycastle:bcprov-jdk18on'
|
||||
@@ -117,64 +115,63 @@ dependencyManagement {
|
||||
dependency 'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
|
||||
dependency 'jakarta.jms:jakarta.jms-api:3.1.0'
|
||||
dependency 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
|
||||
dependency 'org.glassfish.jersey.media:jersey-media-multipart:3.1.5'
|
||||
dependency 'org.glassfish.jersey.media:jersey-media-multipart:3.1.10'
|
||||
dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger needs exactly this version
|
||||
dependency 'org.apache.bval:org.apache.bval.bundle:3.0.0'
|
||||
dependency 'joda-time:joda-time:2.12.7'
|
||||
dependency 'org.apache.bval:org.apache.bval.bundle:3.0.2'
|
||||
dependency 'joda-time:joda-time:2.13.1'
|
||||
|
||||
dependency 'io.github.classgraph:classgraph:4.8.168'
|
||||
dependency 'org.awaitility:awaitility:4.2.1'
|
||||
dependency 'io.github.classgraph:classgraph:4.8.179'
|
||||
dependency 'org.awaitility:awaitility:4.2.2'
|
||||
// TODO: upgrade to 4.8.3
|
||||
dependency 'com.github.spotbugs:spotbugs-annotations:4.8.3'
|
||||
dependency 'com.github.spotbugs:spotbugs-annotations:4.8.6'
|
||||
dependency 'javax.cache:cache-api:1.1.1'
|
||||
dependency 'org.mock-server:mockserver-junit-jupiter:5.15.0'
|
||||
dependency 'org.webjars:webjars-locator-core:0.55'
|
||||
dependency 'org.webjars:webjars-locator-core:0.59'
|
||||
dependency 'com.icegreen:greenmail-junit5:2.0.1'
|
||||
dependency 'com.intuit.karate:karate-junit5:1.4.1'
|
||||
|
||||
// fineract client dependencies
|
||||
dependency "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
dependency "com.squareup.retrofit2:retrofit-mock:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-java8:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-guava:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-wire:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-jackson:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-simplexml:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-jaxb:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-java8:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-scalars:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-gson:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-protobuf:2.9.0"
|
||||
dependency "com.squareup.retrofit2:retrofit:2.11.0"
|
||||
dependency "com.squareup.retrofit2:retrofit-mock:2.11.0"
|
||||
dependency "com.squareup.retrofit2:adapter-java8:2.11.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava2:2.11.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava3:2.11.0"
|
||||
dependency "com.squareup.retrofit2:adapter-guava:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-wire:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-jackson:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-simplexml:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-jaxb:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-java8:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-scalars:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-gson:2.11.0"
|
||||
dependency "com.squareup.retrofit2:converter-protobuf:2.11.0"
|
||||
dependency 'io.reactivex.rxjava2:rxjava:2.2.21'
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.1"
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.1"
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.httpclient4:1.0.1"
|
||||
dependency "io.gsonfire:gson-fire:1.9.0"
|
||||
dependency "com.google.code.findbugs:jsr305:3.0.2"
|
||||
dependency "commons-codec:commons-codec:1.16.0"
|
||||
dependency "org.projectlombok:lombok:1.18.32"
|
||||
dependency "commons-codec:commons-codec:1.17.1"
|
||||
dependency "org.projectlombok:lombok:1.18.36"
|
||||
|
||||
dependency 'org.bouncycastle:bcpkix-jdk15to18:1.77'
|
||||
dependency 'org.bouncycastle:bcprov-jdk15to18:1.77'
|
||||
dependency 'org.bouncycastle:bcpkix-jdk15to18:1.79'
|
||||
dependency 'org.bouncycastle:bcprov-jdk15to18:1.79'
|
||||
dependency 'org.bouncycastle:bcprov-jdk15on:1.70'
|
||||
dependency 'org.bouncycastle:bcpg-jdk15on:1.70'
|
||||
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r'
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.8.0.202311291450-r'
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r'
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.0.0.202409031743-r'
|
||||
|
||||
dependency 'org.tmatesoft.svnkit:svnkit:1.10.11'
|
||||
dependency 'com.vdurmont:semver4j:3.1.0'
|
||||
dependency 'org.beryx:text-io:3.4.1'
|
||||
|
||||
dependency ('org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0') {
|
||||
dependency ('org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0') {
|
||||
exclude 'io.swagger.core.v3:swagger-core'
|
||||
}
|
||||
|
||||
dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.15.2'
|
||||
dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.23.1'
|
||||
|
||||
dependency ('org.apache.activemq:activemq-client:6.0.1') {
|
||||
dependency ('org.apache.activemq:activemq-client:6.1.6') {
|
||||
exclude 'javax.annotation:javax.annotation-api'
|
||||
}
|
||||
|
||||
@@ -186,20 +183,20 @@ dependencyManagement {
|
||||
exclude 'jakarta.activation:jakarta.activation-api'
|
||||
}
|
||||
|
||||
dependency 'jakarta.annotation:jakarta.annotation-api:2.1.1'
|
||||
dependency 'jakarta.activation:jakarta.activation-api:2.1.2'
|
||||
dependency 'jakarta.annotation:jakarta.annotation-api:3.0.0'
|
||||
dependency 'jakarta.activation:jakarta.activation-api:2.1.3'
|
||||
dependency ('com.sun.mail:jakarta.mail:2.0.1') {
|
||||
// Spring needs this version
|
||||
exclude 'com.sun.activation:jakarta.activation'
|
||||
}
|
||||
dependency ('jakarta.xml.bind:jakarta.xml.bind-api:4.0.1') {
|
||||
dependency ('jakarta.xml.bind:jakarta.xml.bind-api:4.0.2') {
|
||||
exclude 'jakarta.activation:jakarta.activation-api'
|
||||
}
|
||||
|
||||
dependency ('org.liquibase:liquibase-core:4.25.1') {
|
||||
dependency ('org.liquibase:liquibase-core:4.31.1') {
|
||||
exclude 'javax.xml.bind:jaxb-api'
|
||||
}
|
||||
dependency 'org.liquibase.ext:liquibase-postgresql:4.25.1.1'
|
||||
dependency 'org.liquibase.ext:liquibase-postgresql:4.31.1'
|
||||
|
||||
dependency ('org.dom4j:dom4j:2.1.4') {
|
||||
exclude 'relaxngDatatype:relaxngDatatype' // already in com.sun.xml.bind:jaxb-osgi:2.3.0.1
|
||||
@@ -208,36 +205,37 @@ dependencyManagement {
|
||||
exclude 'pull-parser:pull-parser'
|
||||
}
|
||||
|
||||
dependency 'org.owasp.esapi:esapi:2.5.3.1'
|
||||
dependency 'org.awaitility:awaitility:4.2.1'
|
||||
dependency 'org.owasp.esapi:esapi:2.6.0.0'
|
||||
dependency 'org.awaitility:awaitility:4.2.2'
|
||||
|
||||
dependencySet(group: 'org.apache.poi', version: '5.2.5') {
|
||||
dependencySet(group: 'org.apache.poi', version: '5.3.0') {
|
||||
entry 'poi'
|
||||
entry 'poi-ooxml'
|
||||
entry 'poi-ooxml-schemas'
|
||||
}
|
||||
|
||||
dependencySet(group: 'io.rest-assured', version: '5.4.0') {
|
||||
dependencySet(group: 'io.rest-assured', version: '5.5.1') {
|
||||
entry 'rest-assured'
|
||||
entry 'json-path'
|
||||
entry 'xml-path'
|
||||
}
|
||||
dependency 'org.apache.groovy:groovy-xml:4.0.18'
|
||||
dependency 'org.apache.groovy:groovy-json:4.0.18'
|
||||
dependency 'org.apache.groovy:groovy-xml:4.0.26'
|
||||
dependency 'org.apache.groovy:groovy-json:4.0.26'
|
||||
|
||||
dependency 'org.mapstruct:mapstruct:1.5.5.Final'
|
||||
dependency 'org.mapstruct:mapstruct-processor:1.5.5.Final'
|
||||
dependency 'org.mapstruct:mapstruct:1.6.3'
|
||||
dependency 'org.mapstruct:mapstruct-processor:1.6.3'
|
||||
|
||||
dependency "org.apache.avro:avro:1.11.3"
|
||||
dependency "org.apache.avro:avro:1.12.0"
|
||||
|
||||
dependency ('org.mariadb.jdbc:mariadb-java-client:3.3.2') {
|
||||
dependency ('org.mariadb.jdbc:mariadb-java-client:3.5.2') {
|
||||
exclude 'org.slf4j:jcl-over-slf4j'
|
||||
exclude 'org.slf4j:slf4j-api'
|
||||
}
|
||||
|
||||
dependency 'org.postgresql:postgresql:42.7.3'
|
||||
//v42.7.5: performance issue: https://github.com/pgjdbc/pgjdbc/issues/3511#issuecomment-2637277977
|
||||
dependency 'org.postgresql:postgresql:42.7.4'
|
||||
|
||||
dependency 'org.assertj:assertj-core:3.25.3'
|
||||
dependency 'org.assertj:assertj-core:3.26.3'
|
||||
|
||||
dependency 'org.apache.commons:commons-math3:3.6.1'
|
||||
|
||||
@@ -245,9 +243,9 @@ dependencyManagement {
|
||||
|
||||
dependency 'com.github.tomakehurst:wiremock-standalone:3.0.1'
|
||||
|
||||
dependency 'io.cucumber:cucumber-java:7.16.1'
|
||||
dependency 'io.cucumber:cucumber-java8:7.16.1'
|
||||
dependency 'io.cucumber:cucumber-junit-platform-engine:7.16.1'
|
||||
dependency 'io.cucumber:cucumber-spring:7.16.1'
|
||||
dependency 'io.cucumber:cucumber-java:7.20.1'
|
||||
dependency 'io.cucumber:cucumber-java8:7.20.1'
|
||||
dependency 'io.cucumber:cucumber-junit-platform-engine:7.20.1'
|
||||
dependency 'io.cucumber:cucumber-spring:7.20.1'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,8 +334,6 @@ class FineractPlugin implements Plugin<Project> {
|
||||
gpgService.sign(step.gpg)
|
||||
|
||||
step.gpg.files.findAll {
|
||||
gpgService.md5(step.gpg)
|
||||
|
||||
gpgService.sha512(step.gpg)
|
||||
}
|
||||
}
|
||||
@@ -440,29 +438,10 @@ class FineractPlugin implements Plugin<Project> {
|
||||
project.tasks.register("fineractReleaseStep12") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step12")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
subversionService.checkout(step.subversion)
|
||||
|
||||
def directory = step.subversion.directory?:System.getProperty("java.io.tmpdir") + "/fineract-dist-release"
|
||||
|
||||
def source = new File("fineract-war/build/distributions")
|
||||
def target = new File("${directory}/${version}")
|
||||
|
||||
FileUtils.copyDirectory(source, target, true)
|
||||
|
||||
subversionService.commit(step.subversion)
|
||||
// TODO: implement this, see FINERACT-1817
|
||||
printInstructions(project, "step12")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,15 +116,6 @@ class GpgService {
|
||||
return generator.generate();
|
||||
}
|
||||
|
||||
|
||||
void md5(FineractPluginExtension.FineractPluginGpgParams params) {
|
||||
params.files.findAll {
|
||||
def result = calc(new FileInputStream(it), MessageDigest.getInstance("MD5", BouncyCastleProvider.PROVIDER_NAME))
|
||||
def file = new File("${it}.md5")
|
||||
file.write result
|
||||
}
|
||||
}
|
||||
|
||||
void sha512(FineractPluginExtension.FineractPluginGpgParams params) {
|
||||
params.files.findAll {
|
||||
def result = calc(new FileInputStream(it), MessageDigest.getInstance("SHA-512", BouncyCastleProvider.PROVIDER_NAME))
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
-->
|
||||
Hello everyone,
|
||||
|
||||
... we have created Apache Fineract ${project['fineract.release.version']} release, with the artifacts below up for a vote.
|
||||
We are proud to present Apache Fineract ${project['fineract.release.version']}, with the artifacts below up for a vote. Releases are important for a number of reasons: They put a stamp of approval on a set of code changes and they build momentum for future improvements.
|
||||
|
||||
It fixes the following issues: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
|
||||
Release notes and ChangeLog: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
|
||||
|
||||
Source & Binary files : https://dist.apache.org/repos/dist/dev/fineract/${project['fineract.release.version']}/
|
||||
Source and binary artifacts: https://dist.apache.org/repos/dist/dev/fineract/${project['fineract.release.version']}/
|
||||
|
||||
Tag to be voted on (rc#): https://gitbox.apache.org/repos/asf?p=fineract.git;a=commit;h=refs/heads/${project['fineract.release.version']}
|
||||
Tagged as ${project['fineract.release.version']}
|
||||
|
||||
Fineract's KEYS containing the PGP key we used to sign the release: https://dist.apache.org/repos/dist/dev/fineract/KEYS
|
||||
Committer PGP keys, including the release signing key: https://dist.apache.org/repos/dist/dev/fineract/KEYS
|
||||
|
||||
Note that this release contains source and binary artifacts.
|
||||
|
||||
@@ -38,6 +38,16 @@ This vote will be open for 72 hours:
|
||||
[ ] +0 no opinion
|
||||
[ ] -1 disapprove (and reason why)
|
||||
|
||||
Please indicate if you are a binding vote (member of the PMC).
|
||||
|
||||
Please also indicate with "Tested: YES/NO/PARTIAL" if you have locally built and/or tested these artifacts and/or a clone of the code checked out to the release commit, following the form:
|
||||
|
||||
Tested: YES ... Verified integrity and signatures of release artifacts locally, built from source, ran jar/war: Did everything mentioned in the current release candidate verification guidance ( https://lists.apache.org/thread/hym94pdy3nk9gjspkz4qonv2v15n5dpo ). If you did more than that, please specify.
|
||||
|
||||
Tested: NO ... No testing performed on release candidate, e.g. relying on testing performed by other contributors and/or output of GitHub Actions, while exercising my right to vote.
|
||||
|
||||
Tested: PARTIAL ... Please specify.
|
||||
|
||||
Cheers,
|
||||
|
||||
${project['fineract.config.name']}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
Move the release candidate from the dev area to the release area using a Subversion server-side copy:
|
||||
|
||||
svn mv https://dist.apache.org/repos/dist/dev/fineract/${project['fineract.release.version']} https://dist.apache.org/repos/dist/release /fineract/
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -27,9 +27,9 @@ Following are the typical things we need to verify before voting on a release ca
|
||||
Make sure release artifacts are hosted at https://dist.apache.org/repos/dist/dev/fineract
|
||||
|
||||
* Release candidates should be in format apache-fineract-${project['fineract.release.version']}-binary.tar.gz
|
||||
* Verify signatures and hashes. You may have to import the public key of the release manager to verify the signatures. (`gpg --recv-key <key id>`)
|
||||
* Verify signatures and hashes. You may have to import the public key of the release manager to verify the signatures. (gpg --import KEYS or gpg --recv-key <key id>)
|
||||
* Git tag matches the released bits (diff -rf)
|
||||
* Can compile successfully from source
|
||||
* Can compile docs and code successfully from source
|
||||
* Verify DISCLAIMER, NOTICE and LICENSE (year etc)
|
||||
* All files have correct headers (Rat check should be clean - gradlew rat)
|
||||
* No jar files in the source artifacts
|
||||
|
||||
@@ -21,7 +21,7 @@ version: "3.8"
|
||||
services:
|
||||
fineract:
|
||||
# user: "${FINERACT_USER}:${FINERACT_GROUP}"
|
||||
image: fineract-custom:latest
|
||||
image: ${IMAGE_NAME:-fineract-custom:latest}
|
||||
volumes:
|
||||
- ${PWD}/config/docker/logback/logback-override.xml:/app/logback-override.xml
|
||||
- ${PWD}/config/docker/aws/etc/credentials:/etc/aws/credentials:ro
|
||||
|
||||
@@ -21,7 +21,7 @@ version: "3.8"
|
||||
services:
|
||||
fineract:
|
||||
# user: "${FINERACT_USER}:${FINERACT_GROUP}"
|
||||
image: fineract:latest
|
||||
image: ${IMAGE_NAME:-apache/fineract:latest}
|
||||
volumes:
|
||||
- ${PWD}/config/docker/logback/logback-override.xml:/app/logback-override.xml
|
||||
- ${PWD}/config/docker/aws/etc/credentials:/etc/aws/credentials:ro
|
||||
|
||||
@@ -18,7 +18,7 @@ version: "3.8"
|
||||
services:
|
||||
mariadb:
|
||||
container_name: mariadb
|
||||
image: mariadb:11.2
|
||||
image: mariadb:11.4
|
||||
volumes:
|
||||
- ${PWD}/config/docker/mysql/conf.d/server_collation.cnf:/etc/mysql/conf.d/server_collation.cnf:ro
|
||||
- ${PWD}/config/docker/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:Z,ro
|
||||
|
||||
Vendored
+5
@@ -17,5 +17,10 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=true
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_URL=tcp://activemq:61616
|
||||
FINERACT_EXTERNAL_EVENTS_ENABLED=true
|
||||
FINERACT_EXTERNAL_EVENTS_PRODUCER_JMS_ENABLED=true
|
||||
FINERACT_EXTERNAL_EVENTS_PRODUCER_JMS_TOPIC_NAME=events
|
||||
FINERACT_EXTERNAL_EVENTS_PRODUCER_JMS_BROKER_URL=tcp://activemq:61616
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
|
||||
FINERACT_DEFAULT_MASTER_PASSWORD=fineract
|
||||
FINERACT_MANAGEMENT_ENDPOINT_WEB_EXPOSURE_INCLUDE=health,info,prometheus
|
||||
FINERACT_MANAGEMENT_METRICS_TAGS_APPLICATION=fineract
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=true
|
||||
FINERACT_INSECURE_HTTP_CLIENT=true
|
||||
SPRING_PROFILES_ACTIVE=test,diagnostics
|
||||
OTEL_SERVICE_NAME=fineract
|
||||
|
||||
+1
@@ -17,6 +17,7 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_KAFKA_ENABLED=true
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_KAFKA_BOOTSTRAP_SERVERS=b-3-public.democluster1.am2oyx.c4.kafka.eu-central-1.amazonaws.com:9198,b-2-public.democluster1.am2oyx.c4.kafka.eu-central-1.amazonaws.com:9198,b-1-public.democluster1.am2oyx.c4.kafka.eu-central-1.amazonaws.com:9198
|
||||
|
||||
Vendored
+1
@@ -17,6 +17,7 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED=false
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_KAFKA_ENABLED=true
|
||||
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_KAFKA_BOOTSTRAP_SERVERS=kafka:9092
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract external events'
|
||||
description = 'ACME Fineract Event External Event'
|
||||
|
||||
group = 'com.acme.fineract.event'
|
||||
|
||||
archivesBaseName = 'acme-fineract-event-externalevent'
|
||||
base {
|
||||
archivesName = 'acme-fineract-event-externalevent'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Event Starter'
|
||||
description = 'ACME Fineract Event Starter'
|
||||
|
||||
group = 'com.acme.fineract.event'
|
||||
|
||||
archivesBaseName = 'acme-fineract-event-starter'
|
||||
base {
|
||||
archivesName = 'acme-fineract-event-starter'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract COB Loan'
|
||||
description = 'ACME Fineract Loan COB'
|
||||
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-loan-cob'
|
||||
base {
|
||||
archivesName = 'acme-fineract-loan-cob'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Loan Job'
|
||||
description = 'ACME Fineract Loan Job'
|
||||
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-loan-job'
|
||||
base {
|
||||
archivesName = 'acme-fineract-loan-job'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
+5
-7
@@ -18,26 +18,24 @@
|
||||
*/
|
||||
package com.acme.fineract.loan.job;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.builder.JobBuilder;
|
||||
import org.springframework.batch.core.launch.support.RunIdIncrementer;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class AcmeNoopJobConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@Autowired
|
||||
private AcmeNoopJobTasklet tasklet;
|
||||
private final JobRepository jobRepository;
|
||||
private final PlatformTransactionManager transactionManager;
|
||||
private final AcmeNoopJobTasklet tasklet;
|
||||
|
||||
@Bean
|
||||
protected Step acmeNoopJobStep() {
|
||||
|
||||
@@ -42,4 +42,10 @@
|
||||
<column name="is_mismatched_job" valueBoolean="true"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
<changeSet author="acme" id="2">
|
||||
<update tableName="job">
|
||||
<column name="short_name" value="ACM_NOOP"/>
|
||||
<where>name='Acme Noop Job'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Loan Transaction Processors'
|
||||
description = 'ACME Fineract Loan Processor'
|
||||
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-loan-processor'
|
||||
base {
|
||||
archivesName = 'acme-fineract-loan-processor'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
+5
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package com.acme.fineract.loan.processor;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -28,6 +29,10 @@ public class AcmeLoanRepaymentScheduleTransactionProcessor extends FineractStyle
|
||||
|
||||
public static final String STRATEGY_NAME = "ACME Corp.: standard loan transaction processing strategy";
|
||||
|
||||
public AcmeLoanRepaymentScheduleTransactionProcessor(ExternalIdFactory externalIdFactory) {
|
||||
super(externalIdFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract COB Starter'
|
||||
description = 'ACME Fineract Loan Starter'
|
||||
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-loan-starter'
|
||||
base {
|
||||
archivesName = 'acme-fineract-loan-starter'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Note Service'
|
||||
description = 'ACME Fineract Note Service'
|
||||
|
||||
group = 'com.acme.fineract.portfolio.note'
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-note-service'
|
||||
base {
|
||||
archivesName = 'acme-fineract-note-service'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package com.acme.fineract.portfolio.note.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.portfolio.note.data.NoteData;
|
||||
import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
|
||||
@@ -42,7 +42,7 @@ public class AcmeNoteReadPlatformService implements NoteReadPlatformService, Ini
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoteData> retrieveNotesByResource(Long resourceId, Integer noteTypeId) {
|
||||
public List<NoteData> retrieveNotesByResource(Long resourceId, Integer noteTypeId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -39,21 +39,21 @@ public class AcmeNoteWritePlatformService implements NoteWritePlatformService, I
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createNote(JsonCommand command) {
|
||||
return null;
|
||||
throw new UnsupportedOperationException("createNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateNote(JsonCommand command) {
|
||||
return null;
|
||||
throw new UnsupportedOperationException("updateNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteNote(JsonCommand command) {
|
||||
return null;
|
||||
throw new UnsupportedOperationException("deleteNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAndPersistClientNote(Client client, JsonCommand command) {
|
||||
|
||||
log.warn("createAndPersistClientNote() is intentionally left empty and does nothing.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Note Starter'
|
||||
description = 'ACME Fineract Note Starter'
|
||||
|
||||
group = 'com.acme.fineract.portfolio.note'
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-note-starter'
|
||||
base {
|
||||
archivesName = 'acme-fineract-note-starter'
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
version: "3.7"
|
||||
services:
|
||||
kafka:
|
||||
image: "bitnami/kafka:3.5.1-debian-11-r7"
|
||||
image: "bitnami/kafka:3.8.1-debian-12-r1"
|
||||
ports:
|
||||
- "9092:9092"
|
||||
env_file:
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
activemq:
|
||||
extends:
|
||||
file: ./config/docker/compose/activemq.yml
|
||||
service: activemq
|
||||
|
||||
db:
|
||||
extends:
|
||||
file: ./config/docker/compose/postgresql.yml
|
||||
service: postgresql
|
||||
|
||||
fineract:
|
||||
extends:
|
||||
file: ./config/docker/compose/fineract.yml
|
||||
service: fineract
|
||||
ports:
|
||||
- "8443:8443"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- ./config/docker/env/fineract.env
|
||||
- ./config/docker/env/fineract-common.env
|
||||
- ./config/docker/env/fineract-postgresql.env
|
||||
- ./config/docker/env/activemq.env
|
||||
@@ -20,7 +20,7 @@ version: "3.8"
|
||||
services:
|
||||
# Frontend service
|
||||
community-app:
|
||||
image: openmf/web-app:latest
|
||||
image: openmf/web-app:master
|
||||
container_name: mifos-web-app
|
||||
restart: always
|
||||
ports:
|
||||
|
||||
@@ -31,7 +31,7 @@ compileJava.doLast {
|
||||
javaexec {
|
||||
description = 'Performs EclipseLink static weaving of entity classes'
|
||||
def target = source
|
||||
main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
|
||||
mainClass = 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
|
||||
args '-persistenceinfo', source, source, target
|
||||
classpath sourceSets.main.runtimeClasspath
|
||||
}
|
||||
|
||||
+5
-7
@@ -32,6 +32,7 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.accrual.request.AccrualAccountRequest;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
@@ -54,13 +55,10 @@ public class AccrualAccountingApiResource {
|
||||
@Operation(summary = "Executes Periodic Accrual Accounting", method = "POST", description = "Mandatory Fields\n" + "\n" + "tillDate\n")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = AccrualAccountingApiResourceSwagger.PostRunaccrualsRequest.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String executePeriodicAccrualAccounting(@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().excuteAccrualAccounting().withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
public CommandProcessingResult executePeriodicAccrualAccounting(@Parameter(hidden = true) AccrualAccountRequest accrualAccountRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().excuteAccrualAccounting()
|
||||
.withJson(apiJsonSerializerService.serialize(accrualAccountRequest)).build();
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -24,9 +24,9 @@ public final class AccrualAccountingConstants {
|
||||
|
||||
}
|
||||
|
||||
public static final String accrueTillParamName = "tillDate";
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
public static final String ACCRUE_TILL_PARAM_NAME = "tillDate";
|
||||
public static final String LOCALE_PARAM_NAME = "locale";
|
||||
public static final String DATE_FORMAT_PARAM_NAME = "dateFormat";
|
||||
|
||||
public static final String PERIODIC_ACCRUAL_ACCOUNTING_RESOURCE_NAME = "periodicaccrual";
|
||||
public static final String PERIODIC_ACCRUAL_ACCOUNTING_EXECUTION_ERROR_CODE = "execution.failed";
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.accounting.accrual.request;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
public record AccrualAccountRequest(String locale, String dateFormat, String tillDate) implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
+6
-6
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.accrual.serialization;
|
||||
|
||||
import static org.apache.fineract.accounting.accrual.api.AccrualAccountingConstants.ACCRUE_TILL_PARAM_NAME;
|
||||
import static org.apache.fineract.accounting.accrual.api.AccrualAccountingConstants.PERIODIC_ACCRUAL_ACCOUNTING_RESOURCE_NAME;
|
||||
import static org.apache.fineract.accounting.accrual.api.AccrualAccountingConstants.accrueTillParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
@@ -46,8 +46,8 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public final class AccrualAccountingDataValidator {
|
||||
|
||||
private static final Set<String> LOAN_PERIODIC_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(accrueTillParamName, AccrualAccountingConstants.localeParamName, AccrualAccountingConstants.dateFormatParamName));
|
||||
private static final Set<String> LOAN_PERIODIC_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(ACCRUE_TILL_PARAM_NAME,
|
||||
AccrualAccountingConstants.LOCALE_PARAM_NAME, AccrualAccountingConstants.DATE_FORMAT_PARAM_NAME));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@@ -63,11 +63,11 @@ public final class AccrualAccountingDataValidator {
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(PERIODIC_ACCRUAL_ACCOUNTING_RESOURCE_NAME);
|
||||
|
||||
final LocalDate date = this.fromApiJsonHelper.extractLocalDateNamed(accrueTillParamName, element);
|
||||
baseDataValidator.reset().parameter(accrueTillParamName).value(date).notNull().validateDateBefore(DateUtils.getBusinessLocalDate());
|
||||
final LocalDate date = this.fromApiJsonHelper.extractLocalDateNamed(ACCRUE_TILL_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(ACCRUE_TILL_PARAM_NAME).value(date).notNull()
|
||||
.validateDateBefore(DateUtils.getBusinessLocalDate());
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
}
|
||||
|
||||
public void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public enum GLClosureJsonInputParams {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
return name().replace("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
|
||||
+22
-41
@@ -39,12 +39,10 @@ import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.closure.data.GLClosureData;
|
||||
import org.apache.fineract.accounting.closure.data.request.GLClosureRequest;
|
||||
import org.apache.fineract.accounting.closure.service.GLClosureReadPlatformService;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
@@ -66,10 +64,6 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class GLClosuresApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList("id", "officeId", "officeName", "closingDate", "deleted", "createdDate", "lastUpdatedDate", "createdByUserId",
|
||||
"createdByUsername", "lastUpdatedByUserId", "lastUpdatedByUsername"));
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSION = "GLCLOSURE";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
@@ -85,14 +79,10 @@ public class GLClosuresApiResource {
|
||||
@Operation(summary = "List Accounting closures", description = "Example Requests:\n" + "\n" + "glclosures")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = GLClosuresApiResourceSwagger.GetGlClosureResponse.class)))) })
|
||||
public String retrieveAllClosures(@Context final UriInfo uriInfo,
|
||||
@QueryParam("officeId") @Parameter(name = "officeId") final Long officeId) {
|
||||
public List<GLClosureData> retrieveAllClosures(@QueryParam("officeId") @Parameter(name = "officeId") final Long officeId) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
final List<GLClosureData> glClosureDatas = this.glClosureReadPlatformService.retrieveAllGLClosures(officeId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, glClosureDatas, RESPONSE_DATA_PARAMETERS);
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
return glClosureReadPlatformService.retrieveAllGLClosures(officeId);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -103,19 +93,17 @@ public class GLClosuresApiResource {
|
||||
+ "/glclosures/1?fields=officeName,closingDate")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.GetGlClosureResponse.class))) })
|
||||
public String retreiveClosure(@PathParam("glClosureId") @Parameter(description = "glClosureId") final Long glClosureId,
|
||||
public GLClosureData retreiveClosure(@PathParam("glClosureId") @Parameter(description = "glClosureId") final Long glClosureId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
final GLClosureData glClosureData = this.glClosureReadPlatformService.retrieveGLClosureById(glClosureId);
|
||||
final GLClosureData glClosureData = glClosureReadPlatformService.retrieveGLClosureById(glClosureId);
|
||||
if (settings.isTemplate()) {
|
||||
glClosureData.setAllowedOffices(this.officeReadPlatformService.retrieveAllOfficesForDropdown());
|
||||
glClosureData.setAllowedOffices(officeReadPlatformService.retrieveAllOfficesForDropdown());
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serialize(settings, glClosureData, RESPONSE_DATA_PARAMETERS);
|
||||
return glClosureData;
|
||||
}
|
||||
|
||||
// NOTE: proposal slight changes @Aleks
|
||||
@@ -126,13 +114,11 @@ public class GLClosuresApiResource {
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.PostGlClosuresRequest.class, description = "Request Body")))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.PostGlClosuresResponse.class))) })
|
||||
public String createGLClosure(@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
public CommandProcessingResult createGLClosure(@Parameter(hidden = true) GLClosureRequest glClosureRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLClosure()
|
||||
.withJson(apiJsonSerializerService.serialize(glClosureRequest)).build();
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLClosure().withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -143,13 +129,11 @@ public class GLClosuresApiResource {
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.PutGlClosuresRequest.class, required = true)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.PutGlClosuresResponse.class))) })
|
||||
public String updateGLClosure(@PathParam("glClosureId") @Parameter(description = "glClosureId") final Long glClosureId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLClosure(glClosureId).withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
public CommandProcessingResult updateGLClosure(@PathParam("glClosureId") @Parameter(description = "glClosureId") final Long glClosureId,
|
||||
@Parameter(hidden = true) GLClosureRequest glClosureRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLClosure(glClosureId)
|
||||
.withJson(apiJsonSerializerService.serialize(glClosureRequest)).build();
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -159,12 +143,9 @@ public class GLClosuresApiResource {
|
||||
@Operation(summary = "Delete an accounting closure", description = "Note: Only the latest accounting closure associated with a branch may be deleted.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLClosuresApiResourceSwagger.DeleteGlClosuresResponse.class))) })
|
||||
public String deleteGLClosure(@PathParam("glClosureId") @Parameter(description = "glclosureId") final Long glClosureId) {
|
||||
|
||||
public CommandProcessingResult deleteGLClosure(
|
||||
@PathParam("glClosureId") @Parameter(description = "glclosureId") final Long glClosureId) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGLClosure(glClosureId).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-10
@@ -21,8 +21,6 @@ package org.apache.fineract.accounting.closure.command;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.closure.api.GLClosureJsonInputParams;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
@@ -31,14 +29,7 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
/**
|
||||
* Immutable command for adding an accounting closure
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class GLClosureCommand {
|
||||
|
||||
private final Long id;
|
||||
private final Long officeId;
|
||||
private final LocalDate closingDate;
|
||||
private final String comments;
|
||||
public record GLClosureCommand(Long id, Long officeId, LocalDate closingDate, String comments) {
|
||||
|
||||
public void validateForCreate() {
|
||||
|
||||
|
||||
+6
-1
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.closure.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -30,7 +32,10 @@ import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
* Note: no getter/setters required as google-gson will produce json from fields of object.
|
||||
*/
|
||||
@Data
|
||||
public class GLClosureData {
|
||||
public class GLClosureData implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Long id;
|
||||
private final Long officeId;
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.accounting.closure.data.request;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
public record GLClosureRequest(Long id, Long officeId, String closingDate, String comments, String dateFormat,
|
||||
String locale) implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
+6
-6
@@ -32,21 +32,21 @@ public class GLClosureInvalidException extends AbstractPlatformDomainRuleExcepti
|
||||
FUTURE_DATE, ACCOUNTING_CLOSED;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("FUTURE_DATE")) {
|
||||
if (name().equalsIgnoreCase("FUTURE_DATE")) {
|
||||
return "Accounting closures cannot be made for a future date";
|
||||
} else if (name().toString().equalsIgnoreCase("ACCOUNTING_CLOSED")) {
|
||||
} else if (name().equalsIgnoreCase("ACCOUNTING_CLOSED")) {
|
||||
return "Accounting Closure for this branch has already been defined for a greater date";
|
||||
}
|
||||
return name().toString();
|
||||
return name();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("FUTURE_DATE")) {
|
||||
if (name().equalsIgnoreCase("FUTURE_DATE")) {
|
||||
return "error.msg.glclosure.invalid.future.date";
|
||||
} else if (name().toString().equalsIgnoreCase("ACCOUNTING_CLOSED")) {
|
||||
} else if (name().equalsIgnoreCase("ACCOUNTING_CLOSED")) {
|
||||
return "error.msg.glclosure.invalid.accounting.closed";
|
||||
}
|
||||
return name().toString();
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+49
-68
@@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@@ -41,6 +40,7 @@ import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.financialactivityaccount.data.FinancialActivityAccountData;
|
||||
import org.apache.fineract.accounting.financialactivityaccount.data.request.FinancialActivityAccRequest;
|
||||
import org.apache.fineract.accounting.financialactivityaccount.service.FinancialActivityAccountReadPlatformService;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
@@ -54,9 +54,17 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/financialactivityaccounts")
|
||||
@Component
|
||||
@Tag(name = "Mapping Financial Activities to Accounts", description = "Organization Level Financial Activities like Asset and Liability Transfer can be mapped to GL Account. Integrated accounting takes these accounts into consideration when an Account transfer is made between a savings to loan/savings account and vice-versa\n"
|
||||
+ "\n" + "Field Descriptions\n" + "financialActivityId\n" + "The identifier of the Financial Activity\n" + "glAccountId\n"
|
||||
+ "The identifier of a GL Account ( Ledger Account) which shall be used as the default account for the selected Financial Activity")
|
||||
@Tag(name = "Mapping Financial Activities to Accounts", description = """
|
||||
Organization Level Financial Activities like Asset and Liability Transfer can be mapped to GL Account. \
|
||||
Integrated accounting takes these accounts into consideration when an Account transfer is made between \
|
||||
a savings to loan/savings account and vice-versa
|
||||
|
||||
Field Descriptions
|
||||
financialActivityId
|
||||
The identifier of the Financial Activity
|
||||
glAccountId
|
||||
The identifier of a GL Account ( Ledger Account) which shall be used as the default account for the selected Financial Activity
|
||||
""")
|
||||
@RequiredArgsConstructor
|
||||
public class FinancialActivityAccountsApiResource {
|
||||
|
||||
@@ -70,94 +78,72 @@ public class FinancialActivityAccountsApiResource {
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
|
||||
FinancialActivityAccountData financialActivityAccountData = this.financialActivityAccountReadPlatformService
|
||||
.getFinancialActivityAccountTemplate();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, financialActivityAccountData,
|
||||
FinancialActivityAccountsConstants.RESPONSE_DATA_PARAMETERS);
|
||||
public FinancialActivityAccountData retrieveTemplate() {
|
||||
context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
return financialActivityAccountReadPlatformService.getFinancialActivityAccountTemplate();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List Financial Activities to Accounts Mappings", description = "Example Requests:\n" + "\n"
|
||||
+ "financialactivityaccounts")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class)))) })
|
||||
public String retrieveAll(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
final List<FinancialActivityAccountData> financialActivityAccounts = this.financialActivityAccountReadPlatformService.retrieveAll();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, financialActivityAccounts,
|
||||
FinancialActivityAccountsConstants.RESPONSE_DATA_PARAMETERS);
|
||||
@Operation(summary = "List Financial Activities to Accounts Mappings", description = """
|
||||
Example Requests:
|
||||
financialactivityaccounts""")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class))))
|
||||
public List<FinancialActivityAccountData> retrieveAll() {
|
||||
context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
return financialActivityAccountReadPlatformService.retrieveAll();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{mappingId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Financial Activity to Account Mapping\n", description = "Example Requests:\n" + "\n"
|
||||
+ "financialactivityaccounts/1")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class))) })
|
||||
public String retreive(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId,
|
||||
@Operation(summary = "Retrieve a Financial Activity to Account Mapping\n", description = """
|
||||
Example Requests:
|
||||
financialactivityaccounts/1""")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class)))
|
||||
public FinancialActivityAccountData retreive(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
FinancialActivityAccountData financialActivityAccountData = this.financialActivityAccountReadPlatformService.retrieve(mappingId);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
FinancialActivityAccountData financialActivityAccountData = financialActivityAccountReadPlatformService.retrieve(mappingId);
|
||||
if (settings.isTemplate()) {
|
||||
financialActivityAccountData = this.financialActivityAccountReadPlatformService
|
||||
.addTemplateDetails(financialActivityAccountData);
|
||||
financialActivityAccountData = financialActivityAccountReadPlatformService.addTemplateDetails(financialActivityAccountData);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serialize(settings, financialActivityAccountData,
|
||||
FinancialActivityAccountsConstants.RESPONSE_DATA_PARAMETERS);
|
||||
return financialActivityAccountData;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create a new Financial Activity to Accounts Mapping", description = "Mandatory Fields\n"
|
||||
+ "financialActivityId, glAccountId")
|
||||
@Operation(summary = "Create a new Financial Activity to Accounts Mapping", description = """
|
||||
Mandatory Fields
|
||||
financialActivityId, glAccountId""")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsResponse.class))) })
|
||||
public String createGLAccount(@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsResponse.class)))
|
||||
public CommandProcessingResult createGLAccount(@Parameter(hidden = true) FinancialActivityAccRequest activityAccRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createOfficeToGLAccountMapping()
|
||||
.withJson(apiJsonSerializerService.serialize(activityAccRequest)).build();
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createOfficeToGLAccountMapping().withJson(jsonRequestBody)
|
||||
.build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{mappingId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update a Financial Activity to Account Mapping", description = "the API updates the Ledger account linked to a Financial Activity \n")
|
||||
@Operation(summary = "Update a Financial Activity to Account Mapping", description = "the API updates the Ledger account linked to a Financial Activity")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PutFinancialActivityAccountsResponse.class))) })
|
||||
public String updateGLAccount(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.PutFinancialActivityAccountsResponse.class)))
|
||||
public CommandProcessingResult updateGLAccount(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId,
|
||||
@Parameter(hidden = true) FinancialActivityAccRequest activityAccRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateOfficeToGLAccountMapping(mappingId)
|
||||
.withJson(jsonRequestBody).build();
|
||||
.withJson(apiJsonSerializerService.serialize(activityAccRequest)).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -165,14 +151,9 @@ public class FinancialActivityAccountsApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete a Financial Activity to Account Mapping")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.DeleteFinancialActivityAccountsResponse.class))) })
|
||||
public String deleteGLAccount(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId) {
|
||||
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FinancialActivityAccountsApiResourceSwagger.DeleteFinancialActivityAccountsResponse.class)))
|
||||
public CommandProcessingResult deleteGLAccount(@PathParam("mappingId") @Parameter(description = "mappingId") final Long mappingId) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteOfficeToGLAccountMapping(mappingId).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public enum FinancialActivityAccountsJsonInputParams {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
return name().replace("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.accounting.financialactivityaccount.data.request;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
public record FinancialActivityAccRequest(Long financialActivityId, Long glAccountId) implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
+6
-4
@@ -26,17 +26,19 @@ import org.springframework.dao.EmptyResultDataAccessException;
|
||||
*/
|
||||
public class FinancialActivityAccountNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
private static final String DOES_NOT_EXIST = " does not exist";
|
||||
private static final String ERROR_CODE = "error.msg.financialActivityAccount.not.found";
|
||||
|
||||
public FinancialActivityAccountNotFoundException(final Long id) {
|
||||
super("error.msg.financialActivityAccount.not.found", "Financial Activity account with Id " + id + " does not exist", id);
|
||||
super(ERROR_CODE, "Financial Activity account with Id " + id + DOES_NOT_EXIST, id);
|
||||
}
|
||||
|
||||
public FinancialActivityAccountNotFoundException(final Long id, EmptyResultDataAccessException e) {
|
||||
super("error.msg.financialActivityAccount.not.found", "Financial Activity account with Id " + id + " does not exist", id, e);
|
||||
super(ERROR_CODE, "Financial Activity account with Id " + id + DOES_NOT_EXIST, id, e);
|
||||
}
|
||||
|
||||
public FinancialActivityAccountNotFoundException(final Integer financialActivityType) {
|
||||
super("error.msg.financialActivityAccount.not.found",
|
||||
"Financial Activity account with for the financial Activity with Id " + financialActivityType + " does not exist",
|
||||
super(ERROR_CODE, "Financial Activity account with for the financial Activity with Id " + financialActivityType + DOES_NOT_EXIST,
|
||||
financialActivityType);
|
||||
}
|
||||
|
||||
|
||||
+96
-104
@@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
@@ -41,14 +40,12 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants;
|
||||
import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
|
||||
import org.apache.fineract.accounting.glaccount.command.GLAccountCommand;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.service.GLAccountReadPlatformService;
|
||||
@@ -74,17 +71,13 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/glaccounts")
|
||||
@Component
|
||||
@Tag(name = "General Ledger Account", description = "Ledger accounts represent an Individual account within an Organizations Chart Of Accounts(COA) and are assigned a name and unique number by which they can be identified. \n"
|
||||
+ "All transactions relating to a company's assets, liabilities, owners' equity, revenue and expenses are recorded against these accounts")
|
||||
@Tag(name = "General Ledger Account", description = """
|
||||
Ledger accounts represent an Individual account within an Organizations Chart Of Accounts(COA) and are assigned a name and unique number by which they can be identified.
|
||||
All transactions relating to a company's assets, liabilities, owners' equity, revenue and expenses are recorded against these accounts
|
||||
""")
|
||||
@RequiredArgsConstructor
|
||||
public class GLAccountsApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "name", "parentId", "glCode", "disabled",
|
||||
"manualEntriesAllowed", "type", "usage", "description", "assetHeaderAccountOptions", "liabilityHeaderAccountOptions",
|
||||
"equityHeaderAccountOptions", "incomeHeaderAccountOptions", "expenseHeaderAccountOptions", "nameDecorated", "tagId",
|
||||
"allowedAssetsTagOptions", "allowedLiabilitiesTagOptions", "allowedEquityTagOptions", "allowedIncomeTagOptions",
|
||||
"allowedExpensesTagOptions", "creditAccounts", "debitAccounts"));
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSION = "GLACCOUNT";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
@@ -102,91 +95,103 @@ public class GLAccountsApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = {
|
||||
"General Ledger Account" }, summary = "Retrieve GL Accounts Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
|
||||
+ "\n" + "Field Defaults\n" + "Allowed Value Lists\n" + "Example Request:\n" + "\n" + "glaccounts/template\n"
|
||||
+ "glaccounts/template?type=1\n" + "\n" + "type is optional and integer value from 1 to 5.\n" + "\n" + "1.Assets \n"
|
||||
+ "2.Liabilities \n" + "3.Equity \n" + "4.Income \n" + "5.Expenses")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsTemplateResponse.class))) })
|
||||
public String retrieveNewAccountDetails(@Context final UriInfo uriInfo,
|
||||
@QueryParam("type") @Parameter(description = "type") final Integer type) {
|
||||
"General Ledger Account" }, summary = "Retrieve GL Accounts Template", description = """
|
||||
This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:
|
||||
|
||||
Field Defaults
|
||||
Allowed Value Lists
|
||||
Example Request:
|
||||
|
||||
glaccounts/template
|
||||
glaccounts/template?type=1
|
||||
|
||||
type is optional and integer value from 1 to 5.
|
||||
|
||||
1.Assets
|
||||
2.Liabilities
|
||||
3.Equity
|
||||
4.Income
|
||||
5.Expenses
|
||||
""")
|
||||
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsTemplateResponse.class)))
|
||||
public GLAccountData retrieveNewAccountDetails(@QueryParam("type") @Parameter(description = "type") final Integer type) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
|
||||
GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveNewGLAccountDetails(type);
|
||||
glAccountData = handleTemplate(glAccountData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, glAccountData, RESPONSE_DATA_PARAMETERS);
|
||||
return handleTemplate(this.glAccountReadPlatformService.retrieveNewGLAccountDetails(type));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "List General Ledger Accounts", description = "ARGUMENTS\n"
|
||||
+ "type Integer optional manualEntriesAllowed boolean optional usage Integer optional disabled boolean optional parentId Long optional tagId Long optional\n"
|
||||
+ "Example Requests:\n" + "\n" + "glaccounts\n" + "\n" + "\n"
|
||||
+ "glaccounts?type=1&manualEntriesAllowed=true&usage=1&disabled=false\n" + "\n" + "glaccounts?fetchRunningBalance=true")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class)))) })
|
||||
public String retrieveAllAccounts(@Context final UriInfo uriInfo,
|
||||
@QueryParam("type") @Parameter(description = "type") final Integer type,
|
||||
@Operation(tags = {
|
||||
"General Ledger Account" }, summary = "List General Ledger Account", description = """
|
||||
ARGUMENTS
|
||||
type Integer optional manualEntriesAllowed boolean optional usage Integer optional disabled boolean optional parentId Long optional tagId Long optional
|
||||
Example Requests:
|
||||
|
||||
glaccounts
|
||||
|
||||
glaccounts?type=1&manualEntriesAllowed=true&usage=1&disabled=false
|
||||
|
||||
glaccounts?fetchRunningBalance=true
|
||||
""")
|
||||
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class))))
|
||||
public List<GLAccountData> retrieveAllAccounts(@QueryParam("type") @Parameter(description = "type") final Integer type,
|
||||
@QueryParam("searchParam") @Parameter(description = "searchParam") final String searchParam,
|
||||
@QueryParam("usage") @Parameter(description = "usage") final Integer usage,
|
||||
@QueryParam("manualEntriesAllowed") @Parameter(description = "manualEntriesAllowed") final Boolean manualEntriesAllowed,
|
||||
@QueryParam("disabled") @Parameter(description = "disabled") final Boolean disabled,
|
||||
@QueryParam("fetchRunningBalance") @Parameter(description = "fetchRunningBalance") final boolean runningBalance) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(false, runningBalance);
|
||||
final List<GLAccountData> glAccountDatas = this.glAccountReadPlatformService.retrieveAllGLAccounts(type, searchParam, usage,
|
||||
manualEntriesAllowed, disabled, associationParametersData);
|
||||
return this.glAccountReadPlatformService.retrieveAllGLAccounts(type, searchParam, usage, manualEntriesAllowed, disabled,
|
||||
associationParametersData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, glAccountDatas, RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{glAccountId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "Retrieve a General Ledger Account", description = "Example Requests:\n"
|
||||
+ "\n" + "glaccounts/1\n" + "\n" + "\n" + "glaccounts/1?template=true\n" + "\n" + "\n" + "glaccounts/1?fields=name,glCode\n"
|
||||
+ "\n" + "\n" + "glaccounts/1?fetchRunningBalance=true")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class))) })
|
||||
public String retreiveAccount(@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId,
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "Retrieve a General Ledger Account", description = """
|
||||
Example Requests:
|
||||
|
||||
glaccounts/1
|
||||
|
||||
glaccounts/1?template=true
|
||||
|
||||
glaccounts/1?fields=name,glCode
|
||||
|
||||
glaccounts/1?fetchRunningBalance=true
|
||||
""")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class)))
|
||||
public GLAccountData retreiveAccount(@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId,
|
||||
@Context final UriInfo uriInfo,
|
||||
@QueryParam("fetchRunningBalance") @Parameter(description = "fetchRunningBalance") final boolean runningBalance) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(false, runningBalance);
|
||||
GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveGLAccountById(glAccountId, associationParametersData);
|
||||
if (settings.isTemplate()) {
|
||||
glAccountData = handleTemplate(glAccountData);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serialize(settings, glAccountData, RESPONSE_DATA_PARAMETERS);
|
||||
final GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveGLAccountById(glAccountId, associationParametersData);
|
||||
return settings.isTemplate() ? handleTemplate(glAccountData) : glAccountData;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = {
|
||||
"General Ledger Account" }, summary = "Create a General Ledger Account", description = "Note: You may optionally create Hierarchical Chart of Accounts by using the \"parentId\" property of an Account\n"
|
||||
+ "Mandatory Fields: \n" + "name, glCode, type, usage and manualEntriesAllowed")
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "Create a General Ledger Account", description = """
|
||||
Note: You may optionally create Hierarchical Chart of Accounts by using the "parentId" property of an Account
|
||||
Mandatory Fields:
|
||||
name, glCode, type, usage and manualEntriesAllowed
|
||||
""")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PostGLAccountsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PostGLAccountsResponse.class))) })
|
||||
public String createGLAccount(@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLAccount().withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PostGLAccountsResponse.class)))
|
||||
public CommandProcessingResult createGLAccount(@Parameter(hidden = true) GLAccountCommand glAccountCommand) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLAccount()
|
||||
.withJson(apiJsonSerializerService.serialize(glAccountCommand)).build();
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -195,16 +200,12 @@ public class GLAccountsApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "Update a GL Account", description = "Updates a GL Account")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PutGLAccountsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PutGLAccountsResponse.class))) })
|
||||
public String updateGLAccount(@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLAccount(glAccountId).withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.PutGLAccountsResponse.class)))
|
||||
public CommandProcessingResult updateGLAccount(@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId,
|
||||
@Parameter(hidden = true) GLAccountCommand accountCommand) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLAccount(glAccountId)
|
||||
.withJson(apiJsonSerializerService.serialize(accountCommand)).build();
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -212,15 +213,30 @@ public class GLAccountsApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(tags = { "General Ledger Account" }, summary = "Delete a GL Account", description = "Deletes a GL Account")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.DeleteGLAccountsRequest.class))) })
|
||||
public String deleteGLAccount(@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId) {
|
||||
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GLAccountsApiResourceSwagger.DeleteGLAccountsRequest.class)))
|
||||
public CommandProcessingResult deleteGLAccount(
|
||||
@PathParam("glAccountId") @Parameter(description = "glAccountId") final Long glAccountId) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGLAccount(glAccountId).build();
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
@GET
|
||||
@Path("downloadtemplate")
|
||||
@Produces("application/vnd.ms-excel")
|
||||
public Response getGlAccountsTemplate(@QueryParam("dateFormat") final String dateFormat) {
|
||||
return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.CHART_OF_ACCOUNTS.toString(), null, null, dateFormat);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
@POST
|
||||
@Path("uploadtemplate")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@RequestBody(description = "Upload GL accounts template", content = {
|
||||
@Content(mediaType = MediaType.MULTIPART_FORM_DATA, schema = @Schema(implementation = UploadRequest.class)) })
|
||||
public Long postGlAccountsTemplate(@FormDataParam("file") InputStream uploadedInputStream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale,
|
||||
@FormDataParam("dateFormat") final String dateFormat) {
|
||||
return bulkImportWorkbookService.importWorkbook(GlobalEntityType.CHART_OF_ACCOUNTS.toString(), uploadedInputStream, fileDetail,
|
||||
locale, dateFormat);
|
||||
}
|
||||
|
||||
private GLAccountData handleTemplate(final GLAccountData glAccountData) {
|
||||
@@ -262,30 +278,6 @@ public class GLAccountsApiResource {
|
||||
}
|
||||
|
||||
private List<GLAccountData> defaultIfEmpty(final List<GLAccountData> list) {
|
||||
List<GLAccountData> returnList = null;
|
||||
if (list != null && !list.isEmpty()) {
|
||||
returnList = list;
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("downloadtemplate")
|
||||
@Produces("application/vnd.ms-excel")
|
||||
public Response getGlAccountsTemplate(@QueryParam("dateFormat") final String dateFormat) {
|
||||
return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.CHART_OF_ACCOUNTS.toString(), null, null, dateFormat);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("uploadtemplate")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@RequestBody(description = "Upload GL accounts template", content = {
|
||||
@Content(mediaType = MediaType.MULTIPART_FORM_DATA, schema = @Schema(implementation = UploadRequest.class)) })
|
||||
public String postGlAccountsTemplate(@FormDataParam("file") InputStream uploadedInputStream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale,
|
||||
@FormDataParam("dateFormat") final String dateFormat) {
|
||||
Long importDocumentId = bulkImportWorkbookService.importWorkbook(GlobalEntityType.CHART_OF_ACCOUNTS.toString(), uploadedInputStream,
|
||||
fileDetail, locale, dateFormat);
|
||||
return this.apiJsonSerializerService.serialize(importDocumentId);
|
||||
return list != null && !list.isEmpty() ? list : null;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-15
@@ -20,8 +20,6 @@ package org.apache.fineract.accounting.glaccount.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.glaccount.api.GLAccountJsonInputParams;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
|
||||
@@ -32,20 +30,9 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
/**
|
||||
* Immutable command for adding a general Ledger Account
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class GLAccountCommand {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final Long parentId;
|
||||
private final String glCode;
|
||||
private final Boolean disabled;
|
||||
private final Boolean manualEntriesAllowed;
|
||||
private final Integer type;
|
||||
private final Integer usage;
|
||||
private final String description;
|
||||
private final Long tagId;
|
||||
public record GLAccountCommand(Long id, String name, Long parentId, String glCode, Boolean disabled, Boolean manualEntriesAllowed,
|
||||
Integer type, Integer usage, String description, Long tagId) {
|
||||
|
||||
public void validateForCreate() {
|
||||
|
||||
|
||||
+2
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.glaccount.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -28,6 +29,7 @@ import lombok.experimental.Accessors;
|
||||
@Accessors(chain = true)
|
||||
public class GLAccountDataForLookup implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
|
||||
+8
-8
@@ -28,24 +28,24 @@ public class GLAccountInvalidDeleteException extends AbstractPlatformDomainRuleE
|
||||
/*** Enum of reasons for invalid delete **/
|
||||
public enum GlAccountInvalidDeleteReason {
|
||||
|
||||
TRANSANCTIONS_LOGGED, HAS_CHILDREN;
|
||||
TRANSACTIONS_LOGGED, HAS_CHILDREN;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("TRANSANCTIONS_LOGGED")) {
|
||||
if (name().equalsIgnoreCase("TRANSACTIONS_LOGGED")) {
|
||||
return "This GL Account cannot be deleted as it has transactions logged against it";
|
||||
} else if (name().toString().equalsIgnoreCase("HAS_CHILDREN")) {
|
||||
return "Cannot delete this Header GL Account without first deleting or reassinging its children";
|
||||
} else if (name().equalsIgnoreCase("HAS_CHILDREN")) {
|
||||
return "Cannot delete this Header GL Account without first deleting or reassigning its children";
|
||||
}
|
||||
return name().toString();
|
||||
return name();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("TRANSANCTIONS_LOGGED")) {
|
||||
if (name().equalsIgnoreCase("TRANSACTIONS_LOGGED")) {
|
||||
return "error.msg.glaccount.glcode.invalid.delete.transactions.logged";
|
||||
} else if (name().toString().equalsIgnoreCase("HAS_CHILDREN")) {
|
||||
} else if (name().equalsIgnoreCase("HAS_CHILDREN")) {
|
||||
return "error.msg.glaccount.glcode.invalid.delete.has.children";
|
||||
}
|
||||
return name().toString();
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-9
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.glaccount.jobs.updatetrialbalancedetails;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.glaccount.domain.TrialBalanceRepositoryWrapper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
|
||||
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
||||
@@ -27,22 +28,18 @@ import org.springframework.batch.core.job.builder.JobBuilder;
|
||||
import org.springframework.batch.core.launch.support.RunIdIncrementer;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class UpdateTrialBalanceDetailsConfig {
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@Autowired
|
||||
private RoutingDataSourceServiceFactory dataSourceServiceFactory;
|
||||
@Autowired
|
||||
private TrialBalanceRepositoryWrapper trialBalanceRepositoryWrapper;
|
||||
private final JobRepository jobRepository;
|
||||
private final PlatformTransactionManager transactionManager;
|
||||
private final RoutingDataSourceServiceFactory dataSourceServiceFactory;
|
||||
private final TrialBalanceRepositoryWrapper trialBalanceRepositoryWrapper;
|
||||
|
||||
@Bean
|
||||
protected Step updateTrialBalanceDetailsStep() {
|
||||
|
||||
+1
-2
@@ -20,7 +20,6 @@ package org.apache.fineract.accounting.glaccount.jobs.updatetrialbalancedetails;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -51,7 +50,7 @@ public class UpdateTrialBalanceDetailsTasklet implements Tasklet {
|
||||
.append("where je.transaction_date > (select coalesce(MAX(created_date),'2010-01-01') from m_trial_balance)");
|
||||
final List<LocalDate> tbGaps = jdbcTemplate.queryForList(tbGapSqlBuilder.toString(), LocalDate.class);
|
||||
for (LocalDate tbGap : tbGaps) {
|
||||
int days = Math.toIntExact(ChronoUnit.DAYS.between(tbGap, DateUtils.getBusinessLocalDate()));
|
||||
int days = DateUtils.getExactDifferenceInDays(tbGap, DateUtils.getBusinessLocalDate());
|
||||
if (days < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+25
-36
@@ -44,10 +44,12 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformService {
|
||||
|
||||
private static final String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '.', '')) - 1) * 4)), name)";
|
||||
private static final String NAME_DECORATED_BASE_ON_HIERARCHY = "concat(substring('........................................', 1, ((LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '.', '')) - 1) * 4)), name)";
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private static final String SQL_AND = " and ";
|
||||
|
||||
private static final class GLAccountMapper implements RowMapper<GLAccountData> {
|
||||
|
||||
private final JournalEntryAssociationParametersData associationParametersData;
|
||||
@@ -65,7 +67,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
sb.append(
|
||||
" gl.id as id, name as name, parent_id as parentId, gl_code as glCode, disabled as disabled, manual_journal_entries_allowed as manualEntriesAllowed, ")
|
||||
.append("classification_enum as classification, account_usage as accountUsage, gl.description as description, ")
|
||||
.append(nameDecoratedBaseOnHierarchy).append(" as nameDecorated, ")
|
||||
.append(NAME_DECORATED_BASE_ON_HIERARCHY).append(" as nameDecorated, ")
|
||||
.append("cv.id as codeId, cv.code_value as codeValue ");
|
||||
if (this.associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append(",gl_j.organization_running_balance as organizationRunningBalance ");
|
||||
@@ -109,28 +111,22 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
public List<GLAccountData> retrieveAllGLAccounts(final Integer accountClassification, final String searchParam, final Integer usage,
|
||||
final Boolean manualTransactionsAllowed, final Boolean disabled,
|
||||
JournalEntryAssociationParametersData associationParametersData) {
|
||||
if (accountClassification != null) {
|
||||
if (!checkValidGLAccountType(accountClassification)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
if (accountClassification != null && !checkValidGLAccountType(accountClassification)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
if (usage != null) {
|
||||
if (!checkValidGLAccountUsage(usage)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
if (usage != null && !checkValidGLAccountUsage(usage)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
String sql = "select " + rm.schema();
|
||||
// append SQL statement for fetching account totals
|
||||
if (associationParametersData != null) {
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
|
||||
+ "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = true "
|
||||
+ "group by account_id desc, id) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
|
||||
+ "group by t2.account_id desc) t1)";
|
||||
}
|
||||
if (associationParametersData != null && associationParametersData.isRunningBalanceRequired()) {
|
||||
sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
|
||||
+ "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = true "
|
||||
+ "group by account_id desc, id) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
|
||||
+ "group by t2.account_id desc) t1)";
|
||||
}
|
||||
final Object[] parameterArray = new Object[3];
|
||||
int arrayPos = 0;
|
||||
@@ -151,7 +147,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
}
|
||||
if (StringUtils.isNotBlank(searchParam)) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += " and ";
|
||||
sql += SQL_AND;
|
||||
}
|
||||
sql += " ( name like %?% or gl_code like %?% )";
|
||||
parameterArray[arrayPos] = searchParam;
|
||||
@@ -162,7 +158,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
}
|
||||
if (usage != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += " and ";
|
||||
sql += SQL_AND;
|
||||
}
|
||||
if (GLAccountUsage.HEADER.getValue().equals(usage)) {
|
||||
sql += " account_usage = 2 ";
|
||||
@@ -173,7 +169,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
}
|
||||
if (manualTransactionsAllowed != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += " and ";
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " manual_journal_entries_allowed = " + manualTransactionsAllowed;
|
||||
@@ -181,37 +177,32 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
}
|
||||
if (disabled != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += " and ";
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " disabled = " + disabled;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
sql += " ORDER BY gl_code ASC";
|
||||
|
||||
final Object[] finalObjectArray = Arrays.copyOf(parameterArray, arrayPos);
|
||||
return this.jdbcTemplate.query(sql, rm, finalObjectArray); // NOSONAR
|
||||
return this.jdbcTemplate.query(sql, rm, (Object[]) finalObjectArray);// NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData retrieveGLAccountById(final long glAccountId, JournalEntryAssociationParametersData associationParametersData) {
|
||||
try {
|
||||
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
final StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ").append(rm.schema());
|
||||
sql.append(" where gl.id = ?");
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sql.append(" and gl_j.is_running_balance_calculated = true ");
|
||||
sql.append(" and gl_j.is_running_balance_calculated = true ")
|
||||
.append(" ORDER BY gl_j.entry_date DESC,gl_j.id DESC LIMIT 1");
|
||||
}
|
||||
sql.append("where gl.id = ?");
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sql.append(" ORDER BY gl_j.entry_date DESC,gl_j.id DESC LIMIT 1");
|
||||
}
|
||||
final GLAccountData glAccountData = this.jdbcTemplate.queryForObject(sql.toString(), rm, new Object[] { glAccountId });
|
||||
|
||||
return glAccountData;
|
||||
return this.jdbcTemplate.queryForObject(sql.toString(), rm, new Object[] { glAccountId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new GLAccountNotFoundException(glAccountId, e);
|
||||
}
|
||||
@@ -261,15 +252,13 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
|
||||
@Override
|
||||
public List<GLAccountDataForLookup> retrieveAccountsByTagId(final Long ruleId, final Integer transactionType) {
|
||||
final GLAccountDataLookUpMapper mapper = new GLAccountDataLookUpMapper();
|
||||
final String sql = "Select " + mapper.schema() + " where rule.id=? and tags.acc_type_enum=?";
|
||||
return this.jdbcTemplate.query(sql, mapper, new Object[] { ruleId, transactionType }); // NOSONAR
|
||||
final String sql = "Select " + GLAccountDataLookUpMapper.LOOKUP_SCHEMA + " where rule.id=? and tags.acc_type_enum=?";
|
||||
return this.jdbcTemplate.query(sql, mapper, (Object[]) new Object[] { ruleId, transactionType });// NOSONAR
|
||||
}
|
||||
|
||||
private static final class GLAccountDataLookUpMapper implements RowMapper<GLAccountDataForLookup> {
|
||||
|
||||
public String schema() {
|
||||
return " gl.id as id, gl.name as name, gl.gl_code as glCode from acc_accounting_rule rule join acc_rule_tags tags on tags.acc_rule_id = rule.id join acc_gl_account gl on gl.tag_id=tags.tag_id";
|
||||
}
|
||||
private static final String LOOKUP_SCHEMA = " gl.id as id, gl.name as name, gl.gl_code as glCode from acc_accounting_rule rule join acc_rule_tags tags on tags.acc_rule_id = rule.id join acc_gl_account gl on gl.tag_id=tags.tag_id";
|
||||
|
||||
@Override
|
||||
public GLAccountDataForLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
|
||||
final boolean journalEntriesForAccountExist = this.glJournalEntryRepository
|
||||
.exists((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("glAccountId"), glAccountId));
|
||||
if (journalEntriesForAccountExist) {
|
||||
throw new GLAccountInvalidDeleteException(GlAccountInvalidDeleteReason.TRANSANCTIONS_LOGGED, glAccountId);
|
||||
throw new GLAccountInvalidDeleteException(GlAccountInvalidDeleteReason.TRANSACTIONS_LOGGED, glAccountId);
|
||||
}
|
||||
this.glAccountRepository.delete(glAccount);
|
||||
|
||||
|
||||
+5
-5
@@ -27,6 +27,7 @@ import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
@@ -54,6 +55,7 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
@Column(name = "currency_code", length = 3, nullable = false)
|
||||
private String currencyCode;
|
||||
|
||||
@Setter
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reversal_id")
|
||||
private JournalEntry reversalJournalEntry;
|
||||
@@ -73,6 +75,7 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
@Column(name = "share_transaction_id")
|
||||
private Long shareTransactionId;
|
||||
|
||||
@Setter
|
||||
@Column(name = "reversed", nullable = false)
|
||||
private boolean reversed = false;
|
||||
|
||||
@@ -147,11 +150,8 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
return JournalEntryType.DEBIT.getValue().equals(this.type);
|
||||
}
|
||||
|
||||
public void setReversalJournalEntry(final JournalEntry reversalJournalEntry) {
|
||||
this.reversalJournalEntry = reversalJournalEntry;
|
||||
public boolean isCreditEntry() {
|
||||
return JournalEntryType.CREDIT.getValue().equals(this.type);
|
||||
}
|
||||
|
||||
public void setReversed(final boolean reversed) {
|
||||
this.reversed = reversed;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -29,6 +29,7 @@ import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentType;
|
||||
@@ -63,10 +64,14 @@ public class ProductToGLAccountMapping extends AbstractPersistableCustom<Long> {
|
||||
@Column(name = "financial_account_type", nullable = true)
|
||||
private int financialAccountType;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "charge_off_reason_id", nullable = true)
|
||||
private CodeValue chargeOffReason;
|
||||
|
||||
public static ProductToGLAccountMapping createNew(final GLAccount glAccount, final Long productId, final int productType,
|
||||
final int financialAccountType) {
|
||||
final int financialAccountType, final CodeValue chargeOffReason) {
|
||||
|
||||
return new ProductToGLAccountMapping().setGlAccount(glAccount).setProductId(productId).setProductType(productType)
|
||||
.setFinancialAccountType(financialAccountType);
|
||||
.setFinancialAccountType(financialAccountType).setChargeOffReason(chargeOffReason);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -35,7 +35,7 @@ public interface ProductToGLAccountMappingRepository
|
||||
@Param("productType") int productType, @Param("financialAccountType") int financialAccountType,
|
||||
@Param("chargeId") Long ChargeId);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId and mapping.productType =:productType and mapping.financialAccountType=:financialAccountType and mapping.paymentType is NULL and mapping.charge is NULL")
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId and mapping.productType =:productType and mapping.financialAccountType=:financialAccountType and mapping.paymentType is NULL and mapping.charge is NULL and mapping.chargeOffReason is NULL")
|
||||
ProductToGLAccountMapping findCoreProductToFinAccountMapping(@Param("productId") Long productId, @Param("productType") int productType,
|
||||
@Param("financialAccountType") int financialAccountType);
|
||||
|
||||
@@ -61,4 +61,25 @@ public interface ProductToGLAccountMappingRepository
|
||||
@Param("productType") int productType);
|
||||
|
||||
List<ProductToGLAccountMapping> findByProductIdAndProductType(Long productId, int productType);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId and mapping.productType =:productType and mapping.chargeOffReason is not NULL")
|
||||
List<ProductToGLAccountMapping> findAllChargeOffReasonsMappings(@Param("productId") Long productId,
|
||||
@Param("productType") int productType);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.chargeOffReason.id =:chargeOffReasonId AND mapping.productId =:productId AND mapping.productType =:productType")
|
||||
ProductToGLAccountMapping findChargeOffReasonMapping(@Param("productId") Long productId, @Param("productType") Integer productType,
|
||||
@Param("chargeOffReasonId") Long chargeOffReasonId);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId AND mapping.productType =:productType AND mapping.charge IS NULL AND mapping.paymentType IS NULL AND mapping.chargeOffReason IS NULL")
|
||||
List<ProductToGLAccountMapping> findAllRegularMappings(@Param("productId") Long productId, @Param("productType") Integer productType);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId and mapping.productType =:productType and mapping.paymentType is not NULL")
|
||||
List<ProductToGLAccountMapping> findAllPaymentTypeMappings(@Param("productId") Long productId,
|
||||
@Param("productType") Integer productType);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId AND mapping.productType =:productType AND mapping.charge.penalty = TRUE")
|
||||
List<ProductToGLAccountMapping> findAllPenaltyMappings(@Param("productId") Long productId, @Param("productType") Integer productType);
|
||||
|
||||
@Query("select mapping from ProductToGLAccountMapping mapping where mapping.productId =:productId AND mapping.productType =:productType AND mapping.charge.penalty = FALSE")
|
||||
List<ProductToGLAccountMapping> findAllFeeMappings(@Param("productId") Long productId, @Param("productType") Integer productType);
|
||||
}
|
||||
|
||||
+141
@@ -27,6 +27,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForLoan;
|
||||
@@ -39,7 +40,11 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGL
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingInvalidException;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingNotFoundException;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
@@ -53,6 +58,7 @@ import org.springframework.stereotype.Component;
|
||||
public class ProductToGLAccountMappingHelper {
|
||||
|
||||
protected static final List<GLAccountType> ASSET_LIABILITY_TYPES = List.of(GLAccountType.ASSET, GLAccountType.LIABILITY);
|
||||
private static final Integer GL_ACCOUNT_EXPENSE_TYPE = 5;
|
||||
|
||||
protected final GLAccountRepository accountRepository;
|
||||
protected final ProductToGLAccountMappingRepository accountMappingRepository;
|
||||
@@ -60,6 +66,7 @@ public class ProductToGLAccountMappingHelper {
|
||||
private final ChargeRepositoryWrapper chargeRepositoryWrapper;
|
||||
protected final GLAccountRepositoryWrapper accountRepositoryWrapper;
|
||||
private final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper;
|
||||
private final CodeValueRepository codeValueRepository;
|
||||
|
||||
public void saveProductToAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId, final GLAccountType expectedAccountType, final PortfolioProductType portfolioProductType) {
|
||||
@@ -194,6 +201,27 @@ public class ProductToGLAccountMappingHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveChargeOffReasonToGLAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes, final PortfolioProductType portfolioProductType) {
|
||||
|
||||
final String arrayName = LoanProductAccountingParams.CHARGE_OFF_REASON_TO_EXPENSE_ACCOUNT_MAPPINGS.getValue();
|
||||
final JsonArray chargeOffReasonToExpenseAccountMappingArray = this.fromApiJsonHelper.extractJsonArrayNamed(arrayName, element);
|
||||
|
||||
if (chargeOffReasonToExpenseAccountMappingArray != null) {
|
||||
if (changes != null) {
|
||||
changes.put(arrayName, command.jsonFragment(arrayName));
|
||||
}
|
||||
|
||||
for (int i = 0; i < chargeOffReasonToExpenseAccountMappingArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargeOffReasonToExpenseAccountMappingArray.get(i).getAsJsonObject();
|
||||
final Long reasonId = jsonObject.get(LoanProductAccountingParams.CHARGE_OFF_REASON_CODE_VALUE_ID.getValue()).getAsLong();
|
||||
final Long expenseAccountId = jsonObject.get(LoanProductAccountingParams.EXPENSE_GL_ACCOUNT_ID.getValue()).getAsLong();
|
||||
|
||||
saveChargeOffReasonToExpenseMapping(productId, reasonId, expenseAccountId, portfolioProductType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param command
|
||||
* @param element
|
||||
@@ -356,6 +384,65 @@ public class ProductToGLAccountMappingHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateChargeOffReasonToGLAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes, final PortfolioProductType portfolioProductType) {
|
||||
|
||||
final List<ProductToGLAccountMapping> existingChargeOffReasonToGLAccountMappings = this.accountMappingRepository
|
||||
.findAllChargeOffReasonsMappings(productId, portfolioProductType.getValue());
|
||||
final JsonArray chargeOffReasonToGLAccountMappingArray = this.fromApiJsonHelper
|
||||
.extractJsonArrayNamed(LoanProductAccountingParams.CHARGE_OFF_REASON_TO_EXPENSE_ACCOUNT_MAPPINGS.getValue(), element);
|
||||
|
||||
final Map<Long, Long> inputChargeOffReasonToGLAccountMap = new HashMap<>();
|
||||
|
||||
final Set<Long> existingChargeOffReasons = new HashSet<>();
|
||||
if (chargeOffReasonToGLAccountMappingArray != null) {
|
||||
if (changes != null) {
|
||||
changes.put(LoanProductAccountingParams.CHARGE_OFF_REASON_TO_EXPENSE_ACCOUNT_MAPPINGS.getValue(),
|
||||
command.jsonFragment(LoanProductAccountingParams.CHARGE_OFF_REASON_TO_EXPENSE_ACCOUNT_MAPPINGS.getValue()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < chargeOffReasonToGLAccountMappingArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargeOffReasonToGLAccountMappingArray.get(i).getAsJsonObject();
|
||||
final Long expenseGlAccountId = jsonObject.get(LoanProductAccountingParams.EXPENSE_GL_ACCOUNT_ID.getValue()).getAsLong();
|
||||
final Long chargeOffReasonCodeValueId = jsonObject
|
||||
.get(LoanProductAccountingParams.CHARGE_OFF_REASON_CODE_VALUE_ID.getValue()).getAsLong();
|
||||
inputChargeOffReasonToGLAccountMap.put(chargeOffReasonCodeValueId, expenseGlAccountId);
|
||||
}
|
||||
|
||||
// If input map is empty, delete all existing mappings
|
||||
if (inputChargeOffReasonToGLAccountMap.isEmpty()) {
|
||||
this.accountMappingRepository.deleteAllInBatch(existingChargeOffReasonToGLAccountMappings);
|
||||
} else {
|
||||
for (final ProductToGLAccountMapping existingChargeOffReasonToGLAccountMapping : existingChargeOffReasonToGLAccountMappings) {
|
||||
final Long currentChargeOffReasonId = existingChargeOffReasonToGLAccountMapping.getChargeOffReason().getId();
|
||||
if (currentChargeOffReasonId != null) {
|
||||
existingChargeOffReasons.add(currentChargeOffReasonId);
|
||||
// update existing mappings (if required)
|
||||
if (inputChargeOffReasonToGLAccountMap.containsKey(currentChargeOffReasonId)) {
|
||||
final Long newGLAccountId = inputChargeOffReasonToGLAccountMap.get(currentChargeOffReasonId);
|
||||
if (!newGLAccountId.equals(existingChargeOffReasonToGLAccountMapping.getGlAccount().getId())) {
|
||||
final Optional<GLAccount> glAccount = accountRepository.findById(newGLAccountId);
|
||||
if (glAccount.isPresent()) {
|
||||
existingChargeOffReasonToGLAccountMapping.setGlAccount(glAccount.get());
|
||||
this.accountMappingRepository.saveAndFlush(existingChargeOffReasonToGLAccountMapping);
|
||||
}
|
||||
}
|
||||
} // deleted payment type
|
||||
else {
|
||||
this.accountMappingRepository.delete(existingChargeOffReasonToGLAccountMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only the newly added
|
||||
for (Map.Entry<Long, Long> entry : inputChargeOffReasonToGLAccountMap.entrySet().stream()
|
||||
.filter(e -> !existingChargeOffReasons.contains(e.getKey())).toList()) {
|
||||
saveChargeOffReasonToExpenseMapping(productId, entry.getKey(), entry.getValue(), portfolioProductType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param productId
|
||||
*
|
||||
@@ -402,6 +489,26 @@ public class ProductToGLAccountMappingHelper {
|
||||
this.accountMappingRepository.saveAndFlush(accountMapping);
|
||||
}
|
||||
|
||||
private void saveChargeOffReasonToExpenseMapping(final Long productId, final Long reasonId, final Long expenseAccountId,
|
||||
final PortfolioProductType portfolioProductType) {
|
||||
|
||||
final Optional<GLAccount> glAccount = accountRepository.findById(expenseAccountId);
|
||||
|
||||
final boolean reasonMappingExists = this.accountMappingRepository
|
||||
.findAllChargeOffReasonsMappings(productId, portfolioProductType.getValue()).stream()
|
||||
.anyMatch(mapping -> mapping.getChargeOffReason().getId().equals(reasonId));
|
||||
|
||||
final Optional<CodeValue> codeValueOptional = codeValueRepository.findById(reasonId);
|
||||
|
||||
if (glAccount.isPresent() && !reasonMappingExists && codeValueOptional.isPresent()) {
|
||||
final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping().setGlAccount(glAccount.get())
|
||||
.setProductId(productId).setProductType(portfolioProductType.getValue())
|
||||
.setFinancialAccountType(CashAccountsForLoan.CHARGE_OFF_EXPENSE.getValue()).setChargeOffReason(codeValueOptional.get());
|
||||
|
||||
this.accountMappingRepository.saveAndFlush(accountMapping);
|
||||
}
|
||||
}
|
||||
|
||||
private List<GLAccountType> getAllowedAccountTypesForFeeMapping() {
|
||||
List<GLAccountType> allowedAccountTypes = new ArrayList<>();
|
||||
allowedAccountTypes.add(GLAccountType.INCOME);
|
||||
@@ -455,4 +562,38 @@ public class ProductToGLAccountMappingHelper {
|
||||
this.accountMappingRepository.deleteAllInBatch(productToGLAccountMappings);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateChargeOffMappingsInDatabase(final List<JsonObject> mappings) {
|
||||
final List<ApiParameterError> validationErrors = new ArrayList<>();
|
||||
|
||||
for (JsonObject jsonObject : mappings) {
|
||||
final Long expenseGlAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.EXPENSE_GL_ACCOUNT_ID.getValue(), jsonObject);
|
||||
final Long chargeOffReasonCodeValueId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.CHARGE_OFF_REASON_CODE_VALUE_ID.getValue(), jsonObject);
|
||||
|
||||
// Validation: chargeOffReasonCodeValueId must exist in the database
|
||||
CodeValue codeValue = this.codeValueRepository.findByCodeNameAndId("ChargeOffReasons", chargeOffReasonCodeValueId);
|
||||
if (codeValue == null) {
|
||||
validationErrors.add(ApiParameterError.parameterError("validation.msg.chargeoffreason.invalid",
|
||||
"Charge-off reason with ID " + chargeOffReasonCodeValueId + " does not exist",
|
||||
LoanProductAccountingParams.CHARGE_OFF_REASON_TO_EXPENSE_ACCOUNT_MAPPINGS.getValue()));
|
||||
}
|
||||
|
||||
// Validation: expenseGLAccountId must exist as a valid Expense GL account
|
||||
final Optional<GLAccount> glAccount = accountRepository.findById(expenseGlAccountId);
|
||||
|
||||
if (glAccount.isEmpty() || !glAccount.get().getType().equals(GL_ACCOUNT_EXPENSE_TYPE)) {
|
||||
validationErrors.add(ApiParameterError.parameterError("validation.msg.glaccount.not.found",
|
||||
"GL Account with ID " + expenseGlAccountId + " does not exist or is not an Expense GL account",
|
||||
LoanProductAccountingParams.EXPENSE_GL_ACCOUNT_ID.getValue()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Throw all collected validation errors, if any
|
||||
if (!validationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(validationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -20,6 +20,7 @@ package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeOffReasonToGLAccountMapper;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
|
||||
|
||||
@@ -47,4 +48,5 @@ public interface ProductToGLAccountMappingReadPlatformService {
|
||||
|
||||
List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForShareProduct(Long productId);
|
||||
|
||||
List<ChargeOffReasonToGLAccountMapper> fetchChargeOffReasonMappingsForLoanProduct(Long loanProductId);
|
||||
}
|
||||
|
||||
+85
-144
@@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -37,14 +35,16 @@ import org.apache.fineract.accounting.common.AccountingConstants.SharesProductAc
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingValidations;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeOffReasonToGLAccountMapper;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMapping;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@@ -54,73 +54,24 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private static final class ProductToGLAccountMappingMapper implements RowMapper<Map<String, Object>> {
|
||||
|
||||
public String schema() {
|
||||
return " mapping.id as id, mapping.gl_account_id as glAccountId,glaccount.name as name,glaccount.gl_code as code,"
|
||||
+ " mapping.product_id as productId, mapping.product_type as productType,mapping.financial_account_type as financialAccountType, "
|
||||
+ " mapping.payment_type as paymentTypeId,pt.value as paymentTypeValue, mapping.charge_id as chargeId, charge.is_penalty as penalty, "
|
||||
+ " charge.name as chargeName "
|
||||
+ " from acc_product_mapping mapping left join m_charge charge on mapping.charge_id=charge.id "
|
||||
+ " left join acc_gl_account as glaccount on mapping.gl_account_id = glaccount.id"
|
||||
+ " left join m_payment_type pt on mapping.payment_type=pt.id" + " where mapping.product_type= ? ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final Long glAccountId = rs.getLong("glAccountId");
|
||||
final Long productId = rs.getLong("productId");
|
||||
final Long paymentTypeId = JdbcSupport.getLong(rs, "paymentTypeId");
|
||||
final Long chargeId = rs.getLong("chargeId");
|
||||
final Integer productType = rs.getInt("productType");
|
||||
final String paymentTypeValue = rs.getString("paymentTypeValue");
|
||||
final Integer financialAccountType = rs.getInt("financialAccountType");
|
||||
final String glAccountName = rs.getString("name");
|
||||
final String glCode = rs.getString("code");
|
||||
final String chargeName = rs.getString("chargeName");
|
||||
final Boolean penalty = rs.getBoolean("penalty");
|
||||
|
||||
final Map<String, Object> loanProductToGLAccountMap = new LinkedHashMap<>(5);
|
||||
loanProductToGLAccountMap.put("id", id);
|
||||
loanProductToGLAccountMap.put("glAccountId", glAccountId);
|
||||
loanProductToGLAccountMap.put("productId", productId);
|
||||
loanProductToGLAccountMap.put("productType", productType);
|
||||
loanProductToGLAccountMap.put("financialAccountType", financialAccountType);
|
||||
loanProductToGLAccountMap.put("paymentTypeId", paymentTypeId);
|
||||
loanProductToGLAccountMap.put("paymentTypeValue", paymentTypeValue);
|
||||
loanProductToGLAccountMap.put("chargeId", chargeId);
|
||||
loanProductToGLAccountMap.put("chargeName", chargeName);
|
||||
loanProductToGLAccountMap.put("penalty", penalty);
|
||||
loanProductToGLAccountMap.put("glAccountName", glAccountName);
|
||||
loanProductToGLAccountMap.put("glCode", glCode);
|
||||
return loanProductToGLAccountMap;
|
||||
}
|
||||
}
|
||||
private final ProductToGLAccountMappingRepository productToGLAccountMappingRepository;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> fetchAccountMappingDetailsForLoanProduct(final Long loanProductId, final Integer accountingType) {
|
||||
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<>(8);
|
||||
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ? and payment_type is null and mapping.charge_id is null";
|
||||
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps = this.jdbcTemplate.query(sql, rm, // NOSONAR
|
||||
new Object[] { PortfolioProductType.LOAN.getValue(), loanProductId });
|
||||
final List<ProductToGLAccountMapping> mappings = productToGLAccountMappingRepository.findAllRegularMappings(loanProductId,
|
||||
PortfolioProductType.LOAN.getValue());
|
||||
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingType)) {
|
||||
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
final CashAccountsForLoan glAccountForLoan = CashAccountsForLoan.fromInt(financialAccountType);
|
||||
final CashAccountsForLoan glAccountForLoan = CashAccountsForLoan.fromInt(mapping.getFinancialAccountType());
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
if (glAccountForLoan.equals(CashAccountsForLoan.FUND_SOURCE)) {
|
||||
accountMappingDetails.put(LoanProductAccountingDataParams.FUND_SOURCE.getValue(), gLAccountData);
|
||||
@@ -166,14 +117,11 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
} else if (AccountingValidations.isAccrualBasedAccounting(accountingType)
|
||||
|| AccountingValidations.isUpfrontAccrualAccounting(accountingType)) {
|
||||
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
final AccrualAccountsForLoan glAccountForLoan = AccrualAccountsForLoan.fromInt(financialAccountType);
|
||||
for (ProductToGLAccountMapping mapping : mappings) {
|
||||
final AccrualAccountsForLoan glAccountForLoan = AccrualAccountsForLoan.fromInt(mapping.getFinancialAccountType());
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
if (glAccountForLoan.equals(AccrualAccountsForLoan.FUND_SOURCE)) {
|
||||
accountMappingDetails.put(LoanProductAccountingDataParams.FUND_SOURCE.getValue(), gLAccountData);
|
||||
@@ -229,18 +177,16 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
|
||||
@Override
|
||||
public Map<String, Object> fetchAccountMappingDetailsForSavingsProduct(final Long savingsProductId, final Integer accountingType) {
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ? and payment_type is null and mapping.charge_id is null ";
|
||||
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps = this.jdbcTemplate.query(sql, rm, // NOSONAR
|
||||
new Object[] { PortfolioProductType.SAVING.getValue(), savingsProductId });
|
||||
final List<ProductToGLAccountMapping> mappings = productToGLAccountMappingRepository.findAllRegularMappings(savingsProductId,
|
||||
PortfolioProductType.SAVING.getValue());
|
||||
|
||||
Map<String, Object> accountMappingDetails = null;
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingType)) {
|
||||
accountMappingDetails = setCashSavingsProductToGLAccountMaps(listOfProductToGLAccountMaps);
|
||||
accountMappingDetails = setCashSavingsProductToGLAccountMaps(mappings);
|
||||
|
||||
} else if (AccountingValidations.isAccrualPeriodicBasedAccounting(accountingType)) {
|
||||
accountMappingDetails = setAccrualPeriodicSavingsProductToGLAccountMaps(listOfProductToGLAccountMaps);
|
||||
accountMappingDetails = setAccrualPeriodicSavingsProductToGLAccountMaps(mappings);
|
||||
|
||||
}
|
||||
|
||||
@@ -263,25 +209,15 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
*/
|
||||
private List<PaymentTypeToGLAccountMapper> fetchPaymentTypeToFundSourceMappings(final PortfolioProductType portfolioProductType,
|
||||
final Long loanProductId) {
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ? and payment_type is not null";
|
||||
final List<ProductToGLAccountMapping> mappings = productToGLAccountMappingRepository.findAllPaymentTypeMappings(loanProductId,
|
||||
portfolioProductType.getValue());
|
||||
|
||||
final List<Map<String, Object>> paymentTypeToFundSourceMappingsList = this.jdbcTemplate.query(sql, rm, // NOSONAR
|
||||
new Object[] { portfolioProductType.getValue(), loanProductId });
|
||||
|
||||
List<PaymentTypeToGLAccountMapper> paymentTypeToGLAccountMappers = null;
|
||||
for (final Map<String, Object> productToGLAccountMap : paymentTypeToFundSourceMappingsList) {
|
||||
if (paymentTypeToGLAccountMappers == null) {
|
||||
paymentTypeToGLAccountMappers = new ArrayList<>();
|
||||
}
|
||||
final Long paymentTypeId = (Long) productToGLAccountMap.get("paymentTypeId");
|
||||
final String paymentTypeValue = (String) productToGLAccountMap.get("paymentTypeValue");
|
||||
final PaymentTypeData paymentTypeData = PaymentTypeData.instance(paymentTypeId, paymentTypeValue);
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
List<PaymentTypeToGLAccountMapper> paymentTypeToGLAccountMappers = mappings.isEmpty() ? null : new ArrayList<>();
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
final PaymentTypeData paymentTypeData = PaymentTypeData.instance(mapping.getPaymentType().getId(),
|
||||
mapping.getPaymentType().getName());
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
final PaymentTypeToGLAccountMapper paymentTypeToGLAccountMapper = new PaymentTypeToGLAccountMapper()
|
||||
.setPaymentType(paymentTypeData).setFundSourceAccount(gLAccountData);
|
||||
@@ -312,29 +248,16 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
|
||||
private List<ChargeToGLAccountMapper> fetchChargeToIncomeAccountMappings(final PortfolioProductType portfolioProductType,
|
||||
final Long loanProductId, final boolean penalty) {
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
String sql = "select " + rm.schema() + " and product_id = ? and mapping.charge_id is not null and charge.is_penalty=";
|
||||
if (penalty) {
|
||||
sql = sql + " true";
|
||||
} else {
|
||||
sql = sql + " false";
|
||||
}
|
||||
final List<ProductToGLAccountMapping> mappings = penalty
|
||||
? productToGLAccountMappingRepository.findAllPenaltyMappings(loanProductId, portfolioProductType.getValue())
|
||||
: productToGLAccountMappingRepository.findAllFeeMappings(loanProductId, portfolioProductType.getValue());
|
||||
|
||||
final List<Map<String, Object>> chargeToFundSourceMappingsList = this.jdbcTemplate.query(sql, rm, // NOSONAR
|
||||
new Object[] { portfolioProductType.getValue(), loanProductId });
|
||||
List<ChargeToGLAccountMapper> chargeToGLAccountMappers = null;
|
||||
for (final Map<String, Object> chargeToIncomeAccountMap : chargeToFundSourceMappingsList) {
|
||||
if (chargeToGLAccountMappers == null) {
|
||||
chargeToGLAccountMappers = new ArrayList<>();
|
||||
}
|
||||
final Long glAccountId = (Long) chargeToIncomeAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) chargeToIncomeAccountMap.get("glAccountName");
|
||||
final String glCode = (String) chargeToIncomeAccountMap.get("glCode");
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final Long chargeId = (Long) chargeToIncomeAccountMap.get("chargeId");
|
||||
final String chargeName = (String) chargeToIncomeAccountMap.get("chargeName");
|
||||
final Boolean penalty1 = (Boolean) chargeToIncomeAccountMap.get("penalty");
|
||||
final ChargeData chargeData = ChargeData.builder().id(chargeId).name(chargeName).penalty(penalty1).build();
|
||||
List<ChargeToGLAccountMapper> chargeToGLAccountMappers = mappings.isEmpty() ? null : new ArrayList<>();
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
final ChargeData chargeData = ChargeData.builder().id(mapping.getCharge().getId()).name(mapping.getCharge().getName())
|
||||
.penalty(mapping.getCharge().isPenalty()).build();
|
||||
final ChargeToGLAccountMapper chargeToGLAccountMapper = new ChargeToGLAccountMapper().setCharge(chargeData)
|
||||
.setIncomeAccount(gLAccountData);
|
||||
chargeToGLAccountMappers.add(chargeToGLAccountMapper);
|
||||
@@ -342,26 +265,46 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
return chargeToGLAccountMappers;
|
||||
}
|
||||
|
||||
private List<ChargeOffReasonToGLAccountMapper> fetchChargeOffReasonMappings(final PortfolioProductType portfolioProductType,
|
||||
final Long loanProductId) {
|
||||
final List<ProductToGLAccountMapping> mappings = productToGLAccountMappingRepository.findAllChargeOffReasonsMappings(loanProductId,
|
||||
portfolioProductType.getValue());
|
||||
List<ChargeOffReasonToGLAccountMapper> chargeOffReasonToGLAccountMappers = mappings.isEmpty() ? null : new ArrayList<>();
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
final Long glAccountId = mapping.getGlAccount().getId();
|
||||
final String glAccountName = mapping.getGlAccount().getName();
|
||||
final String glCode = mapping.getGlAccount().getGlCode();
|
||||
final GLAccountData chargeOffExpenseAccount = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final Long chargeOffReasonId = mapping.getChargeOffReason().getId();
|
||||
final String codeValue = mapping.getChargeOffReason().getLabel();
|
||||
final String codeDescription = mapping.getChargeOffReason().getDescription();
|
||||
final Integer orderPosition = mapping.getChargeOffReason().getPosition();
|
||||
final boolean isActive = mapping.getChargeOffReason().isActive();
|
||||
final boolean isMandatory = mapping.getChargeOffReason().isMandatory();
|
||||
final CodeValueData chargeOffReasonsCodeValue = CodeValueData.builder().id(chargeOffReasonId).name(codeValue)
|
||||
.description(codeDescription).position(orderPosition).active(isActive).mandatory(isMandatory).build();
|
||||
|
||||
final ChargeOffReasonToGLAccountMapper chargeOffReasonToGLAccountMapper = new ChargeOffReasonToGLAccountMapper()
|
||||
.setChargeOffReasonCodeValue(chargeOffReasonsCodeValue).setExpenseAccount(chargeOffExpenseAccount);
|
||||
chargeOffReasonToGLAccountMappers.add(chargeOffReasonToGLAccountMapper);
|
||||
}
|
||||
return chargeOffReasonToGLAccountMappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> fetchAccountMappingDetailsForShareProduct(Long productId, Integer accountingType) {
|
||||
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<>(8);
|
||||
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ? and payment_type is null and mapping.charge_id is null ";
|
||||
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps = this.jdbcTemplate.query(sql, rm, // NOSONAR
|
||||
new Object[] { PortfolioProductType.SHARES.getValue(), productId });
|
||||
final List<ProductToGLAccountMapping> mappings = productToGLAccountMappingRepository.findAllRegularMappings(productId,
|
||||
PortfolioProductType.SHARES.getValue());
|
||||
|
||||
if (AccountingRuleType.CASH_BASED.getValue().equals(accountingType)) {
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
final CashAccountsForShares glAccountForShares = CashAccountsForShares.fromInt(financialAccountType);
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
final CashAccountsForShares glAccountForShares = CashAccountsForShares.fromInt(mapping.getFinancialAccountType());
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final GLAccountData gLAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
if (glAccountForShares.equals(CashAccountsForShares.SHARES_REFERENCE)) {
|
||||
accountMappingDetails.put(SharesProductAccountingParams.SHARES_REFERENCE.getValue(), gLAccountData);
|
||||
@@ -388,20 +331,21 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
return fetchChargeToIncomeAccountMappings(PortfolioProductType.SHARES, productId, false);
|
||||
}
|
||||
|
||||
private Map<String, Object> setAccrualPeriodicSavingsProductToGLAccountMaps(
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps) {
|
||||
@Override
|
||||
public List<ChargeOffReasonToGLAccountMapper> fetchChargeOffReasonMappingsForLoanProduct(Long loanProductId) {
|
||||
return fetchChargeOffReasonMappings(PortfolioProductType.LOAN, loanProductId);
|
||||
}
|
||||
|
||||
private Map<String, Object> setAccrualPeriodicSavingsProductToGLAccountMaps(final List<ProductToGLAccountMapping> mappings) {
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<>(8);
|
||||
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
AccrualAccountsForSavings glAccountForSavings = AccrualAccountsForSavings.fromInt(financialAccountType);
|
||||
AccrualAccountsForSavings glAccountForSavings = AccrualAccountsForSavings.fromInt(mapping.getFinancialAccountType());
|
||||
|
||||
if (glAccountForSavings != null) {
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData glAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final GLAccountData glAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
// Assets
|
||||
if (glAccountForSavings.equals(AccrualAccountsForSavings.SAVINGS_REFERENCE)) {
|
||||
@@ -435,26 +379,23 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
accountMappingDetails.put(SavingProductAccountingDataParams.LOSSES_WRITTEN_OFF.getValue(), glAccountData);
|
||||
}
|
||||
} else {
|
||||
log.error("Accounting mapping null {}", financialAccountType);
|
||||
log.error("Accounting mapping null {}", mapping.getFinancialAccountType());
|
||||
}
|
||||
}
|
||||
|
||||
return accountMappingDetails;
|
||||
}
|
||||
|
||||
private Map<String, Object> setCashSavingsProductToGLAccountMaps(final List<Map<String, Object>> listOfProductToGLAccountMaps) {
|
||||
private Map<String, Object> setCashSavingsProductToGLAccountMaps(final List<ProductToGLAccountMapping> mappings) {
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<>(8);
|
||||
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
for (final ProductToGLAccountMapping mapping : mappings) {
|
||||
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
CashAccountsForSavings glAccountForSavings = CashAccountsForSavings.fromInt(financialAccountType);
|
||||
CashAccountsForSavings glAccountForSavings = CashAccountsForSavings.fromInt(mapping.getFinancialAccountType());
|
||||
|
||||
if (glAccountForSavings != null) {
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData glAccountData = new GLAccountData().setId(glAccountId).setName(glAccountName).setGlCode(glCode);
|
||||
final GLAccountData glAccountData = new GLAccountData().setId(mapping.getGlAccount().getId())
|
||||
.setName(mapping.getGlAccount().getName()).setGlCode(mapping.getGlAccount().getGlCode());
|
||||
|
||||
// Assets
|
||||
if (glAccountForSavings.equals(CashAccountsForSavings.SAVINGS_REFERENCE)) {
|
||||
@@ -482,7 +423,7 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
accountMappingDetails.put(SavingProductAccountingDataParams.LOSSES_WRITTEN_OFF.getValue(), glAccountData);
|
||||
}
|
||||
} else {
|
||||
log.error("Accounting mapping null {}", financialAccountType);
|
||||
log.error("Accounting mapping null {}", mapping.getFinancialAccountType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@
|
||||
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
|
||||
@@ -29,7 +30,7 @@ public interface ProductToGLAccountMappingWritePlatformService {
|
||||
void createSavingProductToGLAccountMapping(Long savingProductId, JsonCommand command, DepositAccountType accountType);
|
||||
|
||||
Map<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId);
|
||||
AccountingRuleType accountingRuleTypeId);
|
||||
|
||||
Map<String, Object> updateSavingsProductToGLAccountMapping(Long savingsProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId, DepositAccountType accountType);
|
||||
|
||||
+3
-2
@@ -29,6 +29,7 @@ import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||
@@ -42,9 +43,9 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
public SavingsProductToGLAccountMappingHelper(final GLAccountRepository glAccountRepository,
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepositoryWrapper, final GLAccountRepositoryWrapper accountRepositoryWrapper,
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper) {
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper, final CodeValueRepository codeValueRepository) {
|
||||
super(glAccountRepository, glAccountMappingRepository, fromApiJsonHelper, chargeRepositoryWrapper, accountRepositoryWrapper,
|
||||
paymentTypeRepositoryWrapper);
|
||||
paymentTypeRepositoryWrapper, codeValueRepository);
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
+3
-2
@@ -28,6 +28,7 @@ import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||
@@ -41,9 +42,9 @@ public class ShareProductToGLAccountMappingHelper extends ProductToGLAccountMapp
|
||||
public ShareProductToGLAccountMappingHelper(final GLAccountRepository glAccountRepository,
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepositoryWrapper, final GLAccountRepositoryWrapper accountRepositoryWrapper,
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper) {
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper, final CodeValueRepository codeValueRepository) {
|
||||
super(glAccountRepository, glAccountMappingRepository, fromApiJsonHelper, chargeRepositoryWrapper, accountRepositoryWrapper,
|
||||
paymentTypeRepositoryWrapper);
|
||||
paymentTypeRepositoryWrapper, codeValueRepository);
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
+64
-75
@@ -18,14 +18,15 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.provisioning.api;
|
||||
|
||||
import static org.apache.fineract.accounting.provisioning.constant.ProvisioningEntriesApiConstants.CREATE_JOURNAL_ENTRY;
|
||||
import static org.apache.fineract.accounting.provisioning.constant.ProvisioningEntriesApiConstants.RECREATE_PROVISION_IN_ENTRY;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
@@ -34,24 +35,17 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.provisioning.constant.ProvisioningEntriesApiConstants;
|
||||
import org.apache.fineract.accounting.provisioning.data.LoanProductProvisioningEntryData;
|
||||
import org.apache.fineract.accounting.provisioning.data.ProvisioningEntryData;
|
||||
import org.apache.fineract.accounting.provisioning.data.request.ProvisionEntryRequest;
|
||||
import org.apache.fineract.accounting.provisioning.service.ProvisioningEntriesReadPlatformService;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
@@ -60,38 +54,42 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/provisioningentries")
|
||||
@Component
|
||||
@Tag(name = "Provisioning Entries", description = "This defines the Provisioning Entries for all active loan products\n" + "\n"
|
||||
+ "Field Descriptions\n" + "date\n" + "Date on which day provisioning entries should be created\n" + "createjournalentries\n"
|
||||
+ "Boolean variable whether to add journal entries for generated provisioning entries\n")
|
||||
@Tag(name = "Provisioning Entries", description = """
|
||||
This defines the Provisioning Entries for all active loan products
|
||||
|
||||
Field Descriptions
|
||||
date
|
||||
Date on which day provisioning entries should be created
|
||||
createjournalentries
|
||||
Boolean variable whether to add journal entries for generated provisioning entries
|
||||
""")
|
||||
@RequiredArgsConstructor
|
||||
public class ProvisioningEntriesApiResource {
|
||||
|
||||
private static final Set<String> PROVISIONING_ENTRY_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(ProvisioningEntriesApiConstants.PROVISIONINGENTRY_PARAM, ProvisioningEntriesApiConstants.ENTRIES_PARAM));
|
||||
private static final Set<String> ALL_PROVISIONING_ENTRIES = new HashSet<>(
|
||||
Arrays.asList(ProvisioningEntriesApiConstants.PROVISIONINGENTRY_PARAM));
|
||||
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final DefaultToApiJsonSerializer<ProvisioningEntryData> toApiJsonSerializer;
|
||||
private final DefaultToApiJsonSerializer<Object> entriesApiJsonSerializer;
|
||||
private final ProvisioningEntriesReadPlatformService provisioningEntriesReadPlatformService;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create new Provisioning Entries", description = "Creates a new Provisioning Entries\n" + "\n"
|
||||
+ "Mandatory Fields\n" + "date\n" + "dateFormat\n" + "locale\n" + "Optional Fields\n" + "createjournalentries")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PostProvisioningEntriesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PostProvisioningEntriesResponse.class))) })
|
||||
public String createProvisioningEntries(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
CommandWrapper commandWrapper = null;
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
commandWrapper = new CommandWrapperBuilder().createProvisioningEntries().withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
@Operation(summary = "Create new Provisioning Entries", description = """
|
||||
Creates a new Provisioning Entries
|
||||
|
||||
Mandatory Fields
|
||||
date
|
||||
dateFormat
|
||||
locale
|
||||
Optional Fields
|
||||
createjournalentries""")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = ProvisionEntryRequest.class)))
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PostProvisioningEntriesResponse.class)))
|
||||
public CommandProcessingResult createProvisioningEntries(@Parameter(hidden = true) ProvisionEntryRequest provisionEntryRequest) {
|
||||
platformSecurityContext.authenticatedUser();
|
||||
CommandWrapper commandWrapper = new CommandWrapperBuilder().createProvisioningEntries()
|
||||
.withJson(toApiJsonSerializer.serialize(provisionEntryRequest)).build();
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandWrapper);
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -100,25 +98,12 @@ public class ProvisioningEntriesApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Recreates Provisioning Entry", description = "Recreates Provisioning Entry | createjournalentry.")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PutProvisioningEntriesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PutProvisioningEntriesResponse.class))) })
|
||||
public String modifyProvisioningEntry(@PathParam("entryId") @Parameter(description = "entryId") final Long entryId,
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProvisioningEntriesApiResourceSwagger.PutProvisioningEntriesResponse.class)))
|
||||
public CommandProcessingResult modifyProvisioningEntry(@PathParam("entryId") @Parameter(description = "entryId") final Long entryId,
|
||||
@QueryParam("command") @Parameter(description = "command=createjournalentry\ncommand=recreateprovisioningentry") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
CommandWrapper commandWrapper = null;
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
if ("createjournalentry".equals(commandParam)) {
|
||||
commandWrapper = new CommandWrapperBuilder().createProvisioningJournalEntries(entryId).withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService
|
||||
.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
} else if ("recreateprovisioningentry".equals(commandParam)) {
|
||||
commandWrapper = new CommandWrapperBuilder().reCreateProvisioningEntries(entryId).withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService
|
||||
.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
}
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
@Parameter(hidden = true) String provisionCommandRequest) {
|
||||
platformSecurityContext.authenticatedUser();
|
||||
return getResultByCommandParam(commandParam, entryId, provisionCommandRequest);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -126,45 +111,49 @@ public class ProvisioningEntriesApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieves a Provisioning Entry", description = "Returns the details of a generated Provisioning Entry.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProvisioningEntryData.class))) })
|
||||
public String retrieveProvisioningEntry(@PathParam("entryId") @Parameter(description = "entryId") final Long entryId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
public ProvisioningEntryData retrieveProvisioningEntry(@PathParam("entryId") @Parameter(description = "entryId") final Long entryId) {
|
||||
platformSecurityContext.authenticatedUser();
|
||||
ProvisioningEntryData data = this.provisioningEntriesReadPlatformService.retrieveProvisioningEntryData(entryId);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, data, PROVISIONING_ENTRY_PARAMETERS);
|
||||
return provisioningEntriesReadPlatformService.retrieveProvisioningEntryData(entryId);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("entries")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanProductProvisioningEntryData.class))) })
|
||||
public String retrieveProviioningEntries(@QueryParam("entryId") final Long entryId, @QueryParam("offset") final Integer offset,
|
||||
@QueryParam("limit") final Integer limit, @QueryParam("officeId") final Long officeId,
|
||||
@QueryParam("productId") final Long productId, @QueryParam("categoryId") final Long categoryId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
SearchParameters params = SearchParameters.builder().limit(limit).offset(offset).provisioningEntryId(entryId).officeId(officeId)
|
||||
.productId(productId).categoryId(categoryId).build();
|
||||
Page<LoanProductProvisioningEntryData> entries = this.provisioningEntriesReadPlatformService.retrieveProvisioningEntries(params);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.entriesApiJsonSerializer.serialize(settings, entries, PROVISIONING_ENTRY_PARAMETERS);
|
||||
public Page<LoanProductProvisioningEntryData> retrieveProviioningEntries(@QueryParam("entryId") final Long entryId,
|
||||
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
|
||||
@QueryParam("officeId") final Long officeId, @QueryParam("productId") final Long productId,
|
||||
@QueryParam("categoryId") final Long categoryId) {
|
||||
platformSecurityContext.authenticatedUser();
|
||||
final SearchParameters params = SearchParameters.builder().limit(limit).offset(offset).provisioningEntryId(entryId)
|
||||
.officeId(officeId).productId(productId).categoryId(categoryId).build();
|
||||
|
||||
return provisioningEntriesReadPlatformService.retrieveProvisioningEntries(params);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List all Provisioning Entries")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ProvisioningEntryData.class)))) })
|
||||
public String retrieveAllProvisioningEntries(@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit, @Context final UriInfo uriInfo) {
|
||||
public Page<ProvisioningEntryData> retrieveAllProvisioningEntries(
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit) {
|
||||
platformSecurityContext.authenticatedUser();
|
||||
Page<ProvisioningEntryData> data = this.provisioningEntriesReadPlatformService.retrieveAllProvisioningEntries(offset, limit);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.entriesApiJsonSerializer.serialize(settings, data, ALL_PROVISIONING_ENTRIES);
|
||||
return provisioningEntriesReadPlatformService.retrieveAllProvisioningEntries(offset, limit);
|
||||
}
|
||||
|
||||
private CommandProcessingResult getResultByCommandParam(String commandParam, Long entryId, String apiRequestBodyAsJson) {
|
||||
final CommandWrapperBuilder commandWrapperBuilder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
switch (commandParam) {
|
||||
case CREATE_JOURNAL_ENTRY -> {
|
||||
return commandsSourceWritePlatformService
|
||||
.logCommandSource(commandWrapperBuilder.createProvisioningJournalEntries(entryId).build());
|
||||
}
|
||||
case RECREATE_PROVISION_IN_ENTRY -> {
|
||||
return commandsSourceWritePlatformService
|
||||
.logCommandSource(commandWrapperBuilder.reCreateProvisioningEntries(entryId).build());
|
||||
}
|
||||
default -> throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -32,4 +32,7 @@ public interface ProvisioningEntriesApiConstants {
|
||||
|
||||
String ENTRIES_PARAM = "entries";
|
||||
|
||||
String CREATE_JOURNAL_ENTRY = "createjournalentry";
|
||||
String RECREATE_PROVISION_IN_ENTRY = "recreateprovisioningentry";
|
||||
|
||||
}
|
||||
|
||||
+8
-3
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.accounting.provisioning.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
@@ -29,7 +31,10 @@ import lombok.experimental.Accessors;
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@SuppressWarnings("unused")
|
||||
public class ProvisioningEntryData {
|
||||
public class ProvisioningEntryData implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
|
||||
@@ -39,9 +44,9 @@ public class ProvisioningEntryData {
|
||||
|
||||
private String createdUser;
|
||||
|
||||
LocalDate createdDate;
|
||||
private LocalDate createdDate;
|
||||
|
||||
Long modifiedById;
|
||||
private Long modifiedById;
|
||||
|
||||
private String modifiedUser;
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.accounting.provisioning.data.request;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
public record ProvisionEntryRequest(String date, Boolean createjournalentries, String locale, String dateFormat) implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
+40
-96
@@ -20,7 +20,6 @@ package org.apache.fineract.accounting.rule.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
@@ -39,10 +38,8 @@ import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -52,6 +49,7 @@ import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.service.GLAccountReadPlatformService;
|
||||
import org.apache.fineract.accounting.rule.data.AccountingRuleData;
|
||||
import org.apache.fineract.accounting.rule.data.AccountingTagRuleData;
|
||||
import org.apache.fineract.accounting.rule.data.request.AccountRuleRequest;
|
||||
import org.apache.fineract.accounting.rule.service.AccountingRuleReadPlatformService;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
@@ -81,11 +79,6 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class AccountingRuleApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList("id", "officeId", "officeName", "accountToDebitId", "accountToCreditId", "name", "description", "systemDefined",
|
||||
"allowedCreditTagOptions", "allowedDebitTagOptions", "debitTags", "creditTags", "creditAccounts", "debitAccounts",
|
||||
"allowMultipleCreditEntries", "allowMultipleDebitEntries", "tag"));
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSION = "ACCOUNTINGRULE";
|
||||
|
||||
private final AccountingRuleReadPlatformService accountingRuleReadPlatformService;
|
||||
@@ -103,17 +96,9 @@ public class AccountingRuleApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Accounting Rule Details Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
|
||||
+ "\n" + "Field Defaults\n" + "Allowed Value Lists\n" + "Example Request:\n" + "\n" + "accountingrules/template")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.GetAccountRulesTemplateResponse.class))) })
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
|
||||
AccountingRuleData accountingRuleData = null;
|
||||
accountingRuleData = handleTemplate(accountingRuleData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, accountingRuleData, RESPONSE_DATA_PARAMETERS);
|
||||
public AccountingRuleData retrieveTemplate() {
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
return handleTemplate(null);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -121,30 +106,16 @@ public class AccountingRuleApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Accounting Rules", description = "Returns the list of defined accounting rules.\n" + "\n"
|
||||
+ "Example Requests:\n" + "\n" + "accountingrules")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.GetAccountRulesResponse.class)))) })
|
||||
public String retrieveAllAccountingRules(@Context final UriInfo uriInfo) {
|
||||
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
public List<AccountingRuleData> retrieveAllAccountingRules(@Context final UriInfo uriInfo) {
|
||||
final AppUser currentUser = context.authenticatedUser();
|
||||
currentUser.validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
|
||||
final String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
final String hierarchySearchString = hierarchy + "%";
|
||||
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
boolean isAssociationParametersExists = false;
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
isAssociationParametersExists = true; // If true, retrieve
|
||||
// additional fields for
|
||||
// journal entry form.
|
||||
}
|
||||
}
|
||||
final List<AccountingRuleData> accountingRuleDatas = this.accountingRuleReadPlatformService
|
||||
.retrieveAllAccountingRules(hierarchySearchString, isAssociationParametersExists);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.apiJsonSerializerService.serialize(settings, accountingRuleDatas, RESPONSE_DATA_PARAMETERS);
|
||||
boolean isAssociationParametersExists = !associationParameters.isEmpty() && associationParameters.contains("all");
|
||||
return accountingRuleReadPlatformService.retrieveAllAccountingRules(hierarchySearchString, isAssociationParametersExists);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -153,21 +124,15 @@ public class AccountingRuleApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Accounting rule", description = "Returns the details of a defined Accounting rule.\n" + "\n"
|
||||
+ "Example Requests:\n" + "\n" + "accountingrules/1")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleData.class))) })
|
||||
public String retreiveAccountingRule(
|
||||
public AccountingRuleData retreiveAccountingRule(
|
||||
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
AccountingRuleData accountingRuleData = this.accountingRuleReadPlatformService.retrieveAccountingRuleById(accountingRuleId);
|
||||
if (settings.isTemplate()) {
|
||||
accountingRuleData = handleTemplate(accountingRuleData);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serialize(settings, accountingRuleData, RESPONSE_DATA_PARAMETERS);
|
||||
final AccountingRuleData accountingRuleData = accountingRuleReadPlatformService.retrieveAccountingRuleById(accountingRuleId);
|
||||
return settings.isTemplate() ? handleTemplate(accountingRuleData) : accountingRuleData;
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -176,16 +141,14 @@ public class AccountingRuleApiResource {
|
||||
@Operation(summary = "Create/Define a Accounting rule", description = "Define a new Accounting rule.\n" + "\n" + "Mandatory Fields\n"
|
||||
+ "name, officeId,\n" + "accountToDebit OR debitTags,\n" + "accountToCredit OR creditTags.\n" + "\n" + "Optional Fields\n"
|
||||
+ "description")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PostAccountingRulesRequest.class)))
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PostAccountingRulesResponse.class))) })
|
||||
public String createAccountingRule(@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
public CommandProcessingResult createAccountingRule(@Parameter(hidden = true) AccountRuleRequest accountRuleRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountingRule()
|
||||
.withJson(apiJsonSerializerService.serialize(accountRuleRequest)).build();
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountingRule().withJson(jsonRequestBody).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -193,18 +156,16 @@ public class AccountingRuleApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update a Accounting Rule", description = "Updates the details of a Accounting rule.")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PutAccountingRulesRequest.class)))
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PutAccountingRulesResponse.class))) })
|
||||
public String updateAccountingRule(
|
||||
public CommandProcessingResult updateAccountingRule(
|
||||
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId,
|
||||
@Parameter(hidden = true) final String jsonRequestBody) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateAccountingRule(accountingRuleId).withJson(jsonRequestBody)
|
||||
.build();
|
||||
@Parameter(hidden = true) AccountRuleRequest accountRuleRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateAccountingRule(accountingRuleId)
|
||||
.withJson(apiJsonSerializerService.serialize(accountRuleRequest)).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -214,55 +175,38 @@ public class AccountingRuleApiResource {
|
||||
@Operation(summary = "Delete a Accounting Rule", description = "Deletes a Accounting rule.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.DeleteAccountingRulesResponse.class))) })
|
||||
public String deleteAccountingRule(
|
||||
public CommandProcessingResult deleteAccountingRule(
|
||||
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteAccountingRule(accountingRuleId).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.apiJsonSerializerService.serialize(result);
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
private AccountingRuleData handleTemplate(AccountingRuleData accountingRuleData) {
|
||||
final List<GLAccountData> allowedAccounts = this.accountReadPlatformService.retrieveAllEnabledDetailGLAccounts();
|
||||
final List<OfficeData> allowedOffices = (List<OfficeData>) this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
final Collection<CodeValueData> allowedTagOptions = this.codeValueReadPlatformService
|
||||
final List<GLAccountData> allowedAccounts = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts();
|
||||
final List<OfficeData> allowedOffices = (List<OfficeData>) officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
final Collection<CodeValueData> allowedTagOptions = codeValueReadPlatformService
|
||||
.retrieveCodeValuesByCode(AccountingConstants.ASSESTS_TAG_OPTION_CODE_NAME);
|
||||
|
||||
allowedTagOptions
|
||||
.addAll(this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.LIABILITIES_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions
|
||||
.addAll(this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EQUITY_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions
|
||||
.addAll(this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.INCOME_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions
|
||||
.addAll(this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EXPENSES_TAG_OPTION_CODE_NAME));
|
||||
.addAll(codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.LIABILITIES_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions.addAll(codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EQUITY_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions.addAll(codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.INCOME_TAG_OPTION_CODE_NAME));
|
||||
allowedTagOptions.addAll(codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EXPENSES_TAG_OPTION_CODE_NAME));
|
||||
|
||||
if (accountingRuleData == null) {
|
||||
|
||||
final Collection<CodeValueData> allowedCreditTagOptions = allowedTagOptions;
|
||||
final Collection<CodeValueData> allowedDebitTagOptions = allowedTagOptions;
|
||||
|
||||
accountingRuleData = new AccountingRuleData().setAllowedOffices(allowedOffices).setAllowedAccounts(allowedAccounts)
|
||||
.setAllowedCreditTagOptions(allowedCreditTagOptions).setAllowedDebitTagOptions(allowedDebitTagOptions);
|
||||
.setAllowedCreditTagOptions(allowedTagOptions).setAllowedDebitTagOptions(allowedTagOptions);
|
||||
|
||||
} else {
|
||||
|
||||
final Collection<CodeValueData> allowedCreditTagOptions;
|
||||
final Collection<CodeValueData> allowedDebitTagOptions;
|
||||
|
||||
if (accountingRuleData.getCreditTags() != null) {
|
||||
allowedCreditTagOptions = retrieveSelectedTags(allowedTagOptions, accountingRuleData.getCreditTags());
|
||||
} else {
|
||||
allowedCreditTagOptions = allowedTagOptions;
|
||||
}
|
||||
|
||||
if (accountingRuleData.getDebitTags() != null) {
|
||||
allowedDebitTagOptions = retrieveSelectedTags(allowedTagOptions, accountingRuleData.getDebitTags());
|
||||
} else {
|
||||
allowedDebitTagOptions = allowedTagOptions;
|
||||
}
|
||||
final Collection<CodeValueData> allowedCreditTagOptions = accountingRuleData.getCreditTags() != null
|
||||
? retrieveSelectedTags(allowedTagOptions, accountingRuleData.getCreditTags())
|
||||
: allowedTagOptions;
|
||||
final Collection<CodeValueData> allowedDebitTagOptions = accountingRuleData.getDebitTags() != null
|
||||
? retrieveSelectedTags(allowedTagOptions, accountingRuleData.getDebitTags())
|
||||
: allowedTagOptions;
|
||||
|
||||
accountingRuleData = new AccountingRuleData().setId(accountingRuleData.getId()).setOfficeId(accountingRuleData.getOfficeId())
|
||||
.setOfficeName(accountingRuleData.getOfficeName()).setName(accountingRuleData.getName())
|
||||
|
||||
-67
@@ -19,11 +19,6 @@
|
||||
package org.apache.fineract.accounting.rule.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.rule.data.AccountingTagRuleData;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
|
||||
/**
|
||||
* Created by sanyam on 26/7/17.
|
||||
@@ -34,57 +29,6 @@ final class AccountingRuleApiResourceSwagger {
|
||||
// For Swagger Documentation
|
||||
}
|
||||
|
||||
@Schema(description = "GetAccountRulesResponse")
|
||||
public static final class GetAccountRulesResponse {
|
||||
|
||||
private GetAccountRulesResponse() {
|
||||
|
||||
}
|
||||
|
||||
public Long id;
|
||||
public Long officeId;
|
||||
public String officeName;
|
||||
public String name;
|
||||
public String description;
|
||||
public boolean systemDefined;
|
||||
public boolean allowMultipleDebitEntries;
|
||||
public boolean allowMultipleCreditEntries;
|
||||
public List<AccountingTagRuleData> creditTags;
|
||||
public List<AccountingTagRuleData> debitTags;
|
||||
}
|
||||
|
||||
@Schema(description = "GetAccountRulesTemplateResponse")
|
||||
public static final class GetAccountRulesTemplateResponse {
|
||||
|
||||
private GetAccountRulesTemplateResponse() {
|
||||
|
||||
}
|
||||
|
||||
@Schema(example = "false")
|
||||
public boolean systemDefined;
|
||||
public List<OfficeData> allowedOffices = new ArrayList<OfficeData>();
|
||||
public List<GLAccountData> allowedAccounts = new ArrayList<GLAccountData>();
|
||||
}
|
||||
|
||||
@Schema(description = "PostAccountingRulesRequest")
|
||||
public static final class PostAccountingRulesRequest {
|
||||
|
||||
private PostAccountingRulesRequest() {
|
||||
|
||||
}
|
||||
|
||||
@Schema(example = "test")
|
||||
public String name;
|
||||
@Schema(example = "1")
|
||||
public Long officeId;
|
||||
@Schema(example = "21")
|
||||
public Long accountToDebit;
|
||||
@Schema(example = "9")
|
||||
public Long accountToCredit;
|
||||
@Schema(example = "Employee salary")
|
||||
public String description;
|
||||
}
|
||||
|
||||
@Schema(description = "PostAccountingRulesResponse")
|
||||
public static final class PostAccountingRulesResponse {
|
||||
|
||||
@@ -98,17 +42,6 @@ final class AccountingRuleApiResourceSwagger {
|
||||
public Long resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutAccountingRulesRequest")
|
||||
public static final class PutAccountingRulesRequest {
|
||||
|
||||
private PutAccountingRulesRequest() {
|
||||
|
||||
}
|
||||
|
||||
@Schema(example = "Employee Salary posting rule")
|
||||
public String name;
|
||||
}
|
||||
|
||||
@Schema(description = "PutAccountingRulesResponse")
|
||||
public static final class PutAccountingRulesResponse {
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.accounting.rule.data.request;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
public record AccountRuleRequest(String name, Long officeId, Long accountToDebit, Long accountToCredit,
|
||||
String description) implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -26,18 +26,39 @@ apply plugin: 'com.github.davidmc24.gradle.plugin.avro-base'
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
task preprocessAvroSchemas() {
|
||||
doLast {
|
||||
copy {
|
||||
from "$projectDir/src/main/avro"
|
||||
into "$buildDir/generated/avro/src/main/avro"
|
||||
filter { line ->
|
||||
line.replaceAll("\"bigdecimal\"", new File("$projectDir/src/main/resources/avro-templates/bigdecimal.avsc").getText("UTF-8"))
|
||||
abstract class PreprocessAvroSchemasTask extends DefaultTask {
|
||||
@InputDirectory
|
||||
abstract DirectoryProperty getInputDir()
|
||||
|
||||
@InputFile
|
||||
abstract RegularFileProperty getBigDecimalTemplate()
|
||||
|
||||
@OutputDirectory
|
||||
abstract DirectoryProperty getOutputDir()
|
||||
|
||||
@TaskAction
|
||||
def preprocess() {
|
||||
def template = getBigDecimalTemplate().get().asFile.getText("UTF-8")
|
||||
def input = getInputDir().get().asFile
|
||||
def output = getOutputDir().get().asFile
|
||||
|
||||
input.eachFileRecurse { file ->
|
||||
if (file.isFile()) {
|
||||
def relativePath = input.toPath().relativize(file.toPath())
|
||||
def targetFile = output.toPath().resolve(relativePath).toFile()
|
||||
targetFile.parentFile.mkdirs()
|
||||
targetFile.text = file.text.replaceAll("\"bigdecimal\"", template)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('preprocessAvroSchemas', PreprocessAvroSchemasTask) {
|
||||
inputDir = file("$projectDir/src/main/avro")
|
||||
bigDecimalTemplate = file("$projectDir/src/main/resources/avro-templates/bigdecimal.avsc")
|
||||
outputDir = file("$buildDir/generated/avro/src/main/avro")
|
||||
}
|
||||
|
||||
task buildJavaSdk(type: GenerateAvroJavaTask) {
|
||||
source("$buildDir/generated/avro/src/main/avro")
|
||||
outputDir = file("$buildDir/generated/java/src/main/java")
|
||||
@@ -53,7 +74,33 @@ spotless {
|
||||
}
|
||||
|
||||
buildJavaSdk.dependsOn(preprocessAvroSchemas, spotlessJsonApply)
|
||||
compileJava.dependsOn(buildJavaSdk, licenseFormatMain)
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir file("$buildDir/generated/java/src/main/java")
|
||||
}
|
||||
resources {
|
||||
srcDir file("$projectDir/src/main/resources")
|
||||
srcDir file("$projectDir/src/main/avro")
|
||||
}
|
||||
output.dir(file("$buildDir/generated/java/src/main/java"), builtBy: 'buildJavaSdk')
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
from sourceSets.main.output
|
||||
from("$buildDir/generated/java/src/main/java") {
|
||||
include "**/*.java"
|
||||
}
|
||||
}
|
||||
|
||||
compileJava {
|
||||
dependsOn buildJavaSdk
|
||||
source = sourceSets.main.java.srcDirs
|
||||
options.compilerArgs += ['-parameters']
|
||||
}
|
||||
|
||||
java {
|
||||
// keep this at Java 8, not 17
|
||||
@@ -61,7 +108,10 @@ java {
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.errorprone {
|
||||
enabled = false // Disable ErrorProne for this module since it contains generated code
|
||||
}
|
||||
options.compilerArgs -= ["-Werror"]
|
||||
}
|
||||
|
||||
@@ -74,7 +124,10 @@ test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
sourceSets.main.java.srcDir new File(buildDir, "generated/java/src/main/java")
|
||||
|
||||
licenseFormatMain.dependsOn buildJavaSdk
|
||||
licenseMain.dependsOn licenseFormatMain
|
||||
|
||||
tasks.named('sourcesJar') {
|
||||
dependsOn tasks.named('buildJavaSdk')
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{
|
||||
"name": "id",
|
||||
"doc": "The ID of the message to be sent",
|
||||
"type": "int"
|
||||
"type": "long"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{
|
||||
"name": "id",
|
||||
"doc": "The ID of the message to be sent",
|
||||
"type": "int"
|
||||
"type": "long"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "StringEnumOptionDataV1",
|
||||
"namespace": "org.apache.fineract.avro.generic.v1",
|
||||
"type": "record",
|
||||
"fields": [
|
||||
{
|
||||
"default": null,
|
||||
"name": "id",
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "code",
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "value",
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -607,6 +607,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "loanTermVariations",
|
||||
"type": [
|
||||
"null",
|
||||
{
|
||||
"type": "array",
|
||||
"items": "org.apache.fineract.avro.loan.v1.LoanTermVariationsDataV1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "clientActiveLoanOptions",
|
||||
@@ -709,6 +720,14 @@
|
||||
"org.apache.fineract.avro.generic.v1.EnumOptionDataV1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "daysInYearCustomStrategy",
|
||||
"type": [
|
||||
"null",
|
||||
"org.apache.fineract.avro.generic.v1.StringEnumOptionDataV1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "isInterestRecalculationEnabled",
|
||||
@@ -772,6 +791,57 @@
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "enableInstallmentLevelDelinquency",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "enableDownPayment",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "disbursedAmountPercentageForDownPayment",
|
||||
"type": [
|
||||
"null",
|
||||
"bigdecimal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "enableAutoRepaymentForDownPayment",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "interestRecognitionOnDisbursementDate",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "customData",
|
||||
"type": [
|
||||
"null",
|
||||
{
|
||||
"values": "bytes",
|
||||
"type": "map"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -256,6 +256,17 @@
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "customData",
|
||||
"type": [
|
||||
"null",
|
||||
{
|
||||
"values": "bytes",
|
||||
"type": "map"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -146,6 +146,14 @@
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "disallowInterestCalculationOnPastDue",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "transferExternalGroupId",
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "submittedDate",
|
||||
|
||||
@@ -419,6 +419,14 @@
|
||||
"org.apache.fineract.avro.generic.v1.EnumOptionDataV1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "daysInYearCustomStrategy",
|
||||
"type": [
|
||||
"null",
|
||||
"org.apache.fineract.avro.generic.v1.StringEnumOptionDataV1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "isInterestRecalculationEnabled",
|
||||
@@ -641,6 +649,14 @@
|
||||
"null",
|
||||
"org.apache.fineract.avro.loan.v1.DelinquencyBucketDataV1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "interestRecognitionOnDisbursementDate",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+8
@@ -146,6 +146,14 @@
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "disallowInterestCalculationOnPastDue",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "totalUnpaidAccruedDueInterest",
|
||||
"name": "totalUnpaidPayableDueInterest",
|
||||
"type": [
|
||||
"null",
|
||||
"bigdecimal"
|
||||
@@ -445,7 +445,7 @@
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "totalUnpaidAccruedNotDueInterest",
|
||||
"name": "totalUnpaidPayableNotDueInterest",
|
||||
"type": [
|
||||
"null",
|
||||
"bigdecimal"
|
||||
|
||||
@@ -244,6 +244,25 @@
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "customData",
|
||||
"type": [
|
||||
"null",
|
||||
{
|
||||
"values": "bytes",
|
||||
"type": "map"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "reversed",
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"logicalType": "decimal",
|
||||
"precision": 20,
|
||||
"precision": 27,
|
||||
"scale": 8,
|
||||
"type": "bytes"
|
||||
}
|
||||
|
||||
+4
-10
@@ -29,7 +29,6 @@ import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.teller.data.CashierData;
|
||||
import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService;
|
||||
@@ -41,20 +40,15 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class CashierApiResource {
|
||||
|
||||
private final DefaultToApiJsonSerializer<CashierData> jsonSerializer;
|
||||
private final TellerManagementReadPlatformService readPlatformService;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String getCashierData(@QueryParam("officeId") final Long officeId, @QueryParam("tellerId") final Long tellerId,
|
||||
public Collection<CashierData> getCashierData(@QueryParam("officeId") final Long officeId, @QueryParam("tellerId") final Long tellerId,
|
||||
@QueryParam("staffId") final Long staffId, @QueryParam("date") final String date) {
|
||||
final DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE;
|
||||
|
||||
final LocalDate dateRestriction = (date != null ? LocalDate.parse(date, dateFormatter) : DateUtils.getBusinessLocalDate());
|
||||
|
||||
final Collection<CashierData> allCashiers = this.readPlatformService.getCashierData(officeId, tellerId, staffId, dateRestriction);
|
||||
|
||||
return this.jsonSerializer.serialize(allCashiers);
|
||||
final LocalDate dateRestriction = date != null ? LocalDate.parse(date, DateTimeFormatter.BASIC_ISO_DATE)
|
||||
: DateUtils.getBusinessLocalDate();
|
||||
return readPlatformService.getCashierData(officeId, tellerId, staffId, dateRestriction);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user