Browse Source

first commit

master
yoganandhan 9 months ago
commit
85dd573908
  1. 2
      .gitattributes
  2. 33
      .gitignore
  3. 3
      .mvn/wrapper/maven-wrapper.properties
  4. 295
      mvnw
  5. 189
      mvnw.cmd
  6. 84
      pom.xml
  7. 13
      src/main/java/com/gcc/flagpoles/FlagpolesApplication.java
  8. 66
      src/main/java/com/gcc/flagpoles/configuration/AppConfig.java
  9. 472
      src/main/java/com/gcc/flagpoles/configuration/RefundScheduler.java
  10. 15
      src/main/java/com/gcc/flagpoles/constants/AppConstants.java
  11. 762
      src/main/java/com/gcc/flagpoles/controller/ApiController.java
  12. 35
      src/main/java/com/gcc/flagpoles/controller/DateTimeUtil.java
  13. 77
      src/main/java/com/gcc/flagpoles/controller/DropDownApiController.java
  14. 281
      src/main/java/com/gcc/flagpoles/controller/MainController.java
  15. 179
      src/main/java/com/gcc/flagpoles/controller/RefundController.java
  16. 19
      src/main/java/com/gcc/flagpoles/service/BookingService.java
  17. 183
      src/main/java/com/gcc/flagpoles/service/DropDownService.java
  18. 154
      src/main/java/com/gcc/flagpoles/service/PaymentService.java
  19. 323
      src/main/java/com/gcc/flagpoles/service/RefundService.java
  20. 1337
      src/main/java/com/gcc/flagpoles/service/RequestService.java
  21. 39
      src/main/java/com/gcc/flagpoles/service/SMSService.java
  22. 147
      src/main/java/com/gcc/flagpoles/service/WhatsappMessageService.java
  23. 33
      src/main/resources/application-dev.properties
  24. 31
      src/main/resources/application-prod.properties
  25. 1
      src/main/resources/application.properties
  26. 188
      src/main/resources/templates/fragments/details.html
  27. 178
      src/main/resources/templates/modules/flagpolesregistration/acknowledgement.html
  28. 195
      src/main/resources/templates/modules/flagpolesregistration/index.html
  29. 101
      src/main/resources/templates/modules/flagpolesregistration/nodatafound.html
  30. 252
      src/main/resources/templates/modules/flagpolesregistration/paymentrequestform.html
  31. 135
      src/main/resources/templates/modules/flagpolesregistration/razor-pay.html
  32. 2590
      src/main/resources/templates/modules/flagpolesregistration/requestform.html
  33. 1068
      src/main/resources/templates/modules/flagpolesregistration/status.html
  34. 13
      src/test/java/com/gcc/flagpoles/FlagpolesApplicationTests.java

2
.gitattributes

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

33
.gitignore

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

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"

84
pom.xml

@ -0,0 +1,84 @@
<?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.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gcc</groupId>
<artifactId>flagpoles</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>flagpoles</name>
<description>flag poles</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.razorpay</groupId>
<artifactId>razorpay-java</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

13
src/main/java/com/gcc/flagpoles/FlagpolesApplication.java

@ -0,0 +1,13 @@
package com.gcc.flagpoles;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FlagpolesApplication {
public static void main(String[] args) {
SpringApplication.run(FlagpolesApplication.class, args);
}
}

66
src/main/java/com/gcc/flagpoles/configuration/AppConfig.java

@ -0,0 +1,66 @@
package com.gcc.flagpoles.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
private String title;
private String baseUrl;
private String getOtpUrl;
private String erpUrl;
@Value("${payment.razorpay.my_key_id}")
private String keyId;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getGetOtpUrl() {
return getOtpUrl;
}
public void setGetOtpUrl(String getOtpUrl) {
this.getOtpUrl = getOtpUrl;
}
public String getErpUrl() {
return erpUrl;
}
public void setErpUrl(String erpUrl) {
this.erpUrl = erpUrl;
}
public String getKeyId() {
return keyId;
}
public void setKeyId(String keyId) {
this.keyId = keyId;
}
}

472
src/main/java/com/gcc/flagpoles/configuration/RefundScheduler.java

@ -0,0 +1,472 @@
// package com.gcc.flagpoles.configuration;
// import com.gcc.flagpoles.constants.AppConstants;
// import com.gcc.flagpoles.service.BookingService;
// import com.gcc.flagpoles.service.PaymentService;
// import com.gcc.flagpoles.service.RefundService;
// import com.razorpay.Order;
// import com.razorpay.Payment;
// import com.razorpay.RazorpayClient;
// import com.razorpay.RazorpayException;
// import org.json.JSONObject;
// import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.context.annotation.Lazy;
// import org.springframework.dao.DataAccessException;
// import org.springframework.dao.EmptyResultDataAccessException;
// import org.springframework.http.ResponseEntity;
// import org.springframework.jdbc.core.JdbcTemplate;
// import org.springframework.scheduling.annotation.EnableScheduling;
// import org.springframework.scheduling.annotation.Scheduled;
// import org.springframework.stereotype.Component;
// import org.springframework.stereotype.Service;
// import java.time.Instant;
// import java.time.LocalDate;
// import java.time.LocalDateTime;
// import java.time.ZoneId;
// import java.time.format.DateTimeFormatter;
// import java.util.*;
// @Component
// @EnableScheduling
// public class RefundScheduler {
// @Autowired
// @Lazy
// RefundService refundService;
// @Autowired
// PaymentService paymentService;
// @Autowired
// public JdbcTemplate jdbcTemplate;
// // @Scheduled(cron = "0 0 1 * * *", zone = "Asia/Kolkata") // runs every 30
// // seconds (adjust as needed)
// @Scheduled(cron = "0 30 23 * * *", zone = "Asia/Kolkata") // 11:30 PM IST
// (Asia/Kolkata)
// public void updateOrderPaymentStatus() {
// System.out.println("Fetching payment status from Razorpay...");
// try {
// // Query orders with NULL order_status
// String sql = "SELECT order_id, cdate FROM order_log WHERE (order_status IS
// NULL OR order_status = '') AND is_counter_booking = 0 and cdate < CURDATE()
// ORDER BY id ";//
// List<Map<String, Object>> orders = jdbcTemplate.queryForList(sql);
// if (orders.isEmpty()) {
// System.out.println("No orders with NULL status.");
// return;
// }
// // Collect orderIds into a list
// List<String> orderIds = new ArrayList<>();
// for (Map<String, Object> order : orders) {
// orderIds.add((String) order.get("order_id"));
// }
// // Fetch payment status for all orders using the fetchPayments API for
// multiple
// // orderIds
// fetchAndUpdatePaymentStatus(orderIds);
// } catch (Exception e) {
// System.err.println("Error fetching payment status: " + e.getMessage());
// e.printStackTrace();
// }
// }
// public void fetchAndUpdatePaymentStatus(List<String> orderIds) {
// try {
// System.out.println("Fetching payment status for multiple orders...");
// RazorpayClient razorpayClient = new RazorpayClient(AppConstants.key_id,
// AppConstants.key_secret);
// // Fetch payments for the specified orderIds
// for (String orderId : orderIds) {
// List<Payment> payments = razorpayClient.orders.fetchPayments(orderId);
// System.out.println("Payment response line :100 :" + payments);
// String ps = "Not Processed";
// // Check if there are payments for the order
// if (payments != null && !payments.isEmpty()) {
// int i = 0;
// int c = 0;
// for (Payment payment : payments) {
// String paymentStatus = (payment.get("status") != null) ?
// payment.get("status").toString() : "";
// String paymentId = (payment.get("id") != null) ? payment.get("id").toString()
// : "";
// String amount = (payment.get("amount") != null) ?
// payment.get("amount").toString() : "0";
// String captured_at = ""; // (payment.get("captured_at") != null) ?
// // payment.get("captured_at").toString() : "0";
// String contactNo = (payment.get("contact") != null) ?
// payment.get("contact").toString() : "0";
// System.out.println("contactno line 157--> " + contactNo);
// System.out.println("payments==================" + payment);
// String paymentDate = "";
// Object createdAtObj = null;
// // Date Convention
// try {
// // Object createdAtObj = payment.has("captured_at") ?
// payment.get("captured_at")
// // : null;
// createdAtObj = payment.get("captured_at") != null ?
// payment.get("captured_at") : null;
// if (createdAtObj != null) {
// Instant createdAtInstant = (createdAtObj instanceof Date)
// ? ((Date) createdAtObj).toInstant()
// : (createdAtObj instanceof Number)
// ? Instant.ofEpochSecond(((Number) createdAtObj).longValue())
// : Instant.ofEpochMilli(System.currentTimeMillis());
// paymentDate = createdAtInstant
// .atZone(ZoneId.of("Asia/Kolkata"))
// .toLocalDateTime()
// .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// // Convert to formatted datetime (e.g., 2025-04-19 17:00:00)
// LocalDateTime dateTime = createdAtInstant
// .atZone(ZoneId.of("Asia/Kolkata"))
// .toLocalDateTime();
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// // End of Date Convention
// System.out.println("Payment Status for Order ID " + orderId + ": " +
// paymentStatus);
// if (payments.size() == 1) {
// // Update the order status in the order_log table based on payment status
// payment.get("id").toString();
// updateOrderStatusInOrderLog(orderId, paymentStatus, payments.size(),
// paymentId, amount,
// paymentDate, contactNo);
// c = 1;
// } else if (paymentStatus.equals("captured") && i == 0) {
// updateOrderStatusInOrderLog(orderId, paymentStatus, payments.size(),
// paymentId, amount,
// paymentDate, contactNo);
// c = 1;
// } else if (ps.equals(paymentStatus) && paymentStatus.equals("captured")) {
// // refund logic to be implemented
// // razorpay will handle this scenario
// c = 1;
// } else if (paymentStatus.equals("captured") && c == 0) {
// updateOrderStatusInOrderLog(orderId, paymentStatus, payments.size(),
// paymentId, amount,
// paymentDate, contactNo);
// c = 1;
// }
// ps = paymentStatus;
// i++;
// }
// System.out.println("line :-193 :--->" + ps);
// if (c == 0) {
// updateOrderStatusInOrderLog(orderId, ps, payments.size(), null, null, null,
// null);
// }
// } else {
// System.out.println("No payments found for Order ID: " + orderId);
// updateOrderStatusInOrderLog(orderId, ps, payments.size(), null, null, null,
// null);
// }
// }
// } catch (RazorpayException e) {
// System.err.println("Error fetching payment status: " + e.getMessage());
// }
// }
// public void updateOrderStatusInOrderLog(String orderId, String paymentStatus,
// int pay_attemp,
// String paymentId, String amountStr, String paymentDateTicks, String
// contactNo) {
// // SQL query to update the order status in order_log table
// String sqlUpdate = "UPDATE order_log SET order_status = ? WHERE order_id =
// ?";
// double amount = 0;
// try {
// // Check the payment status and update accordingly
// if ("captured".equalsIgnoreCase(paymentStatus)) {
// // Update status to 'PAID'
// jdbcTemplate.update(sqlUpdate, "captured", orderId);
// if (amountStr != null && !amountStr.equals("0")) {
// amount = Double.parseDouble(amountStr) / 100.0;
// }
// String sqlGetTempId = "SELECT temp_booking_id FROM order_log WHERE order_id =
// ?";
// String tempid = jdbcTemplate.queryForObject(sqlGetTempId, String.class,
// orderId);
// System.out.println("==========tempid==========" + tempid);
// insertPaymentDetails(orderId, paymentId, paymentStatus, paymentDateTicks,
// contactNo, amount, tempid);
// System.out.println("Updated Order ID: " + orderId + " to PAID");
// } else if ("failed".equalsIgnoreCase(paymentStatus)) {
// // Update status to 'FAILED'
// jdbcTemplate.update(sqlUpdate, "failed", orderId);
// System.out.println("Updated Order ID: " + orderId + " to FAILED");
// } else if ("refunded".equalsIgnoreCase(paymentStatus)) {
// // Update status to 'FAILED'
// jdbcTemplate.update(sqlUpdate, "refunded", orderId);
// System.out.println("Updated Order ID: " + orderId + " to refunded");
// } else {
// jdbcTemplate.update(sqlUpdate, paymentStatus, orderId);
// System.out.println("Payment status for Order ID " + orderId
// + " is not 'captured' or 'failed'. No update performed.");
// }
// } catch (DataAccessException e) {
// System.err.println("Error while updating order status: " + e.getMessage());
// }
// }
// public void insertPaymentDetails(String orderId, String paymentId, String
// paymentStatus,
// String paymentDate, String mobileNumber, double amount, String tempid) {
// Integer pid = null;
// int bookingId = 0;
// try {
// // Step 1: Check if order_id already exists in payment table
// String checkSql = "SELECT * FROM payment WHERE order_id = ?";
// List<Map<String, Object>> ids = jdbcTemplate.queryForList(checkSql, orderId);
// if (!ids.isEmpty()) {
// // Already exists — pick first
// pid = (Integer) ids.get(0).get("id");
// bookingId = ids.get(0).get("booking_id") != null ? (Integer)
// ids.get(0).get("booking_id") : 0;
// if (bookingId == 0) {
// // checkBookingAndUpdateStatus(orderId, paymentStatus);
// initiateRefund(orderId, bookingId);
// } else {
// String bkStatus = "success";
// bkStatus = jdbcTemplate.queryForObject("SELECT booking_status FROM booking
// WHERE booking_id = ?",
// String.class, bookingId);
// if ("pending".equalsIgnoreCase(bkStatus) || bkStatus == null) {
// // checkBookingAndUpdateStatus(orderId, paymentStatus);
// initiateRefund(orderId, bookingId);
// }
// }
// System.out.println("⚠️ Payment already exists for order_id: " + orderId + ",
// using pid: " + pid);
// } else {
// // Step 2: Normalize payment status
// if ("captured".equalsIgnoreCase(paymentStatus)) {
// paymentStatus = "paid"; // ✅ convert captured to paid
// }
// // Step 3: Insert new payment
// String paymentIdStr =
// String.valueOf(paymentService.savePayment(String.valueOf(amount), paymentId,
// orderId, paymentStatus, String.valueOf(bookingId), mobileNumber));
// System.out.println("✅ Inserted new payment record for order_id: " + orderId);
// System.out.println("======================>>>>>>" + paymentIdStr);
// initiateRefund(orderId, bookingId);
// }
// } catch (Exception e) {
// System.err.println("❌ Error during insertPaymentDetails for order_id: " +
// orderId);
// e.printStackTrace();
// }
// }
// /*
// * public void checkBookingAndUpdateStatus(String orderId, String
// paymentStatus)
// * {
// * // SQL to check the booking status for this order
// * String sqlBookingStatus = "SELECT b.booking_id, b.booking_status, py.id " +
// * "FROM order_log ol " +
// * "JOIN payment py ON ol.order_id = py.order_id " +
// * "JOIN booking b ON py.booking_id = b.booking_id " +
// * "WHERE ol.order_id = ?";
// *
// *
// * try {
// * // Get the booking information
// * List<Map<String, Object>> bookingInfo =
// * jdbcTemplate.queryForList(sqlBookingStatus, orderId);
// *
// * int bookingId = 0;
// * if (!bookingInfo.isEmpty()) {
// * Map<String, Object> bookingDetails = bookingInfo.get(0);
// * String bookingStatus = (String) bookingDetails.get("booking_status");
// * bookingId = bookingDetails.get("booking_id")!=null?(Integer)
// * bookingDetails.get("booking_id"):0;
// *
// * System.out.println("Booking Status for Order ID " + orderId + ": " +
// * bookingId);
// *
// * // Case 1: If booking status is "null" or "pending", initiate refund
// * // Case 2: If payment status is "captured" (Paid) but no status in the
// * booking table, initiate refund
// * System.out.println("Booking status for Order ID " + orderId +
// * " is confirmed. No update required.");
// * initiateRefund(orderId, bookingId);
// *
// * } else {
// * System.out.println("No booking information found for Order ID: " +
// orderId);
// * initiateRefund(orderId, 0);
// * }
// * } catch (DataAccessException e) {
// * System.err.println("Error while checking and updating booking status: " +
// * e.getMessage());
// * }
// * }
// */
// // Method to initiate refund process
// private void initiateRefund(String orderId, int bookingId) {
// try {
// System.out.println("Initiating refund for Order ID: " + orderId);
// // Fetch the primary key (`id`) from the `payment` table
// String sql = "SELECT id FROM payment WHERE booking_id = ? and order_id = ? ";
// List<Integer> paymentIds = jdbcTemplate.queryForList(sql, Integer.class,
// bookingId, orderId);
// if (!paymentIds.isEmpty()) {
// int paymentId = paymentIds.get(0); // ✅ Get the first result
// System.out.println("Payment ID found: " + paymentId);
// // Call refundProcessOrder() with correct int pid
// ResponseEntity<?> response = refundService.refundProcessOrder("Refund
// Initiated", bookingId, paymentId);
// System.out.println("Refund API Response: " + response.getBody());
// } else {
// System.err.println("No payment record found for Booking ID: " + bookingId);
// }
// } catch (Exception e) {
// System.err.println("Error initiating refund for Order ID: " + orderId + ": "
// + e.getMessage());
// e.printStackTrace();
// }
// }
// // @Scheduled(fixedRate = 3000) // 300000 milliseconds = 5 minutes
// @Scheduled(cron = "0 0 1 * * *", zone = "Asia/Kolkata")
// public void refundRrnScheduler() {
// System.out.println("yes....REFUNDStatus_Check_Intiated");
// List<Map<String, Object>> list =
// refundService.getbyrefundstatus("REFUND_PROCESSED");
// for (Map<String, Object> map : list) {
// // System.out.println(map);
// if (map.get("refund_id") != null) {
// String refund_id = (String) map.get("refund_id");
// String rrn = refundStatus(refund_id);
// if (!rrn.equals("error")) {
// int id = Integer.parseInt(map.get("id") + "");
// refundService.updateRefundRrnStatus(id, map.get("refund_id").toString(), rrn,
// "REFUNDED");
// }
// }
// }
// }
// public String refundStatus(String refund_id) {
// System.out.println("yes....REFUND_PROCESSED ");
// try {
// RazorpayClient razorpayClient = new RazorpayClient(AppConstants.key_id,
// AppConstants.key_secret);
// com.razorpay.Refund refunds = razorpayClient.refunds.fetch(refund_id);
// System.out.println(refunds.get("acquirer_data").toString());
// // if(refunds.get("acquirer_data")!= null){
// JSONObject map = refunds.get("acquirer_data");
// System.out.println(map);
// if (map.get("rrn") != null && !map.get("rrn").equals("")) {
// System.out.println(map.get("rrn"));
// return map.get("rrn").toString();
// }
// // }
// } catch (Exception e) {
// e.printStackTrace();
// return "error";
// }
// return "error";
// }
// /*
// * public void checkBookingStatus(String orderId) {
// * System.out.println("🔍 Checking booking status for order_id: " + orderId);
// *
// * try {
// * // Step 1: Fetch booking_id from payment table using order_id
// * String getBookingIdSql = "SELECT booking_id FROM payment WHERE order_id =
// ?";
// * Integer bookingId = jdbcTemplate.queryForObject(getBookingIdSql,
// * Integer.class, orderId);
// *
// * if (bookingId != null) {
// * // Step 2: Fetch booking status using booking_id
// * String getBookingStatusSql =
// * "SELECT booking_status FROM booking WHERE booking_id = ?";
// * String bookingStatus = jdbcTemplate.queryForObject(getBookingStatusSql,
// * String.class, bookingId);
// *
// * System.out.println("➡ Booking ID: " + bookingId + " | Status: " +
// * bookingStatus);
// *
// * // If status is success, do nothing
// * if ("success".equalsIgnoreCase(bookingStatus)) {
// * System.out.println("✅ Booking is successful. No refund required.");
// * } else {
// * System.out.println("⚠️ Booking is not successful. Initiating refund...");
// *
// * initiateRefund(orderId, bookingId);
// * }
// * } else {
// *
// * System.out.println("⚠️ No booking_id found for order_id: " + orderId +
// * ". Initiating refund...");
// * initiateRefund(orderId, 0);
// * }
// *
// * } catch (EmptyResultDataAccessException e) {
// * System.out.println("⚠️ No booking_id or status found for order_id: " +
// * orderId + ". Initiating refund...");
// * initiateRefund(orderId, 0);
// * } catch (Exception e) {
// * System.err.println("❌ Error in checkBookingStatus for order_id: " +
// orderId);
// * e.printStackTrace();
// * }
// * }
// */
// // public void initiateRefundlog(String orderId, Integer bookingId) {
// // System.out.println("yes....REFUNDStatus_Check_Intiated");
// // // String refundStatus = "refunded";
// // String sql = "INSERT INTO refund_log (order_id, booking_id) VALUES (?,
// ?)";
// // }
// }

