Compare commits

...

50 Commits

Author SHA1 Message Date
Naeem Ullah e07a74565d Refactor CRM application controllers and services
Replaced InProcessApplicationsController with PendingCRMApplicationsController to handle individual and business pending CRM applications. Updated InProcessApplicationsService to separate logic for individual and business workflows, adding new methods for pending CRM retrieval. Adjusted AconnectURI and TokenBypassURI constants to support new endpoints.
2 weeks ago
Naeem Ullah be297f507f Improve userId extraction in LoggingFilter
Updated LoggingFilter to first check for 'userId' header, then fallback to 'X-USER-ID' if not present. Default userId is now set to 'NA' instead of 'ANONYMOUS' when no header is found.
2 weeks ago
Naeem Ullah 393fa16fa3 Add first login password change endpoint
Introduced a new /first-login endpoint in AuthenticationController to handle password changes on first login. Added corresponding constant in SecurityURI and implemented firstLogin method in UserService to update password and firstLogin status.
2 weeks ago
Naeem Ullah 53866feb45 Merge pull request 'Fetch pending CRM applications' (#8) from Wasi/BS-2194 into dev-pending-20-01-2026
Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-BS/pulls/8
2 weeks ago
Wasiullah Khan 6aa0454e3a Fetch pending CRM applications
Fetch Single CRM Application By WorkFlowRefNum
2 weeks ago
Naeem Ullah d304477b8c Implement soft delete for User entity
Added an isDeleted field to the User model and updated the deleteUser method in UserService to perform a soft delete by setting isDeleted to true and isActive to false. Updated UserRepository with methods to filter out deleted users and adjusted getAllUsers to exclude admin roles.
2 weeks ago
Naeem Ullah 72180528de Merge branch 'dev-pending-20-01-2026' into Naeem-PRE-PRODUCTION-26 2 weeks ago
Naeem Ullah e5fbba3728 Add individual loan approval endpoint and service
Introduced a new endpoint and service method for individual loan approval. Updated AconnectURI and TokenBypassURI to include the new approval URI, and implemented the approval logic in LoanAccountService and LoanAccountController.
2 weeks ago
Naeem Ullah 22c1ce530a added
added
2 weeks ago
Naeem Ullah 5388b85261 added validations
added validations
2 weeks ago
Naeem Ullah 49f1a5b503 Merge pull request 'CRM Workflow Creation' (#7) from Wasi/BS-2086 into dev-pending-20-01-2026
Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-BS/pulls/7
2 weeks ago
Naeem Ullah ad1057474b Add validation for credit and debit amounts in transactions
Introduced checks to ensure credit and debit amounts are present and greater than zero in transaction-related methods. Returns appropriate error responses if validation fails, improving input validation and error handling.
2 weeks ago
Wasiullah Khan 5e5512da67 CRM Workflow Creation
CRM Workflow Creation
2 weeks ago
Naeem Ullah 70244da27b validations 2 weeks ago
Naeem Ullah f9bead4543 Approval DTO 2 weeks ago
Naeem Ullah a4a94da20b Update TransactionService.java 3 weeks ago
Naeem Ullah b12c933b41 validation 3 weeks ago
Naeem Ullah 2ed521330c CMB_ORGA_CODE
CMB_ORGA_CODE
4 weeks ago
Naeem Ullah e806389b9d CIIHIVE_API_BASE_URL
CIIHIVE_API_BASE_URL
4 weeks ago
Naeem Ullah bae66d70f9 Added ENV 4 weeks ago
Naeem Ullah 405e8dc53c Revert "Profile for PROD"
This reverts commit c2156ce962.
4 weeks ago
Naeem Ullah c2156ce962 Profile for PROD
Profile for PROD
4 weeks ago
Naeem Ullah c088501ec3 Added CiiHive Base URL
Added CiiHive Base URL
4 weeks ago
Naeem Ullah 3905f27015 Added Loggers
Added Loggers
4 weeks ago
Naeem Ullah d6f656cda5 Transaction Logs
Transaction Logs
4 weeks ago
Naeem Ullah 1639058e20 Add reset password endpoint and DTO
Introduces a new /reset-password endpoint in AuthenticationController, a ResetPasswordDTO for request payload, and a resetPassword method in UserService to handle password resets. Also updates SecurityURI with the new endpoint constant.
4 weeks ago
Naeem Ullah 44707f34c2 Fix password verification logic in UserService
Corrects the password verification by comparing the provided old password with the user's actual stored password instead of the new password.
4 weeks ago
Naeem Ullah 5e85a32f61 Add password change and user uniqueness validation
Introduced ChangePasswordDTO and implemented password change functionality in UserService and AuthenticationController. Added custom exceptions for existing email, username, and incorrect old password. Updated User entity and DTOs to include porOrgacode, and enforced uniqueness checks for userId and email. Enhanced ERRCode with new error codes and improved boolean field handling in User entity.
4 weeks ago
Naeem Ullah a1f993bfd4 Comment out SubscriptionFilter implementation
The SubscriptionFilter class and its contents have been fully commented out, effectively disabling its functionality. This change may be for debugging, refactoring, or temporary removal pending future updates.
4 weeks ago
Naeem Ullah 8507141d9e Add TransactionLog entity and field constants
Introduced the TransactionLog JPA entity for transaction logging. Added FieldNameConstant and DBFieldNameConstant enums for standardized field names, and expanded FieldNameLength with additional constants. Updated SecurityURI and AuthenticationController to support password change endpoint. Commented out request limiting logic in SubscriptionFilter.
4 weeks ago
Naeem Ullah ea9abc99c8 Add TransactionLog entity and field constants
Introduced the TransactionLog entity for transaction logging. Added FieldNameConstant and DBFieldNameConstant enums for standardized field names, and expanded FieldNameLength with additional constants. Updated SecurityURI and AuthenticationController to support password change endpoint. Fixed PermissionService to use the correct repository for user permission updates.
4 weeks ago
Naeem Ullah 6225454d51 Add PermissionRepository and update PermissionService
Introduced PermissionRepository for managing User entities and refactored PermissionService to use this new repository instead of UserRepository. This change streamlines permission-related operations and improves code organization.
4 weeks ago
Naeem Ullah cf224e3f85 Refactor user permissions to dedicated service and controller
Moved user permission management logic from UserService and UserController to new PermissionService and PermissionController classes. This improves separation of concerns and code organization. Also removed unused findByEmail method from UserRepository.
4 weeks ago
Naeem Ullah 5bd79acda5 Validate Endpoints 4 weeks ago
Naeem Ullah 493b1564c8 Add user management endpoints to token bypass list
Added several /aconnect/user/* endpoints to the TokenBypassURI list to allow these user management operations to bypass token authentication.
4 weeks ago
Naeem Ullah 29a5e2f5e1 Refactor AuthService to use default RestTemplate and ObjectMapper
Replaces constructor-based dependency injection with direct instantiation of RestTemplate and ObjectMapper in AuthService. Simplifies the class by removing the constructor and initializing dependencies inline.
4 weeks ago
Naeem Ullah 10084bbd48 Refactor services to inject RestTemplate via constructor
Updated all service classes to receive RestTemplate (and ObjectMapper where needed) through constructor injection instead of instantiating them directly. Removed the RestTemplateConfig class, as RestTemplate is now expected to be provided externally, improving testability and configuration flexibility.
4 weeks ago
Naeem Ullah 63f10ef2fc Add deposit and loan account services and update controllers
Introduced DepositAccountService and LoanAccountService for handling deposit and loan account operations. Updated DepositAccountController and LoanAccountController to use these services and added new endpoints for individual and business deposit/loan creation and approval. Added RestTemplate configuration and updated AconnectURI and TokenBypassURI constants. Modified PermissionDTO to use a String for permissions and adjusted UserService accordingly. Increased requestBody column length in Logger entity. Added Apache HttpClient5 dependency.
4 weeks ago
Naeem Ullah 2426fb7c7e CRM Api added
CRM Api added
1 month ago
Naeem Ullah 1e375887e5 Refactor transaction controllers and services structure
Split transaction-related endpoints into dedicated controllers and services for authorization, cancellation, rejection, and reversal. Renamed LoginController and LoginService to AuthController and AuthService. Added DTOs for account-to-account and GL-to-account transactions, updated TransactionService to handle new transaction types, and adjusted URI constants and token bypass lists accordingly. Removed EnvironmentDetectionService as part of the refactor.
1 month ago
Naeem Ullah 9c7f195e98 Merge pull request 'User Permission Management' (#4) from Wasi-BS/1676 into FMFI-PRE-PRODUCTION
Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-BS/pulls/4
1 month ago
Wasiullah Khan a0529f9b34 User Permission Management 1 month ago
Naeem Ullah 162678d8d9 Rename econnect module to aconnect
All files and references for the 'econnect' module have been renamed to 'aconnect', including source, test files, and module references in the parent POM. This standardizes the module naming across the project.
1 month ago
Naeem Ullah 16ef541e30 Merge branch 'FMFI-PRE-PRODUCTION' of https://ct.mfsys.com.pk/aConnect/aConnect-BS into FMFI-PRE-PRODUCTION 1 month ago
Naeem Ullah 3a475a595d Update pom.xml 1 month ago
Naeem Ullah e54acd9a61 Merge pull request 'Add ptrTrancode to DTOs and update config files' (#3) from FMFI-PRE-PRODUCTION-PROFILING into FMFI-PRE-PRODUCTION
Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-BS/pulls/3
1 month ago
Naeem Ullah 40cc1f1597 Add ptrTrancode to DTOs and update config files
Added the ptrTrancode field to AccountGLTransactionRequest and GLtoGLRequest DTOs. Updated Maven build to include spring-boot-maven-plugin with profile support. Cleaned up and simplified environment-specific application properties, moving most configuration to environment variables and reducing duplication.
1 month ago
Mubashar Hussain 01d3c23103 Merge pull request 'security module- login screen' (#1) from SecurityModuleChanges into FMFI-PRE-PRODUCTION
Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-BS/pulls/1
2 months ago
Wasiullah Khan 173663d935 security module- login screen 2 months ago
Naeem Ullah fc07a8e88f Base Architecture
Base Architecture
2 months ago

33
.gitignore vendored

@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -0,0 +1,2 @@
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

295
aconnect/mvnw vendored

@ -0,0 +1,295 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.3
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
scriptDir="$(dirname "$0")"
scriptName="$(basename "$0")"
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
# Find the actual extracted directory name (handles snapshots where filename != directory name)
actualDistributionDir=""
# First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# If not found, search for any directory with the Maven executable (for snapshots)
if [ -z "$actualDistributionDir" ]; then
# enable globbing to iterate over items
set +f
for dir in "$TMP_DOWNLOAD_DIR"/*; do
if [ -d "$dir" ]; then
if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

189
aconnect/mvnw.cmd vendored

@ -0,0 +1,189 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.3
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
}
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
$MAVEN_WRAPPER_DISTS = $null
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mfsys</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<groupId>com.mfsys</groupId>
<artifactId>aconnect</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>aconnect</name>
<description>Middleware Application</description>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Database -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Tomcat (external deployment) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Internal common module -->
<dependency>
<groupId>com.mfsys</groupId>
<artifactId>common</artifactId>
<version>0.0.1</version>
</dependency>
<!-- Optional Spring Context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>21</source>
<target>21</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<spring.profiles.active>${spring.profiles.active}</spring.profiles.active>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<!-- Maven Environment Profiles -->
<profiles>
<!-- Development -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
<build>
<finalName>aconnect-dev</finalName>
</build>
</profile>
<!-- UAT -->
<profile>
<id>uat</id>
<properties>
<spring.profiles.active>uat</spring.profiles.active>
</properties>
<build>
<finalName>aconnect-uat</finalName>
</build>
</profile>
<!-- Live / Production -->
<profile>
<id>live</id>
<properties>
<spring.profiles.active>live</spring.profiles.active>
</properties>
<build>
<finalName>aconnect</finalName>
</build>
</profile>
</profiles>
</project>

@ -0,0 +1,29 @@
package com.mfsys.aconnect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication(scanBasePackages = {"com.mfsys"})
@EntityScan(basePackages = {"com.mfsys"})
@EnableJpaRepositories({"com.mfsys"})
public class AconnectApplication {
public static void main(String[] args) {
SpringApplication.run(AconnectApplication.class, args);
}
@Value("${app.base.uri}")
private String baseUri;
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> webServerFactoryCustomizer() {
return factory -> factory.setContextPath("/" + baseUri);
}
}

@ -0,0 +1,13 @@
package com.mfsys.aconnect;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AconnectApplication.class);
}
}

@ -0,0 +1,39 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.SigninRequest;
import com.mfsys.aconnect.client.service.AuthService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class AuthController {
AuthService loginService;
@Autowired
public AuthController(AuthService loginService) {
this.loginService = loginService;
}
@PostMapping(AconnectURI.SIGNIN)
public ResponseEntity<Map<String, Object>> login(@RequestBody(required = false) SigninRequest login) {
if (login == null) {
return ResponseEntity.badRequest().body(Map.of("error", "Request body is missing"));
}
Map<String, String> payload = Map.of(
"username", login.getUsername(),
"password", login.getPassword()
);
Map<String, Object> response = loginService.authenticate(payload);
return ResponseEntity.ok(response);
}
}

@ -0,0 +1,39 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.ApproveCRMRequestDTO;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import com.mfsys.aconnect.client.service.CRMService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class CRMController {
@Autowired
private CRMService crmService;
@Autowired
public CRMController(CRMService crmService) {
this.crmService = crmService;
}
@PostMapping(AconnectURI.INDIVIDUAL_CRM_CREATION_URI)
public Object createIndividualCRM(@RequestBody WorkflowRequestDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return crmService.createIndividualCRM(workflowRequestDTO, token);
}
@PostMapping(AconnectURI.BUSINESS_CRM_CREATION_URI)
public Object createBusinessCRM(@RequestBody WorkflowRequestDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return crmService.createBusinessCRM(workflowRequestDTO, token);
}
@PostMapping(AconnectURI.APPROVE_INDIVIDUAL_CRM_URI)
public Object approveCRM(@RequestBody ApproveCRMRequestDTO approveCRMRequestDTO,
@RequestHeader("Authorization") String token){
return crmService.approveCRM(approveCRMRequestDTO, token);
}
}

@ -0,0 +1,39 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import com.mfsys.aconnect.client.service.CRMService;
import com.mfsys.aconnect.client.service.DepositAccountService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class DepositAccountController {
@Autowired
private DepositAccountService depositAccountService;
@Autowired
public DepositAccountController(DepositAccountService depositAccountService) {
this.depositAccountService = depositAccountService;
}
@PostMapping(AconnectURI.INDIVIDUAL_DEPOSIT_CREATION_URI)
public Object createIndividualDeposit(@RequestBody WorkflowRequestDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return depositAccountService.createIndividualDeposit(workflowRequestDTO, token);
}
@PatchMapping(AconnectURI.UPDATE_DEPOSIT_CREATION_URI)
public Object updateIndividualDeposit(@RequestBody WorkflowApprovalDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return depositAccountService.approvalIndividualDeposit(workflowRequestDTO, token);
}
@PostMapping(AconnectURI.BUSINESS_DEPOSIT_CREATION_URI)
public Object createBusinessCRM(@RequestBody WorkflowRequestDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return depositAccountService.createBusinessDeposit(workflowRequestDTO, token);
}
}

@ -0,0 +1,37 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import com.mfsys.aconnect.client.service.DepositAccountService;
import com.mfsys.aconnect.client.service.LoanAccountService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoanAccountController {
@Autowired
private LoanAccountService loanAccountService;
@Autowired
public LoanAccountController(LoanAccountService loanAccountService) {
this.loanAccountService = loanAccountService;
}
@PostMapping(AconnectURI.INDIVIDUAL_LOAN_CREATION_URI)
public Object createIndividualLoan(@RequestBody WorkflowRequestDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return loanAccountService.createIndividualLoan(workflowRequestDTO, token);
}
@PostMapping(AconnectURI.ACONNECT_LOAN_APPROVAL_URI)
public Object approvalIndividualLoan(@RequestBody WorkflowApprovalDTO workflowRequestDTO,
@RequestHeader("Authorization") String token) {
return loanAccountService.approvalIndividualLoan(workflowRequestDTO, token);
}
}

@ -0,0 +1,38 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.InProcessApplicationsRequestDTO;
import com.mfsys.aconnect.client.service.InProcessApplicationsService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
public class PendingCRMApplicationsController {
private final InProcessApplicationsService inProcessApplicationsService;
public PendingCRMApplicationsController(
InProcessApplicationsService inProcessApplicationsService) {
this.inProcessApplicationsService = inProcessApplicationsService;
}
@PostMapping(AconnectURI.GET_INDIVIDUAL_PENDING_APPLICATIONS_URI)
public ResponseEntity<String> getIndividualPendingCRMs(@RequestBody InProcessApplicationsRequestDTO request,
@RequestHeader("Authorization") String token, @RequestHeader("SUS_USERCODE") String susUserCode) {
return inProcessApplicationsService.getIndividualPendingCRM(request, token, susUserCode);
}
@PostMapping(AconnectURI.GET_BUSINESS_PENDING_APPLICATIONS_URI)
public ResponseEntity<String> getBusinessPendingCRMs(@RequestBody InProcessApplicationsRequestDTO request,
@RequestHeader("Authorization") String token, @RequestHeader("SUS_USERCODE") String susUserCode) {
return inProcessApplicationsService.getBusinessPendingCRM(request, token, susUserCode);
}
@GetMapping(AconnectURI.CHECK_INDIVIDUAL_APPLICATIONS_URI)
public ResponseEntity<String>getIndividualApplication(
@RequestParam("POR_ORGACODE") String porOrgacode,@RequestParam("formId") String formId,
@RequestParam(value = "includeFields", required = false) String includeFields,
@RequestHeader("Authorization") String token, @RequestHeader("SUS_USERCODE") String susUserCode){
return inProcessApplicationsService.getPendingIndividualApplication(porOrgacode, formId, includeFields, token, susUserCode);
}
}

@ -0,0 +1,35 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.DepositAuthorizationRequest;
import com.mfsys.aconnect.client.dto.GLAuthorizationDTO;
import com.mfsys.aconnect.client.service.TransactionAuthorizationService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TransactionAuthorizationController {
@Autowired
private TransactionAuthorizationService transactionAuthorizationService;
@Autowired
public TransactionAuthorizationController(TransactionAuthorizationService transactionAuthorizationService) {
this.transactionAuthorizationService = transactionAuthorizationService;
}
@PostMapping(AconnectURI.DEPOSIT_AUTHORIZATION_URI)
public Object depositAuthorizationTransaction(@RequestBody DepositAuthorizationRequest authorizationRequest,
@RequestHeader("Authorization") String token) {
return transactionAuthorizationService.processDepositAuthTransaction(authorizationRequest, token);
}
@PostMapping(AconnectURI.GENERALLEDGER_AUTHORIZATION_URI)
public Object glAuthorizationTransaction(@RequestBody GLAuthorizationDTO glAuthorizationRequest,
@RequestHeader("Authorization") String token) {
return transactionAuthorizationService.processGLAuthTransaction(glAuthorizationRequest, token);
}
}

@ -0,0 +1,36 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.DepositCancellationDTO;
import com.mfsys.aconnect.client.dto.GLCancellationDTO;
import com.mfsys.aconnect.client.service.CancellationTransactionService;
import com.mfsys.aconnect.client.service.TransactionService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TransactionCancellationController {
@Autowired
private CancellationTransactionService cancellationTransactionService;
@Autowired
public TransactionCancellationController(CancellationTransactionService cancellationTransactionService) {
this.cancellationTransactionService = cancellationTransactionService;
}
@PostMapping(AconnectURI.DEPOSIT_CANCELLATION_URI)
public Object depositCancellationTransaction(@RequestBody DepositCancellationDTO depositCancellationDTO,
@RequestHeader("Authorization") String token) {
return cancellationTransactionService.processDepositCancellationTransaction(depositCancellationDTO, token);
}
@PostMapping(AconnectURI.GENERALLEDGER_CANCELLATION_URI)
public Object glCancellationTransaction(@RequestBody GLCancellationDTO glCancellationRequest,
@RequestHeader("Authorization") String token) {
return cancellationTransactionService.processGLCancellationTransaction(glCancellationRequest, token);
}
}

@ -0,0 +1,63 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.AccountToAccountDTO;
import com.mfsys.aconnect.client.dto.AccountGLTransactionRequest;
import com.mfsys.aconnect.client.dto.GLtoGLRequest;
import com.mfsys.aconnect.client.dto.GlToAccountDTO;
import com.mfsys.aconnect.client.service.TransactionService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
@RestController()
public class TransactionController {
@Autowired
private TransactionService transactionService;
@Autowired
public TransactionController(TransactionService transactionService) {
this.transactionService = transactionService;
}
@GetMapping("/account/getAccountDetails")
public ResponseEntity activeAccountDetails(
@RequestParam("porOrgacode") String porOrgacode,
@RequestParam("mbmBkmsnumber") String mbmBkmsnumber,
@RequestParam(required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate sgtGntrvaluedate,
@RequestHeader("Authorization") String token,
@RequestHeader("SUS_USERCODE") String userCode) {
return transactionService.getActiveAccountDetails(porOrgacode, mbmBkmsnumber, sgtGntrvaluedate, token, userCode);
}
@PostMapping(AconnectURI.TRANSACTION_ACCOUNT_GL_URI)
public Object accountGLTransaction(@RequestBody AccountGLTransactionRequest request,
@RequestHeader("Authorization") String token) {
return transactionService.processAccountTransaction(request, token);
}
@PostMapping(AconnectURI.TRANSACTION_GL_GL_URI)
public Object glGlTransaction(@RequestBody GLtoGLRequest request,
@RequestHeader("Authorization") String token) {
return transactionService.processGLTransaction(request, token);
}
@PostMapping(AconnectURI.ACCOUNT_TO_ACCOUNT_TRANSACTION_URI)
public Object accToAccTransaction(@RequestBody AccountToAccountDTO request,
@RequestHeader("Authorization") String token) {
return transactionService.processAccToAccTransaction(request, token);
}
@PostMapping(AconnectURI.GL_TO_ACCOUNT_TRANSACTION_URI)
public Object glToAccTransaction(@RequestBody GlToAccountDTO glToAccountDTO,
@RequestHeader("Authorization") String token) {
return transactionService.processGLtoAccTransaction(glToAccountDTO, token);
}
}

@ -0,0 +1,26 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.model.TransactionLog;
import com.mfsys.aconnect.client.service.TransactionLogService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController()
@RequestMapping(AconnectURI.TRANSACTION)
public class TransactionLogController {
private final TransactionLogService transactionLogService;
public TransactionLogController(TransactionLogService transactionLogService) {
this.transactionLogService = transactionLogService;
}
@GetMapping(AconnectURI.LOGS)
public List<TransactionLog> getAllTransactionLogs() {
return transactionLogService.getAllTransactionLogs();
}
}

@ -0,0 +1,35 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.DepositRejectDTO;
import com.mfsys.aconnect.client.service.RejectTransactionService;
import com.mfsys.aconnect.client.service.TransactionService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TransactionRejectController {
@Autowired
private RejectTransactionService rejectTransactionService;
@Autowired
public TransactionRejectController(RejectTransactionService rejectTransactionService) {
this.rejectTransactionService = rejectTransactionService;
}
@PostMapping(AconnectURI.DEPOSIT_TRANSACTION_REJECT_URI)
public Object depositRejectionTransaction(@RequestBody DepositRejectDTO rejectRequest,
@RequestHeader("Authorization") String token) {
return rejectTransactionService.processDepositRejectionTransaction(rejectRequest, token);
}
@PostMapping(AconnectURI.GENERALLEDGER_TRANSACTION_REJECT_URI)
public Object glRejectionTransaction(@RequestBody DepositRejectDTO rejectRequest,
@RequestHeader("Authorization") String token) {
return rejectTransactionService.processGLRejectionTransaction(rejectRequest, token);
}
}

@ -0,0 +1,36 @@
package com.mfsys.aconnect.client.controller;
import com.mfsys.aconnect.client.dto.DepositReversalDTO;
import com.mfsys.aconnect.client.dto.GLReversalDTO;
import com.mfsys.aconnect.client.service.ReversalTransactionService;
import com.mfsys.aconnect.client.service.TransactionService;
import com.mfsys.common.configuration.constant.AconnectURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TransactionReversalController {
@Autowired
private ReversalTransactionService reversalTransactionService;
@Autowired
public TransactionReversalController(ReversalTransactionService reversalTransactionService) {
this.reversalTransactionService = reversalTransactionService;
}
@PostMapping(AconnectURI.DEPOSIT_TRANSACTION_REVERSAL_URI)
public Object depositReversalTransaction(@RequestBody DepositReversalDTO depositReversalDTO,
@RequestHeader("Authorization") String token) {
return reversalTransactionService.processDepositReversalTransaction(depositReversalDTO, token);
}
@PostMapping(AconnectURI.GENERALLEDGER_TRANSACTION_REVERSAL_URI)
public Object glReversalTransaction(@RequestBody GLReversalDTO glReversalRequest,
@RequestHeader("Authorization") String token) {
return reversalTransactionService.processGLReversalTransaction(glReversalRequest, token);
}
}

@ -0,0 +1,40 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class AccountGLTransactionRequest {
private AdditionalInfo additionalInfo;
private CreditGl creditGl;
private DebitAcc debitAcc;
private String plcLocacode;
private String porOrgacode;
private String ptrTrancode;
private String ppmPymdcode;
private String sgtGntrcreateusr;
private String sgtGntrnarration;
private String sgtGntrvaluedate;
@Data
public static class AdditionalInfo {
private Boolean sgtRemittancetrans;
private String sgtTrandate;
}
@Data
public static class CreditGl {
private String pcaGlaccode;
private String plcLocacode;
private Double sgtGntramtfc;
}
@Data
public static class DebitAcc {
private String mbmBkmsnumber;
private String pitInstcode;
private Double sgtGntramtfc;
private String sgtGntrinstrumentno;
}
}

@ -0,0 +1,41 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
@Data
public class AccountToAccountDTO {
private AdditionalInfo additionalInfo;
private AccountTranInfo debitAcc;
private AccountTranInfo creditAcc;
private String plcLocacode;
private String porOrgacode;
private String ppmPymdcode;
private String sgtGntrcreateusr;
private String sgtGntrnarration;
private LocalDate sgtGntrvaluedate;
// ---------------- INNER CLASSES ----------------
@Data
public static class AdditionalInfo {
private String sgtBnfowner;
private String sgtPrcRlcscodec;
private String sgtPtrtrancode;
private String sgtRelwithbnfowner;
private String sgtTranreason;
}
@Data
public static class AccountTranInfo {
private String mbmBkmsnumber;
private BigDecimal sgtGntramtfc;
private String pitInstcode;
private String sgtGntrinstrumentno;
}
}

@ -0,0 +1,43 @@
package com.mfsys.aconnect.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ApproveCRMRequestDTO {
private String workFlowId;
private String formId;
private String postProcessFormId;
private String operation;
@JsonProperty("SUS_USERCODE")
private String susUserCode;
@JsonProperty("POR_ORGACODE")
private String porOrgacode;
private String filter;
@JsonProperty("$set")
private String set;
@JsonProperty("$push")
private String push;
private String arrayFilters;
private Map<String, Object> filesMap;
private List<AutoIncrementFieldDTO> autoIncrementFields;
private List<FormCounterDTO> formCounters;
private WorkflowDTO workflow;
}

@ -0,0 +1,15 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class AutoIncrementFieldDTO {
private String key;
private String type;
private List<Integer> position;
private boolean incrementByCategoryTag;
private boolean incrementIfFlowTerminated;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class DepositAuthorizationRequest {
private List<TranDetail> tranDetailList;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class DepositCancellationDTO {
private String sgtGntrtranlink;
private String nodeId;
private String sgtGntrnarration;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class DepositRejectDTO {
private List<TranDetail> tranDetailList;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,11 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class DepositReversalDTO {
private String porOrgacode;
private String susUsercode;
private String nodeId;
private String sgtGntrtranlink;
}

@ -0,0 +1,14 @@
package com.mfsys.aconnect.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class FormCounterDTO {
@JsonProperty("POR_ORGACODE")
private String porOrgacode;
private String autoIncrementField;
private int autoIncrementLength;
private String paddingCharacter;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class GLAuthorizationDTO {
private List<TranDetail> tranDetailList;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class GLCancellationDTO {
private String sgtGntrtranlink;
private String nodeId;
private String sgtGntrnarration;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class GLRejectDTO {
private List<TranDetail> tranDetailList;
private String porOrgacode;
private String susUsercode;
}

@ -0,0 +1,11 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class GLReversalDTO {
private String porOrgacode;
private String susUsercode;
private String nodeId;
private String sgtGntrtranlink;
}

@ -0,0 +1,38 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class GLtoGLRequest {
private GLtoGLRequest.AdditionalInfo additionalInfo;
private GLtoGLRequest.CreditGl creditGl;
private GLtoGLRequest.DebitGl debitGl;
private String plcLocacode;
private String ptrTrancode;
private String porOrgacode;
private String ppmPymdcode;
private String sgtGntrcreateusr;
private String sgtGntrnarration;
private String sgtGntrvaluedate;
@Data
public static class AdditionalInfo {
private Boolean sgtRemittancetrans;
private String sgtTrandate;
}
@Data
public static class CreditGl {
private String pcaGlaccode;
private String plcLocacode;
private Double sgtGntramtfc;
}
@Data
public static class DebitGl {
private String pcaGlaccode;
private String plcLocacode;
private Double sgtGntramtfc;
}
}

@ -0,0 +1,49 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Map;
@Data
public class GlToAccountDTO {
private Map<String, Object> additionalInfo;
private DebitGl debitGl;
private CreditAcc creditAcc;
private String plcLocacode;
private String porOrgacode;
private String ppmPymdcode;
private String sgtGntrcreateusr;
private String sgtGntrnarration;
private LocalDate sgtGntrvaluedate;
private String sgtGntrtmudf1;
private String sgtGntrtmudf2;
private String sgtGntrudf3;
private String sgtGntrudf4;
private String sgtGntrudf5;
private String refNo;
@Data
public static class DebitGl {
private String pcaGlaccode;
private String plcLocacode;
private BigDecimal sgtGntramtfc;
}
@Data
public static class CreditAcc {
private String mbmBkmsnumber;
private BigDecimal sgtGntramtfc;
private String accsgtGntrnarration;
private String accsgtGntrudf3;
private String accsgtGntrudf4;
private String accsgtGntrudf5;
private String pitInstcode;
private String sgtGntrinstrumentno;
}
}

@ -0,0 +1,23 @@
package com.mfsys.aconnect.client.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InProcessApplicationsRequestDTO {
private String porOrgacode;
private String plclocacode;
private Integer limit;
@Builder.Default
private boolean includeRegistrationPending = true;
@Builder.Default
private boolean includeAuthorizationApproved = true;
}

@ -0,0 +1,15 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
import java.util.List;
@Data
public class LazyListRequestDTO {
private String collection;
private Object filter;
private String sortBy;
private Integer limit;
private List<String> includeFields;
}

@ -0,0 +1,13 @@
package com.mfsys.aconnect.client.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SigninRequest {
private String username;
private String password;
}

@ -0,0 +1,9 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class TranDetail {
private String sgtGntrtranlink;
private String nodeId;
}

@ -0,0 +1,38 @@
package com.mfsys.aconnect.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class WorkflowApprovalDTO {
private String workFlowId;
@JsonProperty("SUS_USERCODE")
private String susUserCode;
private String formId;
private String postProcessFormId;
private String operation;
@JsonProperty("POR_ORGACODE")
private String porOrgacode;
private Map<String, Object> filesMap;
private List<AutoIncrementFieldDTO> autoIncrementFields;
private List<FormCounterDTO> formCounters;
private String filter;
private String arrayFilters;
@JsonProperty("$set")
private String set;
@JsonProperty("$push")
private String push;
}

@ -0,0 +1,15 @@
package com.mfsys.aconnect.client.dto;
import lombok.Data;
@Data
public class WorkflowDTO {
private String workFlowId;
private Integer workFlowRefNum;
private String previousStage;
private String nextStage;
}

@ -0,0 +1,39 @@
package com.mfsys.aconnect.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class WorkflowRequestDTO {
private String workFlowId;
@JsonProperty("SUS_USERCODE")
private String susUsercode;
private Map<String, Object> filesMap;
private List<AutoIncrementField> autoIncrementFields;
private String formId;
private String postProcessFormId;
private String payload;
private String operation;
@JsonProperty("POR_ORGACODE")
private String porOrgacode;
private List<List<String>> uniqueConstraints;
private List<Object> formCounters;
@Data
public static class AutoIncrementField {
private String key;
private String type;
private List<Object> position;
private Boolean incrementByCategoryTag;
private Boolean incrementIfFlowTerminated;
}
}

@ -0,0 +1,26 @@
package com.mfsys.aconnect.client.model;
public enum IDType {
cnic("CNIC","01"),
poc("POC","04"),
nicop("NICOP","05"),
passport("PASSPORT","02");
private final String value;
private final String code;
IDType(String value, String code) {
this.value = value;
this.code = code;
}
public String getValue() {
return value;
}
public String getCode() {
return code;
}
}

@ -0,0 +1,58 @@
package com.mfsys.aconnect.client.model;
import com.mfsys.common.configuration.constant.FieldNameLength;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Entity(name = "TBL_AC_TRANSACTION_LOGS")
@Table(name = "TBL_AC_TRANSACTION_LOGS")
@Data
public class TransactionLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "LOG_ID", nullable = false, updatable = false)
private Long logId;
@Column(name = "POR_ORGACODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.POR_ORGACODE)
private String porOrgacode;
@Column(name = "DR_MBMBKMSNUMBER", nullable = true, updatable = false, columnDefinition = FieldNameLength.ACCOUNT_NUMBER)
private String drMbmbkmsnumber;
@Column(name = "CR_MBMBKMSNUMBER", nullable = true, updatable = false, columnDefinition = FieldNameLength.ACCOUNT_NUMBER)
private String crMbmbkmsnumber;
@Column(name = "CR_PCAGLACCODE", nullable = true, updatable = false, columnDefinition = FieldNameLength.ACCOUNT_NUMBER)
private String crPcaglacode;
@Column(name = "DR_PCAGLACCODE", nullable = true, updatable = false, columnDefinition = FieldNameLength.ACCOUNT_NUMBER)
private String drPcaGlacode;
@Column(name = "PPM_PYMDCODE", nullable=true, updatable=false, columnDefinition=FieldNameLength.PPM_PYMDCODE)
private String ppmPymdcode;
@Column(name = "SGT_GNTRDATE", nullable=false, updatable=false, columnDefinition=FieldNameLength.DATE)
private LocalDate sgtGntrdate;
@Column(name = "SGT_GNTRCREATEAT",nullable=false, updatable=false, columnDefinition=FieldNameLength.PLC_LOCACODE)
private String sgtGntrcreateat;
@Column(name = "CHANNEL_CODE", columnDefinition=FieldNameLength.CHANNEL_CODE)
private String channelCode;
@Column(name = "TRANSACTION_ID", columnDefinition=FieldNameLength.ACCOUNT_TITLE)
private String transactionID;
@CreationTimestamp
@Column(name = "CREATED_AT", updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "UPDATED_AT")
private LocalDateTime updatedAt;
}

@ -0,0 +1,7 @@
package com.mfsys.aconnect.client.repository;
import com.mfsys.aconnect.client.model.TransactionLog;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TransactionLogRepository extends JpaRepository<TransactionLog, Long> {
}

@ -0,0 +1,52 @@
package com.mfsys.aconnect.client.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@Service
public class AuthService {
@Value("${app.organization.uri}")
private String OrgaCode;
@Value("${app.security.uri}")
private String securityURI;
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
public Map<String, Object> authenticate(Map<String, String> payload) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("mobileLogin", "false");
Map<String, String> requestPayload = new HashMap<>(payload);
requestPayload.put("clientid", OrgaCode);
HttpEntity<Map<String, String>> request = new HttpEntity<>(requestPayload, headers);
try {
ResponseEntity<String> response = restTemplate.postForEntity(securityURI, request, String.class);
JsonNode jsonNode = objectMapper.readTree(response.getBody());
Map<String, Object> result = new HashMap<>();
result.put("authenticated", jsonNode.get("authenticated").asBoolean());
result.put("token", jsonNode.get("token").asText());
result.put("userName", jsonNode.get("userName").asText());
return result;
} catch (Exception e) {
return Map.of(
"authenticated", false,
"error", "Authentication failed: " + e.getMessage()
);
}
}
}

@ -0,0 +1,89 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.ApproveCRMRequestDTO;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@Service
public class CRMService {
@Value("${app.crm.uri}")
private String crmURI;
private final RestTemplate restTemplate;
public CRMService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object createIndividualCRM(WorkflowRequestDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = crmURI + "/crm" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowRequestDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object createBusinessCRM(WorkflowRequestDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = crmURI + "/crm" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowRequestDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object approveCRM(ApproveCRMRequestDTO approveCRMRequestDTO, String token) {
String porOrgacode = approveCRMRequestDTO.getPorOrgacode();
String url = crmURI + "/crm" + "/mongodb/formdata";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", approveCRMRequestDTO.getPorOrgacode());
headers.set("SUS_USERCODE", approveCRMRequestDTO.getSusUserCode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<ApproveCRMRequestDTO> entity = new HttpEntity<>(approveCRMRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.PATCH,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,76 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.DepositCancellationDTO;
import com.mfsys.aconnect.client.dto.GLCancellationDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import static com.mfsys.common.configuration.constant.AconnectURI.ACONNECT;
import static com.mfsys.common.configuration.constant.AconnectURI.GENERALLEDGER;
@Service
public class CancellationTransactionService {
@Value("${app.deposit.uri}")
private String depositURI;
@Value("${app.generalledger.uri}")
private String generalledgerURI;
private final RestTemplate restTemplate;
public CancellationTransactionService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object processDepositCancellationTransaction(DepositCancellationDTO depositCancellationDTO, String tokenHeader) {
String porOrgacode = depositCancellationDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/organizations/" + depositCancellationDTO.getPorOrgacode() +
"/transactions" + ACONNECT + "/cancel/nodes/" + depositCancellationDTO.getNodeId() +
"/trannums/" + depositCancellationDTO.getSgtGntrtranlink();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", depositCancellationDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<DepositCancellationDTO> entity = new HttpEntity<>(depositCancellationDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLCancellationTransaction(GLCancellationDTO glCancellationDTO, String tokenHeader) {
String porOrgacode = glCancellationDTO.getPorOrgacode();
String url = generalledgerURI + GENERALLEDGER + "/organizations/" + glCancellationDTO.getPorOrgacode() +
"/transactions" + ACONNECT + "/cancel/nodes/" + glCancellationDTO.getNodeId() +
"/trannums/" + glCancellationDTO.getSgtGntrtranlink();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", glCancellationDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<GLCancellationDTO> entity = new HttpEntity<>(glCancellationDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,89 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Service
public class DepositAccountService {
@Value("${app.deposit.uri}")
private String depositURI;
private final RestTemplate restTemplate;
public DepositAccountService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object createIndividualDeposit(WorkflowRequestDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowRequestDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object approvalIndividualDeposit(WorkflowApprovalDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUserCode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowApprovalDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.PATCH,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object createBusinessDeposit(WorkflowRequestDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowRequestDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,259 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class InProcessApplicationsService {
@Value("${app.crm.uri}")
private String crmURI;
private final RestTemplate restTemplate;
public InProcessApplicationsService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
private Map<String, Object> param(String columnName, Object columnValue, String columnType, String conditionType) {
return Map.of("columnName", columnName, "columnValue", columnValue,
"columnType", columnType, "conditionType", conditionType
);
}
private Map<String, Object> buildWorkflowFilter(InProcessApplicationsRequestDTO req) {
List<Object> workflowQueries = new ArrayList<>();
if (req.isIncludeRegistrationPending()) {
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_CP_REGISTRATION", "text", "="),
param("applicationStatus", "Pending", "text", "=")
),
"operator", "$and"
));
}
if (req.isIncludeAuthorizationApproved()) {
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_CP_AUTHORIZATION", "text", "="),
param("applicationStatus", "Approved", "text", "="),
param("postProcessCompleted", true, "boolean", "!=")
),
"operator", "$and"
));
}
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_CP_REGISTRATION", "text", "="),
param("applicationStatus", "[\"Rejected\",\"Hold\"]", "text", "in")
),
"operator", "$and"
));
return Map.of(
"nestedQuery", workflowQueries,
"operator", "$or"
);
}
private Map<String, Object> businessBuildWorkflowFilter(InProcessApplicationsRequestDTO req) {
List<Object> workflowQueries = new ArrayList<>();
if (req.isIncludeRegistrationPending()) {
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_BP_REGISTRATION", "text", "="),
param("applicationStatus", "Pending", "text", "=")
),
"operator", "$and"
));
}
if (req.isIncludeAuthorizationApproved()) {
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_BP_AUTHORIZATION", "text", "="),
param("applicationStatus", "Approved", "text", "="),
param("postProcessCompleted", true, "boolean", "!=")
),
"operator", "$and"
));
}
workflowQueries.add(Map.of(
"params", List.of(
param("workFlowStage", "BN_WF_BP_REGISTRATION", "text", "="),
param("applicationStatus", "[\"Rejected\",\"Hold\"]", "text", "in")
),
"operator", "$and"
));
return Map.of(
"nestedQuery", workflowQueries,
"operator", "$or"
);
}
private LazyListRequestDTO indivdualBuildLazyListPayload(InProcessApplicationsRequestDTO req) {
List<Object> rootQueries = new ArrayList<>();
rootQueries.add(Map.of(
"params", List.of(
param("POR_ORGACODE", req.getPorOrgacode(), "text", "="),
param("POR_ORGACODE_ENTRY", req.getPorOrgacode(), "text", "=")
),
"operator", "$or"
));
rootQueries.add(Map.of(
"params", List.of(
param("PLC_LOCACODE", "[\"" + req.getPlclocacode() + "\"]", "text", "in"),
param("PLC_LOCACODE_ENTRY", "[\"" + req.getPlclocacode() + "\"]", "text", "in")
),
"operator", "$or"
));
rootQueries.add(buildWorkflowFilter(req));
LazyListRequestDTO dto = new LazyListRequestDTO();
dto.setCollection("BN_WF_CP_CUSTOMERPROFILE");
dto.setFilter(Map.of(
"nestedQuery", rootQueries,
"operator", "$and"
));
if (req.getLimit() != null) {
dto.setLimit(req.getLimit());
}
dto.setSortBy("{\"workFlowRefNum\":-1}");
dto.setIncludeFields(List.of(
"CMP_CUSTCODE", "CMP_FIRSTNAME", "CMP_LASTNAME", "PLC_LOCACODE", "workFlowRefNum",
"applicationStatus", "workFlowStage", "workFlowLog", "postProcessCompleted", "failureCause",
"postProcessInProgress"
));
return dto;
}
private LazyListRequestDTO BusinessBuildLazyListPayload(InProcessApplicationsRequestDTO req) {
List<Object> rootQueries = new ArrayList<>();
rootQueries.add(Map.of(
"params", List.of(
param("POR_ORGACODE", req.getPorOrgacode(), "text", "="),
param("POR_ORGACODE_ENTRY", req.getPorOrgacode(), "text", "=")
),
"operator", "$or"
));
rootQueries.add(Map.of(
"params", List.of(
param("PLC_LOCACODE", "[\"" + req.getPlclocacode() + "\"]", "text", "in"),
param("PLC_LOCACODE_ENTRY", "[\"" + req.getPlclocacode() + "\"]", "text", "in")
),
"operator", "$or"
));
rootQueries.add(businessBuildWorkflowFilter(req));
LazyListRequestDTO dto = new LazyListRequestDTO();
dto.setCollection("BN_WF_BP_BUSINESSPROFILE");
dto.setFilter(Map.of(
"nestedQuery", rootQueries,
"operator", "$and"
));
if (req.getLimit() != null) {
dto.setLimit(req.getLimit());
}
dto.setSortBy("{\"workFlowRefNum\":-1}");
dto.setIncludeFields(List.of(
"CMP_CUSTCODE", "CMP_COMPANYNAME", "workFlowRefNum", "applicationStatus", "workFlowStage",
"workFlowStage", "workFlowLog", "postProcessCompleted", "failureCause",
"postProcessInProgress"
));
return dto;
}
public ResponseEntity<String> getIndividualPendingCRM(
InProcessApplicationsRequestDTO request, String token, String susUserCode) {
String url = crmURI + "/crm" + "/mongodb/lazylist";
LazyListRequestDTO payload = indivdualBuildLazyListPayload(request);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", request.getPorOrgacode());
headers.set("SUS_USERCODE", susUserCode);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<LazyListRequestDTO> entity = new HttpEntity<>(payload, headers);
return restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class
);
}
public ResponseEntity<String> getBusinessPendingCRM(
InProcessApplicationsRequestDTO request, String token, String susUserCode) {
String url = crmURI + "/crm" + "/mongodb/lazylist";
LazyListRequestDTO payload = BusinessBuildLazyListPayload(request);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", request.getPorOrgacode());
headers.set("SUS_USERCODE", susUserCode);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<LazyListRequestDTO> entity = new HttpEntity<>(payload, headers);
return restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class
);
}
public ResponseEntity<String> getPendingIndividualApplication(
String porOrgacode, String formId, String includeFields, String token, String susUserCode) {
String url = crmURI + "/crm" + "/mongodb/metadata";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("POR_ORGACODE", porOrgacode).queryParam("formId", formId);
if (includeFields != null && !includeFields.isBlank()) {
builder.queryParam("includeFields", includeFields);
}
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", susUserCode);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Void> entity = new HttpEntity<>(headers);
return restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class
);
}
}

@ -0,0 +1,65 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.WorkflowApprovalDTO;
import com.mfsys.aconnect.client.dto.WorkflowRequestDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Service
public class LoanAccountService {
@Value("${app.loan.uri}")
private String loanURI;
private final RestTemplate restTemplate;
public LoanAccountService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object createIndividualLoan(WorkflowRequestDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = loanURI + "/loan" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowRequestDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object approvalIndividualLoan(WorkflowApprovalDTO workflowRequestDTO, String token) {
String porOrgacode = workflowRequestDTO.getPorOrgacode();
String url = loanURI + "/loan" + "/mongodb/formdata" ;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", workflowRequestDTO.getSusUserCode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<WorkflowApprovalDTO> entity = new HttpEntity<>(workflowRequestDTO, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.PATCH,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,69 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.DepositRejectDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import static com.mfsys.common.configuration.constant.AconnectURI.ACONNECT;
@Service
public class RejectTransactionService {
@Value("${app.deposit.uri}")
private String depositURI;
@Value("${app.generalledger.uri}")
private String generalledgerURI;
private final RestTemplate restTemplate;
public RejectTransactionService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object processDepositRejectionTransaction(DepositRejectDTO rejectRequest, String tokenHeader) {
String porOrgacode = rejectRequest.getPorOrgacode();
String url = depositURI + "/deposit/" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT +"/rejection";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", rejectRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<DepositRejectDTO> entity = new HttpEntity<>(rejectRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLRejectionTransaction(DepositRejectDTO rejectRequest, String tokenHeader) {
String porOrgacode = rejectRequest.getPorOrgacode();
String url = generalledgerURI + "/generalledger/" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT +"/rejection";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", rejectRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<DepositRejectDTO> entity = new HttpEntity<>(rejectRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,75 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.DepositReversalDTO;
import com.mfsys.aconnect.client.dto.GLReversalDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import static com.mfsys.common.configuration.constant.AconnectURI.ACONNECT;
@Service
public class ReversalTransactionService {
@Value("${app.deposit.uri}")
private String depositURI;
@Value("${app.generalledger.uri}")
private String generalledgerURI;
private final RestTemplate restTemplate;
public ReversalTransactionService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object processDepositReversalTransaction(DepositReversalDTO reversalRequest, String tokenHeader) {
String porOrgacode = reversalRequest.getPorOrgacode();
String nodeID = reversalRequest.getNodeId();
String sgtGntrtranlink = reversalRequest.getSgtGntrtranlink();
String url = depositURI + "/deposit/" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT + "/reversals/nodes/" + nodeID + "/trannums/" + sgtGntrtranlink;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", reversalRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<DepositReversalDTO> entity = new HttpEntity<>(reversalRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLReversalTransaction(GLReversalDTO reversalRequest, String tokenHeader) {
String porOrgacode = reversalRequest.getPorOrgacode();
String nodeID = reversalRequest.getNodeId();
String sgtGntrtranlink = reversalRequest.getSgtGntrtranlink();
String url = generalledgerURI + "/generalledger/" + "/organizations/" + porOrgacode + "/transactions"+ ACONNECT +"/reversals/nodes/" + nodeID + "/trannums/" + sgtGntrtranlink;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", reversalRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<GLReversalDTO> entity = new HttpEntity<>(reversalRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,71 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.DepositAuthorizationRequest;
import com.mfsys.aconnect.client.dto.GLAuthorizationDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import static com.mfsys.common.configuration.constant.AconnectURI.ACONNECT;
@Service
public class TransactionAuthorizationService {
@Value("${app.deposit.uri}")
private String depositURI;
@Value("${app.generalledger.uri}")
private String generalledgerURI;
private final RestTemplate restTemplate;
public TransactionAuthorizationService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Object processDepositAuthTransaction(DepositAuthorizationRequest authorizationRequest, String tokenHeader) {
String porOrgacode = authorizationRequest.getPorOrgacode();
String url = depositURI + "/deposit/" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT + "/authorizations";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", authorizationRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<DepositAuthorizationRequest> entity = new HttpEntity<>(authorizationRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLAuthTransaction(GLAuthorizationDTO authorizationRequest, String tokenHeader) {
String porOrgacode = authorizationRequest.getPorOrgacode();
String url = generalledgerURI + "/generalledger/" + "/organizations/" + porOrgacode + "/transactions/authorizations";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", authorizationRequest.getSusUsercode());
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<GLAuthorizationDTO> entity = new HttpEntity<>(authorizationRequest, headers);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,110 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.repository.TransactionLogRepository;
import com.mfsys.aconnect.client.dto.AccountGLTransactionRequest;
import com.mfsys.aconnect.client.dto.AccountToAccountDTO;
import com.mfsys.aconnect.client.dto.GLtoGLRequest;
import com.mfsys.aconnect.client.dto.GlToAccountDTO;
import com.mfsys.aconnect.client.model.TransactionLog;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Service
public class TransactionLogService {
private final TransactionLogRepository transactionLogRepository;
public TransactionLogService(TransactionLogRepository transactionLogRepository) {
this.transactionLogRepository = transactionLogRepository;
}
public List<TransactionLog> getAllTransactionLogs() {
return transactionLogRepository.findAll();
}
public TransactionLog createTransactionLog(AccountGLTransactionRequest accountGLTransactionRequest) {
TransactionLog transactionLog = new TransactionLog();
transactionLog.setPorOrgacode(accountGLTransactionRequest.getPorOrgacode());
transactionLog.setChannelCode(accountGLTransactionRequest.getSgtGntrcreateusr());
transactionLog.setSgtGntrcreateat(accountGLTransactionRequest.getSgtGntrcreateusr());
transactionLog.setCrMbmbkmsnumber("");
transactionLog.setDrMbmbkmsnumber(accountGLTransactionRequest.getDebitAcc().getMbmBkmsnumber());
transactionLog.setCrPcaglacode(accountGLTransactionRequest.getCreditGl().getPcaGlaccode());
transactionLog.setDrPcaGlacode("");
transactionLog.setPpmPymdcode(accountGLTransactionRequest.getPpmPymdcode());
transactionLog.setSgtGntrdate(LocalDate.parse(accountGLTransactionRequest.getSgtGntrvaluedate()));
transactionLog.setCreatedAt(LocalDateTime.now());
transactionLog.setUpdatedAt(LocalDateTime.now());
transactionLog.setSgtGntrdate(LocalDate.parse(accountGLTransactionRequest.getSgtGntrvaluedate()));
return transactionLogRepository.save(transactionLog);
}
@Transactional
public void updateResponseFields(Long logId, Map<String, Object> response) {
transactionLogRepository.findById(logId).ifPresent(log -> {
if (response == null) return;
Object argsObj = response.get("arguments");
if (!(argsObj instanceof List<?> args) || args.isEmpty()) return;
String transactionId = args.get(0).toString();
log.setTransactionID(transactionId);
});
}
public TransactionLog createGLtoGLTransactionLog(GLtoGLRequest gLtoGLRequest) {
TransactionLog transactionLog = new TransactionLog();
transactionLog.setPorOrgacode(gLtoGLRequest.getPorOrgacode());
transactionLog.setChannelCode(gLtoGLRequest.getSgtGntrcreateusr());
transactionLog.setSgtGntrcreateat(gLtoGLRequest.getSgtGntrcreateusr());
transactionLog.setCrMbmbkmsnumber("");
transactionLog.setDrMbmbkmsnumber("");
transactionLog.setCrPcaglacode(gLtoGLRequest.getCreditGl().getPcaGlaccode());
transactionLog.setDrPcaGlacode(gLtoGLRequest.getDebitGl().getPcaGlaccode());
transactionLog.setPpmPymdcode(gLtoGLRequest.getPpmPymdcode());
transactionLog.setSgtGntrdate(LocalDate.parse(gLtoGLRequest.getSgtGntrvaluedate()));
transactionLog.setCreatedAt(LocalDateTime.now());
transactionLog.setUpdatedAt(LocalDateTime.now());
transactionLog.setSgtGntrdate(LocalDate.parse(gLtoGLRequest.getSgtGntrvaluedate()));
return transactionLogRepository.save(transactionLog);
}
public TransactionLog createAccToAccTransactionLog(AccountToAccountDTO accountToAccountDTO) {
TransactionLog transactionLog = new TransactionLog();
transactionLog.setPorOrgacode(accountToAccountDTO.getPorOrgacode());
transactionLog.setChannelCode(accountToAccountDTO.getSgtGntrcreateusr());
transactionLog.setSgtGntrcreateat(accountToAccountDTO.getSgtGntrcreateusr());
transactionLog.setCrMbmbkmsnumber(accountToAccountDTO.getCreditAcc().getMbmBkmsnumber());
transactionLog.setDrMbmbkmsnumber(accountToAccountDTO.getDebitAcc().getMbmBkmsnumber());
transactionLog.setCrPcaglacode("");
transactionLog.setDrPcaGlacode("");
transactionLog.setPpmPymdcode(accountToAccountDTO.getPpmPymdcode());
transactionLog.setSgtGntrdate(accountToAccountDTO.getSgtGntrvaluedate());
transactionLog.setCreatedAt(LocalDateTime.now());
transactionLog.setUpdatedAt(LocalDateTime.now());
transactionLog.setSgtGntrdate(accountToAccountDTO.getSgtGntrvaluedate());
return transactionLogRepository.save(transactionLog);
}
public TransactionLog createGLToAccTransactionLog(GlToAccountDTO glToAccountDTO) {
TransactionLog transactionLog = new TransactionLog();
transactionLog.setPorOrgacode(glToAccountDTO.getPorOrgacode());
transactionLog.setChannelCode(glToAccountDTO.getSgtGntrcreateusr());
transactionLog.setSgtGntrcreateat(glToAccountDTO.getSgtGntrcreateusr());
transactionLog.setCrMbmbkmsnumber(glToAccountDTO.getCreditAcc().getMbmBkmsnumber());
transactionLog.setDrMbmbkmsnumber("");
transactionLog.setCrPcaglacode("");
transactionLog.setDrPcaGlacode("");
transactionLog.setPpmPymdcode(glToAccountDTO.getPpmPymdcode());
transactionLog.setSgtGntrdate(glToAccountDTO.getSgtGntrvaluedate());
transactionLog.setCreatedAt(LocalDateTime.now());
transactionLog.setUpdatedAt(LocalDateTime.now());
transactionLog.setSgtGntrdate(glToAccountDTO.getSgtGntrvaluedate());
return transactionLogRepository.save(transactionLog);
}
}

@ -0,0 +1,280 @@
package com.mfsys.aconnect.client.service;
import com.mfsys.aconnect.client.dto.*;
import com.mfsys.aconnect.client.model.TransactionLog;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpHeaders;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Map;
import static com.mfsys.common.configuration.constant.AconnectURI.*;
@Service
public class TransactionService {
@Value("${app.deposit.uri}")
private String depositURI;
@Value("${app.generalledger.uri}")
private String generalledgerURI;
private final RestTemplate restTemplate;
private final TransactionLogService transactionLogService;
public TransactionService(RestTemplate restTemplate, TransactionLogService transactionLogService) {
this.restTemplate = restTemplate;
this.transactionLogService = transactionLogService;
}
public ResponseEntity getActiveAccountDetails(String porOrgacode, String mbmBkmsnumber, LocalDate sgtGntrvaluedate, String tokenHeader, String userCode) {
String url = depositURI + DEPOSIT_CIIHIVE_ACCOUNT_MISCELLANEOUS_DETAILS_URI + "?porOrgacode=" + porOrgacode + "&mbmBkmsnumber=" + mbmBkmsnumber;
if (sgtGntrvaluedate != null) {
url += "&sgtGntrvaluedate=" + sgtGntrvaluedate;
}
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", userCode);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<Void> entity = new HttpEntity<>(headers);
ResponseEntity<Map> response = restTemplate.exchange(url,HttpMethod.GET,entity,Map.class);
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public ResponseEntity processAccountTransaction(AccountGLTransactionRequest accountGLTransactionRequest, String tokenHeader) {
Double creditAmount = accountGLTransactionRequest.getCreditGl().getSgtGntramtfc();
Double debitAmount = accountGLTransactionRequest.getDebitAcc().getSgtGntramtfc();
if (creditAmount == null || debitAmount == null) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts are required");
}
if (creditAmount <= 0 || debitAmount <= 0) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be greater than 0");
}
if (!creditAmount.equals(debitAmount)) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be equal");
}
String porOrgacode = accountGLTransactionRequest.getPorOrgacode();
String url = depositURI + "/deposit/" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT + "/accounttogls";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", accountGLTransactionRequest.getSgtGntrcreateusr());
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<AccountGLTransactionRequest> entity = new HttpEntity<>(accountGLTransactionRequest, headers);
TransactionLog log = transactionLogService.createTransactionLog(accountGLTransactionRequest);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
if (response.getBody() != null) {
transactionLogService.updateResponseFields(log.getLogId(), response.getBody());
}
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLTransaction(GLtoGLRequest gLtoGLRequest, String tokenHeader) {
Double creditAmount = gLtoGLRequest.getCreditGl().getSgtGntramtfc();
Double debitAmount = gLtoGLRequest.getDebitGl().getSgtGntramtfc();
String crGL = gLtoGLRequest.getCreditGl().getPcaGlaccode();
String drGL = gLtoGLRequest.getDebitGl().getPcaGlaccode();
String drLocation = gLtoGLRequest.getDebitGl().getPlcLocacode();
String crLocation = gLtoGLRequest.getCreditGl().getPlcLocacode();
if(crGL == null || drGL == null) {
return ResponseEntity
.badRequest()
.body("Credit and Debit GL codes are required");
}
if(crGL.equals(drGL) && drLocation.equals(crLocation)) {
return ResponseEntity
.badRequest()
.body("Credit and Debit GL codes cannot be same");
}
if (creditAmount == null || debitAmount == null) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts are required");
}
if (creditAmount <= 0 || debitAmount <= 0) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be greater than 0");
}
if (!creditAmount.equals(debitAmount)) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be equal");
}
String porOrgacode = gLtoGLRequest.getPorOrgacode();
String url = generalledgerURI + "/generalledger" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT +"/gltogls";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", gLtoGLRequest.getSgtGntrcreateusr());
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<GLtoGLRequest> entity = new HttpEntity<>(gLtoGLRequest, headers);
RestTemplate restTemplate = new RestTemplate();
TransactionLog log = transactionLogService.createGLtoGLTransactionLog(gLtoGLRequest);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
if (response.getBody() != null) {
transactionLogService.updateResponseFields(log.getLogId(), response.getBody());
}
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processAccToAccTransaction(AccountToAccountDTO accountToAccountDTO, String tokenHeader) {
BigDecimal creditAmount = accountToAccountDTO.getCreditAcc().getSgtGntramtfc();
BigDecimal debitAmount = accountToAccountDTO.getDebitAcc().getSgtGntramtfc();
String crAcc = accountToAccountDTO.getCreditAcc().getMbmBkmsnumber();
String drAcc = accountToAccountDTO.getDebitAcc().getMbmBkmsnumber();
if(crAcc == null || drAcc == null) {
return ResponseEntity
.badRequest()
.body("Credit and Debit account numbers are required");
}
if(crAcc.equals(drAcc)) {
return ResponseEntity
.badRequest()
.body("Debit Account Number and Credit Account Number shouldn't be same");
}
if (creditAmount == null || debitAmount == null) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts are required");
}
if (creditAmount.compareTo(BigDecimal.ZERO) <= 0 ||
debitAmount.compareTo(BigDecimal.ZERO) <= 0) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be greater than 0");
}
if (!creditAmount.equals(debitAmount)) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be equal");
}
String porOrgacode = accountToAccountDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT + "/account-to-account";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", accountToAccountDTO.getSgtGntrcreateusr());
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<AccountToAccountDTO> entity = new HttpEntity<>(accountToAccountDTO, headers);
RestTemplate restTemplate = new RestTemplate();
TransactionLog log = transactionLogService.createAccToAccTransactionLog(accountToAccountDTO);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
if (response.getBody() != null) {
transactionLogService.updateResponseFields(log.getLogId(), response.getBody());
}
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
public Object processGLtoAccTransaction(GlToAccountDTO glToAccountDTO, String tokenHeader) {
BigDecimal creditAmount = glToAccountDTO.getCreditAcc().getSgtGntramtfc();
BigDecimal debitAmount = glToAccountDTO.getDebitGl().getSgtGntramtfc();
if (!creditAmount.equals(debitAmount)) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be equal");
}
if (creditAmount.compareTo(BigDecimal.ZERO) <= 0 ||
debitAmount.compareTo(BigDecimal.ZERO) <= 0) {
return ResponseEntity
.badRequest()
.body("Credit and Debit amounts must be greater than 0");
}
String porOrgacode = glToAccountDTO.getPorOrgacode();
String url = depositURI + "/deposit" + "/organizations/" + porOrgacode + "/transactions" + ACONNECT + "/gl-to-account";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", glToAccountDTO.getSgtGntrcreateusr());
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<GlToAccountDTO> entity = new HttpEntity<>(glToAccountDTO, headers);
RestTemplate restTemplate = new RestTemplate();
TransactionLog log = transactionLogService.createGLToAccTransactionLog(glToAccountDTO);
ResponseEntity<Map> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Map.class
);
if (response.getBody() != null) {
transactionLogService.updateResponseFields(log.getLogId(), response.getBody());
}
return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
}
}

@ -0,0 +1,15 @@
package com.mfsys.aconnect.configuration.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
}

@ -0,0 +1,25 @@
package com.mfsys.aconnect.configuration.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
System.out.println("✅ Custom SecurityFilterChain loaded");
http
.csrf(csrf -> csrf.disable()) // Disable CSRF for API use
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll() // Allow all requests
)
.httpBasic(Customizer.withDefaults()); // Optional — won't do anything since all requests are permitted
return http.build();
}
}

@ -0,0 +1,23 @@
package com.mfsys.aconnect.configuration.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
private final String baseUrl = "http://localhost:8080/digitalkisaan";
@Bean
public WebClient webClient(WebClient.Builder builder) {
return builder
.baseUrl(baseUrl) // Set the base URL for all requests
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // Set a default content type
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) // Set a default accept header
.build();
}
}

@ -0,0 +1,65 @@
package com.mfsys.aconnect.configuration.service;
import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Service
public class RequestRateLimiterService {
private final ConcurrentHashMap<String, RateLimitData> requestCounts = new ConcurrentHashMap<>();
public boolean isRequestAllowed(String userId, String requestURI, int maxRequestsPerMinute) {
String key = userId + ":" + requestURI;
long currentTimeMillis = System.currentTimeMillis();
requestCounts.putIfAbsent(key, new RateLimitData(currentTimeMillis, 0));
RateLimitData data = requestCounts.get(key);
// Check if a minute has passed since the last reset
if (TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - data.getTimestamp()) >= 1) {
// Reset the counter if a minute has passed
data.setCount(1);
data.setTimestamp(currentTimeMillis);
return true;
} else {
// Increment and check the count
data.incrementCount();
if (data.getCount() > maxRequestsPerMinute) {
return false; // Request denied
}
return true; // Request allowed
}
}
}
class RateLimitData {
private long timestamp;
private int count;
public RateLimitData(long timestamp, int count) {
this.timestamp = timestamp;
this.count = count;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void incrementCount() {
this.count++;
}
}

@ -0,0 +1,10 @@
package com.mfsys.aconnect.security.constant;
public interface SecurityURI {
String AUTHENTICATION = "/authentication";
String LOGIN = "/login";
String REGISTER = "/signup";
String CHANGE_PASSWORD = "/change-password";
String FIRST_LOGIN = "/first-login";
String RESET_PASSWORD = "/reset-password";
}

@ -0,0 +1,76 @@
package com.mfsys.aconnect.security.controller;
import com.mfsys.aconnect.security.constant.SecurityURI;
import com.mfsys.aconnect.security.dto.ChangePasswordDTO;
import com.mfsys.aconnect.security.dto.LoginRequest;
import com.mfsys.aconnect.security.dto.LoginResponse;
import com.mfsys.aconnect.security.dto.ResetPasswordDTO;
import com.mfsys.aconnect.security.service.AuthenticationService;
import com.mfsys.aconnect.usermanagement.constant.UserManagementURI;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs;
import com.mfsys.aconnect.usermanagement.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping(SecurityURI.AUTHENTICATION)
public class AuthenticationController {
private final AuthenticationService authenticationService;
private final UserService userService;
@Autowired
public AuthenticationController(AuthenticationService authenticationService, UserService userService) {
this.authenticationService = authenticationService;
this.userService = userService;
}
@PostMapping(SecurityURI.LOGIN)
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
LoginResponse response = authenticationService.login(loginRequest);
return ResponseEntity.ok(response);
}
@PostMapping(SecurityURI.REGISTER)
public ResponseEntity<UserDTOs.UserResponse> signupUser(@RequestBody UserDTOs.UserRequest request) {
UserDTOs.UserResponse response = userService.createUser(request);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
@PostMapping(SecurityURI.CHANGE_PASSWORD)
public ResponseEntity<Map<String, String>> changePassword(@RequestBody ChangePasswordDTO request) {
String message = userService.changePassword(request);
Map<String, String> response = new HashMap<>();
response.put("message", message);
return new ResponseEntity<>(response, HttpStatus.OK);
}
@PostMapping(SecurityURI.FIRST_LOGIN)
public ResponseEntity<Map<String, String>> firstLogin(@RequestBody ChangePasswordDTO request) {
String message = userService.firstLogin(request);
Map<String, String> response = new HashMap<>();
response.put("message", message);
return new ResponseEntity<>(response, HttpStatus.OK);
}
@PostMapping(SecurityURI.RESET_PASSWORD)
public ResponseEntity<Map<String, String>> resetPassword(@RequestBody ResetPasswordDTO request) {
String message = userService.resetPassword(request);
Map<String, String> response = new HashMap<>();
response.put("message", message);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}

@ -0,0 +1,11 @@
package com.mfsys.aconnect.security.dto;
import lombok.Data;
@Data
public class ChangePasswordDTO {
private String userId;
private String porOrgacode;
private String oldPassword;
private String newPassword;
}

@ -0,0 +1,13 @@
package com.mfsys.aconnect.security.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginRequest {
private String userId;
private String password;
}

@ -0,0 +1,16 @@
package com.mfsys.aconnect.security.dto;
import com.mfsys.aconnect.usermanagement.model.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginResponse {
private User user;
private boolean requiresOtp;
private boolean requiresPasswordChange;
private String token;
}

@ -0,0 +1,10 @@
package com.mfsys.aconnect.security.dto;
import lombok.Data;
@Data
public class ResetPasswordDTO {
private String userId;
private String porOrgacode;
private String newPassword;
}

@ -0,0 +1,11 @@
package com.mfsys.aconnect.security.exception;
import com.mfsys.common.configuration.exception.ApplicationException;
import com.mfsys.common.configuration.exception.ErrorMessage;
public class AuthenticationException extends ApplicationException {
public AuthenticationException(String context, ErrorMessage errorMessage) {
super(context, errorMessage);
}
}

@ -0,0 +1,48 @@
package com.mfsys.aconnect.security.model;
import com.mfsys.aconnect.usermanagement.model.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import java.time.LocalDateTime;
@Entity(name = "OTP_TOKENS")
@Table(name = "OTP_TOKENS")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OtpToken {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(nullable = false, length = 10)
private String token;
@Enumerated(EnumType.STRING)
@Column(name = "token_type", nullable = false)
private TokenType tokenType;
@Column(name = "is_used")
private Boolean isUsed = false;
@Column(name = "expires_at", nullable = false)
private LocalDateTime expiresAt;
@CreatedDate
@Column(name = "created_at")
private LocalDateTime createdAt;
public enum TokenType {
LOGIN,
PASSWORD_RESET,
EMAIL_VERIFICATION
}
}

@ -0,0 +1,46 @@
package com.mfsys.aconnect.security.service;
import com.mfsys.aconnect.security.exception.AuthenticationException;
import com.mfsys.common.configuration.constant.ERRCode;
import com.mfsys.common.configuration.service.JwtService;
import com.mfsys.common.configuration.service.PasswordEncryptionService;
import com.mfsys.aconnect.security.dto.LoginRequest;
import com.mfsys.aconnect.security.dto.LoginResponse;
import com.mfsys.aconnect.usermanagement.model.User;
import com.mfsys.aconnect.usermanagement.repository.UserRepository;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AuthenticationService {
private final UserRepository userRepository;
private final JwtService jwtService;
@Autowired
public AuthenticationService (UserRepository userRepository, PasswordEncryptionService passwordEncryptionService,
JwtService jwtService) {
this.userRepository = userRepository;
this.jwtService = jwtService;
}
@Transactional
public LoginResponse login(LoginRequest loginRequest) {
// Find user by email
User user = userRepository.findByUserIdAndIsActiveTrue(loginRequest.getUserId())
.orElseThrow(() ->
new AuthenticationException("Authentication", ERRCode.INVALID_CREDENTIALS)
);
// Verify password
if (!PasswordEncryptionService.verifyPassword(loginRequest.getPassword(), user.getPassword())) {
throw new AuthenticationException("Authentication", ERRCode.INVALID_CREDENTIALS);
}
String token = jwtService.generateToken(loginRequest.getUserId());
return new LoginResponse(user, false, user.isFirstLogin(), token);
}
}

@ -0,0 +1,7 @@
package com.mfsys.aconnect.security.service;
import org.springframework.stereotype.Service;
@Service
public class OtpService {
}

@ -0,0 +1,21 @@
package com.mfsys.aconnect.usermanagement.constant;
public interface UserManagementURI {
String USER = "/user";
String GET_USER = "/getUser";
String CREATE_USER = "/createUser";
String UPDATE_USER = "/updateUser";
String DELETE_USER = "/deleteUser";
String GET_ALL_USERS = "/getAllUsers";
String GET_USER_PERMISSIONS = "/getPermissions";
String SAVE_USER_PERMISSIONS = "/savePermissions";
String UPDATE_USER_PERMISSIONS = "/updatePermissions";
String USER_SUBSCRIPTION = "/userSubscription";
String GET_USER_SUBSCRIPTION = "/getUserSubscription";
String CREATE_USER_SUBSCRIPTION = "/createUserSubscription";
String UPDATE_USER_SUBSCRIPTION = "/updateUserSubscription";
String DELETE_USER_SUBSCRIPTION = "/deleteUserSubscription";
String GET_ALL_USER_SUBSCRIPTIONS = "/getAllUserSubscriptions";
}

@ -0,0 +1,41 @@
package com.mfsys.aconnect.usermanagement.controller;
import com.mfsys.aconnect.usermanagement.constant.UserManagementURI;
import com.mfsys.aconnect.usermanagement.dto.PermissionDTO;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs;
import com.mfsys.aconnect.usermanagement.service.PermissionService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(UserManagementURI.USER)
public class PermissionController {
private final PermissionService permissionService;
public PermissionController(PermissionService permissionService) {
this.permissionService = permissionService;
}
@PostMapping(UserManagementURI.SAVE_USER_PERMISSIONS)
public ResponseEntity<UserDTOs.UserResponse> saveUserPermissions(
@RequestBody PermissionDTO permissionDTO) {
UserDTOs.UserResponse response = permissionService.saveUserPermissions(permissionDTO);
return new ResponseEntity<>(response, HttpStatus.OK);
}
@GetMapping(UserManagementURI.GET_USER_PERMISSIONS)
public ResponseEntity<PermissionDTO> getUserPermissions(@RequestParam String userId) {
PermissionDTO dto = permissionService.getUserPermissions(userId);
return new ResponseEntity<>(dto, HttpStatus.OK);
}
@PutMapping(UserManagementURI.UPDATE_USER_PERMISSIONS)
public ResponseEntity<UserDTOs.UserResponse> updateUserPermissions(
@RequestBody PermissionDTO permissionDTO) {
UserDTOs.UserResponse response = permissionService.updateUserPermissions(permissionDTO);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}

@ -0,0 +1,66 @@
package com.mfsys.aconnect.usermanagement.controller;
import com.mfsys.aconnect.usermanagement.constant.UserManagementURI;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs;
import com.mfsys.aconnect.usermanagement.service.UserService;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(UserManagementURI.USER)
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping(UserManagementURI.CREATE_USER)
public ResponseEntity<UserDTOs.UserResponse> createUser(@RequestBody UserDTOs.UserRequest request) {
UserDTOs.UserResponse response = userService.createUser(request);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
@GetMapping(UserManagementURI.GET_ALL_USERS)
public ResponseEntity<List<UserDTOs.UserResponse>> getAllUsers() {
List<UserDTOs.UserResponse> users = userService.getAllUsers();
return new ResponseEntity<>(users, HttpStatus.OK);
}
@GetMapping(UserManagementURI.GET_USER)
public ResponseEntity<UserDTOs.UserResponse> getUserById(@RequestParam String userId) {
try {
UserDTOs.UserResponse user = userService.getUserById(userId);
return new ResponseEntity<>(user, HttpStatus.OK);
} catch (EntityNotFoundException ex) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PutMapping(UserManagementURI.UPDATE_USER)
public ResponseEntity<UserDTOs.UserResponse> updateUser(@RequestParam String userId, @RequestBody UserDTOs.UserRequest request) {
try {
UserDTOs.UserResponse response = userService.updateUser(userId, request);
return new ResponseEntity<>(response, HttpStatus.OK);
} catch (EntityNotFoundException ex) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@DeleteMapping(UserManagementURI.DELETE_USER)
public ResponseEntity<Void> deleteUser(@RequestParam String userId) {
try {
userService.deleteUser(userId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (EntityNotFoundException ex) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
}

@ -0,0 +1,62 @@
package com.mfsys.aconnect.usermanagement.controller;
import com.mfsys.aconnect.usermanagement.constant.UserManagementURI;
import com.mfsys.aconnect.usermanagement.dto.UserSubscriptionDTOs.UserSubscriptionRequest;
import com.mfsys.aconnect.usermanagement.dto.UserSubscriptionDTOs.UserSubscriptionResponse;
import com.mfsys.aconnect.usermanagement.service.UserSubscriptionService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(UserManagementURI.USER_SUBSCRIPTION)
public class UserSubscriptionController {
private final UserSubscriptionService userSubscriptionService;
@Autowired
public UserSubscriptionController(UserSubscriptionService userSubscriptionService) {
this.userSubscriptionService = userSubscriptionService;
}
@PostMapping(UserManagementURI.CREATE_USER_SUBSCRIPTION)
public ResponseEntity<UserSubscriptionResponse> createSubscription(
@RequestParam String userId,
@Valid @RequestBody UserSubscriptionRequest request) {
UserSubscriptionResponse createdSubscription = userSubscriptionService.createSubscription(userId, request);
return new ResponseEntity<>(createdSubscription, HttpStatus.CREATED);
}
@GetMapping(UserManagementURI.GET_ALL_USER_SUBSCRIPTIONS)
public ResponseEntity<List<UserSubscriptionResponse>> getSubscriptionsByUserId(@RequestParam String userId) {
List<UserSubscriptionResponse> subscriptions = userSubscriptionService.getSubscriptionsByUserId(userId);
return ResponseEntity.ok(subscriptions);
}
@GetMapping(UserManagementURI.GET_USER_SUBSCRIPTION)
public ResponseEntity<UserSubscriptionResponse> getSubscriptionById(
@RequestParam Long subscriptionId) {
return userSubscriptionService.getSubscriptionById(subscriptionId)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PutMapping(UserManagementURI.UPDATE_USER_SUBSCRIPTION)
public ResponseEntity<UserSubscriptionResponse> updateSubscription(
@RequestParam Long subscriptionId,
@Valid @RequestBody UserSubscriptionRequest request) {
UserSubscriptionResponse updatedSubscription = userSubscriptionService.updateSubscription(subscriptionId, request);
return ResponseEntity.ok(updatedSubscription);
}
@DeleteMapping(UserManagementURI.DELETE_USER_SUBSCRIPTION)
public ResponseEntity<Void> deleteSubscription(
@RequestParam Long subscriptionId) {
userSubscriptionService.deleteSubscription(subscriptionId);
return ResponseEntity.noContent().build();
}
}

@ -0,0 +1,10 @@
package com.mfsys.aconnect.usermanagement.dto;
import lombok.Data;
import java.util.List;
@Data
public class PermissionDTO {
private String permissions;
private String userId;
}

@ -0,0 +1,39 @@
package com.mfsys.aconnect.usermanagement.dto;
import com.mfsys.aconnect.usermanagement.model.Role;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* DTOs (Data Transfer Objects) for User.
* This separates the API contract from the internal entity model for security and flexibility.
*/
public class UserDTOs {
@Data
@NoArgsConstructor
public static class UserRequest {
private String userId;
private String porOrgacode;
private String userFullname;
private String password;
private String email;
private Role role;
}
@Data
@NoArgsConstructor
public static class UserResponse {
private String userId;
private String porOrgacode;
private String userFullname;
private String email;
private Role role;
private Boolean isFirstLogin;
private Boolean isActive;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
}

@ -0,0 +1,51 @@
package com.mfsys.aconnect.usermanagement.dto;
import com.mfsys.aconnect.usermanagement.model.UserSubscription;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
public class UserSubscriptionDTOs {
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class UserSubscriptionRequest {
@NotBlank(message = "Endpoint path is required")
private String endpointPath;
private String description;
@NotNull(message = "isActive status is required")
private Boolean isActive;
@NotNull(message = "Max requests per minute is required")
private Integer maxRequestsPerMinute;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class UserSubscriptionResponse {
private Long id;
private String userId;
private String endpointPath;
private String description;
private Boolean isActive;
private Integer maxRequestsPerMinute;
private LocalDateTime createdAt;
public static UserSubscriptionResponse fromEntity(UserSubscription userSubscription) {
return new UserSubscriptionResponse(
userSubscription.getId(),
userSubscription.getUserId(),
userSubscription.getEndpointPath(),
userSubscription.getDescription(),
userSubscription.getIsActive(),
userSubscription.getMaxRequestsPerMinute(),
userSubscription.getCreatedAt()
);
}
}
}

@ -0,0 +1,11 @@
package com.mfsys.aconnect.usermanagement.exceptions;
import com.mfsys.common.configuration.constant.ERRCode;
import com.mfsys.common.configuration.exception.ApplicationException;
public class EmailAlreadyExistException extends ApplicationException {
public EmailAlreadyExistException(String porOrgacode) {
super(porOrgacode, ERRCode.EMAIL_ALREADY_EXIST);
}
}

@ -0,0 +1,12 @@
package com.mfsys.aconnect.usermanagement.exceptions;
import com.mfsys.common.configuration.constant.ERRCode;
import com.mfsys.common.configuration.exception.ResourceNotFoundException;
public class OldPasswordNotMatch extends ResourceNotFoundException {
public OldPasswordNotMatch(String porOrgacode) {
super(porOrgacode, ERRCode.PASSWORD_ALREADY_EXIST);
}
}

@ -0,0 +1,10 @@
package com.mfsys.aconnect.usermanagement.exceptions;
import com.mfsys.common.configuration.constant.ERRCode;
import com.mfsys.common.configuration.exception.ApplicationException;
public class UsernameAlreadyExistException extends ApplicationException {
public UsernameAlreadyExistException(String porOrgacode) {
super(porOrgacode, ERRCode.USERNAME_ALREADY_EXIST);
}
}

@ -0,0 +1,64 @@
//package com.mfsys.aconnect.usermanagement.filter;
//
//import com.mfsys.common.configuration.constant.FilterPriority;
//import com.mfsys.common.configuration.constant.TokenBypassURI;
//import com.mfsys.aconnect.configuration.service.RequestRateLimiterService;
//import com.mfsys.aconnect.usermanagement.model.Role;
//import com.mfsys.aconnect.usermanagement.model.User;
//import com.mfsys.aconnect.usermanagement.model.UserSubscription;
//import com.mfsys.aconnect.usermanagement.service.UserService;
//import com.mfsys.aconnect.usermanagement.service.UserSubscriptionService;
//import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.core.annotation.Order;
//import org.springframework.stereotype.Component;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import java.io.IOException;
//
//@Component
//@Order(FilterPriority.SUBSCRIPTION)
//public class SubscriptionFilter extends OncePerRequestFilter {
//
// private final UserService userService;
// private final UserSubscriptionService userSubscriptionService;
// private final RequestRateLimiterService requestRateLimiterService;
//
// @Autowired
// public SubscriptionFilter(UserService userService, UserSubscriptionService userSubscriptionService,
// RequestRateLimiterService requestRateLimiterService) {
// this.userService = userService;
// this.userSubscriptionService = userSubscriptionService;
// this.requestRateLimiterService = requestRateLimiterService;
// }
//
// @Override
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
// throws ServletException, IOException {
// if (!(request.getMethod().equals("OPTIONS"))) {
//
// System.out.println(">> " + request.getRequestURI() + " <<");
// System.out.println(request.getHeaderNames());
// if (!(TokenBypassURI.URIs.contains(request.getRequestURI()) || request.getRequestURI().startsWith("/MCONNECT/actuator"))) {
// String userId = request.getHeader("userId");
// User user = userService.findActiveUserById(userId)
// .orElseThrow(() -> new RuntimeException("Invalid credentials"));
// if(user.getRole().equals(Role.USER)){
// UserSubscription userSubscription = userSubscriptionService.findByUserIdAndEndpointPath(userId, request.getRequestURI())
// .orElseThrow(() -> new RuntimeException("No Active Subscription"));
//
// int maxRequests = userSubscription.getMaxRequestsPerMinute();
//
// if (!requestRateLimiterService.isRequestAllowed(userId, request.getRequestURI(), maxRequests)) {
// throw new RuntimeException("Too many requests");
// }
// }
// }
//
// filterChain.doFilter(request, response);
// }
// }
//}

@ -0,0 +1,5 @@
package com.mfsys.aconnect.usermanagement.model;
public enum Role {
USER, ADMIN
}

@ -0,0 +1,64 @@
package com.mfsys.aconnect.usermanagement.model;
import com.mfsys.common.configuration.constant.FieldNameLength;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
@Entity(name = "users")
@Table(name = "users")
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@Column(name = "user_id", unique = true, nullable = false)
private String userId;
@Column(name = "POR_ORGACODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.POR_ORGACODE)
private String porOrgacode;
@Column(name = "user_fullname", nullable = false)
private String userFullname;
@Column(name = "password", nullable = false)
private String password;
@Column(name = "email", nullable = false, unique = true)
private String email;
@Enumerated(EnumType.STRING)
@Column(name = "role", nullable = false)
private Role role = Role.USER;
@Column(name = "permissions", columnDefinition = "TEXT")
private String permissions;
@Column(name = "is_first_login", columnDefinition = FieldNameLength.BOOLEAN_BIT)
private boolean isFirstLogin = true;
@Column(name = "is_active", columnDefinition = FieldNameLength.BOOLEAN_BIT)
private boolean isActive = true;
@Column(name = "is_deleted", columnDefinition = FieldNameLength.BOOLEAN_BIT)
private boolean isDeleted = false;
@CreationTimestamp
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserSubscription> userSubscriptions = new HashSet<>();
}

@ -0,0 +1,46 @@
package com.mfsys.aconnect.usermanagement.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Entity(name = "user_subscriptions")
@Table(name = "user_subscriptions")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserSubscription {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "endpoint_path", nullable = false, unique = true)
private String endpointPath;
@Column(columnDefinition = "TEXT")
private String description;
@Column(name = "is_active")
private Boolean isActive = true;
@Column(name = "max_requests_per_minute")
private Integer maxRequestsPerMinute = 60;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "user_id", nullable = false, updatable = false)
private String userId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
private User user;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
}
}

@ -0,0 +1,7 @@
package com.mfsys.aconnect.usermanagement.repository;
import com.mfsys.aconnect.usermanagement.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PermissionRepository extends JpaRepository<User, String> {
}

@ -0,0 +1,17 @@
package com.mfsys.aconnect.usermanagement.repository;
import com.mfsys.aconnect.usermanagement.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, String> {
Optional<User> findByUserIdAndIsActiveTrue(String userId);
boolean existsByUserId(String userId);
boolean existsByEmail(String email);
List<User> findByIsDeletedFalse();
Optional<User> findByUserIdAndIsDeletedFalse(String userId);
}

@ -0,0 +1,14 @@
package com.mfsys.aconnect.usermanagement.repository;
import com.mfsys.aconnect.usermanagement.model.UserSubscription;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserSubscriptionRepository extends JpaRepository<UserSubscription, Long> {
Optional<UserSubscription> findByUserIdAndEndpointPathAndIsActiveTrue(String userId, String endpointPath);
List<UserSubscription> findByUserId(String userId);
}

@ -0,0 +1,70 @@
package com.mfsys.aconnect.usermanagement.service;
import com.mfsys.aconnect.usermanagement.dto.PermissionDTO;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs;
import com.mfsys.aconnect.usermanagement.model.User;
import com.mfsys.aconnect.usermanagement.repository.PermissionRepository;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PermissionService {
private final PermissionRepository permissionRepository;
public PermissionService(PermissionRepository permissionRepository) {
this.permissionRepository = permissionRepository;
}
@Transactional
public UserDTOs.UserResponse saveUserPermissions(PermissionDTO permissionDTO) {
User user = permissionRepository.findById(permissionDTO.getUserId())
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + permissionDTO.getUserId()));
String permissions = String.join(",", permissionDTO.getPermissions());
user.setPermissions(permissions);
User updatedUser = permissionRepository.save(user);
return mapToResponseDTO(updatedUser);
}
public PermissionDTO getUserPermissions(String userId) {
User user = permissionRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + userId));
PermissionDTO dto = new PermissionDTO();
dto.setUserId(userId);
if (user.getPermissions() != null && !user.getPermissions().isEmpty()) {
dto.setPermissions((user.getPermissions()));
}
return dto;
}
@Transactional
public UserDTOs.UserResponse updateUserPermissions(PermissionDTO permissionDTO) {
User user = permissionRepository.findById(permissionDTO.getUserId())
.orElseThrow(() ->
new EntityNotFoundException("User not found with ID: " + permissionDTO.getUserId())
);
String permissions = String.join(",", permissionDTO.getPermissions());
user.setPermissions(permissions);
User updatedUser = permissionRepository.save(user);
return mapToResponseDTO(updatedUser);
}
private UserDTOs.UserResponse mapToResponseDTO(User user) {
UserDTOs.UserResponse response = new UserDTOs.UserResponse();
response.setUserId(user.getUserId());
response.setUserFullname(user.getUserFullname());
response.setEmail(user.getEmail());
response.setRole(user.getRole());
response.setIsFirstLogin(user.isFirstLogin());
response.setIsActive(user.isActive());
response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt());
return response;
}
}

