From 5a2598a833c5d574505bdc79889cf006baab0e27 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Tue, 7 Jul 2026 11:43:14 +0300 Subject: [PATCH 01/19] Remove internal dto, update mapper --- .../unilab/uniplan/room/RoomController.java | 1 - .../org/unilab/uniplan/room/RoomMapper.java | 20 ++++++------------- .../org/unilab/uniplan/room/RoomService.java | 1 - .../org/unilab/uniplan/room/dto/RoomDto.java | 19 ------------------ .../uniplan/room/dto/RoomResponseDto.java | 3 --- .../unilab/uniplan/room/RoomServiceTest.java | 1 - 6 files changed, 6 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/org/unilab/uniplan/room/dto/RoomDto.java diff --git a/src/main/java/org/unilab/uniplan/room/RoomController.java b/src/main/java/org/unilab/uniplan/room/RoomController.java index 20b3f1a6..d8eb1d7e 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomController.java +++ b/src/main/java/org/unilab/uniplan/room/RoomController.java @@ -18,7 +18,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import org.unilab.uniplan.room.dto.RoomDto; import org.unilab.uniplan.room.dto.RoomRequestDto; import org.unilab.uniplan.room.dto.RoomResponseDto; diff --git a/src/main/java/org/unilab/uniplan/room/RoomMapper.java b/src/main/java/org/unilab/uniplan/room/RoomMapper.java index a551abaf..c923d684 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomMapper.java +++ b/src/main/java/org/unilab/uniplan/room/RoomMapper.java @@ -4,29 +4,21 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; -import org.unilab.uniplan.room.dto.RoomDto; import org.unilab.uniplan.room.dto.RoomRequestDto; import org.unilab.uniplan.room.dto.RoomResponseDto; @Mapper public interface RoomMapper { - @Mapping(source = "faculty.id", target = "facultyId") - RoomDto toDto(final Room room); - @Mapping(source = "facultyId", target = "faculty.id") - Room toEntity(final RoomDto roomDto); - - @Mapping(target = "id", ignore = true) - RoomDto toInternalDto(final RoomRequestDto roomRequestDto); + Room toEntity(final RoomRequestDto roomRequestDto); - RoomResponseDto toResponseDto(final RoomDto roomDto); + @Mapping(target = "facultyId", source = "faculty.id") + RoomResponseDto toResponseDto(Room room); - List toDtoList(final List rooms); + List toResponseDtoList(final List rooms); - List toResponseDtoList(final List rooms); - - @Mapping(source = "roomDto.facultyId", target = "faculty.id") + @Mapping(source = "facultyId", target = "faculty.id") @Mapping(target = "id", ignore = true) - void updateEntityFromDto(final RoomDto roomDto, @MappingTarget final Room room); + void updateEntityFromDto(final RoomRequestDto roomRequestDto, @MappingTarget final Room room); } diff --git a/src/main/java/org/unilab/uniplan/room/RoomService.java b/src/main/java/org/unilab/uniplan/room/RoomService.java index 5dbd29ac..582a9d5b 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomService.java +++ b/src/main/java/org/unilab/uniplan/room/RoomService.java @@ -8,7 +8,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.room.dto.RoomDto; @Service @RequiredArgsConstructor diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomDto.java deleted file mode 100644 index 0acf52e4..00000000 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.unilab.uniplan.room.dto; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.util.UUID; - -public record RoomDto( - - UUID id, - - @NotNull(message = "Faculty ID cannot be null") - UUID facultyId, - - @NotNull(message = "Room number cannot be null") - @Size(max = 50, message = "Room number cannot exceed 50 characters") - String roomNumber -) { - -} diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java index b5cf53fe..184b1844 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java @@ -8,11 +8,8 @@ public record RoomResponseDto( UUID id, - @NotNull(message = "Faculty ID cannot be null") UUID facultyId, - @NotNull(message = "Room number cannot be null") - @Size(max = 50, message = "Room number cannot exceed 50 characters") String roomNumber ) { diff --git a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java index 26d1d931..1e56536d 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java @@ -18,7 +18,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.room.dto.RoomDto; @ExtendWith(MockitoExtension.class) class RoomServiceTest { From 81bd802beaa6cdd85a693a4fb64acef2daf80742 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Tue, 7 Jul 2026 11:48:03 +0300 Subject: [PATCH 02/19] Update roomService by implementing baseService --- .../org/unilab/uniplan/room/RoomService.java | 54 ++++++------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/unilab/uniplan/room/RoomService.java b/src/main/java/org/unilab/uniplan/room/RoomService.java index 582a9d5b..57a3b7f5 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomService.java +++ b/src/main/java/org/unilab/uniplan/room/RoomService.java @@ -3,62 +3,38 @@ import static org.unilab.uniplan.utils.ErrorConstants.ROOM_NOT_FOUND; import java.util.List; +import java.util.Optional; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.unilab.uniplan.common.model.BaseService; import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.room.dto.RoomRequestDto; @Service @RequiredArgsConstructor -public class RoomService { +public class RoomService implements BaseService { private final RoomRepository roomRepository; - private final RoomMapper roomMapper; - @Transactional - public RoomDto createRoom(final RoomDto roomDto) { - final Room room = roomMapper.toEntity(roomDto); - - return saveEntityAndConvertToDto(room); - } - - public List getAllRooms() { - return roomMapper.toDtoList(roomRepository.findAll()); + @Override + public void save(final Room room) { + roomRepository.save(room); } - public RoomDto getRoomById(final UUID id) { - return roomRepository.findById(id) - .map(roomMapper::toDto) - .orElseThrow(() -> new ResourceNotFoundException(ROOM_NOT_FOUND.getMessage( - String.valueOf(id)))); + @Override + public List getAll() { + return roomRepository.findAll(); } - @Transactional - public RoomDto updateRoom(final UUID id, final RoomDto roomDto) { - return roomRepository.findById(id) - .map(existingRoom -> updateEntityAndConvertToDto( - roomDto, - existingRoom)).orElseThrow(() -> new ResourceNotFoundException( - ROOM_NOT_FOUND.getMessage(String.valueOf(id)))); + @Override + public Optional getById(final UUID id) { + return roomRepository.findById(id); } - @Transactional - public void deleteRoom(final UUID id) { - final Room room = roomRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException( - ROOM_NOT_FOUND.getMessage(String.valueOf(id)))); + @Override + public void delete(final Room room) { roomRepository.delete(room); } - - private RoomDto updateEntityAndConvertToDto(final RoomDto dto, - final Room entity) { - roomMapper.updateEntityFromDto(dto, entity); - return saveEntityAndConvertToDto(entity); - } - - private RoomDto saveEntityAndConvertToDto(final Room entity) { - final Room savedEntity = roomRepository.save(entity); - return roomMapper.toDto(savedEntity); - } } From 8527924dc0f273812c638568ca8a0e4629831f0b Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Tue, 7 Jul 2026 11:58:26 +0300 Subject: [PATCH 03/19] Add room facade layer --- .../unilab/uniplan/room/RoomWebFacade.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/org/unilab/uniplan/room/RoomWebFacade.java diff --git a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java new file mode 100644 index 00000000..282ad7e9 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java @@ -0,0 +1,64 @@ +package org.unilab.uniplan.room; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.faculty.Faculty; +import org.unilab.uniplan.room.dto.RoomRequestDto; +import org.unilab.uniplan.room.dto.RoomResponseDto; +import java.util.List; +import java.util.UUID; + +import static org.unilab.uniplan.utils.ErrorConstants.FACULTY_NOT_FOUND; +import static org.unilab.uniplan.utils.ErrorConstants.ROOM_NOT_FOUND; + +@Component +@Slf4j +@RequiredArgsConstructor +public class RoomWebFacade { + + private RoomMapper roomMapper; + private RoomService roomService; + + private Room getRoomOrThrow(final UUID id) { + return roomService.getById(id) + .orElseThrow(() -> new ResourceNotFoundException(ROOM_NOT_FOUND.getMessage( + String.valueOf(id)))); + } + + @Transactional + public void saveRoom(RoomRequestDto roomRequestDto) { + Room room = roomMapper.toEntity(roomRequestDto); + roomService.save(room); + log.info("created room {} with ID: {}", + room.getRoomNumber(), + room.getId()); + } + + @Transactional(readOnly=true) + public List getAllRooms() { + return roomMapper.toResponseDtoList(roomService.getAll()); + } + + @Transactional + public void deleteRoom(final UUID id) { + final Room room = getRoomOrThrow(id); + roomService.delete(room); + log.info("deleted room with id {}", id); + } + + @Transactional(readOnly=true) + public RoomResponseDto getRoomById(final UUID id) { + final Room room = getRoomOrThrow(id); + return roomMapper.toResponseDto(room); + } + + @Transactional + public void updateRoom(final UUID id, final RoomRequestDto roomRequestDto) { + final Room room = getRoomOrThrow(id); + roomService.save(room); + log.info("updated room with id {}", id); + } +} From 5217de6184458d2cd369e785a7c662420af05cd5 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Tue, 7 Jul 2026 12:50:34 +0300 Subject: [PATCH 04/19] Update controller to use facade layer --- .../unilab/uniplan/room/RoomController.java | 27 ++--- .../unilab/uniplan/room/RoomWebFacade.java | 9 +- .../unilab/uniplan/room/RoomServiceTest.java | 103 ------------------ 3 files changed, 13 insertions(+), 126 deletions(-) diff --git a/src/main/java/org/unilab/uniplan/room/RoomController.java b/src/main/java/org/unilab/uniplan/room/RoomController.java index d8eb1d7e..55206cf6 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomController.java +++ b/src/main/java/org/unilab/uniplan/room/RoomController.java @@ -1,7 +1,5 @@ package org.unilab.uniplan.room; -import static org.springframework.http.ResponseEntity.ok; - import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -27,39 +25,34 @@ @Tag(name = "Rooms", description = "Manage classrooms and lecture halls, including room numbers and assigned faculties") public class RoomController { - private final RoomService roomService; - private final RoomMapper roomMapper; + private final RoomWebFacade roomWebFacade; @PostMapping - public ResponseEntity createRoom(@Valid @NotNull @RequestBody final RoomRequestDto roomRequestDto) { - final RoomDto roomDto = roomService.createRoom(roomMapper.toInternalDto(roomRequestDto)); - - return new ResponseEntity<>(roomMapper.toResponseDto(roomDto), HttpStatus.CREATED); + public ResponseEntity createRoom(@Valid @NotNull @RequestBody final RoomRequestDto roomRequestDto) { + roomWebFacade.createRoom(roomRequestDto); + return ResponseEntity.status(HttpStatus.CREATED).build(); } @GetMapping - public List getAllRooms() { - return roomMapper.toResponseDtoList(roomService.getAllRooms()); + public ResponseEntity> getAllRooms() { + return ResponseEntity.ok(roomWebFacade.getAllRooms()); } @GetMapping("/{id}") public ResponseEntity getRoomById(@PathVariable final UUID id) { - final RoomDto roomDto = roomService.getRoomById(id); - - return ok(roomMapper.toResponseDto(roomDto)); + return ResponseEntity.ok(roomWebFacade.getRoomById(id)); } @PutMapping("/{id}") public ResponseEntity updateRoom(@PathVariable final UUID id, @Valid @NotNull @RequestBody final RoomRequestDto roomRequestDto) { - final RoomDto internalDto = roomMapper.toInternalDto(roomRequestDto); - - return ok(roomMapper.toResponseDto(roomService.updateRoom(id, internalDto))); + roomWebFacade.updateRoom(id, roomRequestDto); + return ResponseEntity.noContent().build(); } @DeleteMapping("/{id}") public ResponseEntity deleteRoom(@PathVariable final UUID id) { - roomService.deleteRoom(id); + roomWebFacade.deleteRoom(id); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java index 282ad7e9..7e04990f 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java +++ b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java @@ -5,13 +5,10 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.faculty.Faculty; import org.unilab.uniplan.room.dto.RoomRequestDto; import org.unilab.uniplan.room.dto.RoomResponseDto; import java.util.List; import java.util.UUID; - -import static org.unilab.uniplan.utils.ErrorConstants.FACULTY_NOT_FOUND; import static org.unilab.uniplan.utils.ErrorConstants.ROOM_NOT_FOUND; @Component @@ -19,8 +16,8 @@ @RequiredArgsConstructor public class RoomWebFacade { - private RoomMapper roomMapper; - private RoomService roomService; + private final RoomMapper roomMapper; + private final RoomService roomService; private Room getRoomOrThrow(final UUID id) { return roomService.getById(id) @@ -29,7 +26,7 @@ private Room getRoomOrThrow(final UUID id) { } @Transactional - public void saveRoom(RoomRequestDto roomRequestDto) { + public void createRoom(RoomRequestDto roomRequestDto) { Room room = roomMapper.toEntity(roomRequestDto); roomService.save(room); log.info("created room {} with ID: {}", diff --git a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java index 1e56536d..9ad76785 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java @@ -22,108 +22,5 @@ @ExtendWith(MockitoExtension.class) class RoomServiceTest { - @Mock - private RoomRepository roomRepository; - @Mock - private RoomMapper roomMapper; - - @InjectMocks - private RoomService roomService; - - private UUID id; - private UUID facultyId; - private RoomDto dto; - private Room entity; - - @BeforeEach - void setUp() { - id = UUID.randomUUID(); - facultyId = UUID.randomUUID(); - dto = new RoomDto(id, facultyId, "101"); - entity = new Room(); - } - - @Test - void testCreateRoomShouldSaveAndReturnDto() { - when(roomMapper.toEntity(dto)).thenReturn(entity); - when(roomRepository.save(entity)).thenReturn(entity); - when(roomMapper.toDto(entity)).thenReturn(dto); - - RoomDto result = roomService.createRoom(dto); - - assertEquals(dto, result); - } - - @Test - void testGetAllRoomsShouldReturnListOfRoomDtos() { - List entities = List.of(entity); - List dtos = List.of(dto); - - when(roomRepository.findAll()).thenReturn(entities); - when(roomMapper.toDtoList(entities)).thenReturn(dtos); - - List result = roomService.getAllRooms(); - - assertEquals(dtos, result); - } - - @Test - void testGetRoomByIdShouldReturnRoomDtoIfFound() { - when(roomRepository.findById(id)).thenReturn(Optional.of(entity)); - when(roomMapper.toDto(entity)).thenReturn(dto); - - RoomDto result = roomService.getRoomById(id); - - assertEquals(dto, result); - } - - @Test - void testGetRoomByIdShouldReturnEmptyOptionalIfRoomNotFound() { - when(roomRepository.findById(id)).thenReturn(Optional.empty()); - - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> roomService.getRoomById(id)); - - assertTrue(exception.getMessage().contains(String.valueOf(id))); - } - - @Test - void testUpdateRoomShouldUpdateAndReturnDtoIfFound() { - when(roomRepository.findById(id)).thenReturn(Optional.of(entity)); - doAnswer(invocation -> null).when(roomMapper).updateEntityFromDto(dto, entity); - when(roomRepository.save(entity)).thenReturn(entity); - when(roomMapper.toDto(entity)).thenReturn(dto); - - RoomDto result = roomService.updateRoom(id, dto); - - assertEquals(dto, result); - } - - @Test - void testUpdateRoomShouldReturnEmptyOptionalIfNotFound() { - when(roomRepository.findById(id)).thenReturn(Optional.empty()); - - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> roomService.updateRoom(id, dto)); - - assertTrue(exception.getMessage().contains(String.valueOf(id))); - } - - @Test - void testDeleteRoomShouldDeleteRoomIfFound() { - when(roomRepository.findById(id)).thenReturn(Optional.of(entity)); - doAnswer(invocation -> null).when(roomRepository).delete(entity); - - assertDoesNotThrow(() -> roomService.deleteRoom(id)); - verify(roomRepository).delete(entity); - } - - @Test - void testDeleteRoomShouldThrowIfNotFound() { - when(roomRepository.findById(id)).thenReturn(Optional.empty()); - - ResourceNotFoundException exception = assertThrows(ResourceNotFoundException.class, () -> - roomService.deleteRoom(id)); - - assertTrue(exception.getMessage().contains(String.valueOf(id))); - } } From cd5b74c8d15b58ffde706c9a1d645dd589bd58a0 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Wed, 8 Jul 2026 09:49:30 +0300 Subject: [PATCH 05/19] Add tests for room service --- .../uniplan/room/dto/RoomResponseDto.java | 2 - .../unilab/uniplan/room/RoomServiceTest.java | 55 +++++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java index 184b1844..8e243f2e 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java @@ -1,7 +1,5 @@ package org.unilab.uniplan.room.dto; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; import java.util.UUID; public record RoomResponseDto( diff --git a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java index 9ad76785..58e3736f 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomServiceTest.java @@ -1,10 +1,6 @@ package org.unilab.uniplan.room; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -17,10 +13,59 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.unilab.uniplan.exception.ResourceNotFoundException; @ExtendWith(MockitoExtension.class) class RoomServiceTest { + @Mock + private RoomRepository roomRepository; + @InjectMocks + private RoomService roomService; + private Room room; + private UUID id; + + @BeforeEach + void setUp() { + id = UUID.randomUUID(); + room = new Room(); + } + + @Test + void save_shouldSaveEntity() { + when(roomRepository.save(room)).thenReturn(room); + + roomService.save(room); + + verify(roomRepository).save(room); + } + + @Test + void findAll_shouldReturnListOfEntities() { + List rooms = List.of(room); + when(roomRepository.findAll()).thenReturn(List.of(room)); + + List result = roomService.getAll(); + + verify(roomRepository).findAll(); + assertEquals(result, rooms); + } + + @Test + void findById_shouldReturnEntity_whenRoomExists() { + Optional expected = Optional.of(room); + when(roomRepository.findById(id)).thenReturn(expected); + + Optional result = roomService.getById(id); + + verify(roomRepository).findById(id); + assertEquals(expected, result); + } + + @Test + void delete_shouldDeleteEntity_whenFacultyExists() { + roomService.delete(room); + + verify(roomRepository).delete(room); + } } From 93be8fa46200f6c1d632da7e84df302d333e9456 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Wed, 8 Jul 2026 10:25:54 +0300 Subject: [PATCH 06/19] Add tests for roomMapper --- .../unilab/uniplan/room/RoomMapperTest.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/test/java/org/unilab/uniplan/room/RoomMapperTest.java diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java new file mode 100644 index 00000000..c7045662 --- /dev/null +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -0,0 +1,97 @@ +package org.unilab.uniplan.room; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.unilab.uniplan.faculty.Faculty; +import org.unilab.uniplan.room.dto.RoomRequestDto; +import org.unilab.uniplan.room.dto.RoomResponseDto; +import org.unilab.uniplan.university.University; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class RoomMapperTest { + + private final RoomMapper roomMapper = new RoomMapperImpl(); + private Room room1; + private Room room2; + private RoomRequestDto roomRequestDto; + private RoomResponseDto roomResponseDto1; + private RoomResponseDto roomResponseDto2; + + private String roomNumber1; + private UUID facultyId; + + @BeforeEach + void setUp() { + facultyId = UUID.randomUUID(); + + University university = new University("Sofia University", + "Sofia, Bulgaria", + (short) 1888, + "NEAA", + "https://uni-sofia.bg" + ); + Faculty faculty = new Faculty(university, "FMI", "Faculty Name"); + faculty.setId(facultyId); + roomNumber1 = "111"; + String roomNumber2 = "222"; + room1 = new Room(faculty, roomNumber1); + room1.setId(UUID.randomUUID()); + room2 = new Room(faculty, roomNumber2); + room2.setId(UUID.randomUUID()); + roomRequestDto = new RoomRequestDto(facultyId, roomNumber1); + roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1); + roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2); + + } + + @Test + void toEntity_shouldMapAllFieldsAndIgnoreId_whenRequestDtoIsValid() { + final Room result = roomMapper.toEntity(roomRequestDto); + assertThat(result.getFaculty().getId()).isEqualTo(facultyId); + assertThat(result.getRoomNumber()).isEqualTo(roomNumber1); + assertThat(result.getId()).isNull(); + } + + @Test + void toResponseDto_shouldMapAllFields_whenFacultyIsValid() { + RoomResponseDto result = roomMapper.toResponseDto(room1); + assertThat(result.id()).isEqualTo(room1.getId()); + assertThat(result.facultyId()).isEqualTo(facultyId); + assertThat(result.roomNumber()).isEqualTo(roomNumber1); + } + + @Test + void toResponseDtoList_shouldMapAllElements_whenListIsNotEmpty() { + List rooms = List.of(room1, room2); + List results = roomMapper.toResponseDtoList(rooms); + + assertThat(results.size()).isEqualTo(2); + assertThat(results.get(0)).isEqualTo(roomResponseDto1); + assertThat(results.get(1)).isEqualTo(roomResponseDto2); + } + + @Test + void toResponseDtoList_shouldReturnEmptyList_whenListIsEmpty() { + List rooms = List.of(); + List results = roomMapper.toResponseDtoList(rooms); + + assertThat(results).isEmpty(); + } + + @Test + void updateEntity_shouldUpdateAllFields_whenRequestDtoIsValid() { + roomMapper.updateEntityFromDto(roomRequestDto, room2); + assertThat(room2.getRoomNumber()).isEqualTo(roomNumber1); + } + + @Test + void updateEntity_shouldNotChangeId_whenUpdating() { + UUID id = room2.getId(); + roomMapper.updateEntityFromDto(roomRequestDto, room2); + assertThat(room2.getId()).isEqualTo(id); + } +} \ No newline at end of file From 5745b7711c4a830a8e3adbf36939093f2526d30f Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Wed, 8 Jul 2026 11:16:41 +0300 Subject: [PATCH 07/19] Add tests for RoomWebFacade --- .../unilab/uniplan/room/RoomWebFacade.java | 1 + .../uniplan/room/RoomWebFacadeTest.java | 143 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java diff --git a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java index 7e04990f..706e2f7b 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java +++ b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java @@ -55,6 +55,7 @@ public RoomResponseDto getRoomById(final UUID id) { @Transactional public void updateRoom(final UUID id, final RoomRequestDto roomRequestDto) { final Room room = getRoomOrThrow(id); + roomMapper.updateEntityFromDto(roomRequestDto, room); roomService.save(room); log.info("updated room with id {}", id); } diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java new file mode 100644 index 00000000..a3dd4b96 --- /dev/null +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -0,0 +1,143 @@ +package org.unilab.uniplan.room; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.faculty.Faculty; +import org.unilab.uniplan.room.dto.RoomRequestDto; +import org.unilab.uniplan.room.dto.RoomResponseDto; +import org.unilab.uniplan.university.University; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class RoomWebFacadeTest { + + @Mock + private RoomMapper roomMapper; + @Mock + private RoomService roomService; + @InjectMocks + private RoomWebFacade roomWebFacade; + private RoomRequestDto requestDto; + private Room entity; + private RoomResponseDto responseDto; + private UUID id; + + @BeforeEach + void setUp() { + id = UUID.randomUUID(); + UUID facultyId = UUID.randomUUID(); + University university = new University("Sofia University", + "Sofia, Bulgaria", + (short) 1888, + "NEAA", + "https://uni-sofia.bg" + ); + Faculty faculty = new Faculty(university, "FMI", "Faculty Name"); + faculty.setId(facultyId); + String roomNumber = "111"; + requestDto = new RoomRequestDto(facultyId, "222"); + entity = new Room(faculty, roomNumber); + entity.setId(id); + responseDto = new RoomResponseDto(id, facultyId, roomNumber); + } + + @Test + void createRoom_shouldSaveRoom_whenRequestIsValid() { + when(roomMapper.toEntity(requestDto)).thenReturn(entity); + + roomWebFacade.createRoom(requestDto); + + final var inOrder = inOrder(roomMapper, roomService); + inOrder.verify(roomMapper).toEntity(requestDto); + inOrder.verify(roomService).save(entity); + } + + @Test + void getAllRooms_shouldReturnListOfResponseDtos() { + List rooms = List.of(responseDto); + List roomEntities=List.of(entity); + when(roomService.getAll()).thenReturn(roomEntities); + when(roomMapper.toResponseDtoList(roomEntities)) + .thenReturn(rooms); + + List results = roomWebFacade.getAllRooms(); + + assertEquals(rooms, results); + verify(roomService).getAll(); + verify(roomMapper).toResponseDtoList(roomEntities); + } + + @Test + void deleteRoom_shouldDeleteRoom_whenRoomExists() { + when(roomService.getById(id)).thenReturn(Optional.of(entity)); + + roomWebFacade.deleteRoom(entity.getId()); + + verify(roomService).delete(entity); + } + + @Test + void deleteRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { + when(roomService.getById(id)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> roomWebFacade.deleteRoom(id)) + .isInstanceOf(ResourceNotFoundException.class) + .hasMessageContaining(id.toString()); + } + + @Test + void getRoomById_shouldReturnResponseDto_whenRoomExists() { + when(roomService.getById(id)).thenReturn(Optional.of(entity)); + when(roomMapper.toResponseDto(entity)).thenReturn(responseDto); + + RoomResponseDto result = roomWebFacade.getRoomById(id); + + assertThat(result.roomNumber()).isEqualTo(entity.getRoomNumber()); + verify(roomService).getById(id); + verify(roomMapper).toResponseDto(entity); + } + + @Test + void getRoomById_shouldThrowResourceNotFoundException_whenRoomNotFound() { + when(roomService.getById(id)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> roomWebFacade.getRoomById(id)) + .isInstanceOf(ResourceNotFoundException.class) + .hasMessageContaining(id.toString()); + verify(roomService).getById(id); + } + + @Test + void updateRoom_shouldUpdateRoom_whenRoomExists() { + when(roomService.getById(id)).thenReturn(Optional.of(entity)); + + roomWebFacade.updateRoom(id, requestDto); + + verify(roomMapper).updateEntityFromDto(requestDto, entity); + verify(roomService).save(entity); + } + + @Test + void updateRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { + when(roomService.getById(id)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> roomWebFacade.updateRoom(id, requestDto)) + .isInstanceOf(ResourceNotFoundException.class) + .hasMessageContaining(id.toString()); + } +} From f8fc9aa99ce9542e618dbc43826ca83cbc977c8d Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Wed, 15 Jul 2026 15:14:30 +0300 Subject: [PATCH 08/19] Include category in room response --- .../unilab/uniplan/room/RoomRepository.java | 32 +++++++++++++++++++ .../org/unilab/uniplan/room/RoomService.java | 9 ++++++ .../unilab/uniplan/room/RoomWebFacade.java | 11 ++++--- .../uniplan/room/dto/RoomResponseDto.java | 7 ++-- .../roomcategory/RoomCategoryRepository.java | 4 ++- .../unilab/uniplan/room/RoomMapperTest.java | 4 +-- .../uniplan/room/RoomWebFacadeTest.java | 4 +-- 7 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/unilab/uniplan/room/RoomRepository.java b/src/main/java/org/unilab/uniplan/room/RoomRepository.java index 0597aa71..62dcc1a8 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomRepository.java +++ b/src/main/java/org/unilab/uniplan/room/RoomRepository.java @@ -1,10 +1,42 @@ package org.unilab.uniplan.room; + +import java.util.List; +import java.util.Optional; import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.unilab.uniplan.room.dto.RoomResponseDto; @Repository public interface RoomRepository extends JpaRepository { + @Query(""" + SELECT new org.unilab.uniplan.room.dto.RoomResponseDto( + r.id, + r.faculty.id, + r.roomNumber, + c.id + ) + FROM Room r + JOIN RoomCategory rc ON rc.room = r + JOIN rc.category c + """) + List findAllRoomResponses(); + + @Query(""" + SELECT new org.unilab.uniplan.room.dto.RoomResponseDto( + r.id, + r.faculty.id, + r.roomNumber, + c.id + ) + FROM RoomCategory rc + JOIN rc.room r + JOIN rc.category c + WHERE r.id = :id + """) + Optional findRoomResponseById(@Param("id") UUID id); } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/room/RoomService.java b/src/main/java/org/unilab/uniplan/room/RoomService.java index 57a3b7f5..ee8074e1 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomService.java +++ b/src/main/java/org/unilab/uniplan/room/RoomService.java @@ -11,6 +11,7 @@ import org.unilab.uniplan.common.model.BaseService; import org.unilab.uniplan.exception.ResourceNotFoundException; import org.unilab.uniplan.room.dto.RoomRequestDto; +import org.unilab.uniplan.room.dto.RoomResponseDto; @Service @RequiredArgsConstructor @@ -37,4 +38,12 @@ public Optional getById(final UUID id) { public void delete(final Room room) { roomRepository.delete(room); } + + public List getAllRoomResponses() { + return roomRepository.findAllRoomResponses(); + } + + public Optional getRoomResponseById(final UUID id) { + return roomRepository.findRoomResponseById(id); + } } diff --git a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java index 706e2f7b..b2cab683 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java +++ b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java @@ -34,9 +34,9 @@ public void createRoom(RoomRequestDto roomRequestDto) { room.getId()); } - @Transactional(readOnly=true) + @Transactional(readOnly = true) public List getAllRooms() { - return roomMapper.toResponseDtoList(roomService.getAll()); + return roomService.getAllRoomResponses(); } @Transactional @@ -46,10 +46,11 @@ public void deleteRoom(final UUID id) { log.info("deleted room with id {}", id); } - @Transactional(readOnly=true) + @Transactional(readOnly = true) public RoomResponseDto getRoomById(final UUID id) { - final Room room = getRoomOrThrow(id); - return roomMapper.toResponseDto(room); + return roomService.getRoomResponseById(id) + .orElseThrow(() -> new ResourceNotFoundException(ROOM_NOT_FOUND.getMessage( + String.valueOf(id)))); } @Transactional diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java index 8e243f2e..e0a2df5b 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java @@ -8,7 +8,8 @@ public record RoomResponseDto( UUID facultyId, - String roomNumber -) { + String roomNumber, -} + UUID categoryId + +) { } diff --git a/src/main/java/org/unilab/uniplan/roomcategory/RoomCategoryRepository.java b/src/main/java/org/unilab/uniplan/roomcategory/RoomCategoryRepository.java index 8f8a1f2c..00957015 100644 --- a/src/main/java/org/unilab/uniplan/roomcategory/RoomCategoryRepository.java +++ b/src/main/java/org/unilab/uniplan/roomcategory/RoomCategoryRepository.java @@ -1,9 +1,11 @@ package org.unilab.uniplan.roomcategory; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; @Repository public interface RoomCategoryRepository extends JpaRepository { - } \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index c7045662..9d4122ab 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -13,7 +13,7 @@ public class RoomMapperTest { - +/* private final RoomMapper roomMapper = new RoomMapperImpl(); private Room room1; private Room room2; @@ -93,5 +93,5 @@ void updateEntity_shouldNotChangeId_whenUpdating() { UUID id = room2.getId(); roomMapper.updateEntityFromDto(roomRequestDto, room2); assertThat(room2.getId()).isEqualTo(id); - } + }*/ } \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java index a3dd4b96..7190b99e 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -25,7 +25,7 @@ @ExtendWith(MockitoExtension.class) public class RoomWebFacadeTest { - +/* @Mock private RoomMapper roomMapper; @Mock @@ -139,5 +139,5 @@ void updateRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { assertThatThrownBy(() -> roomWebFacade.updateRoom(id, requestDto)) .isInstanceOf(ResourceNotFoundException.class) .hasMessageContaining(id.toString()); - } + }*/ } From 18a22b879a8d8682a61b0c678d571fa8f5219ca6 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Mon, 20 Jul 2026 12:08:18 +0300 Subject: [PATCH 09/19] Change to left join instead of inner --- .../java/org/unilab/uniplan/room/RoomRepository.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/unilab/uniplan/room/RoomRepository.java b/src/main/java/org/unilab/uniplan/room/RoomRepository.java index 62dcc1a8..1bd453b6 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomRepository.java +++ b/src/main/java/org/unilab/uniplan/room/RoomRepository.java @@ -20,8 +20,8 @@ public interface RoomRepository extends JpaRepository { c.id ) FROM Room r - JOIN RoomCategory rc ON rc.room = r - JOIN rc.category c + LEFT JOIN RoomCategory rc ON rc.room = r + LEFT JOIN rc.category c """) List findAllRoomResponses(); @@ -32,9 +32,9 @@ public interface RoomRepository extends JpaRepository { r.roomNumber, c.id ) - FROM RoomCategory rc - JOIN rc.room r - JOIN rc.category c + FROM Room r + LEFT JOIN RoomCategory rc ON rc.room = r + LEFT JOIN rc.category c WHERE r.id = :id """) Optional findRoomResponseById(@Param("id") UUID id); From 2109a9e0dbe22e0acfae129033bbd253058023a2 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Mon, 20 Jul 2026 13:19:43 +0300 Subject: [PATCH 10/19] Use Criteria API instead of jpql in room repository --- .../uniplan/room/CustomRoomRepository.java | 14 ++++ .../room/CustomRoomRepositoryImpl.java | 77 +++++++++++++++++++ .../unilab/uniplan/room/RoomRepository.java | 35 +-------- 3 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java create mode 100644 src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java diff --git a/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java b/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java new file mode 100644 index 00000000..0202cda3 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java @@ -0,0 +1,14 @@ +package org.unilab.uniplan.room; + +import org.springframework.data.repository.query.Param; +import org.unilab.uniplan.room.dto.RoomResponseDto; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface CustomRoomRepository { + + List findAllRoomResponses(); + + Optional findRoomResponseById(@Param("id") UUID id); +} diff --git a/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java new file mode 100644 index 00000000..1ddc4014 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java @@ -0,0 +1,77 @@ +package org.unilab.uniplan.room; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.hibernate.query.common.JoinType; +import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaCriteriaQuery; +import org.hibernate.query.criteria.JpaEntityJoin; +import org.hibernate.query.criteria.JpaRoot; +import org.springframework.data.repository.query.Param; +import org.unilab.uniplan.category.Category; +import org.unilab.uniplan.room.dto.RoomResponseDto; +import org.unilab.uniplan.roomcategory.RoomCategory; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class CustomRoomRepositoryImpl implements CustomRoomRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findAllRoomResponses() { + HibernateCriteriaBuilder cb = (HibernateCriteriaBuilder) entityManager.getCriteriaBuilder(); + + JpaCriteriaQuery query = cb.createQuery(RoomResponseDto.class); + + JpaRoot room = query.from(Room.class); + + JpaEntityJoin roomCategory = + room.join(RoomCategory.class, JoinType.LEFT); + roomCategory.on(cb.equal(roomCategory.get("room"), room)); + + JpaEntityJoin category = + roomCategory.join(Category.class, JoinType.LEFT); + category.on(cb.equal(category, roomCategory.get("category"))); + + query.select(cb.construct( + RoomResponseDto.class, + room.get("id"), + room.get("faculty").get("id"), + room.get("roomNumber"), + category.get("id") + )); + + return entityManager.createQuery(query).getResultList(); + } + + @Override + public Optional findRoomResponseById(UUID id) { + HibernateCriteriaBuilder cb = (HibernateCriteriaBuilder) entityManager.getCriteriaBuilder(); + + JpaCriteriaQuery query = cb.createQuery(RoomResponseDto.class); + + JpaRoot room = query.from(Room.class); + JpaEntityJoin roomCategory = + room.join(RoomCategory.class, JoinType.LEFT); + roomCategory.on(cb.equal(roomCategory.get("room"), room)); + + JpaEntityJoin category = + roomCategory.join(Category.class, JoinType.LEFT); + category.on(cb.equal(category, roomCategory.get("category"))); + + query.select(cb.construct( + RoomResponseDto.class, + room.get("id"), + room.get("faculty").get("id"), + room.get("roomNumber"), + category.get("id") + )).where(cb.equal(room.get("id"), id)); + + return entityManager.createQuery(query) + .getResultStream() + .findFirst(); + } +} \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/room/RoomRepository.java b/src/main/java/org/unilab/uniplan/room/RoomRepository.java index 1bd453b6..268d42de 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomRepository.java +++ b/src/main/java/org/unilab/uniplan/room/RoomRepository.java @@ -1,42 +1,9 @@ package org.unilab.uniplan.room; - -import java.util.List; -import java.util.Optional; import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import org.unilab.uniplan.room.dto.RoomResponseDto; @Repository -public interface RoomRepository extends JpaRepository { - @Query(""" - SELECT new org.unilab.uniplan.room.dto.RoomResponseDto( - r.id, - r.faculty.id, - r.roomNumber, - c.id - ) - FROM Room r - LEFT JOIN RoomCategory rc ON rc.room = r - LEFT JOIN rc.category c - """) - List findAllRoomResponses(); - - @Query(""" - SELECT new org.unilab.uniplan.room.dto.RoomResponseDto( - r.id, - r.faculty.id, - r.roomNumber, - c.id - ) - FROM Room r - LEFT JOIN RoomCategory rc ON rc.room = r - LEFT JOIN rc.category c - WHERE r.id = :id - """) - Optional findRoomResponseById(@Param("id") UUID id); - +public interface RoomRepository extends JpaRepository, CustomRoomRepository { } \ No newline at end of file From 01bbc6c664caac66898ce766e17a46171b267712 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Mon, 20 Jul 2026 13:26:08 +0300 Subject: [PATCH 11/19] Update mapper test --- .../org/unilab/uniplan/room/RoomMapperTest.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index 9d4122ab..a658ca0b 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -13,7 +13,7 @@ public class RoomMapperTest { -/* + private final RoomMapper roomMapper = new RoomMapperImpl(); private Room room1; private Room room2; @@ -27,7 +27,6 @@ public class RoomMapperTest { @BeforeEach void setUp() { facultyId = UUID.randomUUID(); - University university = new University("Sofia University", "Sofia, Bulgaria", (short) 1888, @@ -43,8 +42,8 @@ void setUp() { room2 = new Room(faculty, roomNumber2); room2.setId(UUID.randomUUID()); roomRequestDto = new RoomRequestDto(facultyId, roomNumber1); - roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1); - roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2); + roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1,null); + roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2,null); } @@ -93,5 +92,12 @@ void updateEntity_shouldNotChangeId_whenUpdating() { UUID id = room2.getId(); roomMapper.updateEntityFromDto(roomRequestDto, room2); assertThat(room2.getId()).isEqualTo(id); - }*/ + } + + @Test + void toResponseDto_shouldSetCategoryIdToNull_whenMappingFromRoomEntity() { + RoomResponseDto result = roomMapper.toResponseDto(room1); + + assertThat(result.categoryId()).isNull(); + } } \ No newline at end of file From c1969bc898a317653bb5099f3d252490806b2fd7 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Mon, 20 Jul 2026 13:40:23 +0300 Subject: [PATCH 12/19] Update room web facade tests --- .../uniplan/room/RoomWebFacadeTest.java | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java index 7190b99e..c99d6dfa 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -25,7 +25,6 @@ @ExtendWith(MockitoExtension.class) public class RoomWebFacadeTest { -/* @Mock private RoomMapper roomMapper; @Mock @@ -36,11 +35,13 @@ public class RoomWebFacadeTest { private Room entity; private RoomResponseDto responseDto; private UUID id; +private UUID categoryId; @BeforeEach void setUp() { id = UUID.randomUUID(); UUID facultyId = UUID.randomUUID(); + categoryId = UUID.randomUUID(); University university = new University("Sofia University", "Sofia, Bulgaria", (short) 1888, @@ -53,7 +54,7 @@ void setUp() { requestDto = new RoomRequestDto(facultyId, "222"); entity = new Room(faculty, roomNumber); entity.setId(id); - responseDto = new RoomResponseDto(id, facultyId, roomNumber); + responseDto = new RoomResponseDto(id, facultyId, roomNumber, categoryId); } @Test @@ -70,56 +71,41 @@ void createRoom_shouldSaveRoom_whenRequestIsValid() { @Test void getAllRooms_shouldReturnListOfResponseDtos() { List rooms = List.of(responseDto); - List roomEntities=List.of(entity); - when(roomService.getAll()).thenReturn(roomEntities); - when(roomMapper.toResponseDtoList(roomEntities)) - .thenReturn(rooms); + when(roomService.getAllRoomResponses()).thenReturn(rooms); List results = roomWebFacade.getAllRooms(); assertEquals(rooms, results); - verify(roomService).getAll(); - verify(roomMapper).toResponseDtoList(roomEntities); + assertThat(results.getFirst().categoryId()).isEqualTo(categoryId); + verify(roomService).getAllRoomResponses(); } @Test - void deleteRoom_shouldDeleteRoom_whenRoomExists() { - when(roomService.getById(id)).thenReturn(Optional.of(entity)); + void getRoomById_shouldReturnResponseDto_whenRoomExists() { + when(roomService.getRoomResponseById(id)).thenReturn(Optional.of(responseDto)); - roomWebFacade.deleteRoom(entity.getId()); + RoomResponseDto result = roomWebFacade.getRoomById(id); - verify(roomService).delete(entity); + assertEquals(result, responseDto); + verify(roomService).getRoomResponseById(id); } @Test - void deleteRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { - when(roomService.getById(id)).thenReturn(Optional.empty()); - - assertThatThrownBy(() -> roomWebFacade.deleteRoom(id)) - .isInstanceOf(ResourceNotFoundException.class) - .hasMessageContaining(id.toString()); - } - - @Test - void getRoomById_shouldReturnResponseDto_whenRoomExists() { + void deleteRoom_shouldDeleteRoom_whenRoomExists() { when(roomService.getById(id)).thenReturn(Optional.of(entity)); - when(roomMapper.toResponseDto(entity)).thenReturn(responseDto); - RoomResponseDto result = roomWebFacade.getRoomById(id); + roomWebFacade.deleteRoom(entity.getId()); - assertThat(result.roomNumber()).isEqualTo(entity.getRoomNumber()); - verify(roomService).getById(id); - verify(roomMapper).toResponseDto(entity); + verify(roomService).delete(entity); } @Test - void getRoomById_shouldThrowResourceNotFoundException_whenRoomNotFound() { + void deleteRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { when(roomService.getById(id)).thenReturn(Optional.empty()); - assertThatThrownBy(() -> roomWebFacade.getRoomById(id)) + assertThatThrownBy(() -> roomWebFacade.deleteRoom(id)) .isInstanceOf(ResourceNotFoundException.class) .hasMessageContaining(id.toString()); - verify(roomService).getById(id); } @Test @@ -139,5 +125,5 @@ void updateRoom_shouldThrowResourceNotFoundException_whenRoomNotFound() { assertThatThrownBy(() -> roomWebFacade.updateRoom(id, requestDto)) .isInstanceOf(ResourceNotFoundException.class) .hasMessageContaining(id.toString()); - }*/ + } } From 68610f887302286723c037d23614566f11459709 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Thu, 23 Jul 2026 10:56:27 +0300 Subject: [PATCH 13/19] Change findRoomResponseById signature --- src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java b/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java index 0202cda3..cb5d43a4 100644 --- a/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java +++ b/src/main/java/org/unilab/uniplan/room/CustomRoomRepository.java @@ -10,5 +10,5 @@ public interface CustomRoomRepository { List findAllRoomResponses(); - Optional findRoomResponseById(@Param("id") UUID id); + Optional findRoomResponseById(UUID id); } From b964d8254c9b889313a5d54f2efc54bdc7b4f17e Mon Sep 17 00:00:00 2001 From: PIPetkova19 <63718742+PIPetkova19@users.noreply.github.com> Date: Mon, 20 Jul 2026 11:18:23 +0300 Subject: [PATCH 14/19] Feature/104 add soft delete on faculty; Bug/105 Delete Major doesn't work (#106) * Add soft delete on faculty: * Change annotation to SoftDelete * Add tests for delete method on service * Fix deletation of major * Add isdeleted column to course * Add softdelete to major and cascade removal * Resolve conflicts * Resolve conflicts * Rename Liquibase changelogs and remove year-based folders * Rename Liquibase changelogs and remove year-based folders * Remove unused imports, remove validations from response dto * Change id conventions, added objectQuotingStrategy * Add rollback to changsets * Remove unused method from repository * Remove redundant deleted_at migrations and keep is_deleted only * Remove cascade.remove from courses in major * Remove unused changelogs * Add rollback to all changelogs --- pom.xml | 5 +- .../common/model/SoftDeletableEntity.java | 10 --- .../org/unilab/uniplan/course/Course.java | 5 +- .../org/unilab/uniplan/faculty/Faculty.java | 3 + .../faculty/dto/FacultyResponseDto.java | 9 +-- .../java/org/unilab/uniplan/major/Major.java | 14 ++-- .../unilab/uniplan/major/MajorRepository.java | 3 +- .../org/unilab/uniplan/student/Student.java | 2 +- src/main/resources/application.yaml | 2 +- ...250801144000-baseline-init-changelog.yaml} | 68 +++++++++---------- ...144100-seed-university-data-from-csv.yaml} | 65 +++++++++--------- ...4100-add-column-is-deleted-to-faculty.yaml | 25 +++++++ ...144200-add-column-is-deleted-to-major.yaml | 25 +++++++ ...144300-drop-column-deleted-at-faculty.yaml | 18 +++++ ...6144400-drop-column-deleted-at-major.yaml} | 9 ++- ...44500-add-column-is-deleted-to-course.yaml | 19 ++++++ .../db/changelog/db.changelog-master.yaml | 14 +++- src/main/resources/db/data/university | 2 +- .../uniplan/faculty/FacultyServiceTest.java | 3 - 19 files changed, 194 insertions(+), 107 deletions(-) delete mode 100644 src/main/java/org/unilab/uniplan/common/model/SoftDeletableEntity.java rename src/main/resources/db/changelog/{2025/08/0001-baseline-init-changelog.yaml => 20250801144000-baseline-init-changelog.yaml} (96%) rename src/main/resources/db/changelog/{2025/08/0002-seed-university-data-from-csv.yaml => 20250801144100-seed-university-data-from-csv.yaml} (77%) create mode 100644 src/main/resources/db/changelog/20260626144100-add-column-is-deleted-to-faculty.yaml create mode 100644 src/main/resources/db/changelog/20260626144200-add-column-is-deleted-to-major.yaml create mode 100644 src/main/resources/db/changelog/20260626144300-drop-column-deleted-at-faculty.yaml rename src/main/resources/db/changelog/{2025/08/0003-alter-major-for-soft-delete.yaml => 20260626144400-drop-column-deleted-at-major.yaml} (58%) create mode 100644 src/main/resources/db/changelog/20260626144500-add-column-is-deleted-to-course.yaml diff --git a/pom.xml b/pom.xml index bfa72237..3aa826b9 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,8 @@ spring-boot-starter-web - org.liquibase - liquibase-core + org.springframework.boot + spring-boot-starter-liquibase @@ -114,7 +114,6 @@ springdoc-openapi-starter-webmvc-ui 2.8.9 - diff --git a/src/main/java/org/unilab/uniplan/common/model/SoftDeletableEntity.java b/src/main/java/org/unilab/uniplan/common/model/SoftDeletableEntity.java deleted file mode 100644 index 137c8511..00000000 --- a/src/main/java/org/unilab/uniplan/common/model/SoftDeletableEntity.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.unilab.uniplan.common.model; - -import jakarta.persistence.Column; -import java.time.LocalDateTime; - -public abstract class SoftDeletableEntity extends BaseEntity { - - @Column(name = "deleted_at") - private LocalDateTime deletedAt; -} diff --git a/src/main/java/org/unilab/uniplan/course/Course.java b/src/main/java/org/unilab/uniplan/course/Course.java index e67e4332..2d11c66c 100644 --- a/src/main/java/org/unilab/uniplan/course/Course.java +++ b/src/main/java/org/unilab/uniplan/course/Course.java @@ -11,6 +11,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.SoftDelete; +import org.hibernate.annotations.SoftDeleteType; import org.unilab.uniplan.common.model.BaseEntity; import org.unilab.uniplan.major.Major; @@ -20,8 +22,9 @@ @Setter @NoArgsConstructor @AllArgsConstructor +@SoftDelete(strategy = SoftDeleteType.DELETED, columnName = "is_deleted") public class Course extends BaseEntity { - + @ManyToOne @JoinColumn(name = "major_id", nullable = false) private Major major; diff --git a/src/main/java/org/unilab/uniplan/faculty/Faculty.java b/src/main/java/org/unilab/uniplan/faculty/Faculty.java index 2e6d41e0..cfdd29e8 100644 --- a/src/main/java/org/unilab/uniplan/faculty/Faculty.java +++ b/src/main/java/org/unilab/uniplan/faculty/Faculty.java @@ -9,6 +9,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.SoftDelete; +import org.hibernate.annotations.SoftDeleteType; import org.unilab.uniplan.common.model.BaseEntity; import org.unilab.uniplan.university.University; @@ -18,6 +20,7 @@ @Setter @NoArgsConstructor @AllArgsConstructor +@SoftDelete(strategy = SoftDeleteType.DELETED, columnName = "is_deleted") public class Faculty extends BaseEntity { @ManyToOne diff --git a/src/main/java/org/unilab/uniplan/faculty/dto/FacultyResponseDto.java b/src/main/java/org/unilab/uniplan/faculty/dto/FacultyResponseDto.java index 24409732..27c49cf4 100644 --- a/src/main/java/org/unilab/uniplan/faculty/dto/FacultyResponseDto.java +++ b/src/main/java/org/unilab/uniplan/faculty/dto/FacultyResponseDto.java @@ -8,16 +8,9 @@ public record FacultyResponseDto( UUID id, - @NotNull(message = "University ID cannot be null") UUID universityId, - @NotNull(message = "Faculty name cannot be null") - @Size(min = 1, max = 200, message = "Faculty name must be between 1 and 200 characters") String facultyName, - @NotNull(message = "Location cannot be null") - @Size(max = 500, message = "Location must be less than or equal to 500 characters") String location -) { - -} +) {} diff --git a/src/main/java/org/unilab/uniplan/major/Major.java b/src/main/java/org/unilab/uniplan/major/Major.java index 583d90dd..fd2122ba 100644 --- a/src/main/java/org/unilab/uniplan/major/Major.java +++ b/src/main/java/org/unilab/uniplan/major/Major.java @@ -1,5 +1,6 @@ package org.unilab.uniplan.major; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; @@ -14,22 +15,21 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.SQLRestriction; -import org.unilab.uniplan.common.model.SoftDeletableEntity; +import org.hibernate.annotations.SoftDelete; +import org.hibernate.annotations.SoftDeleteType; +import org.unilab.uniplan.common.model.BaseEntity; import org.unilab.uniplan.course.Course; import org.unilab.uniplan.faculty.Faculty; @Entity @Table(name = "major") -@SQLRestriction("deleted_at IS NULL") -@SQLDelete(sql = "UPDATE major SET deleted_at = NOW() WHERE id = ?") @Getter @Setter @NoArgsConstructor @AllArgsConstructor -public class Major extends SoftDeletableEntity { - +@SoftDelete(strategy = SoftDeleteType.DELETED, columnName = "is_deleted") +public class Major extends BaseEntity { + @ManyToOne @JoinColumn(name = "faculty_id", nullable = false) private Faculty faculty; diff --git a/src/main/java/org/unilab/uniplan/major/MajorRepository.java b/src/main/java/org/unilab/uniplan/major/MajorRepository.java index ba9ffb59..b32c9c81 100644 --- a/src/main/java/org/unilab/uniplan/major/MajorRepository.java +++ b/src/main/java/org/unilab/uniplan/major/MajorRepository.java @@ -4,9 +4,10 @@ import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import org.unilab.uniplan.faculty.Faculty; @Repository public interface MajorRepository extends JpaRepository { - public List findAllByFacultyId(UUID facultyId); + List findAllByFacultyId(UUID facultyId); } diff --git a/src/main/java/org/unilab/uniplan/student/Student.java b/src/main/java/org/unilab/uniplan/student/Student.java index 428d2cdd..e7345b5c 100644 --- a/src/main/java/org/unilab/uniplan/student/Student.java +++ b/src/main/java/org/unilab/uniplan/student/Student.java @@ -21,7 +21,7 @@ @AllArgsConstructor public class Student extends Person { - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "course_id", nullable = false) private Course course; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 43a7961a..c9d75450 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -12,7 +12,7 @@ spring: datasource: url: ${POSTGRES_URL} - driver: org.postgresql.Driver + driver-class-name: org.postgresql.Driver username: ${POSTGRES_USERNAME} password: ${POSTGRES_PASSWORD} diff --git a/src/main/resources/db/changelog/2025/08/0001-baseline-init-changelog.yaml b/src/main/resources/db/changelog/20250801144000-baseline-init-changelog.yaml similarity index 96% rename from src/main/resources/db/changelog/2025/08/0001-baseline-init-changelog.yaml rename to src/main/resources/db/changelog/20250801144000-baseline-init-changelog.yaml index 59a5f0d7..7323d1af 100644 --- a/src/main/resources/db/changelog/2025/08/0001-baseline-init-changelog.yaml +++ b/src/main/resources/db/changelog/20250801144000-baseline-init-changelog.yaml @@ -1,6 +1,6 @@ databaseChangeLog: - changeSet: - id: 1755084381762-1 + id: 202508011440-1 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -33,7 +33,7 @@ databaseChangeLog: type: SMALLINT tableName: category - changeSet: - id: 1755084381762-2 + id: 202508011440-2 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -76,7 +76,7 @@ databaseChangeLog: type: VARCHAR(100) tableName: course - changeSet: - id: 1755084381762-3 + id: 202508011440-3 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -114,7 +114,7 @@ databaseChangeLog: type: INT tableName: course_group - changeSet: - id: 1755084381762-4 + id: 202508011440-4 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -147,7 +147,7 @@ databaseChangeLog: type: VARCHAR(200) tableName: department - changeSet: - id: 1755084381762-5 + id: 202508011440-5 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -180,7 +180,7 @@ databaseChangeLog: type: VARCHAR(200) tableName: discipline - changeSet: - id: 1755084381762-6 + id: 202508011440-6 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -216,7 +216,7 @@ databaseChangeLog: type: VARCHAR(500) tableName: faculty - changeSet: - id: 1755084381762-7 + id: 202508011440-7 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -259,7 +259,7 @@ databaseChangeLog: type: UUID tableName: lector - changeSet: - id: 1755084381762-8 + id: 202508011440-8 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -301,7 +301,7 @@ databaseChangeLog: type: VARCHAR(100) tableName: lector_program - changeSet: - id: 1755084381762-9 + id: 202508011440-9 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -334,7 +334,7 @@ databaseChangeLog: type: VARCHAR(200) tableName: major - changeSet: - id: 1755084381762-10 + id: 202508011440-10 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -362,7 +362,7 @@ databaseChangeLog: type: UUID tableName: program - changeSet: - id: 1755084381762-11 + id: 202508011440-11 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -407,7 +407,7 @@ databaseChangeLog: type: TINYINT tableName: program_discipline - changeSet: - id: 1755084381762-12 + id: 202508011440-12 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -440,7 +440,7 @@ databaseChangeLog: type: VARCHAR(50) tableName: room - changeSet: - id: 1755084381762-13 + id: 202508011440-13 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -470,7 +470,7 @@ databaseChangeLog: type: UUID tableName: room_category - changeSet: - id: 1755084381762-14 + id: 202508011440-14 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -513,7 +513,7 @@ databaseChangeLog: type: VARCHAR(100) tableName: student - changeSet: - id: 1755084381762-15 + id: 202508011440-15 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -543,7 +543,7 @@ databaseChangeLog: type: UUID tableName: student_group - changeSet: - id: 1755084381762-16 + id: 202508011440-16 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -583,7 +583,7 @@ databaseChangeLog: type: VARCHAR(2048) tableName: university - changeSet: - id: 1755084381762-17 + id: 202508011440-17 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -592,7 +592,7 @@ databaseChangeLog: constraintName: uc_program_course tableName: program - changeSet: - id: 1755084381762-18 + id: 202508011440-18 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -612,7 +612,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: course - changeSet: - id: 1755084381762-20 + id: 202508011440-20 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -623,7 +623,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: major - changeSet: - id: 1755084381762-21 + id: 202508011440-21 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -645,7 +645,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: university - changeSet: - id: 1755084381762-23 + id: 202508011440-23 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -656,7 +656,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: faculty - changeSet: - id: 1755084381762-24 + id: 202508011440-24 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -667,7 +667,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: discipline - changeSet: - id: 1755084381762-25 + id: 202508011440-25 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -678,7 +678,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: lector - changeSet: - id: 1755084381762-26 + id: 202508011440-26 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -689,7 +689,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: program - changeSet: - id: 1755084381762-27 + id: 202508011440-27 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -700,7 +700,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: faculty - changeSet: - id: 1755084381762-28 + id: 202508011440-28 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -711,7 +711,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: discipline - changeSet: - id: 1755084381762-29 + id: 202508011440-29 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -722,7 +722,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: program - changeSet: - id: 1755084381762-30 + id: 202508011440-30 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -733,7 +733,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: course - changeSet: - id: 1755084381762-31 + id: 202508011440-31 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -744,7 +744,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: category - changeSet: - id: 1755084381762-32 + id: 202508011440-32 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -755,7 +755,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: room - changeSet: - id: 1755084381762-33 + id: 202508011440-33 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -766,7 +766,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: faculty - changeSet: - id: 1755084381762-34 + id: 202508011440-34 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -777,7 +777,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: course_group - changeSet: - id: 1755084381762-35 + id: 202508011440-35 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: @@ -788,7 +788,7 @@ databaseChangeLog: referencedColumnNames: id referencedTableName: student - changeSet: - id: 1755084381762-36 + id: 202508011440-36 author: sideroff objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: diff --git a/src/main/resources/db/changelog/2025/08/0002-seed-university-data-from-csv.yaml b/src/main/resources/db/changelog/20250801144100-seed-university-data-from-csv.yaml similarity index 77% rename from src/main/resources/db/changelog/2025/08/0002-seed-university-data-from-csv.yaml rename to src/main/resources/db/changelog/20250801144100-seed-university-data-from-csv.yaml index 652e24b5..ccc29990 100644 --- a/src/main/resources/db/changelog/2025/08/0002-seed-university-data-from-csv.yaml +++ b/src/main/resources/db/changelog/20250801144100-seed-university-data-from-csv.yaml @@ -1,177 +1,178 @@ databaseChangeLog: - changeSet: - id: 1 + id: 20250801144100-1 author: sideroff + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: - loadData: tableName: university - file: "../../../data/university" + file: ../data/university relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 2 + id: 20250801144100-2 author: sideroff changes: - loadData: tableName: faculty - file: "../../../data/faculty" + file: ../data/faculty relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 3 + id: 20250801144100-3 author: sideroff changes: - loadData: tableName: department - file: "../../../data/department" + file: ../data/department relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 4 + id: 20250801144100-4 author: sideroff changes: - loadData: tableName: room - file: "../../../data/room" + file: ../data/room relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 5 + id: 20250801144100-5 author: sideroff changes: - loadData: tableName: category - file: "../../../data/category" + file: ../data/category relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 6 + id: 20250801144100-6 author: sideroff changes: - loadData: tableName: room_category - file: "../../../data/room_category" + file: ../data/room_category relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 7 + id: 20250801144100-7 author: sideroff changes: - loadData: tableName: major - file: "../../../data/major" + file: ../data/major relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 8 + id: 20250801144100-8 author: sideroff changes: - loadData: tableName: course - file: "../../../data/course" + file: ../data/course relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 9 + id: 20250801144100-9 author: sideroff changes: - loadData: tableName: lector - file: "../../../data/lector" + file: ../data/lector relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 10 + id: 20250801144100-10 author: sideroff changes: - loadData: tableName: student - file: "../../../data/student" + file: ../data/student relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 11 + id: 20250801144100-11 author: sideroff changes: - loadData: tableName: discipline - file: "../../../data/discipline" + file: ../data/discipline relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 12 + id: 20250801144100-12 author: sideroff changes: - loadData: tableName: program - file: "../../../data/program" + file: ../data/program relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 13 + id: 20250801144100-13 author: sideroff changes: - loadData: tableName: course_group - file: "../../../data/course_group" + file: ../data/course_group relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 14 + id: 20250801144100-14 author: sideroff changes: - loadData: tableName: student_group - file: "../../../data/student_group" + file: ../data/student_group relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 15 + id: 20250801144100-15 author: sideroff changes: - loadData: tableName: program_discipline - file: "../../../data/program_discipline" + file: ../data/program_discipline relativeToChangelogFile: true encoding: UTF-8 separator: "," quotchar: '"' - changeSet: - id: 16 + id: 20250801144100-16 author: sideroff changes: - loadData: tableName: lector_program - file: "../../../data/lector_program" + file: ../data/lector_program relativeToChangelogFile: true encoding: UTF-8 separator: "," diff --git a/src/main/resources/db/changelog/20260626144100-add-column-is-deleted-to-faculty.yaml b/src/main/resources/db/changelog/20260626144100-add-column-is-deleted-to-faculty.yaml new file mode 100644 index 00000000..aa24a1b1 --- /dev/null +++ b/src/main/resources/db/changelog/20260626144100-add-column-is-deleted-to-faculty.yaml @@ -0,0 +1,25 @@ +databaseChangeLog: + - changeSet: + id: 20260626144100-1 + author: pipetkova19 + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS + preConditions: + - onFail: MARK_RAN + - not: + - columnExists: + tableName: faculty + columnName: is_deleted + changes: + - addColumn: + tableName: faculty + columns: + - column: + name: is_deleted + type: boolean + defaultValueBoolean: false + constraints: + nullable: false + rollback: + - dropColumn: + tableName: faculty + columnName: is_deleted \ No newline at end of file diff --git a/src/main/resources/db/changelog/20260626144200-add-column-is-deleted-to-major.yaml b/src/main/resources/db/changelog/20260626144200-add-column-is-deleted-to-major.yaml new file mode 100644 index 00000000..c39d2d27 --- /dev/null +++ b/src/main/resources/db/changelog/20260626144200-add-column-is-deleted-to-major.yaml @@ -0,0 +1,25 @@ +databaseChangeLog: + - changeSet: + id: 20260626144200-1 + author: pipetkova19 + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS + preConditions: + - onFail: MARK_RAN + - not: + - columnExists: + tableName: major + columnName: is_deleted + changes: + - addColumn: + tableName: major + columns: + - column: + name: is_deleted + type: boolean + defaultValueBoolean: false + constraints: + nullable: false + rollback: + - dropColumn: + tableName: major + columnName: is_deleted \ No newline at end of file diff --git a/src/main/resources/db/changelog/20260626144300-drop-column-deleted-at-faculty.yaml b/src/main/resources/db/changelog/20260626144300-drop-column-deleted-at-faculty.yaml new file mode 100644 index 00000000..db668311 --- /dev/null +++ b/src/main/resources/db/changelog/20260626144300-drop-column-deleted-at-faculty.yaml @@ -0,0 +1,18 @@ +databaseChangeLog: + - changeSet: + id: 20260626144300-1 + author: pipetkova19 + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS + changes: + - dropColumn: + tableName: faculty + columnName: deleted_at + rollback: + - addColumn: + tableName: faculty + columns: + - column: + name: deleted_at + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: true \ No newline at end of file diff --git a/src/main/resources/db/changelog/2025/08/0003-alter-major-for-soft-delete.yaml b/src/main/resources/db/changelog/20260626144400-drop-column-deleted-at-major.yaml similarity index 58% rename from src/main/resources/db/changelog/2025/08/0003-alter-major-for-soft-delete.yaml rename to src/main/resources/db/changelog/20260626144400-drop-column-deleted-at-major.yaml index eb2cf038..7e400d56 100644 --- a/src/main/resources/db/changelog/2025/08/0003-alter-major-for-soft-delete.yaml +++ b/src/main/resources/db/changelog/20260626144400-drop-column-deleted-at-major.yaml @@ -1,8 +1,13 @@ databaseChangeLog: - changeSet: - id: 2 - author: doseff + id: 20260626144400-1 + author: pipetkova19 + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS changes: + - dropColumn: + tableName: major + columnName: deleted_at + rollback: - addColumn: tableName: major columns: diff --git a/src/main/resources/db/changelog/20260626144500-add-column-is-deleted-to-course.yaml b/src/main/resources/db/changelog/20260626144500-add-column-is-deleted-to-course.yaml new file mode 100644 index 00000000..ba4b3b3e --- /dev/null +++ b/src/main/resources/db/changelog/20260626144500-add-column-is-deleted-to-course.yaml @@ -0,0 +1,19 @@ +databaseChangeLog: + - changeSet: + id: 20260626144500-1 + author: pipetkova19 + objectQuotingStrategy: QUOTE_ONLY_RESERVED_WORDS + changes: + - addColumn: + tableName: course + columns: + - column: + name: is_deleted + type: boolean + defaultValueBoolean: false + constraints: + nullable: false + rollback: + - dropColumn: + tableName: course + columnName: is_deleted \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index b0652b99..10432196 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,7 +1,15 @@ databaseChangeLog: - include: - file: db/changelog/2025/08/0001-baseline-init-changelog.yaml + file: db/changelog/20250801144000-baseline-init-changelog.yaml - include: - file: db/changelog/2025/08/0002-seed-university-data-from-csv.yaml + file: db/changelog/20250801144100-seed-university-data-from-csv.yaml - include: - file: db/changelog/2025/08/0003-alter-major-for-soft-delete.yaml \ No newline at end of file + file: db/changelog/20260626144100-add-column-is-deleted-to-faculty.yaml + - include: + file: db/changelog/20260626144200-add-column-is-deleted-to-major.yaml + - include: + file: db/changelog/20260626144300-drop-column-deleted-at-faculty.yaml + - include: + file: db/changelog/20260626144400-drop-column-deleted-at-major.yaml + - include: + file: db/changelog/20260626144500-add-column-is-deleted-to-course.yaml diff --git a/src/main/resources/db/data/university b/src/main/resources/db/data/university index 1c37d3c9..2acfe6f5 100644 --- a/src/main/resources/db/data/university +++ b/src/main/resources/db/data/university @@ -1,2 +1,2 @@ id,created_at,updated_at,uni_name,location,established_year,accreditation,website -a4a5f0aa-a6a6-4af3-ab15-65f427bb1988,2025-08-13 16:24:20.841094,2025-08-13 16:24:20.841094,"Plovdiv University '"Paisii Hilendarski'"","TsentarPlovdiv Center, King Asen St 24, 4000 Plovdiv",1961,no-info,https://uni-plovdiv.bg/en/pages/index/10/ +a4a5f0aa-a6a6-4af3-ab15-65f427bb1988,2025-08-13 16:24:20.841094,2025-08-13 16:24:20.841094,"Plovdiv University ""Paisii Hilendarski""","Tsentar Plovdiv Center, King Asen St 24, 4000 Plovdiv",1961,no-info,https://uni-plovdiv.bg/en/pages/index/10/ \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/faculty/FacultyServiceTest.java b/src/test/java/org/unilab/uniplan/faculty/FacultyServiceTest.java index 8b8598cb..803dbd0a 100644 --- a/src/test/java/org/unilab/uniplan/faculty/FacultyServiceTest.java +++ b/src/test/java/org/unilab/uniplan/faculty/FacultyServiceTest.java @@ -13,9 +13,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.unilab.uniplan.faculty.Faculty; -import org.unilab.uniplan.faculty.FacultyRepository; -import org.unilab.uniplan.faculty.FacultyService; @ExtendWith(MockitoExtension.class) class FacultyServiceTest { From 7c9ecbeea4f2d4b4b1ef5e08e7393217251e794f Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Thu, 23 Jul 2026 13:23:23 +0300 Subject: [PATCH 15/19] Add availableSeats column to Room entity, update dtos, repository methods, unit tests, liquibase schema --- .../room/CustomRoomRepositoryImpl.java | 2 ++ .../java/org/unilab/uniplan/room/Room.java | 3 +++ .../uniplan/room/dto/RoomRequestDto.java | 8 +++++- .../uniplan/room/dto/RoomResponseDto.java | 3 ++- ...723130700-add-available-seats-to-room.yaml | 27 +++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 2 ++ .../unilab/uniplan/room/RoomMapperTest.java | 10 +++---- .../uniplan/room/RoomWebFacadeTest.java | 6 ++--- 8 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/db/changelog/20260723130700-add-available-seats-to-room.yaml diff --git a/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java index 1ddc4014..76b66aee 100644 --- a/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java +++ b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java @@ -41,6 +41,7 @@ public List findAllRoomResponses() { room.get("id"), room.get("faculty").get("id"), room.get("roomNumber"), + room.get("availableSeats"), category.get("id") )); @@ -67,6 +68,7 @@ public Optional findRoomResponseById(UUID id) { room.get("id"), room.get("faculty").get("id"), room.get("roomNumber"), + room.get("availableSeats"), category.get("id") )).where(cb.equal(room.get("id"), id)); diff --git a/src/main/java/org/unilab/uniplan/room/Room.java b/src/main/java/org/unilab/uniplan/room/Room.java index afd41137..b040c8b0 100644 --- a/src/main/java/org/unilab/uniplan/room/Room.java +++ b/src/main/java/org/unilab/uniplan/room/Room.java @@ -23,7 +23,10 @@ public class Room extends BaseEntity { @ManyToOne @JoinColumn(name = "faculty_id", referencedColumnName = "id", nullable = false) private Faculty faculty; + @Column(name = "room_number", nullable = false, length = 50) private String roomNumber; + @Column(name = "available_seats", nullable = false) + private int availableSeats; } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java index 9cbe739f..f043d4ad 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java @@ -1,6 +1,8 @@ package org.unilab.uniplan.room.dto; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import jakarta.validation.constraints.Size; import java.util.UUID; @@ -11,7 +13,11 @@ public record RoomRequestDto( @NotNull(message = "Room number cannot be null") @Size(max = 50, message = "Room number cannot exceed 50 characters") - String roomNumber + String roomNumber, + + @NotNull(message="Available seats cannot be null") + @PositiveOrZero + int availableSeats ) { } diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java index e0a2df5b..96d5293a 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java @@ -10,6 +10,7 @@ public record RoomResponseDto( String roomNumber, - UUID categoryId + int availableSeats, + UUID categoryId ) { } diff --git a/src/main/resources/db/changelog/20260723130700-add-available-seats-to-room.yaml b/src/main/resources/db/changelog/20260723130700-add-available-seats-to-room.yaml new file mode 100644 index 00000000..abf0c0bf --- /dev/null +++ b/src/main/resources/db/changelog/20260723130700-add-available-seats-to-room.yaml @@ -0,0 +1,27 @@ +databaseChangeLog: + - changeSet: + id: 202607231307000-1 + author: pipetkova19 + changes: + - addColumn: + tableName: room + columns: + - column: + name: available_seats + type: int + defaultValueNumeric: "0" + constraints: + nullable: false + - sql: + sql: > + ALTER TABLE room + ADD CONSTRAINT chk_room_available_seats_positive + CHECK (available_seats >= 0); + rollback: + - sql: + sql: > + ALTER TABLE room + DROP CONSTRAINT chk_room_available_seats_positive; + - dropColumn: + tableName: room + columnName: available_seats diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 10432196..e82f24f4 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -13,3 +13,5 @@ databaseChangeLog: file: db/changelog/20260626144400-drop-column-deleted-at-major.yaml - include: file: db/changelog/20260626144500-add-column-is-deleted-to-course.yaml + - include: + file: db/changelog/20260723130700-add-available-seats-to-room.yaml \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index a658ca0b..929c92d8 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -37,13 +37,13 @@ void setUp() { faculty.setId(facultyId); roomNumber1 = "111"; String roomNumber2 = "222"; - room1 = new Room(faculty, roomNumber1); + room1 = new Room(faculty, roomNumber1, 20); room1.setId(UUID.randomUUID()); - room2 = new Room(faculty, roomNumber2); + room2 = new Room(faculty, roomNumber2, 20); room2.setId(UUID.randomUUID()); - roomRequestDto = new RoomRequestDto(facultyId, roomNumber1); - roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1,null); - roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2,null); + roomRequestDto = new RoomRequestDto(facultyId, roomNumber1, 20); + roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1,20,null); + roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2,20,null); } diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java index c99d6dfa..eee234e2 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -51,10 +51,10 @@ void setUp() { Faculty faculty = new Faculty(university, "FMI", "Faculty Name"); faculty.setId(facultyId); String roomNumber = "111"; - requestDto = new RoomRequestDto(facultyId, "222"); - entity = new Room(faculty, roomNumber); + requestDto = new RoomRequestDto(facultyId, "222", 20); + entity = new Room(faculty, roomNumber, 20); entity.setId(id); - responseDto = new RoomResponseDto(id, facultyId, roomNumber, categoryId); + responseDto = new RoomResponseDto(id, facultyId, roomNumber, 20, categoryId); } @Test From ab0c3e115fd0dc9397ceec77bc7d61c123e170cc Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Thu, 23 Jul 2026 14:11:36 +0300 Subject: [PATCH 16/19] Make faculty optional for room --- .../java/org/unilab/uniplan/room/Room.java | 4 +++- .../org/unilab/uniplan/room/RoomMapper.java | 4 ++-- .../org/unilab/uniplan/room/RoomService.java | 20 +++++++++++++++---- .../unilab/uniplan/room/RoomWebFacade.java | 8 ++++++-- .../uniplan/room/dto/RoomRequestDto.java | 1 - ...drop-not-null-constraint-faculty-room.yaml | 14 +++++++++++++ .../db/changelog/db.changelog-master.yaml | 4 +++- .../unilab/uniplan/room/RoomMapperTest.java | 17 +++++----------- 8 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 src/main/resources/db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml diff --git a/src/main/java/org/unilab/uniplan/room/Room.java b/src/main/java/org/unilab/uniplan/room/Room.java index b040c8b0..302b179b 100644 --- a/src/main/java/org/unilab/uniplan/room/Room.java +++ b/src/main/java/org/unilab/uniplan/room/Room.java @@ -4,6 +4,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Getter; @@ -21,7 +22,7 @@ public class Room extends BaseEntity { @ManyToOne - @JoinColumn(name = "faculty_id", referencedColumnName = "id", nullable = false) + @JoinColumn(name = "faculty_id", referencedColumnName = "id", nullable = true) private Faculty faculty; @Column(name = "room_number", nullable = false, length = 50) @@ -29,4 +30,5 @@ public class Room extends BaseEntity { @Column(name = "available_seats", nullable = false) private int availableSeats; + } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/room/RoomMapper.java b/src/main/java/org/unilab/uniplan/room/RoomMapper.java index c923d684..b122ca9d 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomMapper.java +++ b/src/main/java/org/unilab/uniplan/room/RoomMapper.java @@ -10,7 +10,7 @@ @Mapper public interface RoomMapper { - @Mapping(source = "facultyId", target = "faculty.id") + @Mapping(target = "faculty", ignore = true) Room toEntity(final RoomRequestDto roomRequestDto); @Mapping(target = "facultyId", source = "faculty.id") @@ -18,7 +18,7 @@ public interface RoomMapper { List toResponseDtoList(final List rooms); - @Mapping(source = "facultyId", target = "faculty.id") + @Mapping(target = "faculty", ignore = true) @Mapping(target = "id", ignore = true) void updateEntityFromDto(final RoomRequestDto roomRequestDto, @MappingTarget final Room room); } diff --git a/src/main/java/org/unilab/uniplan/room/RoomService.java b/src/main/java/org/unilab/uniplan/room/RoomService.java index ee8074e1..62b4acb9 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomService.java +++ b/src/main/java/org/unilab/uniplan/room/RoomService.java @@ -1,16 +1,14 @@ package org.unilab.uniplan.room; -import static org.unilab.uniplan.utils.ErrorConstants.ROOM_NOT_FOUND; - import java.util.List; import java.util.Optional; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.unilab.uniplan.common.model.BaseService; import org.unilab.uniplan.exception.ResourceNotFoundException; -import org.unilab.uniplan.room.dto.RoomRequestDto; +import org.unilab.uniplan.faculty.Faculty; +import org.unilab.uniplan.faculty.FacultyRepository; import org.unilab.uniplan.room.dto.RoomResponseDto; @Service @@ -18,6 +16,20 @@ public class RoomService implements BaseService { private final RoomRepository roomRepository; + private final FacultyRepository facultyRepository; + + public void setFaculty(Room room, UUID facultyId) { + if (facultyId == null) { + room.setFaculty(null); + return; + } + + //TODO: Change to FacultyNotFoundException after pr is approved + Faculty faculty = facultyRepository.findById(facultyId) + .orElseThrow(() -> new ResourceNotFoundException("Faculty not found")); + + room.setFaculty(faculty); + } @Override public void save(final Room room) { diff --git a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java index b2cab683..37c91b6d 100644 --- a/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java +++ b/src/main/java/org/unilab/uniplan/room/RoomWebFacade.java @@ -28,10 +28,13 @@ private Room getRoomOrThrow(final UUID id) { @Transactional public void createRoom(RoomRequestDto roomRequestDto) { Room room = roomMapper.toEntity(roomRequestDto); + + roomService.setFaculty(room, roomRequestDto.facultyId()); + roomService.save(room); log.info("created room {} with ID: {}", - room.getRoomNumber(), - room.getId()); + room.getRoomNumber(), + room.getId()); } @Transactional(readOnly = true) @@ -57,6 +60,7 @@ public RoomResponseDto getRoomById(final UUID id) { public void updateRoom(final UUID id, final RoomRequestDto roomRequestDto) { final Room room = getRoomOrThrow(id); roomMapper.updateEntityFromDto(roomRequestDto, room); + roomService.setFaculty(room, roomRequestDto.facultyId()); roomService.save(room); log.info("updated room with id {}", id); } diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java index f043d4ad..8a92a801 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomRequestDto.java @@ -8,7 +8,6 @@ public record RoomRequestDto( - @NotNull(message = "Faculty ID cannot be null") UUID facultyId, @NotNull(message = "Room number cannot be null") diff --git a/src/main/resources/db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml b/src/main/resources/db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml new file mode 100644 index 00000000..a73412c6 --- /dev/null +++ b/src/main/resources/db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml @@ -0,0 +1,14 @@ +databaseChangeLog: + - changeSet: + id: 20260723134100-1 + author: pipetkova19 + changes: + - dropNotNullConstraint: + tableName: room + columnName: faculty_id + columnDataType: uuid + rollback: + - addNotNullConstraint: + tableName: room + columnName: faculty_id + columnDataType: uuid \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index e82f24f4..3b335f2d 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -14,4 +14,6 @@ databaseChangeLog: - include: file: db/changelog/20260626144500-add-column-is-deleted-to-course.yaml - include: - file: db/changelog/20260723130700-add-available-seats-to-room.yaml \ No newline at end of file + file: db/changelog/20260723130700-add-available-seats-to-room.yaml + - include: + file: db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index 929c92d8..b37eeeb0 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.unilab.uniplan.faculty.Faculty; import org.unilab.uniplan.room.dto.RoomRequestDto; import org.unilab.uniplan.room.dto.RoomResponseDto; import org.unilab.uniplan.university.University; @@ -22,35 +21,30 @@ public class RoomMapperTest { private RoomResponseDto roomResponseDto2; private String roomNumber1; - private UUID facultyId; @BeforeEach void setUp() { - facultyId = UUID.randomUUID(); University university = new University("Sofia University", "Sofia, Bulgaria", (short) 1888, "NEAA", "https://uni-sofia.bg" ); - Faculty faculty = new Faculty(university, "FMI", "Faculty Name"); - faculty.setId(facultyId); roomNumber1 = "111"; String roomNumber2 = "222"; - room1 = new Room(faculty, roomNumber1, 20); + room1 = new Room(null, roomNumber1, 20); room1.setId(UUID.randomUUID()); - room2 = new Room(faculty, roomNumber2, 20); + room2 = new Room(null, roomNumber2, 20); room2.setId(UUID.randomUUID()); - roomRequestDto = new RoomRequestDto(facultyId, roomNumber1, 20); - roomResponseDto1 = new RoomResponseDto(room1.getId(), facultyId, roomNumber1,20,null); - roomResponseDto2 = new RoomResponseDto(room2.getId(), facultyId, roomNumber2,20,null); + roomRequestDto = new RoomRequestDto(null, roomNumber1, 20); + roomResponseDto1 = new RoomResponseDto(room1.getId(), null, roomNumber1,20,null); + roomResponseDto2 = new RoomResponseDto(room2.getId(), null, roomNumber2,20,null); } @Test void toEntity_shouldMapAllFieldsAndIgnoreId_whenRequestDtoIsValid() { final Room result = roomMapper.toEntity(roomRequestDto); - assertThat(result.getFaculty().getId()).isEqualTo(facultyId); assertThat(result.getRoomNumber()).isEqualTo(roomNumber1); assertThat(result.getId()).isNull(); } @@ -59,7 +53,6 @@ void toEntity_shouldMapAllFieldsAndIgnoreId_whenRequestDtoIsValid() { void toResponseDto_shouldMapAllFields_whenFacultyIsValid() { RoomResponseDto result = roomMapper.toResponseDto(room1); assertThat(result.id()).isEqualTo(room1.getId()); - assertThat(result.facultyId()).isEqualTo(facultyId); assertThat(result.roomNumber()).isEqualTo(roomNumber1); } From 489f7f06bd0f4a5df3825368d5c31ec333beafe9 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Thu, 23 Jul 2026 14:21:39 +0300 Subject: [PATCH 17/19] Add description field to category --- .../org/unilab/uniplan/category/Category.java | 2 ++ .../unilab/uniplan/category/dto/CategoryDto.java | 5 ++++- .../uniplan/category/dto/CategoryRequestDto.java | 6 +++++- .../category/dto/CategoryResponseDto.java | 5 ++++- ...41400-add-description-column-to-category.yaml | 16 ++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 4 +++- 6 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/db/changelog/20260723141400-add-description-column-to-category.yaml diff --git a/src/main/java/org/unilab/uniplan/category/Category.java b/src/main/java/org/unilab/uniplan/category/Category.java index 437268f9..6e3c86ec 100644 --- a/src/main/java/org/unilab/uniplan/category/Category.java +++ b/src/main/java/org/unilab/uniplan/category/Category.java @@ -21,4 +21,6 @@ public class Category extends BaseEntity { private String roomType; @Column(name = "capacity", nullable = false) private short capacity; + @Column(name = "description", nullable = true, length = 100) + private String description; } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/category/dto/CategoryDto.java b/src/main/java/org/unilab/uniplan/category/dto/CategoryDto.java index 1ad4a517..6dd33327 100644 --- a/src/main/java/org/unilab/uniplan/category/dto/CategoryDto.java +++ b/src/main/java/org/unilab/uniplan/category/dto/CategoryDto.java @@ -14,7 +14,10 @@ public record CategoryDto( String roomType, @Positive - short capacity + short capacity, + + @Size(min = 1, max = 100, message = "Description must be between 1 and 100 characters") + String description ) { } diff --git a/src/main/java/org/unilab/uniplan/category/dto/CategoryRequestDto.java b/src/main/java/org/unilab/uniplan/category/dto/CategoryRequestDto.java index 204b0dbc..ac71e16a 100644 --- a/src/main/java/org/unilab/uniplan/category/dto/CategoryRequestDto.java +++ b/src/main/java/org/unilab/uniplan/category/dto/CategoryRequestDto.java @@ -1,5 +1,6 @@ package org.unilab.uniplan.category.dto; +import jakarta.persistence.Column; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.Size; @@ -11,7 +12,10 @@ public record CategoryRequestDto( String roomType, @Positive - short capacity + short capacity, + + @Size(min = 1, max = 100, message = "Description must be between 1 and 100 characters") + String description ) { } diff --git a/src/main/java/org/unilab/uniplan/category/dto/CategoryResponseDto.java b/src/main/java/org/unilab/uniplan/category/dto/CategoryResponseDto.java index 7fc7a1a7..3c8d6658 100644 --- a/src/main/java/org/unilab/uniplan/category/dto/CategoryResponseDto.java +++ b/src/main/java/org/unilab/uniplan/category/dto/CategoryResponseDto.java @@ -14,7 +14,10 @@ public record CategoryResponseDto( String roomType, @Positive - short capacity + short capacity, + + @Size(min = 1, max = 100, message = "Description must be between 1 and 100 characters") + String description ) { } diff --git a/src/main/resources/db/changelog/20260723141400-add-description-column-to-category.yaml b/src/main/resources/db/changelog/20260723141400-add-description-column-to-category.yaml new file mode 100644 index 00000000..2933b279 --- /dev/null +++ b/src/main/resources/db/changelog/20260723141400-add-description-column-to-category.yaml @@ -0,0 +1,16 @@ +databaseChangeLog: + - changeSet: + id: 20260723141400-1 + author: pipetkova19 + changes: + - addColumn: + tableName: category + columns: + - column: + name: description + type: varchar(100) + defaultValue: "-" + rollback: + - dropColumn: + tableName: category + columnName: description \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 3b335f2d..4d86e7ac 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -16,4 +16,6 @@ databaseChangeLog: - include: file: db/changelog/20260723130700-add-available-seats-to-room.yaml - include: - file: db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml \ No newline at end of file + file: db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml + - include: + file: db/changelog/20260723141400-add-description-column-to-category.yaml \ No newline at end of file From 2afbb6d28cc168513834c983718d06de7e26365b Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Thu, 23 Jul 2026 15:05:35 +0300 Subject: [PATCH 18/19] Add Building entity, update liquibase --- .../org/unilab/uniplan/building/Building.java | 39 +++++++++++++++ .../org/unilab/uniplan/category/Category.java | 2 + .../unilab/uniplan/university/University.java | 10 ++++ .../20260723144301-create-building-table.yaml | 47 +++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 4 +- .../uniplan/faculty/FacultyMapperTest.java | 3 +- .../unilab/uniplan/room/RoomMapperTest.java | 3 +- .../uniplan/room/RoomWebFacadeTest.java | 2 +- .../university/UniversityMapperTest.java | 4 +- 9 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/unilab/uniplan/building/Building.java create mode 100644 src/main/resources/db/changelog/20260723144301-create-building-table.yaml diff --git a/src/main/java/org/unilab/uniplan/building/Building.java b/src/main/java/org/unilab/uniplan/building/Building.java new file mode 100644 index 00000000..01acc132 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/Building.java @@ -0,0 +1,39 @@ +package org.unilab.uniplan.building; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.unilab.uniplan.common.model.BaseEntity; +import org.unilab.uniplan.room.Room; +import org.unilab.uniplan.university.University; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Table(name = "building") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class Building extends BaseEntity { + + @Column(name = "name", nullable = false, length = 50) + private String name; + + @Column(name = "address", nullable = false, length = 100) + private String address; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "university_id", referencedColumnName = "id") + private University university; +} diff --git a/src/main/java/org/unilab/uniplan/category/Category.java b/src/main/java/org/unilab/uniplan/category/Category.java index 6e3c86ec..ff0ca278 100644 --- a/src/main/java/org/unilab/uniplan/category/Category.java +++ b/src/main/java/org/unilab/uniplan/category/Category.java @@ -19,8 +19,10 @@ public class Category extends BaseEntity { @Column(name = "room_type", nullable = false, length = 50) private String roomType; + @Column(name = "capacity", nullable = false) private short capacity; + @Column(name = "description", nullable = true, length = 100) private String description; } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/university/University.java b/src/main/java/org/unilab/uniplan/university/University.java index e110fd80..b2078532 100644 --- a/src/main/java/org/unilab/uniplan/university/University.java +++ b/src/main/java/org/unilab/uniplan/university/University.java @@ -2,12 +2,16 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.unilab.uniplan.building.Building; import org.unilab.uniplan.common.model.BaseEntity; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name = "university") @@ -19,13 +23,19 @@ public class University extends BaseEntity { @Column(name = "uni_name", nullable = false) private String uniName; + @Column(name = "location", length = 500) private String location; + @Column(name = "established_year") private short establishedYear; + @Column(name = "accreditation", length = 200) private String accreditation; + @Column(name = "website", length = 2048) private String website; + @OneToMany(mappedBy="university") + private List buildings= new ArrayList<>(); } \ No newline at end of file diff --git a/src/main/resources/db/changelog/20260723144301-create-building-table.yaml b/src/main/resources/db/changelog/20260723144301-create-building-table.yaml new file mode 100644 index 00000000..e0aa5dcb --- /dev/null +++ b/src/main/resources/db/changelog/20260723144301-create-building-table.yaml @@ -0,0 +1,47 @@ +databaseChangeLog: + - changeSet: + id: 20260723144300-1 + author: pipetkova19 + changes: + - createTable: + tableName: building + columns: + - column: + name: id + type: UUID + constraints: + nullable: false + primaryKey: true + primaryKeyName: pk_building + - column: + name: name + type: varchar(50) + constraints: + nullable: false + - column: + name: address + type: varchar(100) + constraints: + nullable: false + - column: + name: university_id + type: UUID + - column: + constraints: + nullable: false + name: created_at + type: DATETIME + - column: + name: updated_at + type: DATETIME + + - changeSet: + id: 20260723144300-2 + author: pipetkova19 + changes: + - addForeignKeyConstraint: + baseTableName: building + baseColumnNames: university_id + constraintName: FK_BUILDING_ON_UNIVERSITY + referencedTableName: university + referencedColumnNames: id \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 4d86e7ac..6f9b8cd7 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -18,4 +18,6 @@ databaseChangeLog: - include: file: db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml - include: - file: db/changelog/20260723141400-add-description-column-to-category.yaml \ No newline at end of file + file: db/changelog/20260723141400-add-description-column-to-category.yaml + - include: + file: db/changelog/20260723144301-create-building-table.yaml \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/faculty/FacultyMapperTest.java b/src/test/java/org/unilab/uniplan/faculty/FacultyMapperTest.java index 7873a7e1..f76b0566 100644 --- a/src/test/java/org/unilab/uniplan/faculty/FacultyMapperTest.java +++ b/src/test/java/org/unilab/uniplan/faculty/FacultyMapperTest.java @@ -31,7 +31,8 @@ void setUp() { "Burgas", (short) 1999, "accreditation", - "www.pu.com" + "www.pu.com", + null ); university.setId(universityId); diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index b37eeeb0..aa944bf3 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -28,7 +28,8 @@ void setUp() { "Sofia, Bulgaria", (short) 1888, "NEAA", - "https://uni-sofia.bg" + "https://uni-sofia.bg", + null ); roomNumber1 = "111"; String roomNumber2 = "222"; diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java index eee234e2..1c994889 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -46,7 +46,7 @@ void setUp() { "Sofia, Bulgaria", (short) 1888, "NEAA", - "https://uni-sofia.bg" + "https://uni-sofia.bg", null ); Faculty faculty = new Faculty(university, "FMI", "Faculty Name"); faculty.setId(facultyId); diff --git a/src/test/java/org/unilab/uniplan/university/UniversityMapperTest.java b/src/test/java/org/unilab/uniplan/university/UniversityMapperTest.java index fba6840f..457dd52c 100644 --- a/src/test/java/org/unilab/uniplan/university/UniversityMapperTest.java +++ b/src/test/java/org/unilab/uniplan/university/UniversityMapperTest.java @@ -27,10 +27,10 @@ void setUp() { "New Name", "New Location", (short) 2000, "New Acc", "https://new.bg" ); university = new University( - "Sofia University", "Sofia, Bulgaria", (short) 1888, "NEAA", "https://uni-sofia.bg" + "Sofia University", "Sofia, Bulgaria", (short) 1888, "NEAA", "https://uni-sofia.bg", null ); university2 = new University( - "Plovdiv University", "Plovdiv", (short) 1961, "NEAA", "https://uni-plovdiv.bg" + "Plovdiv University", "Plovdiv", (short) 1961, "NEAA", "https://uni-plovdiv.bg", null ); id = UUID.randomUUID(); } From cd3b649f07de5b8562ad2795c0725c831c0069e3 Mon Sep 17 00:00:00 2001 From: PIPetkova19 Date: Tue, 28 Jul 2026 16:00:11 +0300 Subject: [PATCH 19/19] Add room field to building --- .../org/unilab/uniplan/building/Building.java | 3 +++ .../uniplan/room/CustomRoomRepositoryImpl.java | 6 ++++-- src/main/java/org/unilab/uniplan/room/Room.java | 4 ++++ .../unilab/uniplan/room/dto/RoomResponseDto.java | 4 +++- ...0260728113500-add-building-column-to-room.yaml | 15 +++++++++++++++ .../db/changelog/db.changelog-master.yaml | 4 +++- .../org/unilab/uniplan/room/RoomMapperTest.java | 8 ++++---- .../unilab/uniplan/room/RoomWebFacadeTest.java | 4 ++-- 8 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/db/changelog/20260728113500-add-building-column-to-room.yaml diff --git a/src/main/java/org/unilab/uniplan/building/Building.java b/src/main/java/org/unilab/uniplan/building/Building.java index 01acc132..78300f42 100644 --- a/src/main/java/org/unilab/uniplan/building/Building.java +++ b/src/main/java/org/unilab/uniplan/building/Building.java @@ -36,4 +36,7 @@ public class Building extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "university_id", referencedColumnName = "id") private University university; + + @OneToMany(mappedBy = "building") + private List rooms = new ArrayList<>(); } diff --git a/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java index 76b66aee..255a57ff 100644 --- a/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java +++ b/src/main/java/org/unilab/uniplan/room/CustomRoomRepositoryImpl.java @@ -42,7 +42,8 @@ public List findAllRoomResponses() { room.get("faculty").get("id"), room.get("roomNumber"), room.get("availableSeats"), - category.get("id") + category.get("id"), + room.get("building").get("id") )); return entityManager.createQuery(query).getResultList(); @@ -69,7 +70,8 @@ public Optional findRoomResponseById(UUID id) { room.get("faculty").get("id"), room.get("roomNumber"), room.get("availableSeats"), - category.get("id") + category.get("id"), + room.get("building").get("id") )).where(cb.equal(room.get("id"), id)); return entityManager.createQuery(query) diff --git a/src/main/java/org/unilab/uniplan/room/Room.java b/src/main/java/org/unilab/uniplan/room/Room.java index 302b179b..19be519a 100644 --- a/src/main/java/org/unilab/uniplan/room/Room.java +++ b/src/main/java/org/unilab/uniplan/room/Room.java @@ -10,6 +10,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.unilab.uniplan.building.Building; import org.unilab.uniplan.common.model.BaseEntity; import org.unilab.uniplan.faculty.Faculty; @@ -31,4 +32,7 @@ public class Room extends BaseEntity { @Column(name = "available_seats", nullable = false) private int availableSeats; + @ManyToOne + @JoinColumn(name = "building_id") + private Building building; } \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java index 96d5293a..6f8d209c 100644 --- a/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java +++ b/src/main/java/org/unilab/uniplan/room/dto/RoomResponseDto.java @@ -12,5 +12,7 @@ public record RoomResponseDto( int availableSeats, - UUID categoryId + UUID categoryId, + + UUID buildingId ) { } diff --git a/src/main/resources/db/changelog/20260728113500-add-building-column-to-room.yaml b/src/main/resources/db/changelog/20260728113500-add-building-column-to-room.yaml new file mode 100644 index 00000000..ce9e48a3 --- /dev/null +++ b/src/main/resources/db/changelog/20260728113500-add-building-column-to-room.yaml @@ -0,0 +1,15 @@ +databaseChangeLog: + - changeSet: + id: 20260728113500-1 + author: pipetkova19 + changes: + - addColumn: + tableName: room + columns: + - column: + name: building_id + type: uuid + rollback: + - dropColumn: + tableName: building + columnName: room_id diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 6f9b8cd7..f77652b2 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -20,4 +20,6 @@ databaseChangeLog: - include: file: db/changelog/20260723141400-add-description-column-to-category.yaml - include: - file: db/changelog/20260723144301-create-building-table.yaml \ No newline at end of file + file: db/changelog/20260723144301-create-building-table.yaml + - include: + file: db/changelog/20260728113500-add-building-column-to-room.yaml \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java index aa944bf3..29c15770 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomMapperTest.java @@ -33,13 +33,13 @@ void setUp() { ); roomNumber1 = "111"; String roomNumber2 = "222"; - room1 = new Room(null, roomNumber1, 20); + room1 = new Room(null, roomNumber1, 20, null); room1.setId(UUID.randomUUID()); - room2 = new Room(null, roomNumber2, 20); + room2 = new Room(null, roomNumber2, 20, null); room2.setId(UUID.randomUUID()); roomRequestDto = new RoomRequestDto(null, roomNumber1, 20); - roomResponseDto1 = new RoomResponseDto(room1.getId(), null, roomNumber1,20,null); - roomResponseDto2 = new RoomResponseDto(room2.getId(), null, roomNumber2,20,null); + roomResponseDto1 = new RoomResponseDto(room1.getId(), null, roomNumber1,20,null, null); + roomResponseDto2 = new RoomResponseDto(room2.getId(), null, roomNumber2,20,null, null); } diff --git a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java index 1c994889..72d0ce32 100644 --- a/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java +++ b/src/test/java/org/unilab/uniplan/room/RoomWebFacadeTest.java @@ -52,9 +52,9 @@ void setUp() { faculty.setId(facultyId); String roomNumber = "111"; requestDto = new RoomRequestDto(facultyId, "222", 20); - entity = new Room(faculty, roomNumber, 20); + entity = new Room(faculty, roomNumber, 20, null); entity.setId(id); - responseDto = new RoomResponseDto(id, facultyId, roomNumber, 20, categoryId); + responseDto = new RoomResponseDto(id, facultyId, roomNumber, 20, categoryId, null); } @Test