15
src/main/java/com/gcc/flagpoles/constants/AppConstants.java

@ -0,0 +1,15 @@
package com.gcc.flagpoles.constants;
public final class AppConstants {
// for Production
// public static String key_id="rzp_live_66FhxMUNAb9McO";
// public static String key_secret="aoIzMGQE3xOxin92rYaK75jV";
//uncomment for testing payment
public static String key_id="rzp_test_TADBzz8BXbBpos";
public static String key_secret="3es3YZ3DFVYdibbGLBtL8nBB";
}

762
src/main/java/com/gcc/flagpoles/controller/ApiController.java

@ -0,0 +1,762 @@
package com.gcc.flagpoles.controller;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.gcc.flagpoles.configuration.AppConfig;
//import org.json.JSONObject;
import com.gcc.flagpoles.constants.AppConstants;
import com.gcc.flagpoles.service.PaymentService;
import com.razorpay.Order;
import com.razorpay.RazorpayClient;
import com.razorpay.RazorpayException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gcc.flagpoles.service.RequestService;
// import com.dumpregistration.configuration.AppConfig;
// import com.dumpregistration.constants.AppConstants;
// import com.dumpregistration.service.PaymentService;
// import com.dumpregistration.service.RequestService;
// import com.fasterxml.jackson.databind.ObjectMapper;
// import com.razorpay.Order;
// import com.razorpay.RazorpayClient;
// import com.razorpay.RazorpayException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
@RestController
@RequestMapping("/flagpolesregistration/api")
public class ApiController {
@Autowired
private RequestService requestService;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private PaymentService paymentService;
// @Autowired
// private PaymentService paymentService ;
@Autowired
private AppConfig appConfig;
/* ///////////////// otp configuration ///////////////////// */
// send otp for registered user
@GetMapping(value = "/sendOTPforregistereduser")
public String sendOtpforregistereduser(HttpServletRequest request, @RequestParam String mobile) {
// Create an ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
// Create a response map
Map<String, Object> response = new HashMap<>();
String MobileNo = mobile;
System.out.print("\n MobileNo---:" + mobile);
Random rand = new Random();
// int otp = rand.nextInt(90000) + 10000;
int otp = 22222;
System.out.print("\n otp---:" + otp);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-yyyy%20HH:mm");
LocalDateTime now = LocalDateTime.now();
System.out.println(dtf.format(now));
// String generatedToken = "Welcome to GCC! Your OTP for C%26D waste collectors
// Registration process is "+otp;
// String generatedToken = "Welcome to GCC "+otp+" is your OTP for gcc QR
// System";
// String generatedToken = "Welcome to GCC! Your OTP for C and D waste
// collectors Registration process is " + otp;
// // String key="qxg4mklD";
// String key = "pfTEYN6H";
// String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP&key=" + key +
// "&sender=GCCCRP&to=" + MobileNo
// + "&body=" + generatedToken +
// "&entityid=1401572690000011081&templateid=1407172967243483268";
String key = "pfTEYN6H";
String entityId = "1401572690000011081";
String templateId = "1407175765770900925";
String appName = "Flagpoles";
String generatedMessage = "Welcome to GCC! Your OTP for " + appName + " is " + otp + ".";
String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP" + "&key=" + key + "&sender=GCCCRP" + "&to="
+ MobileNo + "&body="
+ generatedMessage + "&entityid=" + entityId + "&templateid=" + templateId;
// String urlString =
// "https://tmegov.onex-aura.com/api/sms?from=GCCCRP&key=pfTEYN6H&sender=GCCCRP&to=9360777472&body=Welcome%20to%20GCC!%20Your%20OTP%20for%20C%26D%20waste%20collectors%20Registration%20process%20is%20"+otp+"&entityid=1401572690000011081&templateid=1407172959127552127";
// String urlString=
// appConfig.getGetOtpUrl()+"from=GCCCRP&key="+key+"&sender=GCCCRP&to="+MobileNo+"&body="+generatedToken+"&entityid=1401572690000011081&templateid=1407168250479102852";
// String
// urlString=appConfig.getGetOtpUrl()+"user=GCCtrans&authkey=92kOC1RBGBIws&sender=GCCCRP&mobile="+MobileNo+"&text="+generatedToken+"&rpt=1&summary=1&output=json&entityid=1401572690000011081&templateid=1407168250479102852";
System.out.print("\n urlString---: " + urlString);
String bodyMessage = "";
try {
RestTemplate restTemplate = new RestTemplate();
String Response = restTemplate.getForObject(urlString, String.class);
bodyMessage = Response;
System.out.println("\n bodyMessage" + bodyMessage);
System.out.println("OTP sent successfully!");
} catch (Exception e) {
System.out.print("ERROR---: " + e);
bodyMessage = "Error";
}
HttpSession session = request.getSession();
session.setAttribute("otp", otp);
return bodyMessage;
}
// verify without registered user
@GetMapping(value = "/sendOTP")
public String sendOtp(HttpServletRequest request, @RequestParam String mobile) {
// Create an ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
// Check if mobile number is already registered
// List<WasteRegistration> registrations =
// wasteregistrationrepo.findByMobileNo(mobile);
// Create a response map
Map<String, Object> response = new HashMap<>();
// if (registrations.isEmpty()) {
// // If mobile number is not registered
// response.put("status", "NOT_REGISTERED");
// response.put("mobile", mobile); // Return the mobile number
// try {
// return objectMapper.writeValueAsString(response); // Use the instance to
// convert map to JSON string
// } catch (Exception e) {
// // Handle JSON conversion error
// return "{\"status\": \"ERROR\", \"message\": \"Could not convert response to
// JSON.\"}";
// }
// }
String MobileNo = mobile;
System.out.print("\n MobileNo---:" + mobile);
Random rand = new Random();
// int otp = rand.nextInt(90000) + 10000;
int otp = 22222;
System.out.print("\n otp---:" + otp);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-yyyy%20HH:mm");
LocalDateTime now = LocalDateTime.now();
System.out.println(dtf.format(now));
// String generatedToken = "Welcome to GCC! Your OTP for C%26D waste collectors
// Registration process is "+otp;
// String generatedToken = "Welcome to GCC "+otp+" is your OTP for gcc QR
// System";
// String generatedToken = "Welcome to GCC! Your OTP for C and D waste
// collectors Registration process is " + otp;
// // String key="qxg4mklD";
// String key = "pfTEYN6H";
// String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP&key=" + key +
// "&sender=GCCCRP&to=" + MobileNo
// + "&body=" + generatedToken +
// "&entityid=1401572690000011081&templateid=1407172967243483268";
String key = "pfTEYN6H";
String entityId = "1401572690000011081";
String templateId = "1407175765770900925";
String appName = "Flagpoles";
String generatedMessage = "Welcome to GCC! Your OTP for " + appName + " is " + otp + ".";
String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP" + "&key=" + key + "&sender=GCCCRP" + "&to="
+ MobileNo + "&body="
+ generatedMessage + "&entityid=" + entityId + "&templateid=" + templateId;
// String urlString =
// "https://tmegov.onex-aura.com/api/sms?from=GCCCRP&key=pfTEYN6H&sender=GCCCRP&to=9360777472&body=Welcome%20to%20GCC!%20Your%20OTP%20for%20C%26D%20waste%20collectors%20Registration%20process%20is%20"+otp+"&entityid=1401572690000011081&templateid=1407172959127552127";
// String urlString=
// appConfig.getGetOtpUrl()+"from=GCCCRP&key="+key+"&sender=GCCCRP&to="+MobileNo+"&body="+generatedToken+"&entityid=1401572690000011081&templateid=1407168250479102852";
// String
// urlString=appConfig.getGetOtpUrl()+"user=GCCtrans&authkey=92kOC1RBGBIws&sender=GCCCRP&mobile="+MobileNo+"&text="+generatedToken+"&rpt=1&summary=1&output=json&entityid=1401572690000011081&templateid=1407168250479102852";
System.out.print("\n urlString---: " + urlString);
String bodyMessage = "";
try {
RestTemplate restTemplate = new RestTemplate();
String Response = restTemplate.getForObject(urlString, String.class);
bodyMessage = Response;
System.out.println("\n bodyMessage" + bodyMessage);
System.out.println("OTP sent successfully!");
} catch (Exception e) {
System.out.print("ERROR---: " + e);
bodyMessage = "Error";
}
HttpSession session = request.getSession();
session.setAttribute("otp", otp);
return bodyMessage;
}
@GetMapping(value = "/verifyOTP")
public String verifyOtp(HttpServletRequest request, @RequestParam String otp) {
HttpSession session = request.getSession();
try {
Integer session_otp = (Integer) session.getAttribute("otp");
System.out.println("session_otp---:" + session_otp);
Integer entered_otp = Integer.parseInt(otp);
if (session_otp != null && session_otp.equals(entered_otp)) {
System.out.println("Entered OTP Correct");
session.setAttribute("verifiedotp", "success");
return "Success";
} else {
System.out.println("Incorrect OTP. Please enter correct OTPs.");
session.setAttribute("verifiedotp", "error");
return "Error";
}
} catch (NumberFormatException e) {
System.out.println("Invalid OTP format: " + otp);
return "Error";
} catch (Exception e) {
System.out.println("Error verifying OTP: " + e.getMessage());
return "Error";
}
}
@PostMapping("/saveRequest")
public ResponseEntity<?> saveRequest(@RequestParam MultiValueMap<String, String> params) {
try {
// ✅ 1. Extract Applicant Info
Map<String, Object> applicant = new HashMap<>();
applicant.put("name", params.getFirst("name"));
applicant.put("mobileNumber", params.getFirst("mobileNumber"));
applicant.put("address", params.getFirst("address"));
if (applicant.get("name") == null || applicant.get("mobileNumber") == null
|| applicant.get("address") == null) {
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", "Applicant details are incomplete."));
}
// ✅ 2. Extract Event Info (with cost-related fields)
Map<String, Object> event = new HashMap<>();
event.put("type", params.getFirst("eventType"));
event.put("date", params.getFirst("eventDate"));
event.put("description", params.getFirst("description"));
event.put("totalPoles", params.getFirst("totalPoles"));
// event.put("deposit", params.getFirst("deposit"));
event.put("totalCost", params.getFirst("totalCost"));
if (event.get("type") == null || event.get("date") == null || event.get("description") == null) {
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", "Event details are incomplete."));
}
// ✅ 3. Build List of Streets
List<Map<String, Object>> streets = new ArrayList<>();
int index = 0;
String globalRatePerPole = params.getFirst("ratePerPole"); // top-level
while (true) {
String prefix = "streets[" + index + "].";
if (params.getFirst(prefix + "streetName") == null)
break;
Map<String, Object> s = new HashMap<>();
s.put("streetName", params.getFirst(prefix + "streetName"));
s.put("zoneId", params.getFirst(prefix + "zone"));
s.put("wardId", params.getFirst(prefix + "ward"));
s.put("noOfPoles", params.getFirst(prefix + "noOfPoles"));
s.put("poleHeight", params.getFirst(prefix + "poleHeight"));
s.put("poleMaterial", params.getFirst(prefix + "poleMaterial"));
s.put("flagMaterial", params.getFirst(prefix + "flagMaterial"));
s.put("spacing", params.getFirst(prefix + "spacing"));
s.put("durationDays", params.getFirst(prefix + "durationDays"));
// ✅ Ensure latitude/longitude keys match your service
s.put("lat", params.getFirst(prefix + "lat"));
s.put("long", params.getFirst(prefix + "long"));
// ✅ Fix here: use top-level rate if per-street is null
String rate = params.getFirst(prefix + "ratePerPole");
s.put("ratePerPole", rate != null ? rate : globalRatePerPole);
// ⚙️ Optional validation
if (s.get("lat") == null || s.get("long") == null) {
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", "Latitude and Longitude are required for all streets."));
}
streets.add(s);
index++;
}
if (streets.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", "No street data found in request."));
}
// System.out.println("applicant" + applicant);
// System.out.println("streets" + streets);
// System.out.println("events" + event);
// ✅ 4. Save request (Service internally checks for nearby requests)
// String userReqId = requestService.saveFlagPoleRequest(applicant, event,
// streets);
String tempRefId = requestService.saveTempBooking(applicant, event, streets);
// ✅ 5. Return Success Response
return ResponseEntity.ok(Map.of(
"status", "success",
"message", "Application saved successfully.",
"request_id", tempRefId));
} catch (IllegalArgumentException iae) {
// ⛔ Custom validation or nearby request check failure
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", iae.getMessage()));
} catch (Exception e) {
// ⛔ Unexpected errors
e.printStackTrace();
return ResponseEntity.internalServerError().body(Map.of(
"status", "error",
"message", "Server error: " + e.getMessage()));
}
}
@GetMapping("/searchRequestStatus")
public ResponseEntity<?> searchRequestStatus(
@RequestParam(required = false) String refId,
@RequestParam(required = false) String mobileNo) {
try {
List<Map<String, Object>> result = requestService.searchRequestsByRefIdOrMobile(refId, mobileNo);
return ResponseEntity.ok(
Map.of(
"status", "success",
"count", result.size(),
"data", result));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(
Map.of(
"status", "error",
"message", "Failed to fetch data",
"error", e.getMessage()));
}
}
@GetMapping("/getFineDetails")
public ResponseEntity<?> getFineDetails(
@RequestParam String refId) {
try {
List<Map<String, Object>> result = requestService.getFineDetails(refId);
return ResponseEntity.ok(
Map.of(
"status", "success",
"count", result.size(),
"data", result));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(
Map.of(
"status", "error",
"message", "Failed to fetch data",
"error", e.getMessage()));
}
}
// Helper method for bad requests
private ResponseEntity<Map<String, Object>> badRequest(String message) {
return ResponseEntity.badRequest().body(Map.of("status", "error", "message", message));
}
private boolean isEmpty(Object val) {
return val == null || val.toString().trim().isEmpty();
}
// payment related api
// // old
// @PostMapping("/create_order")
// @ResponseBody
// public String createOrder(@RequestBody Map<String, Object> data) throws
// RazorpayException {
// System.out.println("Received JSON Body: " + data);
// String ref_id = data.get("id").toString();
// // double amount=Double.parseDouble("50");
// System.out.println("ref_id>>>>>>>>>>>>>" + ref_id);
// // List<Map<String, Object>> userDetails =
// // requestService.getUserDetails(ref_id);
// List<Map<String, Object>> userDetails =
// requestService.getUserDetailsfromTemp(ref_id);
// System.out.println("Fetched User Details: " + userDetails);
// Map<String, Object> userDetail = userDetails.get(0); // Get first map
// Object chargeObj = userDetail.get("total_cost");
// System.out.println();
// double amount = Math.ceil(Double.parseDouble(chargeObj.toString()) * 100);
// // var client= new
// // RazorpayClient("rzp_live_ySI5Ns54Y7qOcJ","Nwf1TjhUtaskof8vePkRR8Sb");
// // var client= new
// // RazorpayClient("rzp_test_tDkHFEqWXmuEi8","cBQUjMcKZ4J6vmOKSyNZ92py");
// System.out.println("amount:-->" + amount);
// // To enable testing mode in appConstants if required for testing &
// // development
// var client = new RazorpayClient(AppConstants.key_id,
// AppConstants.key_secret);
// // System.out.println("client details " + client);
// JSONObject options = new JSONObject();
// options.put("amount", amount);
// options.put("currency", "INR");
// // options.put("receipt","Pet_ID/"+pet_id);
// Order od = client.orders.create(options);
// // paymentService.saveorderLog("FP" + od.get("id").toString(), od.toString(),
// // ref_id);
// paymentService.saveorderLog(od.get("id").toString(), od.toString(), ref_id);
// System.out.println(od);
// return od.toString();
// }
@PostMapping("/create_order")
@ResponseBody
public String createOrder(@RequestBody Map<String, Object> data)
throws RazorpayException {
String refId = data.get("id").toString();
// 🔥 Detect where data exists
boolean isFinal = requestService.existsInFinal(refId);
List<Map<String, Object>> list = isFinal
? requestService.getFinalDetailsByRefId(refId)
: requestService.getDetailsByRequestIdTemp(refId);
if (list.isEmpty()) {
throw new RuntimeException("No payment details found");
}
Map<String, Object> d = list.get(0);
String bookingStatus = (String) d.get("booking_payment_status");
String fineStatus = (String) d.get("fine_payment_status");
String restorationStatus = (String) d.get("restoration_payment_status");
double amount;
boolean bookingPaid = "PAID".equalsIgnoreCase(bookingStatus)
|| "COMPLETED".equalsIgnoreCase(bookingStatus);
/* ================= PAYMENT PRIORITY ================= */
// 1️⃣ Booking
if (!bookingPaid) {
amount = Double.parseDouble(d.get("total_cost").toString());
}
// 2️⃣ Fine
else if (fineStatus != null && "PENDING".equalsIgnoreCase(fineStatus)) {
amount = Double.parseDouble(d.get("fine_amount").toString());
}
// 3️⃣ Restoration
else if (restorationStatus != null && "PENDING".equalsIgnoreCase(restorationStatus)) {
amount = Double.parseDouble(d.get("restoration_amount").toString());
} else {
throw new RuntimeException("No pending payment");
}
long paise = Math.round(amount * 100);
RazorpayClient client = new RazorpayClient(AppConstants.key_id, AppConstants.key_secret);
JSONObject options = new JSONObject();
options.put("amount", paise);
options.put("currency", "INR");
Order order = client.orders.create(options);
// ✅ Save order log with SAME refId (FINAL or TEMP)
paymentService.saveorderLog(
order.get("id").toString(),
order.toString(),
refId);
return order.toString();
}
// @PostMapping("/Confirm")
// public ResponseEntity<?> updateOrder(@RequestBody Map<String, Object> data) {
// String tempRefId = data.get("id").toString();
// String refId = (String) data.get("id");
// String pay_id = data.get("payment_id").toString();
// String order_id = data.get("order_id").toString();
// String status = data.get("status").toString();
// String amt = data.get("amt").toString();
// String mobileNumber = data.get("mobile_no").toString();
// DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
// LocalDateTime now = LocalDateTime.now();
// System.out.println(data);
// // Move temp → final
// paymentService.savePayment(
// data.get("amt").toString(),
// data.get("payment_id").toString(),
// data.get("order_id").toString(),
// data.get("status").toString(),
// tempRefId,
// data.get("mobile_no").toString());
// String finalRefId = requestService.moveTempToFinal(tempRefId);
// // paymentService.savePayment(amt, pay_id, order_id, status, refId,
// // mobileNumber);
// return ResponseEntity.ok(Map.of("msg", "updated"));
// }
// old yogi
// @PostMapping("/Confirm")
// @Transactional
// public ResponseEntity<?> confirmPayment(@RequestBody Map<String, Object>
// data) {
// String tempRefId = data.get("id").toString();
// // Save payment
// paymentService.savePayment(
// data.get("amt").toString(),
// data.get("payment_id").toString(),
// data.get("order_id").toString(),
// data.get("status").toString(),
// tempRefId,
// data.get("mobile_no").toString());
// // 2 Update TEMP payment status
// requestService.updateTempPaymentStatus(tempRefId, "COMPLETED");
// // Move temp → final
// String finalRefId = requestService.moveTempToFinal(tempRefId);
// return ResponseEntity.ok(Map.of(
// "status", "success",
// "request_id", finalRefId));
// }
// @PostMapping("/Confirm")
// @Transactional
// public ResponseEntity<?> confirmPayment(@RequestBody Map<String, Object>
// data) {
// String tempRefId = data.get("id").toString();
// String amount = data.get("amt").toString();
// // 🔹 Get temp details
// Map<String, Object> details =
// requestService.getDetailsByRequestIdTemp(tempRefId).get(0);
// String bookingStatus = (String) details.get("booking_payment_status");
// boolean bookingPaid = "PAID".equalsIgnoreCase(bookingStatus)
// || "COMPLETED".equalsIgnoreCase(bookingStatus);
// /* 🔴 BOOKING PAYMENT */
// if (!bookingPaid) {
// // 1️⃣ Update TEMP payment status
// requestService.updateTempPaymentStatus(tempRefId, "COMPLETED");
// // 2️⃣ Move TEMP → FINAL and get finalRefId
// String finalRefId = requestService.moveTempToFinal(tempRefId);
// // 3️⃣ NOW save payment with FINAL refId ✅
// paymentService.savePayment(
// amount,
// data.get("payment_id").toString(),
// data.get("order_id").toString(),
// data.get("status").toString(),
// finalRefId, // ✅ IMPORTANT
// data.get("mobile_no").toString());
// return ResponseEntity.ok(Map.of(
// "status", "success",
// "paymentType", "BOOKING",
// "request_id", finalRefId));
// }
// throw new IllegalStateException("Invalid payment state");
// }
@PostMapping("/Confirm")
@Transactional
public ResponseEntity<?> confirmPayment(@RequestBody Map<String, Object> data) {
String refId = data.get("id").toString();
String amount = data.get("amt").toString();
boolean isFinal = requestService.existsInFinal(refId);
Map<String, Object> details = isFinal
? requestService.getFinalDetailsByRefId(refId).get(0)
: requestService.getDetailsByRequestIdTemp(refId).get(0);
String bookingStatus = (String) details.get("booking_payment_status");
String fineStatus = (String) details.get("fine_payment_status");
String restorationStatus = (String) details.get("restoration_payment_status");
/* ================= BOOKING ================= */
if (!"PAID".equalsIgnoreCase(bookingStatus)
&& !"COMPLETED".equalsIgnoreCase(bookingStatus)) {
requestService.updateTempPaymentStatus(refId, "COMPLETED");
String finalRefId = requestService.moveTempToFinal(refId);
paymentService.savePayment(
amount,
data.get("payment_id").toString(),
data.get("order_id").toString(),
data.get("status").toString(),
finalRefId,
data.get("mobile_no").toString(),
"BOOKING" // ✅
);
return ResponseEntity.ok(Map.of(
"status", "success",
"paymentType", "BOOKING",
"request_id", finalRefId));
}
/* ================= FINE ================= */
if ("PENDING".equalsIgnoreCase(fineStatus)) {
requestService.updateFinePaymentStatus(refId);
paymentService.savePayment(
amount,
data.get("payment_id").toString(),
data.get("order_id").toString(),
data.get("status").toString(),
refId,
data.get("mobile_no").toString(),
"FINE" // ✅
);
return ResponseEntity.ok(Map.of(
"status", "success",
"paymentType", "FINE",
"request_id", refId));
}
/* ================= RESTORATION ================= */
if ("PENDING".equalsIgnoreCase(restorationStatus)) {
requestService.updateRestorationPaymentStatus(refId);
paymentService.savePayment(
amount,
data.get("payment_id").toString(),
data.get("order_id").toString(),
data.get("status").toString(),
refId,
data.get("mobile_no").toString(),
"RESTORATION" // ✅
);
return ResponseEntity.ok(Map.of(
"status", "success",
"paymentType", "RESTORATION",
"request_id", refId));
}
throw new IllegalStateException("No pending payment");
}
// 🔴 CANCEL EVENT
@PostMapping("/cancelEvent")
public ResponseEntity<Map<String, String>> cancelEvent(
@RequestParam String refId) {
String result = requestService.cancelEvent(refId);
return ResponseEntity.ok(Map.of("status", result));
}
// 🟡 POSTPONE EVENT
@PostMapping("/postponeEvent")
public ResponseEntity<Map<String, String>> postponeEvent(
@RequestParam String refId,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate newDate) {
String result = requestService.postponeEvent(refId, newDate);
return ResponseEntity.ok(Map.of("status", result));
}
@GetMapping("/checkUserExists")
public Map<String, Object> checkUserExists(@RequestParam String mobile) {
Map<String, Object> response = new HashMap<>();
boolean exists = requestService.isUserExistsByMobile(mobile);
response.put("exists", exists);
if (!exists) {
response.put("message", "Mobile number not registered. Please register first.");
}
return response;
}
}

