From 71ddfe0f7b9759224aabea48f21d1655f8e3fea1 Mon Sep 17 00:00:00 2001 From: RIT Services Date: Fri, 21 Aug 2026 06:42:25 +0000 Subject: [PATCH] grievances redressal system --- .../whatsapp/handler/GrievanceHandler.java | 17 +- .../whatsapp/handler/StudentMenuHandler.java | 150 ++++++++++-------- src/main/resources/application.properties | 2 +- 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java b/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java index 638c5cc..2b74a20 100644 --- a/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java +++ b/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java @@ -30,19 +30,14 @@ public class GrievanceHandler { } public void startGrievanceFlow(String phoneNumber) { - sessionService.setUserState(phoneNumber, UserState.AWAITING_GRIEVANCE_CATEGORY); + sessionService.resetState(phoneNumber); - List> buttons = new ArrayList<>(); - buttons.add(createButton("grievance_academic", "Academic")); - buttons.add(createButton("grievance_hostel", "Hostel")); - buttons.add(createButton("grievance_other", "Other")); + String message = "📢 *RIT Grievance Portal Notice*\n\n" + + "Please note that grievances and complaints must be officially registered and tracked using our dedicated mobile application, *Complixr*.\n\n" + + "Kindly download the app from the Google Play Store to submit your ticket:\n" + + "🔗 https://play.google.com/store/apps/details?id=com.ritchennai.complixr&pcampaignid=web_share"; - Map buttonMessage = WhatsAppMessageBuilder.buildButtonMessage( - "Please select the category for your grievance:", - buttons - ); - - messageService.sendInteractiveMessage(phoneNumber, buttonMessage); + messageService.sendMessage(phoneNumber, message); studentMenuHandler.sendStudentMenuDirectly(phoneNumber); } diff --git a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java index 253cb25..99eff2f 100644 --- a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java +++ b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java @@ -68,30 +68,7 @@ public class StudentMenuHandler { break; case "student_timetable": - String rawTimetable = imsApiService.getTimetable(token); - String todaySchedule = MessageFormatter.formatTimetable(rawTimetable); - - // Truncate to stay safely within WhatsApp 1024 character limit for button bodies - if (todaySchedule.length() > 1020) { - todaySchedule = todaySchedule.substring(0, 1017) + "..."; - } - - List> buttons = new ArrayList<>(); - Map weeklyBtn = new HashMap<>(); - weeklyBtn.put("id", "student_weekly_timetable"); - weeklyBtn.put("title", "Weekly Timetable"); - buttons.add(weeklyBtn); - - Map menuBtn = new HashMap<>(); - menuBtn.put("id", "student_show_menu"); - menuBtn.put("title", "Student Menu"); - buttons.add(menuBtn); - - System.out.println("FINAL TODAY TIMETABLE MESSAGE:\n" + todaySchedule); - - Map buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons); - messageService.sendInteractiveMessage(phoneNumber, buttonMessage); - sendStudentMenuDirectly(phoneNumber); + sendTimetableMenu(phoneNumber, token); break; case "student_internal_marks": @@ -113,35 +90,14 @@ public class StudentMenuHandler { case "student_assignment_marks": handleAssignmentMarks(phoneNumber); break; - + case "student_semester_results": sendSemesterSelection(phoneNumber, token); break; - - case "student_fee_details": { - String rawFees = imsApiService.getFees(token); - String bodyText = MessageFormatter.formatAcademicFeesOnly(rawFees); - - List> feeButtons = new ArrayList<>(); - Map examBtn = new HashMap<>(); - examBtn.put("id", "student_exam_fees"); - examBtn.put("title", "Exam Fees"); - feeButtons.add(examBtn); - - Map historyBtn = new HashMap<>(); - historyBtn.put("id", "student_payment_history"); - historyBtn.put("title", "Payment History"); - feeButtons.add(historyBtn); - - if (bodyText.length() > 1020) { - bodyText = bodyText.substring(0, 1017) + "..."; - } - - Map feeButtonMessage = WhatsAppMessageBuilder.buildButtonMessage(bodyText, feeButtons); - messageService.sendInteractiveMessage(phoneNumber, feeButtonMessage); - sendStudentMenuDirectly(phoneNumber); + + case "student_fee_details": + sendFeeDetailsMenu(phoneNumber, token); break; - } case "student_raise_grievance": grievanceHandler.startGrievanceFlow(phoneNumber); @@ -208,16 +164,18 @@ public class StudentMenuHandler { if (mediaId != null) { messageService.sendDocumentMessage(phoneNumber, mediaId, "Here are your Semester " + semester + " results!", fileName); - // Send menu afterwards - sendResponseWithMenu(phoneNumber, "Select an option from the menu below."); + sendSemesterSelection(phoneNumber, token); } else { - sendResponseWithMenu(phoneNumber, "Failed to upload the results document to WhatsApp."); + messageService.sendMessage(phoneNumber, "Failed to upload the results document to WhatsApp."); + sendSemesterSelection(phoneNumber, token); } } else { - sendResponseWithMenu(phoneNumber, "Failed to download your results. They may not be published yet."); + messageService.sendMessage(phoneNumber, "Failed to download your results. They may not be published yet."); + sendSemesterSelection(phoneNumber, token); } } catch (Exception e) { - sendResponseWithMenu(phoneNumber, "Invalid semester selected."); + messageService.sendMessage(phoneNumber, "Invalid semester selected."); + sendSemesterSelection(phoneNumber, token); } sessionService.resetState(phoneNumber); // Reset state after fetching results @@ -256,15 +214,18 @@ public class StudentMenuHandler { String mediaId = messageService.uploadMedia(pdfBytes, fileName, "application/pdf"); if (mediaId != null) { messageService.sendDocumentMessage(phoneNumber, mediaId, docMessage, fileName); - sendResponseWithMenu(phoneNumber, "Select an option from the menu below."); + sendPaymentHistoryMenu(phoneNumber, token); } else { - sendResponseWithMenu(phoneNumber, "Failed to upload the receipt document to WhatsApp."); + messageService.sendMessage(phoneNumber, "Failed to upload the receipt document to WhatsApp."); + sendPaymentHistoryMenu(phoneNumber, token); } } else { - sendResponseWithMenu(phoneNumber, "Failed to download your receipt. It may not be available."); + messageService.sendMessage(phoneNumber, "Failed to download your receipt. It may not be available."); + sendPaymentHistoryMenu(phoneNumber, token); } } catch (Exception e) { - sendResponseWithMenu(phoneNumber, "Invalid receipt selected."); + messageService.sendMessage(phoneNumber, "Invalid receipt selected."); + sendPaymentHistoryMenu(phoneNumber, token); } sessionService.resetState(phoneNumber); // Reset state after fetching receipt @@ -283,8 +244,8 @@ public class StudentMenuHandler { // Send weekly timetable as standard message (up to 4096 characters limit) messageService.sendMessage(phoneNumber, weeklyTimetable); - // Follow up with Student Menu list message - sendResponseWithMenu(phoneNumber, "Select an option from the menu below."); + // Follow up with Timetable sub-menu again + sendTimetableMenu(phoneNumber, token); } public void handleExamFees(String phoneNumber) { @@ -296,7 +257,8 @@ public class StudentMenuHandler { String rawExamFees = imsApiService.getExamFees(token); String formattedExamFees = MessageFormatter.formatExamFees(rawExamFees); - sendResponseWithMenu(phoneNumber, formattedExamFees); + messageService.sendMessage(phoneNumber, formattedExamFees); + sendFeeDetailsMenu(phoneNumber, token); } public void handlePaymentHistory(String phoneNumber) { @@ -305,7 +267,61 @@ public class StudentMenuHandler { messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again."); return; } + sendPaymentHistoryMenu(phoneNumber, token); + } + public void sendTimetableMenu(String phoneNumber, String token) { + String rawTimetable = imsApiService.getTimetable(token); + String todaySchedule = MessageFormatter.formatTimetable(rawTimetable); + + // Truncate to stay safely within WhatsApp 1024 character limit for button bodies + if (todaySchedule.length() > 1020) { + todaySchedule = todaySchedule.substring(0, 1017) + "..."; + } + + List> buttons = new ArrayList<>(); + Map weeklyBtn = new HashMap<>(); + weeklyBtn.put("id", "student_weekly_timetable"); + weeklyBtn.put("title", "Weekly Timetable"); + buttons.add(weeklyBtn); + + Map menuBtn = new HashMap<>(); + menuBtn.put("id", "student_show_menu"); + menuBtn.put("title", "Student Menu"); + buttons.add(menuBtn); + + System.out.println("FINAL TODAY TIMETABLE MESSAGE:\n" + todaySchedule); + + Map buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons); + messageService.sendInteractiveMessage(phoneNumber, buttonMessage); + sendStudentMenuDirectly(phoneNumber); + } + + public void sendFeeDetailsMenu(String phoneNumber, String token) { + String rawFees = imsApiService.getFees(token); + String bodyText = MessageFormatter.formatAcademicFeesOnly(rawFees); + + List> feeButtons = new ArrayList<>(); + Map examBtn = new HashMap<>(); + examBtn.put("id", "student_exam_fees"); + examBtn.put("title", "Exam Fees"); + feeButtons.add(examBtn); + + Map historyBtn = new HashMap<>(); + historyBtn.put("id", "student_payment_history"); + historyBtn.put("title", "Payment History"); + feeButtons.add(historyBtn); + + if (bodyText.length() > 1020) { + bodyText = bodyText.substring(0, 1017) + "..."; + } + + Map feeButtonMessage = WhatsAppMessageBuilder.buildButtonMessage(bodyText, feeButtons); + messageService.sendInteractiveMessage(phoneNumber, feeButtonMessage); + sendStudentMenuDirectly(phoneNumber); + } + + public void sendPaymentHistoryMenu(String phoneNumber, String token) { String rawExamFees = imsApiService.getExamFees(token); String rawFeesHistory = imsApiService.getAcademicFeesHistory(token); @@ -408,7 +424,8 @@ public class StudentMenuHandler { } String rawCatMarks = imsApiService.getCatMarks(token); String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat1Marks(rawCatMarks); - sendResponseWithMenu(phoneNumber, formatted); + messageService.sendMessage(phoneNumber, formatted); + sendInternalMarksMenu(phoneNumber); } public void handleCat2Marks(String phoneNumber) { @@ -419,7 +436,8 @@ public class StudentMenuHandler { } String rawCatMarks = imsApiService.getCatMarks(token); String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat2Marks(rawCatMarks); - sendResponseWithMenu(phoneNumber, formatted); + messageService.sendMessage(phoneNumber, formatted); + sendInternalMarksMenu(phoneNumber); } public void handleCat3Marks(String phoneNumber) { @@ -430,7 +448,8 @@ public class StudentMenuHandler { } String rawCatMarks = imsApiService.getCatMarks(token); String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat3Marks(rawCatMarks); - sendResponseWithMenu(phoneNumber, formatted); + messageService.sendMessage(phoneNumber, formatted); + sendInternalMarksMenu(phoneNumber); } public void handleAssignmentMarks(String phoneNumber) { @@ -441,7 +460,8 @@ public class StudentMenuHandler { } String rawAssignmentMarks = imsApiService.getAssignmentMarks(token); String formatted = com.rit.whatsapp.util.MessageFormatter.formatAssignmentMarks(rawAssignmentMarks); - sendResponseWithMenu(phoneNumber, formatted); + messageService.sendMessage(phoneNumber, formatted); + sendInternalMarksMenu(phoneNumber); } private List> getStudentMenuRows() { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 69fd92f..ed21454 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,4 +18,4 @@ spring.jpa.hibernate.ddl-auto=update # Encryption Secret for Passcodes (Must be 16, 24, or 32 bytes) bot.encryption.secret=12345678901234567890123456789012 -whatsapp.api-token=EAAc3Wjql00oBSWGWTlmDkMegzpdfKYWqNp0jci6efxyhHArM0371vc3t8XEZA74jgy6reRpS0XTwH1qUSoiJ5t1KjlX3PpY2fUVa1zAaWBDq0FB5YG6ll20pSfZBHHcvAABIweGSkWDY4Oe2znY76JWSlPpD0LXORdiRTZChu1uTMOMSgUxGdaQTiJJzxkVovCrK6jzocjGzwZCCLKAKyxKqLMECDfwgnrxaTqwloQ7oZA1X1ZCstFvPfGQ32LJ59SBeGzTuC3PM8GewZB6uvYiKSuGEAZDZD +whatsapp.api-token=EAAc3Wjql00oBSfyIYrQFVzHx9HAmlgBc75yGbmaO1S3oKdDPh6CQixkG16ZA7L70jihZCbVakpiSHsNWTPzyYqy7WEYebZA6B5qVWLww41LZB6szCM582B6WZAkeeoGlzuSBWzrfZAm4ZA9AOedp2mEWdximSNbmbkwn82a1cj1gpCOdZAo5tJfSmZCwy9ZAQEfRrCUY4vaL4HFwNFrZAiEp1lGtamEL2ZBPscutz4xzfaR1X343zroZCxrrP5zpiKUCCAzIX4Oe4RqPMsmaIMzq5oC05BKewHQZDZD