dgPadBootcamps / Java-Bootcamp-2024

1 stars 0 forks source link

Task 4: Spring boot with database #215

Closed mohammad-fahs closed 1 week ago

mohammad-fahs commented 1 month ago

Task: Create an Advanced Student Management System Using Spring Boot, MySQL Database, and REST APIs

Objective:

Your task is to create an advanced Student Management System using Spring Boot, MySQL, and RESTful APIs. This system will manage not only students but also courses and enrollments. You will create a relational database structure that includes multiple entities and relationships between them. This exercise will help you understand how to build a more complex CRUD application with multiple entities and relationships using Spring Boot, JPA, and MySQL.

user this discussion for help:

https://github.com/dgPadBootcamps/Java-Bootcamp-2024/discussions/195

Make Sure to use the best practice architecture discussed in the latest sessions

Requirements:

  1. Project Setup:
    • Set up a Spring Boot project using Maven.
    • Include dependencies for Spring Web, Spring Data JPA, MySQL Connector, and any other libraries you may find necessary.
  2. Database Setup:
    • Install MySQL or use an existing MySQL server.
    • Create a new database named student_management.
    • In your application.properties (or application.yml) file, configure the connection to the MySQL database, including the database URL, username, and password.
  3. Entity Classes:

    • Create the following entities with appropriate JPA annotations:

    a. Student:

    • Fields:
      • id: Primary key, auto-generated.
      • firstName: String, not null.
      • lastName: String, not null.
      • email: String, not null, unique.
      • age: Integer.
      • enrollments: One-to-Many relationship with the Enrollment entity.

    b. Course:

    • Fields:
      • id: Primary key, auto-generated.
      • courseName: String, not null.
      • courseCode: String, not null, unique.
      • credits: Integer.
      • instructor: String, not null.
      • enrollments: One-to-Many relationship with the Enrollment entity.

    c. Enrollment:

    • Fields:
      • id: Primary key, auto-generated.
      • student: Many-to-One relationship with the Student entity.
      • course: Many-to-One relationship with the Course entity.
      • enrollmentDate: Date of enrollment.
      • grade: String, grade received in the course.
    • Ensure that each entity class is properly annotated to represent the relationships, such as @OneToMany, @ManyToOne, and @JoinColumn.
  4. Repository Layer:
    • Create repository interfaces for each entity:
      • StudentRepository, CourseRepository, and EnrollmentRepository should extend JpaRepository.
    • These repositories will provide CRUD operations and any custom queries you may need later.
  5. Service Layer:
    • Create service classes for each entity, such as StudentService, CourseService, and EnrollmentService.
    • Each service class should contain business logic to handle CRUD operations and manage relationships between entities.
    • Inject the corresponding repository into each service to interact with the database.
  6. Controller Layer:

    • Create REST controllers to expose the following endpoints:

    a. Student Endpoints:

    • Create a new student:
      • Endpoint: POST /api/students
      • Request Body: JSON object with student details.
      • Response: JSON object representing the created student.
    • Retrieve all students:
      • Endpoint: GET /api/students
      • Response: JSON array of student objects.
    • Retrieve a student by ID:
      • Endpoint: GET /api/students/{id}
      • Path Variable: id (the student's ID).
      • Response: JSON object representing the student.
    • Update a student:
      • Endpoint: PUT /api/students/{id}
      • Path Variable: id (the student's ID).
      • Request Body: JSON object with updated student details.
      • Response: Updated JSON object of the student.
    • Delete a student:
      • Endpoint: DELETE /api/students/{id}
      • Path Variable: id (the student's ID).
      • Response: Confirmation message or status code indicating the deletion.

    b. Course Endpoints:

    • Create a new course:
      • Endpoint: POST /api/courses
      • Request Body: JSON object with course details.
      • Response: JSON object representing the created course.
    • Retrieve all courses:
      • Endpoint: GET /api/courses
      • Response: JSON array of course objects.
    • Retrieve a course by ID:
      • Endpoint: GET /api/courses/{id}
      • Path Variable: id (the course's ID).
      • Response: JSON object representing the course.
    • Update a course:
      • Endpoint: PUT /api/courses/{id}
      • Path Variable: id (the course's ID).
      • Request Body: JSON object with updated course details.
      • Response: Updated JSON object of the course.
    • Delete a course:
      • Endpoint: DELETE /api/courses/{id}
      • Path Variable: id (the course's ID).
      • Response: Confirmation message or status code indicating the deletion.

    c. Enrollment Endpoints:

    • Enroll a student in a course:
      • Endpoint: POST /api/enrollments
      • Request Body: JSON object with studentId, courseId, enrollmentDate, and grade.
      • Response: JSON object representing the created enrollment.
    • Retrieve all enrollments:
      • Endpoint: GET /api/enrollments
      • Response: JSON array of enrollment objects.
    • Retrieve enrollments for a specific student:
      • Endpoint: GET /api/students/{studentId}/enrollments
      • Path Variable: studentId.
      • Response: JSON array of enrollment objects for the specified student.
    • Retrieve enrollments for a specific course:
      • Endpoint: GET /api/courses/{courseId}/enrollments
      • Path Variable: courseId.
      • Response: JSON array of enrollment objects for the specified course.
    • Update an enrollment:
      • Endpoint: PUT /api/enrollments/{id}
      • Path Variable: id (the enrollment's ID).
      • Request Body: JSON object with updated enrollment details.
      • Response: Updated JSON object of the enrollment.
    • Delete an enrollment:
      • Endpoint: DELETE /api/enrollments/{id}
      • Path Variable: id (the enrollment's ID).
      • Response: Confirmation message or status code indicating the deletion.
  7. Validation:
    • Add validation to ensure:
      • Required fields are not null.
      • The email field in the Student entity is unique and follows a valid email format.
      • The courseCode field in the Course entity is unique.
      • The grade field in the Enrollment entity follows a specific format (e.g., A, B, C, etc.).
  8. Error Handling:
    • Implement error handling for:
      • Entity not found (e.g., when trying to retrieve or delete a non-existent student, course, or enrollment).
      • Invalid input data (e.g., missing required fields, invalid data format, etc.).
    • Return appropriate HTTP status codes (e.g., 404 for not found, 400 for bad request).
  9. Relationships:
    • Ensure that the relationships between entities (Student, Course, and Enrollment) are correctly handled in both the database and the application.
    • Test that creating, updating, or deleting a student or course also correctly updates or deletes related enrollments.

The task is submitted using Postman collection and code snippets as usual in addition to screenshots from the database

jinanabedalnabi commented 1 week ago

,.

jinanabedalnabi commented 1 week ago

Configure database connection at applicatopn.properties

spring.datasource.url=jdbc:mysql://localhost:3306/student_management spring.datasource.username=root spring.datasource.password=admin spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true

Entities

Student

@Entity @Getter @Setter public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String firstName; String lastName; String email; int age; @OneToMany Enrollment enrollments; public Student(String firstName,String lastName,int age ,String email) { this.id = Long.valueOf(UUID.randomUUID().toString()); this.firstName = firstName; this.lastName=lastName; this.email = email; this.age=age; this.enrollments= new Enrollment(); } }

Enrollment

@Entity @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; @ManyToOne Optional student; @ManyToOne Optional course; Date enrollmentDate; String grade; public Enrollment(Optional student, Optional course, Date enrollmentDate, String grade) { this.student = student; this.course = course; this.enrollmentDate = enrollmentDate; this.grade = grade; } }

Course

@Entity @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String courseName; String courseCode; String instructor; int credits; @OneToMany Enrollment enrollments; public Course(String courseName, String courseCode, String instructor, int credits) { this.courseName = courseName; this.courseCode = courseCode; this.instructor = instructor; this.credits = credits; this.enrollments = new Enrollment(); } }

Response

ApiResponse

import java.time.LocalDateTime; public class ApiResponse { private boolean success; private T data; private String message; private int code; private LocalDateTime date; public ApiResponse(boolean success, T data, String message, int code, LocalDateTime date) { this.success = success; this.data = data; this.message = message; this.code = code; this.date = LocalDateTime.now(); } }

jinanabedalnabi commented 1 week ago

DTO

Create Course DTO

import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Setter @getter @NoArgsConstructor @AllArgsConstructor public class CreateCourseDTO { @notblank String courseName; @notblank String courseCode; @notblank String instructor; int credits; }

UpdateCourseDTO

import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateCourseDTO { @NotBlank String courseName; @NotBlank String courseCode; @NotBlank String instructor; int credits; }

CreateStudentDTO

mport lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter @NoArgsConstructor @AllArgsConstructor public class CreateStudentDTO { @NotBlank @Size(min = 2, message = "firstName should have at least 2 characters") String firstName; @NotBlank @Size(min = 2, message = "lastName should have at least 2 characters") String lastName; @Positive int age; @NotBlank @Email(message = "Email should be valid") String email; }

UpdateStudentDTO

@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateStudentDTO { @NotBlank @Size(min = 2, message = "firstName should have at least 2 characters") String firstName;

@NotBlank
@Size(min = 2, message = "lastName should have at least 2 characters")
String lastName;

@Positive
int age;

@NotBlank
@Email(message = "Email should be valid")
String email;

}

EnrollStudentInCourse

import java.util.Date;

@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class EnrollStudentINCourse { @NotBlank Long studentId; @NotBlank Long courseId; Date enrollmentDate;

@Pattern(regexp = "A|B|C|D|F", message = "Grade must be A, B,C,D, or F")
String grade;

}

UpdateEnrollmentDTO

@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateEnrollmentDTO { Student s; Course c; Date enrollmentDate; @Pattern(regexp = "A|B|C|D|F", message = "Grade must be A, B,C,D, or F") String grade; }

jinanabedalnabi commented 1 week ago

Service

StudentService

@Autowired
StudentRepository studentRepository;
public final List<Student> students= new ArrayList<Student>();
public Stutent createStudent(CreateStudentDTO studentDTO){
    Student student= new Student(studentDTO.getFirstName(),studentDTO.getLastName(),studentDTO.getAge(),studentDTO.getEmail());
    students.add(student);
    return student;
}
public List<Student> getAllStudent(){
    return students;
}

public  Optional<Student> getStudentById(Long id){
    Optional<Student> student= studentRepository.findById(id);
    return student;
}

public Student updateStudent(Long id, UpdateStudentDTO updatedStudent) {
    Optional<Student> existingStudentOptional = studentRepository.findById(id);

    if (existingStudentOptional.isPresent()) {
        Student existingStudent = existingStudentOptional.get();
        existingStudent.setFirstName(updatedStudent.getFirstName());
        existingStudent.setLastName(updatedStudent.getLastName());
        existingStudent.setAge(updatedStudent.getAge());
        existingStudent.setEmail(updatedStudent.getEmail());
        return studentRepository.save(existingStudent);
    } else {
        return null;
    }
}

public void deleteStudent(Long id){
    studentRepository.deleteById(id);
}

}

CourseService

@Autowired
public CourseRepository courseRepository;

public final List<Course> courses= new ArrayList<Course>();

public Course createCourse(CreateCourseDTO courseDTO){
    Course course= new Course(courseDTO.getCourseName(),courseDTO.getCourseCode(),courseDTO.getInstructor(),courseDTO.getCredits());
    courses.add(course);
    return course;
}
public List<Course> getAllCourses(){
    return courses;
}

public Optional<Course> getCourseById(Long id){
   Optional<Course> course= courseRepository.findById(id);
   if(course!=null)
       return course;
   return null;
 }

public Course updateCourse(Long id, UpdateCourseDTO updatedCourse) {
    Optional<Course> existingCourseOptional = courseRepository.findById(id);

    if (existingCourseOptional.isPresent()) {
        Course existingCourse = existingCourseOptional.get();
        existingCourse.setCourseName(updatedCourse.getCourseName());
        existingCourse.setInstructor(updatedCourse.getInstructor());
        existingCourse.setCourseCode(updatedCourse.getCourseCode());
        existingCourse.setCredits(updatedCourse.getCredits());
        return courseRepository.save(existingCourse);
    } else {
        return null;
    }
}

public void deleteCourse(Long id){
    courseRepository.deleteById(id);
}

}

EnrollmentService

@Autowired
public EnrollmentRepository enrollmentRepository;

@Autowired
public StudentRepository studentRepository;

@Autowired
public CourseRepository courseRepository;
public Enrollment enrollStudentInACourse(Long studentId, Long courseId, Date enrollmentDate, String grade) {
   Optional<Student> student= studentRepository.findById(studentId);
   Optional<Course> course=courseRepository.findById(courseId);

   Enrollment enrollment= new Enrollment(student,course,enrollmentDate,grade);
   return enrollment;
}

public List<Enrollment> getAllEnrollments(){
    return enrollmentRepository.findAll();
}

public Optional<Enrollment> getEnrollmentForStudent(Long studentId){

   Optional<Enrollment> enrollment= enrollmentRepository.findByStudentId(studentId);
   return enrollment;
}

public Optional<Enrollment> getEnrollmentForCourse(Long courseId){

    Optional<Enrollment> enrollment= enrollmentRepository.findByCourseId(courseId);
    return enrollment;
}

public void deleteEnrollment(Long id){
    enrollmentRepository.deleteById(id);
}
public Enrollment updateEnrollment(Long id, UpdateEnrollmentDTO updatedEnrollment) {
    Optional<Enrollment> existingEnrollmentOptional = enrollmentRepository.findById(id);

    if (existingEnrollmentOptional.isPresent()) {
        Enrollment existingEnrollment= existingEnrollmentOptional.get();
        existingEnrollment.setStudent(Optional.ofNullable(updatedEnrollment.getS()));
        existingEnrollment.setCourse(Optional.ofNullable(updatedEnrollment.getC()));
        existingEnrollment.setEnrollmentDate(updatedEnrollment.getEnrollmentDate());
        existingEnrollment.setGrade(updatedEnrollment.getGrade());
        return enrollmentRepository.save(existingEnrollment);
    } else {
        return null;
    }
}

}

jinanabedalnabi commented 1 week ago

Controller

Course Controller

import jakarta.validation.Valid; 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.LocalDateTime; import java.util.List; import java.util.Optional;

@RestController @RequestMapping("/api/courses") public class CourseController {

@Autowired
private CourseService courseService;

@PostMapping
public ResponseEntity<ApiResponse<Course>> createCourse (@Valid @RequestBody CreateCourseDTO courseDTO){
    try {
        Course createdCourse = courseService.createCourse(courseDTO);
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, createdCourse, "Course created successfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to create Course : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }

}
@GetMapping
public ResponseEntity<ApiResponse<List<Course>>> getAllCourses() {
    try {
        List<Course> courses = courseService.getAllCourses();
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, courses, "courses listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to list courses: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));

    }
}

@GetMapping("/{id}")
public ResponseEntity<ApiResponse<Optional<Course>>> getCourseById(@PathVariable Long id) {
    try {
        Optional<Course> course = courseService.getCourseById(id);
        if (course != null) {
            return ResponseEntity.ok(new ApiResponse<>(true, course, "course retrieved successfully", HttpStatus.OK.value(), LocalDateTime.now()));
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, null, "course not found", HttpStatus.NOT_FOUND.value(), LocalDateTime.now()));
        }
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to retrieve course : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
    }
}

@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Course>> updateCourse(@PathVariable Long id,@Valid @RequestBody UpdateCourseDTO courseToBeUpdated){
    try {
        Course course = courseService.updateCourse(id, courseToBeUpdated);
        if (course != null) {
            return ResponseEntity.ok(new ApiResponse<>(true, course, "course  updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, null, "course  not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
        }
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to update course: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

@DeleteMapping("/{id}")
public ResponseEntity<ApiResponse<Void>> deleteCourse(@PathVariable Long id) {
    try {
        courseService.deleteCourse(id);
        return ResponseEntity.ok(new ApiResponse<>(true, null, "course deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to delete course: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

}

Student Controller

import jakarta.validation.Valid; 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.LocalDateTime; import java.util.List; import java.util.Optional;

@RestController @RequestMapping("/api/students") public class StudentController { @Autowired private StudentService studentService;

@PostMapping
public ResponseEntity<ApiResponse<Student>>  createStudent(@Valid @RequestBody CreateStudentDTO studentDTO){
    try {
        Student createdStudent = studentService.createStudent(studentDTO);
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, createdStudent, "Student created successfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to create student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }

}
@GetMapping
public ResponseEntity<ApiResponse<List<Student>>> getAllStudents() {
    try {
        List<Student> students = studentService.getAllStudent();
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, students, "Student listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to list students: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));

    }
}

@GetMapping("/{id}")
public ResponseEntity<ApiResponse<Optional<Student>>> getStudentById(@PathVariable Long id) {
    try {
        Optional<Student> student = studentService.getStudentById(id);
        if (student != null) {
            return ResponseEntity.ok(new ApiResponse<>(true, student, "Student retrieved successfully", HttpStatus.OK.value(), LocalDateTime.now()));
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, null, "Student not found", HttpStatus.NOT_FOUND.value(), LocalDateTime.now()));
        }
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to retrieve student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
    }
}

@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Student>> updateStudent(@PathVariable Long id,@Valid @RequestBody UpdateStudentDTO studentToBeUpdated){
    try {
        Student student = studentService.updateStudent(id, studentToBeUpdated);
        if (student != null) {
            return ResponseEntity.ok(new ApiResponse<>(true, student, "Student updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, null, "Student not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
        }
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to update student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

@DeleteMapping("/{id}")
public ResponseEntity<ApiResponse<Void>> deleteStudent(@PathVariable Long id) {
    try {
        studentService.deleteStudent(id);
        return ResponseEntity.ok(new ApiResponse<>(true, null, "Student deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to delete student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

} Enrollment Controller

import com.Jinan.Task4.DTO.ApiResponse; import com.Jinan.Task4.DTO.request.EnrollStudentINCourse; import com.Jinan.Task4.DTO.request.UpdateEnrollmentDTO; import com.Jinan.Task4.DTO.request.UpdateStudentDTO; import com.Jinan.Task4.Service.EnrollmentService; import com.Jinan.Task4.model.Enrollment; import com.Jinan.Task4.model.Student; import jakarta.validation.Valid; 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.LocalDateTime; import java.util.List; import java.util.Optional;

@RestController @RequestMapping("/api/enrollments") public class EnrollmentController { @Autowired private EnrollmentService enrollmentService;

@PostMapping
public ResponseEntity<ApiResponse<Enrollment>>  enrollStudentInACourse(@Valid @RequestBody EnrollStudentINCourse enrollStudent){
    try {
        Enrollment enrollment = enrollmentService.enrollStudentInACourse(enrollStudent.getStudentId(), enrollStudent.getCourseId(), enrollStudent.getEnrollmentDate(), enrollStudent.getGrade());

        return ResponseEntity.ok(new ApiResponse<>(true, enrollment, "enrolled successfully", HttpStatus.OK.value(), LocalDateTime.now()));
    }
    catch (Exception e) {
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(new ApiResponse<>(false, null, "Failed to enroll student : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}

}

@GetMapping
public ResponseEntity<ApiResponse<List<Enrollment>>> getAllEnrollmentss() {
    try {
        List<Enrollment> enrollments = enrollmentService.getAllEnrollments();
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, enrollments, "Enrollments listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to list enrollments: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));

    }
}

@GetMapping("/api/students/{studentId}/enrollments")
 public ResponseEntity<ApiResponse<Optional<Enrollment>>> getEnrollmentForStudent(@PathVariable Long studentId) {
    try {
        Optional<Enrollment> enrollment = enrollmentService.getEnrollmentForStudent(studentId);
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, enrollment, "student enrollment is get succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));

    }

}

@GetMapping("api/courses/{courseId}/enrollments")
public ResponseEntity<ApiResponse<Optional<Enrollment>>> getEnrollmentForCourse(@PathVariable Long courseId) {
    try {
        Optional<Enrollment> enrollment = enrollmentService.getEnrollmentForCourse(courseId);
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new ApiResponse<>(true, enrollment, "student enrollment is get succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));

    }

}

@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Enrollment>> updateEnrollment(@PathVariable Long id, @Valid @RequestBody UpdateEnrollmentDTO enrollmenToBeUpdated){
    try {
        Enrollment enrollment = enrollmentService.updateEnrollment(id, enrollmenToBeUpdated);
        if (enrollment != null) {
            return ResponseEntity.ok(new ApiResponse<>(true, enrollment, "Enrollment updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ApiResponse<>(false, null, "Enrollment not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
        }
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to update enrollment " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

@DeleteMapping("api/enrollments/{id}")
public ResponseEntity<ApiResponse<Void>> deleteEnrollment(@PathVariable Long id) {
    try {
        enrollmentService.deleteEnrollment(id);
        return ResponseEntity.ok(new ApiResponse<>(true, null, "Enrollment deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ApiResponse<>(false, null, "Failed to delete enrollment: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
    }
}

}