35
src/main/java/com/gcc/flagpoles/controller/DateTimeUtil.java

@ -0,0 +1,35 @@
// package com.gcc.flagpoles.controller;
// import org.springframework.stereotype.Service;
// import java.time.LocalDateTime;
// import java.time.format.DateTimeFormatter;
// @Service
// public class DateTimeUtil {
// public static String getCurrentDateTime() {
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyyyHHmmss");
// LocalDateTime now = LocalDateTime.now();
// return now.format(formatter);
// }
// public static String getCurrentYear() {
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
// LocalDateTime now = LocalDateTime.now();
// return now.format(formatter);
// }
// public static String getCurrentMonth() {
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM");
// LocalDateTime now = LocalDateTime.now();
// return now.format(formatter);
// }
// public static String getCurrentDay() {
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd");
// LocalDateTime now = LocalDateTime.now();
// return now.format(formatter);
// }
// public static String getCurrentDateTimeMysql() {
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime now = LocalDateTime.now();
// return now.format(formatter);
// }
// }

77
src/main/java/com/gcc/flagpoles/controller/DropDownApiController.java

@ -0,0 +1,77 @@
package com.gcc.flagpoles.controller;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.gcc.flagpoles.service.DropDownService;
@RestController
@RequestMapping("/flagpolesregistration/dropdown/api")
public class DropDownApiController {
@Autowired
private DropDownService dropDownService;
@GetMapping("/getpolemateriallist")
public List<Map<String, Object>> getPoleMaterialList() {
return dropDownService.getPoleMaterialList();
}
@GetMapping("/geteventtype")
public List<Map<String, Object>> getEventTypesList() {
return dropDownService.getEventTypes();
}
// get the vehicles
@GetMapping("/getallflagmaterial")
public List<Map<String, Object>> getFlagMaterialList() {
return dropDownService.getFlagMaterialList();
}
// GET: /flagpoles/api/location/getZoneWard?streetName=Velachery
@GetMapping("/getZoneWard")
public Map<String, Object> getZoneAndWard(@RequestParam String streetName) {
// System.out.println("Received street name: " + streetName);
return dropDownService.getZoneAndWardByStreet(streetName);
}
// get the waste charges
@GetMapping("/getallcharges")
public List<Map<String, Object>> getpaymentcharges() {
return dropDownService.getAllcharges();
}
@GetMapping("/getallzones")
public ResponseEntity<?> getAllZones() {
try {
List<Map<String, Object>> response = dropDownService.getZonesList();
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("error", "Failed to fetch data: " + e.getMessage()));
}
}
@GetMapping("/getwardsbyzone")
public ResponseEntity<?> getWardsByZone(@RequestParam int zoneId) {
try {
List<Map<String, Object>> response = dropDownService.getWardsByZoneId(zoneId);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("error", "Failed to fetch data: " + e.getMessage()));
}
}
}