@ -0,0 +1,136 @@
package com.mfsys.aconnect.usermanagement.service;
import com.mfsys.aconnect.security.dto.ChangePasswordDTO;
import com.mfsys.aconnect.security.dto.ResetPasswordDTO;
import com.mfsys.aconnect.usermanagement.exceptions.EmailAlreadyExistException;
import com.mfsys.aconnect.usermanagement.exceptions.OldPasswordNotMatch;
import com.mfsys.aconnect.usermanagement.exceptions.UsernameAlreadyExistException;
import com.mfsys.aconnect.usermanagement.model.Role;
import com.mfsys.common.configuration.service.PasswordEncryptionService;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs;
import com.mfsys.aconnect.usermanagement.model.User;
import com.mfsys.aconnect.usermanagement.repository.UserRepository;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncryptionService passwordEncryptionService;
public UserService(UserRepository userRepository, PasswordEncryptionService passwordEncryptionService) {
this.userRepository = userRepository;
this.passwordEncryptionService = passwordEncryptionService;
}
@Transactional
public UserDTOs.UserResponse createUser(UserDTOs.UserRequest request) {
if (userRepository.existsByUserId(request.getUserId())) {
throw new UsernameAlreadyExistException(request.getPorOrgacode());
}
if (userRepository.existsByEmail(request.getEmail())) {
throw new EmailAlreadyExistException(request.getPorOrgacode());
}
User user = new User();
user.setUserId(request.getUserId());
user.setPorOrgacode(request.getPorOrgacode());
user.setUserFullname(request.getUserFullname());
user.setEmail(request.getEmail());
user.setRole(request.getRole());
user.setPassword(passwordEncryptionService.hashPassword(request.getPassword()));
User savedUser = userRepository.save(user);
return mapToResponseDTO(savedUser);
}
@Transactional
public String changePassword(ChangePasswordDTO request) {
User user = userRepository.findById(request.getUserId())
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + request.getUserId()));
boolean isPasswordValid = PasswordEncryptionService.verifyPassword(request.getOldPassword(), user.getPassword());
if(!isPasswordValid) {
throw new OldPasswordNotMatch(request.getPorOrgacode());
}
user.setPassword(passwordEncryptionService.hashPassword(request.getNewPassword()));
userRepository.save(user);
return "Password changed successfully";
}
@Transactional
public String firstLogin(ChangePasswordDTO request) {
User user = userRepository.findById(request.getUserId())
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + request.getUserId()));
boolean isPasswordValid = PasswordEncryptionService.verifyPassword(request.getOldPassword(), user.getPassword());
if(!isPasswordValid) {
throw new OldPasswordNotMatch(request.getPorOrgacode());
}
user.setPassword(passwordEncryptionService.hashPassword(request.getNewPassword()));
user.setFirstLogin(false);
userRepository.save(user);
return "Password changed successfully";
}
@Transactional
public String resetPassword(ResetPasswordDTO request) {
User user = userRepository.findById(request.getUserId())
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + request.getUserId()));
user.setPassword(passwordEncryptionService.hashPassword(request.getNewPassword()));
userRepository.save(user);
return "Password changed successfully";
}
public List<UserDTOs.UserResponse> getAllUsers() {
return userRepository.findAll().stream()
.filter(user -> user.getRole() != Role.ADMIN)
.map(this::mapToResponseDTO)
.collect(Collectors.toList());
}
public UserDTOs.UserResponse getUserById(String userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + userId));
return mapToResponseDTO(user);
}
@Transactional
public UserDTOs.UserResponse updateUser(String userId, UserDTOs.UserRequest request) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + userId));
user.setUserFullname(request.getUserFullname());
user.setEmail(request.getEmail());
user.setRole(request.getRole());
user.setPassword(passwordEncryptionService.hashPassword(request.getPassword()));
User updatedUser = userRepository.save(user);
return mapToResponseDTO(updatedUser);
}
@Transactional
public void deleteUser(String userId) {
User user = userRepository.findById(userId).orElseThrow();
user.setDeleted(true);
user.setActive(false);
userRepository.save(user);
}
private UserDTOs.UserResponse mapToResponseDTO(User user) {
UserDTOs.UserResponse response = new UserDTOs.UserResponse();
response.setUserId(user.getUserId());
response.setUserFullname(user.getUserFullname());
response.setEmail(user.getEmail());
response.setRole(user.getRole());
response.setIsFirstLogin(user.isFirstLogin());
response.setIsActive(user.isActive());
response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt());
return response;
}
}

