Browse Source
Six month old transactions option created for HQ login and mail integration implemented.
master
Six month old transactions option created for HQ login and mail integration implemented.
master
31 changed files with 8523 additions and 4886 deletions
-
6pom.xml
-
93src/main/java/com/gcc/communityHall/controller/HQAPIController.java
-
304src/main/java/com/gcc/communityHall/controller/HeadquartersController.java
-
47src/main/java/com/gcc/communityHall/controller/OfficerAPIController.java
-
186src/main/java/com/gcc/communityHall/entity/BookingDetails.java
-
105src/main/java/com/gcc/communityHall/entity/SixMonthMailLog.java
-
54src/main/java/com/gcc/communityHall/paymentService/entity/RefundResponse.java
-
41src/main/java/com/gcc/communityHall/paymentService/repository/TransRefundResRepository.java
-
2src/main/java/com/gcc/communityHall/paymentService/repository/TransactionResponseRepository.java
-
138src/main/java/com/gcc/communityHall/repository/BookingDetailsRepository.java
-
9src/main/java/com/gcc/communityHall/repository/BookingHistoryRepository.java
-
13src/main/java/com/gcc/communityHall/repository/SixMonthMailLogRepository.java
-
18src/main/java/com/gcc/communityHall/service/Impl/BookingServiceImpl.java
-
1src/main/java/com/gcc/communityHall/service/Impl/HallDetailServiceImpl.java
-
86src/main/java/com/gcc/communityHall/service/MailService.java
-
21src/main/resources/application-dev.properties
-
21src/main/resources/application-prod.properties
-
843src/main/resources/resources/templates/headquarters/sixmonthold-transactions.html
-
12src/main/resources/templates/admin/gccblocking-new.html
-
4728src/main/resources/templates/admin/reports.html
-
7src/main/resources/templates/fragments/headquartersMenu.html
-
57src/main/resources/templates/headquarters/bookingwaiting.html
-
12src/main/resources/templates/headquarters/gccblocking-new.html
-
2src/main/resources/templates/headquarters/halldetailslist.html
-
4336src/main/resources/templates/headquarters/reports.html
-
196src/main/resources/templates/headquarters/settlement-completed.html
-
1772src/main/resources/templates/headquarters/sixmonthold-transactions.html
-
27src/main/resources/templates/officer/gccblocking-new.html
-
56src/main/resources/templates/user/hallbookingform.html
-
19src/main/resources/templates/user/viewhallform.html
-
197src/main/resources/templates/user/viewhistory.html
@ -0,0 +1,105 @@ |
|||
package com.gcc.communityHall.entity; |
|||
|
|||
import jakarta.persistence.*; |
|||
import java.time.LocalDateTime; |
|||
|
|||
/** |
|||
* Audit log table that records every refund-follow-up mail dispatched |
|||
* for 6-month-old bookings from the /sixmonthold-transactions page. |
|||
* |
|||
* DDL (run once): |
|||
* CREATE TABLE six_month_mail_log ( |
|||
* id BIGINT AUTO_INCREMENT PRIMARY KEY, |
|||
* booking_id INT NOT NULL, |
|||
* booking_status VARCHAR(50), |
|||
* transaction_id VARCHAR(100), |
|||
* tpsl_id VARCHAR(100), |
|||
* refund_amount DOUBLE, |
|||
* sent_by VARCHAR(100), |
|||
* sent_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
|||
* mail_content TEXT |
|||
* ); |
|||
* |
|||
* Also add to booking_details (run once): |
|||
* ALTER TABLE booking_details |
|||
* ADD COLUMN mail_sent TINYINT(1) DEFAULT 0, |
|||
* ADD COLUMN mail_sent_date DATETIME NULL; |
|||
*/ |
|||
@Entity |
|||
@Table(name = "six_month_mail_log") |
|||
public class SixMonthMailLog { |
|||
|
|||
@Id |
|||
@GeneratedValue(strategy = GenerationType.IDENTITY) |
|||
private Long id; |
|||
|
|||
@Column(name = "booking_id", nullable = false) |
|||
private int bookingId; |
|||
|
|||
@Column(name = "booking_status", length = 50) |
|||
private String bookingStatus; |
|||
|
|||
@Column(name = "transaction_id", length = 100) |
|||
private String transactionId; |
|||
|
|||
@Column(name = "tpsl_id", length = 100) |
|||
private String tpslId; |
|||
|
|||
@Column(name = "refund_amount") |
|||
private Double refundAmount; |
|||
|
|||
@Column(name = "sent_by", length = 100) |
|||
private String sentBy; |
|||
|
|||
@Column(name = "sent_at") |
|||
private LocalDateTime sentAt; |
|||
|
|||
@Column(name = "mail_content", columnDefinition = "TEXT") |
|||
private String mailContent; |
|||
|
|||
// ──── Constructors ──────────────────────────────────────────────────────── |
|||
|
|||
public SixMonthMailLog() { |
|||
} |
|||
|
|||
public SixMonthMailLog(int bookingId, String bookingStatus, String transactionId, |
|||
String tpslId, Double refundAmount, String sentBy, String mailContent) { |
|||
this.bookingId = bookingId; |
|||
this.bookingStatus = bookingStatus; |
|||
this.transactionId = transactionId; |
|||
this.tpslId = tpslId; |
|||
this.refundAmount = refundAmount; |
|||
this.sentBy = sentBy; |
|||
this.sentAt = LocalDateTime.now(); |
|||
this.mailContent = mailContent; |
|||
} |
|||
|
|||
// ──── Getters & Setters ─────────────────────────────────────────────────── |
|||
|
|||
public Long getId() { return id; } |
|||
public void setId(Long id) { this.id = id; } |
|||
|
|||
public int getBookingId() { return bookingId; } |
|||
public void setBookingId(int bookingId) { this.bookingId = bookingId; } |
|||
|
|||
public String getBookingStatus() { return bookingStatus; } |
|||
public void setBookingStatus(String bookingStatus) { this.bookingStatus = bookingStatus; } |
|||
|
|||
public String getTransactionId() { return transactionId; } |
|||
public void setTransactionId(String transactionId) { this.transactionId = transactionId; } |
|||
|
|||
public String getTpslId() { return tpslId; } |
|||
public void setTpslId(String tpslId) { this.tpslId = tpslId; } |
|||
|
|||
public Double getRefundAmount() { return refundAmount; } |
|||
public void setRefundAmount(Double refundAmount) { this.refundAmount = refundAmount; } |
|||
|
|||
public String getSentBy() { return sentBy; } |
|||
public void setSentBy(String sentBy) { this.sentBy = sentBy; } |
|||
|
|||
public LocalDateTime getSentAt() { return sentAt; } |
|||
public void setSentAt(LocalDateTime sentAt) { this.sentAt = sentAt; } |
|||
|
|||
public String getMailContent() { return mailContent; } |
|||
public void setMailContent(String mailContent) { this.mailContent = mailContent; } |
|||
} |
|||
@ -1,16 +1,21 @@ |
|||
package com.gcc.communityHall.repository; |
|||
|
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
|
|||
import org.springframework.data.jpa.repository.JpaRepository; |
|||
import org.springframework.data.jpa.repository.Query; |
|||
import org.springframework.data.repository.query.Param; |
|||
import org.springframework.stereotype.Repository; |
|||
|
|||
import com.gcc.communityHall.entity.BookingHistory; |
|||
|
|||
@Repository |
|||
public interface BookingHistoryRepository extends JpaRepository<BookingHistory,Integer> { |
|||
|
|||
public interface BookingHistoryRepository extends JpaRepository<BookingHistory, Integer> { |
|||
|
|||
@Query(value = "SELECT * FROM booking_history where booking_details_booking_id= :bookingId", nativeQuery = true) |
|||
BookingHistory findbybookingId(int bookingId); |
|||
|
|||
@Query(value = "SELECT * FROM booking_history WHERE booking_details_booking_id = :bookingId ORDER BY history_id ASC limit 1", nativeQuery = true) |
|||
List<BookingHistory> findAllByBookingId(@Param("bookingId") int bookingId); |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
package com.gcc.communityHall.repository; |
|||
|
|||
import com.gcc.communityHall.entity.SixMonthMailLog; |
|||
import org.springframework.data.jpa.repository.JpaRepository; |
|||
import org.springframework.stereotype.Repository; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Repository |
|||
public interface SixMonthMailLogRepository extends JpaRepository<SixMonthMailLog, Long> { |
|||
|
|||
List<SixMonthMailLog> findByBookingIdOrderBySentAtDesc(int bookingId); |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
package com.gcc.communityHall.service; |
|||
|
|||
import jakarta.mail.internet.InternetAddress; |
|||
import jakarta.mail.internet.MimeMessage; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.mail.javamail.JavaMailSender; |
|||
import org.springframework.mail.javamail.MimeMessageHelper; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.text.DecimalFormat; |
|||
|
|||
@Service |
|||
public class MailService { |
|||
|
|||
@Autowired |
|||
private JavaMailSender mailSender; |
|||
|
|||
@Value("${app.mail.from}") |
|||
private String fromAddress; |
|||
|
|||
@Value("${app.mail.to}") |
|||
private String toAddresses; |
|||
|
|||
@Value("${app.mail.cc}") |
|||
private String ccAddresses; |
|||
|
|||
public String sendRefundFollowupMail(int bookingId, String bookingStatus, |
|||
String transactionId, String tpslId, |
|||
String transactionDate, Double refundAmount) throws Exception { |
|||
|
|||
MimeMessage message = mailSender.createMimeMessage(); |
|||
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); |
|||
|
|||
helper.setFrom(new InternetAddress(fromAddress, "Community Hall Support")); |
|||
|
|||
for (String addr : toAddresses.split(",")) { |
|||
if (!addr.trim().isEmpty()) { |
|||
helper.addTo(addr.trim()); |
|||
} |
|||
} |
|||
|
|||
for (String addr : ccAddresses.split(",")) { |
|||
if (!addr.trim().isEmpty()) { |
|||
helper.addCc(addr.trim()); |
|||
} |
|||
} |
|||
|
|||
helper.setSubject("Test Mail Refund Status Update Request - Community Hall Booking"); |
|||
|
|||
DecimalFormat df = new DecimalFormat("#,##0.00"); |
|||
String amt = (refundAmount != null) ? "Rs. " + df.format(refundAmount) : "N/A"; |
|||
|
|||
String body = buildMailBody(bookingId, bookingStatus, transactionId, tpslId, transactionDate, amt); |
|||
helper.setText(body, true); |
|||
|
|||
mailSender.send(message); |
|||
return body; // return body so caller can persist it in the audit log |
|||
} |
|||
|
|||
private String buildMailBody(int bookingId, String bookingStatus, |
|||
String transactionId, String tpslId, |
|||
String transactionDate, String amt) { |
|||
return "Hi,<br><br>" |
|||
+ "Kindly update refund status for the below mentioned transaction made for Community Hall Booking.<br><br>" |
|||
+ "<b>Transaction Details:</b><br><br>" |
|||
+ " Booking ID : " + |
|||
bookingId + "<br>" |
|||
// + " Booking Status : " + nvl(bookingStatus) + |
|||
// "<br>" |
|||
+ " Transaction ID : " + nvl(transactionId) + "<br>" |
|||
+ " TPSL ID : " |
|||
+ nvl(tpslId) + "<br>" |
|||
+ " Transaction Date : " + nvl(transactionDate) + "<br>" |
|||
+ " <b>Refund Amount : " + amt + "</b><br><br>" |
|||
+ "If refund was not initiated, <b>kindly initiate the refund</b> and update refund status at the earliest. " |
|||
+ "Make sure that no duplicate refund was processed against this transaction.<br><br>" |
|||
+ "Regards,<br>" |
|||
+ "Community Hall Support<br>" |
|||
+ "Greater Chennai Corporation"; |
|||
} |
|||
|
|||
private String nvl(String val) { |
|||
return (val != null && !val.isEmpty()) ? val : "N/A"; |
|||
} |
|||
} |
|||
@ -0,0 +1,843 @@ |
|||
<!DOCTYPE html> |
|||
<html xmlns:th="http://www.thymeleaf.org"> |
|||
|
|||
<head th:replace="~{fragments/head-headquarters :: head}"></head> |
|||
<style> |
|||
.nav-tabs .nav-link.active { |
|||
background: #1a73e8; |
|||
color: #fff !important; |
|||
border-color: #1a73e8; |
|||
border-radius: 6px 6px 0 0; |
|||
} |
|||
|
|||
.nav-tabs .nav-link { |
|||
color: #444; |
|||
font-weight: 500; |
|||
} |
|||
|
|||
.tab-badge { |
|||
background: #e8f0fe; |
|||
color: #1a73e8; |
|||
border-radius: 10px; |
|||
padding: 1px 8px; |
|||
font-size: 12px; |
|||
font-weight: 700; |
|||
margin-left: 4px; |
|||
} |
|||
|
|||
.nav-tabs .nav-link.active .tab-badge { |
|||
background: rgba(255, 255, 255, 0.25); |
|||
color: #fff; |
|||
} |
|||
|
|||
.table-responsive { |
|||
overflow-x: auto; |
|||
} |
|||
|
|||
.card-body table { |
|||
width: 100%; |
|||
} |
|||
|
|||
.card-body th, |
|||
td { |
|||
padding: 8px; |
|||
text-align: left; |
|||
} |
|||
|
|||
.amount-cell { |
|||
text-align: right; |
|||
padding-right: 1rem; |
|||
} |
|||
|
|||
.table { |
|||
width: 100% !important; |
|||
} |
|||
|
|||
.btn-sendmail { |
|||
background: #1a73e8; |
|||
color: #fff; |
|||
border: none; |
|||
border-radius: 4px; |
|||
padding: 3px 10px; |
|||
cursor: pointer; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.btn-sendmail:hover { |
|||
background: #1558b0; |
|||
} |
|||
|
|||
.btn-viewdetails { |
|||
background: #f59e0b; |
|||
color: #fff; |
|||
border: none; |
|||
border-radius: 4px; |
|||
padding: 3px 10px; |
|||
cursor: pointer; |
|||
font-size: 12px; |
|||
margin-right: 4px; |
|||
} |
|||
|
|||
.btn-viewdetails:hover { |
|||
background: #b45309; |
|||
} |
|||
|
|||
.badge-cancelled { |
|||
background: #dc2626; |
|||
color: #fff; |
|||
padding: 3px 8px; |
|||
border-radius: 10px; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.badge-rejected { |
|||
background: #7c3aed; |
|||
color: #fff; |
|||
padding: 3px 8px; |
|||
border-radius: 10px; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.badge-approved { |
|||
background: #16a34a; |
|||
color: #fff; |
|||
padding: 3px 8px; |
|||
border-radius: 10px; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.badge-other { |
|||
background: #64748b; |
|||
color: #fff; |
|||
padding: 3px 8px; |
|||
border-radius: 10px; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.not-initiated { |
|||
color: #dc2626; |
|||
font-style: italic; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
/* Draft mail preview */ |
|||
#draftMailBody { |
|||
background: #f8fafc; |
|||
border: 1px solid #cbd5e1; |
|||
border-radius: 6px; |
|||
padding: 16px; |
|||
font-family: Arial, sans-serif; |
|||
font-size: 14px; |
|||
white-space: pre-wrap; |
|||
line-height: 1.6; |
|||
} |
|||
|
|||
.mail-header-row { |
|||
margin-bottom: 6px; |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.mail-header-row strong { |
|||
display: inline-block; |
|||
width: 50px; |
|||
color: #475569; |
|||
} |
|||
</style> |
|||
|
|||
<body> |
|||
<!-- Page Container --> |
|||
<div id="page-container" |
|||
class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark"> |
|||
<!-- Side Overlay aside (right)--> |
|||
<aside th:replace="~{fragments/aside-right :: aside}"></aside> |
|||
<!-- END Side Overlay (right)--> |
|||
|
|||
<!-- Sidebar Nav--> |
|||
<nav th:replace="~{fragments/nav-headquarters :: nav}"></nav> |
|||
<!-- END Sidebar --> |
|||
|
|||
<!-- Header --> |
|||
<header th:replace="~{fragments/header-headquarters :: header}"></header> |
|||
<!-- END Header --> |
|||
|
|||
<!-- Main Container --> |
|||
<main id="main-container" class="container-fluid mt-4 px-4"> |
|||
<div class="block block-rounded"> |
|||
<div class="block-header block-header-default"> |
|||
<h3 class="block-title">6 Months Old Transaction Details</h3> |
|||
</div> |
|||
<div class="block-content"> |
|||
|
|||
<!-- ── TABS ───────────────────────────────────────────── --> |
|||
<ul class="nav nav-tabs mb-0" id="sixMonthTab" role="tablist"> |
|||
<li class="nav-item" role="presentation"> |
|||
<a class="nav-link active" id="tab-sixmonth-lnk" data-toggle="tab" href="#tab-sixmonth" |
|||
role="tab" aria-controls="tab-sixmonth" aria-selected="true"> |
|||
6 Month Old Bookings |
|||
<span class="tab-badge" |
|||
th:text="${sixMonthOldBookings != null ? #lists.size(sixMonthOldBookings) : 0}">0</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item" role="presentation"> |
|||
<a class="nav-link" id="tab-cancelled-lnk" data-toggle="tab" href="#tab-cancelled" |
|||
role="tab" aria-controls="tab-cancelled" aria-selected="false"> |
|||
Cancelled Bookings |
|||
<span class="tab-badge" |
|||
th:text="${cancelledBookings != null ? #lists.size(cancelledBookings) : 0}">0</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item" role="presentation"> |
|||
<a class="nav-link" id="tab-rejected-lnk" data-toggle="tab" href="#tab-rejected" |
|||
role="tab" aria-controls="tab-rejected" aria-selected="false"> |
|||
Rejected Bookings |
|||
<span class="tab-badge" |
|||
th:text="${rejectedBookings != null ? #lists.size(rejectedBookings) : 0}">0</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item" role="presentation"> |
|||
<a class="nav-link" id="tab-mailsent-lnk" data-toggle="tab" href="#tab-mailsent" |
|||
role="tab" aria-controls="tab-mailsent" aria-selected="false"> |
|||
Mail Sent Bookings |
|||
<span class="tab-badge" |
|||
th:text="${mailSentBookings != null ? #lists.size(mailSentBookings) : 0}">0</span> |
|||
</a> |
|||
</li> |
|||
</ul> |
|||
|
|||
<div class="tab-content border border-top-0 p-3" id="sixMonthTabContent"> |
|||
|
|||
<!-- ══════════════════════════════════════════════════ |
|||
TAB 1 – 6 Month Old Bookings (non-cancelled/rejected) |
|||
══════════════════════════════════════════════════ --> |
|||
<div class="tab-pane fade show active" id="tab-sixmonth" role="tabpanel" aria-labelledby="tab-sixmonth-lnk"> |
|||
<div class="table-responsive"> |
|||
<table class="table table-bordered table-striped table-vcenter js-dataTable-responsive" |
|||
id="tbl-sixmonth"> |
|||
<thead class="thead-light"> |
|||
<tr> |
|||
<th>S.No</th> |
|||
<th>Zone</th> |
|||
<th>Division</th> |
|||
<th>Hall Name</th> |
|||
<th>Booking Date</th> |
|||
<th>Event Date (Start – End)</th> |
|||
<th>Settlement Raised Date</th> |
|||
<th>Refund Amount (₹)</th> |
|||
<th>Refund Status</th> |
|||
<th>Booking Status</th> |
|||
<th>Action</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr th:each="row, rowStat : ${sixMonthOldBookings}"> |
|||
<td class="text-center" th:text="${rowStat.index + 1}"></td> |
|||
<td th:text="${row['zone'] != null ? row['zone'] : ''}"></td> |
|||
<td th:text="${row['division'] != null ? row['division'] : ''}"></td> |
|||
<td th:text="${row['hall_name'] != null ? row['hall_name'] : ''}"></td> |
|||
<td class="text-center" |
|||
th:text="${row['booking_date'] != null ? row['booking_date'] : ''}"> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="(${row['event_start_date'] != null ? row['event_start_date'] : ''}) + ' – ' + (${row['event_end_date'] != null ? row['event_end_date'] : ''})"> |
|||
</td> |
|||
<!-- Settlement Raised Date: N/A if no settlement --> |
|||
<td class="text-center"> |
|||
<span th:if="${row['settlement_raised_date'] != null}" |
|||
th:text="${row['settlement_raised_date']}"></span> |
|||
<span th:if="${row['settlement_raised_date'] == null}" |
|||
class="not-initiated">Settlement Not Initiated</span> |
|||
</td> |
|||
<!-- Refund Amount: from settlement.refunded_amount --> |
|||
<td class="text-right"> |
|||
<span th:if="${row['refunded_amount'] != null}" |
|||
th:text="'₹ ' + ${row['refunded_amount']}"></span> |
|||
<span th:if="${row['refunded_amount'] == null}" |
|||
class="not-initiated">—</span> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="${row['refund_status'] != null ? row['refund_status'] : ''}"> |
|||
</td> |
|||
<td class="text-center"> |
|||
<span th:classappend="${row['booking_status'] == 'CANCELED' || row['booking_status'] == 'CANCELLED'} ? 'badge-cancelled' : |
|||
(${row['booking_status'] == 'REJECTED'} ? 'badge-rejected' : |
|||
(${row['booking_status'] == 'APPROVED'} ? 'badge-approved' : 'badge-other'))" |
|||
th:text="${row['booking_status'] != null ? row['booking_status'] : ''}"></span> |
|||
</td> |
|||
<td class="text-center"> |
|||
<!-- View Details: calls getSettlementList if settlement exists --> |
|||
<button th:if="${row['settlement_id'] != null}" class="btn-viewdetails" |
|||
th:onclick="|viewSettlement(${row['settlement_id']})|"> |
|||
View Details |
|||
</button> |
|||
<span th:if="${row['settlement_id'] == null}" |
|||
class="not-initiated d-block mb-1">Settlement Not Initiated</span> |
|||
<button class="btn-sendmail" |
|||
th:onclick="|openSendMail(${row['booking_id'] != null ? row['booking_id'] : 0}, '${row['booking_status'] != null ? row['booking_status'] : ''}', '${row['txansaction_id'] != null ? row['txansaction_id'] : ''}', '${row['tpsl_txn_id'] != null ? row['tpsl_txn_id'] : ''}', '${row['transaction_date'] != null ? row['transaction_date'] : ''}', ${row['refunded_amount'] != null ? row['refunded_amount'] : 0})|"> |
|||
Send Mail |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr |
|||
th:if="${sixMonthOldBookings == null || #lists.isEmpty(sixMonthOldBookings)}"> |
|||
<td colspan="11" class="text-center text-muted py-3">No records found</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div><!-- /tab-sixmonth --> |
|||
|
|||
<!-- ══════════════════════════════════════════════════ |
|||
TAB 2 – Cancelled Bookings |
|||
Refund Amount = deposit_amount |
|||
No Settlement Raised Date column |
|||
══════════════════════════════════════════════════ --> |
|||
<div class="tab-pane fade" id="tab-cancelled" role="tabpanel" aria-labelledby="tab-cancelled-lnk"> |
|||
<div class="table-responsive"> |
|||
<table class="table table-bordered table-striped table-vcenter js-dataTable-responsive" |
|||
id="tbl-cancelled"> |
|||
<thead class="thead-light"> |
|||
<tr> |
|||
<th>S.No</th> |
|||
<th>Zone</th> |
|||
<th>Division</th> |
|||
<th>Hall Name</th> |
|||
<th>Booking Date</th> |
|||
<th>Event Date (Start – End)</th> |
|||
<th>Refund Amount (₹)</th> |
|||
<th>Booking Status</th> |
|||
<th>Action</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr th:each="row, rowStat : ${cancelledBookings}"> |
|||
<td class="text-center" th:text="${rowStat.index + 1}"></td> |
|||
<td th:text="${row['zone'] != null ? row['zone'] : ''}"></td> |
|||
<td th:text="${row['division'] != null ? row['division'] : ''}"></td> |
|||
<td th:text="${row['hall_name'] != null ? row['hall_name'] : ''}"></td> |
|||
<td class="text-center" |
|||
th:text="${row['booking_date'] != null ? row['booking_date'] : ''}"> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="(${row['event_start_date'] != null ? row['event_start_date'] : ''}) + ' – ' + (${row['event_end_date'] != null ? row['event_end_date'] : ''})"> |
|||
</td> |
|||
<td class="text-right" |
|||
th:text="${row['refund_amount'] != null ? '₹ ' + row['refund_amount'] : '—'}"> |
|||
</td> |
|||
<td class="text-center"> |
|||
<span class="badge-cancelled" |
|||
th:text="${row['booking_status'] != null ? row['booking_status'] : ''}"></span> |
|||
</td> |
|||
<td class="text-center"> |
|||
<button class="btn-viewdetails" |
|||
th:onclick="|viewBookingDetails(${row['booking_id'] != null ? row['booking_id'] : 0})|"> |
|||
View Details |
|||
</button> |
|||
<button class="btn-sendmail" |
|||
th:onclick="|openSendMail(${row['booking_id'] != null ? row['booking_id'] : 0}, '${row['booking_status'] != null ? row['booking_status'] : ''}', '${row['txansaction_id'] != null ? row['txansaction_id'] : ''}', '${row['tpsl_txn_id'] != null ? row['tpsl_txn_id'] : ''}', '${row['transaction_date'] != null ? row['transaction_date'] : ''}', ${row['refund_amount'] != null ? row['refund_amount'] : 0})|"> |
|||
Send Mail |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr th:if="${cancelledBookings == null || #lists.isEmpty(cancelledBookings)}"> |
|||
<td colspan="9" class="text-center text-muted py-3">No records found</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div><!-- /tab-cancelled --> |
|||
|
|||
<!-- ══════════════════════════════════════════════════ |
|||
TAB 3 – Rejected Bookings |
|||
Refund Amount = amount_received (full amount) |
|||
No Settlement Raised Date column |
|||
══════════════════════════════════════════════════ --> |
|||
<div class="tab-pane fade" id="tab-rejected" role="tabpanel" aria-labelledby="tab-rejected-lnk"> |
|||
<div class="table-responsive"> |
|||
<table class="table table-bordered table-striped table-vcenter js-dataTable-responsive" |
|||
id="tbl-rejected"> |
|||
<thead class="thead-light"> |
|||
<tr> |
|||
<th>S.No</th> |
|||
<th>Zone</th> |
|||
<th>Division</th> |
|||
<th>Hall Name</th> |
|||
<th>Booking Date</th> |
|||
<th>Event Date (Start – End)</th> |
|||
<th>Refund Amount (₹)</th> |
|||
<th>Booking Status</th> |
|||
<th>Action</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr th:each="row, rowStat : ${rejectedBookings}"> |
|||
<td class="text-center" th:text="${rowStat.index + 1}"></td> |
|||
<td th:text="${row['zone'] != null ? row['zone'] : ''}"></td> |
|||
<td th:text="${row['division'] != null ? row['division'] : ''}"></td> |
|||
<td th:text="${row['hall_name'] != null ? row['hall_name'] : ''}"></td> |
|||
<td class="text-center" |
|||
th:text="${row['booking_date'] != null ? row['booking_date'] : ''}"> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="(${row['event_start_date'] != null ? row['event_start_date'] : ''}) + ' – ' + (${row['event_end_date'] != null ? row['event_end_date'] : ''})"> |
|||
</td> |
|||
<td class="text-right" |
|||
th:text="${row['refund_amount'] != null ? '₹ ' + row['refund_amount'] : '—'}"> |
|||
</td> |
|||
<td class="text-center"> |
|||
<span class="badge-rejected" |
|||
th:text="${row['booking_status'] != null ? row['booking_status'] : ''}"></span> |
|||
</td> |
|||
<td class="text-center"> |
|||
<button class="btn-viewdetails" |
|||
th:onclick="|viewBookingDetails(${row['booking_id'] != null ? row['booking_id'] : 0})|"> |
|||
View Details |
|||
</button> |
|||
<button class="btn-sendmail" |
|||
th:onclick="|openSendMail(${row['booking_id'] != null ? row['booking_id'] : 0}, '${row['booking_status'] != null ? row['booking_status'] : ''}', '${row['txansaction_id'] != null ? row['txansaction_id'] : ''}', '${row['tpsl_txn_id'] != null ? row['tpsl_txn_id'] : ''}', '${row['transaction_date'] != null ? row['transaction_date'] : ''}', ${row['refund_amount'] != null ? row['refund_amount'] : 0})|"> |
|||
Send Mail |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr th:if="${rejectedBookings == null || #lists.isEmpty(rejectedBookings)}"> |
|||
<td colspan="9" class="text-center text-muted py-3">No records found</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div><!-- /tab-rejected --> |
|||
|
|||
<!-- ══════════════════════════════════════════════════ |
|||
TAB 4 – Mail Sent Bookings |
|||
══════════════════════════════════════════════════ --> |
|||
<div class="tab-pane fade" id="tab-mailsent" role="tabpanel" aria-labelledby="tab-mailsent-lnk"> |
|||
<div class="table-responsive"> |
|||
<table class="table table-bordered table-striped table-vcenter js-dataTable-responsive" |
|||
id="tbl-mailsent"> |
|||
<thead class="thead-light"> |
|||
<tr> |
|||
<th>S.No</th> |
|||
<th>Zone</th> |
|||
<th>Division</th> |
|||
<th>Hall Name</th> |
|||
<th>Booking Date</th> |
|||
<th>Event Date (Start – End)</th> |
|||
<th>Booking Status</th> |
|||
<th>Transaction ID</th> |
|||
<th>TPSL ID</th> |
|||
<th>Mail Sent Date</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr th:each="row, rowStat : ${mailSentBookings}"> |
|||
<td class="text-center" th:text="${rowStat.index + 1}"></td> |
|||
<td th:text="${row['zone'] != null ? row['zone'] : ''}"></td> |
|||
<td th:text="${row['division'] != null ? row['division'] : ''}"></td> |
|||
<td th:text="${row['hall_name'] != null ? row['hall_name'] : ''}"></td> |
|||
<td class="text-center" |
|||
th:text="${row['booking_date'] != null ? row['booking_date'] : ''}"> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="(${row['event_start_date'] != null ? row['event_start_date'] : ''}) + ' – ' + (${row['event_end_date'] != null ? row['event_end_date'] : ''})"> |
|||
</td> |
|||
<td class="text-center"> |
|||
<span th:classappend="${row['booking_status'] == 'CANCELED' || row['booking_status'] == 'CANCELLED'} ? 'badge-cancelled' : |
|||
(${row['booking_status'] == 'REJECTED'} ? 'badge-rejected' : |
|||
(${row['booking_status'] == 'APPROVED'} ? 'badge-approved' : 'badge-other'))" |
|||
th:text="${row['booking_status'] != null ? row['booking_status'] : ''}"></span> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="${row['txansaction_id'] != null ? row['txansaction_id'] : ''}"> |
|||
</td> |
|||
<td class="text-center" |
|||
th:text="${row['tpsl_txn_id'] != null ? row['tpsl_txn_id'] : ''}"></td> |
|||
<td class="text-center" |
|||
th:text="${row['mail_sent_date'] != null ? row['mail_sent_date'] : ''}"> |
|||
</td> |
|||
</tr> |
|||
<tr th:if="${mailSentBookings == null || #lists.isEmpty(mailSentBookings)}"> |
|||
<td colspan="10" class="text-center text-muted py-3">No records found</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div><!-- /tab-mailsent --> |
|||
|
|||
</div><!-- /tab-content --> |
|||
</div><!-- /block-content --> |
|||
</div><!-- /block --> |
|||
</main> |
|||
<!-- END Main Container --> |
|||
|
|||
<!-- ══════════════════════════════════════════════════════════════════ |
|||
MODAL – Settlement View Details (Tab 1 with settlement) |
|||
══════════════════════════════════════════════════════════════════ --> |
|||
<div class="modal fade" id="settlementModal" data-backdrop="static" tabindex="-1" role="dialog" |
|||
aria-labelledby="settlementModalLabel" aria-hidden="true"> |
|||
<div class="modal-dialog modal-lg" role="document"> |
|||
<div class="modal-content"> |
|||
<div class="block block-rounded block-themed block-transparent mb-0"> |
|||
<div class="block-header bg-primary-dark"> |
|||
<h3 class="block-title" id="settlementModalLabel">Settlement Information</h3> |
|||
<div class="block-options"> |
|||
<button type="button" class="btn-block-option" data-dismiss="modal" aria-label="Close"> |
|||
<i class="fa fa-fw fa-times"></i> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
<div class="block-content row p-3" id="settlementModalBody"> |
|||
<!-- Populated by JS --> |
|||
</div> |
|||
<div class="block-content block-content-full text-right bg-body"> |
|||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- ══════════════════════════════════════════════════════════════════ |
|||
MODAL – Booking View Details (Tab 2 & 3 – cancelled/rejected) |
|||
══════════════════════════════════════════════════════════════════ --> |
|||
<div class="modal fade" id="bookingModal" data-backdrop="static" tabindex="-1" role="dialog" |
|||
aria-labelledby="bookingModalLabel" aria-hidden="true"> |
|||
<div class="modal-dialog modal-lg" role="document"> |
|||
<div class="modal-content"> |
|||
<div class="block block-rounded block-themed block-transparent mb-0"> |
|||
<div class="block-header bg-primary-dark"> |
|||
<h3 class="block-title" id="bookingModalLabel">Booking Information</h3> |
|||
<div class="block-options"> |
|||
<button type="button" class="btn-block-option" data-dismiss="modal" aria-label="Close"> |
|||
<i class="fa fa-fw fa-times"></i> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
<div class="block-content row p-3" id="bookingModalBody"> |
|||
<!-- Populated by JS --> |
|||
</div> |
|||
<div class="block-content block-content-full text-right bg-body"> |
|||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- ══════════════════════════════════════════════════════════════════ |
|||
MODAL – Draft Mail Preview & Confirm |
|||
══════════════════════════════════════════════════════════════════ --> |
|||
<div class="modal fade" id="draftMailModal" data-backdrop="static" tabindex="-1" role="dialog" |
|||
aria-labelledby="draftMailModalLabel" aria-hidden="true"> |
|||
<div class="modal-dialog modal-lg" role="document"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header" style="background:#1a73e8; color:#fff;"> |
|||
<h5 class="modal-title" id="draftMailModalLabel"> |
|||
<i class="fa fa-envelope mr-2"></i>Draft Mail Preview |
|||
</h5> |
|||
<button type="button" class="close text-white" data-dismiss="modal" aria-label="Close"> |
|||
<span aria-hidden="true">×</span> |
|||
</button> |
|||
</div> |
|||
<div class="modal-body"> |
|||
<!-- Mail Header Fields --> |
|||
<div class="mail-header-row"><strong>From:</strong> |
|||
communityhallsupport@chennaicorporation.gov.in</div> |
|||
<div class="mail-header-row"> |
|||
<strong>To:</strong> |
|||
pgsupport@mail.in.worldline-solutions.com, ranjithkumar@federal.bank.in, |
|||
megha.mattamana@federal.bank.in |
|||
</div> |
|||
<div class="mail-header-row"> |
|||
<strong>CC:</strong> |
|||
arohqcc@gmail.com, it@chennaicorporation.gov.in |
|||
</div> |
|||
<div class="mail-header-row"><strong>Sub:</strong> Refund Status Update Request – Community Hall |
|||
Booking</div> |
|||
<hr class="my-2"> |
|||
<!-- Mail Body --> |
|||
<div id="draftMailBody"></div> |
|||
|
|||
<!-- Hidden fields to carry data through to confirm step --> |
|||
<input type="hidden" id="dm_bookingId"> |
|||
<input type="hidden" id="dm_bookingStatus"> |
|||
<input type="hidden" id="dm_transactionId"> |
|||
<input type="hidden" id="dm_tpslId"> |
|||
<input type="hidden" id="dm_refundAmount"> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" data-dismiss="modal"> |
|||
<i class="fa fa-times mr-1"></i>Close |
|||
</button> |
|||
<button type="button" class="btn btn-primary" id="btn-confirm-mail" onclick="confirmMailSent()"> |
|||
<i class="fa fa-check mr-1"></i>Confirm & Mark as Mail Sent |
|||
</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- File Preview Modal (for settlement images) --> |
|||
<div class="modal fade" id="fileModal" tabindex="-1" role="dialog" aria-hidden="true"> |
|||
<div class="modal-dialog modal-lg"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header"> |
|||
<h5 class="modal-title">File Preview</h5> |
|||
<button type="button" class="close" data-dismiss="modal"><span>×</span></button> |
|||
</div> |
|||
<div class="modal-body"> |
|||
<embed id="filePreview" src="" width="100%" height="600px"> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<footer th:replace="~{fragments/footer2 :: footer}"></footer> |
|||
</div> |
|||
<!-- END Page Container --> |
|||
|
|||
<div th:replace="~{fragments/resetpassword :: div}"></div> |
|||
<script th:replace="~{fragments/loginscript :: script}"></script> |
|||
|
|||
<script> |
|||
// ───────────────────────────────────────────────────────────────────── |
|||
// DataTable initialisation & Tab Switch Handlers |
|||
// ───────────────────────────────────────────────────────────────────── |
|||
$(document).ready(function () { |
|||
var dtButtons = [ |
|||
{ extend: 'pageLength', className: 'btn btn-primary' }, |
|||
{ extend: 'copyHtml5', text: 'Copy', className: 'btn btn-primary' }, |
|||
{ extend: 'excelHtml5', text: 'Excel', className: 'btn btn-primary' }, |
|||
{ extend: 'csvHtml5', text: 'CSV', className: 'btn btn-primary' }, |
|||
{ extend: 'pdfHtml5', text: 'PDF', className: 'btn btn-primary' } |
|||
]; |
|||
var dtOpts = { |
|||
dom: 'Bftip', |
|||
columnDefs: [{ targets: 'no-sort', orderable: false }], |
|||
lengthMenu: [[50, 100, 200, 500, -1], ['50 rows', '100 rows', '200 rows', '500 rows', 'Show all']], |
|||
buttons: dtButtons, |
|||
responsive: true, |
|||
searching: true, |
|||
autoWidth: false |
|||
}; |
|||
|
|||
// Initialize DataTables |
|||
$('#tbl-sixmonth').DataTable(dtOpts); |
|||
$('#tbl-cancelled').DataTable(dtOpts); |
|||
$('#tbl-rejected').DataTable(dtOpts); |
|||
$('#tbl-mailsent').DataTable(dtOpts); |
|||
|
|||
// Explicit click handler to guarantee tab activation |
|||
$('#sixMonthTab a').on('click', function (e) { |
|||
e.preventDefault(); |
|||
$(this).tab('show'); |
|||
}); |
|||
|
|||
// Recalculate columns and responsive layout whenever any tab is shown |
|||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { |
|||
var targetTab = $(e.target).attr('href'); |
|||
if (targetTab && $.fn.dataTable) { |
|||
try { |
|||
$(targetTab).find('table').each(function () { |
|||
if ($.fn.dataTable.isDataTable(this)) { |
|||
$(this).DataTable().columns.adjust().responsive.recalc(); |
|||
} |
|||
}); |
|||
} catch (err) { |
|||
console.log('Error adjusting table columns on tab switch:', err); |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
// ───────────────────────────────────────────────────────────────────── |
|||
// View Settlement Details (Tab 1 – uses /getSettlementList by settlementId) |
|||
// ───────────────────────────────────────────────────────────────────── |
|||
function viewSettlement(settlementId) { |
|||
$.ajax({ |
|||
type: 'GET', |
|||
url: '/communityhall/api/officer/getSettlementList', |
|||
data: { settlementsid: settlementId }, |
|||
success: function (data) { |
|||
populateSettlementModal(data); |
|||
$('#settlementModal').modal('show'); |
|||
}, |
|||
error: function () { |
|||
Swal.fire('Error', 'Failed to fetch settlement details.', 'error'); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function populateSettlementModal(d) { |
|||
var html = '<div class="col-12">'; |
|||
html += '<table class="table table-sm table-bordered">'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">User Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">User Name:</th><td>' + (d.users ? d.users.name : '') + '</td>'; |
|||
html += '<th style="font-weight:normal">Mobile No:</th><td>' + (d.users ? d.users.mobileNo : '') + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">User Type:</th><td colspan="3">' + (d.users ? d.users.usertype : '') + '</td></tr>'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Hall Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Hall Name:</th><td colspan="3">' + (d.hallDetails ? d.hallDetails.hallName : '') + '</td></tr>'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Booking Details (ID: ' + d.bookingId + ')</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Booking Date:</th><td>' + d.bookingDate + '</td>'; |
|||
html += '<th style="font-weight:normal">Deposit Amount:</th><td>₹ ' + parseFloat(d.depositAmount).toFixed(2) + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Start Date:</th><td>' + d.startDate + '</td>'; |
|||
html += '<th style="font-weight:normal">End Date:</th><td>' + d.endDate + '</td></tr>'; |
|||
// Settlement |
|||
if (d.settlement) { |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Settlement Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Refunded Amount:</th><td>₹ ' + parseFloat(d.settlement.refundedAmount || 0).toFixed(2) + '</td>'; |
|||
html += '<th style="font-weight:normal">Damage Amount:</th><td>₹ ' + parseFloat(d.settlement.damageAmount || 0).toFixed(2) + '</td></tr>'; |
|||
} else { |
|||
html += '<tr><td colspan="4" class="text-danger text-center font-italic">Settlement Not Initiated</td></tr>'; |
|||
} |
|||
html += '</table></div>'; |
|||
$('#settlementModalBody').html(html); |
|||
} |
|||
|
|||
// ───────────────────────────────────────────────────────────────────── |
|||
// View Booking Details (Tab 2 & 3 – uses /getBookingDetails by bookingId) |
|||
// ───────────────────────────────────────────────────────────────────── |
|||
function viewBookingDetails(bookingId) { |
|||
if (!bookingId || bookingId === 0) { |
|||
Swal.fire('Warning', 'Invalid Booking ID.', 'warning'); |
|||
return; |
|||
} |
|||
$.ajax({ |
|||
type: 'GET', |
|||
url: '/communityhall/api/officer/getBookingDetails', |
|||
data: { bookingsId: bookingId }, |
|||
success: function (data) { |
|||
populateBookingModal(data); |
|||
$('#bookingModal').modal('show'); |
|||
}, |
|||
error: function () { |
|||
Swal.fire('Error', 'Failed to fetch booking details.', 'error'); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function populateBookingModal(d) { |
|||
var html = '<div class="col-12">'; |
|||
html += '<table class="table table-sm table-bordered">'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">User Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">User Name:</th><td>' + (d.users ? d.users.name : '') + '</td>'; |
|||
html += '<th style="font-weight:normal">Mobile No:</th><td>' + (d.users ? d.users.mobileNo : '') + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">User Type:</th><td colspan="3">' + (d.users ? d.users.usertype : '') + '</td></tr>'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Hall Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Hall Name:</th><td colspan="3">' + (d.hallDetails ? d.hallDetails.hallName : '') + '</td></tr>'; |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Booking Details (ID: ' + d.bookingId + ')</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Booking Date:</th><td>' + d.bookingDate + '</td>'; |
|||
html += '<th style="font-weight:normal">Booking Status:</th><td>' + d.bookingStatus + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Start Date:</th><td>' + d.startDate + '</td>'; |
|||
html += '<th style="font-weight:normal">End Date:</th><td>' + d.endDate + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Deposit Amount:</th><td>₹ ' + parseFloat(d.depositAmount).toFixed(2) + '</td>'; |
|||
html += '<th style="font-weight:normal">Total Amount:</th><td>₹ ' + parseFloat(d.amountReceived).toFixed(2) + '</td></tr>'; |
|||
// Payment |
|||
if (d.payments) { |
|||
html += '<tr><th colspan="4" style="background:#f2f2f2;">Payment Details</th></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Transaction ID:</th><td colspan="3">' + d.payments.transactionId + '</td></tr>'; |
|||
html += '<tr><th style="font-weight:normal">Amount Received:</th><td>₹ ' + d.payments.amountReceived + '</td>'; |
|||
html += '<th style="font-weight:normal">Payment Status:</th><td>' + d.payments.paymentStatus + '</td></tr>'; |
|||
} |
|||
html += '</table></div>'; |
|||
$('#bookingModalBody').html(html); |
|||
} |
|||
|
|||
// ───────────────────────────────────────────────────────────────────── |
|||
// Send Mail Flow |
|||
// ───────────────────────────────────────────────────────────────────── |
|||
function openSendMail(bookingId, bookingStatus, transactionId, tpslId, transactionDate, refundAmount) { |
|||
Swal.fire({ |
|||
title: 'Send Refund Follow-up Mail?', |
|||
html: 'This will send a refund status request mail for Booking ID <strong>' + bookingId + '</strong>.<br>Do you want to proceed?', |
|||
icon: 'question', |
|||
showCancelButton: true, |
|||
confirmButtonText: 'Yes, Show Draft', |
|||
cancelButtonText: 'Cancel', |
|||
confirmButtonColor: '#1a73e8' |
|||
}).then(function (result) { |
|||
if (result.isConfirmed) { |
|||
showDraftMail(bookingId, bookingStatus, transactionId, tpslId, transactionDate, refundAmount); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function showDraftMail(bookingId, bookingStatus, transactionId, tpslId, transactionDate, refundAmount) { |
|||
document.getElementById('dm_bookingId').value = bookingId; |
|||
document.getElementById('dm_bookingStatus').value = bookingStatus; |
|||
document.getElementById('dm_transactionId').value = transactionId || ''; |
|||
document.getElementById('dm_tpslId').value = tpslId || ''; |
|||
document.getElementById('dm_refundAmount').value = refundAmount || 0; |
|||
|
|||
var amt = parseFloat(refundAmount || 0).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); |
|||
|
|||
var body = 'Hi,\n\n'; |
|||
body += 'Kindly update refund status for the foresaid transaction made for Community Hall Booking.\n\n'; |
|||
body += 'Transaction Details:\n\n'; |
|||
body += ' Transaction ID : ' + (transactionId || 'N/A') + '\n'; |
|||
body += ' TPSL ID : ' + (tpslId || 'N/A') + '\n'; |
|||
body += ' Transaction Date : ' + (transactionDate || 'N/A') + '\n'; |
|||
body += ' Refund Amount : ₹ ' + amt + '\n\n'; |
|||
body += 'If refund was not initiated, kindly initiate the refund and update refund status at the earliest. '; |
|||
body += 'Make sure that no duplicate refund was processed against this transaction.\n\n'; |
|||
body += 'Regards,\n'; |
|||
body += 'Community Hall Support\n'; |
|||
body += 'Greater Chennai Corporation'; |
|||
|
|||
document.getElementById('draftMailBody').textContent = body; |
|||
$('#draftMailModal').modal('show'); |
|||
} |
|||
|
|||
function confirmMailSent() { |
|||
var bookingId = document.getElementById('dm_bookingId').value; |
|||
var bookingStatus = document.getElementById('dm_bookingStatus').value; |
|||
var transactionId = document.getElementById('dm_transactionId').value; |
|||
var tpslId = document.getElementById('dm_tpslId').value; |
|||
var refundAmount = document.getElementById('dm_refundAmount').value; |
|||
|
|||
var mailTo = "pgsupport@mail.in.worldline-solutions.com,ranjithkumar@federal.bank.in,megha.mattamana@federal.bank.in"; |
|||
var mailCc = "arohqcc@gmail.com,it@chennaicorporation.gov.in"; |
|||
var mailSubject = "Refund Status Update Request – Community Hall Booking"; |
|||
var mailBody = document.getElementById('draftMailBody').textContent; |
|||
var mailtoLink = "mailto:" + mailTo + "?cc=" + mailCc + "&subject=" + encodeURIComponent(mailSubject) + "&body=" + encodeURIComponent(mailBody); |
|||
|
|||
window.location.href = mailtoLink; |
|||
document.getElementById('btn-confirm-mail').disabled = true; |
|||
|
|||
$.ajax({ |
|||
type: 'POST', |
|||
url: '/communityhall/headquarters/sixmonthold-transactions/markMailSent', |
|||
data: { |
|||
bookingId: bookingId, |
|||
bookingStatus: bookingStatus, |
|||
transactionId: transactionId, |
|||
tpslId: tpslId, |
|||
refundAmount: refundAmount |
|||
}, |
|||
success: function (resp) { |
|||
$('#draftMailModal').modal('hide'); |
|||
if (resp.status === 'success') { |
|||
Swal.fire({ |
|||
icon: 'success', |
|||
title: 'Mail Recorded!', |
|||
text: 'Booking ID ' + bookingId + ' has been moved to "Mail Sent Bookings" tab.', |
|||
confirmButtonColor: '#1a73e8' |
|||
}).then(function () { |
|||
location.reload(); |
|||
}); |
|||
} else { |
|||
Swal.fire('Error', resp.message || 'An error occurred.', 'error'); |
|||
document.getElementById('btn-confirm-mail').disabled = false; |
|||
} |
|||
}, |
|||
error: function () { |
|||
Swal.fire('Error', 'Failed to mark mail as sent. Please try again.', 'error'); |
|||
document.getElementById('btn-confirm-mail').disabled = false; |
|||
} |
|||
}); |
|||
} |
|||
</script> |
|||
</body> |
|||
|
|||
</html> |
|||
4728
src/main/resources/templates/admin/reports.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4336
src/main/resources/templates/headquarters/reports.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1772
src/main/resources/templates/headquarters/sixmonthold-transactions.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue