From 31fcc276588f0dc21e6f93ee39a23397db952a13 Mon Sep 17 00:00:00 2001 From: Abiram070207 Date: Tue, 30 Jun 2026 12:24:30 +0530 Subject: [PATCH] Backend migrated to springboot from firebase --- backend/pom.xml | 61 ++ .../main/java/com/rit/ems/EmsApplication.java | 11 + .../java/com/rit/ems/config/CorsConfig.java | 23 + .../java/com/rit/ems/config/DataSeeder.java | 110 ++++ .../rit/ems/controller/AdminController.java | 102 ++++ .../controller/AnnouncementController.java | 47 ++ .../ems/controller/AttendanceController.java | 72 +++ .../rit/ems/controller/AuthController.java | 220 +++++++ .../rit/ems/controller/BatchController.java | 42 ++ .../rit/ems/controller/ClassController.java | 69 +++ .../rit/ems/controller/EventController.java | 544 ++++++++++++++++++ .../InstitutionalEventController.java | 38 ++ .../rit/ems/controller/NoteController.java | 40 ++ .../controller/RegistrationController.java | 211 +++++++ .../rit/ems/controller/SettingController.java | 40 ++ .../controller/SpecialEventController.java | 55 ++ .../rit/ems/controller/VenueController.java | 39 ++ .../java/com/rit/ems/model/Announcement.java | 48 ++ .../java/com/rit/ems/model/Attendance.java | 100 ++++ .../main/java/com/rit/ems/model/Batch.java | 35 ++ .../java/com/rit/ems/model/ClassMapping.java | 53 ++ .../main/java/com/rit/ems/model/Event.java | 341 +++++++++++ .../com/rit/ems/model/InstitutionalEvent.java | 37 ++ .../src/main/java/com/rit/ems/model/Note.java | 48 ++ .../java/com/rit/ems/model/Registration.java | 222 +++++++ .../main/java/com/rit/ems/model/Setting.java | 28 + .../java/com/rit/ems/model/SpecialEvent.java | 92 +++ .../src/main/java/com/rit/ems/model/User.java | 147 +++++ .../main/java/com/rit/ems/model/Venue.java | 32 ++ .../repository/AnnouncementRepository.java | 7 + .../ems/repository/AttendanceRepository.java | 10 + .../rit/ems/repository/BatchRepository.java | 7 + .../repository/ClassMappingRepository.java | 7 + .../rit/ems/repository/EventRepository.java | 7 + .../InstitutionalEventRepository.java | 7 + .../rit/ems/repository/NoteRepository.java | 7 + .../repository/RegistrationRepository.java | 13 + .../rit/ems/repository/SettingRepository.java | 7 + .../repository/SpecialEventRepository.java | 7 + .../rit/ems/repository/UserRepository.java | 9 + .../rit/ems/repository/VenueRepository.java | 7 + .../java/com/rit/ems/util/JsonConverter.java | 35 ++ .../src/main/resources/application.properties | 17 + frontend/src/main.tsx | 2 +- 44 files changed, 3055 insertions(+), 1 deletion(-) create mode 100644 backend/pom.xml create mode 100644 backend/src/main/java/com/rit/ems/EmsApplication.java create mode 100644 backend/src/main/java/com/rit/ems/config/CorsConfig.java create mode 100644 backend/src/main/java/com/rit/ems/config/DataSeeder.java create mode 100644 backend/src/main/java/com/rit/ems/controller/AdminController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/AnnouncementController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/AttendanceController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/AuthController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/BatchController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/ClassController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/EventController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/InstitutionalEventController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/NoteController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/RegistrationController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/SettingController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/SpecialEventController.java create mode 100644 backend/src/main/java/com/rit/ems/controller/VenueController.java create mode 100644 backend/src/main/java/com/rit/ems/model/Announcement.java create mode 100644 backend/src/main/java/com/rit/ems/model/Attendance.java create mode 100644 backend/src/main/java/com/rit/ems/model/Batch.java create mode 100644 backend/src/main/java/com/rit/ems/model/ClassMapping.java create mode 100644 backend/src/main/java/com/rit/ems/model/Event.java create mode 100644 backend/src/main/java/com/rit/ems/model/InstitutionalEvent.java create mode 100644 backend/src/main/java/com/rit/ems/model/Note.java create mode 100644 backend/src/main/java/com/rit/ems/model/Registration.java create mode 100644 backend/src/main/java/com/rit/ems/model/Setting.java create mode 100644 backend/src/main/java/com/rit/ems/model/SpecialEvent.java create mode 100644 backend/src/main/java/com/rit/ems/model/User.java create mode 100644 backend/src/main/java/com/rit/ems/model/Venue.java create mode 100644 backend/src/main/java/com/rit/ems/repository/AnnouncementRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/AttendanceRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/BatchRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/ClassMappingRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/EventRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/InstitutionalEventRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/NoteRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/RegistrationRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/SettingRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/SpecialEventRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/UserRepository.java create mode 100644 backend/src/main/java/com/rit/ems/repository/VenueRepository.java create mode 100644 backend/src/main/java/com/rit/ems/util/JsonConverter.java create mode 100644 backend/src/main/resources/application.properties diff --git a/backend/pom.xml b/backend/pom.xml new file mode 100644 index 0000000..8c62560 --- /dev/null +++ b/backend/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.0 + + + com.rit + ems + 0.0.1-SNAPSHOT + ems + Event Management System Backend + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.mysql + mysql-connector-j + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + diff --git a/backend/src/main/java/com/rit/ems/EmsApplication.java b/backend/src/main/java/com/rit/ems/EmsApplication.java new file mode 100644 index 0000000..65dac05 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/EmsApplication.java @@ -0,0 +1,11 @@ +package com.rit.ems; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class EmsApplication { + public static void main(String[] args) { + SpringApplication.run(EmsApplication.class, args); + } +} diff --git a/backend/src/main/java/com/rit/ems/config/CorsConfig.java b/backend/src/main/java/com/rit/ems/config/CorsConfig.java new file mode 100644 index 0000000..0c4527d --- /dev/null +++ b/backend/src/main/java/com/rit/ems/config/CorsConfig.java @@ -0,0 +1,23 @@ +package com.rit.ems.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig { + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") + .allowedHeaders("*") + .allowCredentials(true); + } + }; + } +} diff --git a/backend/src/main/java/com/rit/ems/config/DataSeeder.java b/backend/src/main/java/com/rit/ems/config/DataSeeder.java new file mode 100644 index 0000000..ce275bc --- /dev/null +++ b/backend/src/main/java/com/rit/ems/config/DataSeeder.java @@ -0,0 +1,110 @@ +package com.rit.ems.config; + +import com.rit.ems.model.*; +import com.rit.ems.repository.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Component +public class DataSeeder implements CommandLineRunner { + + @Autowired + private UserRepository userRepository; + + @Autowired + private ClassMappingRepository classMappingRepository; + + @Autowired + private VenueRepository venueRepository; + + @Autowired + private InstitutionalEventRepository institutionalEventRepository; + + @Override + public void run(String... args) throws Exception { + seedUsers(); + seedClasses(); + seedVenues(); + seedInstitutionalEvents(); + } + + private void seedUsers() { + if (userRepository.count() == 0) { + System.out.println("[DataSeeder] Seeding default users..."); + List defaultUsers = Arrays.asList( + new User(1L, "admin@rit.edu", "admin123", "System Administrator", "ADMIN", "ADMIN", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(2L, "faculty@rit.edu", "faculty123", "Dr. Faculty Member", "FACULTY", "CSE", false, false, true, 0, "CSE", "3rd Year", "A", "3rd Year", "A", null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(3L, "hod@rit.edu", "hod123", "Prof. Head of Dept", "HOD", "AI&ML", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(4L, "principal@rit.edu", "principal123", "Dr. College Principal", "PRINCIPAL", "ADMIN", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(5L, "placement@rit.edu", "placement123", "Placement Coordinator", "PLACEMENT", "Placement Department", false, true, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(6L, "admin2@rit.edu", "admin123", "Secondary Admin", "ADMIN", "ADMIN", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(7L, "principal2@rit.edu", "principal123", "Vice Principal", "PRINCIPAL", "ADMIN", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(8L, "hod_cse@rit.edu", "hod123", "CSE HOD", "HOD", "CSE", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()), + new User(9L, "faculty2@rit.edu", "faculty123", "Assistant Professor CSE", "FACULTY", "CSE", false, false, false, 0, null, null, null, null, null, null, "", "Male", "Rajalakshmi Institute of Technology", new ArrayList<>()) + ); + userRepository.saveAll(defaultUsers); + } + } + + private void seedClasses() { + if (classMappingRepository.count() == 0) { + System.out.println("[DataSeeder] Seeding default classes..."); + List defaultClasses = Arrays.asList( + new ClassMapping(1L, "RIT", "CSE", "3rd Year", Arrays.asList("A", "B"), "Ready"), + new ClassMapping(2L, "RIT", "AI&ML", "3rd Year", Collections.singletonList("A"), "Ready"), + new ClassMapping(3L, "RIT", "ECE", "2nd Year", Arrays.asList("A", "B", "C"), "Ready") + ); + classMappingRepository.saveAll(defaultClasses); + } + } + + private void seedVenues() { + if (venueRepository.count() == 0) { + System.out.println("[DataSeeder] Seeding default venues..."); + List defaultVenues = Arrays.asList( + new Venue("v-1", "GB 4th floor auditorium", 500), + new Venue("v-2", "Wozniak Auditorium", 180), + new Venue("v-3", "C6-02 Indoor Theatre", 180), + new Venue("v-4", "H Block Guest Lecture Theatre", 60), + new Venue("v-5", "Steve Jobs Computer Centre 1", 120), + new Venue("v-6", "Steve Jobs Computer Centre 2", 120) + ); + venueRepository.saveAll(defaultVenues); + } + } + + private void seedInstitutionalEvents() { + if (institutionalEventRepository.count() == 0) { + System.out.println("[DataSeeder] Seeding institutional events..."); + List defaultEvents = Arrays.asList( + new InstitutionalEvent("ie-1", "New Year & Christmas Celebration", "January", "EVEN"), + new InstitutionalEvent("ie-2", "Republic Day Celebration", "January", "EVEN"), + new InstitutionalEvent("ie-3", "Pongal Celebration", "January", "EVEN"), + new InstitutionalEvent("ie-4", "Yatra Banner Release", "January", "EVEN"), + new InstitutionalEvent("ie-5", "Yatra Ethnic Day", "February", "EVEN"), + new InstitutionalEvent("ie-6", "Yatra", "February", "EVEN"), + new InstitutionalEvent("ie-7", "International Womens Day", "March", "EVEN"), + new InstitutionalEvent("ie-8", "Ugathi", "March", "EVEN"), + new InstitutionalEvent("ie-9", "Tamil New Year", "April", "EVEN"), + new InstitutionalEvent("ie-10", "Techritz", "July", "ODD"), + new InstitutionalEvent("ie-11", "Independence Day", "August", "ODD"), + new InstitutionalEvent("ie-12", "AI Horizon Week", "August", "ODD"), + new InstitutionalEvent("ie-13", "Initiation Day", "September", "ODD"), + new InstitutionalEvent("ie-14", "Onam Celebration", "September", "ODD"), + new InstitutionalEvent("ie-15", "Teachers Day", "September", "ODD"), + new InstitutionalEvent("ie-16", "Engineers Day", "September", "ODD"), + new InstitutionalEvent("ie-17", "SDG Golu", "September", "ODD"), + new InstitutionalEvent("ie-18", "Ayutha Puja", "October", "ODD"), + new InstitutionalEvent("ie-19", "Tech Fest IIT Bombay", "October", "ODD"), + new InstitutionalEvent("ie-20", "EDI Conclave - FICCI Flow", "November", "ODD") + ); + institutionalEventRepository.saveAll(defaultEvents); + } + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/AdminController.java b/backend/src/main/java/com/rit/ems/controller/AdminController.java new file mode 100644 index 0000000..df130f3 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/AdminController.java @@ -0,0 +1,102 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.User; +import com.rit.ems.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; + +@RestController +@RequestMapping("/api/admin/users") +public class AdminController { + + @Autowired + private UserRepository userRepository; + + @GetMapping + public List getAllUsers() { + return userRepository.findAll(); + } + + @PostMapping + public ResponseEntity createUser(@RequestBody User userPayload) { + Optional existing = userRepository.findByEmailIgnoreCase(userPayload.getEmail()); + String role = userPayload.getRole() != null ? userPayload.getRole() : "FACULTY"; + String department = userPayload.getDepartment() != null ? userPayload.getDepartment() : + ((role.equals("HOD") || role.equals("FACULTY")) ? "H&S Dept" : ""); + + if (existing.isPresent()) { + User existingUser = existing.get(); + if ("STUDENT".equals(existingUser.getRole())) { + // Promote existing student to faculty/staff + existingUser.setRole(role); + existingUser.setDepartment(department); + existingUser.setFullName(userPayload.getFullName()); + if (userPayload.getAssignedClubs() != null) { + existingUser.setAssignedClubs(userPayload.getAssignedClubs()); + } + userRepository.save(existingUser); + return ResponseEntity.ok(existingUser); + } else { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message", "User with this email already exists")); + } + } + + userPayload.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + userPayload.setEmail(userPayload.getEmail().trim().toLowerCase()); + userPayload.setFullName(userPayload.getFullName().trim()); + userPayload.setRole(role); + userPayload.setDepartment(department); + if (userPayload.getAssignedClubs() == null) { + userPayload.setAssignedClubs(new java.util.ArrayList<>()); + } + + userRepository.save(userPayload); + return ResponseEntity.ok(userPayload); + } + + @PutMapping("/{id}") + public ResponseEntity updateUser(@PathVariable Long id, @RequestBody Map payload) { + Optional userOpt = userRepository.findById(id); + if (userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("message", "User not found")); + } + + User user = userOpt.get(); + if (payload.containsKey("fullName")) user.setFullName((String) payload.get("fullName")); + if (payload.containsKey("email")) user.setEmail(((String) payload.get("email")).trim().toLowerCase()); + if (payload.containsKey("role")) user.setRole((String) payload.get("role")); + if (payload.containsKey("department")) user.setDepartment((String) payload.get("department")); + if (payload.containsKey("isClubCoordinator")) user.setIsClubCoordinator((Boolean) payload.get("isClubCoordinator")); + if (payload.containsKey("isPlacementStaff")) user.setIsPlacementStaff((Boolean) payload.get("isPlacementStaff")); + if (payload.containsKey("isClassIncharge")) user.setIsClassIncharge((Boolean) payload.get("isClassIncharge")); + if (payload.containsKey("classStrength")) user.setClassStrength(Integer.parseInt(payload.get("classStrength").toString())); + if (payload.containsKey("inchargeClass")) user.setInchargeClass((String) payload.get("inchargeClass")); + if (payload.containsKey("inchargeBatch")) user.setInchargeBatch((String) payload.get("inchargeBatch")); + if (payload.containsKey("inchargeSection")) user.setInchargeSection((String) payload.get("inchargeSection")); + if (payload.containsKey("year")) user.setYear((String) payload.get("year")); + if (payload.containsKey("section")) user.setSection((String) payload.get("section")); + if (payload.containsKey("regNo")) user.setRegNo((String) payload.get("regNo")); + if (payload.containsKey("phone")) user.setPhone((String) payload.get("phone")); + if (payload.containsKey("gender")) user.setGender((String) payload.get("gender")); + if (payload.containsKey("collegeName")) user.setCollegeName((String) payload.get("collegeName")); + if (payload.containsKey("assignedClubs")) { + user.setAssignedClubs((List) payload.get("assignedClubs")); + } + + userRepository.save(user); + return ResponseEntity.ok(user); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUser(@PathVariable Long id) { + userRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "User deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/AnnouncementController.java b/backend/src/main/java/com/rit/ems/controller/AnnouncementController.java new file mode 100644 index 0000000..1c37ae7 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/AnnouncementController.java @@ -0,0 +1,47 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Announcement; +import com.rit.ems.repository.AnnouncementRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RestController +@RequestMapping("/api/announcements") +public class AnnouncementController { + + @Autowired + private AnnouncementRepository announcementRepository; + + @GetMapping + public List getAllAnnouncements() { + List list = announcementRepository.findAll(); + list.sort((a, b) -> { + String ta = a.getTimestamp() != null ? a.getTimestamp() : ""; + String tb = b.getTimestamp() != null ? b.getTimestamp() : ""; + return tb.compareTo(ta); // Descending order + }); + return list; + } + + @PostMapping + public ResponseEntity createAnnouncement(@RequestBody Announcement ann) { + if (ann.getId() == null) { + ann.setId(String.valueOf(System.currentTimeMillis() + new Random().nextInt(1000))); + } + ann.setTimestamp(Instant.now().toString()); + announcementRepository.save(ann); + return ResponseEntity.ok(ann); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteAnnouncement(@PathVariable String id) { + announcementRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Announcement deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/AttendanceController.java b/backend/src/main/java/com/rit/ems/controller/AttendanceController.java new file mode 100644 index 0000000..cad2233 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/AttendanceController.java @@ -0,0 +1,72 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Attendance; +import com.rit.ems.repository.AttendanceRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/attendance") +public class AttendanceController { + + @Autowired + private AttendanceRepository attendanceRepository; + + @GetMapping + public List getAttendance(@RequestParam(required = false) String registrationId, + @RequestParam(required = false) Long eventId) { + if (registrationId != null) { + return attendanceRepository.findByRegistrationId(registrationId); + } + if (eventId != null) { + return attendanceRepository.findByEventId(eventId); + } + return attendanceRepository.findAll(); + } + + @PostMapping + public ResponseEntity saveAttendance(@RequestBody Object payload) { + List> records = new ArrayList<>(); + if (payload instanceof List) { + records = (List>) payload; + } else if (payload instanceof Map) { + records.add((Map) payload); + } + + for (Map rec : records) { + String regId = (String) (rec.containsKey("registrationId") ? rec.get("registrationId") : rec.get("registration_id")); + String day = (String) (rec.containsKey("dayLabel") ? rec.get("dayLabel") : + (rec.containsKey("day_idx") ? rec.get("day_idx") : "Day 1")); + String slot = (String) (rec.containsKey("batchLabel") ? rec.get("batchLabel") : + (rec.containsKey("batch_idx") ? rec.get("batch_idx") : "Batch 1")); + + Object eventIdObj = rec.containsKey("eventId") ? rec.get("eventId") : rec.get("event_id"); + Long eventId = eventIdObj != null ? Long.parseLong(eventIdObj.toString()) : null; + + String id = regId + "_" + day + "_" + slot; + Boolean isPresent = (Boolean) (rec.containsKey("isPresent") ? rec.get("isPresent") : rec.get("is_present")); + String date = (String) rec.get("date"); + if (date == null) { + date = LocalDate.now().toString(); + } + + Attendance att = new Attendance(); + att.setId(id); + att.setRegistrationId(regId); + att.setEventId(eventId); + att.setDayLabel(day); + att.setBatchLabel(slot); + att.setIsPresent(Boolean.TRUE.equals(isPresent)); + att.setDate(date); + + attendanceRepository.save(att); + } + return ResponseEntity.ok(Map.of("message", "Attendance updated successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/AuthController.java b/backend/src/main/java/com/rit/ems/controller/AuthController.java new file mode 100644 index 0000000..553d835 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/AuthController.java @@ -0,0 +1,220 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.User; +import com.rit.ems.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Random; + +@RestController +@RequestMapping("/api/auth") +public class AuthController { + + @Autowired + private UserRepository userRepository; + + @PostMapping("/login") + public ResponseEntity login(@RequestBody Map payload) { + String email = payload.get("email"); + String password = payload.get("password"); + + if (email == null || password == null) { + return ResponseEntity.badRequest().body(Map.of("message", "Email and password are required")); + } + + String emailLower = email.trim().toLowerCase(); + Optional userOpt = userRepository.findByEmailIgnoreCase(emailLower); + + if (userOpt.isPresent()) { + User user = userOpt.get(); + if (password.equals(user.getPassword())) { + // Exclude password from return payload + Map userData = new HashMap<>(); + userData.put("id", user.getId()); + userData.put("email", user.getEmail()); + userData.put("fullName", user.getFullName()); + userData.put("role", user.getRole()); + userData.put("department", user.getDepartment() != null ? user.getDepartment() : "N/A"); + userData.put("isClubCoordinator", user.getIsClubCoordinator()); + userData.put("isPlacementStaff", user.getIsPlacementStaff()); + userData.put("isClassIncharge", user.getIsClassIncharge()); + userData.put("classStrength", user.getClassStrength()); + userData.put("inchargeClass", user.getInchargeClass()); + userData.put("inchargeBatch", user.getInchargeBatch()); + userData.put("inchargeSection", user.getInchargeSection()); + userData.put("year", user.getYear()); + userData.put("section", user.getSection()); + userData.put("regNo", user.getRegNo()); + userData.put("phone", user.getPhone()); + userData.put("gender", user.getGender()); + userData.put("collegeName", user.getCollegeName()); + userData.put("assignedClubs", user.getAssignedClubs() != null ? user.getAssignedClubs() : new ArrayList<>()); + return ResponseEntity.ok(userData); + } else { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid password for this registered email")); + } + } + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid email or passcode. Please check your credentials or register a new account.")); + } + + @PostMapping("/google-login") + public ResponseEntity googleLogin(@RequestBody Map payload) { + String email = payload.get("email"); + String fullName = payload.get("fullName"); + + if (email == null) { + return ResponseEntity.badRequest().body(Map.of("message", "Email is required")); + } + + String emailLower = email.trim().toLowerCase(); + Optional userOpt = userRepository.findByEmailIgnoreCase(emailLower); + + if (userOpt.isPresent()) { + User user = userOpt.get(); + Map userData = convertUserToMap(user); + return ResponseEntity.ok(userData); + } + + // Auto-registration logic for RIT students + boolean isRitEmail = emailLower.contains("@ritchennai.edu.in") || emailLower.contains(".ritchennai.edu.in"); + if (isRitEmail) { + String rollNo = ""; + String rawDept = "CSE"; + + // Try to match student patterns: student.240007@cse.ritchennai.edu.in + if (emailLower.startsWith("student.")) { + try { + String[] parts = emailLower.split("@"); + rollNo = parts[0].substring(8); // extracts "240007" + rawDept = parts[1].split("\\.")[0]; // cse + } catch (Exception e) { + rollNo = String.valueOf(100000 + new Random().nextInt(900000)); + } + } else { + rollNo = String.valueOf(100000 + new Random().nextInt(900000)); + } + + // Calculate joining year and academic year (current local time is 2026-06-30) + int joinYear = 2000 + Integer.parseInt(rollNo.substring(0, Math.min(rollNo.length(), 2))); + int currentYear = 2026; + int academicYearOffset = 1; // Since month is June (June is >= 5) + int yearIndex = currentYear - joinYear + academicYearOffset; + String[] years = {"1st Year", "2nd Year", "3rd Year", "4th Year"}; + String calculatedYear = (yearIndex >= 1 && yearIndex <= 4) ? years[yearIndex - 1] : "3rd Year"; + + // Map department + String dept = rawDept.toUpperCase(); + if (dept.equals("AIDS")) dept = "AI&DS"; + else if (dept.equals("AIML")) dept = "AI&ML"; + else if (dept.equals("VLSI")) dept = "EE(VLSI)"; + else if (dept.equals("BIOTECH") || dept.equals("BIO-TECH")) dept = "BIOTECH"; + else if (dept.equals("H&S")) dept = "H&S Dept"; + + User newUser = new User(); + newUser.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + newUser.setEmail(emailLower); + newUser.setPassword("google-oauth-placeholder"); + newUser.setFullName(fullName != null ? fullName : "Student " + rollNo); + newUser.setRole("STUDENT"); + newUser.setDepartment(dept); + newUser.setYear(calculatedYear); + newUser.setSection("A"); + newUser.setRegNo(rollNo); + newUser.setPhone(""); + newUser.setGender("Male"); + newUser.setCollegeName("Rajalakshmi Institute of Technology"); + newUser.setIsClubCoordinator(false); + newUser.setIsPlacementStaff(false); + newUser.setIsClassIncharge(false); + newUser.setAssignedClubs(new java.util.ArrayList<>()); + + userRepository.save(newUser); + return ResponseEntity.ok(convertUserToMap(newUser)); + } + + // Register external students automatically + User newUser = new User(); + newUser.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + newUser.setEmail(emailLower); + newUser.setPassword("google-oauth-placeholder"); + newUser.setFullName(fullName != null ? fullName : emailLower.split("@")[0]); + newUser.setRole("STUDENT"); + newUser.setDepartment("Others"); + newUser.setYear("N/A"); + newUser.setSection("N/A"); + newUser.setRegNo("EXT-" + (10000 + new Random().nextInt(90000))); + newUser.setPhone(""); + newUser.setGender("Male"); + newUser.setCollegeName("External Institution"); + newUser.setIsClubCoordinator(false); + newUser.setIsPlacementStaff(false); + newUser.setIsClassIncharge(false); + newUser.setAssignedClubs(new java.util.ArrayList<>()); + + userRepository.save(newUser); + return ResponseEntity.ok(convertUserToMap(newUser)); + } + + @PostMapping("/signup") + public ResponseEntity signup(@RequestBody Map payload) { + String email = (String) payload.get("email"); + if (email == null) { + return ResponseEntity.badRequest().body(Map.of("message", "Email is required")); + } + + String emailLower = email.trim().toLowerCase(); + if (userRepository.findByEmailIgnoreCase(emailLower).isPresent()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message", "A user with this email already exists")); + } + + User newUser = new User(); + newUser.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + newUser.setEmail(emailLower); + newUser.setPassword((String) payload.get("password")); + newUser.setFullName((String) payload.get("fullName")); + newUser.setRole("STUDENT"); + newUser.setDepartment(payload.get("department") != null ? (String) payload.get("department") : "CSE"); + newUser.setYear(payload.get("year") != null ? (String) payload.get("year") : "1st Year"); + newUser.setSection(payload.get("section") != null ? (String) payload.get("section") : "A"); + newUser.setRegNo((String) payload.get("regNo")); + newUser.setPhone((String) payload.get("phone")); + newUser.setGender(payload.get("gender") != null ? (String) payload.get("gender") : "Male"); + + boolean isRitEmail = emailLower.contains("@ritchennai.edu.in") || emailLower.contains(".ritchennai.edu.in"); + newUser.setCollegeName(isRitEmail ? "Rajalakshmi Institute of Technology" : (String) payload.get("collegeName")); + + userRepository.save(newUser); + return ResponseEntity.ok(convertUserToMap(newUser)); + } + + private Map convertUserToMap(User user) { + Map userData = new HashMap<>(); + userData.put("id", user.getId()); + userData.put("email", user.getEmail()); + userData.put("fullName", user.getFullName()); + userData.put("role", user.getRole()); + userData.put("department", user.getDepartment() != null ? user.getDepartment() : "N/A"); + userData.put("isClubCoordinator", user.getIsClubCoordinator()); + userData.put("isPlacementStaff", user.getIsPlacementStaff()); + userData.put("isClassIncharge", user.getIsClassIncharge()); + userData.put("classStrength", user.getClassStrength()); + userData.put("inchargeClass", user.getInchargeClass()); + userData.put("inchargeBatch", user.getInchargeBatch()); + userData.put("inchargeSection", user.getInchargeSection()); + userData.put("year", user.getYear()); + userData.put("section", user.getSection()); + userData.put("regNo", user.getRegNo()); + userData.put("phone", user.getPhone()); + userData.put("gender", user.getGender()); + userData.put("collegeName", user.getCollegeName()); + userData.put("assignedClubs", user.getAssignedClubs() != null ? user.getAssignedClubs() : new ArrayList<>()); + return userData; + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/BatchController.java b/backend/src/main/java/com/rit/ems/controller/BatchController.java new file mode 100644 index 0000000..c8e587f --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/BatchController.java @@ -0,0 +1,42 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Batch; +import com.rit.ems.repository.BatchRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RestController +@RequestMapping("/api/batches") +public class BatchController { + + @Autowired + private BatchRepository batchRepository; + + @GetMapping + public List getAllBatches() { + return batchRepository.findAll(); + } + + @PostMapping + public ResponseEntity createBatch(@RequestBody Batch batch) { + if (batch.getId() == null) { + batch.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + } + if (batch.getClasses() == null) { + batch.setClasses(new java.util.ArrayList<>()); + } + batchRepository.save(batch); + return ResponseEntity.ok(batch); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteBatch(@PathVariable Long id) { + batchRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Batch deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/ClassController.java b/backend/src/main/java/com/rit/ems/controller/ClassController.java new file mode 100644 index 0000000..e76c842 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/ClassController.java @@ -0,0 +1,69 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.ClassMapping; +import com.rit.ems.repository.ClassMappingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RestController +@RequestMapping("/api/classes") +public class ClassController { + + @Autowired + private ClassMappingRepository classMappingRepository; + + @GetMapping + public List getAllClasses() { + return classMappingRepository.findAll(); + } + + @PostMapping + public ResponseEntity createClass(@RequestBody ClassMapping classMapping) { + if (classMapping.getId() == null) { + classMapping.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + } + if (classMapping.getStatus() == null) { + classMapping.setStatus("Ready"); + } + classMappingRepository.save(classMapping); + return ResponseEntity.ok(classMapping); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteClass(@PathVariable Long id) { + classMappingRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Class mapping deleted successfully")); + } + + @PostMapping("/promote") + public ResponseEntity promoteClasses(@RequestParam String institution) { + List classes = classMappingRepository.findAll(); + for (ClassMapping cm : classes) { + if (cm.getInstitution() != null && cm.getInstitution().trim().equalsIgnoreCase(institution.trim())) { + switch (cm.getAcademicYear()) { + case "1st Year": + cm.setAcademicYear("2nd Year"); + classMappingRepository.save(cm); + break; + case "2nd Year": + cm.setAcademicYear("3rd Year"); + classMappingRepository.save(cm); + break; + case "3rd Year": + cm.setAcademicYear("4th Year"); + classMappingRepository.save(cm); + break; + case "4th Year": + classMappingRepository.delete(cm); + break; + } + } + } + return ResponseEntity.ok(Map.of("message", "Academic year promotion completed for " + institution)); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/EventController.java b/backend/src/main/java/com/rit/ems/controller/EventController.java new file mode 100644 index 0000000..96e2bff --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/EventController.java @@ -0,0 +1,544 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Event; +import com.rit.ems.model.Registration; +import com.rit.ems.model.User; +import com.rit.ems.repository.EventRepository; +import com.rit.ems.repository.RegistrationRepository; +import com.rit.ems.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.*; + +@RestController +@RequestMapping("/api/events") +public class EventController { + + @Autowired + private EventRepository eventRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private RegistrationRepository registrationRepository; + + @GetMapping + public List getAllEvents() { + List events = eventRepository.findAll(); + List regs = registrationRepository.findAll(); + + for (Event event : events) { + int count = (int) regs.stream() + .filter(r -> r.getEventId() != null && r.getEventId().equals(event.getId())) + .count(); + event.setCurrentParticipants(count); + + // Re-populate conflict messages if needed + if (!Arrays.asList("APPROVED", "COMPLETED", "CANCELLED").contains(event.getStatus())) { + String conflictMsg = getConflictMessage(event, event.getId()); + if (conflictMsg != null) { + event.setConflictMessage(conflictMsg); + } + } + } + return events; + } + + @PostMapping("/propose") + public ResponseEntity proposeEvent(@RequestBody Map payload) { + Object userIdObj = payload.get("userId"); + if (userIdObj == null) { + return ResponseEntity.badRequest().body(Map.of("message", "userId is required")); + } + + Long userId = Long.parseLong(userIdObj.toString()); + Optional userOpt = userRepository.findById(userId); + if (userOpt.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("message", "Proposer user not found")); + } + + User proposer = userOpt.get(); + String startDateStr = (String) payload.get("startDate"); + String endDateStr = (String) payload.get("endDate"); + + Instant start = parseDate(startDateStr); + Instant end = parseDate(endDateStr); + + if (start.isBefore(Instant.now())) { + return ResponseEntity.badRequest().body(Map.of("message", "Cannot schedule events in the past")); + } + if (end.isBefore(start) || end.equals(start)) { + return ResponseEntity.badRequest().body(Map.of("message", "End date must be after start date")); + } + + // Temporarily build target Event object to check conflicts + Event tempEvent = new Event(); + tempEvent.setStartDate(startDateStr); + tempEvent.setEndDate(endDateStr); + tempEvent.setLocation((String) payload.get("venue")); + tempEvent.setInstitution((String) payload.get("institution")); + tempEvent.setGroupRequestId((String) payload.get("groupRequestId")); + + String conflictMsg = getConflictMessage(tempEvent, null); + if (conflictMsg != null) { + String category = (String) payload.get("category"); + Boolean cancelConflicting = (Boolean) payload.get("cancelConflicting"); + + if ("PLACEMENT".equals(category) && Boolean.TRUE.equals(cancelConflicting)) { + // Cancel conflicting events + List allEvents = eventRepository.findAll(); + String location = tempEvent.getLocation().trim(); + String inst = tempEvent.getInstitution() != null ? tempEvent.getInstitution().trim() : "RIT"; + + for (Event other : allEvents) { + if ("CANCELLED".equals(other.getStatus())) continue; + if (tempEvent.getGroupRequestId() != null && tempEvent.getGroupRequestId().equals(other.getGroupRequestId())) continue; + + Instant oStart = parseDate(other.getStartDate()); + Instant oEnd = parseDate(other.getEndDate()); + String oLoc = other.getLocation() != null ? other.getLocation().trim() : ""; + String oInst = other.getInstitution() != null ? other.getInstitution().trim() : "RIT"; + + if (oInst.equalsIgnoreCase(inst) && oLoc.equalsIgnoreCase(location) && start.isBefore(oEnd) && end.isAfter(oStart)) { + other.setStatus("CANCELLED"); + other.setRejectionReason("This event is cancelled due to the placement activity happening at the venue at this timing."); + eventRepository.save(other); + } + } + } else { + // Return conflicts list + List conflicts = new ArrayList<>(); + List allEvents = eventRepository.findAll(); + String location = tempEvent.getLocation().trim(); + String inst = tempEvent.getInstitution() != null ? tempEvent.getInstitution().trim() : "RIT"; + + for (Event other : allEvents) { + if ("CANCELLED".equals(other.getStatus())) continue; + Instant oStart = parseDate(other.getStartDate()); + Instant oEnd = parseDate(other.getEndDate()); + String oLoc = other.getLocation() != null ? other.getLocation().trim() : ""; + String oInst = other.getInstitution() != null ? other.getInstitution().trim() : "RIT"; + + if (oInst.equalsIgnoreCase(inst) && oLoc.equalsIgnoreCase(location) && start.isBefore(oEnd) && end.isAfter(oStart)) { + conflicts.add(other); + } + } + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of( + "message", conflictMsg, + "conflicts", conflicts, + "canOverride", "PLACEMENT".equals(category) + )); + } + } + + // Propose logic status + String status = "REQUESTED"; + if ("PRINCIPAL".equals(proposer.getRole())) { + status = "APPROVED"; + } else if ("HOD".equals(proposer.getRole()) || + "CLUB".equals(payload.get("category")) || + "PLACEMENT".equals(payload.get("category")) || + "INSTITUTIONAL".equals(payload.get("category")) || + "PLACEMENT".equals(proposer.getRole()) || + Boolean.TRUE.equals(proposer.getIsPlacementStaff()) || + "Placement Department".equals(proposer.getDepartment())) { + status = "PENDING_PR"; + } + + Event event = new Event(); + event.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + event.setTitle((String) payload.get("eventName")); + event.setDescription((String) payload.get("description")); + event.setStartDate(start.toString()); + event.setEndDate(end.toString()); + event.setLocation((String) payload.get("venue")); + event.setCategory((String) payload.get("category")); + event.setType((String) payload.get("eventType")); + event.setInstitution((String) payload.get("institution")); + event.setDepartment((String) payload.get("department")); + event.setAcademicYears((List) payload.get("academicYears")); + event.setStatus(status); + event.setGuestName((String) payload.get("guestName")); + event.setGuestSocialProfile((String) payload.get("socialProfile")); + event.setRequirements((List) payload.get("requirements")); + event.setTargetedSections((List) payload.get("targetedSections")); + event.setTargetDepartments((List) payload.get("targetDepartments")); + event.setGroupRequestId((String) payload.get("groupRequestId")); + event.setSponsors((List) payload.get("sponsors")); + + event.setBudget(payload.get("budget") != null ? Double.parseDouble(payload.get("budget").toString()) : 0.0); + event.setHasRegistrationFee(Boolean.TRUE.equals(payload.get("hasRegistrationFee"))); + event.setRegistrationFee(payload.get("registrationFee") != null ? Double.parseDouble(payload.get("registrationFee").toString()) : 0.0); + event.setPaymentLink((String) payload.get("paymentLink")); + event.setCentreName((String) payload.get("centreName")); + event.setIsPublicEvent(Boolean.TRUE.equals(payload.get("isPublicEvent"))); + event.setImage((String) payload.get("image")); + event.setTargetedBatch((String) payload.get("targetedBatch")); + event.setOpenToAll(Boolean.TRUE.equals(payload.get("openToAll"))); + + Integer maxParticipants = payload.get("maxParticipants") != null && !payload.get("maxParticipants").toString().isEmpty() + ? Integer.parseInt(payload.get("maxParticipants").toString()) : null; + event.setMaxParticipants(maxParticipants); + + Event.ProposerInfo proposerInfo = new Event.ProposerInfo( + proposer.getId(), + proposer.getFullName(), + proposer.getEmail(), + proposer.getRole(), + proposer.getDepartment() + ); + event.setProposer(proposerInfo); + + event.setDayConfigs((List) payload.get("dayConfigs")); + event.setDeptLimits((Map) payload.get("deptLimits")); + event.setDeptSectionLimits((Map) payload.get("deptSectionLimits")); + + event.setRefreshmentExpense(payload.get("refreshment_expense") != null ? Double.parseDouble(payload.get("refreshment_expense").toString()) : 0.0); + event.setTransportationExpense(payload.get("transportation_expense") != null ? Double.parseDouble(payload.get("transportation_expense").toString()) : 0.0); + event.setSessionCoverageFee(payload.get("session_coverage_fee") != null ? Double.parseDouble(payload.get("session_coverage_fee").toString()) : 0.0); + event.setTotalExpense(payload.get("total_expense") != null ? Double.parseDouble(payload.get("total_expense").toString()) : 0.0); + event.setDurationDays(payload.get("durationDays") != null ? Integer.parseInt(payload.get("durationDays").toString()) : 1); + + eventRepository.save(event); + return ResponseEntity.ok(Map.of("message", "Event proposed successfully", "id", event.getId())); + } + + @PostMapping("/batch-create") + public ResponseEntity batchCreateEvents(@RequestBody List> batchList) { + List eventsToSave = new ArrayList<>(); + + for (Map payload : batchList) { + String title = (String) payload.get("title"); + String dateObj = payload.containsKey("startDate") ? (String) payload.get("startDate") : (String) payload.get("finalDate"); + if (dateObj == null) { + return ResponseEntity.badRequest().body(Map.of("message", "Missing date for event: " + title)); + } + + Instant start = parseDate(dateObj); + Instant end; + if (payload.containsKey("startDate") && payload.containsKey("endDate")) { + try { + Instant origStart = parseDate((String) payload.get("startDate")); + Instant origEnd = parseDate((String) payload.get("endDate")); + long durationMs = origEnd.toEpochMilli() - origStart.toEpochMilli(); + end = Instant.ofEpochMilli(start.toEpochMilli() + durationMs); + } catch (Exception e) { + end = Instant.ofEpochMilli(start.toEpochMilli() + 2 * 60 * 60 * 1000); + } + } else { + end = Instant.ofEpochMilli(start.toEpochMilli() + 2 * 60 * 60 * 1000); + } + + if (end.isBefore(start) || end.equals(start)) { + return ResponseEntity.badRequest().body(Map.of("message", "End date must be after start date for event: " + title)); + } + + String dept = payload.containsKey("targetDepartment") ? (String) payload.get("targetDepartment") : + (payload.containsKey("department") ? (String) payload.get("department") : "General"); + List ay = payload.containsKey("targetBatch") ? Collections.singletonList((String) payload.get("targetBatch")) : + (List) payload.get("academicYears"); + String venue = payload.containsKey("venue") ? (String) payload.get("venue") : + (payload.containsKey("location") ? (String) payload.get("location") : "TBD"); + + Event.ProposerInfo proposer = new Event.ProposerInfo(1L, "Admin", "admin@rit.edu", "ADMIN", "ADMIN"); + + Event event = new Event(); + event.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + event.setTitle(title); + event.setDescription((String) payload.get("description")); + event.setStartDate(start.toString()); + event.setEndDate(end.toString()); + event.setLocation(venue.trim()); + event.setCategory((String) payload.get("category")); + event.setType((String) payload.get("type")); + event.setInstitution((String) payload.get("institution")); + event.setDepartment(dept); + event.setAcademicYears(ay); + event.setStatus(payload.containsKey("status") ? (String) payload.get("status") : "APPROVED"); + event.setRequirements((List) payload.get("requirements")); + event.setImage((String) payload.get("image")); + event.setProposer(proposer); + event.setOpenToAll(Boolean.TRUE.equals(payload.get("openToAll"))); + + String conflictMsg = getConflictMessage(event, null); + if (conflictMsg != null) { + return ResponseEntity.badRequest().body(Map.of("message", String.format("Conflict in batch item '%s': %s", title, conflictMsg))); + } + eventsToSave.add(event); + } + + // Check intra-batch conflicts + for (int i = 0; i < eventsToSave.size(); i++) { + Event current = eventsToSave.get(i); + Instant currentStart = parseDate(current.getStartDate()); + Instant currentEnd = parseDate(current.getEndDate()); + String currentLoc = current.getLocation().toLowerCase(); + + for (int j = i + 1; j < eventsToSave.size(); j++) { + Event other = eventsToSave.get(j); + Instant otherStart = parseDate(other.getStartDate()); + Instant otherEnd = parseDate(other.getEndDate()); + String otherLoc = other.getLocation().toLowerCase(); + + if (current.getInstitution().equalsIgnoreCase(other.getInstitution()) && + currentLoc.equals(otherLoc) && + currentStart.isBefore(otherEnd) && + currentEnd.isAfter(otherStart)) { + return ResponseEntity.badRequest().body(Map.of("message", String.format("Conflict between imported events '%s' and '%s' at %s", + current.getTitle(), other.getTitle(), current.getLocation()))); + } + } + } + + eventRepository.saveAll(eventsToSave); + return ResponseEntity.ok(Map.of("message", "Batch events created successfully", "count", eventsToSave.size())); + } + + @PostMapping("/{id}/approve") + public ResponseEntity approveEvent(@PathVariable Long id, + @RequestParam Long userId, + @RequestParam(required = false) String newVenue) { + Optional userOpt = userRepository.findById(userId); + Optional eventOpt = eventRepository.findById(id); + + if (userOpt.isEmpty() || eventOpt.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("message", "User or Event not found")); + } + + User user = userOpt.get(); + Event event = eventOpt.get(); + + if (newVenue != null) { + event.setLocation(newVenue); + } + + String conflictMsg = getConflictMessage(event, id); + if (conflictMsg != null) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", conflictMsg)); + } + + String newStatus = event.getStatus(); + if ("HOD".equals(user.getRole())) { + newStatus = "PENDING_PR"; + } else if ("PRINCIPAL".equals(user.getRole())) { + newStatus = "APPROVED"; + } else { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "Only HoD or Principal can approve events")); + } + + event.setStatus(newStatus); + eventRepository.save(event); + return ResponseEntity.ok(Map.of("message", "Event action completed successfully", "status", newStatus)); + } + + @PostMapping("/{id}/reject") + public ResponseEntity rejectEvent(@PathVariable Long id, + @RequestParam Long userId, + @RequestBody Map body) { + String reason = body.get("reason"); + if (reason == null || reason.trim().isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("message", "Rejection reason is mandatory")); + } + + Optional userOpt = userRepository.findById(userId); + Optional eventOpt = eventRepository.findById(id); + + if (userOpt.isEmpty() || eventOpt.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("message", "User or Event not found")); + } + + User user = userOpt.get(); + Event event = eventOpt.get(); + String newStatus = event.getStatus(); + + if ("HOD".equals(user.getRole())) { + newStatus = "HOD_REJECTED"; + } else if ("PRINCIPAL".equals(user.getRole())) { + newStatus = "PRINCIPAL_REJECTED"; + } else { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "Only HoD or Principal can reject events")); + } + + event.setStatus(newStatus); + event.setRejectionReason(reason); + eventRepository.save(event); + return ResponseEntity.ok(Map.of("message", "Event rejected successfully", "status", newStatus)); + } + + @PutMapping("/{id}") + public ResponseEntity updateEvent(@PathVariable Long id, @RequestBody Map payload) { + Optional eventOpt = eventRepository.findById(id); + if (eventOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("message", "Event not found")); + } + + Event event = eventOpt.get(); + Object userIdObj = payload.get("userId"); + if (userIdObj == null) { + return ResponseEntity.badRequest().body(Map.of("message", "User ID is required to update event")); + } + + Long userId = Long.parseLong(userIdObj.toString()); + Optional userOpt = userRepository.findById(userId); + if (userOpt.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("message", "User not found")); + } + + User user = userOpt.get(); + boolean isAdmin = "ADMIN".equals(user.getRole()); + + if (!isAdmin) { + if (event.getProposer() == null || !event.getProposer().getId().equals(userId)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "Only the proposer can edit this event")); + } + if (!"REQUESTED".equals(event.getStatus())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "Event cannot be edited once it moves past the initial request stage")); + } + } + + String startStr = payload.containsKey("startDate") ? (String) payload.get("startDate") : event.getStartDate(); + String endStr = payload.containsKey("endDate") ? (String) payload.get("endDate") : event.getEndDate(); + + Instant start = parseDate(startStr); + Instant end = parseDate(endStr); + + if (end.isBefore(start) || end.equals(start)) { + return ResponseEntity.badRequest().body(Map.of("message", "End date must be after start date")); + } + + // Apply fields selectively + if (payload.containsKey("title")) event.setTitle((String) payload.get("title")); + event.setStartDate(start.toString()); + event.setEndDate(end.toString()); + if (payload.containsKey("eventType")) event.setType((String) payload.get("eventType")); + if (payload.containsKey("institution")) event.setInstitution((String) payload.get("institution")); + if (payload.containsKey("department")) event.setDepartment((String) payload.get("department")); + if (payload.containsKey("venue")) event.setLocation((String) payload.get("venue")); + if (payload.containsKey("category")) event.setCategory((String) payload.get("category")); + + if (payload.containsKey("maxParticipants")) { + String val = payload.get("maxParticipants").toString(); + event.setMaxParticipants(val.isEmpty() ? null : Integer.parseInt(val)); + } + + if (payload.containsKey("guestName")) event.setGuestName((String) payload.get("guestName")); + if (payload.containsKey("socialProfile")) event.setGuestSocialProfile((String) payload.get("socialProfile")); + if (payload.containsKey("academicYears")) event.setAcademicYears((List) payload.get("academicYears")); + if (payload.containsKey("targetedSections")) event.setTargetedSections((List) payload.get("targetedSections")); + if (payload.containsKey("requirements")) event.setRequirements((List) payload.get("requirements")); + if (payload.containsKey("sponsors")) event.setSponsors((List) payload.get("sponsors")); + if (payload.containsKey("description")) event.setDescription((String) payload.get("description")); + + if (payload.containsKey("budget")) { + String b = payload.get("budget").toString(); + event.setBudget(b.isEmpty() ? 0.0 : Double.parseDouble(b)); + } + if (payload.containsKey("hasRegistrationFee")) { + event.setHasRegistrationFee((Boolean) payload.get("hasRegistrationFee")); + } + if (payload.containsKey("registrationFee")) { + String f = payload.get("registrationFee").toString(); + event.setRegistrationFee(f.isEmpty() ? 0.0 : Double.parseDouble(f)); + } + + if (payload.containsKey("centreName")) event.setCentreName((String) payload.get("centreName")); + if (payload.containsKey("isPublicEvent")) event.setIsPublicEvent((Boolean) payload.get("isPublicEvent")); + if (payload.containsKey("image")) event.setImage((String) payload.get("image")); + if (payload.containsKey("openToAll")) event.setOpenToAll((Boolean) payload.get("openToAll")); + if (payload.containsKey("targetedBatch")) event.setTargetedBatch((String) payload.get("targetedBatch")); + if (payload.containsKey("dayConfigs")) event.setDayConfigs((List) payload.get("dayConfigs")); + if (payload.containsKey("deptLimits")) event.setDeptLimits((Map) payload.get("deptLimits")); + if (payload.containsKey("deptSectionLimits")) event.setDeptSectionLimits((Map) payload.get("deptSectionLimits")); + + if (payload.containsKey("refreshment_expense")) event.setRefreshmentExpense(Double.parseDouble(payload.get("refreshment_expense").toString())); + if (payload.containsKey("transportation_expense")) event.setTransportationExpense(Double.parseDouble(payload.get("transportation_expense").toString())); + if (payload.containsKey("session_coverage_fee")) event.setSessionCoverageFee(Double.parseDouble(payload.get("session_coverage_fee").toString())); + if (payload.containsKey("total_expense")) event.setTotalExpense(Double.parseDouble(payload.get("total_expense").toString())); + if (payload.containsKey("durationDays")) event.setDurationDays(Integer.parseInt(payload.get("durationDays").toString())); + + if (payload.containsKey("status") && isAdmin) { + event.setStatus((String) payload.get("status")); + } + + String conflictMsg = getConflictMessage(event, id); + if (conflictMsg != null) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", conflictMsg)); + } + + eventRepository.save(event); + return ResponseEntity.ok(Map.of("message", "Event updated successfully")); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteEvent(@PathVariable Long id) { + eventRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Event deleted successfully")); + } + + private Instant parseDate(String val) { + if (val == null || val.trim().isEmpty()) { + return Instant.now(); + } + String clean = val.trim().replace(" ", "T"); + if (clean.length() == 10) { + clean += "T00:00:00"; + } + if (clean.length() == 16) { + clean += ":00"; + } + if (!clean.contains("Z") && !clean.contains("+") && !clean.contains("-")) { + clean += "Z"; + } + try { + return Instant.parse(clean); + } catch (Exception e) { + try { + return java.time.LocalDateTime.parse(clean.substring(0, 19)) + .toInstant(java.time.ZoneOffset.UTC); + } catch (Exception ex) { + return Instant.now(); + } + } + } + + private String getConflictMessage(Event event, Long ignoreId) { + if (event.getLocation() == null || event.getStartDate() == null || event.getEndDate() == null) { + return null; + } + String location = event.getLocation().trim(); + String institution = event.getInstitution() != null ? event.getInstitution().trim() : "RIT"; + Instant start = parseDate(event.getStartDate()); + Instant end = parseDate(event.getEndDate()); + + List existingEvents = eventRepository.findAll(); + for (Event other : existingEvents) { + if ("CANCELLED".equals(other.getStatus())) continue; + if (ignoreId != null && other.getId().equals(ignoreId)) continue; + if (event.getId() != null && other.getId().equals(event.getId())) continue; + if (event.getGroupRequestId() != null && event.getGroupRequestId().equals(other.getGroupRequestId())) continue; + + Instant oStart = parseDate(other.getStartDate()); + Instant oEnd = parseDate(other.getEndDate()); + String oLoc = other.getLocation() != null ? other.getLocation().trim() : ""; + String oInst = other.getInstitution() != null ? other.getInstitution().trim() : "RIT"; + + if (oInst.equalsIgnoreCase(institution) && + oLoc.equalsIgnoreCase(location) && + start.isBefore(oEnd) && + end.isAfter(oStart)) { + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm") + .withZone(java.time.ZoneOffset.UTC); + return String.format("Venue Conflict: '%s' is already booked for '%s' from %s to %s", + location, other.getTitle(), formatter.format(oStart), formatter.format(oEnd)); + } + } + return null; + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/InstitutionalEventController.java b/backend/src/main/java/com/rit/ems/controller/InstitutionalEventController.java new file mode 100644 index 0000000..966cbf9 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/InstitutionalEventController.java @@ -0,0 +1,38 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.InstitutionalEvent; +import com.rit.ems.repository.InstitutionalEventRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/institutional-events") +public class InstitutionalEventController { + + @Autowired + private InstitutionalEventRepository institutionalEventRepository; + + @GetMapping + public List getAllEvents() { + return institutionalEventRepository.findAll(); + } + + @PostMapping + public ResponseEntity createEvent(@RequestBody InstitutionalEvent event) { + if (event.getId() == null) { + event.setId("ie-" + System.currentTimeMillis()); + } + institutionalEventRepository.save(event); + return ResponseEntity.ok(event); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteEvent(@PathVariable String id) { + institutionalEventRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Institutional event deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/NoteController.java b/backend/src/main/java/com/rit/ems/controller/NoteController.java new file mode 100644 index 0000000..0334043 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/NoteController.java @@ -0,0 +1,40 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Note; +import com.rit.ems.repository.NoteRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.Instant; +import java.util.List; +import java.util.Random; + +@RestController +@RequestMapping("/api/notes") +public class NoteController { + + @Autowired + private NoteRepository noteRepository; + + @GetMapping + public List getAllNotes() { + List list = noteRepository.findAll(); + list.sort((a, b) -> { + String ca = a.getCreatedAt() != null ? a.getCreatedAt() : ""; + String cb = b.getCreatedAt() != null ? b.getCreatedAt() : ""; + return cb.compareTo(ca); // Descending order + }); + return list; + } + + @PostMapping + public ResponseEntity createNote(@RequestBody Note note) { + if (note.getId() == null) { + note.setId(System.currentTimeMillis() + new Random().nextInt(1000)); + } + note.setCreatedAt(Instant.now().toString()); + noteRepository.save(note); + return ResponseEntity.ok(note); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/RegistrationController.java b/backend/src/main/java/com/rit/ems/controller/RegistrationController.java new file mode 100644 index 0000000..7db0257 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/RegistrationController.java @@ -0,0 +1,211 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Event; +import com.rit.ems.model.Registration; +import com.rit.ems.repository.EventRepository; +import com.rit.ems.repository.RegistrationRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@RestController +@RequestMapping("/api/registrations") +public class RegistrationController { + + @Autowired + private RegistrationRepository registrationRepository; + + @Autowired + private EventRepository eventRepository; + + @GetMapping + public List getRegistrations(@RequestParam(required = false) Long userId, + @RequestParam(required = false) Long eventId, + @RequestParam(required = false) String teamCode) { + if (userId != null) { + return registrationRepository.findByUserId(userId); + } + if (eventId != null) { + return registrationRepository.findByEventId(eventId); + } + if (teamCode != null) { + return registrationRepository.findByTeamCode(teamCode); + } + return registrationRepository.findAll(); + } + + @PostMapping + public ResponseEntity createRegistration(@RequestBody Registration payload) { + Long userId = payload.getUserId(); + Long eventId = payload.getEventId(); + + if (userId == null || eventId == null) { + return ResponseEntity.badRequest().body(Map.of("message", "userId and eventId are required")); + } + + String regId = userId + "_" + eventId; + Optional existing = registrationRepository.findById(regId); + if (existing.isPresent()) { + return ResponseEntity.badRequest().body(Map.of("message", "You are already registered for this event.")); + } + + Optional eventOpt = eventRepository.findById(eventId); + if (eventOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("message", "Event not found")); + } + Event event = eventOpt.get(); + + if (event.getEndDate() != null) { + // Check deadline + Instant deadline = parseDate(event.getEndDate()); + if (Instant.now().isAfter(deadline)) { + return ResponseEntity.badRequest().body(Map.of("message", "Registration Blocked: The deadline for this event has passed.")); + } + } + + List eventRegs = registrationRepository.findByEventId(eventId); + int currentParticipants = eventRegs.size(); + + if (event.getMaxParticipants() != null && currentParticipants >= event.getMaxParticipants()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: The event has reached its capacity.")); + } + + String studentDept = payload.getDept() != null ? payload.getDept() : (payload.getDepartment() != null ? payload.getDepartment() : "CSE"); + String studentSec = payload.getSection() != null ? payload.getSection() : "A"; + + if (event.getDeptLimits() != null && !event.getDeptLimits().isEmpty()) { + if (!event.getDeptLimits().containsKey(studentDept)) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: Department " + studentDept + " is not permitted to register.")); + } + + int deptLimit = Integer.parseInt(event.getDeptLimits().get(studentDept).toString()); + long deptRegsCount = eventRegs.stream().filter(r -> studentDept.equals(r.getDept()) || studentDept.equals(r.getDepartment())).count(); + + if (event.getDeptSectionLimits() != null && event.getDeptSectionLimits().containsKey(studentDept)) { + Map sectionLimits = (Map) event.getDeptSectionLimits().get(studentDept); + if (!sectionLimits.containsKey(studentSec)) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: Section " + studentSec + " of " + studentDept + " is not permitted to register.")); + } + int sectionLimit = Integer.parseInt(sectionLimits.get(studentSec).toString()); + if (sectionLimit <= 0) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: Section " + studentSec + " of " + studentDept + " is not permitted to register.")); + } + + long secRegsCount = eventRegs.stream().filter(r -> (studentDept.equals(r.getDept()) || studentDept.equals(r.getDepartment())) && studentSec.equals(r.getSection())).count(); + if (secRegsCount >= sectionLimit) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: Quota for Section " + studentSec + " of " + studentDept + " is full.")); + } + } else { + if (deptRegsCount >= deptLimit) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Registration Blocked: Quota for department " + studentDept + " is full.")); + } + } + } + + boolean isFree = event.getHasRegistrationFee() == null || !event.getHasRegistrationFee() || event.getRegistrationFee() == 0; + payload.setId(regId); + payload.setPaymentStatus(isFree ? "COMPLETED" : "PENDING"); + payload.setCertificationStatus("NOT_SUBMITTED"); + payload.setRegisteredAt(Instant.now().toString()); + + registrationRepository.save(payload); + + event.setCurrentParticipants(currentParticipants + 1); + eventRepository.save(event); + + return ResponseEntity.ok(payload); + } + + @PutMapping("/{id}") + public ResponseEntity updateRegistration(@PathVariable String id, @RequestBody Map payload) { + Optional regOpt = registrationRepository.findById(id); + if (regOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("message", "Registration not found")); + } + + Registration reg = regOpt.get(); + + if (payload.containsKey("payment_status")) reg.setPaymentStatus((String) payload.get("payment_status")); + if (payload.containsKey("paymentStatus")) reg.setPaymentStatus((String) payload.get("paymentStatus")); + + if (payload.containsKey("team_code")) reg.setTeamCode((String) payload.get("team_code")); + if (payload.containsKey("teamCode")) reg.setTeamCode((String) payload.get("teamCode")); + + if (payload.containsKey("team_name")) reg.setTeamName((String) payload.get("team_name")); + if (payload.containsKey("teamName")) reg.setTeamName((String) payload.get("teamName")); + + if (payload.containsKey("is_team_leader")) reg.setIsTeamLeader((Boolean) payload.get("is_team_leader")); + if (payload.containsKey("isTeamLeader")) reg.setIsTeamLeader((Boolean) payload.get("isTeamLeader")); + + if (payload.containsKey("certification_url")) reg.setCertificationUrl((String) payload.get("certification_url")); + if (payload.containsKey("certificationUrl")) reg.setCertificationUrl((String) payload.get("certificationUrl")); + + if (payload.containsKey("certification_status")) reg.setCertificationStatus((String) payload.get("certification_status")); + if (payload.containsKey("certificationStatus")) reg.setCertificationStatus((String) payload.get("certificationStatus")); + + if (payload.containsKey("od_url")) reg.setOdUrl((String) payload.get("od_url")); + if (payload.containsKey("odUrl")) reg.setOdUrl((String) payload.get("odUrl")); + + if (payload.containsKey("ticket_id")) reg.setTicketId((String) payload.get("ticket_id")); + if (payload.containsKey("ticketId")) reg.setTicketId((String) payload.get("ticketId")); + + if (payload.containsKey("ticket_qrcode")) reg.setTicketQrcode((String) payload.get("ticket_qrcode")); + if (payload.containsKey("ticketQrcode")) reg.setTicketQrcode((String) payload.get("ticketQrcode")); + + registrationRepository.save(reg); + return ResponseEntity.ok(Map.of("message", "Registration updated successfully", "data", reg)); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteRegistration(@PathVariable String id) { + Optional regOpt = registrationRepository.findById(id); + if (regOpt.isPresent()) { + Registration reg = regOpt.get(); + Long eventId = reg.getEventId(); + registrationRepository.delete(reg); + + if (eventId != null) { + Optional eventOpt = eventRepository.findById(eventId); + if (eventOpt.isPresent()) { + Event event = eventOpt.get(); + int count = registrationRepository.findByEventId(eventId).size(); + event.setCurrentParticipants(count); + eventRepository.save(event); + } + } + } + return ResponseEntity.ok(Map.of("message", "Registration deleted successfully")); + } + + private Instant parseDate(String val) { + if (val == null || val.trim().isEmpty()) { + return Instant.now(); + } + String clean = val.trim().replace(" ", "T"); + if (clean.length() == 10) { + clean += "T00:00:00"; + } + if (clean.length() == 16) { + clean += ":00"; + } + if (!clean.contains("Z") && !clean.contains("+") && !clean.contains("-")) { + clean += "Z"; + } + try { + return Instant.parse(clean); + } catch (Exception e) { + try { + return java.time.LocalDateTime.parse(clean.substring(0, 19)) + .toInstant(java.time.ZoneOffset.UTC); + } catch (Exception ex) { + return Instant.now(); + } + } + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/SettingController.java b/backend/src/main/java/com/rit/ems/controller/SettingController.java new file mode 100644 index 0000000..50e241e --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/SettingController.java @@ -0,0 +1,40 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Setting; +import com.rit.ems.repository.SettingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/settings") +public class SettingController { + + @Autowired + private SettingRepository settingRepository; + + @GetMapping + public Map getSettings() { + List list = settingRepository.findAll(); + Map settings = new HashMap<>(); + for (Setting s : list) { + settings.put(s.getId(), s.getValue()); + } + return settings; + } + + @PostMapping + public ResponseEntity saveSetting(@RequestBody Map payload) { + String key = (String) payload.get("key"); + Object value = payload.get("value"); + if (key != null) { + Setting setting = new Setting(key, value); + settingRepository.save(setting); + } + return ResponseEntity.ok(Map.of("message", "Settings saved successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/SpecialEventController.java b/backend/src/main/java/com/rit/ems/controller/SpecialEventController.java new file mode 100644 index 0000000..bc9e2da --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/SpecialEventController.java @@ -0,0 +1,55 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.SpecialEvent; +import com.rit.ems.repository.SpecialEventRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RestController +@RequestMapping("/api/special-events") +public class SpecialEventController { + + @Autowired + private SpecialEventRepository specialEventRepository; + + @GetMapping + public List getAllSpecialEvents() { + List list = specialEventRepository.findAll(); + list.sort((a, b) -> { + String ca = a.getCreatedAt() != null ? a.getCreatedAt() : ""; + String cb = b.getCreatedAt() != null ? b.getCreatedAt() : ""; + return cb.compareTo(ca); // Descending order + }); + return list; + } + + @PostMapping + public ResponseEntity createSpecialEvent(@RequestBody SpecialEvent se) { + if (se.getId() == null) { + se.setId(String.valueOf(System.currentTimeMillis() + new Random().nextInt(1000))); + } + if (se.getCreatedAt() == null) { + se.setCreatedAt(Instant.now().toString()); + } + if (se.getIsActive() == null) { + se.setIsActive(true); + } + if (se.getVerificationStatus() == null) { + se.setVerificationStatus("APPROVED"); + } + specialEventRepository.save(se); + return ResponseEntity.ok(se); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteSpecialEvent(@PathVariable String id) { + specialEventRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Special event deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/controller/VenueController.java b/backend/src/main/java/com/rit/ems/controller/VenueController.java new file mode 100644 index 0000000..4133dba --- /dev/null +++ b/backend/src/main/java/com/rit/ems/controller/VenueController.java @@ -0,0 +1,39 @@ +package com.rit.ems.controller; + +import com.rit.ems.model.Venue; +import com.rit.ems.repository.VenueRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RestController +@RequestMapping("/api/venues") +public class VenueController { + + @Autowired + private VenueRepository venueRepository; + + @GetMapping + public List getAllVenues() { + return venueRepository.findAll(); + } + + @PostMapping + public ResponseEntity createVenue(@RequestBody Venue venue) { + if (venue.getId() == null) { + venue.setId("v-" + (System.currentTimeMillis() + new Random().nextInt(1000))); + } + venueRepository.save(venue); + return ResponseEntity.ok(venue); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteVenue(@PathVariable String id) { + venueRepository.deleteById(id); + return ResponseEntity.ok(Map.of("message", "Venue deleted successfully")); + } +} diff --git a/backend/src/main/java/com/rit/ems/model/Announcement.java b/backend/src/main/java/com/rit/ems/model/Announcement.java new file mode 100644 index 0000000..4c14c69 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Announcement.java @@ -0,0 +1,48 @@ +package com.rit.ems.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_announcements") +public class Announcement { + @Id + private String id; + + private String title; + + @Column(columnDefinition = "TEXT") + private String content; + + private String timestamp; + + @Column(name = "sender_role") + private String senderRole; + + public Announcement() {} + + public Announcement(String id, String title, String content, String timestamp, String senderRole) { + this.id = id; + this.title = title; + this.content = content; + this.timestamp = timestamp; + this.senderRole = senderRole; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + + public String getContent() { return content; } + public void setContent(String content) { this.content = content; } + + public String getTimestamp() { return timestamp; } + public void setTimestamp(String timestamp) { this.timestamp = timestamp; } + + public String getSenderRole() { return senderRole; } + public void setSenderRole(String senderRole) { this.senderRole = senderRole; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Attendance.java b/backend/src/main/java/com/rit/ems/model/Attendance.java new file mode 100644 index 0000000..95331cd --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Attendance.java @@ -0,0 +1,100 @@ +package com.rit.ems.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_attendance") +public class Attendance { + @Id + private String id; // format: regId_day_slot + + @Column(name = "registration_id") + private String registrationId; + + @Column(name = "event_id") + private Long eventId; + + @Column(name = "day_label") + private String dayLabel; + + @Column(name = "batch_label") + private String batchLabel; + + @Column(name = "is_present") + private Boolean isPresent = false; + + private String date; + + public Attendance() {} + + public Attendance(String id, String registrationId, Long eventId, String dayLabel, String batchLabel, Boolean isPresent, String date) { + this.id = id; + this.registrationId = registrationId; + this.eventId = eventId; + this.dayLabel = dayLabel; + this.batchLabel = batchLabel; + this.isPresent = isPresent; + this.date = date; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getRegistrationId() { return registrationId; } + public void setRegistrationId(String registrationId) { this.registrationId = registrationId; } + + public Long getEventId() { return eventId; } + public void setEventId(Long eventId) { this.eventId = eventId; } + + public String getDayLabel() { return dayLabel; } + public void setDayLabel(String dayLabel) { this.dayLabel = dayLabel; } + + public String getBatchLabel() { return batchLabel; } + public void setBatchLabel(String batchLabel) { this.batchLabel = batchLabel; } + + public Boolean getIsPresent() { return isPresent; } + public void setIsPresent(Boolean isPresent) { this.isPresent = isPresent; } + + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + + // Getters and setters to bridge snake_case from frontend + @JsonProperty("registration_id") + public String getRegistrationIdSnake() { return registrationId; } + @JsonProperty("registration_id") + public void setRegistrationIdSnake(String registrationId) { this.registrationId = registrationId; } + + @JsonProperty("event_id") + public Long getEventIdSnake() { return eventId; } + @JsonProperty("event_id") + public void setEventIdSnake(Long eventId) { this.eventId = eventId; } + + @JsonProperty("day_label") + public String getDayLabelSnake() { return dayLabel; } + @JsonProperty("day_label") + public void setDayLabelSnake(String dayLabel) { this.dayLabel = dayLabel; } + + @JsonProperty("day_idx") + public String getDayIdx() { return dayLabel; } + @JsonProperty("day_idx") + public void setDayIdx(String dayLabel) { this.dayLabel = dayLabel; } + + @JsonProperty("batch_label") + public String getBatchLabelSnake() { return batchLabel; } + @JsonProperty("batch_label") + public void setBatchLabelSnake(String batchLabel) { this.batchLabel = batchLabel; } + + @JsonProperty("batch_idx") + public String getBatchIdx() { return batchLabel; } + @JsonProperty("batch_idx") + public void setBatchIdx(String batchLabel) { this.batchLabel = batchLabel; } + + @JsonProperty("is_present") + public Boolean getIsPresentSnake() { return isPresent; } + @JsonProperty("is_present") + public void setIsPresentSnake(Boolean isPresent) { this.isPresent = isPresent; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Batch.java b/backend/src/main/java/com/rit/ems/model/Batch.java new file mode 100644 index 0000000..d1af055 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Batch.java @@ -0,0 +1,35 @@ +package com.rit.ems.model; + +import com.rit.ems.util.JsonConverter; +import jakarta.persistence.*; +import java.util.List; + +@Entity +@Table(name = "ems_batches") +public class Batch { + @Id + private Long id; + + private String name; + + @Convert(converter = JsonConverter.class) + @Column(columnDefinition = "TEXT") + private List classes; + + public Batch() {} + + public Batch(Long id, String name, List classes) { + this.id = id; + this.name = name; + this.classes = classes; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public List getClasses() { return classes; } + public void setClasses(List classes) { this.classes = classes; } +} diff --git a/backend/src/main/java/com/rit/ems/model/ClassMapping.java b/backend/src/main/java/com/rit/ems/model/ClassMapping.java new file mode 100644 index 0000000..4e6f528 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/ClassMapping.java @@ -0,0 +1,53 @@ +package com.rit.ems.model; + +import com.rit.ems.util.JsonConverter; +import jakarta.persistence.*; +import java.util.List; + +@Entity +@Table(name = "ems_classes") +public class ClassMapping { + @Id + private Long id; + + private String institution; + private String department; + + @Column(name = "academic_year") + private String academicYear; + + @Convert(converter = JsonConverter.class) + @Column(columnDefinition = "TEXT") + private List sections; + + private String status; + + public ClassMapping() {} + + public ClassMapping(Long id, String institution, String department, String academicYear, List sections, String status) { + this.id = id; + this.institution = institution; + this.department = department; + this.academicYear = academicYear; + this.sections = sections; + this.status = status; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getInstitution() { return institution; } + public void setInstitution(String institution) { this.institution = institution; } + + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + + public String getAcademicYear() { return academicYear; } + public void setAcademicYear(String academicYear) { this.academicYear = academicYear; } + + public List getSections() { return sections; } + public void setSections(List sections) { this.sections = sections; } + + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Event.java b/backend/src/main/java/com/rit/ems/model/Event.java new file mode 100644 index 0000000..72120ec --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Event.java @@ -0,0 +1,341 @@ +package com.rit.ems.model; + +import com.rit.ems.util.JsonConverter; +import jakarta.persistence.*; +import java.util.List; +import java.util.Map; + +@Entity +@Table(name = "ems_events") +public class Event { + @Id + private Long id; + + private String title; + + @Column(columnDefinition = "TEXT") + private String description; + + @Column(name = "start_date") + private String startDate; + + @Column(name = "end_date") + private String endDate; + + private String location; + private String category; + private String type; + private String institution; + private String department; + + @Convert(converter = JsonConverter.class) + @Column(name = "academic_years", columnDefinition = "TEXT") + private List academicYears; + + private String status; + + @Column(name = "guest_name") + private String guestName; + + @Column(name = "guest_social_profile") + private String guestSocialProfile; + + @Convert(converter = JsonConverter.class) + @Column(columnDefinition = "TEXT") + private List requirements; + + @Convert(converter = JsonConverter.class) + @Column(name = "targeted_sections", columnDefinition = "TEXT") + private List targetedSections; + + @Convert(converter = JsonConverter.class) + @Column(name = "target_departments", columnDefinition = "TEXT") + private List targetDepartments; + + @Column(name = "group_request_id") + private String groupRequestId; + + @Convert(converter = JsonConverter.class) + @Column(columnDefinition = "TEXT") + private List sponsors; + + private Double budget = 0.0; + + @Column(name = "has_registration_fee") + private Boolean hasRegistrationFee = false; + + @Column(name = "registration_fee") + private Double registrationFee = 0.0; + + @Column(name = "payment_link") + private String paymentLink; + + @Column(name = "centre_name") + private String centreName; + + @Column(name = "is_public_event") + private Boolean isPublicEvent = false; + + @Column(columnDefinition = "MEDIUMTEXT") + private String image; + + @Column(name = "targeted_batch") + private String targetedBatch; + + @Column(name = "open_to_all") + private Boolean openToAll = false; + + @Column(name = "max_participants") + private Integer maxParticipants; + + @Column(name = "current_participants") + private Integer currentParticipants = 0; + + @Embedded + private ProposerInfo proposer; + + @Convert(converter = JsonConverter.class) + @Column(name = "day_configs", columnDefinition = "TEXT") + private List dayConfigs; + + @Convert(converter = JsonConverter.class) + @Column(name = "dept_limits", columnDefinition = "TEXT") + private Map deptLimits; + + @Convert(converter = JsonConverter.class) + @Column(name = "dept_section_limits", columnDefinition = "TEXT") + private Map deptSectionLimits; + + @Column(name = "refreshment_expense") + private Double refreshmentExpense = 0.0; + + @Column(name = "transportation_expense") + private Double transportationExpense = 0.0; + + @Column(name = "session_coverage_fee") + private Double sessionCoverageFee = 0.0; + + @Column(name = "total_expense") + private Double totalExpense = 0.0; + + @Column(name = "duration_days") + private Integer durationDays = 1; + + @Column(name = "rejection_reason") + private String rejectionReason; + + @Column(name = "conflict_message") + private String conflictMessage; + + public Event() {} + + public Event(Long id, String title, String description, String startDate, String endDate, String location, String category, String type, String institution, String department, List academicYears, String status, String guestName, String guestSocialProfile, List requirements, List targetedSections, List targetDepartments, String groupRequestId, List sponsors, Double budget, Boolean hasRegistrationFee, Double registrationFee, String paymentLink, String centreName, Boolean isPublicEvent, String image, String targetedBatch, Boolean openToAll, Integer maxParticipants, Integer currentParticipants, ProposerInfo proposer, List dayConfigs, Map deptLimits, Map deptSectionLimits, Double refreshmentExpense, Double transportationExpense, Double sessionCoverageFee, Double totalExpense, Integer durationDays, String rejectionReason, String conflictMessage) { + this.id = id; + this.title = title; + this.description = description; + this.startDate = startDate; + this.endDate = endDate; + this.location = location; + this.category = category; + this.type = type; + this.institution = institution; + this.department = department; + this.academicYears = academicYears; + this.status = status; + this.guestName = guestName; + this.guestSocialProfile = guestSocialProfile; + this.requirements = requirements; + this.targetedSections = targetedSections; + this.targetDepartments = targetDepartments; + this.groupRequestId = groupRequestId; + this.sponsors = sponsors; + this.budget = budget; + this.hasRegistrationFee = hasRegistrationFee; + this.registrationFee = registrationFee; + this.paymentLink = paymentLink; + this.centreName = centreName; + this.isPublicEvent = isPublicEvent; + this.image = image; + this.targetedBatch = targetedBatch; + this.openToAll = openToAll; + this.maxParticipants = maxParticipants; + this.currentParticipants = currentParticipants; + this.proposer = proposer; + this.dayConfigs = dayConfigs; + this.deptLimits = deptLimits; + this.deptSectionLimits = deptSectionLimits; + this.refreshmentExpense = refreshmentExpense; + this.transportationExpense = transportationExpense; + this.sessionCoverageFee = sessionCoverageFee; + this.totalExpense = totalExpense; + this.durationDays = durationDays; + this.rejectionReason = rejectionReason; + this.conflictMessage = conflictMessage; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + + public String getStartDate() { return startDate; } + public void setStartDate(String startDate) { this.startDate = startDate; } + + public String getEndDate() { return endDate; } + public void setEndDate(String endDate) { this.endDate = endDate; } + + public String getLocation() { return location; } + public void setLocation(String location) { this.location = location; } + + public String getCategory() { return category; } + public void setCategory(String category) { this.category = category; } + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + + public String getInstitution() { return institution; } + public void setInstitution(String institution) { this.institution = institution; } + + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + + public List getAcademicYears() { return academicYears; } + public void setAcademicYears(List academicYears) { this.academicYears = academicYears; } + + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + + public String getGuestName() { return guestName; } + public void setGuestName(String guestName) { this.guestName = guestName; } + + public String getGuestSocialProfile() { return guestSocialProfile; } + public void setGuestSocialProfile(String guestSocialProfile) { this.guestSocialProfile = guestSocialProfile; } + + public List getRequirements() { return requirements; } + public void setRequirements(List requirements) { this.requirements = requirements; } + + public List getTargetedSections() { return targetedSections; } + public void setTargetedSections(List targetedSections) { this.targetedSections = targetedSections; } + + public List getTargetDepartments() { return targetDepartments; } + public void setTargetDepartments(List targetDepartments) { this.targetDepartments = targetDepartments; } + + public String getGroupRequestId() { return groupRequestId; } + public void setGroupRequestId(String groupRequestId) { this.groupRequestId = groupRequestId; } + + public List getSponsors() { return sponsors; } + public void setSponsors(List sponsors) { this.sponsors = sponsors; } + + public Double getBudget() { return budget; } + public void setBudget(Double budget) { this.budget = budget; } + + public Boolean getHasRegistrationFee() { return hasRegistrationFee; } + public void setHasRegistrationFee(Boolean hasRegistrationFee) { this.hasRegistrationFee = hasRegistrationFee; } + + public Double getRegistrationFee() { return registrationFee; } + public void setRegistrationFee(Double registrationFee) { this.registrationFee = registrationFee; } + + public String getPaymentLink() { return paymentLink; } + public void setPaymentLink(String paymentLink) { this.paymentLink = paymentLink; } + + public String getCentreName() { return centreName; } + public void setCentreName(String centreName) { this.centreName = centreName; } + + public Boolean getIsPublicEvent() { return isPublicEvent; } + public void setIsPublicEvent(Boolean isPublicEvent) { this.isPublicEvent = isPublicEvent; } + + public String getImage() { return image; } + public void setImage(String image) { this.image = image; } + + public String getTargetedBatch() { return targetedBatch; } + public void setTargetedBatch(String targetedBatch) { this.targetedBatch = targetedBatch; } + + public Boolean getOpenToAll() { return openToAll; } + public void setOpenToAll(Boolean openToAll) { this.openToAll = openToAll; } + + public Integer getMaxParticipants() { return maxParticipants; } + public void setMaxParticipants(Integer maxParticipants) { this.maxParticipants = maxParticipants; } + + public Integer getCurrentParticipants() { return currentParticipants; } + public void setCurrentParticipants(Integer currentParticipants) { this.currentParticipants = currentParticipants; } + + public ProposerInfo getProposer() { return proposer; } + public void setProposer(ProposerInfo proposer) { this.proposer = proposer; } + + public List getDayConfigs() { return dayConfigs; } + public void setDayConfigs(List dayConfigs) { this.dayConfigs = dayConfigs; } + + public Map getDeptLimits() { return deptLimits; } + public void setDeptLimits(Map deptLimits) { this.deptLimits = deptLimits; } + + public Map getDeptSectionLimits() { return deptSectionLimits; } + public void setDeptSectionLimits(Map deptSectionLimits) { this.deptSectionLimits = deptSectionLimits; } + + public Double getRefreshmentExpense() { return refreshmentExpense; } + public void setRefreshmentExpense(Double refreshmentExpense) { this.refreshmentExpense = refreshmentExpense; } + + public Double getTransportationExpense() { return transportationExpense; } + public void setTransportationExpense(Double transportationExpense) { this.transportationExpense = transportationExpense; } + + public Double getSessionCoverageFee() { return sessionCoverageFee; } + public void setSessionCoverageFee(Double sessionCoverageFee) { this.sessionCoverageFee = sessionCoverageFee; } + + public Double getTotalExpense() { return totalExpense; } + public void setTotalExpense(Double totalExpense) { this.totalExpense = totalExpense; } + + public Integer getDurationDays() { return durationDays; } + public void setDurationDays(Integer durationDays) { this.durationDays = durationDays; } + + public String getRejectionReason() { return rejectionReason; } + public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; } + + public String getConflictMessage() { return conflictMessage; } + public void setConflictMessage(String conflictMessage) { this.conflictMessage = conflictMessage; } + + @Embeddable + public static class ProposerInfo { + @Column(name = "proposer_id") + private Long id; + + @Column(name = "proposer_full_name") + private String fullName; + + @Column(name = "proposer_email") + private String email; + + @Column(name = "proposer_role") + private String role; + + @Column(name = "proposer_department") + private String department; + + public ProposerInfo() {} + + public ProposerInfo(Long id, String fullName, String email, String role, String department) { + this.id = id; + this.fullName = fullName; + this.email = email; + this.role = role; + this.department = department; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getFullName() { return fullName; } + public void setFullName(String fullName) { this.fullName = fullName; } + + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + } +} diff --git a/backend/src/main/java/com/rit/ems/model/InstitutionalEvent.java b/backend/src/main/java/com/rit/ems/model/InstitutionalEvent.java new file mode 100644 index 0000000..c433034 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/InstitutionalEvent.java @@ -0,0 +1,37 @@ +package com.rit.ems.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_institutional_events") +public class InstitutionalEvent { + @Id + private String id; + + private String name; + private String month; + private String semester; + + public InstitutionalEvent() {} + + public InstitutionalEvent(String id, String name, String month, String semester) { + this.id = id; + this.name = name; + this.month = month; + this.semester = semester; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public String getMonth() { return month; } + public void setMonth(String month) { this.month = month; } + + public String getSemester() { return semester; } + public void setSemester(String semester) { this.semester = semester; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Note.java b/backend/src/main/java/com/rit/ems/model/Note.java new file mode 100644 index 0000000..7ce73f4 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Note.java @@ -0,0 +1,48 @@ +package com.rit.ems.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_notes") +public class Note { + @Id + private Long id; + + private String title; + + @Column(columnDefinition = "TEXT") + private String content; + + @Column(name = "created_at") + private String createdAt; + + public Note() {} + + public Note(Long id, String title, String content, String createdAt) { + this.id = id; + this.title = title; + this.content = content; + this.createdAt = createdAt; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + + public String getContent() { return content; } + public void setContent(String content) { this.content = content; } + + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + + @JsonProperty("created_at") + public String getCreatedAtSnake() { return createdAt; } + @JsonProperty("created_at") + public void setCreatedAtSnake(String createdAt) { this.createdAt = createdAt; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Registration.java b/backend/src/main/java/com/rit/ems/model/Registration.java new file mode 100644 index 0000000..f806261 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Registration.java @@ -0,0 +1,222 @@ +package com.rit.ems.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.persistence.*; + +@Entity +@Table(name = "ems_registrations") +public class Registration { + @Id + private String id; // format: userId_eventId + + @Column(name = "user_id") + private Long userId; + + @Column(name = "event_id") + private Long eventId; + + @Column(name = "payment_status") + private String paymentStatus; + + @Column(name = "certification_status") + private String certificationStatus = "NOT_SUBMITTED"; + + @Column(name = "registered_at") + private String registeredAt; + + @Column(name = "team_code") + private String teamCode; + + @Column(name = "team_name") + private String teamName; + + @Column(name = "is_team_leader") + private Boolean isTeamLeader = false; + + @Column(name = "certification_url", columnDefinition = "TEXT") + private String certificationUrl; + + @Column(name = "od_url", columnDefinition = "TEXT") + private String odUrl; + + @Column(name = "ticket_id") + private String ticketId; + + @Column(name = "ticket_qrcode", columnDefinition = "TEXT") + private String ticketQrcode; + + // Student profile details captured at registration time + private String name; + private String email; + private String dept; + private String department; + private String section; + private String year; + + @Column(name = "reg_no") + private String regNo; + + private String phone; + private String gender; + + @Column(name = "college_name") + private String collegeName; + + public Registration() {} + + public Registration(String id, Long userId, Long eventId, String paymentStatus, String certificationStatus, String registeredAt, String teamCode, String teamName, Boolean isTeamLeader, String certificationUrl, String odUrl, String ticketId, String ticketQrcode, String name, String email, String dept, String department, String section, String year, String regNo, String phone, String gender, String collegeName) { + this.id = id; + this.userId = userId; + this.eventId = eventId; + this.paymentStatus = paymentStatus; + this.certificationStatus = certificationStatus; + this.registeredAt = registeredAt; + this.teamCode = teamCode; + this.teamName = teamName; + this.isTeamLeader = isTeamLeader; + this.certificationUrl = certificationUrl; + this.odUrl = odUrl; + this.ticketId = ticketId; + this.ticketQrcode = ticketQrcode; + this.name = name; + this.email = email; + this.dept = dept; + this.department = department; + this.section = section; + this.year = year; + this.regNo = regNo; + this.phone = phone; + this.gender = gender; + this.collegeName = collegeName; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public Long getUserId() { return userId; } + public void setUserId(Long userId) { this.userId = userId; } + + public Long getEventId() { return eventId; } + public void setEventId(Long eventId) { this.eventId = eventId; } + + public String getPaymentStatus() { return paymentStatus; } + public void setPaymentStatus(String paymentStatus) { this.paymentStatus = paymentStatus; } + + public String getCertificationStatus() { return certificationStatus; } + public void setCertificationStatus(String certificationStatus) { this.certificationStatus = certificationStatus; } + + public String getRegisteredAt() { return registeredAt; } + public void setRegisteredAt(String registeredAt) { this.registeredAt = registeredAt; } + + public String getTeamCode() { return teamCode; } + public void setTeamCode(String teamCode) { this.teamCode = teamCode; } + + public String getTeamName() { return teamName; } + public void setTeamName(String teamName) { this.teamName = teamName; } + + public Boolean getIsTeamLeader() { return isTeamLeader; } + public void setIsTeamLeader(Boolean isTeamLeader) { this.isTeamLeader = isTeamLeader; } + + public String getCertificationUrl() { return certificationUrl; } + public void setCertificationUrl(String certificationUrl) { this.certificationUrl = certificationUrl; } + + public String getOdUrl() { return odUrl; } + public void setOdUrl(String odUrl) { this.odUrl = odUrl; } + + public String getTicketId() { return ticketId; } + public void setTicketId(String ticketId) { this.ticketId = ticketId; } + + public String getTicketQrcode() { return ticketQrcode; } + public void setTicketQrcode(String ticketQrcode) { this.ticketQrcode = ticketQrcode; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + + public String getDept() { return dept; } + public void setDept(String dept) { this.dept = dept; } + + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + + public String getSection() { return section; } + public void setSection(String section) { this.section = section; } + + public String getYear() { return year; } + public void setYear(String year) { this.year = year; } + + public String getRegNo() { return regNo; } + public void setRegNo(String regNo) { this.regNo = regNo; } + + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + + public String getGender() { return gender; } + public void setGender(String gender) { this.gender = gender; } + + public String getCollegeName() { return collegeName; } + public void setCollegeName(String collegeName) { this.collegeName = collegeName; } + + // Getters and setters to bridge snake_case from frontend + @JsonProperty("user_id") + public Long getUserIdSnake() { return userId; } + @JsonProperty("user_id") + public void setUserIdSnake(Long userId) { this.userId = userId; } + + @JsonProperty("event_id") + public Long getEventIdSnake() { return eventId; } + @JsonProperty("event_id") + public void setEventIdSnake(Long eventId) { this.eventId = eventId; } + + @JsonProperty("payment_status") + public String getPaymentStatusSnake() { return paymentStatus; } + @JsonProperty("payment_status") + public void setPaymentStatusSnake(String paymentStatus) { this.paymentStatus = paymentStatus; } + + @JsonProperty("certification_status") + public String getCertificationStatusSnake() { return certificationStatus; } + @JsonProperty("certification_status") + public void setCertificationStatusSnake(String certificationStatus) { this.certificationStatus = certificationStatus; } + + @JsonProperty("registered_at") + public String getRegisteredAtSnake() { return registeredAt; } + @JsonProperty("registered_at") + public void setRegisteredAtSnake(String registeredAt) { this.registeredAt = registeredAt; } + + @JsonProperty("team_code") + public String getTeamCodeSnake() { return teamCode; } + @JsonProperty("team_code") + public void setTeamCodeSnake(String teamCode) { this.teamCode = teamCode; } + + @JsonProperty("team_name") + public String getTeamNameSnake() { return teamName; } + @JsonProperty("team_name") + public void setTeamNameSnake(String teamName) { this.teamName = teamName; } + + @JsonProperty("is_team_leader") + public Boolean getIsTeamLeaderSnake() { return isTeamLeader; } + @JsonProperty("is_team_leader") + public void setIsTeamLeaderSnake(Boolean isTeamLeader) { this.isTeamLeader = isTeamLeader; } + + @JsonProperty("certification_url") + public String getCertificationUrlSnake() { return certificationUrl; } + @JsonProperty("certification_url") + public void setCertificationUrlSnake(String certificationUrl) { this.certificationUrl = certificationUrl; } + + @JsonProperty("od_url") + public String getOdUrlSnake() { return odUrl; } + @JsonProperty("od_url") + public void setOdUrlSnake(String odUrl) { this.odUrl = odUrl; } + + @JsonProperty("ticket_id") + public String getTicketIdSnake() { return ticketId; } + @JsonProperty("ticket_id") + public void setTicketIdSnake(String ticketId) { this.ticketId = ticketId; } + + @JsonProperty("ticket_qrcode") + public String getTicketQrcodeSnake() { return ticketQrcode; } + @JsonProperty("ticket_qrcode") + public void setTicketQrcodeSnake(String ticketQrcode) { this.ticketQrcode = ticketQrcode; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Setting.java b/backend/src/main/java/com/rit/ems/model/Setting.java new file mode 100644 index 0000000..e23c325 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Setting.java @@ -0,0 +1,28 @@ +package com.rit.ems.model; + +import com.rit.ems.util.JsonConverter; +import jakarta.persistence.*; + +@Entity +@Table(name = "ems_settings") +public class Setting { + @Id + private String id; // key + + @Convert(converter = JsonConverter.class) + @Column(name = "setting_value", columnDefinition = "TEXT") + private Object value; + + public Setting() {} + + public Setting(String id, Object value) { + this.id = id; + this.value = value; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public Object getValue() { return value; } + public void setValue(Object value) { this.value = value; } +} diff --git a/backend/src/main/java/com/rit/ems/model/SpecialEvent.java b/backend/src/main/java/com/rit/ems/model/SpecialEvent.java new file mode 100644 index 0000000..e4332e2 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/SpecialEvent.java @@ -0,0 +1,92 @@ +package com.rit.ems.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_special_events") +public class SpecialEvent { + @Id + private String id; + + private String name; + + @Column(columnDefinition = "TEXT") + private String description; + + private String location; + + @Column(name = "start_date") + private String startDate; + + @Column(name = "end_date") + private String endDate; + + @Column(name = "created_at") + private String createdAt; + + @Column(name = "is_active") + private Boolean isActive = true; + + @Column(name = "verification_status") + private String verificationStatus = "APPROVED"; + + public SpecialEvent() {} + + public SpecialEvent(String id, String name, String description, String location, String startDate, String endDate, String createdAt, Boolean isActive, String verificationStatus) { + this.id = id; + this.name = name; + this.description = description; + this.location = location; + this.startDate = startDate; + this.endDate = endDate; + this.createdAt = createdAt; + this.isActive = isActive; + this.verificationStatus = verificationStatus; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + + public String getLocation() { return location; } + public void setLocation(String location) { this.location = location; } + + public String getStartDate() { return startDate; } + public void setStartDate(String startDate) { this.startDate = startDate; } + + public String getEndDate() { return endDate; } + public void setEndDate(String endDate) { this.endDate = endDate; } + + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + + public Boolean getIsActive() { return isActive; } + public void setIsActive(Boolean isActive) { this.isActive = isActive; } + + public String getVerificationStatus() { return verificationStatus; } + public void setVerificationStatus(String verificationStatus) { this.verificationStatus = verificationStatus; } + + @JsonProperty("created_at") + public String getCreatedAtSnake() { return createdAt; } + @JsonProperty("created_at") + public void setCreatedAtSnake(String createdAt) { this.createdAt = createdAt; } + + @JsonProperty("is_active") + public Boolean getIsActiveSnake() { return isActive; } + @JsonProperty("is_active") + public void setIsActiveSnake(Boolean isActive) { this.isActive = isActive; } + + @JsonProperty("verification_status") + public String getVerificationStatusSnake() { return verificationStatus; } + @JsonProperty("verification_status") + public void setVerificationStatusSnake(String verificationStatus) { this.verificationStatus = verificationStatus; } +} diff --git a/backend/src/main/java/com/rit/ems/model/User.java b/backend/src/main/java/com/rit/ems/model/User.java new file mode 100644 index 0000000..185c105 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/User.java @@ -0,0 +1,147 @@ +package com.rit.ems.model; + +import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Table(name = "ems_users") +public class User { + @Id + private Long id; + + @Column(unique = true, nullable = false) + private String email; + + private String password; + + @Column(name = "full_name") + private String fullName; + + private String role; + + private String department; + + @Column(name = "is_club_coordinator") + private Boolean isClubCoordinator = false; + + @Column(name = "is_placement_staff") + private Boolean isPlacementStaff = false; + + @Column(name = "is_class_incharge") + private Boolean isClassIncharge = false; + + @Column(name = "class_strength") + private Integer classStrength = 0; + + @Column(name = "incharge_class") + private String inchargeClass; + + @Column(name = "incharge_batch") + private String inchargeBatch; + + @Column(name = "incharge_section") + private String inchargeSection; + + private String year; + private String section; + + @Column(name = "reg_no") + private String regNo; + + private String phone; + private String gender; + + @Column(name = "college_name") + private String collegeName; + + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "ems_user_assigned_clubs", joinColumns = @JoinColumn(name = "user_id")) + @Column(name = "club_name") + private List assignedClubs = new ArrayList<>(); + + public User() {} + + public User(Long id, String email, String password, String fullName, String role, String department, Boolean isClubCoordinator, Boolean isPlacementStaff, Boolean isClassIncharge, Integer classStrength, String inchargeClass, String inchargeBatch, String inchargeSection, String year, String section, String regNo, String phone, String gender, String collegeName, List assignedClubs) { + this.id = id; + this.email = email; + this.password = password; + this.fullName = fullName; + this.role = role; + this.department = department; + this.isClubCoordinator = isClubCoordinator; + this.isPlacementStaff = isPlacementStaff; + this.isClassIncharge = isClassIncharge; + this.classStrength = classStrength; + this.inchargeClass = inchargeClass; + this.inchargeBatch = inchargeBatch; + this.inchargeSection = inchargeSection; + this.year = year; + this.section = section; + this.regNo = regNo; + this.phone = phone; + this.gender = gender; + this.collegeName = collegeName; + this.assignedClubs = assignedClubs; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + + public String getFullName() { return fullName; } + public void setFullName(String fullName) { this.fullName = fullName; } + + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + + public Boolean getIsClubCoordinator() { return isClubCoordinator; } + public void setIsClubCoordinator(Boolean isClubCoordinator) { this.isClubCoordinator = isClubCoordinator; } + + public Boolean getIsPlacementStaff() { return isPlacementStaff; } + public void setIsPlacementStaff(Boolean isPlacementStaff) { this.isPlacementStaff = isPlacementStaff; } + + public Boolean getIsClassIncharge() { return isClassIncharge; } + public void setIsClassIncharge(Boolean isClassIncharge) { this.isClassIncharge = isClassIncharge; } + + public Integer getClassStrength() { return classStrength; } + public void setClassStrength(Integer classStrength) { this.classStrength = classStrength; } + + public String getInchargeClass() { return inchargeClass; } + public void setInchargeClass(String inchargeClass) { this.inchargeClass = inchargeClass; } + + public String getInchargeBatch() { return inchargeBatch; } + public void setInchargeBatch(String inchargeBatch) { this.inchargeBatch = inchargeBatch; } + + public String getInchargeSection() { return inchargeSection; } + public void setInchargeSection(String inchargeSection) { this.inchargeSection = inchargeSection; } + + public String getYear() { return year; } + public void setYear(String year) { this.year = year; } + + public String getSection() { return section; } + public void setSection(String section) { this.section = section; } + + public String getRegNo() { return regNo; } + public void setRegNo(String regNo) { this.regNo = regNo; } + + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + + public String getGender() { return gender; } + public void setGender(String gender) { this.gender = gender; } + + public String getCollegeName() { return collegeName; } + public void setCollegeName(String collegeName) { this.collegeName = collegeName; } + + public List getAssignedClubs() { return assignedClubs; } + public void setAssignedClubs(List assignedClubs) { this.assignedClubs = assignedClubs; } +} diff --git a/backend/src/main/java/com/rit/ems/model/Venue.java b/backend/src/main/java/com/rit/ems/model/Venue.java new file mode 100644 index 0000000..f99a161 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/model/Venue.java @@ -0,0 +1,32 @@ +package com.rit.ems.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "ems_venues") +public class Venue { + @Id + private String id; + + private String name; + private Integer capacity; + + public Venue() {} + + public Venue(String id, String name, Integer capacity) { + this.id = id; + this.name = name; + this.capacity = capacity; + } + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public Integer getCapacity() { return capacity; } + public void setCapacity(Integer capacity) { this.capacity = capacity; } +} diff --git a/backend/src/main/java/com/rit/ems/repository/AnnouncementRepository.java b/backend/src/main/java/com/rit/ems/repository/AnnouncementRepository.java new file mode 100644 index 0000000..06416ee --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/AnnouncementRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Announcement; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AnnouncementRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/AttendanceRepository.java b/backend/src/main/java/com/rit/ems/repository/AttendanceRepository.java new file mode 100644 index 0000000..ea3e60e --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/AttendanceRepository.java @@ -0,0 +1,10 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Attendance; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + +public interface AttendanceRepository extends JpaRepository { + List findByRegistrationId(String registrationId); + List findByEventId(Long eventId); +} diff --git a/backend/src/main/java/com/rit/ems/repository/BatchRepository.java b/backend/src/main/java/com/rit/ems/repository/BatchRepository.java new file mode 100644 index 0000000..9c01a5f --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/BatchRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Batch; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BatchRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/ClassMappingRepository.java b/backend/src/main/java/com/rit/ems/repository/ClassMappingRepository.java new file mode 100644 index 0000000..29aa128 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/ClassMappingRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.ClassMapping; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ClassMappingRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/EventRepository.java b/backend/src/main/java/com/rit/ems/repository/EventRepository.java new file mode 100644 index 0000000..147617e --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/EventRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Event; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface EventRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/InstitutionalEventRepository.java b/backend/src/main/java/com/rit/ems/repository/InstitutionalEventRepository.java new file mode 100644 index 0000000..9c3cc98 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/InstitutionalEventRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.InstitutionalEvent; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface InstitutionalEventRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/NoteRepository.java b/backend/src/main/java/com/rit/ems/repository/NoteRepository.java new file mode 100644 index 0000000..7032794 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/NoteRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Note; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NoteRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/RegistrationRepository.java b/backend/src/main/java/com/rit/ems/repository/RegistrationRepository.java new file mode 100644 index 0000000..5249fea --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/RegistrationRepository.java @@ -0,0 +1,13 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Registration; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; +import java.util.Optional; + +public interface RegistrationRepository extends JpaRepository { + List findByUserId(Long userId); + List findByEventId(Long eventId); + List findByTeamCode(String teamCode); + Optional findByUserIdAndEventId(Long userId, Long eventId); +} diff --git a/backend/src/main/java/com/rit/ems/repository/SettingRepository.java b/backend/src/main/java/com/rit/ems/repository/SettingRepository.java new file mode 100644 index 0000000..ca107f9 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/SettingRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Setting; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SettingRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/SpecialEventRepository.java b/backend/src/main/java/com/rit/ems/repository/SpecialEventRepository.java new file mode 100644 index 0000000..70e8326 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/SpecialEventRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.SpecialEvent; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SpecialEventRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/repository/UserRepository.java b/backend/src/main/java/com/rit/ems/repository/UserRepository.java new file mode 100644 index 0000000..b8d0a28 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/UserRepository.java @@ -0,0 +1,9 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByEmailIgnoreCase(String email); +} diff --git a/backend/src/main/java/com/rit/ems/repository/VenueRepository.java b/backend/src/main/java/com/rit/ems/repository/VenueRepository.java new file mode 100644 index 0000000..2a855ad --- /dev/null +++ b/backend/src/main/java/com/rit/ems/repository/VenueRepository.java @@ -0,0 +1,7 @@ +package com.rit.ems.repository; + +import com.rit.ems.model.Venue; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VenueRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/rit/ems/util/JsonConverter.java b/backend/src/main/java/com/rit/ems/util/JsonConverter.java new file mode 100644 index 0000000..a8713e9 --- /dev/null +++ b/backend/src/main/java/com/rit/ems/util/JsonConverter.java @@ -0,0 +1,35 @@ +package com.rit.ems.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; + +@Converter +public class JsonConverter implements AttributeConverter { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public String convertToDatabaseColumn(Object attribute) { + if (attribute == null) { + return null; + } + try { + return objectMapper.writeValueAsString(attribute); + } catch (JsonProcessingException e) { + throw new RuntimeException("Error converting object to JSON string", e); + } + } + + @Override + public Object convertToEntityAttribute(String dbData) { + if (dbData == null || dbData.isEmpty()) { + return null; + } + try { + return objectMapper.readValue(dbData, Object.class); + } catch (JsonProcessingException e) { + throw new RuntimeException("Error converting JSON string to object", e); + } + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties new file mode 100644 index 0000000..02c1731 --- /dev/null +++ b/backend/src/main/resources/application.properties @@ -0,0 +1,17 @@ +spring.application.name=ems-backend +server.port=8081 + +# Database Configuration +spring.datasource.url=jdbc:mysql://localhost:3306/rit_ems?createDatabaseIfNotExist=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password=Abiram@07 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +# JPA/Hibernate Config +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect + +# Max upload sizes for files/images (if any) +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 79de8a5..e41f6f6 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,4 +1,4 @@ -import './lib/firebaseBackend' +// import './lib/firebaseBackend' import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css'