Browse Source

Initial commit on 26 December, 2025

master
example 10 months ago
commit
ebedfd152f
  1. 4
      .env
  2. 2
      .gitattributes
  3. 42
      .gitignore
  4. 3
      .mvn/wrapper/maven-wrapper.properties
  5. 295
      mvnw
  6. 189
      mvnw.cmd
  7. 125
      pom.xml
  8. 32
      src/main/java/com/adjustment_file_management_system/springboot/AdjustmentFileManagementSystemApplication.java
  9. 16
      src/main/java/com/adjustment_file_management_system/springboot/configuration/ApplicationConfiguration.java
  10. 42
      src/main/java/com/adjustment_file_management_system/springboot/configuration/AuditorAwareConfiguration.java
  11. 44
      src/main/java/com/adjustment_file_management_system/springboot/configuration/CustomAuthenticationProvider.java
  12. 15
      src/main/java/com/adjustment_file_management_system/springboot/configuration/FileDataProperties.java
  13. 64
      src/main/java/com/adjustment_file_management_system/springboot/configuration/FileDataPropertiesConfiguration.java
  14. 100
      src/main/java/com/adjustment_file_management_system/springboot/configuration/LogFolderInitializer.java
  15. 18
      src/main/java/com/adjustment_file_management_system/springboot/configuration/LogReadyInitializer.java
  16. 90
      src/main/java/com/adjustment_file_management_system/springboot/configuration/SecurityConfiguration.java
  17. 82
      src/main/java/com/adjustment_file_management_system/springboot/controller/FileDataController.java
  18. 44
      src/main/java/com/adjustment_file_management_system/springboot/controller/HomeController.java
  19. 22
      src/main/java/com/adjustment_file_management_system/springboot/mapper/AdvanceTypeMapper.java
  20. 18
      src/main/java/com/adjustment_file_management_system/springboot/mapper/AppUserMapper.java
  21. 127
      src/main/java/com/adjustment_file_management_system/springboot/mapper/FileDataMapper.java
  22. 15
      src/main/java/com/adjustment_file_management_system/springboot/mapper/FundTypeMapper.java
  23. 13
      src/main/java/com/adjustment_file_management_system/springboot/mapper/UserRoleMapper.java
  24. 43
      src/main/java/com/adjustment_file_management_system/springboot/model/AdvanceType.java
  25. 52
      src/main/java/com/adjustment_file_management_system/springboot/model/AppUser.java
  26. 213
      src/main/java/com/adjustment_file_management_system/springboot/model/FileData.java
  27. 43
      src/main/java/com/adjustment_file_management_system/springboot/model/FundType.java
  28. 52
      src/main/java/com/adjustment_file_management_system/springboot/model/UserRole.java
  29. 18
      src/main/java/com/adjustment_file_management_system/springboot/repository/AdvanceTypeRepository.java
  30. 13
      src/main/java/com/adjustment_file_management_system/springboot/repository/AppUserRepository.java
  31. 15
      src/main/java/com/adjustment_file_management_system/springboot/repository/FileDataRepository.java
  32. 11
      src/main/java/com/adjustment_file_management_system/springboot/repository/FundTypeRepository.java
  33. 34
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/AddFileDataRequestDTO.java
  34. 18
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/AdvanceTypeRequestDTO.java
  35. 17
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/AppUserRequestDTO.java
  36. 44
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/FileDataRequestDTO.java
  37. 50
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/UpdateFileDataRequestDTO.java
  38. 19
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/AdvanceTypeResponseDTO.java
  39. 19
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/AppUserResponseDTO.java
  40. 46
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/FileDataResponseDTO.java
  41. 17
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/FundTypeResponseDTO.java
  42. 19
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/ServiceResponseDTO.java
  43. 17
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/UserRoleResponseDTO.java
  44. 93
      src/main/java/com/adjustment_file_management_system/springboot/rest_controller/FileDataRestController.java
  45. 78
      src/main/java/com/adjustment_file_management_system/springboot/rest_controller/HomeRestController.java
  46. 606
      src/main/java/com/adjustment_file_management_system/springboot/service/FileDataService.java
  47. 119
      src/main/java/com/adjustment_file_management_system/springboot/service/FolderService.java
  48. 64
      src/main/java/com/adjustment_file_management_system/springboot/service/HomeService.java
  49. 12
      src/main/resources/META-INF/additional-spring-configuration-metadata.json
  50. 48
      src/main/resources/application.properties
  51. 33
      src/main/resources/logback-spring.xml
  52. 11794
      src/main/resources/static/bootstrap-5.3.2/css/bootstrap.min.css
  53. 2212
      src/main/resources/static/bootstrap-5.3.2/js/bootstrap.min.js
  54. 192
      src/main/resources/static/css/body-form-styles.css
  55. 12
      src/main/resources/static/css/btn-secondary-styles.css
  56. 98
      src/main/resources/static/css/datatable-styles.css
  57. 77
      src/main/resources/static/css/header-styles.css
  58. 40
      src/main/resources/static/css/home-styles.css
  59. 272
      src/main/resources/static/css/login-form-styles.css
  60. 58
      src/main/resources/static/css/view-file-detail-styles.css
  61. 60
      src/main/resources/static/css/view-file-styles.css
  62. 532
      src/main/resources/static/datatables-1.13.6/css/dataTables.bootstrap5.min.css
  63. 80
      src/main/resources/static/datatables-1.13.6/js/dataTables.bootstrap5.min.js
  64. 2990
      src/main/resources/static/datatables-1.13.6/js/jquery.dataTables.min.js
  65. 248
      src/main/resources/static/datatables-buttons-2.4.1/css/buttons.bootstrap5.min.css
  66. 70
      src/main/resources/static/datatables-buttons-2.4.1/js/buttons.bootstrap5.min.js
  67. 538
      src/main/resources/static/datatables-buttons-2.4.1/js/buttons.html5.min.js
  68. 79
      src/main/resources/static/datatables-buttons-2.4.1/js/buttons.print.min.js
  69. 764
      src/main/resources/static/datatables-buttons-2.4.1/js/dataTables.buttons.min.js
  70. 793
      src/main/resources/static/flatpickr-4.6.13/css/flatpickr.min.css
  71. 1379
      src/main/resources/static/flatpickr-4.6.13/js/flatpickr.js
  72. 6995
      src/main/resources/static/font-awesome-6.5.1/css/all.min.css
  73. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-brands-400.ttf
  74. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-brands-400.woff2
  75. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-regular-400.ttf
  76. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-regular-400.woff2
  77. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-solid-900.ttf
  78. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-solid-900.woff2
  79. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-v4compatibility.ttf
  80. BIN
      src/main/resources/static/font-awesome-6.5.1/webfonts/fa-v4compatibility.woff2
  81. 7023
      src/main/resources/static/font-awesome-6.5.2/css/all.min.css
  82. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-brands-400.ttf
  83. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-brands-400.woff2
  84. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-regular-400.ttf
  85. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-regular-400.woff2
  86. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-solid-900.ttf
  87. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-solid-900.woff2
  88. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf
  89. BIN
      src/main/resources/static/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2
  90. BIN
      src/main/resources/static/header-images/gcc1.png
  91. 25996
      src/main/resources/static/html2pdf-0.9.3/js/html2pdf.bundle.min.js
  92. 3244
      src/main/resources/static/jquery-3.6.4/js/jquery-3.6.4.min.js
  93. 77
      src/main/resources/static/js/add-file-script.js
  94. 17
      src/main/resources/static/js/adjust-row-class-script.js
  95. 20
      src/main/resources/static/js/fetch-csrf-script.js
  96. 3
      src/main/resources/static/js/go-back-script.js
  97. 31
      src/main/resources/static/js/login-script.js
  98. 118
      src/main/resources/static/js/update-ejv-number-script.js
  99. 351
      src/main/resources/static/js/update-file-script.js
  100. 157
      src/main/resources/static/js/view-file-detail-script.js

4
.env

@ -0,0 +1,4 @@
DB_URL=jdbc:oracle:thin:@10.1.0.14:1521:chncorp
DB_USERNAME=fileadjust
DB_PASSWORD=fileadjust
FORCE_HTTPS=false

2
.gitattributes

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

42
.gitignore

@ -0,0 +1,42 @@
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/
### Logs ###
log/
logs/
*.log
### File Uploads ###
uploads/file-data/*
!uploads/file-data/.gitkeep

3
.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,3 @@
wrapperVersion=3.3.4
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
mvnw

@ -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.4
#
# 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
mvnw.cmd

@ -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.4
@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"

125
pom.xml

@ -0,0 +1,125 @@
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.adjustment-file-management-system</groupId>
<artifactId>adjustment-file-management-system</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>adjustment-file-management-system</name>
<description>Springboot Project For Adjustment File Management System</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>java-dotenv</artifactId>
<version>5.2.2</version>
</dependency>
</dependencies>
<build>
<finalName>adjustment-file-management-system</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

32
src/main/java/com/adjustment_file_management_system/springboot/AdjustmentFileManagementSystemApplication.java

@ -0,0 +1,32 @@
package com.adjustment_file_management_system.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import com.adjustment_file_management_system.springboot.configuration.LogFolderInitializer;
import com.adjustment_file_management_system.springboot.configuration.LogReadyInitializer;
import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvEntry;
@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class AdjustmentFileManagementSystemApplication {
static {
Dotenv dotEnv = Dotenv.configure().ignoreIfMissing().load();
for(DotenvEntry entry : dotEnv.entries()) {
System.setProperty(entry.getKey(), entry.getValue());
}
}
public static void main(String[] args) {
SpringApplication app = new SpringApplication(AdjustmentFileManagementSystemApplication.class);
// Register pre-logging and post-logging listeners
app.addListeners(new LogFolderInitializer()); // creates logs folder & initial file
app.addListeners(new LogReadyInitializer()); // logs a startup info message
app.run(args);
}
}

16
src/main/java/com/adjustment_file_management_system/springboot/configuration/ApplicationConfiguration.java

@ -0,0 +1,16 @@
package com.adjustment_file_management_system.springboot.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class ApplicationConfiguration {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}

42
src/main/java/com/adjustment_file_management_system/springboot/configuration/AuditorAwareConfiguration.java

@ -0,0 +1,42 @@
package com.adjustment_file_management_system.springboot.configuration;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.adjustment_file_management_system.springboot.model.AppUser;
import com.adjustment_file_management_system.springboot.repository.AppUserRepository;
@Component("auditorAware")
public class AuditorAwareConfiguration implements AuditorAware<AppUser> {
@Autowired
private AppUserRepository appUsrRepo;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
public Optional<AppUser> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty();
}
// If it's already AppUser, no need to hit DB
Object principal = authentication.getPrincipal();
if (principal instanceof AppUser user) {
return Optional.of(user);
}
// Fetch AppUser from DB using username
String username = authentication.getName();
return appUsrRepo.findByUsrName(username);
}
}

44
src/main/java/com/adjustment_file_management_system/springboot/configuration/CustomAuthenticationProvider.java

@ -0,0 +1,44 @@
package com.adjustment_file_management_system.springboot.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.service.HomeService;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private HomeService homeSer;
@Autowired
private PasswordEncoder passEncode;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails usrDets = homeSer.loadUserByUsername(username); // throws UsernameNotFoundException if not found
if (!passEncode.matches(password, usrDets.getPassword())) {
throw new BadCredentialsException("Invalid username or password");
}
return new UsernamePasswordAuthenticationToken(usrDets.getUsername(), usrDets.getPassword(),
usrDets.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}

15
src/main/java/com/adjustment_file_management_system/springboot/configuration/FileDataProperties.java

@ -0,0 +1,15 @@
package com.adjustment_file_management_system.springboot.configuration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "file.data")
public class FileDataProperties {
private String uploadDir;
}

64
src/main/java/com/adjustment_file_management_system/springboot/configuration/FileDataPropertiesConfiguration.java

@ -0,0 +1,64 @@
package com.adjustment_file_management_system.springboot.configuration;
import java.io.File;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
@Configuration
@Getter
public class FileDataPropertiesConfiguration implements WebMvcConfigurer {
@Autowired
private FileDataProperties fileDataProps;
private File uploadDirFile;
private static final Logger logger = LoggerFactory.getLogger(FileDataPropertiesConfiguration.class);
@PostConstruct
public void init() {
try {
File baseDir;
ApplicationHome home = new ApplicationHome(FileDataPropertiesConfiguration.class);
if (home.getSource() != null && home.getSource().isFile() && home.getSource().getName().endsWith(".jar")) {
// Running as a packaged JAR
baseDir = home.getDir();
} else {
// Running from IDE -> use project root instead of target/classes
baseDir = new File(System.getProperty("user.dir"));
}
// Create /images/product relative to baseDir
uploadDirFile = Paths.get(baseDir.getAbsolutePath(), fileDataProps.getUploadDir()).toFile();
if (!uploadDirFile.exists()) {
boolean created = uploadDirFile.mkdirs();
if (created) {
logger.info("Created upload directory at: {}", uploadDirFile.getAbsolutePath());
} else {
logger.error("Failed to create upload directory at: {}", uploadDirFile.getAbsolutePath());
}
}
} catch (Exception e) {
logger.error("Exception in ProductImagePropertiesConfiguration.init(): {}", e.getMessage(), e);
}
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String fullPath = uploadDirFile.toURI().toString();
registry.addResourceHandler("uploads/file-data/**").addResourceLocations(fullPath);
}
}

100
src/main/java/com/adjustment_file_management_system/springboot/configuration/LogFolderInitializer.java

@ -0,0 +1,100 @@
package com.adjustment_file_management_system.springboot.configuration;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.context.ApplicationListener;
import org.springframework.util.ClassUtils;
public class LogFolderInitializer implements ApplicationListener<ApplicationStartingEvent> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void onApplicationEvent(ApplicationStartingEvent event) {
File logFile = null;
try {
// Determine safe base folder
File baseDir = determineBaseFolder();
// Create logs folder
File logsDir = new File(baseDir, "logs");
if (!logsDir.exists() && !logsDir.mkdirs()) {
writeError(logsDir, "Failed to create logs folder at: " + logsDir.getAbsolutePath(), null);
}
// Create initial log file
logFile = new File(logsDir, "app-logs.txt");
if (!logFile.exists()) {
logFile.createNewFile();
}
// Log pre-start messages
writeInfo(logFile, "Created log file at: " + logFile.getAbsolutePath());
writeInfo(logFile, "LOG_ROOT set to: " + logsDir.getAbsolutePath());
// Set system property for logback-spring.xml
System.setProperty("LOG_ROOT", logsDir.getAbsolutePath());
} catch (IOException ioe) {
writeError(logFile, "Failed to create logs folder/file", ioe);
}
}
/** Determine a safe base folder for logs/uploads */
private File determineBaseFolder() {
try {
boolean devtoolsActive = ClassUtils.isPresent("org.springframework.boot.devtools.restart.RestartLauncher",
this.getClass().getClassLoader());
if (devtoolsActive) {
// IDE development: use user.dir (project root) to avoid DevTools restart loop
return new File(System.getProperty("user.dir"));
} else {
// JAR deployment: use folder containing the JAR
ApplicationHome home = new ApplicationHome(LogFolderInitializer.class);
return home.getDir();
}
} catch (Exception e) {
// Last resort: use temp directory
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
tmpDir.mkdirs();
return tmpDir;
}
}
private void writeInfo(File logFile, String message) {
String timestamp = LocalDateTime.now().format(formatter);
if (logFile != null) {
try (PrintWriter pw = new PrintWriter(new FileWriter(logFile, true))) {
pw.println(timestamp + " INFO " + message);
} catch (IOException e) {
System.err.println(timestamp + " ERROR Failed to write INFO to log file: " + e.getMessage());
}
}
System.out.println(timestamp + " INFO " + message);
}
private void writeError(File logFile, String message, Throwable t) {
String timestamp = LocalDateTime.now().format(formatter);
if (logFile != null) {
try (PrintWriter pw = new PrintWriter(new FileWriter(logFile, true))) {
pw.println(timestamp + " ERROR " + message);
if (t != null)
t.printStackTrace(pw);
} catch (IOException e) {
System.err.println(timestamp + " ERROR Failed to write ERROR to log file: " + e.getMessage());
}
}
System.err.println(timestamp + " ERROR " + message);
if (t != null)
t.printStackTrace(System.err);
}
}

18
src/main/java/com/adjustment_file_management_system/springboot/configuration/LogReadyInitializer.java

@ -0,0 +1,18 @@
package com.adjustment_file_management_system.springboot.configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
public class LogReadyInitializer implements ApplicationListener<ApplicationReadyEvent> {
private static final Logger logger = LoggerFactory.getLogger(LogReadyInitializer.class);
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// TODO Auto-generated method stub
logger.info("Log folder and initial log file are ready at: {}", System.getProperty("LOG_ROOT"));
}
}

90
src/main/java/com/adjustment_file_management_system/springboot/configuration/SecurityConfiguration.java

@ -0,0 +1,90 @@
package com.adjustment_file_management_system.springboot.configuration;
import static org.springframework.security.config.Customizer.withDefaults;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private final CustomAuthenticationProvider custAuthProvider;
public SecurityConfiguration(CustomAuthenticationProvider custAuthenProvider) {
this.custAuthProvider = custAuthenProvider;
}
@Value("${app.security.force-https}")
private boolean isForceHttps;
// List of all admin-only endpoints
private final List<String> adminEndpoints = List.of("/home", "/redirect", "/file/upd-adjust", "/file/add-file",
"/file/upd-ejv-num", "/file/upd-file", "/file/view-file");
// --- AUTHENTICATION MANAGER (NO DEPRECATION) ---
@Bean
AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class).authenticationProvider(custAuthProvider)
.build();
}
// Return 404 for unauthenticated requests to admin endpoints
private final AuthenticationEntryPoint notFoundEntryPoint = (req, res, authException) -> {
if (adminEndpoints.contains(req.getRequestURI())) {
res.sendError(404); // hide existence
} else {
res.sendRedirect("/"); // fallback for login for other endpoints
}
};
// Return 404 for access denied on admin endpoints
private final AccessDeniedHandler adminNotFoundAccessDeniedHandler = (req, res, accessDeniedException) -> {
if (adminEndpoints.contains(req.getRequestURI())) {
res.sendError(404); // hide existence
} else {
res.sendRedirect("/"); // fallback for login for other endpoints
}
};
// disable default login form
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// CSRF with Cookie repository for forms + AJAX
http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
// Force HTTPS if enabled
if (isForceHttps) {
http.redirectToHttps(withDefaults());
}
// Admin-only endpoints and general authorization
http.authorizeHttpRequests(
auth -> auth
.requestMatchers("/home", "/redirect", "/file/upd-adjust", "/file/add-file",
"/file/upd-ejv-num", "/file/upd-file", "/file/view-file")
.hasRole("ADMIN").anyRequest().permitAll());
// Custom access handlers
http.exceptionHandling(exceptionHandler -> exceptionHandler.authenticationEntryPoint(notFoundEntryPoint)
.accessDeniedHandler(adminNotFoundAccessDeniedHandler));
// Custom login and logout
http.formLogin(form -> form.loginPage("/").failureUrl("/").permitAll())
.logout(logout -> logout.logoutUrl("/usr-logout").logoutSuccessUrl("/").invalidateHttpSession(true)
.clearAuthentication(true).permitAll());
return http.build();
}
}

82
src/main/java/com/adjustment_file_management_system/springboot/controller/FileDataController.java

@ -0,0 +1,82 @@
package com.adjustment_file_management_system.springboot.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.adjustment_file_management_system.springboot.response_dto.FileDataResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.FundTypeResponseDTO;
import com.adjustment_file_management_system.springboot.service.FileDataService;
@Controller
@RequestMapping("/file")
public class FileDataController {
@Autowired
private FileDataService fileDataSer;
@GetMapping("/view-file-det")
public String viewFileDetails(Model model, @RequestParam("file-num") String fileNum) {
FileDataResponseDTO fileDataResDTO = fileDataSer.getFileDataByFileNum(fileNum);
model.addAttribute("fileDatum", fileDataResDTO);
model.addAttribute("curPage", "view-file-det");
return "file/view-file-detail";
}
@GetMapping("/add-file")
public String addFile(Model model) {
List<FundTypeResponseDTO> fundTypeResDTOs = fileDataSer.getAllFundTypes();
model.addAttribute("fundTypes", fundTypeResDTOs);
model.addAttribute("curPage", "add-file");
return "file/add-file";
}
@GetMapping("/upd-ejv-num")
public String updEjvNum(Model model) {
List<Map<String, Object>> fileDatum = fileDataSer.getAllFileData().stream().map(fileData -> {
Map<String, Object> fileDataMapObj = new HashMap<String, Object>();
fileDataMapObj.put("fileNum", fileData.getFileDataNum());
boolean asFinalFileStat = (fileData.getAsFinalFilePath() != null
&& !fileData.getAsFinalFilePath().trim().equalsIgnoreCase("-"));
boolean ejvNumFileStat = (fileData.getEjvNumFilePath() != null
&& !fileData.getEjvNumFilePath().trim().equalsIgnoreCase("-"));
boolean ejvNumStat = (!fileData.getEjvNum().trim().isEmpty()
&& !fileData.getEjvNum().trim().equalsIgnoreCase("-"));
fileDataMapObj.put("asFinalFileStat", asFinalFileStat);
fileDataMapObj.put("ejvNumFileStat", ejvNumFileStat);
fileDataMapObj.put("ejvNumStat", ejvNumStat);
fileDataMapObj.put("ejvNum", fileData.getEjvNum());
fileDataMapObj.put("ejvNumFile", fileData.getEjvNumFilePath());
return fileDataMapObj;
}).toList();
model.addAttribute("curPage", "upd-ejv-num");
model.addAttribute("fileDatum", fileDatum);
return "file/update-ejv-number";
}
@GetMapping("/upd-file")
public String updFile(Model model) {
List<FileDataResponseDTO> fileDataResDTOs = fileDataSer.getAllFileData();
List<FundTypeResponseDTO> fundTypeResDTOs = fileDataSer.getAllFundTypes();
model.addAttribute("fundTypes", fundTypeResDTOs);
model.addAttribute("fileDatum", fileDataResDTOs);
model.addAttribute("curPage", "upd-file");
return "file/update-file";
}
@GetMapping("/view-file")
public String viewFile(Model model) {
List<FileDataResponseDTO> fileDataResDTOs = fileDataSer.getAllFileData();
model.addAttribute("fileDatum", fileDataResDTOs);
model.addAttribute("curPage", "view-file");
return "file/view-file";
}
}

44
src/main/java/com/adjustment_file_management_system/springboot/controller/HomeController.java

@ -0,0 +1,44 @@
package com.adjustment_file_management_system.springboot.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.adjustment_file_management_system.springboot.service.HomeService;
@Controller
@RequestMapping("/")
public class HomeController {
@Autowired
private HomeService homeSer;
@GetMapping("/home")
public String homePage(Model model) {
Map<String, Long> stats = homeSer.getFileDataStat();
model.addAttribute("curPage", "home");
model.addAttribute("stats", stats);
return "home/home";
}
@GetMapping("/redirect")
public String usrRedirect(@RequestParam("usr-role") String usrRole) {
return switch (usrRole) {
case "ROLE_ADMIN" -> "redirect:/home";
default -> "redirect:/"; // fallback to login page
};
}
@GetMapping("/")
public String loginPage() {
return "home/login";
}
}

22
src/main/java/com/adjustment_file_management_system/springboot/mapper/AdvanceTypeMapper.java

@ -0,0 +1,22 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.AdvanceType;
import com.adjustment_file_management_system.springboot.request_dto.AdvanceTypeRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.AdvanceTypeResponseDTO;
@Component
public class AdvanceTypeMapper {
public AdvanceTypeResponseDTO toAdvTypeResDTO(AdvanceType advType) {
return new AdvanceTypeResponseDTO(advType.getAdvTypeId(), advType.getAdvType());
}
public AdvanceType toAdvTypeEnt(AdvanceTypeRequestDTO advTypeReqDTO) {
AdvanceType advType = new AdvanceType();
advType.setAdvType(advTypeReqDTO.getAdvType());
return advType;
}
}

18
src/main/java/com/adjustment_file_management_system/springboot/mapper/AppUserMapper.java

@ -0,0 +1,18 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.AppUser;
import com.adjustment_file_management_system.springboot.response_dto.AppUserResponseDTO;
@Component
public class AppUserMapper {
@Autowired
private UserRoleMapper usrRoleMap;
public AppUserResponseDTO toUsrResDTO(AppUser usr) {
return new AppUserResponseDTO(usr.getUsrId(), usr.getUsrName(), usrRoleMap.toUsrRoleResDTO(usr.getUsrRole()),
usr.getUsrPass());
}
}

127
src/main/java/com/adjustment_file_management_system/springboot/mapper/FileDataMapper.java