281
src/main/java/com/gcc/flagpoles/controller/MainController.java

@ -0,0 +1,281 @@
package com.gcc.flagpoles.controller;
import java.util.List;
import java.util.Map;
import com.gcc.flagpoles.service.RequestService;
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;
@Controller
@RequestMapping(value = { "/flagpolesregistration" })
public class MainController {
@Autowired
private RequestService requestService;
@GetMapping(value = { "", "/", "/index" })
public String requestform() {
return "modules/flagpolesregistration/index";
}
// @GetMapping("/paymentform")
// public String paymentform(@RequestParam("requestId") String requestId, Model
// model) {
// List<Map<String, Object>> detailsList =
// requestService.getDetailsByRequestId(requestId);
// if (!detailsList.isEmpty()) {
// Map<String, Object> requestData = detailsList.get(0);
// model.addAttribute("requestData", requestData); //
// String paymentStatus = (String) requestData.get("payment_status");
// if ("pending".equalsIgnoreCase(paymentStatus)) {
// return "modules/dumpwastecollector/paymentrequestform";
// } else {
// return "modules/dumpwastecollector/acknowledgement";
// }
// }
// model.addAttribute("message", "No details found for Request ID: " +
// requestId);
// return "modules/dumpwastecollector/nodatafound";
// }
// Register pages flagpoles
@GetMapping("/register")
public String wastecollectorsregister(Model model) {
return "modules/flagpolesregistration/requestform";
}
// Status pages flagpoles
@GetMapping("/status")
public String wastecollectorsstatus(Model model) {
return "modules/flagpolesregistration/status";
}
// old payment form
// @GetMapping("/paymentform")
// public String paymentform(@RequestParam("requestId") String requestId, Model
// model) {
// boolean isFinal = requestService.existsInFinal(requestId);
// List<Map<String, Object>> list = isFinal
// ? requestService.getFinalDetailsByRefId(requestId)
// : requestService.getDetailsByRequestIdTemp(requestId);
// if (list.isEmpty()) {
// model.addAttribute("message", "No details found");
// return "modules/flagpolesregistration/nodatafound";
// }
// Map<String, Object> data = list.get(0);
// model.addAttribute("requestData", data);
// List<Map<String, Object>> streetList = isFinal
// ? requestService.getFinalStreetDetails(requestId)
// : requestService.getTempStreetDetails(requestId);
// model.addAttribute("streetList", streetList);
// String bookingStatus = (String) data.get("booking_payment_status");
// String fineStatus = (String) data.get("fine_payment_status");
// String restorationStatus = (String) data.get("restoration_payment_status");
// boolean bookingPaid = "PAID".equalsIgnoreCase(bookingStatus)
// || "COMPLETED".equalsIgnoreCase(bookingStatus);
// /* BOOKING PAYMENT */
// if (!bookingPaid) {
// model.addAttribute("paymentType", "FLAGPOLE BOOKING");
// model.addAttribute("paymentDesc", "Flagpole Booking Charges");
// model.addAttribute("displayAmount", data.get("total_cost"));
// return "modules/flagpolesregistration/paymentrequestform";
// }
// /* FINE PAYMENT */
// if (fineStatus != null && "PENDING".equalsIgnoreCase(fineStatus)) {
// model.addAttribute("paymentType", "FLAGPOLE FINE");
// model.addAttribute("paymentDesc", "Flagpole Fine Charges");
// model.addAttribute("displayAmount", data.get("fine_amount"));
// return "modules/flagpolesregistration/paymentrequestform";
// }
// /* RESTORATION PAYMENT */
// if (restorationStatus != null &&
// "PENDING".equalsIgnoreCase(restorationStatus)) {
// model.addAttribute("paymentType", "FLAGPOLE RESTORATION");
// model.addAttribute("paymentDesc", "Flagpole Restoration Charges");
// model.addAttribute("displayAmount", data.get("restoration_amount"));
// return "modules/flagpolesregistration/paymentrequestform";
// }
// /* ACKNOWLEDGEMENT */
// if (fineStatus != null) {
// model.addAttribute("paymentType", "FLAGPOLE FINE COLLECTION");
// model.addAttribute("paymentDesc", "Flagpole Fine Charges");
// } else if (restorationStatus != null) {
// model.addAttribute("paymentType", "FLAGPOLE RESTORATION COLLECTION");
// model.addAttribute("paymentDesc", "Flagpole Restoration Charges");
// } else {
// model.addAttribute("paymentType", "FLAGPOLE BOOKING ");
// model.addAttribute("paymentDesc", "Flagpole Booking Charges");
// }
// return "modules/flagpolesregistration/acknowledgement";
// }
// payment related api
@GetMapping("/paymentform")
public String paymentform(
@RequestParam("requestId") String requestId,
@RequestParam(value = "type", required = false) String type,
Model model) {
boolean isFinal = requestService.existsInFinal(requestId);
List<Map<String, Object>> list = isFinal
? requestService.getFinalDetailsByRefId(requestId)
: requestService.getDetailsByRequestIdTemp(requestId);
if (list.isEmpty()) {
model.addAttribute("message", "No details found");
return "modules/flagpolesregistration/nodatafound";
}
Map<String, Object> data = list.get(0);
model.addAttribute("requestData", data);
List<Map<String, Object>> streetList = isFinal
? requestService.getFinalStreetDetails(requestId)
: requestService.getTempStreetDetails(requestId);
model.addAttribute("streetList", streetList);
String bookingStatus = (String) data.get("booking_payment_status");
String fineStatus = (String) data.get("fine_payment_status");
String restorationStatus = (String) data.get("restoration_payment_status");
boolean bookingPaid = "PAID".equalsIgnoreCase(bookingStatus)
|| "COMPLETED".equalsIgnoreCase(bookingStatus);
boolean fineApplicable = fineStatus != null;
boolean finePaid = fineApplicable &&
("PAID".equalsIgnoreCase(fineStatus) || "COMPLETED".equalsIgnoreCase(fineStatus));
boolean restorationApplicable = restorationStatus != null;
boolean restorationPaid = restorationApplicable &&
("PAID".equalsIgnoreCase(restorationStatus) || "COMPLETED".equalsIgnoreCase(restorationStatus));
/* ================= ACKNOWLEDGEMENT MODE ================= */
if (type != null) {
String paymentTypeKey = type.toUpperCase();
Map<String, Object> payment = null;
switch (paymentTypeKey) {
case "BOOKING":
if (!bookingPaid) {
model.addAttribute("message", "Booking payment not completed");
return "modules/flagpolesregistration/nodatafound";
}
payment = requestService.getPaymentByRefIdAndType(requestId, "BOOKING");
model.addAttribute("paymentType", "FLAGPOLE BOOKING");
model.addAttribute("paymentDesc", "Flagpole Booking Charges");
model.addAttribute("displayAmount", data.get("total_cost"));
break;
case "FINE":
if (!fineApplicable) {
model.addAttribute("message", "Fine is not applicable for this request");
return "modules/flagpolesregistration/nodatafound";
}
if (!finePaid) {
model.addAttribute("message", "Fine payment not completed");
return "modules/flagpolesregistration/nodatafound";
}
payment = requestService.getPaymentByRefIdAndType(requestId, "FINE");
model.addAttribute("paymentType", "FLAGPOLE FINE COLLECTION");
model.addAttribute("paymentDesc", "Flagpole Fine Charges");
model.addAttribute("displayAmount", data.get("fine_amount"));
break;
case "RESTORATION":
if (!restorationApplicable) {
model.addAttribute("message", "Restoration is not applicable for this request");
return "modules/flagpolesregistration/nodatafound";
}
if (!restorationPaid) {
model.addAttribute("message", "Restoration payment not completed");
return "modules/flagpolesregistration/nodatafound";
}
payment = requestService.getPaymentByRefIdAndType(requestId, "RESTORATION");
model.addAttribute("paymentType", "FLAGPOLE RESTORATION COLLECTION");
model.addAttribute("paymentDesc", "Flagpole Restoration Charges");
model.addAttribute("displayAmount", data.get("restoration_amount"));
break;
default:
model.addAttribute("message", "Invalid payment type");
return "modules/flagpolesregistration/nodatafound";
}
// ✅ Final safety check
if (payment == null) {
model.addAttribute("message", "Payment record not found");
return "modules/flagpolesregistration/nodatafound";
}
model.addAttribute("payment", payment);
return "modules/flagpolesregistration/acknowledgement";
}
/* ================= PAYMENT FLOW ================= */
if (!bookingPaid) {
model.addAttribute("paymentType", "FLAGPOLE BOOKING");
model.addAttribute("paymentDesc", "Flagpole Booking Charges");
model.addAttribute("displayAmount", data.get("total_cost"));
return "modules/flagpolesregistration/paymentrequestform";
}
if (fineApplicable && "PENDING".equalsIgnoreCase(fineStatus)) {
model.addAttribute("paymentType", "FLAGPOLE FINE");
model.addAttribute("paymentDesc", "Flagpole Fine Charges");
model.addAttribute("displayAmount", data.get("fine_amount"));
return "modules/flagpolesregistration/paymentrequestform";
}
if (restorationApplicable && "PENDING".equalsIgnoreCase(restorationStatus)) {
model.addAttribute("paymentType", "FLAGPOLE RESTORATION");
model.addAttribute("paymentDesc", "Flagpole Restoration Charges");
model.addAttribute("displayAmount", data.get("restoration_amount"));
return "modules/flagpolesregistration/paymentrequestform";
}
model.addAttribute("message", "No pending payments");
return "modules/flagpolesregistration/nodatafound";
}
}

179
src/main/java/com/gcc/flagpoles/controller/RefundController.java

