Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions src/main/java/org/unilab/uniplan/course/CourseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,40 @@
)
public class CourseController {

private final CourseService courseService;
private final CourseMapper courseMapper;
private final CourseWebFacade courseWebFacade;

@PostMapping
public ResponseEntity<CourseResponseDto> addCourse(@RequestBody @NotNull
public ResponseEntity<Void> addCourse(@RequestBody @NotNull
@Valid final CourseRequestDto courseRequestDTO) {
final CourseDto courseDTO = courseMapper.toInnerDto(courseRequestDTO);
return ResponseEntity.status(HttpStatus.CREATED)
.body(courseMapper.toResponseDto(courseService.createCourse(courseDTO)));
courseWebFacade.createCourse(courseRequestDTO);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@GetMapping("/major/{majorId}")
public List<CourseResponseDto> getCoursesByMajorId(@PathVariable @NotNull final UUID majorId) {
return courseMapper.toResponseDtoList(courseService.findAllByMajorId(majorId));
public ResponseEntity<List<CourseResponseDto>> getCoursesByMajorId(@PathVariable final UUID majorId) {
return ResponseEntity.ok(courseWebFacade.getCoursesByMajorId(majorId));
}

@GetMapping("/{id}")
public ResponseEntity<CourseResponseDto> getMajorById(@PathVariable @NotNull final UUID id) {
return ResponseEntity.ok(courseMapper.toResponseDto(courseService.findCourseById(id)));
public ResponseEntity<CourseResponseDto> getCourseById(@PathVariable final UUID id) {
return ResponseEntity.ok(courseWebFacade.getCourseById(id));
}

@GetMapping
public List<CourseResponseDto> getAllCourses() {
return courseMapper.toResponseDtoList(courseService.findAll());
public ResponseEntity<List<CourseResponseDto>> getAllCourses() {
return ResponseEntity.ok(courseWebFacade.getAllCourses());
}

@PutMapping("/{id}")
public ResponseEntity<CourseResponseDto> updateCourse(@PathVariable @NotNull final UUID id,
public ResponseEntity<Void> updateCourse(@PathVariable final UUID id,
@RequestBody @NotNull @Valid final CourseRequestDto courseRequestDTO) {
final CourseDto courseDTO = courseMapper.toInnerDto(courseRequestDTO);
return ResponseEntity.ok(courseMapper.toResponseDto(courseService.updateCourse(id, courseDTO)));
courseWebFacade.updateCourse(id, courseRequestDTO);
return ResponseEntity.noContent().build();
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteCourse(@PathVariable @NotNull final UUID id) {
courseService.deleteCourse(id);
public ResponseEntity<Void> deleteCourse(@PathVariable final UUID id) {
courseWebFacade.deleteCourse(id);
return ResponseEntity.noContent().build();
}
}
19 changes: 7 additions & 12 deletions src/main/java/org/unilab/uniplan/course/CourseMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,22 @@
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.unilab.uniplan.course.dto.CourseDto;
import org.unilab.uniplan.course.dto.CourseRequestDto;
import org.unilab.uniplan.course.dto.CourseResponseDto;

@Mapper
public interface CourseMapper {

@Mapping(target = "id", ignore = true)
@Mapping(source = "majorId", target = "major.id")
Course toEntity(CourseDto courseDto);

@Mapping(source = "major.id", target = "majorId")
CourseDto toDto(Course course);

@Mapping(source = "majorId", target = "major.id")
void updateEntityFromDto(CourseDto courseDto, @MappingTarget Course course);
Course toEntity(final CourseRequestDto courseRequestDto);

@Mapping(target = "id", ignore = true)
CourseDto toInnerDto(CourseRequestDto courseRequestDto);
@Mapping(source = "majorId", target = "major.id")
void updateEntityFromDto(final CourseRequestDto courserequestDto, @MappingTarget final Course course);

@Mapping(source = "majorId", target = "majorId")
CourseResponseDto toResponseDto(CourseDto courseDto);
@Mapping(source = "major.id", target = "majorId")
CourseResponseDto toResponseDto(final Course course);

List<CourseResponseDto> toResponseDtoList(List<CourseDto> courses);
List<CourseResponseDto> toResponseDtoList(final List<Course> courses);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
@Repository
public interface CourseRepository extends JpaRepository<Course, UUID> {

public List<Course> findAllByMajorId(UUID majorId);
List<Course> findAllByMajorId(UUID majorId);
}
66 changes: 17 additions & 49 deletions src/main/java/org/unilab/uniplan/course/CourseService.java
Original file line number Diff line number Diff line change
@@ -1,71 +1,39 @@
package org.unilab.uniplan.course;

import static org.unilab.uniplan.utils.ErrorConstants.COURSE_NOT_FOUND;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.unilab.uniplan.course.dto.CourseDto;
import org.unilab.uniplan.exception.ResourceNotFoundException;
import org.unilab.uniplan.common.model.BaseService;

@Service
@RequiredArgsConstructor
public class CourseService {
public class CourseService implements BaseService<Course> {

private final CourseRepository courseRepository;
private final CourseMapper courseMapper;

@Transactional
public CourseDto createCourse(final CourseDto courseDTO) {
final Course course = courseMapper.toEntity(courseDTO);
return saveEntityAndConvertToDto(course);
@Override
public void save(final Course entity) {
courseRepository.save(entity);
}

public CourseDto findCourseById(final UUID id) {
return courseRepository.findById(id)
.map(courseMapper::toDto)
.orElseThrow(() -> new ResourceNotFoundException(COURSE_NOT_FOUND.getMessage(
String.valueOf(id))));
@Override
public Optional<Course> getById(final UUID id) {
return courseRepository.findById(id);
}

public List<CourseDto> findAllByMajorId(final UUID majorId) {
return courseRepository.findAllByMajorId(majorId)
.stream()
.map(courseMapper::toDto).toList();
public List<Course> findAllByMajorId(final UUID majorId) {
return courseRepository.findAllByMajorId(majorId);
}

public List<CourseDto> findAll() {
return courseRepository.findAll()
.stream().map(courseMapper::toDto).toList();
@Override
public List<Course> getAll() {
return courseRepository.findAll();
}

@Transactional
public CourseDto updateCourse(final UUID id, final CourseDto courseDTO) {
return courseRepository.findById(id).map(
existingCourse -> updateEntityAndConvertToDto(
courseDTO,
existingCourse))
.orElseThrow(() -> new ResourceNotFoundException(COURSE_NOT_FOUND.getMessage(
String.valueOf(id))));
}

@Transactional
public void deleteCourse(final UUID id) {
final Course course = courseRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException(
COURSE_NOT_FOUND.getMessage(String.valueOf(id))));
courseRepository.delete(course);
}

private CourseDto updateEntityAndConvertToDto(final CourseDto dto,
final Course entity) {
courseMapper.updateEntityFromDto(dto, entity);
return saveEntityAndConvertToDto(entity);
}

private CourseDto saveEntityAndConvertToDto(final Course entity) {
final Course savedEntity = courseRepository.save(entity);
return courseMapper.toDto(savedEntity);
@Override
public void delete(final Course entity) {
courseRepository.delete(entity);
}
}
29 changes: 29 additions & 0 deletions src/main/java/org/unilab/uniplan/course/CourseValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.unilab.uniplan.course;

import static org.unilab.uniplan.utils.ErrorConstants.MAJOR_NOT_FOUND;

import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.unilab.uniplan.course.dto.CourseRequestDto;
import org.unilab.uniplan.exception.ResourceNotFoundException;
import org.unilab.uniplan.major.MajorRepository;

@Component
@RequiredArgsConstructor
public class CourseValidator {

private final MajorRepository majorRepository;

public void validate(final CourseRequestDto requestDto) {
validateMajorExists(requestDto.majorId());
}

private void validateMajorExists(final UUID majorId) {
if (!majorRepository.existsById(majorId)) {
throw new ResourceNotFoundException(
MAJOR_NOT_FOUND.getMessage(String.valueOf(majorId))
);
}
}
}
78 changes: 78 additions & 0 deletions src/main/java/org/unilab/uniplan/course/CourseWebFacade.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.unilab.uniplan.course;

import static org.unilab.uniplan.utils.ErrorConstants.COURSE_NOT_FOUND;

import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.unilab.uniplan.course.dto.CourseRequestDto;
import org.unilab.uniplan.course.dto.CourseResponseDto;
import org.unilab.uniplan.exception.ResourceNotFoundException;

@Component
@Slf4j
@RequiredArgsConstructor
public class CourseWebFacade {

private final CourseService courseService;
private final CourseMapper courseMapper;
private final CourseValidator courseValidator;

@Transactional
public void createCourse(final CourseRequestDto requestDto) {
courseValidator.validate(requestDto);

final Course course = courseMapper.toEntity(requestDto);
courseService.save(course);

log.info("Created course with ID: {}", course.getId());
}

@Transactional(readOnly = true)
public List<CourseResponseDto> getAllCourses() {
return courseMapper.toResponseDtoList(courseService.getAll());
}

@Transactional(readOnly = true)
public CourseResponseDto getCourseById(final UUID id) {
final Course course = getCourseOrThrow(id);

return courseMapper.toResponseDto(course);
}

@Transactional(readOnly = true)
public List<CourseResponseDto> getCoursesByMajorId(final UUID majorId) {
return courseMapper.toResponseDtoList(courseService.findAllByMajorId(majorId));
}

@Transactional
public void updateCourse(final UUID id,
final CourseRequestDto requestDto) {
courseValidator.validate(requestDto);

final Course course = getCourseOrThrow(id);
courseMapper.updateEntityFromDto(requestDto, course);
courseService.save(course);

log.info("Updated course with ID: {}", id);
}

@Transactional
public void deleteCourse(final UUID id) {
final Course course = getCourseOrThrow(id);

courseService.delete(course);

log.info("Deleted course with ID: {}", id);
}

private Course getCourseOrThrow(final UUID id) {
return courseService.getById(id)
.orElseThrow(() -> new ResourceNotFoundException(
COURSE_NOT_FOUND.getMessage(String.valueOf(id))
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;
import java.util.UUID;

public record CourseRequestDto(
UUID id,
@NotNull
@NotNull(message = "Major ID cannot be null")
UUID majorId,
@Positive
@Min(1)
@Max(20)
@Min(value = 1, message = "Course year must be at least 1")
@Max(value = 20, message = "Course year must be at least 1")
byte courseYear,
@NotNull
@Size(max = 100)
@NotBlank(message = "Course type is required")
@Max(value = 100, message = "Course type must be at most 100 characters")
String courseType,
@NotNull
@Size(max = 100)
@NotBlank(message = "Course subtype cannot be null")
@Max(value = 100, message = "Course subtype must be at most 100 characters")
String courseSubtype
) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
package org.unilab.uniplan.course.dto;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;
import java.util.UUID;

public record CourseResponseDto(
UUID id,
@NotNull
UUID majorId,
@Positive
@Min(1)
@Max(20)
byte courseYear,
@NotNull
@Size(max = 100)
String courseType,
@NotNull
@Size(max = 100)
String courseSubtype
) {

Expand Down
Loading
Loading