@ -0,0 +1,84 @@
package com.mfsys.aconnect.usermanagement.service;
import com.mfsys.aconnect.usermanagement.dto.UserSubscriptionDTOs.UserSubscriptionRequest;
import com.mfsys.aconnect.usermanagement.model.User;
import com.mfsys.aconnect.usermanagement.model.UserSubscription;
import com.mfsys.aconnect.usermanagement.repository.UserRepository;
import com.mfsys.aconnect.usermanagement.repository.UserSubscriptionRepository;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import com.mfsys.aconnect.usermanagement.dto.UserSubscriptionDTOs.UserSubscriptionResponse;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserSubscriptionService {
private final UserSubscriptionRepository userSubscriptionRepository;
private final UserRepository userRepository;
@Autowired
public UserSubscriptionService(UserSubscriptionRepository userSubscriptionRepository, UserRepository userRepository) {
this.userSubscriptionRepository = userSubscriptionRepository;
this.userRepository = userRepository;
}
@Transactional
public UserSubscriptionResponse createSubscription(String userId, UserSubscriptionRequest request) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found with id: " + userId));
UserSubscription userSubscription = new UserSubscription();
userSubscription.setUserId(userId);
userSubscription.setEndpointPath(request.getEndpointPath());
userSubscription.setDescription(request.getDescription());
userSubscription.setIsActive(request.getIsActive());
userSubscription.setMaxRequestsPerMinute(request.getMaxRequestsPerMinute());
userSubscription.setUser(user);
UserSubscription savedSubscription = userSubscriptionRepository.save(userSubscription);
return UserSubscriptionResponse.fromEntity(savedSubscription);
}
public List<UserSubscriptionResponse> getSubscriptionsByUserId(String userId) {
return userSubscriptionRepository.findByUserId(userId)
.stream()
.map(UserSubscriptionResponse::fromEntity)
.collect(Collectors.toList());
}
public Optional<UserSubscriptionResponse> getSubscriptionById(Long subscriptionId) {
return userSubscriptionRepository.findById(subscriptionId)
.map(UserSubscriptionResponse::fromEntity);
}
@Transactional
public UserSubscriptionResponse updateSubscription(Long subscriptionId, UserSubscriptionRequest request) {
UserSubscription existingSubscription = userSubscriptionRepository.findById(subscriptionId)
.orElseThrow(() -> new EntityNotFoundException("User subscription not found with id: " + subscriptionId));
existingSubscription.setEndpointPath(request.getEndpointPath());
existingSubscription.setDescription(request.getDescription());
existingSubscription.setIsActive(request.getIsActive());
existingSubscription.setMaxRequestsPerMinute(request.getMaxRequestsPerMinute());
UserSubscription updatedSubscription = userSubscriptionRepository.save(existingSubscription);
return UserSubscriptionResponse.fromEntity(updatedSubscription);
}
@Transactional
public void deleteSubscription(Long subscriptionId) {
if (!userSubscriptionRepository.existsById(subscriptionId)) {
throw new EntityNotFoundException("User subscription not found with id: " + subscriptionId);
}
userSubscriptionRepository.deleteById(subscriptionId);
}
public Optional<UserSubscription> findByUserIdAndEndpointPath(String userId, String endpointPath) {
return userSubscriptionRepository.findByUserIdAndEndpointPathAndIsActiveTrue(userId, endpointPath);
}
}