@ -0,0 +1,179 @@
package com.gcc.flagpoles.controller;
import com.gcc.flagpoles.constants.AppConstants;
import com.gcc.flagpoles.service.BookingService;
import com.gcc.flagpoles.service.RefundService;
import com.razorpay.RazorpayClient;
import com.razorpay.RazorpayException;
import com.razorpay.Refund;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
@RestController
@RequestMapping("/flagpolesregistration/book/api")
public class RefundController {
@Autowired
private RefundService refundService;
// @Autowired
// private RefundScheduler refundScheduler;
@Autowired
BookingService bookingService;
@Autowired
JdbcTemplate jdbcTemplate;
@PostMapping("/initiateRefund")
public ResponseEntity<?> initiateRefund(
@RequestParam("refId") String refId,
@RequestParam(value = "reason", defaultValue = "Event cancelled by user") String reason) {
try {
// 1️⃣ Fetch booking + payment data
Map<String, Object> booking = refundService.getBookingForRefund(refId);
System.out.println("Booking: " + booking);
// 2️⃣ Validate eligibility
refundService.validateRefundEligibility(booking);
// 3️⃣ Razorpay refund
Refund refund = refundService.initiateRazorpayRefund(
(String) booking.get("payment_id"),
((Number) booking.get("amount")).doubleValue());
System.out.println("Refund: " + refund);
// 4️⃣ Extract refund amount
double refundAmount = refund.get("amount") != null
? ((Number) refund.get("amount")).doubleValue() / 100
: ((Number) booking.get("amount")).doubleValue();
System.out.println("Refund Amount: " + refundAmount);
// 5️⃣ Finalize refund ✅ FIXED
refundService.finalizeRefund(
refId,
((Number) booking.get("booking_id")).intValue(),
((Number) booking.get("payment_db_id")).intValue(),
(String) booking.get("order_id"),
refundAmount,
refund.get("id").toString(),
refund.get("status").toString(),
reason);
return ResponseEntity.ok(Map.of(
"status", "REFUND_INITIATED",
"refund_id", refund.get("id").toString(),
"refund_status", refund.get("status").toString()));
} catch (IllegalStateException e) {
return ResponseEntity.badRequest().body(e.getMessage());
} catch (RazorpayException e) {
return ResponseEntity.status(500)
.body("Razorpay Error: " + e.getMessage());
} catch (Exception e) {
return ResponseEntity.status(500)
.body("Refund Failed: " + e.getMessage());
}
}
// @PostMapping("/initiateRefund")
// public ResponseEntity<?> initiateRefund(
// @RequestParam("orderId") String orderId,
// @RequestParam("bookingId") int bookingId,
// @RequestParam(value = "reason", defaultValue = "Manual refund") String
// reason) {
// try {
// // Step 1: Get payment ID and amount using orderId
// String sql = "SELECT id, payment_id, amount FROM payment WHERE order_id = ?";
// Map<String, Object> result = jdbcTemplate.queryForMap(sql, orderId);
// int pid = (int) result.get("id");
// String paymentId = (String) result.get("payment_id");
// double amount = Double.parseDouble(result.get("amount").toString());
// // Step 2: Initiate refund via Razorpay
// RazorpayClient razorpayClient = new RazorpayClient(AppConstants.key_id,
// AppConstants.key_secret);
// JSONObject refundRequest = new JSONObject();
// refundRequest.put("amount", (int) (amount * 100)); // Razorpay expects paise
// Refund refund = razorpayClient.payments.refund(paymentId, refundRequest);
// // Step 3: Extract refund response details
// String refundId = refund.get("id");
// String refundStatus = refund.get("status");
// double refundAmount = Double.parseDouble(refund.get("amount").toString()) /
// 100.0;
// Object createdAtObj = refund.get("created_at");
// long createdAtEpoch;
// if (createdAtObj instanceof Number) {
// createdAtEpoch = ((Number) createdAtObj).longValue();
// } else if (createdAtObj instanceof Date) {
// createdAtEpoch = ((Date) createdAtObj).toInstant().getEpochSecond();
// } else {
// throw new IllegalArgumentException("Unexpected type for created_at: " +
// createdAtObj.getClass());
// }
// LocalDateTime createdAt = Instant.ofEpochSecond(createdAtEpoch)
// .atZone(ZoneId.of("Asia/Kolkata"))
// .toLocalDateTime();
// // Step 4: Save refund record
// refundService.saveRefund(bookingId, pid, refundAmount, refundId,
// refundStatus, reason);
// // Step 5: Update status in payment and order_log tables
// // jdbcTemplate.update("UPDATE order_log SET order_status = ? WHERE order_id
// =
// // ?", "" orderId);
// jdbcTemplate.update("UPDATE payment SET payment_status = ? WHERE order_id =
// ?", "refunded", orderId);
// // Step 6: Print refund info to console
// System.out.println("✅ Refund initiated successfully:");
// System.out.println("Refund ID : " + refundId);
// System.out.println("Payment ID : " + paymentId);
// System.out.println("Refund Amount : ₹" + refundAmount);
// System.out.println("Refund Status : " + refundStatus);
// System.out.println("Refunded At : " + createdAt);
// System.out.println("📝 payment tables updated to 'refund'.");
// // Step 7: Return response
// Map<String, Object> responseMap = new HashMap<>();
// responseMap.put("refund_id", refundId);
// responseMap.put("status", refundStatus);
// responseMap.put("amount", refundAmount);
// responseMap.put("created_at", createdAt.toString());
// return ResponseEntity.ok(responseMap);
// } catch (RazorpayException e) {
// e.printStackTrace();
// String errorMsg = e.getMessage();
// System.err.println("Razorpay Error: " + errorMsg);
// if (errorMsg.contains("already")) {
// return ResponseEntity.status(400).body("Refund already completed for this
// payment.");
// }
// return ResponseEntity.status(500).body("Razorpay Error: " + e.getMessage());
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(500).body("Error: " + e.getMessage());
// }
// }
}

19
src/main/java/com/gcc/flagpoles/service/BookingService.java

@ -0,0 +1,19 @@
package com.gcc.flagpoles.service;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class BookingService {
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getTempBookingByTempId(int tempbookid) {
String sql = "SELECT * FROM temp_request_details where tempbookid = ?";
return jdbcTemplate.queryForMap(sql, tempbookid);
}
}

183
src/main/java/com/gcc/flagpoles/service/DropDownService.java

@ -0,0 +1,183 @@
package com.gcc.flagpoles.service;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class DropDownService {
@Autowired
private JdbcTemplate jdbcTemplate;
// @Autowired
// private RestTemplate restTemplate;
// @Autowired
// private AppConfig appConfig;
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
private static final String STREET_API = "https://gccservices.in/gccrestservices/api/location/getDetails?address=";
public List<Map<String, Object>> getPoleMaterialList() {
String sql = " SELECT * FROM pole_material where is_active = '1' ";
return jdbcTemplate.queryForList(sql);
}
public List<Map<String, Object>> getEventTypes() {
String sql = " SELECT * FROM event_type where is_active = '1' ";
return jdbcTemplate.queryForList(sql);
}
public List<Map<String, Object>> getFlagMaterialList() {
String sql = "SELECT * FROM flag_material where is_active = '1' ";
return jdbcTemplate.queryForList(sql);
}
public Map<String, Object> getZoneAndWardByStreet(String streetName) {
Map<String, Object> responseMap = new LinkedHashMap<>();
RestTemplate restTemplate = new RestTemplate();
try {
if (streetName == null || streetName.trim().isEmpty()) {
responseMap.put("status", "error");
responseMap.put("message", "Street name is required.");
return responseMap;
}
// Step 1️⃣: Get latitude & longitude
String encodedStreet = URLEncoder.encode(streetName.trim(), StandardCharsets.UTF_8);
String url1 = STREET_API + encodedStreet;
ResponseEntity<String> response1 = restTemplate.getForEntity(url1, String.class);
JSONObject json1 = new JSONObject(response1.getBody());
System.out.println("Response from STREET_API: " + json1);
String latitude = json1.optString("latitude", "");
String longitude = json1.optString("longitude", "");
if (latitude.isEmpty() || longitude.isEmpty()) {
responseMap.put("status", "error");
responseMap.put("message", "Latitude/Longitude not found for this street.");
return responseMap;
}
// Step 2️⃣: Encode geometry safely
String geometryJson = String.format("{\"y\":%s,\"x\":%s}", latitude, longitude);
String encodedGeometry = URLEncoder.encode(geometryJson, StandardCharsets.UTF_8);
String url2 = "https://gisgcc.chennaicorporation.gov.in/server/rest/services/GCCDepts/EDPMobile2025/FeatureServer/2/query"
+
"?where=&objectIds=&time=&geometry=" + encodedGeometry +
"&geometryType=esriGeometryPoint" +
"&inSR=4326" +
"&defaultSR=4326" +
"&spatialRel=esriSpatialRelIntersects" +
"&distance=1" +
"&units=esriSRUnit_Meter" +
"&relationParam=&outFields=zone,ward" +
"&returnGeometry=false" +
"&returnDistinctValues=false" +
"&returnIdsOnly=false" +
"&returnCountOnly=false" +
"&returnExtentOnly=false" +
"&orderByFields=&groupByFieldsForStatistics=&outStatistics=" +
"&returnZ=false&returnM=false" +
"&multipatchOption=xyFootprint" +
"&resultOffset=&resultRecordCount=" +
"&returnTrueCurves=false" +
"&returnExceededLimitFeatures=false" +
"&quantizationParameters=&returnCentroid=false" +
"&timeReferenceUnknownClient=false" +
"&maxRecordCountFactor=&sqlFormat=none" +
"&resultType=&featureEncoding=esriDefault" +
"&datumTransformation=&f=geojson";
System.out.println("Fetching Zone/Ward with URL: " + url2);
// ✅ Use URI to avoid template parsing issues
ResponseEntity<String> response2 = restTemplate.getForEntity(new URI(url2), String.class);
System.out.println("Response from ZONE_WARD_API: " + response2.getBody());
JSONObject json2 = new JSONObject(response2.getBody());
if (!json2.has("features") || json2.getJSONArray("features").isEmpty()) {
responseMap.put("status", "error");
responseMap.put("message", "Zone/Ward not found for this location.");
return responseMap;
}
JSONObject properties = json2.getJSONArray("features")
.getJSONObject(0)
.getJSONObject("properties");
String zone = properties.optString("zone", "N/A");
String ward = properties.optString("ward", "N/A");
// ✅ Success
responseMap.put("status", "success");
responseMap.put("streetName", streetName);
responseMap.put("latitude", latitude);
responseMap.put("longitude", longitude);
responseMap.put("zone", zone);
responseMap.put("ward", ward);
} catch (Exception e) {
e.printStackTrace();
responseMap.put("status", "error");
responseMap.put("message", "Failed to fetch data: Internal server error.");
}
return responseMap;
}
public List<Map<String, Object>> getAllcharges() {
String sql = "SELECT * FROM waste_collection_charges where is_active = 1 ";
return jdbcTemplate.queryForList(sql);
}
// public Map<String, Object> fetchZones() throws Exception {
// String apiUrl = appConfig.getErpUrl() + "serviceId=getZones";
// ResponseEntity<String> response = restTemplate.getForEntity(apiUrl,
// String.class);
// return objectMapper.readValue(response.getBody(), Map.class);
// }
// public Map<String, Object> fetchWardsByZoneId(String zoneId) throws Exception
// {
// String apiUrl = appConfig.getErpUrl() + "serviceId=getWards&Zoneid=" +
// zoneId;
// ResponseEntity<String> response = restTemplate.getForEntity(apiUrl,
// String.class);
// return objectMapper.readValue(response.getBody(), Map.class);
// }
// get zones
public List<Map<String, Object>> getZonesList() {
String sql = " SELECT id,zone_name from zones where is_active = 1 ";
return jdbcTemplate.queryForList(sql);
}
// get wardsby zone id
public List<Map<String, Object>> getWardsByZoneId(int zoneId) {
String sql = "SELECT id, ward_name FROM wards WHERE zone_id = ? AND is_active = 1 ";
return jdbcTemplate.queryForList(sql, zoneId);
}
}

154
src/main/java/com/gcc/flagpoles/service/PaymentService.java

@ -0,0 +1,154 @@
package com.gcc.flagpoles.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Service
public class PaymentService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private RequestService requestService;
@Autowired
private WhatsappMessageService whatsappMessageService;
@Transactional
public int saveorderLog(
String order_id,
String order_info,
String ref_id) {
int lastInsertId = 0;
String sqlQuery = "INSERT INTO `order_log`(`order_id`, `order_info`, `ref_id`) "
+ "VALUES (?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
try {
int affectedRows = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sqlQuery, new String[] { "id" });
ps.setString(1, order_id);
ps.setString(2, order_info);
ps.setString(3, ref_id);
return ps;
}
}, keyHolder);
if (affectedRows > 0) {
Number generatedId = keyHolder.getKey();
lastInsertId = (generatedId != null) ? generatedId.intValue() : 0;
return lastInsertId;
} else {
System.out.println("Error on temp save!");
}
} catch (DataAccessException e) {
System.out.println("Data Access Exception:");
Throwable rootCause = e.getMostSpecificCause();
if (rootCause instanceof SQLException) {
SQLException sqlException = (SQLException) rootCause;
System.out.println("SQL State: " + sqlException.getSQLState());
System.out.println("Error Code: " + sqlException.getErrorCode());
System.out.println("Message: " + sqlException.getMessage());
} else {
System.out.println("Message: " + rootCause.getMessage());
}
}
return 0;
}
@Transactional
public int savePayment(String totalAmount,
String payment_id,
String payment_orderid,
String payment_status,
String refId,
String mobile_no,
String paymentType) {
int lastInsertId = 0;
String sqlQuery = "INSERT INTO `payment`(`amount`, `mobile_no`, `order_id`, `payment_id`, `paymentstatus`, `payment_date`, `ref_id`, `payment_type`) "
+ "VALUES (?,?,?,?,?,?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
try {
int affectedRows = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sqlQuery, new String[] { "id" });
ps.setString(1, totalAmount);
ps.setString(2, mobile_no);
ps.setString(3, payment_orderid);
ps.setString(4, payment_id);
ps.setString(5, payment_status);
ps.setString(6, LocalDateTime.now().toString());
ps.setString(7, refId);
ps.setString(8, paymentType);
return ps;
}
}, keyHolder);
if (affectedRows > 0) {
Number generatedId = keyHolder.getKey();
lastInsertId = (generatedId != null) ? generatedId.intValue() : 0;
String mobileNumber = mobile_no;
double actualWeight = 100;
double totalCharge = Integer.parseInt(totalAmount);
if ("paid".equalsIgnoreCase(payment_status)) {
requestService.updatePaymentStatus(refId);
requestService.updatePaymentStatusInOrderLog(refId, payment_orderid);
// whatsappMessageService.sendrequestraisedWhatsappMessage(refId, mobileNumber);
// whatsappMessageService.sendPaymentCompleteWhatsappMessage(refId,
// actualWeight, totalCharge, mobileNumber);
}
return lastInsertId;
} else {
System.out.println("Error on temp save!");
return 0;
}
} catch (DataAccessException e) {
System.out.println("Data Access Exception:");
Throwable rootCause = e.getMostSpecificCause();
if (rootCause instanceof SQLException) {
SQLException sqlException = (SQLException) rootCause;
System.out.println("SQL State: " + sqlException.getSQLState());
System.out.println("Error Code: " + sqlException.getErrorCode());
System.out.println("Message: " + sqlException.getMessage());
} else {
System.out.println("Message: " + rootCause.getMessage());
}
return 0;
}
}
}

323
src/main/java/com/gcc/flagpoles/service/RefundService.java