@ -0,0 +1,127 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.FileData;
import com.adjustment_file_management_system.springboot.repository.AdvanceTypeRepository;
import com.adjustment_file_management_system.springboot.repository.FundTypeRepository;
import com.adjustment_file_management_system.springboot.request_dto.FileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.FileDataResponseDTO;
@Component
public class FileDataMapper {
@Autowired
private AdvanceTypeRepository advTypeRepo;
@Autowired
private FundTypeRepository fundTypeRepo;
@Autowired
private FundTypeMapper fundTypeMap;
@Autowired
private AdvanceTypeMapper advTypeMap;
public FileData toFileDataEnt(FileDataResponseDTO fileDataResDTO) {
FileData fileData = new FileData();
fileData.setAdvType(advTypeRepo.findById(fileDataResDTO.getAdvTypeResDTO().getAdvTypeId()).get());
fileData.setAsFileGenDate(fileDataResDTO.getAsFileGenDate());
fileData.setAsFilePath(fileDataResDTO.getAsFilePath());
fileData.setAsFinalFileGenDate(fileDataResDTO.getAsFinalFileGenDate());
fileData.setAsFinalFilePath(fileDataResDTO.getAsFinalFilePath());
fileData.setBalAmt(fileDataResDTO.getBalAmt());
fileData.setDcFilePath(fileDataResDTO.getDcFilePath());
fileData.setEjvNum(fileDataResDTO.getEjvNum());
fileData.setEjvNumFileGenDate(fileDataResDTO.getEjvNumFileGenDate());
fileData.setEjvNumFilePath(fileDataResDTO.getEjvNumFilePath());
fileData.setFiAmt(fileDataResDTO.getFiAmt());
fileData.setFiFileGenDate(fileDataResDTO.getFiFileGenDate());
fileData.setFiFilePath(fileDataResDTO.getFiFilePath());
fileData.setFileRmrk(fileDataResDTO.getFileRmrk());
fileData.setFileDataNum(fileDataResDTO.getFileDataNum());
fileData.setFileDataId(fileDataResDTO.getFileDataId());
fileData.setFinYear(fileDataResDTO.getFinYear());
fileData.setFundType(fundTypeRepo.findById(fileDataResDTO.getFundTypeResDTO().getFundTypeId()).get());
fileData.setIrFilePath(fileDataResDTO.getIrFilePath());
fileData.setPiAmt(fileDataResDTO.getPiAmt());
fileData.setPiFileGenDate(fileDataResDTO.getPiFileGenDate());
fileData.setPiFilePath(fileDataResDTO.getPiFilePath());
fileData.setPoFilePath(fileDataResDTO.getPoFilePath());
fileData.setRtgsFilePath(fileDataResDTO.getRtgsFilePath());
fileData.setSrFilePath(fileDataResDTO.getSrFilePath());
fileData.setTcFileGenDate(fileDataResDTO.getTcFileGenDate());
fileData.setTcFilePath(fileDataResDTO.getTcFilePath());
fileData.setVendName(fileDataResDTO.getVendName());
return fileData;
}
public FileData toFileDataEnt(FileDataRequestDTO fileDataReqDTO) {
FileData fileData = new FileData();
fileData.setAdvType(advTypeRepo.findById(fileDataReqDTO.getAdvTypeId()).get());
fileData.setAsFileGenDate(fileDataReqDTO.getAsFileGenDate());
fileData.setAsFilePath(fileDataReqDTO.getAsFilePath());
fileData.setAsFinalFileGenDate(fileDataReqDTO.getAsFinalFileGenDate());
fileData.setAsFinalFilePath(fileDataReqDTO.getAsFinalFilePath());
fileData.setBalAmt(fileDataReqDTO.getBalAmt());
fileData.setDcFilePath(fileDataReqDTO.getDcFilePath());
fileData.setEjvNum(fileDataReqDTO.getEjvNum());
fileData.setEjvNumFilePath(fileDataReqDTO.getEjvNumFilePath());
fileData.setFiAmt(fileDataReqDTO.getFiAmt());
fileData.setFiFileGenDate(fileDataReqDTO.getFiFileGenDate());
fileData.setFiFilePath(fileDataReqDTO.getFiFilePath());
fileData.setFileDataNum(fileDataReqDTO.getFileDataNum());
fileData.setFileRmrk(fileDataReqDTO.getFileRmrk());
fileData.setFinYear(fileDataReqDTO.getFinYear());
fileData.setFundType(fundTypeRepo.findById(fileDataReqDTO.getFundTypeId()).get());
fileData.setIrFilePath(fileDataReqDTO.getIrFilePath());
fileData.setPiAmt(fileDataReqDTO.getPiAmt());
fileData.setPiFileGenDate(fileDataReqDTO.getPiFileGenDate());
fileData.setPiFilePath(fileDataReqDTO.getPiFilePath());
fileData.setPoFilePath(fileDataReqDTO.getPoFilePath());
fileData.setRtgsFilePath(fileDataReqDTO.getRtgsFilePath());
fileData.setSrFilePath(fileDataReqDTO.getSrFilePath());
fileData.setTcFileGenDate(fileDataReqDTO.getTcFileGenDate());
fileData.setTcFilePath(fileDataReqDTO.getTcFilePath());
fileData.setVendName(fileDataReqDTO.getVendName());
fileData.setEjvNumFileGenDate(fileDataReqDTO.getEjvNumFileGenDate());
return fileData;
}
public FileDataResponseDTO toFileDataResDTO(FileData fileData) {
FileDataResponseDTO fileDataResDTO = new FileDataResponseDTO();
fileDataResDTO.setAsFileGenDate(fileData.getAsFileGenDate());
fileDataResDTO.setAdvTypeResDTO(
advTypeMap.toAdvTypeResDTO(advTypeRepo.findById(fileData.getAdvType().getAdvTypeId()).get()));
fileDataResDTO.setAsFilePath(fileData.getAsFilePath());
fileDataResDTO.setAsFinalFileGenDate(fileData.getAsFinalFileGenDate());
fileDataResDTO.setAsFinalFilePath(fileData.getAsFinalFilePath());
fileDataResDTO.setBalAmt(fileData.getBalAmt());
fileDataResDTO.setDcFilePath(fileData.getDcFilePath());
fileDataResDTO.setEjvNum(fileData.getEjvNum());
fileDataResDTO.setEjvNumFilePath(fileData.getEjvNumFilePath());
fileDataResDTO.setFiAmt(fileData.getFiAmt());
fileDataResDTO.setFiFileGenDate(fileData.getFiFileGenDate());
fileDataResDTO.setFiFilePath(fileData.getFiFilePath());
fileDataResDTO.setFileDataId(fileData.getFileDataId());
fileDataResDTO.setFileDataNum(fileData.getFileDataNum());
fileDataResDTO.setFileRmrk(fileData.getFileRmrk());
fileDataResDTO.setFinYear(fileData.getFinYear());
fileDataResDTO.setFundTypeResDTO(
fundTypeMap.toFundTypeResDTO(fundTypeRepo.findById(fileData.getFundType().getFundTypeId()).get()));
fileDataResDTO.setIrFilePath(fileData.getIrFilePath());
fileDataResDTO.setPiAmt(fileData.getPiAmt());
fileDataResDTO.setPiFileGenDate(fileData.getPiFileGenDate());
fileDataResDTO.setPiFilePath(fileData.getPiFilePath());
fileDataResDTO.setPoFilePath(fileData.getPoFilePath());
fileDataResDTO.setRtgsFilePath(fileData.getRtgsFilePath());
fileDataResDTO.setSrFilePath(fileData.getSrFilePath());
fileDataResDTO.setTcFileGenDate(fileData.getTcFileGenDate());
fileDataResDTO.setTcFilePath(fileData.getTcFilePath());
fileDataResDTO.setVendName(fileData.getVendName());
fileDataResDTO.setEjvNumFileGenDate(fileData.getEjvNumFileGenDate());
return fileDataResDTO;
}
}

15
src/main/java/com/adjustment_file_management_system/springboot/mapper/FundTypeMapper.java

@ -0,0 +1,15 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.FundType;
import com.adjustment_file_management_system.springboot.response_dto.FundTypeResponseDTO;
@Component
public class FundTypeMapper {
public FundTypeResponseDTO toFundTypeResDTO(FundType fundType) {
return new FundTypeResponseDTO(fundType.getFundTypeId(), fundType.getFundType());
}
}

13
src/main/java/com/adjustment_file_management_system/springboot/mapper/UserRoleMapper.java

@ -0,0 +1,13 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.UserRole;
import com.adjustment_file_management_system.springboot.response_dto.UserRoleResponseDTO;
@Component
public class UserRoleMapper {
public UserRoleResponseDTO toUsrRoleResDTO(UserRole usrRole) {
return new UserRoleResponseDTO(usrRole.getUsrRoleId(), usrRole.getUsrRoleName());
}
}

43
src/main/java/com/adjustment_file_management_system/springboot/model/AdvanceType.java