@ -0,0 +1,37 @@
package com.mfsys.aconnect.validation.controller;
import com.mfsys.aconnect.validation.service.ValidationService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ValidationController {
private final ValidationService validationService;
public ValidationController(ValidationService validationService) {
this.validationService = validationService;
}
@GetMapping("/validate-primary")
public boolean validatePrimaryIdenNo(
@RequestHeader("Authorization") String token,
@RequestHeader("SUS_USERCODE") String userCode,
@RequestHeader("POR_ORGACODE") String porOrgacode,
@RequestParam String primaryIdenNo) {
return validationService.validatePrimaryIdenNo(porOrgacode, primaryIdenNo, userCode, token);
}
@GetMapping("/validate-customer")
public boolean validateCustomerNo(
@RequestHeader("Authorization") String token,
@RequestHeader("SUS_USERCODE") String userCode,
@RequestHeader("POR_ORGACODE") String porOrgacode,
@RequestParam String cmpCustcode) {
return validationService.validateCustomerNo(porOrgacode, cmpCustcode, userCode, token);
}
}

@ -0,0 +1,52 @@
package com.mfsys.aconnect.validation.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import static com.mfsys.common.configuration.constant.AconnectURI.DEPOSIT;
@Service
public class ValidationService {
@Value("${app.deposit.uri}")
private String depositURI;
private final RestTemplate restTemplate;
public ValidationService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public boolean validatePrimaryIdenNo(String porOrgacode, String primaryIdenNo, String userCode, String tokenHeader) {
String url = depositURI + DEPOSIT + "/validate-cnicno" + "?porOrgacode=" + porOrgacode + "&pitIdenvalue=" + primaryIdenNo;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", userCode);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<Void> entity = new HttpEntity<>(headers);
ResponseEntity<Boolean> response = restTemplate.exchange(url, HttpMethod.GET,entity,Boolean.class);
Boolean result = response.getBody();
return result != null && result;
}
public boolean validateCustomerNo(String porOrgacode, String cmpCustcode, String userCode, String tokenHeader) {
String url = depositURI + DEPOSIT + "/validate-customerno" + "?porOrgacode=" + porOrgacode + "&cmpCustcode=" + cmpCustcode;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", tokenHeader);
headers.set("POR_ORGACODE", porOrgacode);
headers.set("SUS_USERCODE", userCode);
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<Void> entity = new HttpEntity<>(headers);
ResponseEntity<Boolean> response = restTemplate.exchange(url, HttpMethod.GET,entity,Boolean.class);
Boolean result = response.getBody();
return result != null && result;
}
}