@ -0,0 +1,323 @@
package com.gcc.flagpoles.service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.gcc.flagpoles.constants.AppConstants;
import com.razorpay.RazorpayClient;
import com.razorpay.RazorpayException;
import com.razorpay.Refund;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class RefundService {
@Autowired
PaymentService paymentService;
@Autowired
BookingService bookingService;
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Map<String, Object>> refund(int refund_id) {
String refundsql = "select * from refund_info where refund_id=?";
return jdbcTemplate.queryForList(refundsql.toString(), refund_id);
}
public Map<String, Object> getBookingForRefund(String refId) {
List<Map<String, Object>> list = jdbcTemplate.queryForList("""
SELECT
urd.id AS booking_id,
urd.refid,
urd.event_date,
urd.payment_status,
p.id AS payment_db_id,
p.payment_id,
p.order_id,
p.amount,
p.paymentstatus
FROM user_request_details urd
JOIN payment p ON p.ref_id = urd.refid
WHERE urd.refid = ?
AND p.paymentstatus IN ('paid', 'PAID', 'COMPLETED')
""", refId);
if (list.isEmpty()) {
throw new IllegalStateException(
"No eligible payment found for refund for refId: " + refId);
}
return list.get(0);
}
public void validateRefundEligibility(Map<String, Object> booking) {
Object eventDateObj = booking.get("event_date");
LocalDateTime eventDate;
if (eventDateObj instanceof LocalDateTime) {
eventDate = (LocalDateTime) eventDateObj;
} else if (eventDateObj instanceof Timestamp) {
eventDate = ((Timestamp) eventDateObj).toLocalDateTime();
} else {
throw new IllegalStateException("Invalid event_date type: " + eventDateObj);
}
String bookingPaymentStatus = (String) booking.get("payment_status");
if (!"COMPLETED".equalsIgnoreCase(bookingPaymentStatus)) {
throw new IllegalStateException("Payment not completed");
}
String paymentTableStatus = (String) booking.get("paymentstatus");
if ("refunded".equalsIgnoreCase(paymentTableStatus)) {
throw new IllegalStateException("Refund already processed");
}
if (LocalDateTime.now().isAfter(eventDate.minusHours(24))) {
throw new IllegalStateException("Refund not allowed within 24 hours of event");
}
}
public Refund initiateRazorpayRefund(
String paymentId,
double amount) throws RazorpayException {
RazorpayClient razorpayClient = new RazorpayClient(AppConstants.key_id, AppConstants.key_secret);
JSONObject refundRequest = new JSONObject();
refundRequest.put("amount", (int) (amount * 100)); // paise
return razorpayClient.payments.refund(paymentId, refundRequest);
}
@Transactional
public void finalizeRefund(
String refId,
int bookingId,
int paymentDbId,
String orderId,
double refundAmount,
String refundId,
String refundStatus,
String reason) {
// 1️⃣ Save refund record (USING EXISTING METHOD)
saveRefund(
bookingId, // ✅ correct
paymentDbId, // pid
refundAmount,
refundId,
refundStatus,
reason);
// 2️⃣ Update payment table
jdbcTemplate.update("""
UPDATE payment
SET paymentstatus = 'refunded'
WHERE order_id = ?
""", orderId);
// 3️⃣ Update booking status
jdbcTemplate.update("""
UPDATE user_request_details
SET booking_status = 'CANCELLED'
WHERE refid = ?
""", refId);
}
public int saveRefund(int bookingId, int pid, double refundAmount, String refundId, String refundStatus,
String desc) {
List<Map<String, Object>> result = null;
Map<String, Object> response = new HashMap<>();
int calendarId = 0;
String sqlQuery = "INSERT INTO refund_info (bookingId, refund_amt, balance_amt, pid, refund_id, cdate, refund_status, r_desc) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
System.out.println("Inserting Refund Info:");
System.out.println(" bookingId = " + bookingId);
System.out.println(" refundAmount = " + refundAmount);
System.out.println(" pid = " + pid);
System.out.println(" refundId = " + refundId);
System.out.println(" refundStatus = " + refundStatus);
System.out.println(" desc = " + desc);
try {
int affectedRows = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
PreparedStatement ps = connection.prepareStatement(sqlQuery, new String[] { "id" });
ps.setInt(1, bookingId); // Fix: Use setInt for bookingId
ps.setDouble(2, refundAmount); // Fix: Use setDouble for refund_amt
ps.setDouble(3, 0.0); // Fix: Add balance_amt (defaulting to 0)
ps.setInt(4, pid); // Fix: Use setInt for pid
ps.setString(5, refundId);
ps.setString(6, refundStatus);
ps.setString(7, desc);
return ps;
}
}, keyHolder);
if (affectedRows > 0) {
Number generatedId = keyHolder.getKey();
calendarId = (generatedId != null) ? generatedId.intValue() : 0;
return calendarId;
} else {
return 10;
}
} catch (DataAccessException e) {
System.out.println("Data Access Exception:");
Throwable rootCause = e.getMostSpecificCause();
if (rootCause instanceof SQLException) {
SQLException sqlException = (SQLException) rootCause;
System.out.println("SQL State: " + sqlException.getSQLState());
System.out.println("Error Code: " + sqlException.getErrorCode());
System.out.println("Message: " + sqlException.getMessage());
return 0;
} else {
System.out.println("Message: " + rootCause.getMessage());
return 0;
}
}
}
// public ResponseEntity<?> refundProcessOrder(String msg, int bookingId, int
// pid) {
// try {
// Map<String, Object> pay = paymentService.getPaymentById(pid);
// if (pay == null || pay.isEmpty()) {
// return ResponseEntity.badRequest().body("No payment found for given id");
// }
// String paymentId = pay.get("payment_id").toString();
// double amount = Double.parseDouble(pay.get("amount") + "");
// RazorpayClient razorpay = new RazorpayClient(AppConstants.key_id,
// AppConstants.key_secret);
// JSONObject refundRequest = new JSONObject();
// refundRequest.put("amount", amount * 100);
// refundRequest.put("speed", "normal");
// JSONObject notes = new JSONObject();
// notes.put("notes_key_1", msg);
// refundRequest.put("notes", notes);
// com.razorpay.Refund payment = razorpay.payments.refund(paymentId,
// refundRequest);
// JSONObject pj = payment.toJson();
// //new update
// System.err.println("Refund Process Order:line 216");
// System.err.println(pj);
// System.err.println("refundProcessOrder->"+pj.get("id")+"bookingId:-"+bookingId
// +"pid:-"+pid);
// if (pj.get("id") != null) {
// double amt = (pj.get("amount") != null) ?
// (Double.parseDouble(pj.get("amount") + "") / 100) : 0;
// saveRefundOrder(bookingId, pid, amt, pj.get("id").toString(),
// "REFUND_PROCESSED", pj.toString());
// if(bookingId != 0) {
// bookingService.updateBookingStatus(bookingId, "refunded");
// }
// } else {
// saveRefundOrder(bookingId, pid, 0, "", "REJECTED", pj.toString());
// }
// return ResponseEntity.ok(pj.toString());
// } catch (RazorpayException e) {
// if (e.getMessage().contains("fully refunded")) {
// System.err.println("Already refunded: " + e.getMessage());
// saveRefundOrder(bookingId, pid, 0, "", "ALREADY_REFUNDED", e.getMessage());
// if(bookingId != 0) {
// bookingService.updateBookingStatus(bookingId, "refunded");
// }
// return ResponseEntity.ok("Already refunded");
// }
// return ResponseEntity.status(500).body("Refund failed: " + e.getMessage());
// }
// }
// public int saveRefundOrder(int bookingId, int pid, double refundAmount,
// String refundId, String refundStatus, String desc) {
// try {
// updateRefundStatusInOrderLog(pid, true);
// // Insert new refund record
// String sqlQuery = "INSERT INTO refund_info (bookingId, refund_amt,
// balance_amt, pid, refund_id, refund_status, r_desc) VALUES (?, ?, ?, ?, ?, ?,
// ?)";
// KeyHolder keyHolder = new GeneratedKeyHolder();
// int affectedRows = jdbcTemplate.update(connection -> {
// PreparedStatement ps = connection.prepareStatement(sqlQuery, new
// String[]{"id"});
// ps.setInt(1, bookingId);
// ps.setDouble(2, refundAmount);
// ps.setDouble(3, 0.0);
// ps.setInt(4, pid);
// ps.setString(5, refundId);
// ps.setString(6, refundStatus);
// ps.setString(7, desc != null ? desc : "");
// return ps;
// }, keyHolder);
// if (affectedRows > 0) {
// Number generatedId = keyHolder.getKey();
// return (generatedId != null) ? generatedId.intValue() : -1;
// } else {
// return -1; // Indicate failure
// }
// } catch (EmptyResultDataAccessException e) {
// System.err.println("No existing refund record found, proceeding with
// insert.");
// } catch (DataAccessException e) {
// System.err.println("saveRefundOrder Database error: " + e.getMessage());
// }
// return -1;
// }
// public void updateRefundStatusInOrderLog(int pid, boolean
// isRefundedProcessed) {
// String sql = "UPDATE order_log od inner join payment pay on od.order_id =
// pay.order_id SET od.sch_refund_status = ? WHERE pay.id = ?";
// jdbcTemplate.update(sql, isRefundedProcessed, pid);
// }
}

1337
src/main/java/com/gcc/flagpoles/service/RequestService.java
File diff suppressed because it is too large
View File

39
src/main/java/com/gcc/flagpoles/service/SMSService.java