@ -0,0 +1,43 @@
package com.adjustment_file_management_system.springboot.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
//For local DB Server
/* @Table(name = "tbl_adv_type_det", schema = "GCC") */
//For Production DB Server
@Table(name = "tbl_adv_type_det", schema = "fileadjust")
public class AdvanceType {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "adv_type_seq")
/*
* @SequenceGenerator(name = "adv_type_seq", sequenceName = "adv_type_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "adv_type_seq", sequenceName = "adv_type_id_seq", allocationSize = 1, schema = "fileadjust")
@Column(name = "adv_type_id", nullable = false, updatable = false)
private Long advTypeId;
@Column(name = "adv_type", nullable = false)
@NotBlank
private String advType;
}

52
src/main/java/com/adjustment_file_management_system/springboot/model/AppUser.java

@ -0,0 +1,52 @@
package com.adjustment_file_management_system.springboot.model;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@Table(name = "tbl_app_usr_det", schema = "fileadjust")
/* @Table(name = "tbl_app_usr_det", schema = "gcc") */
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "usrRole", "usrPass" })
@NoArgsConstructor
@AllArgsConstructor
public class AppUser {
@Id
@Column(name = "usr_id", nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_usr_seq")
/*
* @SequenceGenerator(name = "app_usr_seq", sequenceName = "usr_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "app_usr_seq", sequenceName = "app_usr_id_seq", allocationSize = 1, schema = "fileadjust")
private Integer usrId;
@Column(name = "usr_name", nullable = false)
@NotBlank
private String usrName;
@Column(name = "usr_pass", nullable = false)
@NotBlank
private String usrPass;
@ManyToOne
@JoinColumn(name = "usr_role_id", nullable = false, referencedColumnName = "usr_role_id")
@JsonBackReference
private UserRole usrRole;
}

213
src/main/java/com/adjustment_file_management_system/springboot/model/FileData.java

@ -0,0 +1,213 @@
package com.adjustment_file_management_system.springboot.model;
import java.util.Date;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "advType", "fundType", "createdBy",
"updatedBy" })
@AllArgsConstructor
@NoArgsConstructor
// For local DB Server
/* @Table(name = "tbl_file_data_det", schema = "GCC") */
// For Production DB Server
@Table(name = "tbl_file_data_det", schema = "fileadjust")
public class FileData {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "file_data_seq")
/*
* @SequenceGenerator(name = "file_data_seq", sequenceName = "file_data_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "file_data_seq", sequenceName = "file_data_id_seq", allocationSize = 1, schema = "fileadjust")
@Column(name = "file_data_id", nullable = false, updatable = false)
private Long fileDataId;
@Column(name = "file_data_num", nullable = false, unique = true)
@NotBlank
private String fileDataNum;
@Column(name = "fin_year", nullable = false)
@NotBlank
private String finYear;
@Column(name = "as_file_path", nullable = false, length = 1000)
@NotBlank
private String asFilePath;
@Column(name = "as_file_gen_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date asFileGenDate;
@Column(name = "pi_file_path", nullable = false, length = 1000)
@NotBlank
private String piFilePath;
@Column(name = "pi_file_gen_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date piFileGenDate;
@Column(name = "pi_amt", nullable = false)
@NotNull
private Double piAmt;
@Column(name = "fi_file_path", nullable = false, length = 1000)
@NotBlank
private String fiFilePath;
@Column(name = "fi_amt", nullable = false)
@NotNull
private Double fiAmt;
@Column(name = "fi_file_gen_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date fiFileGenDate;
@Column(name = "bal_amt", nullable = false)
@NotNull
private Double balAmt;
@Column(name = "rtgs_file_path", nullable = false, length = 1000)
@NotBlank
private String rtgsFilePath;
@Column(name = "po_file_path", nullable = false, length = 1000)
@NotBlank
private String poFilePath;
@Column(name = "dc_file_path", nullable = false, length = 1000)
@NotBlank
private String dcFilePath;
@Column(name = "sr_file_path", nullable = false, length = 1000)
@NotBlank
private String srFilePath;
@Column(name = "ir_file_path", nullable = false, length = 1000)
@NotBlank
private String irFilePath;
@Column(name = "as_final_file_path", nullable = false, length = 1000)
@NotBlank
private String asFinalFilePath;
@Column(name = "as_final_file_gen_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date asFinalFileGenDate;
@Column(name = "ejv_num", nullable = false)
@NotBlank
private String ejvNum;
@Column(name = "ejv_num_file_path", nullable = false, length = 1000)
@NotBlank
private String ejvNumFilePath;
@Column(name = "ejv_num_file_gen_date", nullable = false)
@NotNull
@Temporal(TemporalType.DATE)
private Date ejvNumFileGenDate;
@Column(name = "tc_file_path", nullable = false, length = 1000)
@NotBlank
private String tcFilePath;
@Column(name = "tc_file_gen_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date tcFileGenDate;
@Column(name = "file_rmrk", nullable = false, length = 1000)
@NotBlank
private String fileRmrk;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "adv_type_id", referencedColumnName = "adv_type_id", nullable = false)
private AdvanceType advType;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fund_type_id", referencedColumnName = "fund_type_id", nullable = false)
private FundType fundType;
@Column(name = "vend_name", nullable = false)
@NotBlank
private String vendName;
@CreatedBy
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "created_by_usr_id", referencedColumnName = "usr_id", updatable = false, nullable = false)
private AppUser createdBy;
@LastModifiedBy
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "updated_by_usr_id", referencedColumnName = "usr_id", nullable = false)
private AppUser updatedBy;
// User timestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "usr_created_timestamp", nullable = false, updatable = false)
private Date usrCreatedTimestamp;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "usr_updated_timestamp", nullable = false)
private Date usrUpdatedTimestamp;
// DB-managed timestamps
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false, nullable = false, name = "db_created_timestamp")
private Date dbCreatedTimestamp;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false, name = "db_updated_timestamp")
private Date dbUpdatedTimestamp;
@PrePersist
public void onCreate() {
this.usrCreatedTimestamp = new Date();
this.usrUpdatedTimestamp = new Date();
}
@PreUpdate
public void onUpdate() {
this.usrUpdatedTimestamp = new Date();
}
}

43
src/main/java/com/adjustment_file_management_system/springboot/model/FundType.java

@ -0,0 +1,43 @@
package com.adjustment_file_management_system.springboot.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
//For local DB Server
/* @Table(name = "tbl_fund_type_det", schema = "GCC") */
//For Production DB Server
@Table(name = "tbl_fund_type_det", schema = "fileadjust")
public class FundType {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fund_type_seq")
/*
* @SequenceGenerator(name = "fund_type_seq", sequenceName = "fund_type_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "fund_type_seq", sequenceName = "fund_type_id_seq", allocationSize = 1, schema = "fileadjust")
@Column(name = "fund_type_id", nullable = false, updatable = false)
private Long fundTypeId;
@Column(name = "fund_type", nullable = false)
@NotBlank
private String fundType;
}

52
src/main/java/com/adjustment_file_management_system/springboot/model/UserRole.java

@ -0,0 +1,52 @@
package com.adjustment_file_management_system.springboot.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@ToString(includeFieldNames = true, doNotUseGetters = true, exclude = { "appUsrs" })
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
/* @Table(name = "tbl_usr_role_det", schema = "gcc") */
@Table(name = "tbl_usr_role_det", schema = "fileadjust")
public class UserRole {
@Id
@Column(name = "usr_role_id", nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "usr_role_seq")
/*
* @SequenceGenerator(name = "usr_role_seq", sequenceName = "usr_role_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "usr_role_seq", sequenceName = "usr_role_id_seq", allocationSize = 1, schema = "fileadjust")
private Integer usrRoleId;
@Column(name = "usr_role_name", nullable = false)
@NotBlank
private String usrRoleName;
@OneToMany(mappedBy = "usrRole", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonManagedReference
private List<AppUser> appUsrs;
}

18
src/main/java/com/adjustment_file_management_system/springboot/repository/AdvanceTypeRepository.java

@ -0,0 +1,18 @@
package com.adjustment_file_management_system.springboot.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.AdvanceType;
@Repository
public interface AdvanceTypeRepository extends JpaRepository<AdvanceType, Long> {
@Query(nativeQuery = true, value = "SELECT * FROM TBL_ADV_TYPE_DET WHERE ADV_TYPE = :advType")
Optional<AdvanceType> findAdvTypeByAdvType(@Param("advType") String advType);
}

13
src/main/java/com/adjustment_file_management_system/springboot/repository/AppUserRepository.java

@ -0,0 +1,13 @@
package com.adjustment_file_management_system.springboot.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.AppUser;
@Repository
public interface AppUserRepository extends JpaRepository<AppUser, Integer> {
Optional<AppUser> findByUsrName(String usrName);
}

15
src/main/java/com/adjustment_file_management_system/springboot/repository/FileDataRepository.java

@ -0,0 +1,15 @@
package com.adjustment_file_management_system.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.FileData;
@Repository
public interface FileDataRepository extends JpaRepository<FileData, Long> {
@Query(value = "SELECT fd FROM FileData fd WHERE fd.fileDataNum = ?1")
FileData findFileDataByFileDataNum(String fileDataNum);
}

11
src/main/java/com/adjustment_file_management_system/springboot/repository/FundTypeRepository.java

@ -0,0 +1,11 @@
package com.adjustment_file_management_system.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.FundType;
@Repository
public interface FundTypeRepository extends JpaRepository<FundType, Long> {
}

34
src/main/java/com/adjustment_file_management_system/springboot/request_dto/AddFileDataRequestDTO.java

@ -0,0 +1,34 @@
package com.adjustment_file_management_system.springboot.request_dto;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.multipart.MultipartFile;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class AddFileDataRequestDTO {
private String fileNum;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date asFileGenDate;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date piFileGenDate;
private Double piAmt;
private String fileRmrk;
private MultipartFile asFile;
private MultipartFile piFile;
private String finYear;
private String vendName;
private String advType;
private Long fundTypeId;
}

18
src/main/java/com/adjustment_file_management_system/springboot/request_dto/AdvanceTypeRequestDTO.java

@ -0,0 +1,18 @@
package com.adjustment_file_management_system.springboot.request_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class AdvanceTypeRequestDTO {
private String advType;
}

17
src/main/java/com/adjustment_file_management_system/springboot/request_dto/AppUserRequestDTO.java

@ -0,0 +1,17 @@
package com.adjustment_file_management_system.springboot.request_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@NoArgsConstructor
@AllArgsConstructor
public class AppUserRequestDTO {
private String usrName;
private String usrPass;
}

44
src/main/java/com/adjustment_file_management_system/springboot/request_dto/FileDataRequestDTO.java

@ -0,0 +1,44 @@
package com.adjustment_file_management_system.springboot.request_dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@NoArgsConstructor
@AllArgsConstructor
public class FileDataRequestDTO {
private String fileDataNum;
private String asFilePath;
private Date asFileGenDate;
private String piFilePath;
private Date piFileGenDate;
private Double piAmt;
private String fiFilePath;
private Double fiAmt;
private Date fiFileGenDate;
private Double balAmt;
private String rtgsFilePath;
private String poFilePath;
private String dcFilePath;
private String srFilePath;
private String irFilePath;
private String asFinalFilePath;
private Date asFinalFileGenDate;
private String ejvNum;
private String ejvNumFilePath;
private String tcFilePath;
private Date tcFileGenDate;
private String fileRmrk;
private String vendName;
private String finYear;
private Long advTypeId;
private Long fundTypeId;
private Date ejvNumFileGenDate;
}

50
src/main/java/com/adjustment_file_management_system/springboot/request_dto/UpdateFileDataRequestDTO.java

@ -0,0 +1,50 @@
package com.adjustment_file_management_system.springboot.request_dto;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.multipart.MultipartFile;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class UpdateFileDataRequestDTO {
private String fileNum;
private String fileRmrk;
private String advType;
private Long fundTypeId;
private String vendName;
private MultipartFile poFile;
private MultipartFile dcFile;
private MultipartFile srFile;
private MultipartFile irFile;
private MultipartFile rtgsFile;
private MultipartFile piFile;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date piFileGenDate;
private Double piAmt;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date asFileGenDate;
private MultipartFile asFile;
private MultipartFile fiFile;
private Double fiAmt;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date fiFileGenDate;
private MultipartFile asFinalFile;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date asFinalFileGenDate;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date tcFileGenDate;
private MultipartFile tcFile;
private Double balAmt;
}

19
src/main/java/com/adjustment_file_management_system/springboot/response_dto/AdvanceTypeResponseDTO.java

@ -0,0 +1,19 @@
package com.adjustment_file_management_system.springboot.response_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class AdvanceTypeResponseDTO {
private Long advTypeId;
private String advType;
}

19
src/main/java/com/adjustment_file_management_system/springboot/response_dto/AppUserResponseDTO.java

@ -0,0 +1,19 @@
package com.adjustment_file_management_system.springboot.response_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "usrPass" })
@AllArgsConstructor
@NoArgsConstructor
public class AppUserResponseDTO {
private Integer usrId;
private String usrName;
private UserRoleResponseDTO usrRole;
private String usrPass;
}

46
src/main/java/com/adjustment_file_management_system/springboot/response_dto/FileDataResponseDTO.java

@ -0,0 +1,46 @@
package com.adjustment_file_management_system.springboot.response_dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class FileDataResponseDTO {
private Long fileDataId;
private String fileDataNum;
private String asFilePath;
private Date asFileGenDate;
private String piFilePath;
private Date piFileGenDate;
private Double piAmt;
private String fiFilePath;
private Double fiAmt;
private Date fiFileGenDate;
private Double balAmt;
private String rtgsFilePath;
private String poFilePath;
private String dcFilePath;
private String srFilePath;
private String irFilePath;
private String asFinalFilePath;
private Date asFinalFileGenDate;
private String ejvNum;
private String ejvNumFilePath;
private String tcFilePath;
private Date tcFileGenDate;
private String fileRmrk;
private String vendName;
private String finYear;
private AdvanceTypeResponseDTO advTypeResDTO;
private Date ejvNumFileGenDate;
private FundTypeResponseDTO fundTypeResDTO;
private Long daysPass;
}

17
src/main/java/com/adjustment_file_management_system/springboot/response_dto/FundTypeResponseDTO.java

@ -0,0 +1,17 @@
package com.adjustment_file_management_system.springboot.response_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(includeFieldNames = true, doNotUseGetters = true)
@NoArgsConstructor
@AllArgsConstructor
public class FundTypeResponseDTO {
private Long fundTypeId;
private String fundType;
}

19
src/main/java/com/adjustment_file_management_system/springboot/response_dto/ServiceResponseDTO.java

@ -0,0 +1,19 @@
package com.adjustment_file_management_system.springboot.response_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class ServiceResponseDTO {
private boolean resStat;
private String res;
}

17
src/main/java/com/adjustment_file_management_system/springboot/response_dto/UserRoleResponseDTO.java

@ -0,0 +1,17 @@
package com.adjustment_file_management_system.springboot.response_dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@NoArgsConstructor
@AllArgsConstructor
public class UserRoleResponseDTO {
private Integer usrRoleId;
private String usrRoleName;
}

93
src/main/java/com/adjustment_file_management_system/springboot/rest_controller/FileDataRestController.java

@ -0,0 +1,93 @@
package com.adjustment_file_management_system.springboot.rest_controller;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.adjustment_file_management_system.springboot.request_dto.AddFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.UpdateFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.ServiceResponseDTO;
import com.adjustment_file_management_system.springboot.service.FileDataService;
@RestController
@RequestMapping("/api/file")
public class FileDataRestController {
@Autowired
private FileDataService fileDataSer;
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
sdf.setLenient(false);
// true = allow empty string to be converted to null
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
}
@PostMapping("/view-supp-docs")
public ResponseEntity<byte[]> viewSuppDocs(@RequestParam("file-type") String fileType,
@RequestParam("file-path") String filePath, @RequestParam("file-num") String fileNum) {
try {
byte[] fileData = fileDataSer.getFileBytes(fileType, filePath, fileNum);
String fileName = fileDataSer.getFileName(filePath);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"" + fileName + "\"").body(fileData);
} catch (IllegalArgumentException iae) {
return ResponseEntity.badRequest().body(iae.getMessage().getBytes(StandardCharsets.UTF_8));
} catch (IOException ioe) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ioe.getMessage().getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(e.getMessage().getBytes(StandardCharsets.UTF_8));
}
}
@PostMapping("/add-file")
public ResponseEntity<ServiceResponseDTO> addFile(@ModelAttribute AddFileDataRequestDTO addFileDataReqDTO) {
ServiceResponseDTO serResDTO = fileDataSer.addFileData(addFileDataReqDTO);
if (serResDTO.isResStat()) {
return ResponseEntity.ok(serResDTO);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(serResDTO);
}
}
@PostMapping("/upd-file")
public ResponseEntity<ServiceResponseDTO> updFile(@ModelAttribute UpdateFileDataRequestDTO updFileDataReqDTO) {
ServiceResponseDTO serResDTO = fileDataSer.updFileData(updFileDataReqDTO);
if (serResDTO.isResStat()) {
return ResponseEntity.ok(serResDTO);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(serResDTO);
}
}
@PostMapping("/upd-ejv-num")
public ResponseEntity<ServiceResponseDTO> updEjvNum(@RequestParam("file-num") String fileNum,
@RequestParam("ejv-num") String ejvNum, @RequestParam("ejv-num-file") MultipartFile ejvNumFile) {
ServiceResponseDTO serResDTO = fileDataSer.updEjvNum(fileNum, ejvNumFile, ejvNum);
if (serResDTO.isResStat()) {
return ResponseEntity.ok(serResDTO);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(serResDTO);
}
}
}

78
src/main/java/com/adjustment_file_management_system/springboot/rest_controller/HomeRestController.java

@ -0,0 +1,78 @@
package com.adjustment_file_management_system.springboot.rest_controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.adjustment_file_management_system.springboot.request_dto.AppUserRequestDTO;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
@RestController
@RequestMapping("/api")
public class HomeRestController {
@Autowired
private AuthenticationManager authManager;
@PostMapping("/val-app-usr-login")
public ResponseEntity<?> valUsrLogin(@ModelAttribute AppUserRequestDTO appUsrReqDTO, HttpServletRequest req) {
Map<String, Object> res = new HashMap<String, Object>();
try {
Authentication auth = authManager.authenticate(
new UsernamePasswordAuthenticationToken(appUsrReqDTO.getUsrName(), appUsrReqDTO.getUsrPass()));
/**
* Store authentication in session so Spring Security knows the user is logged
* in
**/
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(auth);
SecurityContextHolder.setContext(securityContext);
HttpSession httpSession = req.getSession(true);
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
// Authentication successful
res.put("result", true);
res.put("usrName", auth.getName());
res.put("role", auth.getAuthorities());
return ResponseEntity.ok(res);
} catch (AuthenticationException ae) {
// 1️ Username not found (direct)
if (ae instanceof UsernameNotFoundException) {
res.put("result", false);
res.put("error", "User not found");
return ResponseEntity.status(404).body(res);
}
// 2 Wrong password (direct)
if (ae instanceof BadCredentialsException) {
res.put("result", false);
res.put("error", "Invalid username or password");
return ResponseEntity.status(401).body(res);
}
// 3️ Default fallback
res.put("result", false);
res.put("error", "Authentication failed");
return ResponseEntity.status(401).body(res);
}
}
}

606
src/main/java/com/adjustment_file_management_system/springboot/service/FileDataService.java

@ -0,0 +1,606 @@
package com.adjustment_file_management_system.springboot.service;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import com.adjustment_file_management_system.springboot.configuration.FileDataPropertiesConfiguration;
import com.adjustment_file_management_system.springboot.mapper.AdvanceTypeMapper;
import com.adjustment_file_management_system.springboot.mapper.FileDataMapper;
import com.adjustment_file_management_system.springboot.mapper.FundTypeMapper;
import com.adjustment_file_management_system.springboot.repository.AdvanceTypeRepository;
import com.adjustment_file_management_system.springboot.repository.FileDataRepository;
import com.adjustment_file_management_system.springboot.repository.FundTypeRepository;
import com.adjustment_file_management_system.springboot.request_dto.AddFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.AdvanceTypeRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.FileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.UpdateFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.AdvanceTypeResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.FileDataResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.FundTypeResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.ServiceResponseDTO;
@Service
public class FileDataService {
@Autowired
private FileDataRepository fileDataRepo;
@Autowired
private FolderService folderSer;
@Autowired
private AdvanceTypeRepository advTypeRepo;
@Autowired
private FundTypeRepository fundTypeRepo;
@Autowired
private FundTypeMapper fundTypeMap;
@Autowired
private FileDataPropertiesConfiguration fileDataPropsConfig;
@Autowired
private FileDataMapper fileDataMap;
@Autowired
private AdvanceTypeMapper advTypeMap;
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
private static final Logger logger = LoggerFactory.getLogger(FileDataService.class);
private static final Date placeHolderDate = new Date(0);
// Clean file if error occurrs while adding file
private void cleanUpFiles(String... paths) {
for (String path : paths) {
folderSer.deleteFileIfExists(path);
}
}
// Setting default values for new file
private void setDefaultFileDataValues(FileDataRequestDTO fileDataReqDTO) {
fileDataReqDTO.setAsFinalFileGenDate(placeHolderDate);
fileDataReqDTO.setAsFinalFilePath("-");
fileDataReqDTO.setBalAmt(0.0);
fileDataReqDTO.setDcFilePath("-");
fileDataReqDTO.setEjvNum("-");
fileDataReqDTO.setEjvNumFilePath("-");
fileDataReqDTO.setFiAmt(0.0);
fileDataReqDTO.setFiFileGenDate(placeHolderDate);
fileDataReqDTO.setFiFilePath("-");
fileDataReqDTO.setPiFilePath("-");
fileDataReqDTO.setPoFilePath("-");
fileDataReqDTO.setRtgsFilePath("-");
fileDataReqDTO.setSrFilePath("-");
fileDataReqDTO.setIrFilePath("-");
fileDataReqDTO.setTcFileGenDate(placeHolderDate);
fileDataReqDTO.setTcFilePath("-");
fileDataReqDTO.setAsFilePath("-");
fileDataReqDTO.setPiFilePath("-");
fileDataReqDTO.setEjvNumFileGenDate(placeHolderDate);
}
/**
* Helper method for file uploads, tracks uploaded files automatically.
*/
private void handleFileUpload(String fileNum, String type, Date date, MultipartFile file,
Consumer<String> pathSetter, List<String> uploadedFiles) throws IOException {
if (file == null || file.isEmpty()) {
return;
}
String path = folderSer.saveFile(fileNum, type, date, file);
pathSetter.accept(path);
// Track uploaded file for cleanup if something goes wrong later
uploadedFiles.add(path);
}
/**
* Utility method for choosing first non-null value.
*/
private <T> T firstNonNull(T a, T b) {
return (a != null) ? a : b;
}
// Helper method for date modifying
public String formatForFlatpickr(Date date) {
if (date == null) {
return "";
}
// Convert java.util.Date to LocalDate
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
if (localDate.equals(LocalDate.of(1970, 1, 1))) {
return "";
}
return localDate.format(formatter);
}
/**
* Helper to update a field if not null
*/
private <T> void updateIfNotNull(Consumer<T> setter, T value) {
if (value != null)
setter.accept(value);
}
/**
* Helper to update a String field if not blank
*/
private void updateIfNotBlank(Consumer<String> setter, String value) {
if (value != null && !value.isBlank())
setter.accept(value.trim());
}
/**
* Returns the file from Respective File Data Request DTO by type
*/
private MultipartFile getFileByType(Object obj, String type) {
if (obj instanceof AddFileDataRequestDTO addFileDataReqDTO) {
return switch (type) {
case "AS" -> addFileDataReqDTO.getAsFile();
case "PI" -> addFileDataReqDTO.getPiFile();
default -> null;
};
} else if (obj instanceof UpdateFileDataRequestDTO updFileDataReqDTO) {
return switch (type) {
case "AS" -> updFileDataReqDTO.getAsFile();
case "PI" -> updFileDataReqDTO.getPiFile();
case "FI" -> updFileDataReqDTO.getFiFile();
case "AS-Final" -> updFileDataReqDTO.getAsFinalFile();
case "TC" -> updFileDataReqDTO.getTcFile();
default -> null;
};
}
return null;
}
// Returns the file name from path
public String getFileName(String filePath) {
return Path.of(filePath).getFileName().toString();
}
// Calculates the number of days from present till the date of FI uploaded date
private void calculateDaysPass(FileDataResponseDTO fileDataResDTO) {
LocalDate fiFileGenDate = ((java.sql.Date) fileDataResDTO.getFiFileGenDate()).toLocalDate();
LocalDate ejvNumFileGenDate = ((java.sql.Date) fileDataResDTO.getEjvNumFileGenDate()).toLocalDate();
boolean fiFilePresent = !fileDataResDTO.getFiFilePath().equals("-");
boolean ejvFilePresent = !fileDataResDTO.getEjvNumFilePath().equals("-");
if (!fiFileGenDate.equals(LocalDate.of(1970, 1, 1)) && fiFilePresent) {
long daysPassed;
if (ejvFilePresent && !ejvNumFileGenDate.equals(LocalDate.of(1970, 1, 1))) {
daysPassed = ChronoUnit.DAYS.between(fiFileGenDate, ejvNumFileGenDate);
} else {
daysPassed = ChronoUnit.DAYS.between(fiFileGenDate, LocalDate.now());
}
fileDataResDTO.setDaysPass(daysPassed);
} else {
fileDataResDTO.setDaysPass(0L);
}
}
// Extract the starting year from financial year string
private Integer extractStartYear(String finYear) {
if (finYear == null || !finYear.contains("-")) {
return 0;
}
try {
// Extract the part before the dash (e.g., "2020" from "2020-2021")
return Integer.parseInt(finYear.split("-")[0].trim());
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
logger.info("Exception occurred while extracting the financial starting year: {}", nfe.getMessage());
return 0;
}
}
/**
* Extract the ending year from financial year string
**/
private Integer extractEndYear(String finYear) {
if (finYear == null || !finYear.contains("-"))
return 0;
try {
return Integer.parseInt(finYear.split("-")[1].trim());
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
logger.info("Exception occurred while extracting the financial end year: {}", nfe.getMessage());
return 0;
}
}
// Reads PDF bytes from the given file path of respective file number if valid
public byte[] getFileBytes(String fileType, String filePath, String fileNum) throws IOException {
fileType = fileType.trim();
filePath = filePath.trim();
fileNum = fileNum.trim();
if (!StringUtils.hasText(fileType) || !StringUtils.hasText(filePath)) {
throw new IllegalArgumentException("Invalid request parameters");
}
switch (fileType) {
case "AS", "PI", "RTGS", "PO", "DC", "SR", "IR", "EJV-Number", "AS-Final", "FI", "TC" -> {
// Remove duplicate prefix from filePath if present
if (filePath.startsWith("/uploads/file-data/")) {
filePath = filePath.substring("/uploads/file-data/".length());
} else if (filePath.startsWith("uploads/file-data/")) {
filePath = filePath.substring("uploads/file-data/".length());
}
// Resolve relative path inside uploadDir
File baseDir = fileDataPropsConfig.getUploadDirFile();
Path fullPath = Path.of(baseDir.getAbsolutePath(), filePath).normalize();
if (!Files.exists(fullPath)) {
throw new IOException("File not found for file number: " + fileNum);
}
return Files.readAllBytes(fullPath);
}
default ->
throw new IllegalArgumentException("Unknown file type: " + fileType + " for file number: " + fileNum);
}
}
@Transactional(readOnly = true)
public FileDataResponseDTO getFileDataByFileNum(String fileNum) {
FileDataResponseDTO dto = fileDataMap.toFileDataResDTO(fileDataRepo.findFileDataByFileDataNum(fileNum));
calculateDaysPass(dto);
return dto;
}
@Transactional(readOnly = true)
public List<String> getAllFileDataNum() {
return fileDataRepo.findAll().stream().map(fileData -> fileData.getFileDataNum()).toList();
}
@Transactional(readOnly = true)
public List<FileDataResponseDTO> getAllFileData() {
// Comparator for comparing financial year
Comparator<FileDataResponseDTO> comparator = Comparator
.comparing((FileDataResponseDTO dto) -> extractStartYear(dto.getFinYear()))
.thenComparing(dto -> extractEndYear(dto.getFinYear()));
return fileDataRepo.findAll().stream().map(fileData -> {
FileDataResponseDTO dto = fileDataMap.toFileDataResDTO(fileData);
calculateDaysPass(dto);
return dto;
}).sorted(comparator).toList();
}
@Transactional(rollbackFor = Exception.class)
public ServiceResponseDTO addFileData(AddFileDataRequestDTO addFileDataReqDTO) {
List<String> uploadedFiles = new ArrayList<String>(); // Track uploaded file paths
try {
String fileNum = addFileDataReqDTO.getFileNum().trim();
String vendName = (addFileDataReqDTO.getVendName() != null
&& !addFileDataReqDTO.getVendName().trim().isEmpty())
? addFileDataReqDTO.getVendName().trim().toUpperCase()
: "-";
String advTypeName = addFileDataReqDTO.getAdvType().trim().toUpperCase();
Double piAmt = addFileDataReqDTO.getPiAmt() != null ? addFileDataReqDTO.getPiAmt() : 0.0;
Date piFileGenDate = addFileDataReqDTO.getPiFileGenDate() != null ? addFileDataReqDTO.getPiFileGenDate()
: placeHolderDate;
Date asFileGenDate = addFileDataReqDTO.getAsFileGenDate() != null ? addFileDataReqDTO.getAsFileGenDate()
: placeHolderDate;
// 1️. Get or create AdvanceType
AdvanceTypeResponseDTO advTypeResDTO = advTypeMap
.toAdvTypeResDTO(advTypeRepo.findAdvTypeByAdvType(advTypeName).orElseGet(() -> {
AdvanceTypeRequestDTO advTypeReqDTO = new AdvanceTypeRequestDTO(advTypeName);
return advTypeRepo.save(advTypeMap.toAdvTypeEnt(advTypeReqDTO));
}));
// 2️. Prepare DTO
FileDataRequestDTO fileDataReqDTO = new FileDataRequestDTO();
fileDataReqDTO.setAdvTypeId(advTypeResDTO.getAdvTypeId());
fileDataReqDTO.setFileDataNum(fileNum);
fileDataReqDTO.setFileRmrk(addFileDataReqDTO.getFileRmrk().trim());
fileDataReqDTO.setFinYear(addFileDataReqDTO.getFinYear().trim());
fileDataReqDTO.setFundTypeId(addFileDataReqDTO.getFundTypeId());
fileDataReqDTO.setVendName(vendName);
fileDataReqDTO.setPiAmt(piAmt);
fileDataReqDTO.setAsFileGenDate(asFileGenDate);
fileDataReqDTO.setPiFileGenDate(piFileGenDate);
// Set default values
setDefaultFileDataValues(fileDataReqDTO);
// 3️. Handle file uploads
Map<String, MultipartFile> files = new HashMap<String, MultipartFile>();
if (addFileDataReqDTO.getAsFile() != null) {
files.put("AS", addFileDataReqDTO.getAsFile());
}
if (addFileDataReqDTO.getPiFile() != null) {
files.put("PI", addFileDataReqDTO.getPiFile());
}
Map<String, Consumer<String>> pathSetters = Map.of("AS", fileDataReqDTO::setAsFilePath, "PI",
fileDataReqDTO::setPiFilePath);
for (String type : files.keySet()) {
MultipartFile file = files.get(type);
// use the dates already set
handleFileUpload(fileNum, type, "AS".equals(type) ? asFileGenDate : piFileGenDate, file,
pathSetters.get(type), uploadedFiles);
}
// 4️. Save to DB
fileDataRepo.save(fileDataMap.toFileDataEnt(fileDataReqDTO));
logger.info("File saved with file number: {}", fileNum);
return new ServiceResponseDTO(true, "File added successfully");
} catch (IOException ioe) {
logger.error("Exception occurred in file upload part: {}", ioe.getMessage(), ioe);
ioe.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to add the file. Error in file upload: " + ioe.getMessage());
} catch (Exception e) {
logger.error("Exception occurred: {}", e.getMessage(), e);
e.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to add the file. Error: " + e.getMessage());
}
}
@Transactional(rollbackFor = Exception.class)
public ServiceResponseDTO updFileData(UpdateFileDataRequestDTO updFileReqDTO) {
List<String> uploadedFiles = new ArrayList<String>(); // Track uploaded paths
try {
String fileNum = updFileReqDTO.getFileNum().trim();
FileDataResponseDTO fileDataResDTO = fileDataMap
.toFileDataResDTO(fileDataRepo.findFileDataByFileDataNum(fileNum));
String advTypeName = updFileReqDTO.getAdvType().trim().toUpperCase();
String reqVendName = updFileReqDTO.getVendName();
String vendName = reqVendName != null ? reqVendName.trim().toUpperCase() : "-";
if (fileDataResDTO == null) {
return new ServiceResponseDTO(false, "File not found for file number: " + fileNum);
}
// Get or create AdvanceType
AdvanceTypeResponseDTO advTypeResDTO = advTypeMap
.toAdvTypeResDTO(advTypeRepo.findAdvTypeByAdvType(advTypeName).orElseGet(() -> {
AdvanceTypeRequestDTO advTypeReqDTO = new AdvanceTypeRequestDTO(advTypeName);
return advTypeRepo.save(advTypeMap.toAdvTypeEnt(advTypeReqDTO));
}));
// Update simple fields
fileDataResDTO.setAdvTypeResDTO(advTypeResDTO);
fileDataResDTO.setVendName(vendName);
fileDataResDTO.setFundTypeResDTO(
fundTypeMap.toFundTypeResDTO(fundTypeRepo.findById(updFileReqDTO.getFundTypeId()).get()));
updateIfNotBlank(fileDataResDTO::setFileRmrk, updFileReqDTO.getFileRmrk());
updateIfNotNull(fileDataResDTO::setPiAmt, updFileReqDTO.getPiAmt());
updateIfNotNull(fileDataResDTO::setFiAmt, updFileReqDTO.getFiAmt());
updateIfNotNull(fileDataResDTO::setBalAmt, updFileReqDTO.getBalAmt());
// Simple files (no dates)
Map<String, MultipartFile> simpleFiles = new HashMap<String, MultipartFile>();
if (updFileReqDTO.getPoFile() != null) {
simpleFiles.put("PO", updFileReqDTO.getPoFile());
}
if (updFileReqDTO.getDcFile() != null) {
simpleFiles.put("DC", updFileReqDTO.getDcFile());
}
if (updFileReqDTO.getRtgsFile() != null) {
simpleFiles.put("RTGS", updFileReqDTO.getRtgsFile());
}
if (updFileReqDTO.getSrFile() != null) {
simpleFiles.put("SR", updFileReqDTO.getSrFile());
}
if (updFileReqDTO.getIrFile() != null) {
simpleFiles.put("IR", updFileReqDTO.getIrFile());
}
Map<String, Consumer<String>> simpleSetters = Map.of("PO", fileDataResDTO::setPoFilePath, "DC",
fileDataResDTO::setDcFilePath, "RTGS", fileDataResDTO::setRtgsFilePath, "SR",
fileDataResDTO::setSrFilePath, "IR", fileDataResDTO::setIrFilePath);
// Handle simple files
for (Map.Entry<String, MultipartFile> entry : simpleFiles.entrySet()) {
handleFileUpload(fileNum, entry.getKey(), null, entry.getValue(), simpleSetters.get(entry.getKey()),
uploadedFiles);
}
// Complex files (with dates)
Map<String, MultipartFile> complexFiles = new HashMap<String, MultipartFile>();
if (updFileReqDTO.getAsFile() != null) {
complexFiles.put("AS", updFileReqDTO.getAsFile());
}
if (updFileReqDTO.getPiFile() != null) {
complexFiles.put("PI", updFileReqDTO.getPiFile());
}
if (updFileReqDTO.getFiFile() != null) {
complexFiles.put("FI", updFileReqDTO.getFiFile());
}
if (updFileReqDTO.getAsFinalFile() != null) {
complexFiles.put("AS-Final", updFileReqDTO.getAsFinalFile());
}
if (updFileReqDTO.getTcFile() != null) {
complexFiles.put("TC", updFileReqDTO.getTcFile());
}
Map<String, Date> currentDates = new HashMap<String, Date>();
if (fileDataResDTO.getAsFileGenDate() != null) {
currentDates.put("AS", fileDataResDTO.getAsFileGenDate());
}
if (fileDataResDTO.getPiFileGenDate() != null) {
currentDates.put("PI", fileDataResDTO.getPiFileGenDate());
}
if (fileDataResDTO.getFiFileGenDate() != null) {
currentDates.put("FI", fileDataResDTO.getFiFileGenDate());
}
if (fileDataResDTO.getAsFinalFileGenDate() != null) {
currentDates.put("AS-Final", fileDataResDTO.getAsFinalFileGenDate());
}
if (fileDataResDTO.getTcFileGenDate() != null) {
currentDates.put("TC", fileDataResDTO.getTcFileGenDate());
}
Map<String, Date> newDates = new HashMap<String, Date>();
if (updFileReqDTO.getAsFileGenDate() != null) {
newDates.put("AS", updFileReqDTO.getAsFileGenDate());
}
if (updFileReqDTO.getPiFileGenDate() != null) {
newDates.put("PI", updFileReqDTO.getPiFileGenDate());
}
if (updFileReqDTO.getFiFileGenDate() != null) {
newDates.put("FI", updFileReqDTO.getFiFileGenDate());
}
if (updFileReqDTO.getAsFinalFileGenDate() != null) {
newDates.put("AS-Final", updFileReqDTO.getAsFinalFileGenDate());
}
if (updFileReqDTO.getTcFileGenDate() != null) {
newDates.put("TC", updFileReqDTO.getTcFileGenDate());
}
Map<String, Consumer<String>> pathSetters = Map.of("AS", fileDataResDTO::setAsFilePath, "PI",
fileDataResDTO::setPiFilePath, "FI", fileDataResDTO::setFiFilePath, "AS-Final",
fileDataResDTO::setAsFinalFilePath, "TC", fileDataResDTO::setTcFilePath);
Map<String, Consumer<Date>> dateSetters = Map.of("AS", fileDataResDTO::setAsFileGenDate, "PI",
fileDataResDTO::setPiFileGenDate, "FI", fileDataResDTO::setFiFileGenDate, "AS-Final",
fileDataResDTO::setAsFinalFileGenDate, "TC", fileDataResDTO::setTcFileGenDate);
// Handle complex files
for (String type : currentDates.keySet()) {
Date dateToUse = firstNonNull(newDates.get(type), currentDates.get(type));
dateSetters.get(type).accept(dateToUse);
handleFileUpload(fileNum, type, dateToUse, getFileByType(updFileReqDTO, type), pathSetters.get(type),
uploadedFiles);
}
// Save updated entity
fileDataRepo.save(fileDataMap.toFileDataEnt(fileDataResDTO));
return new ServiceResponseDTO(true, "File updated successfully.");
} catch (IOException ioe) {
logger.error("Exception occurred in file upload part: {}", ioe.getMessage(), ioe);
ioe.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false,
"Failed to update the file. Error in file upload: " + ioe.getMessage());
} catch (Exception e) {
logger.error("Exception occurred: {}", e.getMessage(), e);
e.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to update the file. Error: " + e.getMessage());
}
}
@Transactional(rollbackFor = Exception.class)
public ServiceResponseDTO updEjvNum(String fileNum, MultipartFile ejvNumFile, String ejvNum) {
List<String> uploadedFiles = new ArrayList<String>(); // Track uploaded files
try {
fileNum = fileNum.trim();
ejvNum = ejvNum.trim();
// 1️. Find existing FileData
FileDataResponseDTO fileDataResDTO = fileDataMap
.toFileDataResDTO(fileDataRepo.findFileDataByFileDataNum(fileNum));
if (fileDataResDTO == null) {
return new ServiceResponseDTO(false, "File not found for file number: " + fileNum);
}
// 2️. Update fields
fileDataResDTO.setEjvNum(ejvNum);
fileDataResDTO.setEjvNumFileGenDate(new Date());
// 3️. Handle file upload
if (ejvNumFile != null && !ejvNumFile.isEmpty()) {
handleFileUpload(fileNum, "EJV-Number", fileDataResDTO.getEjvNumFileGenDate(), ejvNumFile,
fileDataResDTO::setEjvNumFilePath, uploadedFiles);
}
// 4️. Save updated entity
fileDataRepo.save(fileDataMap.toFileDataEnt(fileDataResDTO));
return new ServiceResponseDTO(true, "Updated the EJV Number successfully.");
} catch (IOException ioe) {
logger.error("Exception occurred in file upload part: {}", ioe.getMessage(), ioe);
ioe.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false,
"Failed to update the EJV Number. Error in file upload: " + ioe.getMessage());
} catch (Exception e) {
logger.error("Exception occurred: {}", e.getMessage(), e);
e.printStackTrace();
cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to update the EJV Number. Error: " + e.getMessage());
}
}
@Transactional(readOnly = true)
public List<AdvanceTypeResponseDTO> getAllAdvTypes() {
// TODO Auto-generated method stub
return advTypeRepo.findAll().stream().map(advTypeMap::toAdvTypeResDTO).toList();
}
@Transactional(readOnly = true)
public List<FundTypeResponseDTO> getAllFundTypes() {
// TODO Auto-generated method stub
return fundTypeRepo.findAll().stream().map(fundTypeMap::toFundTypeResDTO).toList();
}
@Transactional(readOnly = true)
public Long getAllAdjustFileData() {
return fileDataRepo.findAll().stream()
.filter(fileDatum -> fileDatum.getEjvNum() != null && fileDatum.getEjvNumFilePath() != null
&& !fileDatum.getEjvNum().trim().equals("-")
&& !fileDatum.getEjvNumFilePath().trim().equals("-"))
.count();
}
@Transactional(readOnly = true)
public Long getAllNotAdjustFileData() {
return fileDataRepo.findAll().stream().filter(fileDatum -> fileDatum.getEjvNum() != null
&& fileDatum.getEjvNumFilePath() != null
&& (fileDatum.getEjvNum().trim().equals("-") || fileDatum.getEjvNumFilePath().trim().equals("-")))
.count();
}
@Transactional(readOnly = true)
public Long getAllItcFileData() {
return fileDataRepo.findAll().stream().filter(fileDatum -> fileDatum.getFileDataNum() != null
&& fileDatum.getFileDataNum().toUpperCase().contains("I.T.C")).count();
}
@Transactional(readOnly = true)
public Long getAllEdpFileData() {
return fileDataRepo.findAll().stream().filter(fileDatum -> fileDatum.getFileDataNum() != null
&& fileDatum.getFileDataNum().toUpperCase().contains("E.D.P")).count();
}
}

