diff --git a/src/main/java/com/rit/whatsapp/controller/WebhookController.java b/src/main/java/com/rit/whatsapp/controller/WebhookController.java index fdcca8a..f31dd5b 100644 --- a/src/main/java/com/rit/whatsapp/controller/WebhookController.java +++ b/src/main/java/com/rit/whatsapp/controller/WebhookController.java @@ -21,6 +21,9 @@ public class WebhookController { @Value("${whatsapp.verify-token:my_secure_verify_token}") private String verifyToken; + @Value("${whatsapp.phone-number-id:}") + private String configuredPhoneId; + private final WhatsAppMessageService messageService; private final SessionService sessionService; private final StudentMenuHandler studentMenuHandler; @@ -71,6 +74,20 @@ public class WebhookController { JsonNode changesNode = entryNode.get("changes").get(0); JsonNode valueNode = changesNode.get("value"); + if (valueNode != null) { + if (valueNode.has("metadata")) { + JsonNode metadataNode = valueNode.get("metadata"); + if (metadataNode.has("phone_number_id")) { + String incomingPhoneId = metadataNode.get("phone_number_id").asText(); + if (configuredPhoneId != null && !configuredPhoneId.trim().isEmpty() + && !incomingPhoneId.trim().equals(configuredPhoneId.trim())) { + System.out.println("Incoming phone ID " + incomingPhoneId + " does not match configured ID " + configuredPhoneId + ". Ignoring webhook payload."); + return ResponseEntity.ok("EVENT_IGNORED"); + } + } + } + } + if (valueNode != null && valueNode.has("messages") && valueNode.get("messages").isArray()) { JsonNode messageNode = valueNode.get("messages").get(0); diff --git a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java index c6dbc0b..26623ea 100644 --- a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java +++ b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java @@ -415,9 +415,9 @@ public class StudentMenuHandler { public void sendInternalMarksMenu(String phoneNumber) { List> rows = new ArrayList<>(); - rows.add(createRow("student_cat1_marks", "CAT 1 Marks", "View CAT 1 (CO1) marks")); - rows.add(createRow("student_cat2_marks", "CAT 2 Marks", "View CAT 2 (CO2) marks")); - rows.add(createRow("student_cat3_marks", "CAT 3 Marks", "View CAT 3 (CO3) marks")); + rows.add(createRow("student_cat1_marks", "CAT 1 Marks", "View CAT 1 (CO1 & CO2) marks")); + rows.add(createRow("student_cat2_marks", "CAT 2 Marks", "View CAT 2 (CO3) marks")); + rows.add(createRow("student_cat3_marks", "CAT 3 Marks", "View CAT 3 (CO4 & CO5) marks")); rows.add(createRow("student_assignment_marks", "Assignment Marks", "View assignments 1-5 marks")); Map interactiveList = WhatsAppMessageBuilder.buildListMessage( diff --git a/src/main/java/com/rit/whatsapp/util/MessageFormatter.java b/src/main/java/com/rit/whatsapp/util/MessageFormatter.java index 43f67b4..5aa1ec2 100644 --- a/src/main/java/com/rit/whatsapp/util/MessageFormatter.java +++ b/src/main/java/com/rit/whatsapp/util/MessageFormatter.java @@ -285,6 +285,36 @@ public class MessageFormatter { return defaultMsg; } + private static boolean isPresent(String val) { + return val != null && !val.trim().isEmpty() && !val.equalsIgnoreCase("N/A") && !val.equalsIgnoreCase("null"); + } + + private static Double parseMark(String val) { + if (!isPresent(val)) return null; + try { + return Double.parseDouble(val.trim()); + } catch (NumberFormatException e) { + return null; + } + } + + private static String formatMarkValue(Double val) { + if (val == null) return "N/A"; + if (val == (long) val.doubleValue()) { + return String.format("%d", (long) val.doubleValue()); + } else { + return String.format(java.util.Locale.US, "%.1f", val); + } + } + + private static String formatDouble(double val) { + if (val == (long) val) { + return String.format("%d", (long) val); + } else { + return String.format(java.util.Locale.US, "%.2f", val); + } + } + public static String formatInternalMarks(String rawCatJson, String rawAssignmentJson) { StringBuilder sb = new StringBuilder(); sb.append("📈 *INTERNAL MARKS REPORT*\n\n"); @@ -312,10 +342,17 @@ public class MessageFormatter { String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); - String co1 = subject.has("co1") ? subject.get("co1").asText().trim() : ""; - String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; - String total = subject.has("total") ? subject.get("total").asText().trim() : ""; - String weightage = subject.has("weightage") ? subject.get("weightage").asText().trim() : ""; + String co1Str = subject.has("co1") ? subject.get("co1").asText().trim() : ""; + String co2Str = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + String co3Str = subject.has("co3") ? subject.get("co3").asText().trim() : ""; + String co4Str = subject.has("co4") ? subject.get("co4").asText().trim() : ""; + String co5Str = subject.has("co5") ? subject.get("co5").asText().trim() : ""; + + Double co1 = parseMark(co1Str); + Double co2 = parseMark(co2Str); + Double co3 = parseMark(co3Str); + Double co4 = parseMark(co4Str); + Double co5 = parseMark(co5Str); sb.append("📚 *").append(name).append("*"); if (!code.isEmpty()) { @@ -323,22 +360,39 @@ public class MessageFormatter { } sb.append("\n"); - if (!co1.isEmpty() || !co2.isEmpty()) { - sb.append(" ├─ "); - if (!co1.isEmpty()) sb.append("CO1: ").append(co1); - if (!co1.isEmpty() && !co2.isEmpty()) sb.append(" | "); - if (!co2.isEmpty()) sb.append("CO2: ").append(co2); - sb.append("\n"); - sb.append(" └─ "); - } else { - sb.append(" └─ "); + int activeCos = 0; + double total = 0.0; + java.util.List catDetails = new java.util.ArrayList<>(); + + if (co1 != null || co2 != null) { + catDetails.add(" ├─ *CAT 1 (CO1 & CO2)*: " + formatMarkValue(co1) + " | " + formatMarkValue(co2)); + if (co1 != null) { total += co1; activeCos++; } + if (co2 != null) { total += co2; activeCos++; } + } + if (co3 != null) { + catDetails.add(" ├─ *CAT 2 (CO3)*: " + formatMarkValue(co3)); + total += co3; + activeCos++; + } + if (co4 != null || co5 != null) { + catDetails.add(" ├─ *CAT 3 (CO4 & CO5)*: " + formatMarkValue(co4) + " | " + formatMarkValue(co5)); + if (co4 != null) { total += co4; activeCos++; } + if (co5 != null) { total += co5; activeCos++; } } - sb.append("*Total*: *").append(total.isEmpty() ? "N/A" : total).append("*"); - if (!weightage.isEmpty()) { - sb.append(" (").append(weightage).append(" wt)"); + for (String detail : catDetails) { + sb.append(detail).append("\n"); + } + + if (activeCos > 0) { + double maxMarks = activeCos * 25.0; + double weightage = total * 8.0 / 75.0; + double maxWeightage = activeCos * 8.0 / 3.0; + sb.append(" └─ *Total*: *").append(formatDouble(total)).append("/").append(formatDouble(maxMarks)) + .append("* (").append(formatDouble(weightage)).append("/").append(formatDouble(maxWeightage)).append(" wt)\n\n"); + } else { + sb.append(" └─ No CAT marks updated yet.\n\n"); } - sb.append("\n\n"); foundData = true; } } @@ -442,7 +496,8 @@ public class MessageFormatter { if (targetArray != null && targetArray.size() > 0) { for (JsonNode subject : targetArray) { String co1 = subject.has("co1") ? subject.get("co1").asText().trim() : ""; - if (!co1.isEmpty() && !co1.equalsIgnoreCase("N/A") && !co1.equalsIgnoreCase("null")) { + String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + if (isPresent(co1) || isPresent(co2)) { hasAnyCat1Marks = true; break; } @@ -458,14 +513,25 @@ public class MessageFormatter { String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); - String co1 = subject.has("co1") ? subject.get("co1").asText().trim() : ""; + String co1Str = subject.has("co1") ? subject.get("co1").asText().trim() : ""; + String co2Str = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + + Double co1 = parseMark(co1Str); + Double co2 = parseMark(co2Str); sb.append("📚 *").append(name).append("*"); if (!code.isEmpty()) { sb.append(" (").append(code).append(")"); } sb.append("\n"); - sb.append(" └─ *CAT 1 (CO1)*: *").append(co1.isEmpty() ? "N/A" : co1).append("*\n\n"); + sb.append(" ├─ CO1: ").append(formatMarkValue(co1)) + .append(" | CO2: ").append(formatMarkValue(co2)).append("\n"); + + double total = (co1 != null ? co1 : 0.0) + (co2 != null ? co2 : 0.0); + double weightage = total * 8.0 / 75.0; + + sb.append(" ├─ *Total*: *").append(formatDouble(total)).append("/50*\n"); + sb.append(" └─ *Internal Weightage*: *").append(formatDouble(weightage)).append("/5.33*\n\n"); foundData = true; } } @@ -502,8 +568,8 @@ public class MessageFormatter { boolean hasAnyCat2Marks = false; if (targetArray != null && targetArray.size() > 0) { for (JsonNode subject : targetArray) { - String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; - if (!co2.isEmpty() && !co2.equalsIgnoreCase("N/A") && !co2.equalsIgnoreCase("null")) { + String co3 = subject.has("co3") ? subject.get("co3").asText().trim() : ""; + if (isPresent(co3)) { hasAnyCat2Marks = true; break; } @@ -519,14 +585,22 @@ public class MessageFormatter { String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); - String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + String co3Str = subject.has("co3") ? subject.get("co3").asText().trim() : ""; + + Double co3 = parseMark(co3Str); sb.append("📚 *").append(name).append("*"); if (!code.isEmpty()) { sb.append(" (").append(code).append(")"); } sb.append("\n"); - sb.append(" └─ *CAT 2 (CO2)*: *").append(co2.isEmpty() ? "N/A" : co2).append("*\n\n"); + sb.append(" ├─ CO3: ").append(formatMarkValue(co3)).append("\n"); + + double total = co3 != null ? co3 : 0.0; + double weightage = total * 8.0 / 75.0; + + sb.append(" ├─ *Total*: *").append(formatDouble(total)).append("/25*\n"); + sb.append(" └─ *Internal Weightage*: *").append(formatDouble(weightage)).append("/2.67*\n\n"); foundData = true; } } @@ -563,8 +637,9 @@ public class MessageFormatter { boolean hasAnyCat3Marks = false; if (targetArray != null && targetArray.size() > 0) { for (JsonNode subject : targetArray) { - String co3 = subject.has("co3") ? subject.get("co3").asText().trim() : ""; - if (!co3.isEmpty() && !co3.equalsIgnoreCase("N/A") && !co3.equalsIgnoreCase("null")) { + String co4 = subject.has("co4") ? subject.get("co4").asText().trim() : ""; + String co5 = subject.has("co5") ? subject.get("co5").asText().trim() : ""; + if (isPresent(co4) || isPresent(co5)) { hasAnyCat3Marks = true; break; } @@ -580,14 +655,25 @@ public class MessageFormatter { String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); - String co3 = subject.has("co3") ? subject.get("co3").asText().trim() : ""; + String co4Str = subject.has("co4") ? subject.get("co4").asText().trim() : ""; + String co5Str = subject.has("co5") ? subject.get("co5").asText().trim() : ""; + + Double co4 = parseMark(co4Str); + Double co5 = parseMark(co5Str); sb.append("📚 *").append(name).append("*"); if (!code.isEmpty()) { sb.append(" (").append(code).append(")"); } sb.append("\n"); - sb.append(" └─ *CAT 3 (CO3)*: *").append(co3.isEmpty() ? "N/A" : co3).append("*\n\n"); + sb.append(" ├─ CO4: ").append(formatMarkValue(co4)) + .append(" | CO5: ").append(formatMarkValue(co5)).append("\n"); + + double total = (co4 != null ? co4 : 0.0) + (co5 != null ? co5 : 0.0); + double weightage = total * 8.0 / 75.0; + + sb.append(" ├─ *Total*: *").append(formatDouble(total)).append("/50*\n"); + sb.append(" └─ *Internal Weightage*: *").append(formatDouble(weightage)).append("/5.33*\n\n"); foundData = true; } }