@ -0,0 +1,39 @@
package com.gcc.flagpoles.service;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.net.HttpURLConnection;
import java.net.URL;
@Service
public class SMSService {
public String sendMsg(String msgUrl) {
System.out.println("Whatsapp URL :-" + msgUrl);
String response = "";
try {
HttpURLConnection connection = null;
URL url = new URL(msgUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
response = responseCode + "";
System.out.println("Response Code: " + responseCode);
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
public String sendSMS(String SMS_Url) {
System.out.println("SMS URL:- " + SMS_Url);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(SMS_Url, String.class);
return response;
}
}

147
src/main/java/com/gcc/flagpoles/service/WhatsappMessageService.java

@ -0,0 +1,147 @@
package com.gcc.flagpoles.service;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class WhatsappMessageService {
@Autowired
private SMSService smsService;
// c & d waste template after user register
public void sendrequestraisedWhatsappMessage(String refId, String mobileNumber) {
try {
String apiUrl = "https://media.smsgupshup.com/GatewayAPI/rest?userid=2000233507&password=h2YjFNcJ&send_to="
+ mobileNumber
+ "&v=1.1&format=json&msg_type=TEXT&method=SENDMESSAGE&msg=Thank+you%21+Your+request+has+been+successfully+submitted.%0ARequest+Id+%3A+"
+ refId
+ "&isTemplate=true&header=C%26D+Waste+Collection+Request+Registered&footer=Greater+Chennai+Corporation";
System.out.println("WhatsApp API URL: " + apiUrl); // Optional debug
smsService.sendMsg(apiUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
// payment complete template
public void sendPaymentCompleteWhatsappMessage(String refId, double actualWeight, double totalCharge,
String mobileNumber) {
try {
String message = String.format(
"Your request (Request ID: *%s*) has been processed. Please proceed with the payment.\n\nActual Weight: *%.0f kg*\nAmount Payable: *%.0f*",
refId, actualWeight, totalCharge);
String encodedMessage = URLEncoder.encode(message, StandardCharsets.UTF_8);
String encodedHeader = URLEncoder.encode("C&D Waste Collection – Payment Request", StandardCharsets.UTF_8);
String encodedFooter = URLEncoder.encode("Greater Chennai Corporation", StandardCharsets.UTF_8);
String redirectUrlParam = URLEncoder.encode(
"http://localhost:8077/flagpolesregistration/paymentform?requestId=" + refId,
StandardCharsets.UTF_8);
String apiUrl = "https://media.smsgupshup.com/GatewayAPI/rest?userid=2000233507" +
"&password=h2YjFNcJ" +
"&send_to=" + mobileNumber +
"&v=1.1&format=json&msg_type=TEXT&method=SENDMESSAGE" +
"&msg=" + encodedMessage +
"&isTemplate=true" +
"&header=" + encodedHeader +
"&footer=" + encodedFooter +
"&buttonUrlParam=" + redirectUrlParam;
// Optional: log URL before hitting for debugging
System.out.println("WhatsApp API URL: " + apiUrl);
// Make API call
// restTemplate.getForObject(apiUrl, String.class);
smsService.sendMsg(apiUrl);
} catch (Exception e) {
e.printStackTrace();
// Optionally log or alert failure
}
}
// for fine collection
public void sendFineCollectionWhatsappMessage(String refId, double actualWeight, double totalCharge,
String mobileNumber) {
try {
String message = String.format(
"Your request (Request ID: *%s*) has been processed. Please proceed with the payment.\n\nActual Weight: *%.0f kg*\nAmount Payable: *%.0f*",
refId, actualWeight, totalCharge);
String encodedMessage = URLEncoder.encode(message, StandardCharsets.UTF_8);
String encodedHeader = URLEncoder.encode("C&D Waste Collection – Payment Request", StandardCharsets.UTF_8);
String encodedFooter = URLEncoder.encode("Greater Chennai Corporation", StandardCharsets.UTF_8);
String redirectUrlParam = URLEncoder.encode(
"http://localhost:8077/flagpolesregistration/paymentform?requestId=" + refId,
StandardCharsets.UTF_8);
String apiUrl = "https://media.smsgupshup.com/GatewayAPI/rest?userid=2000233507" +
"&password=h2YjFNcJ" +
"&send_to=" + mobileNumber +
"&v=1.1&format=json&msg_type=TEXT&method=SENDMESSAGE" +
"&msg=" + encodedMessage +
"&isTemplate=true" +
"&header=" + encodedHeader +
"&footer=" + encodedFooter +
"&buttonUrlParam=" + redirectUrlParam;
// Optional: log URL before hitting for debugging
System.out.println("WhatsApp API URL: " + apiUrl);
// Make API call
// restTemplate.getForObject(apiUrl, String.class);
smsService.sendMsg(apiUrl);
} catch (Exception e) {
e.printStackTrace();
// Optionally log or alert failure
}
}
// restoration message
public void sendRestorationWhatsappMessage(String refId, double actualWeight, double totalCharge,
String mobileNumber) {
try {
String message = String.format(
"Your request (Request ID: *%s*) has been processed. Please proceed with the payment.\n\nActual Weight: *%.0f kg*\nAmount Payable: *%.0f*",
refId, actualWeight, totalCharge);
String encodedMessage = URLEncoder.encode(message, StandardCharsets.UTF_8);
String encodedHeader = URLEncoder.encode("C&D Waste Collection – Payment Request", StandardCharsets.UTF_8);
String encodedFooter = URLEncoder.encode("Greater Chennai Corporation", StandardCharsets.UTF_8);
String redirectUrlParam = URLEncoder.encode(
"http://localhost:8077/flagpolesregistration/paymentform?requestId=" + refId,
StandardCharsets.UTF_8);
String apiUrl = "https://media.smsgupshup.com/GatewayAPI/rest?userid=2000233507" +
"&password=h2YjFNcJ" +
"&send_to=" + mobileNumber +
"&v=1.1&format=json&msg_type=TEXT&method=SENDMESSAGE" +
"&msg=" + encodedMessage +
"&isTemplate=true" +
"&header=" + encodedHeader +
"&footer=" + encodedFooter +
"&buttonUrlParam=" + redirectUrlParam;
// Optional: log URL before hitting for debugging
System.out.println("WhatsApp API URL: " + apiUrl);
// Make API call
// restTemplate.getForObject(apiUrl, String.class);
smsService.sendMsg(apiUrl);
} catch (Exception e) {
e.printStackTrace();
// Optionally log or alert failure
}
}
}

33
src/main/resources/application-dev.properties

@ -0,0 +1,33 @@
spring.application.name=flagpolesregistration
spring.datasource.url=jdbc:mysql://localhost:3306/gcc_flag_pole
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=8083
spring.servlet.multipart.max-file-size=20MB
# file.upload.directory=${user.dir}/gccoffice_uploads
# file.dump.upload.directory=${user.dir}/cd_waste_docs/cdwaste_dump
# file.fullpath=/
# file.dump.fullpath=/cd_waste_docs/
fileBaseUrl=http://localhost:8083
payment.razorpay.my_key_id="rzp_test_tDkHFEqWXmuEi8"
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms?
app.erpUrl=https://erp.chennaicorporation.gov.in/pgr/external/mobileservice?
# dump_directory=cdwaste_dump

31
src/main/resources/application-prod.properties

@ -0,0 +1,31 @@
spring.application.name=flagpolesregistration
spring.datasource.url=jdbc:mysql://gcc-facial-db-instance-1.cf48eqcciziq.ap-south-1.rds.amazonaws.com:3306/gcc_flag_pole
spring.datasource.username=root
spring.datasource.password=gcc-facial-password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=8083
#production port = 8083
spring.servlet.multipart.max-file-size=20MB
# file.upload.directory=${user.dir}/gccoffice_uploads
# file.dump.upload.directory=${user.dir}/cd_waste_docs/cdwaste_dump
# file.fullpath=/
# file.dump.fullpath=/cd_waste_docs/
fileBaseUrl=https://gccservices.in
payment.razorpay.my_key_id="rzp_test_tDkHFEqWXmuEi8"
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms?
app.erpUrl=https://erp.chennaicorporation.gov.in/pgr/external/mobileservice?
# dump_directory=cdwaste_dump

1
src/main/resources/application.properties

@ -0,0 +1 @@
spring.profiles.active=dev

188
src/main/resources/templates/fragments/details.html

@ -0,0 +1,188 @@
<div id="pcoded" class="pcoded">
<div class="pcoded-container" id="acknowledgement-section">
<!-- Menu header -->
<div class="header d-flex justify-content-between align-items-center">
<div class="logo">
<img src="https://gccservices.in/gcc/assets/images/logo.png" alt="Logo">
</div>
<div class="center-text">
GREATER CHENNAI CORPORATION
</div>
</div>
<!-- Main content -->
<div class="container-fluid">
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="card" style="width: 90%; max-width: 1060px; margin: 0 auto;">
<div class="card-body">
<!-- Acknowledgement Header -->
<div style="text-align: center; margin-bottom: 20px;">
<h6 style="font-weight: bold; text-decoration: underline;">
<span style="list-style-type: none; margin: 0; padding: 0; font-size:23px;"
th:text="'ACKNOWLEDGEMENT FOR ' + ${paymentType} + ' PAYMENT'"></span>
</h6>
<!-- <h6 style="font-weight: bold; text-decoration: underline;">
<ul style="list-style-type: none; margin: 0; padding: 0; font-size:18px; ">
ACKNOWLEDGEMENT FOR FLAG POLE</ul>
</h6> -->
</div>
<!-- User Details -->
<div class="section"
style="display: flex; justify-content: space-between; margin-bottom: 15px;">
<!-- User Details Box -->
<div th:if="${requestData != null}" class="user-details-box"
style="border: 1px solid #ddd; border-radius: 8px; padding: 10px; width: 48%; background-color: #f9f9f9;">
<h6
style="font-weight: bold;background-color: #404E67;color: white; padding: 8px; border-radius: 5px; font-size:16px;">
User Details:</h6>
<p><strong>User Name:</strong> <span id="uName"
th:text="${requestData.applicant_name}"></span></p>
<p><strong>Mobile Number:</strong> <span id="uPhoneNumber"
th:text="${requestData.mobile_number}"></span></p>
<p><strong>Address:</strong> <span id="address"
th:text="${requestData.applicant_address}"></span></p>
</div>
<!-- Payment Details Box -->
<div class="payment-details-box"
style="border: 1px solid #ddd; border-radius: 8px; padding: 10px; width: 48%; background-color: #f9f9f9;">
<h6
style="font-weight: bold; background-color: #404E67; color: white; padding: 8px; border-radius: 5px; font-size:16px;">
Payment Details:</h6>
<!-- Check if payments is not null -->
<div th:if="${requestData != null}">
<!-- Transaction Id -->
<p><strong>Transaction Id:</strong>
<span th:text="${payment.payment_id}"></span>
</p>
<p><strong>Payment Type:</strong>
<span th:text="${paymentType}"></span>
</p>
<p><strong>Payment Date:</strong>
<span th:text="${payment.payment_date}"></span>
</p>
<p><strong>Payment Status:</strong>
<span th:text="${payment.paymentstatus}" th:class="${payment.paymentstatus == 'paid'}
? 'text-success fw-bold'
: 'text-danger fw-bold'">
</span>
</p>
<p><strong>Total Amount Paid:</strong>
<span th:text="'₹ ' + ${displayAmount}" style="font-weight:bold;"></span>
</p>
</div>
<!-- Display NA if payments is null -->
<div th:if="${requestData == null}">
<p><strong>Transaction Id:</strong> <span>NA</span></p>
<p><strong>Payment Status:</strong> <span>NA</span></p>
<p><strong>Total Amount Paid:</strong> <span>NA</span></p>
</div>
</div>
</div>
<!-- Event & Street Details Section -->
<div class="section" th:if="${requestData != null}"
style="border: 1px solid #ddd; border-radius: 8px; padding: 8px; margin-bottom: 10px; background-color: #f9f9f9;">
<h6
style="font-weight: bold; background-color: #404E67;color: white; padding: 5px; border-radius: 5px; font-size:16px;">
Event & Street Details:</h6>
<div style="display: flex; justify-content: space-between;">
<div class="request-details-left" style="width: 48%;">
<p><strong>Request Id:</strong> <span th:text="${requestData.refid}"></span></p>
<p><strong>Event Name:</strong> <span
th:text="${requestData.event_name}"></span></p>
<p><strong>Event Date:</strong> <span
th:text="${requestData.event_date}"></span></p>
</div>
<div class="request-details-right" style="width: 48%;">
<p><strong>Request Date:</strong> <span th:text="${requestData.cdate}"></span>
</p>
<p><strong>Event Conducting Days:</strong> <span
th:text="${requestData.no_of_days}"></span> Days</p>
<p><strong>Total No of Poles</strong> <span id="bookId"
th:text="${requestData.total_poles}"></span></p>
</div>
</div>
<div th:each="s : ${streetList}"
style=" padding:5px; margin-bottom:8px; border-radius:6px;">
<strong>Zone:</strong>
<span th:text="${s.zone}"></span>
|
<strong>Ward:</strong>
<span th:text="${s.ward}"></span>
|
<strong>Street Name:</strong>
<span th:text="${s.street_name}"></span>
</div>
<!--<div class="amount-details"
style="display: flex; justify-content: space-between; border-top: 1px solid #ddd; padding-top: 10px; margin-top: 10px; " >
<div class="amount-item" style="flex: 1; text-align: center;">
<p><strong>Street Name:</strong> <span
th:text="${streetList.street_name}"></span></p>
</div>
<div class="amount-item" style="flex: 1; text-align: center;">
<p><strong>Zone:</strong> <span
th:text="${streetList.vehicle_name}"></span></p>
</div>
<div class="amount-item" style="flex: 1; text-align: center;">
<p><strong>Ward:</strong> <span
th:text="${streetList.ward}"></span></p>
</div>
</div>-->
</div>
<!-- Computer Generated Note
<div class="generated-note" style="border: 1px solid #ddd; border-radius: 8px; padding: 10px; text-align: center; background-color: #f9f9f9;"> -->
<h6 style="text-align:center;font-size:15px;">* This is a computer-generated document. No
signature is required *</h6>
<p><span id="generatedDate" style="font-size:10px;"></span></p>
</div>
</div>
<!-- Buttons -->
<div class="button-container" id="downloadBtnContainer" th:if="${requestData != null}"
style="text-align:center;font-size:15px; justify-content: space-around;">
<button class="btn btn-success" onclick="downloadPDF()"
style="background: #FB6340; font-size:18px;">Download</button>
</div>
</div>
</div>
</div>
</div>
</div>

178
src/main/resources/templates/modules/flagpolesregistration/acknowledgement.html

@ -0,0 +1,178 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<style>
@media print {
/* Hide buttons when printing */
.button-container {
display: none !important;
justify-content: space-around;
}
.nav-display {
display: none !important;
}
}
.header {
background-color: #1d495a;
padding: 10px 20px;
color: white;
font-family: Arial, sans-serif;
display: flex;
justify-content: space-between;
/* Spread elements */
align-items: center;
position: relative;
/* Needed for centering the text */
}
.header .logo {
flex-shrink: 0;
/* Keep the logo at the left */
}
.header .logo img {
height: 60px;
}
.header .center-text {
position: absolute;
/* Centered text */
left: 50%;
transform: translateX(-50%);
font-size: 24px;
text-align: center;
}
</style>
</head>
<body>
<div th:replace="~{fragments/details :: div}"></div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
<script>
function downloadPDF() {
const element = document.getElementById('acknowledgement-section');
const buttonContainer = document.getElementById('downloadBtnContainer');
// Temporarily hide the button
buttonContainer.style.display = 'none';
const opt = {
margin: [0.5, 0.5, 0.5, 0.5],
filename: 'Acknowledgement_Copy.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: {
scale: 3,
useCORS: true,
allowTaint: true,
scrollX: 0,
scrollY: 0,
windowWidth: document.documentElement.scrollWidth,
windowHeight: document.documentElement.scrollHeight
},
jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' },
// pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
};
// Generate and save PDF
html2pdf().set(opt).from(element).save().then(() => {
// Show the button back after PDF is downloaded
buttonContainer.style.display = 'flex';
}).catch(() => {
// Make sure it gets shown again even on error
buttonContainer.style.display = 'flex';
});
}
function exportLicToPDF(details, requestId, format = 'a4', orientation = 'portrait') {
var parser = new DOMParser();
var doc = parser.parseFromString(details, 'text/html');
// Select the entire container element
var element = document.querySelector('#pcoded');
// Hide unwanted elements
document.querySelector('.button-container').style.display = 'none'; // Hide the button container
// Generate PDF
html2pdf().from(element).set({
margin: [0.1, 0.1, 0.1, 0.1], // Adjust margins to fit content better
filename: `BookingAck-${requestId}.pdf`, // Construct the filename with bookingId
html2canvas: {
scale: 1, // Set scale to 1 to ensure content fits on a single page
useCORS: true, // Allow cross-origin images to load
scrollX: 0,
scrollY: 0,
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight
},
jsPDF: {
unit: 'in',
format: format, // Set format to A4
orientation: orientation,
compress: true // Enable compression to reduce file size
}
}).toPdf().get('pdf').then(function (pdf) {
// Check if content fits on one page; scale down if needed
let totalHeight = element.offsetHeight;
let pageHeight = pdf.internal.pageSize.height;
if (totalHeight > pageHeight) {
pdf.internal.pageSize.height = totalHeight;
}
}).save().then(() => {
// Restore the visibility of hidden elements
document.querySelector('.button-container').style.display = 'flex'; // Show the button container again
});
}
function formatDateTime(date) {
// Format date and time
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // 24-hour time
timeZone: 'auto' // Use the user's local time zone
};
try {
return new Intl.DateTimeFormat('en-GB', options).format(date);
} catch (error) {
console.error('Error formatting date:', error);
return date.toString(); // Fallback
}
}
function updateGeneratedDate() {
const dateElement = document.getElementById('generatedDate');
if (dateElement) {
const now = new Date();
const formattedDate = formatDateTime(now);
// console.log('Formatted Date:', formattedDate); // Debug log
dateElement.textContent = formattedDate;
} else {
console.error('Date element not found');
}
}
/* function redirect(bookingtype) {
if (bookingtype === 'OFFLINE') {
window.location.href = "/communityhall/counter/counterbooking";
} else {
window.location.href = "/communityhall/user/dashboard";
}
} */
</script>
</body>
</html>

195
src/main/resources/templates/modules/flagpolesregistration/index.html

@ -0,0 +1,195 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GCC - FlagPoles</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Only load it once) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Popper.js (Required for Bootstrap 4) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<!-- SweetAlert JS (optional if you plan to use it) -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
/* Header Styling */
.header {
background-color: #1d495a;
padding: 10px 20px;
color: white;
font-family: Arial, sans-serif;
}
.header .logo img {
height: 60px;
}
.header .center-text {
text-align: center;
font-size: 24px;
}
.header .menu-btn {
background-color: transparent;
border: none;
font-size: 24px;
color: white;
}
.header .menu-btn:hover {
color: #ccc;
}
/* Menu Dropdown */
.menu-dropdown {
position: absolute;
top: 80px;
right: 20px;
background-color: #1d495a;
padding: 10px;
display: none;
flex-direction: column;
z-index: 1000; /* Add z-index to bring the menu above other elements */
}
.menu-dropdown a {
color: white;
margin-bottom: 5px;
text-decoration: none;
}
.menu-dropdown a:hover {
text-decoration: underline;
}
/* Mobile Specific Styling */
@media (max-width: 768px) {
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.center-text {
font-size: 18px !important;
flex-grow: 1;
text-align: center;
}
.menu-dropdown {
right: 0;
left: 0;
z-index: 1000; /* Add z-index to bring the menu above other elements */
}
}
</style>
</head>
<body style="background-color: #ebf1fa;">
<!-- Header Start-->
<header>
<div class="header d-flex justify-content-between align-items-center">
<!-- Left: Logo -->
<div class="logo">
<img src="https://gccservices.in/gcc/assets/images/logo.png" alt="Logo">
</div>
<!-- Center: Text -->
<div class="center-text">
GREATER CHENNAI CORPORATION
</div>
<!-- Right: Button for Menu -->
<div class="menu">
<button class="menu-btn" onclick="toggleMenu()">
&#9776; <!-- Unicode for hamburger menu icon -->
</button>
</div>
</div>
<!-- Dropdown Menu -->
<div class="menu-dropdown" id="menuDropdown">
<a href="https://chennaicorporation.gov.in/gcc/">Home</a>
<a href="https://chennaicorporation.gov.in/gcc/about-GCC/">About GCC</a>
<a href="https://chennaicorporation.gov.in/gcc/who-is-who/index_data.jsp">Who's Who</a>
<a href="https://chennaicorporation.gov.in/gcc/council/about-council/">Council</a>
<a href="https://chennaicorporation.gov.in/gcc/tender/">Tender</a>
<a href="https://chennaicorporation.gov.in/gcc/department/">Departments</a>
<a href="https://chennaicorporation.gov.in/gcc/online-services/">Online Services</a>
<a href="https://gccservices.in/gcc/login">Official Login</a>
</div>
</header>
<!-- Header End-->
<main class="container mt-4">
<!-- First Card -->
<div class="card mb-4" style="border: 1px solid #1d495a;">
<div class="card-header text-center" style="border-bottom:1px solid #1d495a; ">
<h4>FlagPoles Registration</h4>
</div>
<div class="card-body d-flex flex-column justify-content-center align-items-center" style="width: 100%;">
<div class="d-flex justify-content-between align-items-center mb-3" style="width: 70%;">
<label for="register-btn" class="text-right" style="width: 40%;">Click Here to Register:</label>
<button type="button" class="btn btn-success" id="register-btn" onclick="goToRegister()" style="width: 50%;">Register</button>
</div>
<div class="d-flex justify-content-between align-items-center" style="width: 70%;">
<label for="status-btn" class="text-right" style="width: 40%;">Click Here to Check Status:</label>
<button type="button" class="btn btn-primary" id="status-btn" onclick="goToStatus()" style="width: 50%;">Status</button>
</div>
</div>
</div>
<!-- <div class="card mb-4" style="border: 1px solid #1d495a;">
<div class="card-header text-center" style="border-bottom:1px solid #1d495a; ">
<h4>DEBRIS DUMPING SECONDARY COLLECTION CENTRE</h4>
</div>
<div class="card-body d-flex flex-column justify-content-center align-items-center" style="width: 100%;">
<a href="#" id="viewPdfLink">Click here to view</a>
PDF Viewer Div (Initially Hidden)
<div id="pdfViewer" style="display: none; width: 100%; height: 500px; margin-top: 20px;">
<iframe src="https://gccservices.in/gcc/files/c_d/DEBRIS_DUMPING_SECONDARY_COLLECTION_CENTRE.pdf" style="width: 100%; height: 100%;" frameborder="0"></iframe>
</div>
</div>
</div> -->
</main>
<script>
function toggleMenu() {
var dropdown = document.getElementById("menuDropdown");
if (dropdown.style.display === "flex") {
dropdown.style.display = "none";
} else {
dropdown.style.display = "flex";
}
}
// Function to redirect to the register page
function goToRegister() {
window.location.href = '/flagpolesregistration/register'; // Change '/register' to your actual register page URL
}
// Function to redirect to the status page
function goToStatus() {
window.location.href = '/flagpolesregistration/status'; // Change '/status' to your actual status page URL
}
</script>
</body>
</html>

101
src/main/resources/templates/modules/flagpolesregistration/nodatafound.html

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GCC - Flagpoles Registration</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Only load it once) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Popper.js (Required for Bootstrap 4) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<!-- SweetAlert JS (optional if you plan to use it) -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head>
<style>
/* Header Styling */
.header {
background-color: #1d495a;
padding: 10px 20px;
color: white;
font-family: Arial, sans-serif;
display: flex;
justify-content: space-between;
/* Spread elements */
align-items: center;
position: relative;
/* Needed for centering the text */
}
.header .logo {
flex-shrink: 0;
/* Keep the logo at the left */
}
.header .logo img {
height: 60px;
}
.header .center-text {
position: absolute;
/* Centered text */
left: 50%;
transform: translateX(-50%);
font-size: 24px;
text-align: center;
}
.required {
color: red;
}
/* Mobile Specific Styling */
@media (max-width: 768px) {
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.center-text {
font-size: 18px !important;
}
}
</style>
<!-- Header Start-->
<header>
<div class="header d-flex justify-content-between align-items-center">
<!-- Left: Logo -->
<div class="logo">
<img src="https://gccservices.in/gcc/assets/images/logo.png" alt="Logo">
</div>
<!-- Center: Text -->
<div class="center-text">
GREATER CHENNAI CORPORATION
</div>
</div>
</header>
<body style="background-color: #ebf1fa;">
<div class="container">
<div class="row justify-content-center align-items-center" style="height: 80vh;">
<div class="col-md-6 text-center">
<h3 th:text="${message}"></h3>
</div>
</div>
</div>
</body>
</html>

252
src/main/resources/templates/modules/flagpolesregistration/paymentrequestform.html

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Important for mobile responsiveness -->
<title>GCC - Flagpoles Registration</title>
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
.header {
background-color: #1d495a;
padding: 10px 20px;
color: white;
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
}
.header .logo img {
height: 50px;
margin-bottom: 5px;
}
.center-text {
font-size: 20px;
}
@media (min-width: 768px) {
.header {
flex-direction: row;
justify-content: space-between;
text-align: left;
}
.header .center-text {
font-size: 24px;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
}
</style>
</head>
<header th:replace="~{modules/flagpolesregistration/razor-pay :: header}"></header>
<body style="background-color: #ebf1fa;">
<!-- Responsive Header -->
<div class="header">
<div class="logo">
<img src="https://gccservices.in/gcc/assets/images/logo.png" alt="Logo">
</div>
<div class="center-text">GREATER CHENNAI CORPORATION</div>
</div>
<!-- Payment Details Card -->
<div class="container mt-4 mb-4">
<div class="card shadow-lg">
<div class="card-header bg-dark text-white">
<!-- <h5 class="mb-0 text-center text-md-left">Flagpole Payment Details</h5> -->
<h5 class="mb-0 text-center" th:text="${paymentDesc}">
</h5>
</div>
<div class="card-body">
<!-- Row 1 -->
<div class="form-group">
<label class="form-label fw-bold">Name:</label>
<input type="text" class="form-control" th:value="${requestData['applicant_name']}" readonly />
</div>
<div class="form-group">
<label class="form-label fw-bold">Phone No:</label>
<input type="text" id="paymentNumber" class="form-control"
th:value="${requestData['mobile_number']}" readonly />
</div>
<!-- Row 2 -->
<div class="form-group">
<label class="form-label fw-bold">Payment Purpose:</label>
<!-- <input type="text" class="form-control" value="Flag pole collection Charges" readonly /> -->
<input type="text" class="form-control" th:value="${paymentDesc}" readonly />
</div>
<div class="form-group">
<label class="form-label fw-bold">Total Amount:</label>
<!-- <input type="text" class="form-control" th:value="${requestData['total_cost']}" readonly /> -->
<input type="text" class="form-control" th:value="${displayAmount}" readonly />
</div>
<!-- Terms and Conditions Checkbox -->
<div class="form-check mt-3 text-center">
<input class="form-check-input" type="checkbox" id="termsCheck">
<label class="form-check-label" for="termsCheck">
I agree to the <a href="#" data-bs-toggle="modal" data-bs-target="#termsModal">terms and
conditions</a>.
</label>
</div>
<div class="text-center mt-4">
<span style="background-color: #f8d7da; color: #721c24; padding: 5px 10px; border-radius: 4px;">
⚠️ Important: Do not refresh or close the page after clicking the payment button until the
payment is confirmed.
</span>
</div>
<!-- Confirm Button -->
<div class="text-center mt-4">
<!-- <button type="button" class="btn btn-success btn-block btn-lg" id="submitBtn"
th:onclick="paymentStart([[${requestData.refid}]])" disabled>Confirm Payment</button> -->
<button type="button" class="btn btn-success btn-lg" id="submitBtn"
th:onclick="paymentStart([[${requestData.refid}]], '[[${paymentDesc}]]')" disabled>
Confirm Payment
</button>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="termsModal" tabindex="-1" aria-labelledby="termsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header text-white" style="background-color:#1d495a;">
<h5 class="modal-title" id="termsModalLabel">Terms and Conditions</h5>
<!-- <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button> -->
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"
style="color:black;border: white;background-color: white;">
<span aria-hidden="true">&times;</span>
</button>
</div>
<!-- <div class="modal-body border p-4">
<ol>
<li>By accepting to make Payment online it is implied that you agree to the terms and conditions
of Netbanking System/Credit Card company.</li>
<li>All payments are processed via secure third-party gateways. Greater Chennai Corporation does
not store your card or bank information.</li>
<li>The actual updation of payment by Greater Chennai Corporation will take place after getting
confirmation from the Banks.</li>
<li>All charges related to waste collection and processing fees are non-refundable once
successfully paid.</li>
<li>If a transaction fails but funds are debited, the refund will be processed automatically by
the bank/payment gateway. Greater Chennai Corporation is not responsible for delays in such
refunds.</li>
<li>In the exigency of connection getting timed out or user clicking to close the browser before
getting payment confirmation message he/she has to wait for 15 minutes before proceeding to
make subsequent payment for the same Request ID.</li>
</ol>
</div> -->
<div class="modal-body border p-4">
<ol>
<li>Payment of fees does not automatically guarantee approval of the application.</li>
<li>All applications are subject to technical scrutiny, site inspection, compliance with
applicable laws, rules, and local regulations.</li>
<li>The Authority reserves the right to approve, reject without assigning any reason.</li>
<li>Fees once paid are non-refundable, however change in date can be
permissible on availability of the selected slot.</li>
<li>The applicant is solely responsible for the correctness of the information
furnished in the application. Any false, misleading, or incomplete information may
result in rejection of the application without refund.</li>
<li>The applicant shall comply with all applicable laws, rules, guidelines, and safety
norms relating to pole erection, including road safety, public safety,
environmental protection, and utility coordination.</li>
<li>Upon successful payment, an electronic receipt or transaction reference number
will be generated and shared via SMS to the registered mobile number</li>
<li>Applicants are advised to retain the application ID for future reference.</li>
<li>In case of payment failure, the amount (if debited) will be reversed to the account
through which payment is made within 3-15 business days.</li>
<li>Temporary flagpoles shall be allowed for erection for a short period not more than three
days. (The day before the event / on day of event/ the day after the event).</li>
<li>The temporary flagpoles shall not be erected on bituminous surface of the road. i.e.,
over the riding surface of the road.</li>
<li>The temporary flagpoles may be allowed for erection only over earthen surface of the
road and the same shall not be within three meters from the edge of the Bituminous
surface/Riding Surface.</li>
<li>No temporary flagpoles shall be allowed over any types of structures (Centre median,
Footpath, Drain, Culvert, Bridges, Parapets, Road Furniture etc.,) within the Right of Way
(Row) of the Public Road.</li>
<li>The Maximum height of the temporary flagpole shall be restricted to 3.50 m from the
Ground Level (GL). The depth below Ground level shall be 1.00 m (Minimum) and it shall be
ensured that, no accidents happen due to the erection of temporary flagpoles.</li>
<li>The temporary flagpoles shall be strictly insulated during erection on the
<li>The organizers / Applicants shall ensure that the flagpoles do not touch or interfere
with electric wires, especially under low or high-tension lines by covering the top end of
the flagpole with appropriate insulation materials to avoid electrocution.</li>
<li> If any undesirable events happen, the applicant who was permitted to erect the flagpoles
is wholly responsible and any loss claimed by the affected persons shall be borne by the
applicant only. Legal action shall also be pursued in case of accidents occur.</li>
<li>If any damage is caused to public infrastructure, the person who was granted permission
/ licence shall restore the public places to its original position by cleaning and filling
up the holes and the cost to be paid to the concerned authorities apart from the rent for
installing flagpoles.</li>
<li>In case of religious events, maximum period of seven days may be allowed for installing
flagpoles.</li>
<li>The temporary flagpoles have to be removed by the organizers immediately on expiry of
the permission period, at their own cost. In case of any failure, the land-owning department
shall remove the flagpoles and collect the cost of removal from the organizers.</li>
<li>If there is any public unrest during the installation of flagpoles, it can be decided
based on the field situation and suitable decision to be taken by Police and Revenue
authorities.</li>
</ol>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).ready(function () {
$('#termsCheck').on('change', function () {
$('#submitBtn').prop('disabled', !this.checked);
});
});
</script>
</body>
</html>

135
src/main/resources/templates/modules/flagpolesregistration/razor-pay.html

@ -0,0 +1,135 @@
<html>
<header>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
var updatePaymentFailed = false;
const paymentStart = (id, paymentDesc) => {
console.log("payment started");
// ✅ Get the value from an input field with name="amount"
//let amount = $('[name="amount"]').val();
let amount = 50;
/* console.log(amount);
if(amount=="0.0"||amount==null){
swal("Sorry!", "Add Product in Basket", "error");
return;
} */
$.ajax({
url: '/flagpolesregistration/api/create_order',
data: JSON.stringify({ amount: amount, info: 'order_request', id: id }),
contentType: 'application/json',
type: 'POST',
dataType: 'json',
success: function (response) {
let amt = response.amount;
// console.log("FIRST:==>");
console.log(response);
if (response.status == "created") {
let options = {
"key": "rzp_test_TADBzz8BXbBpos", // for development
//"key": "rzp_live_66FhxMUNAb9McO", // for production
"amount": response.amount, // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
"currency": "INR",
"name": "Greater Chennai Corporation",
"description": paymentDesc + " Transaction",
"image": "https://upload.wikimedia.org/wikipedia/commons/a/a8/Chennai_Corporation_Emblem.png",
"order_id": response.id, //This is a sample Order ID. Pass the `id` obtained in the response of Step 1
"handler": function (response) {
console.log("second==>\n");
console.log(response);
console.log(response.razorpay_payment_id);
console.log(response.razorpay_order_id);
console.log(response.razorpay_signature);
console.log("payment success");
//alert("congrates !payment successfull");
updatePaymentInServer(response.razorpay_payment_id, response.razorpay_order_id, "paid", id, amt);
},
"prefill": {
"name": "",
"email": "",
"contact": ""
},
"notes": {
"address": "Greater Chennai Corporation."
},
"theme": {
"color": "#3399cc"
}
};
var rzp1 = new Razorpay(options);
rzp1.on('payment.failed', function (response) {
alert("Payment Failed unfortunately");
console.log(response.error.code);
console.log(response.error.description);
console.log(response.error.source);
console.log(response.error.step);
console.log(response.error.reason);
console.log(response.error.metadata.order_id);
console.log(response.error.metadata.payment_id);
// if (!updatePaymentFailed) {
// updatePaymentFailure(response.error, id);
// }
});
rzp1.open();
}
},
error: function (error) {
console.log(error);
alert("Try After Sometime");
}
})
};
function updatePaymentInServer(payment_id, order_id, status, id, amt) {
var mobile_no = $("#paymentNumber").val();
$.ajax({
url: '/flagpolesregistration/api/Confirm',
data: JSON.stringify({ payment_id: payment_id, order_id: order_id, status: status, id: id, amt: amt / 100, mobile_no: mobile_no }),
contentType: 'application/json',
type: 'POST',
dataType: 'json',
success: function (response) {
console.log("update payment in server");
//const type = 'BOOKING';
const type = response.paymentType;
console.log(type);
window.location.href =
`/flagpolesregistration/paymentform?requestId=${response.request_id}&type=${type}`;
},
error: function (error) {
swal("Failed`!", "We will check & contact you soon", "error");
}
});
};
// function updatePaymentFailure(response, id) {
// // console.log(response);
// // alert("Payment Not Processed...");
// $.ajax({
// url: '/flagpoles/api/paymentFailure',
// data: JSON.stringify({ 'response': response, 'id': id }),
// contentType: 'application/json',
// type: 'POST',
// dataType: 'json',
// success: function (response) {
// // console.log("update payment in server",response);
// alert("If the amount has been debited,\nplease contact the GCC SWD Department for assistance.");
// updatePaymentFailed = true;
// },
// error: function (error) {
// swal("Failed`!", "We will check & contact you soon", "error");
// }
// });
// }
</script>
</header>
</html>

2590
src/main/resources/templates/modules/flagpolesregistration/requestform.html
File diff suppressed because it is too large
View File

1068
src/main/resources/templates/modules/flagpolesregistration/status.html
File diff suppressed because it is too large
View File

13
src/test/java/com/gcc/flagpoles/FlagpolesApplicationTests.java

@ -0,0 +1,13 @@
package com.gcc.flagpoles;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class FlagpolesApplicationTests {
@Test
void contextLoads() {
}
}
Loading…
Cancel
Save