119
src/main/java/com/adjustment_file_management_system/springboot/service/FolderService.java

@ -0,0 +1,119 @@
package com.adjustment_file_management_system.springboot.service;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.adjustment_file_management_system.springboot.configuration.FileDataProperties;
import com.adjustment_file_management_system.springboot.configuration.FileDataPropertiesConfiguration;
import jakarta.annotation.PostConstruct;
@Service
public class FolderService {
private static final Logger logger = LoggerFactory.getLogger(FolderService.class);
@Autowired
private FileDataPropertiesConfiguration fileDataPropsConfig;
@Autowired
private FileDataProperties fileDataProps;
private Path fullUploadPath;
@PostConstruct
public void init() throws IOException {
// Initialize absolute upload path after config is ready
fullUploadPath = fileDataPropsConfig.getUploadDirFile().toPath();
Files.createDirectories(fullUploadPath);
}
/**
* Save uploaded file in a structured directory:
* uploads/file-data/{fileNum}/{category}/{category-year.extension}
*
* @param fileNum File number (e.g., I.T.C.C.NO.C1/240/2024)
* @param fileType Category (AS, PI, RTGS)
* @param genDate Generation date for naming (if null, current date is used)
* @param file The uploaded MultipartFile
* @return relative path (for DB)
*/
public String saveFile(String fileNum, String fileType, Date genDate, MultipartFile file) throws IOException {
// Build target directory under the absolute upload path
Path targetDir = fullUploadPath.resolve(fileNum).resolve(fileType);
Files.createDirectories(targetDir);
// Extract file extension
String originalName = file.getOriginalFilename();
String extension = "";
String baseName = "file"; // Fallback name
if (originalName != null && originalName.contains(".")) {
int dotIndex = originalName.lastIndexOf(".");
if (dotIndex >= 0) {
extension = originalName.substring(dotIndex); // Includes dot
baseName = originalName.substring(0, dotIndex); // Name without extension
} else {
baseName = originalName;
}
}
/**
* Sanitize the base name by removing leading/trailing spaces, replacing spaces
* with underscore and removing special characters except _ and -
**/
baseName = baseName.trim().replaceAll("\\s+", "_").replaceAll("[^a-zA-Z0-9_\\-]", "");
// Use provided date or fallback to current date
Calendar cal = Calendar.getInstance();
if (genDate != null) {
cal.setTime(genDate);
}
int year = cal.get(Calendar.YEAR);
// Build new filename: originalname-filetype-year.extension
String newFileName = baseName + "-" + fileType.toLowerCase() + "-" + year + extension;
// Save file
Path targetPath = targetDir.resolve(newFileName);
file.transferTo(targetPath.toFile());
logger.info("Saved file to {}", targetPath.toAbsolutePath());
// Return relative path to store in DB
return "/"
+ Paths.get(fileDataProps.getUploadDir(), fileNum, fileType, newFileName).toString().replace("\\", "/");
}
/**
* Utility method to safely delete a file.
*/
public void deleteFileIfExists(String filePath) {
if (filePath != null && !filePath.equals("-")) {
try {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
if (file.delete()) {
logger.info("Deleted orphan file: {}", filePath);
} else {
logger.warn("Failed to delete orphan file: {}", filePath);
}
}
} catch (Exception ex) {
logger.error("Error while deleting file {}: {}", filePath, ex.getMessage(), ex);
}
}
}
}

64
src/main/java/com/adjustment_file_management_system/springboot/service/HomeService.java

@ -0,0 +1,64 @@
package com.adjustment_file_management_system.springboot.service;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.adjustment_file_management_system.springboot.model.AppUser;
import com.adjustment_file_management_system.springboot.repository.AppUserRepository;
import com.adjustment_file_management_system.springboot.repository.FileDataRepository;
@Service
public class HomeService implements UserDetailsService {
@Autowired
private AppUserRepository appUsrRepo;
@Autowired
private FileDataRepository fileDataRepo;
@Autowired
private FileDataService fileDataSer;
private static final Logger logger = LoggerFactory.getLogger(HomeService.class);
@Override
public UserDetails loadUserByUsername(String usrName) throws UsernameNotFoundException {
logger.info("Loading user: {}", usrName);
Optional<AppUser> optAppUsr = appUsrRepo.findByUsrName(usrName);
AppUser appUsr = optAppUsr
.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + usrName));
// Uses Bcrypt for password verification
UserDetails userDetails = User.withUsername(appUsr.getUsrName()).password(appUsr.getUsrPass())
.authorities(appUsr.getUsrRole().getUsrRoleName()).build();
return userDetails;
}
public Map<String, Long> getFileDataStat() {
Map<String, Long> fileDatumStat = new HashMap<String, Long>();
Long totFileDatum = fileDataRepo.count();
Long totAdjustFileDatum = fileDataSer.getAllAdjustFileData();
Long totNotAdjustFileDatum = fileDataSer.getAllNotAdjustFileData();
Long totItcFileDatum = fileDataSer.getAllItcFileData();
Long totEdpFileDatum = fileDataSer.getAllEdpFileData();
fileDatumStat.put("totFile", totFileDatum);
fileDatumStat.put("totAdjustFile", totAdjustFileDatum);
fileDatumStat.put("totNotAdjustFile", totNotAdjustFileDatum);
fileDatumStat.put("totItcFile", totItcFileDatum);
fileDatumStat.put("totEdpFile", totEdpFileDatum);
return fileDatumStat;
}
}

12
src/main/resources/META-INF/additional-spring-configuration-metadata.json

@ -0,0 +1,12 @@
{"properties": [
{
"name": "file.data.upload-dir",
"type": "java.lang.String",
"description": "Folder or Directory where all the uploaded files are stored"
},
{
"name": "app.security.force-https",
"type": "java.lang.String",
"description": "Enables Forcing of HTTPS for CSRF"
}
]}

48
src/main/resources/application.properties

@ -0,0 +1,48 @@
spring.application.name=adjustment_file_management_system
server.port=8190
server.address=0.0.0.0
# 30 minutes
server.servlet.session.timeout=30m
# ===============================
# Oracle Database Configuration
# ===============================
# Production DB server
# spring.datasource.url=jdbc:oracle:thin:@10.1.0.14:1521:chncorp
# spring.datasource.username=fileadjust
# spring.datasource.password=fileadjust
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
# Local DB server
# spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/XEPDB1
# spring.datasource.username=gcc
# spring.datasource.password=product
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
# ===============================
# JPA / Hibernate Config
# ===============================
# spring.jpa.database-platform=org.hibernate.dialect.OracleDialect
# spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# spring.jpa.properties.hibernate.format_sql=true
spring.jpa.open-in-view=true
logging.level.org.hibernate.SQL=DEBUG
# logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.hibernate.type.descriptor.sql=TRACE
# Directory/Folder to store uploaded files (can be used anywhere in the app using @Value or Environment)
# Relative path inside project root
file.data.upload-dir=uploads/file-data/
# Max file size (single file)
spring.servlet.multipart.max-file-size=100MB
# Max request size (total request size including multiple files)
spring.servlet.multipart.max-request-size=400MB
# To enable forced HTTPS for CSRF (false for dev/testing and https is disabled, true for production only if https is enabled)
# (can be used anywhere in the app using @Value or Environment)
app.security.force-https=${FORCE_HTTPS:false}

33
src/main/resources/logback-spring.xml

@ -0,0 +1,33 @@
<configuration scan="true">
<!-- Read Spring property LOG_ROOT or default to 'logs' -->
<springProperty scope="context" name="LOG_DIR" source="LOG_ROOT" defaultValue="logs"/>
<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) [%thread] %logger - %msg%n</pattern>
</encoder>
</appender>
<!-- File Appender with Daily Rolling -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender" prudent="true">
<!-- Current log File -->
<file>${LOG_DIR}/app-logs.txt</file>
<!-- Rolling policy -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Log file per day -->
<fileNamePattern>${LOG_DIR}/app-logs.%d{yyyy-MM-dd}.txt</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger - %msg%n</pattern>
</encoder>
</appender>
<!-- Root logger: Log everything -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>

11794
src/main/resources/static/bootstrap-5.3.2/css/bootstrap.min.css
File diff suppressed because it is too large
View File

2212
src/main/resources/static/bootstrap-5.3.2/js/bootstrap.min.js
File diff suppressed because it is too large
View File

192
src/main/resources/static/css/body-form-styles.css

@ -0,0 +1,192 @@
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background: linear-gradient(45deg, #f6f7fb, #4ca3b3);
background-repeat: no-repeat;
}
.form-title {
text-align: center;
margin-bottom: 20px;
font-size: 1.8rem;
color: #003366;
text-decoration: underline;
}
.header-row {
display: flex;
align-items: center;
gap: 20px;
margin-bottom: 20px;
}
.back-button {
background-color: white;
border: 2px solid black !important;
border-radius: 4px;
padding: 10px 20px;
border-radius: 5px;
font-size: 16px;
position: relative; /* override absolute */
color: #005f73;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
}
.back-button:hover {
background: #4ca3b3;
transform: scale(1.05);
color: #000000;
}
.back-to-home-btn {
background-color: white;
border: 2px solid black !important;
border-radius: 4px;
padding: 10px 20px;
border-radius: 5px;
font-size: 16px;
position: relative; /* override absolute */
color: #005f73;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
}
.back-to-home-btn:hover {
background: #4ca3b3;
transform: scale(1.05);
color: #000000;
}
.required {
color: red;
font-weight: bold;
}
.container {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
h2 {
color: #0B3954;
margin-bottom: 30px;
}
.form-container {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 20px;
display: flex;
flex-direction: column;
}
.form-group label {
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
.form-control {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.file-input {
display: flex;
gap: 10px;
}
.file-input button {
background: #f0f0f0;
border: none;
padding: 8px 15px;
border-radius: 4px;
}
.radio-group {
display: flex;
gap: 20px;
}
.radio-option {
display: flex;
align-items: center;
gap: 5px;
}
.submit-btn {
display: flex;
justify-content: center;
margin-top: 20px;
}
.submit-btn input[type="submit"]:disabled {
background-color: #cccccc; /* grey color */
color: #666666;
cursor: not-allowed;
}
.submit-btn input[type="submit"] {
background-color: #005f73;
color: #fff;
font-size: 1rem;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s ease;
}
.submit-btn input[type="submit"]:hover {
background: #005f05;
}
/* Responsive Design for Tablets */
@media ( max-width : 768px) {
.form-row {
grid-template-columns: 1fr;
}
.form-container {
padding: 20px;
}
.form-title {
font-size: 1.5rem;
}
.form-control {
font-size: 1rem;
}
}
/* Responsive Design for Mobile */
@media ( max-width : 480px) {
.form-row {
grid-template-columns: 1fr;
}
.submit-btn input[type="submit"] {
width: 100%;
font-size: 1.2rem;
padding: 12px;
}
.form-container {
padding: 15px;
}
.form-title {
font-size: 1.2rem;
}
}

12
src/main/resources/static/css/btn-secondary-styles.css

@ -0,0 +1,12 @@
.btn-secondary {
background-color: white !important;
color: black !important;
border: 2px solid black !important;
padding: 5px 10px;
border-radius: 4px;
}
.btn-secondary:hover {
background-color: #6c757d !important;
color: white !important;
}

98
src/main/resources/static/css/datatable-styles.css

@ -0,0 +1,98 @@
#custom-info {
display: flex;
align-items: center;
}
#custom-length {
display: flex;
align-items: center;
gap: 8px; /* Add spacing between dropdown and label */
white-space: nowrap; /* Prevent wrapping */
}
.dataTables_length label {
display: flex;
align-items: center;
margin: 0;
gap: 5px; /* Adjust spacing between text and dropdown */
}
.dataTables_length select {
display: inline-block;
width: auto; /* Ensure dropdown adjusts to content */
}
#custom-pagination {
display: flex;
justify-content: flex-end; /* Align pagination to the right */
align-items: center;
}
.dataTables_filter {
display: none;
}
/* Apply border-radius to the table */
.det-table {
width: 125%;
border-collapse: separate;
border-spacing: 0;
border: 2px solid #f0f0f0;
margin-top: 20px;
font-family: Arial, sans-serif;
font-size: 14px;
table-layout: auto;
border-radius: 12px;
overflow: hidden;
}
.det-table th, .det-table td {
border: 1px solid #e0e0e0;
padding: 12px;
text-align: center;
}
.det-table td.no-word-wrap {
white-space: nowrap;
}
.det-table th {
background-color: #005f73;
color: white;
text-align: center;
}
.det-table tr:nth-child(even) {
background-color: #f9f9f9;
}
.det-table tr:hover {
background-color: #f1f1f1;
}
.det-table th, .det-table td {
text-align: center;
}
.view-btn {
background-color: #005f73;
color: white;
padding: 5px 10px;
border: none;
border-radius: 4px;
}
.view-btn:hover {
background-color: #005f05;
}
@media (max-width: 767.98px) {
.btn-group {
width: 100%;
justify-content: center;
}
.btn-group .btn {
width: 48%; /* make buttons fill container nicely */
margin: 1px;
}
}

77
src/main/resources/static/css/header-styles.css

@ -0,0 +1,77 @@
.header {
background-color: #005f73;
padding: 10px 20px;
display: flex;
align-items: center;
/* justify-content: space-between; */
position: relative;
color: white;
}
.header .logo-left img {
height: 60px;
width: 60px;
margin-right: 10px;
}
.header .title {
text-align: center;
/* flex-grow: 1; */
position: absolute;
transform: translateX(-50%);
left: 50%
}
.header .title h2 {
margin: 0;
font-size: 1.5rem;
}
.header .logos-right img {
height: 60px;
margin-left: 10px;
}
.header .logo-left {
display: flex;
align-items: center;
}
.header .logo-text {
display: flex;
flex-direction: column;
line-height: 1;
}
.header .logo-text h2 {
margin: 0;
font-size: 0.8rem;
color: white;
font-weight: bold;
}
.header .logo-text p {
margin: 0;
font-size: 0.5rem;
color: white;
}
@media ( max-width : 480px) {
.header {
flex-direction: column;
align-items: flex-start;
position: relative;
}
.header .logo-left img {
margin-bottom: 10px;
}
.header .logos-right img {
margin-bottom: 10px;
}
.header .title {
position: static; /* Reset absolute positioning */
transform: none; /* Remove the translate effect */
margin-top: 10px;
text-align: center; /* Ensure the text stays centered */
}
}

40
src/main/resources/static/css/home-styles.css

@ -0,0 +1,40 @@
.button-row {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 20px;
}
.stats {
color: #005f73;
font-weight: bold;
}
.custom-button {
padding: 15px 30px;
background: white;
border: 1px solid #ccc;
border-radius: 10px;
font-size: 1rem;
color: #005f73;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.custom-button:hover {
background: #4ca3b3;
transform: scale(1.05);
color: #000000;
}
.custom-button:active {
transform: scale(0.95);
}
@media (max-width : 768px) {
.button-row {
flex-direction: column;
gap: 20px;
}
}

272
src/main/resources/static/css/login-form-styles.css