@ -0,0 +1,8 @@
app.security.uri=http://localhost:9090/security/auth/user
app.deposit.uri=http://localhost:9095
app.generalledger.uri=http://localhost:9093
app.onlinebanking.uri=http://localhost:9099
app.crm.uri=http://localhost:9096
app.loan.uri=http://localhost:9094
app.organization.uri=0005

@ -0,0 +1,8 @@
app.deposit.uri=${CIIHIVE_API_BASE_URL}
app.generalledger.uri=${CIIHIVE_API_BASE_URL}
app.organization.uri=${CMB_ORGA_CODE}
app.security.uri=${CIIHIVE_API_BASE_URL}/security/auth/user
app.crm.uri=${CIIHIVE_API_BASE_URL}
app.loan.uri=${CIIHIVE_API_BASE_URL}

@ -0,0 +1,7 @@
app.deposit.uri=${CIIHIVE_API_BASE_URL}
app.generalledger.uri=${CIIHIVE_API_BASE_URL}
app.organization.uri=${CMB_ORGA_CODE}
app.security.uri=${CIIHIVE_API_BASE_URL}/security/auth/user
app.crm.uri=${CIIHIVE_API_BASE_URL}
app.loan.uri=${CIIHIVE_API_BASE_URL}

@ -0,0 +1,7 @@
app.deposit.uri=${CIIHIVE_API_BASE_URL}
app.generalledger.uri=${CIIHIVE_API_BASE_URL}
app.organization.uri=${CMB_ORGA_CODE}
app.security.uri=${CIIHIVE_API_BASE_URL}/security/auth/user
app.crm.uri=${CIIHIVE_API_BASE_URL}
app.loan.uri=${CIIHIVE_API_BASE_URL}

@ -0,0 +1,23 @@
spring.application.name = aconnect
app.base.uri=aconnect
app.db.dbname = aconnect
app.db.dbuser=${CMB_SQL_DB_USER}
app.db.dbpassword=${CMB_SQL_DB_PASSWORD}
app.db.url=${CMB_SQL_DB_MACHINE_IP}
app.server.timezone=${APP_SERVER_TIMEZONE}
spring.datasource.username = ${app.db.dbuser}
spring.datasource.password = ${app.db.dbpassword}
spring.datasource.url = jdbc:mysql://${app.db.url}/${app.db.dbname}?createDatabaseIfNotExist=true&serverTimezone=${app.server.timezone}&useLegacyDatetimeCode=false&useUnicode=yes&characterEncoding=UTF-8&characterSetResults=UTF-8
spring.jpa.properties.hibernate.connection.characterEncoding=utf-8
spring.jpa.properties.hibernate.connection.CharSet=utf-8
spring.jpa.properties.hibernate.connection.useUnicode=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.profiles.active=@spring.profiles.active@
jwt.secret = D1kD4fP8wQ2zL6hM9sR3vX7yU0tJ5nB2cV8pG4qW6eY1iK3oA9uH7jN2mZ5xT9bS4rF0lP3dQ8wE1
jwt.expiration = 86400000
jwt.refresh-expiration= 604800000

@ -0,0 +1,13 @@
package com.mfsys.aconnect;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class AconnectApplicationTests {
@Test
void contextLoads() {
}
}

@ -0,0 +1,19 @@
# 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.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip

259
common/mvnw vendored

@ -0,0 +1,259 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

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

Loading…
Cancel
Save