@ -0,0 +1,272 @@
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 100;
src: url("/poppins-23.0/fonts/devanagari/poppins-v23-devanagari-700.woff2") format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 200;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-200.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 300;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-300.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-regular.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-500.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-600.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
src: url("../poppins-23.0/fonts/devanagari/poppins-v23-devanagari-700.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 100;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-100.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 200;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-200.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 300;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-300.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-regular.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-500.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-600.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
src: url("../poppins-23.0/fonts/latin-ext/poppins-v23-latin-ext-700.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 100;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-100.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 200;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-200.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 300;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-300.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-regular.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-500.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
src: url("../poppins-23.0/fonts/latin/poppins-v23-latin-600.woff2")
format("woff2");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
src: url("/poppins-23.0/fonts/latin/poppins-v23-latin-700.woff2")
format("woff2");
}
* {
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
background: linear-gradient(45deg, #f6f7fb, #4ca3b3);
background-repeat: no-repeat;
min-height: 100vh;
min-width: 100vw;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
margin: 0;
padding: 0;
}
div.container {
background: white;
min-width: 320px;
min-height: 33vh;
padding: 2rem;
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
div h2 {
font-weight: 600;
margin-bottom: 2rem;
position: relative;
}
.container h3,
.container h4 {
text-align: center;
}
div h2::before {
content: "";
position: absolute;
height: 4px;
width: 25px;
bottom: 3px;
left: 0;
border-radius: 8px;
background: #005f73;
}
form {
display: flex;
flex-direction: column;
}
.input-field {
position: relative;
margin-bottom: 1.5rem; /* instead of targeting only first-child */
}
.input-field .underline::before {
content: "";
position: absolute;
height: 1px;
width: 100%;
bottom: -5px;
left: 0;
background: rgba(0, 0, 0, 0.2);
}
.input-field .underline::after {
content: "";
position: absolute;
height: 1px;
width: 100%;
bottom: -5px;
left: 0;
background: linear-gradient(45deg, #8e2de2, #4a00e0);
transform: scaleX(0);
transition: all 0.3s ease-in-out;
transform-origin: left;
}
.input-field input:focus ~ .underline::after {
transform: scaleX(1);
}
.input-field input {
outline: none;
font-size: 0.9rem;
color: rgba(0, 0, 0, 0.7);
width: 100%;
}
.input-field input::placeholder {
color: rgba(0, 0, 0, 0.5);
}
form input[type="submit"] {
margin-top: 2rem;
padding: 0.4rem;
width: 100%;
background: #005f73;
cursor: pointer;
color: white;
font-size: 0.9rem;
font-weight: 300;
border-radius: 4px;
transition: all 0.3s ease;
}
form input[type="submit"]:hover {
letter-spacing: 0.5px;
background: #005f05;
}
.small-logo {
width: 60px;
height: 60px;
display: block;
margin: 0 auto; /* Centers the image */
}

58
src/main/resources/static/css/view-file-detail-styles.css

@ -0,0 +1,58 @@
.table-header {
background-color: #003366;
color: white;
}
.table-bordered th, .table-bordered td {
border: 1px solid #003366;
}
/* Make the cell a flex container so its contents are perfectly centered */
.table-bordered td.status-cell {
display: flex;
align-items: center; /* vertical center */
justify-content: center; /* horizontal center */
padding: 8px; /* adjust if you want taller rows */
vertical-align: middle; /* fallback */
}
.status-active,
.status-expired {
display: inline-flex; /* let the badge size to content */
align-items: center;
justify-content: center;
padding: 6px 12px; /* pill padding */
border-radius: 20px; /* pill */
font-size: 14px;
font-weight: 700;
line-height: 1;
min-height: 32px; /* ensures nice vertical size */
margin: 0; /* remove margins that push it off-center */
white-space: nowrap;
}
.fas.fa-eye {
background-color: white;
color: black;
}
.fas.fa-eye:hover {
color: #6c757d;
}
.pdf-container {
width: 100%;
height: 80vh; /* Responsive height: 80% of viewport height */
overflow-y: auto;
}
canvas {
width: 100% !important; /* Ensures canvas scales with container */
height: auto !important;
}
@media ( max-width : 768px) {
.responsive-text {
font-size: 0.9rem;
}
}

60
src/main/resources/static/css/view-file-styles.css

@ -0,0 +1,60 @@
.table-header {
background-color: #003366;
color: white;
}
.table-bordered th, .table-bordered td {
border: 1px solid #003366;
}
/* Make the cell a flex container so its contents are perfectly centered */
.table-bordered td.status-cell {
display: flex;
align-items: center; /* vertical center */
justify-content: center; /* horizontal center */
padding: 8px; /* adjust if you want taller rows */
vertical-align: middle; /* fallback */
}
.status-active,
.status-expired {
display: inline-flex; /* let the badge size to content */
align-items: center;
justify-content: center;
padding: 6px 12px; /* pill padding */
border-radius: 20px; /* pill */
font-size: 14px;
font-weight: 700;
line-height: 1;
min-height: 32px; /* ensures nice vertical size */
margin: 0; /* remove margins that push it off-center */
white-space: nowrap;
}
.pdf-container {
width: 100%;
height: 80vh; /* Responsive height: 80% of viewport height */
overflow-y: auto;
}
/* Colors (use contrast-friendly text color) */
.status-active {
background-color: #28a745;
color: black
}
.status-expired {
background-color: #dc3545;
color: black
}
canvas {
width: 100% !important; /* Ensures canvas scales with container */
height: auto !important;
}
@media ( max-width : 768px) {
.responsive-text {
font-size: 0.9rem;
}
}

532
src/main/resources/static/datatables-1.13.6/css/dataTables.bootstrap5.min.css

@ -0,0 +1,532 @@
:root {
--dt-row-selected: 13, 110, 253;
--dt-row-selected-text: 255, 255, 255;
--dt-row-selected-link: 9, 10, 11;
--dt-row-stripe: 0, 0, 0;
--dt-row-hover: 0, 0, 0;
--dt-column-ordering: 0, 0, 0;
--dt-html-background: white;
}
:root.dark {
--dt-html-background: rgb(33, 37, 41);
}
table.dataTable td.dt-control {
text-align: center;
cursor: pointer;
}
table.dataTable td.dt-control:before {
display: inline-block;
color: rgba(0, 0, 0, 0.5);
content: "►";
}
table.dataTable tr.dt-hasChild td.dt-control:before {
content: "▼";
}
html.dark table.dataTable td.dt-control:before {
color: rgba(255, 255, 255, 0.5);
}
html.dark table.dataTable tr.dt-hasChild td.dt-control:before {
color: rgba(255, 255, 255, 0.5);
}
table.dataTable thead > tr > th.sorting,
table.dataTable thead > tr > th.sorting_asc,
table.dataTable thead > tr > th.sorting_desc,
table.dataTable thead > tr > th.sorting_asc_disabled,
table.dataTable thead > tr > th.sorting_desc_disabled,
table.dataTable thead > tr > td.sorting,
table.dataTable thead > tr > td.sorting_asc,
table.dataTable thead > tr > td.sorting_desc,
table.dataTable thead > tr > td.sorting_asc_disabled,
table.dataTable thead > tr > td.sorting_desc_disabled {
cursor: pointer;
position: relative;
padding-right: 26px;
}
table.dataTable thead > tr > th.sorting:before,
table.dataTable thead > tr > th.sorting:after,
table.dataTable thead > tr > th.sorting_asc:before,
table.dataTable thead > tr > th.sorting_asc:after,
table.dataTable thead > tr > th.sorting_desc:before,
table.dataTable thead > tr > th.sorting_desc:after,
table.dataTable thead > tr > th.sorting_asc_disabled:before,
table.dataTable thead > tr > th.sorting_asc_disabled:after,
table.dataTable thead > tr > th.sorting_desc_disabled:before,
table.dataTable thead > tr > th.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting:before,
table.dataTable thead > tr > td.sorting:after,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_asc:after,
table.dataTable thead > tr > td.sorting_desc:before,
table.dataTable thead > tr > td.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_asc_disabled:after,
table.dataTable thead > tr > td.sorting_desc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:after {
position: absolute;
display: block;
opacity: 0.125;
right: 10px;
line-height: 9px;
font-size: 0.8em;
}
table.dataTable thead > tr > th.sorting:before,
table.dataTable thead > tr > th.sorting_asc:before,
table.dataTable thead > tr > th.sorting_desc:before,
table.dataTable thead > tr > th.sorting_asc_disabled:before,
table.dataTable thead > tr > th.sorting_desc_disabled:before,
table.dataTable thead > tr > td.sorting:before,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_desc:before,
table.dataTable thead > tr > td.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:before {
bottom: 50%;
content: "▲";
content: "▲"/"";
}
table.dataTable thead > tr > th.sorting:after,
table.dataTable thead > tr > th.sorting_asc:after,
table.dataTable thead > tr > th.sorting_desc:after,
table.dataTable thead > tr > th.sorting_asc_disabled:after,
table.dataTable thead > tr > th.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting:after,
table.dataTable thead > tr > td.sorting_asc:after,
table.dataTable thead > tr > td.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc_disabled:after,
table.dataTable thead > tr > td.sorting_desc_disabled:after {
top: 50%;
content: "▼";
content: "▼"/"";
}
table.dataTable thead > tr > th.sorting_asc:before,
table.dataTable thead > tr > th.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_desc:after {
opacity: 0.6;
}
table.dataTable thead > tr > th.sorting_desc_disabled:after,
table.dataTable thead > tr > th.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting_asc_disabled:before {
display: none;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
outline: none;
}
div.dataTables_scrollBody > table.dataTable > thead > tr > th:before,
div.dataTables_scrollBody > table.dataTable > thead > tr > th:after,
div.dataTables_scrollBody > table.dataTable > thead > tr > td:before,
div.dataTables_scrollBody > table.dataTable > thead > tr > td:after {
display: none;
}
div.dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
margin-left: -100px;
margin-top: -26px;
text-align: center;
padding: 2px;
}
div.dataTables_processing > div:last-child {
position: relative;
width: 80px;
height: 15px;
margin: 1em auto;
}
div.dataTables_processing > div:last-child > div {
position: absolute;
top: 0;
width: 13px;
height: 13px;
border-radius: 50%;
background: rgb(13, 110, 253);
background: rgb(var(--dt-row-selected));
animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
div.dataTables_processing > div:last-child > div:nth-child(1) {
left: 8px;
animation: datatables-loader-1 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(2) {
left: 8px;
animation: datatables-loader-2 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(3) {
left: 32px;
animation: datatables-loader-2 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(4) {
left: 56px;
animation: datatables-loader-3 0.6s infinite;
}
@keyframes datatables-loader-1 {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes datatables-loader-3 {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes datatables-loader-2 {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(24px, 0);
}
}
table.dataTable.nowrap th,
table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable th.dt-left,
table.dataTable td.dt-left {
text-align: left;
}
table.dataTable th.dt-center,
table.dataTable td.dt-center,
table.dataTable td.dataTables_empty {
text-align: center;
}
table.dataTable th.dt-right,
table.dataTable td.dt-right {
text-align: right;
}
table.dataTable th.dt-justify,
table.dataTable td.dt-justify {
text-align: justify;
}
table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap {
white-space: nowrap;
}
table.dataTable thead th,
table.dataTable thead td,
table.dataTable tfoot th,
table.dataTable tfoot td {
text-align: left;
}
table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left,
table.dataTable tfoot td.dt-head-left {
text-align: left;
}
table.dataTable thead th.dt-head-center,
table.dataTable thead td.dt-head-center,
table.dataTable tfoot th.dt-head-center,
table.dataTable tfoot td.dt-head-center {
text-align: center;
}
table.dataTable thead th.dt-head-right,
table.dataTable thead td.dt-head-right,
table.dataTable tfoot th.dt-head-right,
table.dataTable tfoot td.dt-head-right {
text-align: right;
}
table.dataTable thead th.dt-head-justify,
table.dataTable thead td.dt-head-justify,
table.dataTable tfoot th.dt-head-justify,
table.dataTable tfoot td.dt-head-justify {
text-align: justify;
}
table.dataTable thead th.dt-head-nowrap,
table.dataTable thead td.dt-head-nowrap,
table.dataTable tfoot th.dt-head-nowrap,
table.dataTable tfoot td.dt-head-nowrap {
white-space: nowrap;
}
table.dataTable tbody th.dt-body-left,
table.dataTable tbody td.dt-body-left {
text-align: left;
}
table.dataTable tbody th.dt-body-center,
table.dataTable tbody td.dt-body-center {
text-align: center;
}
table.dataTable tbody th.dt-body-right,
table.dataTable tbody td.dt-body-right {
text-align: right;
}
table.dataTable tbody th.dt-body-justify,
table.dataTable tbody td.dt-body-justify {
text-align: justify;
}
table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap;
} /*! Bootstrap 5 integration for DataTables
*
* ©2020 SpryMedia Ltd, all rights reserved.
* License: MIT datatables.net/license/mit
*/
table.dataTable {
clear: both;
margin-top: 6px !important;
margin-bottom: 6px !important;
max-width: none !important;
border-collapse: separate !important;
border-spacing: 0;
}
table.dataTable td,
table.dataTable th {
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
table.dataTable td.dataTables_empty,
table.dataTable th.dataTables_empty {
text-align: center;
}
table.dataTable.nowrap th,
table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable.table-striped > tbody > tr:nth-of-type(2n + 1) > * {
box-shadow: none;
}
table.dataTable > tbody > tr {
background-color: transparent;
}
table.dataTable > tbody > tr.selected > * {
box-shadow: inset 0 0 0 9999px rgb(13, 110, 253);
box-shadow: inset 0 0 0 9999px rgb(var(--dt-row-selected));
color: rgb(255, 255, 255);
color: rgb(var(--dt-row-selected-text));
}
table.dataTable > tbody > tr.selected a {
color: rgb(9, 10, 11);
color: rgb(var(--dt-row-selected-link));
}
table.dataTable.table-striped > tbody > tr.odd > * {
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.05);
}
table.dataTable.table-striped > tbody > tr.odd.selected > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95);
}
table.dataTable.table-hover > tbody > tr:hover > * {
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.075);
}
table.dataTable.table-hover > tbody > tr.selected:hover > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975);
}
div.dataTables_wrapper div.dataTables_length label {
font-weight: normal;
text-align: left;
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_length select {
width: auto;
display: inline-block;
}
div.dataTables_wrapper div.dataTables_filter {
text-align: right;
}
div.dataTables_wrapper div.dataTables_filter label {
font-weight: normal;
white-space: nowrap;
text-align: left;
}
div.dataTables_wrapper div.dataTables_filter input {
margin-left: 0.5em;
display: inline-block;
width: auto;
}
div.dataTables_wrapper div.dataTables_info {
padding-top: 0.85em;
}
div.dataTables_wrapper div.dataTables_paginate {
margin: 0;
white-space: nowrap;
text-align: right;
}
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
margin: 2px 0;
white-space: nowrap;
justify-content: flex-end;
}
div.dataTables_wrapper div.dt-row {
position: relative;
}
div.dataTables_scrollHead table.dataTable {
margin-bottom: 0 !important;
}
div.dataTables_scrollBody > table {
border-top: none;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
div.dataTables_scrollBody > table > thead .sorting:before,
div.dataTables_scrollBody > table > thead .sorting_asc:before,
div.dataTables_scrollBody > table > thead .sorting_desc:before,
div.dataTables_scrollBody > table > thead .sorting:after,
div.dataTables_scrollBody > table > thead .sorting_asc:after,
div.dataTables_scrollBody > table > thead .sorting_desc:after {
display: none;
}
div.dataTables_scrollBody > table > tbody tr:first-child th,
div.dataTables_scrollBody > table > tbody tr:first-child td {
border-top: none;
}
div.dataTables_scrollFoot > .dataTables_scrollFootInner {
box-sizing: content-box;
}
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
margin-top: 0 !important;
border-top: none;
}
@media screen and (max-width: 767px) {
div.dataTables_wrapper div.dataTables_length,
div.dataTables_wrapper div.dataTables_filter,
div.dataTables_wrapper div.dataTables_info,
div.dataTables_wrapper div.dataTables_paginate {
text-align: center;
}
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
justify-content: center !important;
}
}
table.dataTable.table-sm > thead > tr > th:not(.sorting_disabled) {
padding-right: 20px;
}
table.table-bordered.dataTable {
border-right-width: 0;
}
table.table-bordered.dataTable thead tr:first-child th,
table.table-bordered.dataTable thead tr:first-child td {
border-top-width: 1px;
}
table.table-bordered.dataTable th,
table.table-bordered.dataTable td {
border-left-width: 0;
}
table.table-bordered.dataTable th:first-child,
table.table-bordered.dataTable th:first-child,
table.table-bordered.dataTable td:first-child,
table.table-bordered.dataTable td:first-child {
border-left-width: 1px;
}
table.table-bordered.dataTable th:last-child,
table.table-bordered.dataTable th:last-child,
table.table-bordered.dataTable td:last-child,
table.table-bordered.dataTable td:last-child {
border-right-width: 1px;
}
table.table-bordered.dataTable th,
table.table-bordered.dataTable td {
border-bottom-width: 1px;
}
div.dataTables_scrollHead table.table-bordered {
border-bottom-width: 0;
}
div.table-responsive > div.dataTables_wrapper > div.row {
margin: 0;
}
div.table-responsive
> div.dataTables_wrapper
> div.row
> div[class^="col-"]:first-child {
padding-left: 0;
}
div.table-responsive
> div.dataTables_wrapper
> div.row
> div[class^="col-"]:last-child {
padding-right: 0;
}
:root[data-bs-theme="dark"] {
--dt-row-hover: 255, 255, 255;
--dt-row-stripe: 255, 255, 255;
--dt-column-ordering: 255, 255, 255;
}

80
src/main/resources/static/datatables-1.13.6/js/dataTables.bootstrap5.min.js

@ -0,0 +1,80 @@
/*! DataTables Bootstrap 5 integration
* 2020 SpryMedia Ltd - datatables.net/license
*/
! function(t) {
var n, r;
"function" == typeof define && define.amd ? define(["jquery", "datatables.net"], function(e) {
return t(e, window, document)
}) : "object" == typeof exports ? (n = require("jquery"), r = function(e, a) {
a.fn.dataTable || require("datatables.net")(e, a)
}, "undefined" == typeof window ? module.exports = function(e, a) {
return e = e || window, a = a || n(e), r(e, a), t(a, 0, e.document)
} : (r(window, n), module.exports = t(n, window, window.document))) : t(jQuery, window, document)
}(function(x, e, r, o) {
"use strict";
var i = x.fn.dataTable;
return x.extend(!0, i.defaults, {
dom: "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row dt-row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
renderer: "bootstrap"
}), x.extend(i.ext.classes, {
sWrapper: "dataTables_wrapper dt-bootstrap5",
sFilterInput: "form-control form-control-sm",
sLengthSelect: "form-select form-select-sm",
sProcessing: "dataTables_processing card",
sPageButton: "paginate_button page-item"
}), i.ext.renderer.pageButton.bootstrap = function(d, e, s, a, l, c) {
function u(e, a) {
for (var t, n, r = function(e) {
e.preventDefault(), x(e.currentTarget).hasClass("disabled") || b.page() == e.data.action || b.page(e.data.action).draw("page")
}, o = 0, i = a.length; o < i; o++)
if (t = a[o], Array.isArray(t)) u(e, t);
else {
switch (f = p = "", t) {
case "ellipsis":
p = "&#x2026;", f = "disabled";
break;
case "first":
p = g.sFirst, f = t + (0 < l ? "" : " disabled");
break;
case "previous":
p = g.sPrevious, f = t + (0 < l ? "" : " disabled");
break;
case "next":
p = g.sNext, f = t + (l < c - 1 ? "" : " disabled");
break;
case "last":
p = g.sLast, f = t + (l < c - 1 ? "" : " disabled");
break;
default:
p = t + 1, f = l === t ? "active" : ""
}
p && (n = -1 !== f.indexOf("disabled"), n = x("<li>", {
class: m.sPageButton + " " + f,
id: 0 === s && "string" == typeof t ? d.sTableId + "_" + t : null
}).append(x("<a>", {
href: n ? null : "#",
"aria-controls": d.sTableId,
"aria-disabled": n ? "true" : null,
"aria-label": w[t],
role: "link",
"aria-current": "active" === f ? "page" : null,
"data-dt-idx": t,
tabindex: n ? -1 : d.iTabIndex,
class: "page-link"
}).html(p)).appendTo(e), d.oApi._fnBindAction(n, {
action: t
}, r))
}
}
var p, f, t, b = new i.Api(d),
m = d.oClasses,
g = d.oLanguage.oPaginate,
w = d.oLanguage.oAria.paginate || {},
e = x(e);
try {
t = e.find(r.activeElement).data("dt-idx")
} catch (e) { }
var n = e.children("ul.pagination");
n.length ? n.empty() : n = e.html("<ul/>").children("ul").addClass("pagination"), u(n, a), t !== o && e.find("[data-dt-idx=" + t + "]").trigger("focus")
}, i
});

2990
src/main/resources/static/datatables-1.13.6/js/jquery.dataTables.min.js
File diff suppressed because it is too large
View File

248
src/main/resources/static/datatables-buttons-2.4.1/css/buttons.bootstrap5.min.css

@ -0,0 +1,248 @@
@keyframes dtb-spinner {
100% {
transform: rotate(360deg);
}
}
@-o-keyframes dtb-spinner {
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-ms-keyframes dtb-spinner {
100% {
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes dtb-spinner {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes dtb-spinner {
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
div.dataTables_wrapper {
position: relative;
}
div.dt-buttons {
position: initial;
}
div.dt-buttons .dt-button {
overflow: hidden;
text-overflow: ellipsis;
}
div.dt-button-info {
position: fixed;
top: 50%;
left: 50%;
width: 400px;
margin-top: -100px;
margin-left: -200px;
background-color: white;
border-radius: 0.75em;
box-shadow: 3px 4px 10px 1px rgba(0, 0, 0, 0.8);
text-align: center;
z-index: 2003;
overflow: hidden;
}
div.dt-button-info h2 {
padding: 2rem 2rem 1rem 2rem;
margin: 0;
font-weight: normal;
}
div.dt-button-info > div {
padding: 1em 2em 2em 2em;
}
div.dtb-popover-close {
position: absolute;
top: 6px;
right: 6px;
width: 22px;
height: 22px;
text-align: center;
border-radius: 3px;
cursor: pointer;
z-index: 2003;
}
button.dtb-hide-drop {
display: none !important;
}
div.dt-button-collection-title {
text-align: center;
padding: 0.3em 0 0.5em;
margin-left: 0.5em;
margin-right: 0.5em;
font-size: 0.9em;
}
div.dt-button-collection-title:empty {
display: none;
}
span.dt-button-spacer {
display: inline-block;
margin: 0.5em;
white-space: nowrap;
}
span.dt-button-spacer.bar {
border-left: 1px solid rgba(0, 0, 0, 0.3);
vertical-align: middle;
padding-left: 0.5em;
}
span.dt-button-spacer.bar:empty {
height: 1em;
width: 1px;
padding-left: 0;
}
div.dt-button-collection .dt-button-active {
padding-right: 3em;
}
div.dt-button-collection .dt-button-active:after {
position: absolute;
top: 50%;
margin-top: -10px;
right: 1em;
display: inline-block;
content: "✓";
color: inherit;
}
div.dt-button-collection .dt-button-active.dt-button-split {
padding-right: 0;
}
div.dt-button-collection .dt-button-active.dt-button-split:after {
display: none;
}
div.dt-button-collection .dt-button-active.dt-button-split > *:first-child {
padding-right: 3em;
}
div.dt-button-collection
.dt-button-active.dt-button-split
> *:first-child:after {
position: absolute;
top: 50%;
margin-top: -10px;
right: 1em;
display: inline-block;
content: "✓";
color: inherit;
}
div.dt-button-collection .dt-button-active-a a {
padding-right: 3em;
}
div.dt-button-collection .dt-button-active-a a:after {
position: absolute;
right: 1em;
display: inline-block;
content: "✓";
color: inherit;
}
div.dt-button-collection span.dt-button-spacer {
width: 100%;
font-size: 0.9em;
text-align: center;
margin: 0.5em 0;
}
div.dt-button-collection span.dt-button-spacer:empty {
height: 0;
width: 100%;
}
div.dt-button-collection span.dt-button-spacer.bar {
border-left: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding-left: 0;
}
html.dark div.dt-button-info {
background-color: var(--dt-html-background);
border: 1px solid rgba(255, 255, 255, 0.15);
}
div.dt-buttons div.btn-group {
position: initial;
}
div.dt-buttons div.dropdown-menu {
margin-top: 4px;
}
div.dt-buttons div.dropdown-menu .dt-button {
position: relative;
}
div.dt-buttons div.dropdown-menu div.dt-button-split {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: flex-start;
align-items: stretch;
}
div.dt-buttons div.dropdown-menu div.dt-button-split a:first-child {
min-width: auto;
flex: 1 0 50px;
padding-right: 0;
}
div.dt-buttons div.dropdown-menu div.dt-button-split button:last-child {
min-width: 33px;
flex: 0;
background: transparent;
border: none;
line-height: 1rem;
color: var(--bs-dropdown-link-color);
padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);
}
div.dt-buttons div.dropdown-menu div.dt-button-split button:last-child:hover {
color: var(--bs-dropdown-link-hover-color);
background-color: var(--bs-dropdown-link-hover-bg);
}
div.dt-buttons div.dropdown-menu div.dt-button-split button:last-child:after {
position: relative;
left: -3px;
}
div.dt-buttons span.dt-button-spacer.empty {
margin: 1px;
}
div.dt-buttons span.dt-button-spacer.bar:empty {
height: inherit;
}
div.dt-buttons .btn.processing {
color: rgba(0, 0, 0, 0.2);
}
div.dt-buttons .btn.processing:after {
position: absolute;
top: 50%;
left: 50%;
width: 16px;
height: 16px;
margin: -8px 0 0 -8px;
box-sizing: border-box;
display: block;
content: " ";
border: 2px solid rgb(40, 40, 40);
border-radius: 50%;
border-left-color: transparent;
border-right-color: transparent;
animation: dtb-spinner 1500ms infinite linear;
-o-animation: dtb-spinner 1500ms infinite linear;
-ms-animation: dtb-spinner 1500ms infinite linear;
-webkit-animation: dtb-spinner 1500ms infinite linear;
-moz-animation: dtb-spinner 1500ms infinite linear;
}
div.dt-button-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
@media screen and (max-width: 767px) {
div.dt-buttons {
float: none;
width: 100%;
text-align: center;
margin-bottom: 0.5em;
}
div.dt-buttons a.btn {
float: none;
}
}

70
src/main/resources/static/datatables-buttons-2.4.1/js/buttons.bootstrap5.min.js

@ -0,0 +1,70 @@
/*! Bootstrap integration for DataTables' Buttons
* © SpryMedia Ltd - datatables.net/license
*/
! function(o) {
var e, a;
"function" == typeof define && define.amd ? define(["jquery", "datatables.net-bs5", "datatables.net-buttons"], function(t) {
return o(t, window, document)
}) : "object" == typeof exports ? (e = require("jquery"), a = function(t, n) {
n.fn.dataTable || require("datatables.net-bs5")(t, n), n.fn.dataTable.Buttons || require("datatables.net-buttons")(t, n)
}, "undefined" == typeof window ? module.exports = function(t, n) {
return t = t || window, n = n || e(t), a(t, n), o(n, 0, t.document)
} : (a(window, e), module.exports = o(e, window, window.document))) : o(jQuery, window, document)
}(function(o, t, n, e) {
"use strict";
var a = o.fn.dataTable;
return o.extend(!0, a.Buttons.defaults, {
dom: {
container: {
className: "dt-buttons btn-group flex-wrap"
},
button: {
className: "btn btn-secondary",
active: "active"
},
collection: {
action: {
dropHtml: ""
},
container: {
tag: "div",
className: "dropdown-menu dt-button-collection"
},
closeButton: !1,
button: {
tag: "a",
className: "dt-button dropdown-item",
active: "dt-button-active",
disabled: "disabled",
spacer: {
className: "dropdown-divider",
tag: "hr"
}
}
},
split: {
action: {
tag: "a",
className: "btn btn-secondary dt-button-split-drop-button",
closeButton: !1
},
dropdown: {
tag: "button",
dropHtml: "",
className: "btn btn-secondary dt-button-split-drop dropdown-toggle dropdown-toggle-split",
closeButton: !1,
align: "split-left",
splitAlignClass: "dt-button-split-left"
},
wrapper: {
tag: "div",
className: "dt-button-split btn-group",
closeButton: !1
}
}
},
buttonCreated: function(t, n) {
return t.buttons ? o('<div class="btn-group"/>').append(n) : n
}
}), a.ext.buttons.collection.className += " dropdown-toggle", a.ext.buttons.collection.rightAlignClassName = "dropdown-menu-right", a
});

538
src/main/resources/static/datatables-buttons-2.4.1/js/buttons.html5.min.js
File diff suppressed because it is too large
View File

79
src/main/resources/static/datatables-buttons-2.4.1/js/buttons.print.min.js

@ -0,0 +1,79 @@
/*!
* Print button for Buttons and DataTables.
* © SpryMedia Ltd - datatables.net/license
*/
! function(n) {
var o, r;
"function" == typeof define && define.amd ? define(["jquery", "datatables.net", "datatables.net-buttons"], function(t) {
return n(t, window, document)
}) : "object" == typeof exports ? (o = require("jquery"), r = function(t, e) {
e.fn.dataTable || require("datatables.net")(t, e), e.fn.dataTable.Buttons || require("datatables.net-buttons")(t, e)
}, "undefined" == typeof window ? module.exports = function(t, e) {
return t = t || window, e = e || o(t), r(t, e), n(e, t, t.document)
} : (r(window, o), module.exports = n(o, window, window.document))) : n(jQuery, window, document)
}(function(m, b, t, p) {
"use strict";
function h(t) {
return n.href = t, -1 === (t = n.host).indexOf("/") && 0 !== n.pathname.indexOf("/") && (t += "/"), n.protocol + "//" + t + n.pathname + n.search
}
var e = m.fn.dataTable,
n = t.createElement("a");
return e.ext.buttons.print = {
className: "buttons-print",
text: function(t) {
return t.i18n("buttons.print", "Print")
},
action: function(t, e, n, o) {
function r(t, e) {
for (var n = "<tr>", o = 0, r = t.length; o < r; o++) {
var i = null === t[o] || t[o] === p ? "" : t[o];
n += "<" + e + " " + (s[o] ? 'class="' + s[o] + '"' : "") + ">" + i + "</" + e + ">"
}
return n + "</tr>"
}
var i = e.buttons.exportData(m.extend({
decodeEntities: !1
}, o.exportOptions)),
a = e.buttons.exportInfo(o),
s = e.columns(o.exportOptions.columns).flatten().map(function(t) {
return e.settings()[0].aoColumns[e.column(t).index()].sClass
}).toArray(),
u = '<table class="' + e.table().node().className + '">';
o.header && (u += "<thead>" + r(i.header, "th") + "</thead>"), u += "<tbody>";
for (var d = 0, c = i.body.length; d < c; d++) u += r(i.body[d], "td");
u += "</tbody>", o.footer && i.footer && (u += "<tfoot>" + r(i.footer, "th") + "</tfoot>"), u += "</table>";
var l = b.open("", "");
if (l) {
l.document.close();
var f = "<title>" + a.title + "</title>";
m("style, link").each(function() {
f += function(t) {
t = m(t).clone()[0];
return "link" === t.nodeName.toLowerCase() && (t.href = h(t.href)), t.outerHTML
}(this)
});
try {
l.document.head.innerHTML = f
} catch (t) {
m(l.document.head).html(f)
}
l.document.body.innerHTML = "<h1>" + a.title + "</h1><div>" + (a.messageTop || "") + "</div>" + u + "<div>" + (a.messageBottom || "") + "</div>", m(l.document.body).addClass("dt-print-view"), m("img", l.document.body).each(function(t, e) {
e.setAttribute("src", h(e.getAttribute("src")))
}), o.customize && o.customize(l, o, e);
a = function() {
o.autoPrint && (l.print(), l.close())
};
navigator.userAgent.match(/Trident\/\d.\d/) ? a() : l.setTimeout(a, 1e3)
} else e.buttons.info(e.i18n("buttons.printErrorTitle", "Unable to open print view"), e.i18n("buttons.printErrorMsg", "Please allow popups in your browser for this site to be able to view the print view."), 5e3)
},
title: "*",
messageTop: "*",
messageBottom: "*",
exportOptions: {},
header: !0,
footer: !1,
autoPrint: !0,
customize: null
}, e
});

764
src/main/resources/static/datatables-buttons-2.4.1/js/dataTables.buttons.min.js

@ -0,0 +1,764 @@
/*! Buttons for DataTables 2.4.1
* © SpryMedia Ltd - datatables.net/license
*/
! function(e) {
var o, i;
"function" == typeof define && define.amd ? define(["jquery", "datatables.net"], function(t) {
return e(t, window, document)
}) : "object" == typeof exports ? (o = require("jquery"), i = function(t, n) {
n.fn.dataTable || require("datatables.net")(t, n)
}, "undefined" == typeof window ? module.exports = function(t, n) {
return t = t || window, n = n || o(t), i(t, n), e(n, t, t.document)
} : (i(window, o), module.exports = e(o, window, window.document))) : e(jQuery, window, document)
}(function(y, v, x, w) {
"use strict";
var e = y.fn.dataTable,
o = 0,
C = 0,
_ = e.ext.buttons;
function A(t, n, e) {
y.fn.animate ? t.stop().fadeIn(n, e) : (t.css("display", "block"), e && e.call(t))
}
function k(t, n, e) {
y.fn.animate ? t.stop().fadeOut(n, e) : (t.css("display", "none"), e && e.call(t))
}
function B(n, t) {
if (!(this instanceof B)) return function(t) {
return new B(t, n).container()
};
!0 === (t = void 0 === t ? {} : t) && (t = {}), Array.isArray(t) && (t = {
buttons: t
}), this.c = y.extend(!0, {}, B.defaults, t), t.buttons && (this.c.buttons = t.buttons), this.s = {
dt: new e.Api(n),
buttons: [],
listenKeys: "",
namespace: "dtb" + o++
}, this.dom = {
container: y("<" + this.c.dom.container.tag + "/>").addClass(this.c.dom.container.className)
}, this._constructor()
}
y.extend(B.prototype, {
action: function(t, n) {
t = this._nodeToButton(t);
return n === w ? t.conf.action : (t.conf.action = n, this)
},
active: function(t, n) {
var t = this._nodeToButton(t),
e = this.c.dom.button.active,
o = y(t.node);
return t.inCollection && this.c.dom.collection.button && this.c.dom.collection.button.active !== w && (e = this.c.dom.collection.button.active), n === w ? o.hasClass(e) : (o.toggleClass(e, n === w || n), this)
},
add: function(t, n, e) {
var o = this.s.buttons;
if ("string" == typeof n) {
for (var i = n.split("-"), s = this.s, a = 0, r = i.length - 1; a < r; a++) s = s.buttons[+i[a]];
o = s.buttons, n = +i[i.length - 1]
}
return this._expandButton(o, t, t !== w ? t.split : w, (t === w || t.split === w || 0 === t.split.length) && s !== w, !1, n), e !== w && !0 !== e || this._draw(), this
},
collectionRebuild: function(t, n) {
var e = this._nodeToButton(t);
if (n !== w) {
for (var o = e.buttons.length - 1; 0 <= o; o--) this.remove(e.buttons[o].node);
for (e.conf.prefixButtons && n.unshift.apply(n, e.conf.prefixButtons), e.conf.postfixButtons && n.push.apply(n, e.conf.postfixButtons), o = 0; o < n.length; o++) {
var i = n[o];
this._expandButton(e.buttons, i, i !== w && i.config !== w && i.config.split !== w, !0, i.parentConf !== w && i.parentConf.split !== w, null, i.parentConf)
}
}
this._draw(e.collection, e.buttons)
},
container: function() {
return this.dom.container
},
disable: function(t) {
t = this._nodeToButton(t);
return y(t.node).addClass(this.c.dom.button.disabled).prop("disabled", !0), this
},
destroy: function() {
y("body").off("keyup." + this.s.namespace);
for (var t = this.s.buttons.slice(), n = 0, e = t.length; n < e; n++) this.remove(t[n].node);
this.dom.container.remove();
var o = this.s.dt.settings()[0];
for (n = 0, e = o.length; n < e; n++)
if (o.inst === this) {
o.splice(n, 1);
break
} return this
},
enable: function(t, n) {
return !1 === n ? this.disable(t) : (n = this._nodeToButton(t), y(n.node).removeClass(this.c.dom.button.disabled).prop("disabled", !1), this)
},
index: function(t, n, e) {
n || (n = "", e = this.s.buttons);
for (var o = 0, i = e.length; o < i; o++) {
var s = e[o].buttons;
if (e[o].node === t) return n + o;
if (s && s.length) {
s = this.index(t, o + "-", s);
if (null !== s) return s
}
}
return null
},
name: function() {
return this.c.name
},
node: function(t) {
return t ? (t = this._nodeToButton(t), y(t.node)) : this.dom.container
},
processing: function(t, n) {
var e = this.s.dt,
o = this._nodeToButton(t);
return n === w ? y(o.node).hasClass("processing") : (y(o.node).toggleClass("processing", n), y(e.table().node()).triggerHandler("buttons-processing.dt", [n, e.button(t), e, y(t), o.conf]), this)
},
remove: function(t) {
var n = this._nodeToButton(t),
e = this._nodeToHost(t),
o = this.s.dt;
if (n.buttons.length)
for (var i = n.buttons.length - 1; 0 <= i; i--) this.remove(n.buttons[i].node);
n.conf.destroying = !0, n.conf.destroy && n.conf.destroy.call(o.button(t), o, y(t), n.conf), this._removeKey(n.conf), y(n.node).remove();
o = y.inArray(n, e);
return e.splice(o, 1), this
},
text: function(t, n) {
function e(t) {
return "function" == typeof t ? t(i, s, o.conf) : t
}
var o = this._nodeToButton(t),
t = o.textNode,
i = this.s.dt,
s = y(o.node);
return n === w ? e(o.conf.text) : (o.conf.text = n, t.html(e(n)), this)
},
_constructor: function() {
var e = this,
t = this.s.dt,
o = t.settings()[0],
n = this.c.buttons;
o._buttons || (o._buttons = []), o._buttons.push({
inst: this,
name: this.c.name
});
for (var i = 0, s = n.length; i < s; i++) this.add(n[i]);
t.on("destroy", function(t, n) {
n === o && e.destroy()
}), y("body").on("keyup." + this.s.namespace, function(t) {
var n;
x.activeElement && x.activeElement !== x.body || (n = String.fromCharCode(t.keyCode).toLowerCase(), -1 !== e.s.listenKeys.toLowerCase().indexOf(n) && e._keypress(n, t))
})
},
_addKey: function(t) {
t.key && (this.s.listenKeys += (y.isPlainObject(t.key) ? t.key : t).key)
},
_draw: function(t, n) {
t || (t = this.dom.container, n = this.s.buttons), t.children().detach();
for (var e = 0, o = n.length; e < o; e++) t.append(n[e].inserter), t.append(" "), n[e].buttons && n[e].buttons.length && this._draw(n[e].collection, n[e].buttons)
},
_expandButton: function(t, n, e, o, i, s, a) {
for (var r, l = this.s.dt, c = this.c.dom.collection, u = Array.isArray(n) ? n : [n], d = 0, f = (u = n === w ? Array.isArray(e) ? e : [e] : u).length; d < f; d++) {
var p = this._resolveExtends(u[d]);
if (p)
if (r = !(!p.config || !p.config.split), Array.isArray(p)) this._expandButton(t, p, h !== w && h.conf !== w ? h.conf.split : w, o, a !== w && a.split !== w, s, a);
else {
var h = this._buildButton(p, o, p.split !== w || p.config !== w && p.config.split !== w, i);
if (h) {
if (s !== w && null !== s ? (t.splice(s, 0, h), s++) : t.push(h), h.conf.buttons && (h.collection = y("<" + c.container.content.tag + "/>"), h.conf._collection = h.collection, y(h.node).append(c.action.dropHtml), this._expandButton(h.buttons, h.conf.buttons, h.conf.split, !r, r, s, h.conf)), h.conf.split) {
h.collection = y("<" + c.container.tag + "/>"), h.conf._collection = h.collection;
for (var b = 0; b < h.conf.split.length; b++) {
var g = h.conf.split[b];
"object" == typeof g && (g.parent = a, g.collectionLayout === w && (g.collectionLayout = h.conf.collectionLayout), g.dropup === w && (g.dropup = h.conf.dropup), g.fade === w) && (g.fade = h.conf.fade)
}
this._expandButton(h.buttons, h.conf.buttons, h.conf.split, !r, r, s, h.conf)
}
h.conf.parent = a, p.init && p.init.call(l.button(h.node), l, y(h.node), p)
}
}
}
},
_buildButton: function(n, t, e, o) {
function i(t) {
return "function" == typeof t ? t(u, l, n) : t
}
var s, a, r, l, c = this.c.dom,
u = this.s.dt,
d = y.extend(!0, {}, c.button);
if (t && e && c.collection.split ? y.extend(!0, d, c.collection.split.action) : o || t ? y.extend(!0, d, c.collection.button) : e && y.extend(!0, d, c.split.button), n.spacer) return c = y("<" + d.spacer.tag + "/>").addClass("dt-button-spacer " + n.style + " " + d.spacer.className).html(i(n.text)), {
conf: n,
node: c,
inserter: c,
buttons: [],
inCollection: t,
isSplit: e,
collection: null,
textNode: c
};
if (n.available && !n.available(u, n) && !n.hasOwnProperty("html")) return !1;
n.hasOwnProperty("html") ? l = y(n.html) : (a = function(t, n, e, o) {
o.action.call(n.button(e), t, n, e, o), y(n.table().node()).triggerHandler("buttons-action.dt", [n.button(e), n, e, o])
}, c = n.tag || d.tag, r = n.clickBlurs === w || n.clickBlurs, l = y("<" + c + "/>").addClass(d.className).attr("tabindex", this.s.dt.settings()[0].iTabIndex).attr("aria-controls", this.s.dt.table().node().id).on("click.dtb", function(t) {
t.preventDefault(), !l.hasClass(d.disabled) && n.action && a(t, u, l, n), r && l.trigger("blur")
}).on("keypress.dtb", function(t) {
13 === t.keyCode && (t.preventDefault(), !l.hasClass(d.disabled)) && n.action && a(t, u, l, n)
}), "a" === c.toLowerCase() && l.attr("href", "#"), "button" === c.toLowerCase() && l.attr("type", "button"), s = d.liner.tag ? (c = y("<" + d.liner.tag + "/>").html(i(n.text)).addClass(d.liner.className), "a" === d.liner.tag.toLowerCase() && c.attr("href", "#"), l.append(c), c) : (l.html(i(n.text)), l), !1 === n.enabled && l.addClass(d.disabled), n.className && l.addClass(n.className), n.titleAttr && l.attr("title", i(n.titleAttr)), n.attr && l.attr(n.attr), n.namespace || (n.namespace = ".dt-button-" + C++), n.config !== w && n.config.split && (n.split = n.config.split));
var f, p, h, b, g, m, c = this.c.dom.buttonContainer,
c = c && c.tag ? y("<" + c.tag + "/>").addClass(c.className).append(l) : l;
return this._addKey(n), this.c.buttonCreated && (c = this.c.buttonCreated(n, c)), e && (p = (f = t ? y.extend(!0, this.c.dom.split, this.c.dom.collection.split) : this.c.dom.split).wrapper, h = y("<" + p.tag + "/>").addClass(p.className).append(l), b = y.extend(n, {
align: f.dropdown.align,
attr: {
"aria-haspopup": "dialog",
"aria-expanded": !1
},
className: f.dropdown.className,
closeButton: !1,
splitAlignClass: f.dropdown.splitAlignClass,
text: f.dropdown.text
}), this._addKey(b), g = function(t, n, e, o) {
_.split.action.call(n.button(h), t, n, e, o), y(n.table().node()).triggerHandler("buttons-action.dt", [n.button(e), n, e, o]), e.attr("aria-expanded", !0)
}, m = y('<button class="' + f.dropdown.className + ' dt-button"></button>').html(f.dropdown.dropHtml).on("click.dtb", function(t) {
t.preventDefault(), t.stopPropagation(), m.hasClass(d.disabled) || g(t, u, m, b), r && m.trigger("blur")
}).on("keypress.dtb", function(t) {
13 === t.keyCode && (t.preventDefault(), m.hasClass(d.disabled) || g(t, u, m, b))
}), 0 === n.split.length && m.addClass("dtb-hide-drop"), h.append(m).attr(b.attr)), {
conf: n,
node: (e ? h : l).get(0),
inserter: e ? h : c,
buttons: [],
inCollection: t,
isSplit: e,
inSplit: o,
collection: null,
textNode: s
}
},
_nodeToButton: function(t, n) {
for (var e = 0, o = (n = n || this.s.buttons).length; e < o; e++) {
if (n[e].node === t) return n[e];
if (n[e].buttons.length) {
var i = this._nodeToButton(t, n[e].buttons);
if (i) return i
}
}
},
_nodeToHost: function(t, n) {
for (var e = 0, o = (n = n || this.s.buttons).length; e < o; e++) {
if (n[e].node === t) return n;
if (n[e].buttons.length) {
var i = this._nodeToHost(t, n[e].buttons);
if (i) return i
}
}
},
_keypress: function(s, a) {
var r;
a._buttonsHandled || (r = function(t) {
for (var n, e, o = 0, i = t.length; o < i; o++) n = t[o].conf, e = t[o].node, !n.key || n.key !== s && (!y.isPlainObject(n.key) || n.key.key !== s || n.key.shiftKey && !a.shiftKey || n.key.altKey && !a.altKey || n.key.ctrlKey && !a.ctrlKey || n.key.metaKey && !a.metaKey) || (a._buttonsHandled = !0, y(e).click()), t[o].buttons.length && r(t[o].buttons)
})(this.s.buttons)
},
_removeKey: function(t) {
var n;
t.key && (t = (y.isPlainObject(t.key) ? t.key : t).key, n = this.s.listenKeys.split(""), t = y.inArray(t, n), n.splice(t, 1), this.s.listenKeys = n.join(""))
},
_resolveExtends: function(e) {
function t(t) {
for (var n = 0; !y.isPlainObject(t) && !Array.isArray(t);) {
if (t === w) return;
if ("function" == typeof t) {
if (!(t = t.call(i, s, e))) return !1
} else if ("string" == typeof t) {
if (!_[t]) return {
html: t
};
t = _[t]
}
if (30 < ++n) throw "Buttons: Too many iterations"
}
return Array.isArray(t) ? t : y.extend({}, t)
}
var n, o, i = this,
s = this.s.dt;
for (e = t(e); e && e.extend;) {
if (!_[e.extend]) throw "Cannot extend unknown button type: " + e.extend;
var a = t(_[e.extend]);
if (Array.isArray(a)) return a;
if (!a) return !1;
var r = a.className;
e.config !== w && a.config !== w && (e.config = y.extend({}, a.config, e.config)), e = y.extend({}, a, e), r && e.className !== r && (e.className = r + " " + e.className), e.extend = a.extend
}
var l = e.postfixButtons;
if (l)
for (e.buttons || (e.buttons = []), n = 0, o = l.length; n < o; n++) e.buttons.push(l[n]);
var c = e.prefixButtons;
if (c)
for (e.buttons || (e.buttons = []), n = 0, o = c.length; n < o; n++) e.buttons.splice(n, 0, c[n]);
return e
},
_popover: function(o, t, n, e) {
function i() {
h = !0, k(y(g), b.fade, function() {
y(this).detach()
}), y(f.buttons('[aria-haspopup="dialog"][aria-expanded="true"]').nodes()).attr("aria-expanded", "false"), y("div.dt-button-background").off("click.dtb-collection"), B.background(!1, b.backgroundClassName, b.fade, m), y(v).off("resize.resize.dtb-collection"), y("body").off(".dtb-collection"), f.off("buttons-action.b-internal"), f.off("destroy")
}
var s, a, r, l, c, u, d, f = t,
p = this.c,
h = !1,
b = y.extend({
align: "button-left",
autoClose: !1,
background: !0,
backgroundClassName: "dt-button-background",
closeButton: !0,
containerClassName: p.dom.collection.container.className,
contentClassName: p.dom.collection.container.content.className,
collectionLayout: "",
collectionTitle: "",
dropup: !1,
fade: 400,
popoverTitle: "",
rightAlignClassName: "dt-button-right",
tag: p.dom.collection.container.tag
}, n),
g = b.tag + "." + b.containerClassName.replace(/ /g, "."),
m = t.node();
!1 === o ? i() : ((p = y(f.buttons('[aria-haspopup="dialog"][aria-expanded="true"]').nodes())).length && (m.closest(g).length && (m = p.eq(0)), i()), n = y(".dt-button", o).length, p = "", 3 === n ? p = "dtb-b3" : 2 === n ? p = "dtb-b2" : 1 === n && (p = "dtb-b1"), s = y("<" + b.tag + "/>").addClass(b.containerClassName).addClass(b.collectionLayout).addClass(b.splitAlignClass).addClass(p).css("display", "none").attr({
"aria-modal": !0,
role: "dialog"
}), o = y(o).addClass(b.contentClassName).attr("role", "menu").appendTo(s), m.attr("aria-expanded", "true"), m.parents("body")[0] !== x.body && (m = x.body.lastChild), b.popoverTitle ? s.prepend('<div class="dt-button-collection-title">' + b.popoverTitle + "</div>") : b.collectionTitle && s.prepend('<div class="dt-button-collection-title">' + b.collectionTitle + "</div>"), b.closeButton && s.prepend('<div class="dtb-popover-close">&times;</div>').addClass("dtb-collection-closeable"), A(s.insertAfter(m), b.fade), n = y(t.table().container()), d = s.css("position"), "container" !== b.span && "dt-container" !== b.align || (m = m.parent(), s.css("width", n.width())), "absolute" === d ? (p = y(m[0].offsetParent), t = m.position(), n = m.offset(), a = p.offset(), r = p.position(), l = v.getComputedStyle(p[0]), a.height = p.outerHeight(), a.width = p.width() + parseFloat(l.paddingLeft), a.right = a.left + a.width, a.bottom = a.top + a.height, p = t.top + m.outerHeight(), c = t.left, s.css({
top: p,
left: c
}), l = v.getComputedStyle(s[0]), (u = s.offset()).height = s.outerHeight(), u.width = s.outerWidth(), u.right = u.left + u.width, u.bottom = u.top + u.height, u.marginTop = parseFloat(l.marginTop), u.marginBottom = parseFloat(l.marginBottom), b.dropup && (p = t.top - u.height - u.marginTop - u.marginBottom), "button-right" !== b.align && !s.hasClass(b.rightAlignClassName) || (c = t.left - u.width + m.outerWidth()), "dt-container" !== b.align && "container" !== b.align || (c = c < t.left ? -t.left : c) + u.width > a.width && (c = a.width - u.width), r.left + c + u.width > y(v).width() && (c = y(v).width() - u.width - r.left), n.left + c < 0 && (c = -n.left), r.top + p + u.height > y(v).height() + y(v).scrollTop() && (p = t.top - u.height - u.marginTop - u.marginBottom), r.top + p < y(v).scrollTop() && (p = t.top + m.outerHeight()), s.css({
top: p,
left: c
})) : ((d = function() {
var t = y(v).height() / 2,
n = s.height() / 2;
s.css("marginTop", -1 * (n = t < n ? t : n))
})(), y(v).on("resize.dtb-collection", function() {
d()
})), b.background && B.background(!0, b.backgroundClassName, b.fade, b.backgroundHost || m), y("div.dt-button-background").on("click.dtb-collection", function() { }), b.autoClose && setTimeout(function() {
f.on("buttons-action.b-internal", function(t, n, e, o) {
o[0] !== m[0] && i()
})
}, 0), y(s).trigger("buttons-popover.dt"), f.on("destroy", i), setTimeout(function() {
h = !1, y("body").on("click.dtb-collection", function(t) {
var n, e;
!h && (n = y.fn.addBack ? "addBack" : "andSelf", e = y(t.target).parent()[0], !y(t.target).parents()[n]().filter(o).length && !y(e).hasClass("dt-buttons") || y(t.target).hasClass("dt-button-background")) && i()
}).on("keyup.dtb-collection", function(t) {
27 === t.keyCode && i()
}).on("keydown.dtb-collection", function(t) {
var n = y("a, button", o),
e = x.activeElement;
9 === t.keyCode && (-1 === n.index(e) ? (n.first().focus(), t.preventDefault()) : t.shiftKey ? e === n[0] && (n.last().focus(), t.preventDefault()) : e === n.last()[0] && (n.first().focus(), t.preventDefault()))
})
}, 0))
}
}), B.background = function(t, n, e, o) {
e === w && (e = 400), o = o || x.body, t ? A(y("<div/>").addClass(n).css("display", "none").insertAfter(o), e) : k(y("div." + n), e, function() {
y(this).removeClass(n).remove()
})
}, B.instanceSelector = function(t, i) {
var s, a, r;
return t === w || null === t ? y.map(i, function(t) {
return t.inst
}) : (s = [], a = y.map(i, function(t) {
return t.name
}), (r = function(t) {
var n;
if (Array.isArray(t))
for (var e = 0, o = t.length; e < o; e++) r(t[e]);
else "string" == typeof t ? -1 !== t.indexOf(",") ? r(t.split(",")) : -1 !== (n = y.inArray(t.trim(), a)) && s.push(i[n].inst) : "number" == typeof t ? s.push(i[t].inst) : "object" == typeof t && s.push(t)
})(t), s)
}, B.buttonSelector = function(t, n) {
for (var c = [], u = function(t, n, e) {
for (var o, i, s = 0, a = n.length; s < a; s++)(o = n[s]) && (t.push({
node: o.node,
name: o.conf.name,
idx: i = e !== w ? e + s : s + ""
}), o.buttons) && u(t, o.buttons, i + "-")
}, d = function(t, n) {
var e = [],
o = (u(e, n.s.buttons), y.map(e, function(t) {
return t.node
}));
if (Array.isArray(t) || t instanceof y)
for (s = 0, a = t.length; s < a; s++) d(t[s], n);
else if (null === t || t === w || "*" === t)
for (s = 0, a = e.length; s < a; s++) c.push({
inst: n,
node: e[s].node
});
else if ("number" == typeof t) n.s.buttons[t] && c.push({
inst: n,
node: n.s.buttons[t].node
});
else if ("string" == typeof t)
if (-1 !== t.indexOf(","))
for (var i = t.split(","), s = 0, a = i.length; s < a; s++) d(i[s].trim(), n);
else if (t.match(/^\d+(\-\d+)*$/)) {
var r = y.map(e, function(t) {
return t.idx
});
c.push({
inst: n,
node: e[y.inArray(t, r)].node
})
} else if (-1 !== t.indexOf(":name")) {
var l = t.replace(":name", "");
for (s = 0, a = e.length; s < a; s++) e[s].name === l && c.push({
inst: n,
node: e[s].node
})
} else y(o).filter(t).each(function() {
c.push({
inst: n,
node: this
})
});
else "object" == typeof t && t.nodeName && -1 !== (r = y.inArray(t, o)) && c.push({
inst: n,
node: o[r]
})
}, e = 0, o = t.length; e < o; e++) {
var i = t[e];
d(n, i)
}
return c
}, B.stripData = function(t, n) {
return "string" == typeof t && (t = (t = t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")).replace(/<!\-\-.*?\-\->/g, ""), n && !n.stripHtml || (t = t.replace(/<[^>]*>/g, "")), n && !n.trim || (t = t.replace(/^\s+|\s+$/g, "")), n && !n.stripNewlines || (t = t.replace(/\n/g, " ")), !n || n.decodeEntities) && (l.innerHTML = t, t = l.value), t
}, B.defaults = {
buttons: ["copy", "excel", "csv", "pdf", "print"],
name: "main",
tabIndex: 0,
dom: {
container: {
tag: "div",
className: "dt-buttons"
},
collection: {
action: {
dropHtml: '<span class="dt-button-down-arrow">&#x25BC;</span>'
},
container: {
className: "dt-button-collection",
content: {
className: "",
tag: "div"
},
tag: "div"
}
},
button: {
tag: "button",
className: "dt-button",
active: "dt-button-active",
disabled: "disabled",
spacer: {
className: "dt-button-spacer",
tag: "span"
},
liner: {
tag: "span",
className: ""
}
},
split: {
action: {
className: "dt-button-split-drop-button dt-button",
tag: "button"
},
dropdown: {
align: "split-right",
className: "dt-button-split-drop",
dropHtml: '<span class="dt-button-down-arrow">&#x25BC;</span>',
splitAlignClass: "dt-button-split-left",
tag: "button"
},
wrapper: {
className: "dt-button-split",
tag: "div"
}
}
}
}, y.extend(_, {
collection: {
text: function(t) {
return t.i18n("buttons.collection", "Collection")
},
className: "buttons-collection",
closeButton: !(B.version = "2.4.1"),
init: function(t, n, e) {
n.attr("aria-expanded", !1)
},
action: function(t, n, e, o) {
o._collection.parents("body").length ? this.popover(!1, o) : this.popover(o._collection, o), "keypress" === t.type && y("a, button", o._collection).eq(0).focus()
},
attr: {
"aria-haspopup": "dialog"
}
},
split: {
text: function(t) {
return t.i18n("buttons.split", "Split")
},
className: "buttons-split",
closeButton: !1,
init: function(t, n, e) {
return n.attr("aria-expanded", !1)
},
action: function(t, n, e, o) {
this.popover(o._collection, o)
},
attr: {
"aria-haspopup": "dialog"
}
},
copy: function(t, n) {
if (_.copyHtml5) return "copyHtml5"
},
csv: function(t, n) {
if (_.csvHtml5 && _.csvHtml5.available(t, n)) return "csvHtml5"
},
excel: function(t, n) {
if (_.excelHtml5 && _.excelHtml5.available(t, n)) return "excelHtml5"
},
pdf: function(t, n) {
if (_.pdfHtml5 && _.pdfHtml5.available(t, n)) return "pdfHtml5"
},
pageLength: function(t) {
var n = t.settings()[0].aLengthMenu,
e = [],
o = [];
if (Array.isArray(n[0])) e = n[0], o = n[1];
else
for (var i = 0; i < n.length; i++) {
var s = n[i];
y.isPlainObject(s) ? (e.push(s.value), o.push(s.label)) : (e.push(s), o.push(s))
}
return {
extend: "collection",
text: function(t) {
return t.i18n("buttons.pageLength", {
"-1": "Show all rows",
_: "Show %d rows"
}, t.page.len())
},
className: "buttons-page-length",
autoClose: !0,
buttons: y.map(e, function(s, t) {
return {
text: o[t],
className: "button-page-length",
action: function(t, n) {
n.page.len(s).draw()
},
init: function(t, n, e) {
function o() {
i.active(t.page.len() === s)
}
var i = this;
t.on("length.dt" + e.namespace, o), o()
},
destroy: function(t, n, e) {
t.off("length.dt" + e.namespace)
}
}
}),
init: function(t, n, e) {
var o = this;
t.on("length.dt" + e.namespace, function() {
o.text(e.text)
})
},
destroy: function(t, n, e) {
t.off("length.dt" + e.namespace)
}
}
},
spacer: {
style: "empty",
spacer: !0,
text: function(t) {
return t.i18n("buttons.spacer", "")
}
}
}), e.Api.register("buttons()", function(n, e) {
e === w && (e = n, n = w), this.selector.buttonGroup = n;
var t = this.iterator(!0, "table", function(t) {
if (t._buttons) return B.buttonSelector(B.instanceSelector(n, t._buttons), e)
}, !0);
return t._groupSelector = n, t
}), e.Api.register("button()", function(t, n) {
t = this.buttons(t, n);
return 1 < t.length && t.splice(1, t.length), t
}), e.Api.registerPlural("buttons().active()", "button().active()", function(n) {
return n === w ? this.map(function(t) {
return t.inst.active(t.node)
}) : this.each(function(t) {
t.inst.active(t.node, n)
})
}), e.Api.registerPlural("buttons().action()", "button().action()", function(n) {
return n === w ? this.map(function(t) {
return t.inst.action(t.node)
}) : this.each(function(t) {
t.inst.action(t.node, n)
})
}), e.Api.registerPlural("buttons().collectionRebuild()", "button().collectionRebuild()", function(e) {
return this.each(function(t) {
for (var n = 0; n < e.length; n++) "object" == typeof e[n] && (e[n].parentConf = t);
t.inst.collectionRebuild(t.node, e)
})
}), e.Api.register(["buttons().enable()", "button().enable()"], function(n) {
return this.each(function(t) {
t.inst.enable(t.node, n)
})
}), e.Api.register(["buttons().disable()", "button().disable()"], function() {
return this.each(function(t) {
t.inst.disable(t.node)
})
}), e.Api.register("button().index()", function() {
var n = null;
return this.each(function(t) {
t = t.inst.index(t.node);
null !== t && (n = t)
}), n
}), e.Api.registerPlural("buttons().nodes()", "button().node()", function() {
var n = y();
return y(this.each(function(t) {
n = n.add(t.inst.node(t.node))
})), n
}), e.Api.registerPlural("buttons().processing()", "button().processing()", function(n) {
return n === w ? this.map(function(t) {
return t.inst.processing(t.node)
}) : this.each(function(t) {
t.inst.processing(t.node, n)
})
}), e.Api.registerPlural("buttons().text()", "button().text()", function(n) {
return n === w ? this.map(function(t) {
return t.inst.text(t.node)
}) : this.each(function(t) {
t.inst.text(t.node, n)
})
}), e.Api.registerPlural("buttons().trigger()", "button().trigger()", function() {
return this.each(function(t) {
t.inst.node(t.node).trigger("click")
})
}), e.Api.register("button().popover()", function(n, e) {
return this.map(function(t) {
return t.inst._popover(n, this.button(this[0].node), e)
})
}), e.Api.register("buttons().containers()", function() {
var i = y(),
s = this._groupSelector;
return this.iterator(!0, "table", function(t) {
if (t._buttons)
for (var n = B.instanceSelector(s, t._buttons), e = 0, o = n.length; e < o; e++) i = i.add(n[e].container())
}), i
}), e.Api.register("buttons().container()", function() {
return this.containers().eq(0)
}), e.Api.register("button().add()", function(t, n, e) {
var o = this.context;
return o.length && (o = B.instanceSelector(this._groupSelector, o[0]._buttons)).length && o[0].add(n, t, e), this.button(this._groupSelector, t)
}), e.Api.register("buttons().destroy()", function() {
return this.pluck("inst").unique().each(function(t) {
t.destroy()
}), this
}), e.Api.registerPlural("buttons().remove()", "buttons().remove()", function() {
return this.each(function(t) {
t.inst.remove(t.node)
}), this
}), e.Api.register("buttons.info()", function(t, n, e) {
var o = this;
return !1 === t ? (this.off("destroy.btn-info"), k(y("#datatables_buttons_info"), 400, function() {
y(this).remove()
}), clearTimeout(i), i = null) : (i && clearTimeout(i), y("#datatables_buttons_info").length && y("#datatables_buttons_info").remove(), t = t ? "<h2>" + t + "</h2>" : "", A(y('<div id="datatables_buttons_info" class="dt-button-info"/>').html(t).append(y("<div/>")["string" == typeof n ? "html" : "append"](n)).css("display", "none").appendTo("body")), e !== w && 0 !== e && (i = setTimeout(function() {
o.buttons.info(!1)
}, e)), this.on("destroy.btn-info", function() {
o.buttons.info(!1)
})), this
}), e.Api.register("buttons.exportData()", function(t) {
if (this.context.length) return c(new e.Api(this.context[0]), t)
}), e.Api.register("buttons.exportInfo()", function(t) {
return {
filename: n(t = t || {}),
title: a(t),
messageTop: r(this, t.message || t.messageTop, "top"),
messageBottom: r(this, t.messageBottom, "bottom")
}
});
var i, n = function(t) {
var n;
return (n = "function" == typeof (n = "*" === t.filename && "*" !== t.title && t.title !== w && null !== t.title && "" !== t.title ? t.title : t.filename) ? n() : n) === w || null === n ? null : (n = (n = -1 !== n.indexOf("*") ? n.replace("*", y("head > title").text()).trim() : n).replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "")) + (s(t.extension) || "")
},
s = function(t) {
return null === t || t === w ? null : "function" == typeof t ? t() : t
},
a = function(t) {
t = s(t.title);
return null === t ? null : -1 !== t.indexOf("*") ? t.replace("*", y("head > title").text() || "Exported data") : t
},
r = function(t, n, e) {
n = s(n);
return null === n ? null : (t = y("caption", t.table().container()).eq(0), "*" === n ? t.css("caption-side") !== e ? null : t.length ? t.text() : "" : n)
},
l = y("<textarea/>")[0],
c = function(e, t) {
for (var o = y.extend(!0, {}, {
rows: null,
columns: "",
modifier: {
search: "applied",
order: "applied"
},
orthogonal: "display",
stripHtml: !0,
stripNewlines: !0,
decodeEntities: !0,
trim: !0,
format: {
header: function(t) {
return B.stripData(t, o)
},
footer: function(t) {
return B.stripData(t, o)
},
body: function(t) {
return B.stripData(t, o)
}
},
customizeData: null
}, t), t = e.columns(o.columns).indexes().map(function(t) {
var n = e.column(t).header();
return o.format.header(n.innerHTML, t, n)
}).toArray(), n = e.table().footer() ? e.columns(o.columns).indexes().map(function(t) {
var n = e.column(t).footer();
return o.format.footer(n ? n.innerHTML : "", t, n)
}).toArray() : null, i = y.extend({}, o.modifier), i = (e.select && "function" == typeof e.select.info && i.selected === w && e.rows(o.rows, y.extend({
selected: !0
}, i)).any() && y.extend(i, {
selected: !0
}), e.rows(o.rows, i).indexes().toArray()), i = e.cells(i, o.columns), s = i.render(o.orthogonal).toArray(), a = i.nodes().toArray(), r = t.length, l = [], c = 0, u = 0, d = 0 < r ? s.length / r : 0; u < d; u++) {
for (var f = [r], p = 0; p < r; p++) f[p] = o.format.body(s[c], u, p, a[c]), c++;
l[u] = f
}
i = {
header: t,
footer: n,
body: l
};
return o.customizeData && o.customizeData(i), i
};
function t(t, n) {
t = new e.Api(t), n = n || t.init().buttons || e.defaults.buttons;
return new B(t, n).container()
}
return y.fn.dataTable.Buttons = B, y.fn.DataTable.Buttons = B, y(x).on("init.dt plugin-init.dt", function(t, n) {
"dt" === t.namespace && (t = n.oInit.buttons || e.defaults.buttons) && !n._buttons && new B(n, t).container()
}), e.ext.feature.push({
fnInit: t,
cFeature: "B"
}), e.ext.features && e.ext.features.register("buttons", t), e
});

793
src/main/resources/static/flatpickr-4.6.13/css/flatpickr.min.css

@ -0,0 +1,793 @@
.flatpickr-calendar {
background: transparent;
opacity: 0;
display: none;
text-align: center;
visibility: hidden;
padding: 0;
-webkit-animation: none;
animation: none;
direction: ltr;
border: 0;
font-size: 14px;
line-height: 24px;
border-radius: 5px;
position: absolute;
width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-touch-action: manipulation;
touch-action: manipulation;
background: #fff;
-webkit-box-shadow: 1px 0 0 #e6e6e6, -1px 0 0 #e6e6e6, 0 1px 0 #e6e6e6,
0 -1px 0 #e6e6e6, 0 3px 13px rgba(0, 0, 0, 0.08);
box-shadow: 1px 0 0 #e6e6e6, -1px 0 0 #e6e6e6, 0 1px 0 #e6e6e6,
0 -1px 0 #e6e6e6, 0 3px 13px rgba(0, 0, 0, 0.08);
}
.flatpickr-calendar.open,
.flatpickr-calendar.inline {
opacity: 1;
max-height: 640px;
visibility: visible;
}
.flatpickr-calendar.open {
display: inline-block;
z-index: 99999;
}
.flatpickr-calendar.animate.open {
-webkit-animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.flatpickr-calendar.inline {
display: block;
position: relative;
top: 2px;
}
.flatpickr-calendar.static {
position: absolute;
top: calc(100% + 2px);
}
.flatpickr-calendar.static.open {
z-index: 999;
display: block;
}
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 1)
.flatpickr-day.inRange:nth-child(7n + 7) {
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 2)
.flatpickr-day.inRange:nth-child(7n + 1) {
-webkit-box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
}
.flatpickr-calendar .hasWeeks .dayContainer,
.flatpickr-calendar .hasTime .dayContainer {
border-bottom: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.flatpickr-calendar .hasWeeks .dayContainer {
border-left: 0;
}
.flatpickr-calendar.hasTime .flatpickr-time {
height: 40px;
border-top: 1px solid #e6e6e6;
}
.flatpickr-calendar.noCalendar.hasTime .flatpickr-time {
height: auto;
}
.flatpickr-calendar:before,
.flatpickr-calendar:after {
position: absolute;
display: block;
pointer-events: none;
border: solid transparent;
content: "";
height: 0;
width: 0;
left: 22px;
}
.flatpickr-calendar.rightMost:before,
.flatpickr-calendar.arrowRight:before,
.flatpickr-calendar.rightMost:after,
.flatpickr-calendar.arrowRight:after {
left: auto;
right: 22px;
}
.flatpickr-calendar.arrowCenter:before,
.flatpickr-calendar.arrowCenter:after {
left: 50%;
right: 50%;
}
.flatpickr-calendar:before {
border-width: 5px;
margin: 0 -5px;
}
.flatpickr-calendar:after {
border-width: 4px;
margin: 0 -4px;
}
.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after {
bottom: 100%;
}
.flatpickr-calendar.arrowTop:before {
border-bottom-color: #e6e6e6;
}
.flatpickr-calendar.arrowTop:after {
border-bottom-color: #fff;
}
.flatpickr-calendar.arrowBottom:before,
.flatpickr-calendar.arrowBottom:after {
top: 100%;
}
.flatpickr-calendar.arrowBottom:before {
border-top-color: #e6e6e6;
}
.flatpickr-calendar.arrowBottom:after {
border-top-color: #fff;
}
.flatpickr-calendar:focus {
outline: 0;
}
.flatpickr-wrapper {
position: relative;
display: inline-block;
}
.flatpickr-months {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.flatpickr-months .flatpickr-month {
background: transparent;
color: rgba(0, 0, 0, 0.9);
fill: rgba(0, 0, 0, 0.9);
height: 34px;
line-height: 1;
text-align: center;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
overflow: hidden;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-decoration: none;
cursor: pointer;
position: absolute;
top: 0;
height: 34px;
padding: 10px;
z-index: 3;
color: rgba(0, 0, 0, 0.9);
fill: rgba(0, 0, 0, 0.9);
}
.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,
.flatpickr-months .flatpickr-next-month.flatpickr-disabled {
display: none;
}
.flatpickr-months .flatpickr-prev-month i,
.flatpickr-months .flatpickr-next-month i {
position: relative;
}
.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
/*
/*rtl:begin:ignore*/
left: 0; /*
/*rtl:end:ignore*/
} /*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
.flatpickr-months .flatpickr-next-month.flatpickr-next-month {
/*
/*rtl:begin:ignore*/
right: 0; /*
/*rtl:end:ignore*/
} /*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.flatpickr-months .flatpickr-prev-month:hover,
.flatpickr-months .flatpickr-next-month:hover {
color: #959ea9;
}
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
fill: #f64747;
}
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
width: 14px;
height: 14px;
}
.flatpickr-months .flatpickr-prev-month svg path,
.flatpickr-months .flatpickr-next-month svg path {
-webkit-transition: fill 0.1s;
transition: fill 0.1s;
fill: inherit;
}
.numInputWrapper {
position: relative;
height: auto;
}
.numInputWrapper input,
.numInputWrapper span {
display: inline-block;
}
.numInputWrapper input {
width: 100%;
}
.numInputWrapper input::-ms-clear {
display: none;
}
.numInputWrapper input::-webkit-outer-spin-button,
.numInputWrapper input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
}
.numInputWrapper span {
position: absolute;
right: 0;
width: 14px;
padding: 0 4px 0 2px;
height: 50%;
line-height: 50%;
opacity: 0;
cursor: pointer;
border: 1px solid rgba(57, 57, 57, 0.15);
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.numInputWrapper span:hover {
background: rgba(0, 0, 0, 0.1);
}
.numInputWrapper span:active {
background: rgba(0, 0, 0, 0.2);
}
.numInputWrapper span:after {
display: block;
content: "";
position: absolute;
}
.numInputWrapper span.arrowUp {
top: 0;
border-bottom: 0;
}
.numInputWrapper span.arrowUp:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid rgba(57, 57, 57, 0.6);
top: 26%;
}
.numInputWrapper span.arrowDown {
top: 50%;
}
.numInputWrapper span.arrowDown:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid rgba(57, 57, 57, 0.6);
top: 40%;
}
.numInputWrapper span svg {
width: inherit;
height: auto;
}
.numInputWrapper span svg path {
fill: rgba(0, 0, 0, 0.5);
}
.numInputWrapper:hover {
background: rgba(0, 0, 0, 0.05);
}
.numInputWrapper:hover span {
opacity: 1;
}
.flatpickr-current-month {
font-size: 135%;
line-height: inherit;
font-weight: 300;
color: inherit;
position: absolute;
width: 75%;
left: 12.5%;
padding: 7.48px 0 0 0;
line-height: 1;
height: 34px;
display: inline-block;
text-align: center;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.flatpickr-current-month span.cur-month {
font-family: inherit;
font-weight: 700;
color: inherit;
display: inline-block;
margin-left: 0.5ch;
padding: 0;
}
.flatpickr-current-month span.cur-month:hover {
background: rgba(0, 0, 0, 0.05);
}
.flatpickr-current-month .numInputWrapper {
width: 6ch;
width: 7ch\0;
display: inline-block;
}
.flatpickr-current-month .numInputWrapper span.arrowUp:after {
border-bottom-color: rgba(0, 0, 0, 0.9);
}
.flatpickr-current-month .numInputWrapper span.arrowDown:after {
border-top-color: rgba(0, 0, 0, 0.9);
}
.flatpickr-current-month input.cur-year {
background: transparent;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: inherit;
cursor: text;
padding: 0 0 0 0.5ch;
margin: 0;
display: inline-block;
font-size: inherit;
font-family: inherit;
font-weight: 300;
line-height: inherit;
height: auto;
border: 0;
border-radius: 0;
vertical-align: initial;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.flatpickr-current-month input.cur-year:focus {
outline: 0;
}
.flatpickr-current-month input.cur-year[disabled],
.flatpickr-current-month input.cur-year[disabled]:hover {
font-size: 100%;
color: rgba(0, 0, 0, 0.5);
background: transparent;
pointer-events: none;
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
appearance: menulist;
background: transparent;
border: none;
border-radius: 0;
box-sizing: border-box;
color: inherit;
cursor: pointer;
font-size: inherit;
font-family: inherit;
font-weight: 300;
height: auto;
line-height: inherit;
margin: -1px 0 0 0;
outline: none;
padding: 0 0 0 0.5ch;
position: relative;
vertical-align: initial;
-webkit-box-sizing: border-box;
-webkit-appearance: menulist;
-moz-appearance: menulist;
width: auto;
}
.flatpickr-current-month .flatpickr-monthDropdown-months:focus,
.flatpickr-current-month .flatpickr-monthDropdown-months:active {
outline: none;
}
.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
background: rgba(0, 0, 0, 0.05);
}
.flatpickr-current-month
.flatpickr-monthDropdown-months
.flatpickr-monthDropdown-month {
background-color: transparent;
outline: none;
padding: 0;
}
.flatpickr-weekdays {
background: transparent;
text-align: center;
overflow: hidden;
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 28px;
}
.flatpickr-weekdays .flatpickr-weekdaycontainer {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
span.flatpickr-weekday {
cursor: default;
font-size: 90%;
background: transparent;
color: rgba(0, 0, 0, 0.54);
line-height: 1;
margin: 0;
text-align: center;
display: block;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
font-weight: bolder;
}
.dayContainer,
.flatpickr-weeks {
padding: 1px 0 0 0;
}
.flatpickr-days {
position: relative;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
width: 307.875px;
}
.flatpickr-days:focus {
outline: 0;
}
.dayContainer {
padding: 0;
outline: 0;
text-align: left;
width: 307.875px;
min-width: 307.875px;
max-width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
display: -ms-flexbox;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-wrap: wrap;
-ms-flex-pack: justify;
-webkit-justify-content: space-around;
justify-content: space-around;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
.dayContainer + .dayContainer {
-webkit-box-shadow: -1px 0 0 #e6e6e6;
box-shadow: -1px 0 0 #e6e6e6;
}
.flatpickr-day {
background: none;
border: 1px solid transparent;
border-radius: 150px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #393939;
cursor: pointer;
font-weight: 400;
width: 14.2857143%;
-webkit-flex-basis: 14.2857143%;
-ms-flex-preferred-size: 14.2857143%;
flex-basis: 14.2857143%;
max-width: 39px;
height: 39px;
line-height: 39px;
margin: 0;
display: inline-block;
position: relative;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
text-align: center;
}
.flatpickr-day.inRange,
.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange,
.flatpickr-day.today.inRange,
.flatpickr-day.prevMonthDay.today.inRange,
.flatpickr-day.nextMonthDay.today.inRange,
.flatpickr-day:hover,
.flatpickr-day.prevMonthDay:hover,
.flatpickr-day.nextMonthDay:hover,
.flatpickr-day:focus,
.flatpickr-day.prevMonthDay:focus,
.flatpickr-day.nextMonthDay:focus {
cursor: pointer;
outline: 0;
background: #e6e6e6;
border-color: #e6e6e6;
}
.flatpickr-day.today {
border-color: #959ea9;
}
.flatpickr-day.today:hover,
.flatpickr-day.today:focus {
border-color: #959ea9;
background: #959ea9;
color: #fff;
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
background: #569ff7;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #569ff7;
}
.flatpickr-day.selected.startRange,
.flatpickr-day.startRange.startRange,
.flatpickr-day.endRange.startRange {
border-radius: 50px 0 0 50px;
}
.flatpickr-day.selected.endRange,
.flatpickr-day.startRange.endRange,
.flatpickr-day.endRange.endRange {
border-radius: 0 50px 50px 0;
}
.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n + 1)) {
-webkit-box-shadow: -10px 0 0 #569ff7;
box-shadow: -10px 0 0 #569ff7;
}
.flatpickr-day.selected.startRange.endRange,
.flatpickr-day.startRange.startRange.endRange,
.flatpickr-day.endRange.startRange.endRange {
border-radius: 50px;
}
.flatpickr-day.inRange {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
box-shadow: -5px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay,
.flatpickr-day.notAllowed,
.flatpickr-day.notAllowed.prevMonthDay,
.flatpickr-day.notAllowed.nextMonthDay {
color: rgba(57, 57, 57, 0.3);
background: transparent;
border-color: transparent;
cursor: default;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
cursor: not-allowed;
color: rgba(57, 57, 57, 0.1);
}
.flatpickr-day.week.selected {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #569ff7, 5px 0 0 #569ff7;
box-shadow: -5px 0 0 #569ff7, 5px 0 0 #569ff7;
}
.flatpickr-day.hidden {
visibility: hidden;
}
.rangeMode .flatpickr-day {
margin-top: 1px;
}
.flatpickr-weekwrapper {
float: left;
}
.flatpickr-weekwrapper .flatpickr-weeks {
padding: 0 12px;
-webkit-box-shadow: 1px 0 0 #e6e6e6;
box-shadow: 1px 0 0 #e6e6e6;
}
.flatpickr-weekwrapper .flatpickr-weekday {
float: none;
width: 100%;
line-height: 28px;
}
.flatpickr-weekwrapper span.flatpickr-day,
.flatpickr-weekwrapper span.flatpickr-day:hover {
display: block;
width: 100%;
max-width: none;
color: rgba(57, 57, 57, 0.3);
background: transparent;
cursor: default;
border: none;
}
.flatpickr-innerContainer {
display: block;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
}
.flatpickr-rContainer {
display: inline-block;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.flatpickr-time {
text-align: center;
outline: 0;
display: block;
height: 0;
line-height: 40px;
max-height: 40px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.flatpickr-time:after {
content: "";
display: table;
clear: both;
}
.flatpickr-time .numInputWrapper {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
width: 40%;
height: 40px;
float: left;
}
.flatpickr-time .numInputWrapper span.arrowUp:after {
border-bottom-color: #393939;
}
.flatpickr-time .numInputWrapper span.arrowDown:after {
border-top-color: #393939;
}
.flatpickr-time.hasSeconds .numInputWrapper {
width: 26%;
}
.flatpickr-time.time24hr .numInputWrapper {
width: 49%;
}
.flatpickr-time input {
background: transparent;
-webkit-box-shadow: none;
box-shadow: none;
border: 0;
border-radius: 0;
text-align: center;
margin: 0;
padding: 0;
height: inherit;
line-height: inherit;
color: #393939;
font-size: 14px;
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.flatpickr-time input.flatpickr-hour {
font-weight: bold;
}
.flatpickr-time input.flatpickr-minute,
.flatpickr-time input.flatpickr-second {
font-weight: 400;
}
.flatpickr-time input:focus {
outline: 0;
border: 0;
}
.flatpickr-time .flatpickr-time-separator,
.flatpickr-time .flatpickr-am-pm {
height: inherit;
float: left;
line-height: inherit;
color: #393939;
font-weight: bold;
width: 2%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-align-self: center;
-ms-flex-item-align: center;
align-self: center;
}
.flatpickr-time .flatpickr-am-pm {
outline: 0;
width: 18%;
cursor: pointer;
text-align: center;
font-weight: 400;
}
.flatpickr-time input:hover,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:focus {
background: #eee;
}
.flatpickr-input[readonly] {
cursor: pointer;
}
@-webkit-keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}

1379
src/main/resources/static/flatpickr-4.6.13/js/flatpickr.js
File diff suppressed because it is too large
View File

6995
src/main/resources/static/font-awesome-6.5.1/css/all.min.css
File diff suppressed because it is too large
View File

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-brands-400.ttf

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-brands-400.woff2

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-regular-400.ttf

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-regular-400.woff2

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-solid-900.ttf

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-solid-900.woff2

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-v4compatibility.ttf

BIN
src/main/resources/static/font-awesome-6.5.1/webfonts/fa-v4compatibility.woff2

7023
src/main/resources/static/font-awesome-6.5.2/css/all.min.css
File diff suppressed because it is too large
View File

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-brands-400.ttf

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-brands-400.woff2

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-regular-400.ttf

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-regular-400.woff2

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-solid-900.ttf

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-solid-900.woff2

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf

BIN
src/main/resources/static/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2

BIN
src/main/resources/static/header-images/gcc1.png

After

Width: 325  |  Height: 435  |  Size: 204 KiB

25996
src/main/resources/static/html2pdf-0.9.3/js/html2pdf.bundle.min.js
File diff suppressed because it is too large
View File

3244
src/main/resources/static/jquery-3.6.4/js/jquery-3.6.4.min.js
File diff suppressed because it is too large
View File

77
src/main/resources/static/js/add-file-script.js

@ -0,0 +1,77 @@
// Initialize date pickers
["asFileGenDate", "piFileGenDate"].forEach(id => {
flatpickr("#" + id, {
dateFormat: "d-m-Y",
enableTime: false,
noCalendar: false,
allowInput: true
});
});
document.addEventListener("DOMContentLoaded", function() {
const form = document.getElementById("frm-file-det");
// Listen for advance type changes
const advTypeInput = document.getElementById("advType");
const vendNameContainer = document.getElementById("vend-name");
advTypeInput.addEventListener("input", function() {
// Force uppercase
this.value = this.value.toUpperCase();
const enteredText = this.value.trim();
// If user types "senior system manager"
if (enteredText.toLowerCase() === "senior system manager".toLowerCase()) {
vendNameContainer.innerHTML = `
<label for="vendName">Vendor Name : <span class="required">*</span></label>
<input type="text" id="vendName" name="vendName" class="form-control"
placeholder="Enter Vendor Name" required autocomplete="on">
`;
} else {
// Clear when not "SSM"
vendNameContainer.innerHTML = "";
}
});
// Existing form submission logic...
form.addEventListener("submit", function(e) {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(form);
fetch(form.getAttribute("action"), {
method: "POST",
body: formData
})
.then(response => {
if (!response.ok) {
throw new Error("Network response was not ok: " + response.statusText);
}
return response.json();
})
.then(data => {
if (data.resStat) {
alert("Success: " + data.res);
form.reset();
// Reset flatpickr
if (flatpickr) {
["#asFileGenDate", "#piFileGenDate"].forEach(selector => {
const fp = document.querySelector(selector)?._flatpickr;
if (fp) fp.clear();
});
}
// Reset dynamic vendor field
vendNameContainer.innerHTML = "";
} else {
alert("Failed: " + data.res);
}
})
.catch(error => {
console.error("Error submitting file:", error);
alert("Error submitting file. Please try again.");
});
});
});

17
src/main/resources/static/js/adjust-row-class-script.js

@ -0,0 +1,17 @@
function adjustRowClass() {
let row = document.getElementById("fileRow");
let row2 = document.getElementById("fileRow2");
let row3 = document.getElementById("fileRow3");
let row4 = document.getElementById("fileRow4");
if (window.innerWidth < 768) {
row.classList.remove("d-flex", "justify-content-between", "text-center");
row2.classList.remove("d-flex", "justify-content-between", "text-center");
row3.classList.remove("d-flex", "justify-content-between", "text-center");
row4.classList.remove("d-flex", "justify-content-between", "text-center");
} else {
row.classList.add("d-flex", "justify-content-between", "text-center");
row2.classList.add("d-flex", "justify-content-between", "text-center");
row3.classList.add("d-flex", "justify-content-between", "text-center");
row4.classList.add("d-flex", "justify-content-between", "text-center");
}
}

20
src/main/resources/static/js/fetch-csrf-script.js

@ -0,0 +1,20 @@
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;
// Save original fetch
const originalFetch = window.fetch;
window.fetch = (url, options = {}) => {
// Default method is GET if not provided
const method = (options.method || "GET").toUpperCase();
// Only attach CSRF for unsafe methods
if (["POST", "PUT", "DELETE", "PATCH"].includes(method)) {
options.headers = {
...options.headers,
[csrfHeader]: csrfToken
};
}
return originalFetch(url, options);
};

3
src/main/resources/static/js/go-back-script.js

@ -0,0 +1,3 @@
function goBack() {
window.history.back();
}

31
src/main/resources/static/js/login-script.js

@ -0,0 +1,31 @@
document.getElementById("frm-usr-login-det").addEventListener("submit", function(event) {
event.preventDefault(); // prevent normal form submission
const formData = new FormData(this);
fetch('/api/val-app-usr-login', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.result) {
// Extract first role authority (user only has 1 role)
let userRole = data.role && data.role.length > 0 ? data.role[0].authority : null;
if (userRole) {
// Redirect using the role name instead of ID
alert("Login Success");
window.location.href = "/redirect?usr-role=" + encodeURIComponent(userRole);
} else {
alert("No role found for this user!");
}
} else {
alert(data.error || "Login failed");
}
})
.catch(err => {
console.error("Error during login:", err);
});
});

118
src/main/resources/static/js/update-ejv-number-script.js

@ -0,0 +1,118 @@
document.addEventListener("DOMContentLoaded", function() {
const fileNumInput = document.getElementById("file-num");
const dataList = document.getElementById("file-num-list");
const asFinalFileStatInput = document.getElementById("as-final-file-stat");
const ejvNumFileInput = document.getElementById("ejv-num-file");
const ejvNumInput = document.getElementById("ejv-num");
const submitBtn = document.querySelector(".submit-btn input[type='submit']");
const form = document.getElementById("frm-file-det");
// Disable EJV-related inputs & submit initially
ejvNumFileInput.disabled = true;
ejvNumInput.disabled = true;
fileNumInput.addEventListener("input", function() {
// Find matching option from datalist
const selectedOption = Array.from(dataList.options).find(
option => option.value === fileNumInput.value
);
if (!selectedOption) {
// No valid selection (user typed arbitrary text)
asFinalFileStatInput.value = "";
ejvNumInput.value = "";
ejvNumFileInput.value = "";
document.getElementById("selected-ejv-num-file-name").textContent = "";
ejvNumInput.disabled = true;
ejvNumFileInput.disabled = true;
submitBtn.disabled = true;
return;
}
const asFinalStat = selectedOption.dataset.asFinalFileStat;
const ejvFileStat = selectedOption.dataset.ejvNumFileStat;
const ejvNumStat = selectedOption.dataset.ejvNum;
let ejvNumValue = selectedOption.dataset.ejvNumInput || "";
if (ejvNumValue === "-") ejvNumValue = "";
const ejvNumFileValue = selectedOption.dataset.ejvNumFileInput || "";
// Show Adjustment Order status
if (asFinalStat === "true") {
asFinalFileStatInput.value = "Yes";
} else if (asFinalStat === "false") {
asFinalFileStatInput.value = "No";
} else {
asFinalFileStatInput.value = "";
}
// Always show span with EJV number
document.getElementById("selected-ejv-num-file-name").textContent =
ejvNumFileValue && ejvNumFileValue !== "-"
? "Uploaded file: " + ejvNumFileValue.split("/").pop()
: "Uploaded file: N/A";
ejvNumInput.style.display = "inline";
ejvNumFileInput.style.display = "inline";
// Handle enable/disable logic
if (asFinalStat === "true" && (ejvFileStat === "true" || ejvNumStat === "true")) {
// Already updated → disabled
ejvNumInput.value = ejvNumValue;
ejvNumInput.disabled = true;
ejvNumFileInput.disabled = true;
submitBtn.disabled = true;
} else if (asFinalStat === "true" && (ejvFileStat !== "true" || ejvNumStat !== "true")) {
// Not updated yet → enabled
ejvNumInput.value = ejvNumValue;
ejvNumInput.disabled = false;
ejvNumFileInput.disabled = false;
submitBtn.disabled = false;
} else if (asFinalStat !== "true") {
// Adjustment Order not uploaded → disabled
ejvNumInput.value = ejvNumValue;
ejvNumInput.disabled = true;
ejvNumFileInput.disabled = true;
submitBtn.disabled = true;
}
});
// Handle form submit with fetch
form.addEventListener("submit", function(e) {
e.preventDefault(); // prevent default page reload
const selectedOption = Array.from(dataList.options).find(
option => option.value === fileNumInput.value
);
if (!selectedOption) {
alert("Please select a valid file number from the list.");
return;
}
const formData = new FormData();
formData.append("file-num", fileNumInput.value);
formData.append("ejv-num", ejvNumInput.value);
formData.append("ejv-num-file", ejvNumFileInput.files[0]);
fetch("/api/file/upd-ejv-num", {
method: "POST",
body: formData
})
.then(response => response.json())
.then(data => {
if (data.resStat) {
alert(data.res);
form.reset();
asFinalFileStatInput.value = "";
ejvNumFileInput.disabled = true;
ejvNumInput.disabled = true;
submitBtn.disabled = true;
} else {
alert(data.res);
}
})
.catch(error => {
console.error("Error:", error);
alert("Something went wrong while updating EJV.");
});
});
});

351
src/main/resources/static/js/update-file-script.js

@ -0,0 +1,351 @@
document.addEventListener("DOMContentLoaded", function() {
// ========== COMMON HELPERS ==========
function getFileName(path) {
let fileSpan = "Uploaded file: ";
return (!path || path === '-' ? fileSpan + "N/A" : fileSpan + path.split(/[/\\]/).pop());
}
function formatDateForInput(dateStr) {
if (!dateStr || dateStr === '-' || dateStr === '1970-01-01') return '';
const parts = dateStr.split('-'); // ["2024","09","09"]
return `${parts[2]}-${parts[1]}-${parts[0]}`; // "09-09-2024"
}
// Debounce helper
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
}
// ========== PART 1: AS/PI FILE SECTION (update-file-script.js logic) ==========
["asFileGenDate", "piFileGenDate"].forEach(id => {
flatpickr("#" + id, {
dateFormat: "d-m-Y",
enableTime: false,
noCalendar: false,
allowInput: true
});
});
const fileNumSelect = document.getElementById("fileNum");
const fileInputs = {
rtgsFile: 'selected-rtgs-file-name',
poFile: 'selected-po-file-name',
dcFile: 'selected-dc-file-name',
srFile: 'selected-sr-file-name',
irFile: 'selected-ir-file-name',
asFile: 'selected-as-file-name',
piFile: 'selected-pi-file-name',
asFileGenDate: null,
piFileGenDate: null,
piAmt: null,
fileRmrk: null,
advType: null,
vendName: null,
fundTypeId: null
};
function setInputsState(enabledIds = [], preserveValues = []) {
Object.keys(fileInputs).forEach(id => {
const input = document.getElementById(id);
const spanId = fileInputs[id];
const span = spanId ? document.getElementById(spanId) : null;
if (input) input.disabled = !enabledIds.includes(id);
if (span) {
if (enabledIds.includes(id) || preserveValues.includes(id)) {
span.style.display = "inline";
} else {
span.style.display = "none";
if (!preserveValues.includes(id)) span.textContent = "";
}
}
if (!enabledIds.includes(id) && input && !preserveValues.includes(id)) {
input.value = "";
}
});
}
const list = document.getElementById("fileNumList");
const handleFileSelection = () => {
if (!fileNumSelect.value) {
setInputsState([]);
handleFIPanel(null);
return;
}
// Find matching datalist option
const selectedOption = Array.from(list.options).find(opt => opt.value === fileNumSelect.value);
if (!selectedOption) {
setInputsState([]);
handleFIPanel(null);
return;
}
const ejvNum = selectedOption.dataset.ejv;
const ejvPath = selectedOption.dataset.ejvPath;
const hasEJV = ejvNum && ejvNum !== '-' && ejvPath && ejvPath !== '-';
if (hasEJV) {
setInputsState(['fileRmrk'], ['piAmt', 'piFileGenDate', 'asFileGenDate', 'vendName', 'advType', 'fundTypeId']);
} else {
setInputsState(Object.keys(fileInputs));
}
document.getElementById("piAmt").value = selectedOption.dataset.piAmt || '';
document.getElementById("advType").value = selectedOption.dataset.advType || '';
document.getElementById("vendName").value = selectedOption.dataset.vendName || '';
document.getElementById("asFileGenDate").value = formatDateForInput(selectedOption.dataset.asFileGenDate);
document.getElementById("piFileGenDate").value = formatDateForInput(selectedOption.dataset.piFileGenDate);
document.getElementById("fileRmrk").value = selectedOption.dataset.remarks || '';
const fundTypeSelect = document.getElementById("fundTypeId");
const fundType = selectedOption.dataset.fundType || '';
if (fundTypeSelect) {
fundTypeSelect.value = fundType;
}
Object.keys(fileInputs).forEach(id => {
if (!['asFileGenDate', 'piFileGenDate', 'piAmt', 'fileRmrk', 'vendName', 'advType', 'fundTypeId'].includes(id)) {
const spanId = fileInputs[id];
const span = spanId ? document.getElementById(spanId) : null;
const filePath = selectedOption.dataset[id] || '';
if (span) {
span.style.display = "inline";
span.textContent = getFileName(filePath);
}
}
});
handleFIPanel(selectedOption, hasEJV);
};
// Wrap it with debounce (300ms delay)
const debouncedHandle = debounce(handleFileSelection, 300);
// Attach event listener
fileNumSelect.addEventListener("input", debouncedHandle);
fileNumSelect.addEventListener("change", debouncedHandle); // optional, for safety
// ========== PART 2: FI / AS FINAL / TC SECTION (add-update-adjustment-script.js logic) ==========
const piAmtInput = document.getElementById("piAmt");
const fiFileGenDate = document.getElementById("fiFileGenDate");
const fiAmtInput = document.getElementById("fiAmt");
const balAmtInput = document.getElementById("balAmt");
const asFinalFileGenDate = document.getElementById("asFinalFileGenDate");
const tcFileGenDate = document.getElementById("tcFileGenDate");
const submitBtn = document.querySelector(".submit-btn input[type='submit']");
const fiSectionInputs = ["fiFileGenDate", "fiFile", "fiAmt", "asFinalFile", "asFinalFileGenDate", "tcFileGenDate", "tcFile"];
const fiSpans = ["selected-fi-file-name", "selected-as-final-file-name", "selected-tc-file-name"];
// Disable initially
fiSectionInputs.forEach(id => {
const el = document.getElementById(id);
if (el) el.disabled = true;
});
// Initialize Flatpickr
const fpFI = flatpickr(fiFileGenDate, { dateFormat: "d-m-Y", maxDate: "today", allowInput: true });
const fpAS = flatpickr(asFinalFileGenDate, { dateFormat: "d-m-Y", maxDate: "today", allowInput: true });
const fpTC = flatpickr(tcFileGenDate, { dateFormat: "d-m-Y", maxDate: "today", allowInput: true });
function handleFIPanel(selected, hasEJV = false) {
if (!selected) {
fiSectionInputs.forEach(id => document.getElementById(id).disabled = true);
if (submitBtn) submitBtn.disabled = true;
fiSpans.forEach(id => document.getElementById(id).textContent = "");
if (fpFI) fpFI.clear();
if (fpAS) fpAS.clear();
if (fpTC) fpTC.clear();
if (typeof piAmtInput !== "undefined" && piAmtInput) piAmtInput.value = "";
if (typeof fiAmtInput !== "undefined" && fiAmtInput) fiAmtInput.value = "";
if (typeof balAmtInput !== "undefined" && balAmtInput) balAmtInput.value = 0;
return;
}
const ejvStat = selected.getAttribute("data-ejv-stat") === "true";
const ejvFileStat = selected.getAttribute("data-ejv-file-stat") === "true";
// Fill data
piAmtInput.value = parseFloat(selected.getAttribute("data-pi-amt") || 0) || 0;
fiAmtInput.value = selected.getAttribute("data-fi-amt") || "";
balAmtInput.value = 0;
// Trigger balance calculation when fiAmt is auto-filled
fiAmtInput.dispatchEvent(new Event("input"));
const files = {
"selected-fi-file-name": selected.getAttribute("data-fi-file"),
"selected-as-final-file-name": selected.getAttribute("data-as-final-file"),
"selected-tc-file-name": selected.getAttribute("data-tc-file")
};
Object.entries(files).forEach(([spanId, path]) => {
document.getElementById(spanId).textContent = getFileName(path);
});
// Dates
const fiVal = formatDateForInput(selected.getAttribute("data-fi-file-gen-date"));
const asVal = formatDateForInput(selected.getAttribute("data-as-final-file-gen-date"));
const tcVal = formatDateForInput(selected.getAttribute("data-tc-file-gen-date"));
if (fiVal) fpFI.setDate(fiVal, true, "d-m-Y"); else fpFI.clear();
if (asVal) fpAS.setDate(asVal, true, "d-m-Y"); else fpAS.clear();
if (tcVal) fpTC.setDate(tcVal, true, "d-m-Y"); else fpTC.clear();
// Dependencies
const piGenRaw = selected.getAttribute("data-pi-file-gen-date");
if (piGenRaw && piGenRaw !== "-" && piGenRaw !== "1970-01-01") {
const [y, m, d] = piGenRaw.split("-"); // Fixed: y,m,d
fpFI.set("minDate", new Date(y, m - 1, d));
} else {
fpFI.set("minDate", null);
}
if (fiVal) {
const [d, m, y] = fiVal.split("-");
const fiDateObj = new Date(y, m - 1, d);
fpAS.set("minDate", fiDateObj);
fpTC.set("minDate", fiDateObj);
} else {
fpAS.set("minDate", null);
fpTC.set("minDate", null);
}
// Enable/disable section
if (hasEJV || ejvStat || ejvFileStat) {
fiSectionInputs.forEach(id => {
const el = document.getElementById(id);
if (el) el.disabled = true;
});
// Allow submit if remarks are enabled (e.g., when hasEJV is true)
if (submitBtn) submitBtn.disabled = !document.getElementById("fileRmrk")?.disabled ? false : true;
} else {
fiSectionInputs.forEach(id => {
const el = document.getElementById(id);
if (el) el.disabled = false;
});
if (submitBtn) submitBtn.disabled = false;
}
}
// Update AS/TC minDate when FI date changes manually
if (fiFileGenDate) {
fiFileGenDate.addEventListener("change", function() {
const fiDate = this.value;
if (fiDate) {
const [d, m, y] = fiDate.split("-");
const fiDateObj = new Date(y, m - 1, d);
fpAS.set("minDate", fiDateObj);
fpTC.set("minDate", fiDateObj);
} else {
fpAS.set("minDate", null);
fpTC.set("minDate", null);
}
});
}
// Balance calculation
const calculateBalance = debounce(() => {
const piAmt = parseFloat(piAmtInput.value || 0);
const fiAmtRaw = fiAmtInput.value.trim();
balAmtInput.value = fiAmtRaw ? Math.max(piAmt - parseFloat(fiAmtRaw), 0) : "";
}, 500);
fiAmtInput.addEventListener("input", calculateBalance);
// ----- Unified Form Submission (merged from update-file-script.js + add-update-adjustment-script.js) -----
const form = document.getElementById("frm-file-det");
form.addEventListener("submit", function(event) {
event.preventDefault();
const formData = new FormData(form);
// ensure disabled inputs (advType, fundTypeId, etc.) are sent
["advType", "fundTypeId"].forEach(id => {
const el = document.getElementById(id);
if (el && !formData.has(id)) {
formData.append(id, el.value || "");
}
});
// Include balance amount if it exists
if (typeof balAmtInput !== "undefined" && balAmtInput) {
formData.append("balAmt", balAmtInput.value || "");
}
fetch(form.getAttribute("action"), {
method: form.getAttribute("method") || "POST",
body: formData
})
.then(res => res.ok ? res.json() : Promise.reject("Network response not ok"))
.then(data => {
if (data.resStat) {
alert(data.res || "Form submitted successfully!");
// Reset the form and UI
form.reset();
// Reset AS/PI section
const asFileGenDateEl = document.getElementById("asFileGenDate");
const piFileGenDateEl = document.getElementById("piFileGenDate");
const fundTypeSelect = document.getElementById("fundTypeId");
if (fundTypeSelect) {
fundTypeSelect.value = "";
fundTypeSelect.disabled = false;
}
if (asFileGenDateEl) asFileGenDateEl.value = "";
if (piFileGenDateEl) piFileGenDateEl.value = "";
if (document.getElementById("fileRmrk")) document.getElementById("fileRmrk").value = "";
// Reset FI/AS Final/TC section
if (typeof piAmtInput !== "undefined" && piAmtInput) piAmtInput.value = 0;
if (typeof balAmtInput !== "undefined" && balAmtInput) balAmtInput.value = 0;
if (typeof fiAmtInput !== "undefined" && fiAmtInput) fiAmtInput.value = "";
if (typeof fileNameSpans !== "undefined") {
fileNameSpans.forEach(id => {
const span = document.getElementById(id);
if (span) span.textContent = "";
});
}
// Clear Flatpickr pickers if available
if (typeof fpFI !== "undefined" && fpFI) {
fpFI.clear();
fpFI.set("minDate", null);
}
if (typeof fpAS !== "undefined" && fpAS) {
fpAS.clear();
fpAS.set("minDate", null);
}
if (typeof fpTC !== "undefined" && fpTC) {
fpTC.clear();
fpTC.set("minDate", null);
}
fileNumSelect.selectedIndex = 0;
fileNumSelect.dispatchEvent(new Event('change'));
console.log("Response:", data);
} else {
alert("Submission failed: " + (data.res || "Unknown error"));
}
})
.catch(err => {
console.error("Error submitting form:", err);
alert("Error submitting form. Check console for details.");
});
});
// Initial trigger
fileNumSelect.dispatchEvent(new Event('change'));
});

157
src/main/resources/static/js/view-file-detail-script.js

@ -0,0 +1,157 @@
// Function to view Supporting Document in modal
function viewFileInModal(fileNum, fileType, filePath) {
var pdfModal = new bootstrap.Modal(document.getElementById('pdf-modal'));
var modalTitle = document.getElementById('pdf-modal-label');
var pdfContainer = document.getElementById('pdf-container');
pdfContainer.innerHTML = ''; // Clear previous pages
var decodedFilePath = decodeURIComponent(filePath);
var fileName = decodedFilePath.split(/[\\/]/).pop();
modalTitle.textContent = fileType + " File (" + fileName + ")";
/*var userId = document.getElementById('hid_user_id').value;*/
var params = new URLSearchParams();
params.append('file-type', fileType);
params.append('file-path', decodedFilePath);
/*params.append('user_id', userId);*/
params.append('file-num', fileNum); // matches data-file-num
fetch('/api/file/view-supp-docs', { // Controller endpoint
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString()
}).then(function(response) {
if (!response.ok) {
throw new Error('Failed to fetch PDF: ' + response.statusText);
}
return response.arrayBuffer();
}).then(function(pdfData) {
var blob = new Blob([pdfData], { type: 'application/pdf' });
var blobUrl = URL.createObjectURL(blob);
// Set download link
var downloadBtn = document.getElementById('download-pdf-btn');
downloadBtn.href = blobUrl;
downloadBtn.download = fileName;
return pdfjsLib.getDocument({ data: pdfData }).promise;
}).then(function(pdf) {
let renderPage = function(pageNum) {
return pdf.getPage(pageNum).then(function(page) {
var viewport = page.getViewport({ scale: 1.5 });
var canvas = document.createElement('canvas');
canvas.classList.add('mb-3');
var ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = { canvasContext: ctx, viewport: viewport };
pdfContainer.appendChild(canvas);
return page.render(renderContext).promise;
});
};
// Render all pages sequentially
let sequence = Promise.resolve();
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
sequence = sequence.then(() => renderPage(pageNum));
}
return sequence;
}).then(function() {
pdfModal.show();
}).catch(function(error) {
alert('Error loading PDF: ' + error.message);
});
}
$(document).ready(function() {
// Initialize DataTable
var table = $('#file-data-det-tbl').DataTable({
paging: true,
searching: true,
ordering: true,
lengthChange: true,
pageLength: 10,
language: {
emptyTable: "No data available",
lengthMenu: "Display _MENU_ records per page",
info: "Showing _START_ to _END_ of _TOTAL_ entries",
infoEmpty: "No records to show",
infoFiltered: "(filtered from _MAX_ total records)"
},
columnDefs: [
{
orderable: false,
targets: 0, // S.No column
render: function(data, type, row, meta) {
return meta.row + 1;
}
}
],
buttons: [
{
extend: 'excelHtml5',
title: "File Details",
filename: "File Details",
exportOptions: {
columns: ':visible:not(:eq(11))' // exclude 12th column
}
},
'pdfHtml5'
]
});
// Move DataTable controls to custom container
$('#custom-pagination').html($('.dataTables_paginate'));
$('#custom-info').html($('.dataTables_info'));
$('#custom-length').html($('.dataTables_length'));
// Custom export buttons
$('#export-excel').on('click', function() {
table.button('.buttons-excel').trigger();
});
$('#export-pdf').on('click', function() {
var originalLength = table.page.len();
table.one('draw', function() {
var tableClone = $('#file-det-tbl').clone();
tableClone.removeClass('dataTable');
tableClone.find('thead, tbody, tfoot').removeAttr('style');
// Remove "Supporting Documents" column (13th col = index 12)
tableClone.find('tr').each(function() {
$(this).find('th:eq(12), td:eq(12)').remove();
});
var pdfContainer = $('#pdf-print-container');
pdfContainer.html('<h2 style="text-align:center;">File Details</h2>');
pdfContainer.append(tableClone).css({ display: 'block', padding: '20px' });
tableClone.css({ width: '100%', borderCollapse: 'collapse' });
tableClone.find('th, td').css(
{
border: '1px solid #ccc',
padding: '5px',
fontSize: '10px',
textAlign: 'left',
verticalAlign: 'top'
});
tableClone.find('tr').css({ pageBreakInside: 'avoid', breakInside: 'avoid', webkitBreakInside: 'avoid' });
html2pdf().set({
margin: 0.5,
filename: 'File Details.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2, useCORS: true },
jsPDF: { unit: 'in', format: 'a3', orientation: 'landscape' }
}).from(pdfContainer[0]).save().then(function() {
table.page.len(originalLength).draw();
pdfContainer.hide();
});
});
table.page.len(-1).draw(); // show all rows for PDF
});
});

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

Loading…
Cancel
Save