diff --git a/output.log b/output.log new file mode 100644 index 00000000..9316c9e3 Binary files /dev/null and b/output.log differ diff --git a/pr.diff b/pr.diff new file mode 100644 index 00000000..036f8e13 Binary files /dev/null and b/pr.diff differ 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..3212029e --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/Building.java @@ -0,0 +1,33 @@ +package org.unilab.uniplan.building; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +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.university.University; + +@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/building/BuildingController.java b/src/main/java/org/unilab/uniplan/building/BuildingController.java new file mode 100644 index 00000000..d2bb2179 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingController.java @@ -0,0 +1,58 @@ +package org.unilab.uniplan.building; + +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +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.building.dto.BuildingRequestDto; +import org.unilab.uniplan.building.dto.BuildingResponseDto; +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/buildings") +@RequiredArgsConstructor +@Tag(name = "Buildings", description = "Manage university buildings, including name, address, and associated university") +public class BuildingController { + private final BuildingWebFacade buildingWebFacade; + + @PostMapping + public ResponseEntity createBuilding(@Valid @NotNull @RequestBody final BuildingRequestDto buildingRequestDto) { + buildingWebFacade.createBuilding(buildingRequestDto); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @GetMapping + public ResponseEntity> getAllBuildings() { + return ResponseEntity.ok(buildingWebFacade.getAllBuildings()); + } + + @GetMapping("/{id}") + public ResponseEntity getBuildingById(@PathVariable final UUID id) { + return ResponseEntity.ok(buildingWebFacade.getBuildingById(id)); + } + + @PutMapping("/{id}") + public ResponseEntity updateBuilding( + @PathVariable final UUID id, + @Valid @NotNull @RequestBody final BuildingRequestDto buildingRequestDto) { + buildingWebFacade.updateBuilding(id, buildingRequestDto); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteBuilding(@PathVariable final UUID id) { + buildingWebFacade.deleteBuilding(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/org/unilab/uniplan/building/BuildingMapper.java b/src/main/java/org/unilab/uniplan/building/BuildingMapper.java new file mode 100644 index 00000000..b7f4d116 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingMapper.java @@ -0,0 +1,26 @@ +package org.unilab.uniplan.building; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.unilab.uniplan.building.dto.BuildingRequestDto; +import org.unilab.uniplan.building.dto.BuildingResponseDto; +import java.util.List; + +@Mapper +public interface BuildingMapper { + @Mapping(target = "id", ignore = true) + @Mapping(target = "university", ignore = true) + Building toEntity(final BuildingRequestDto buildingRequestDto); + + @Mapping(source = "university.id", target = "universityId") + @Mapping(source = "university.uniName", target = "universityName") + BuildingResponseDto toResponseDto(final Building building); + + List toResponseDtoList(final List buildings); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "university", ignore = true) + void updateEntityFromDto(final BuildingRequestDto buildingRequestDto, + @MappingTarget final Building building); +} diff --git a/src/main/java/org/unilab/uniplan/building/BuildingRepository.java b/src/main/java/org/unilab/uniplan/building/BuildingRepository.java new file mode 100644 index 00000000..5ae9ed3f --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingRepository.java @@ -0,0 +1,10 @@ +package org.unilab.uniplan.building; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.UUID; + +@Repository +public interface BuildingRepository extends JpaRepository { + +} diff --git a/src/main/java/org/unilab/uniplan/building/BuildingService.java b/src/main/java/org/unilab/uniplan/building/BuildingService.java new file mode 100644 index 00000000..7b9a4992 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingService.java @@ -0,0 +1,35 @@ +package org.unilab.uniplan.building; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.unilab.uniplan.common.model.BaseService; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class BuildingService implements BaseService { + + private final BuildingRepository buildingRepository; + + @Override + public void save(final Building building) { + buildingRepository.save(building); + } + + @Override + public List getAll() { + return buildingRepository.findAll(); + } + + @Override + public Optional getById(final UUID id) { + return buildingRepository.findById(id); + } + + @Override + public void delete(Building building) { + buildingRepository.delete(building); + } +} diff --git a/src/main/java/org/unilab/uniplan/building/BuildingValidator.java b/src/main/java/org/unilab/uniplan/building/BuildingValidator.java new file mode 100644 index 00000000..60a617c2 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingValidator.java @@ -0,0 +1,29 @@ +package org.unilab.uniplan.building; + +import static org.unilab.uniplan.utils.ErrorConstants.UNIVERSITY_NOT_FOUND; + +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.unilab.uniplan.building.dto.BuildingRequestDto; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.university.UniversityRepository; + +@Component +@RequiredArgsConstructor +public class BuildingValidator { + + private final UniversityRepository universityRepository; + + public void validate(final BuildingRequestDto requestDto) { + validateUniversityExists(requestDto.universityId()); + } + + private void validateUniversityExists(final UUID universityId) { + if (!universityRepository.existsById(universityId)) { + throw new ResourceNotFoundException( + UNIVERSITY_NOT_FOUND.getMessage(String.valueOf(universityId)) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/unilab/uniplan/building/BuildingWebFacade.java b/src/main/java/org/unilab/uniplan/building/BuildingWebFacade.java new file mode 100644 index 00000000..ce295a55 --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/BuildingWebFacade.java @@ -0,0 +1,79 @@ +package org.unilab.uniplan.building; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.unilab.uniplan.building.dto.BuildingRequestDto; +import org.unilab.uniplan.building.dto.BuildingResponseDto; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.university.University; +import org.unilab.uniplan.university.UniversityService; +import java.util.List; +import java.util.UUID; + +import static org.unilab.uniplan.utils.ErrorConstants.BUILDING_NOT_FOUND; +import static org.unilab.uniplan.utils.ErrorConstants.UNIVERSITY_NOT_FOUND; + +@Component +@Slf4j +@RequiredArgsConstructor +public class BuildingWebFacade { + private final BuildingService buildingService; + private final BuildingMapper buildingMapper; + private final UniversityService universityService; + private final BuildingValidator buildingValidator; + + @Transactional + public void createBuilding(final BuildingRequestDto request) { + buildingValidator.validate(request); + + final Building building = buildingMapper.toEntity(request); + building.setUniversity(getUniversityOrThrow(request.universityId())); + buildingService.save(building); + + log.info("created building with ID: {}", building.getId()); + } + + @Transactional + public void updateBuilding(final UUID id, final BuildingRequestDto request) { + buildingValidator.validate(request); + + final Building building = getBuildingOrThrow(id); + buildingMapper.updateEntityFromDto(request, building); + building.setUniversity(getUniversityOrThrow(request.universityId())); + buildingService.save(building); + log.info("updated building with ID: {}", building.getId()); + } + + @Transactional(readOnly = true) + public BuildingResponseDto getBuildingById(final UUID id) { + final Building building = getBuildingOrThrow(id); + return buildingMapper.toResponseDto(building); + } + + @Transactional + public void deleteBuilding(final UUID id) { + final Building building = getBuildingOrThrow(id); + buildingService.delete(building); + log.info("deleted building with ID: {}", id); + } + + @Transactional(readOnly = true) + public List getAllBuildings() { + return buildingMapper.toResponseDtoList(buildingService.getAll()); + } + + private Building getBuildingOrThrow(final UUID id) { + return buildingService.getById(id) + .orElseThrow(() -> new ResourceNotFoundException( + BUILDING_NOT_FOUND.getMessage(String.valueOf(id))) + ); + } + + private University getUniversityOrThrow(final UUID universityId) { + return universityService.getById(universityId) + .orElseThrow(() -> new ResourceNotFoundException( + UNIVERSITY_NOT_FOUND.getMessage(String.valueOf(universityId)))); + } +} diff --git a/src/main/java/org/unilab/uniplan/building/dto/BuildingRequestDto.java b/src/main/java/org/unilab/uniplan/building/dto/BuildingRequestDto.java new file mode 100644 index 00000000..1d0f1f7a --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/dto/BuildingRequestDto.java @@ -0,0 +1,17 @@ +package org.unilab.uniplan.building.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.util.UUID; + +public record BuildingRequestDto ( + @NotBlank(message="Name is required") + @Size(max = 50) + String name, + @NotBlank(message="Address is required") + @Size(max = 50) + String address, + @NotNull(message = "University is required") + UUID universityId +){} diff --git a/src/main/java/org/unilab/uniplan/building/dto/BuildingResponseDto.java b/src/main/java/org/unilab/uniplan/building/dto/BuildingResponseDto.java new file mode 100644 index 00000000..961a7c0b --- /dev/null +++ b/src/main/java/org/unilab/uniplan/building/dto/BuildingResponseDto.java @@ -0,0 +1,11 @@ +package org.unilab.uniplan.building.dto; + +import java.util.UUID; + +public record BuildingResponseDto ( + UUID id, + String name, + String address, + UUID universityId, + String universityName +){} diff --git a/src/main/java/org/unilab/uniplan/category/Category.java b/src/main/java/org/unilab/uniplan/category/Category.java index 437268f9..ff0ca278 100644 --- a/src/main/java/org/unilab/uniplan/category/Category.java +++ b/src/main/java/org/unilab/uniplan/category/Category.java @@ -19,6 +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/java/org/unilab/uniplan/utils/ErrorConstants.java b/src/main/java/org/unilab/uniplan/utils/ErrorConstants.java index a5d9bdca..77c58ed8 100644 --- a/src/main/java/org/unilab/uniplan/utils/ErrorConstants.java +++ b/src/main/java/org/unilab/uniplan/utils/ErrorConstants.java @@ -19,7 +19,8 @@ public enum ErrorConstants { STUDENT_GROUP_NOT_FOUND("Student group with ID {0} not found."), ROOM_CATEGORY_NOT_FOUND("Room category with ID {0} not found."), PROGRAM_DISCIPLINE_NOT_FOUND("Program discipline with ID {0} not found."), - PROGRAM_DISCIPLINE_LECTOR_NOT_FOUND("Program discipline lector with ID {0} not found."); + PROGRAM_DISCIPLINE_LECTOR_NOT_FOUND("Program discipline lector with ID {0} not found."), + BUILDING_NOT_FOUND("Building with ID {0} not found."); private final String message; 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 10432196..6f9b8cd7 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -13,3 +13,11 @@ 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 + - include: + file: db/changelog/20260723134100-drop-not-null-constraint-faculty-room.yaml + - 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 diff --git a/src/test/java/org/unilab/uniplan/building/BuildingServiceTest.java b/src/test/java/org/unilab/uniplan/building/BuildingServiceTest.java new file mode 100644 index 00000000..6edc6145 --- /dev/null +++ b/src/test/java/org/unilab/uniplan/building/BuildingServiceTest.java @@ -0,0 +1,79 @@ +package org.unilab.uniplan.building; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +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; + +@ExtendWith(MockitoExtension.class) +class BuildingServiceTest { + + @Mock + private BuildingRepository buildingRepository; + + @InjectMocks + private BuildingService buildingService; + + private Building building; + private UUID buildingId; + + @BeforeEach + void setUp() { + buildingId = UUID.randomUUID(); + building = new Building(); + } + + @Test + void saveShouldSaveBuilding() { + buildingService.save(building); + + verify(buildingRepository).save(building); + } + + @Test + void getByIdShouldReturnBuildingOptionalIfBuildingExists() { + when(buildingRepository.findById(buildingId)).thenReturn(Optional.of(building)); + + final Optional result = buildingService.getById(buildingId); + + assertEquals(Optional.of(building), result); + verify(buildingRepository).findById(buildingId); + } + + @Test + void getByIdShouldReturnEmptyOptionalIfBuildingDoesNotExist() { + when(buildingRepository.findById(buildingId)).thenReturn(Optional.empty()); + + final Optional result = buildingService.getById(buildingId); + + assertEquals(Optional.empty(), result); + verify(buildingRepository).findById(buildingId); + } + + @Test + void getAllShouldReturnListOfBuildings() { + final List buildings = List.of(building); + when(buildingRepository.findAll()).thenReturn(buildings); + + final List result = buildingService.getAll(); + + assertEquals(buildings, result); + verify(buildingRepository).findAll(); + } + + @Test + void deleteShouldDeleteBuilding() { + buildingService.delete(building); + + verify(buildingRepository).delete(building); + } +} \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/building/BuildingValidatorTest.java b/src/test/java/org/unilab/uniplan/building/BuildingValidatorTest.java new file mode 100644 index 00000000..63f05784 --- /dev/null +++ b/src/test/java/org/unilab/uniplan/building/BuildingValidatorTest.java @@ -0,0 +1,58 @@ +package org.unilab.uniplan.building; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.UUID; +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.building.dto.BuildingRequestDto; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.university.UniversityRepository; + +@ExtendWith(MockitoExtension.class) +class BuildingValidatorTest { + + @Mock + private UniversityRepository universityRepository; + + @InjectMocks + private BuildingValidator buildingValidator; + + private UUID universityId; + private BuildingRequestDto requestDto; + + @BeforeEach + void setUp() { + universityId = UUID.randomUUID(); + requestDto = mock(BuildingRequestDto.class); + + when(requestDto.universityId()).thenReturn(universityId); + } + + @Test + void validate_shouldPass_whenUniversityExists() { + when(universityRepository.existsById(universityId)).thenReturn(true); + + assertDoesNotThrow(() -> buildingValidator.validate(requestDto)); + + verify(universityRepository).existsById(universityId); + } + + @Test + void validate_shouldThrow_whenUniversityDoesNotExist() { + when(universityRepository.existsById(universityId)).thenReturn(false); + + assertThrows(ResourceNotFoundException.class, + () -> buildingValidator.validate(requestDto)); + + verify(universityRepository).existsById(universityId); + } +} \ No newline at end of file diff --git a/src/test/java/org/unilab/uniplan/building/BuildingWebFacadeTest.java b/src/test/java/org/unilab/uniplan/building/BuildingWebFacadeTest.java new file mode 100644 index 00000000..a46ebc2b --- /dev/null +++ b/src/test/java/org/unilab/uniplan/building/BuildingWebFacadeTest.java @@ -0,0 +1,192 @@ +package org.unilab.uniplan.building; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.unilab.uniplan.building.dto.BuildingRequestDto; +import org.unilab.uniplan.building.dto.BuildingResponseDto; +import org.unilab.uniplan.exception.ResourceNotFoundException; +import org.unilab.uniplan.university.University; +import org.unilab.uniplan.university.UniversityService; + +@ExtendWith(MockitoExtension.class) +class BuildingWebFacadeTest { + + @Mock + private BuildingService buildingService; + + @Mock + private BuildingMapper buildingMapper; + + @Mock + private UniversityService universityService; + + @Mock + private BuildingValidator buildingValidator; + + @InjectMocks + private BuildingWebFacade buildingWebFacade; + + private UUID buildingId; + private UUID universityId; + private Building building; + private University university; + private BuildingRequestDto requestDto; + private BuildingResponseDto responseDto; + + @BeforeEach + void setUp() { + buildingId = UUID.randomUUID(); + universityId = UUID.randomUUID(); + building = new Building(); + university = new University(); + requestDto = mock(BuildingRequestDto.class); + responseDto = mock(BuildingResponseDto.class); + } + + @Test + void createBuildingShouldMapResolveUniversityAndSaveBuilding() { + when(requestDto.universityId()).thenReturn(universityId); + when(buildingMapper.toEntity(requestDto)).thenReturn(building); + when(universityService.getById(universityId)).thenReturn(Optional.of(university)); + + buildingWebFacade.createBuilding(requestDto); + + final InOrder inOrder = inOrder(buildingValidator, buildingMapper, universityService, buildingService); + inOrder.verify(buildingValidator).validate(requestDto); + inOrder.verify(buildingMapper).toEntity(requestDto); + inOrder.verify(universityService).getById(universityId); + inOrder.verify(buildingService).save(building); + assertEquals(university, building.getUniversity()); + } + + @Test + void createBuildingShouldThrowIfUniversityDoesNotExist() { + when(requestDto.universityId()).thenReturn(universityId); + when(buildingMapper.toEntity(requestDto)).thenReturn(building); + when(universityService.getById(universityId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> buildingWebFacade.createBuilding(requestDto)); + + verify(buildingValidator).validate(requestDto); + verify(buildingService, never()).save(any(Building.class)); + } + + @Test + void getAllBuildingsShouldReturnResponseDtoList() { + final List buildings = List.of(building); + final List responseDtos = List.of(responseDto); + + when(buildingService.getAll()).thenReturn(buildings); + when(buildingMapper.toResponseDtoList(buildings)).thenReturn(responseDtos); + + final List result = buildingWebFacade.getAllBuildings(); + + assertEquals(responseDtos, result); + verify(buildingService).getAll(); + verify(buildingMapper).toResponseDtoList(buildings); + } + + @Test + void getBuildingByIdShouldReturnResponseDtoIfFound() { + when(buildingService.getById(buildingId)).thenReturn(Optional.of(building)); + when(buildingMapper.toResponseDto(building)).thenReturn(responseDto); + + final BuildingResponseDto result = buildingWebFacade.getBuildingById(buildingId); + + assertEquals(responseDto, result); + verify(buildingService).getById(buildingId); + verify(buildingMapper).toResponseDto(building); + } + + @Test + void getBuildingByIdShouldThrowIfBuildingDoesNotExist() { + when(buildingService.getById(buildingId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> buildingWebFacade.getBuildingById(buildingId)); + + verify(buildingService).getById(buildingId); + verify(buildingMapper, never()).toResponseDto(any(Building.class)); + } + + @Test + void updateBuildingShouldUpdateResolveUniversityAndSaveBuildingIfFound() { + when(requestDto.universityId()).thenReturn(universityId); + when(buildingService.getById(buildingId)).thenReturn(Optional.of(building)); + when(universityService.getById(universityId)).thenReturn(Optional.of(university)); + + buildingWebFacade.updateBuilding(buildingId, requestDto); + + final InOrder inOrder = inOrder(buildingValidator, buildingService, buildingMapper, universityService); + inOrder.verify(buildingValidator).validate(requestDto); + inOrder.verify(buildingService).getById(buildingId); + inOrder.verify(buildingMapper).updateEntityFromDto(requestDto, building); + inOrder.verify(universityService).getById(universityId); + inOrder.verify(buildingService).save(building); + assertEquals(university, building.getUniversity()); + } + + @Test + void updateBuildingShouldThrowIfBuildingDoesNotExist() { + when(buildingService.getById(buildingId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> buildingWebFacade.updateBuilding(buildingId, requestDto)); + + verify(buildingValidator).validate(requestDto); + verify(buildingService).getById(buildingId); + verify(buildingMapper, never()).updateEntityFromDto(any(BuildingRequestDto.class), any(Building.class)); + verify(buildingService, never()).save(any(Building.class)); + } + + @Test + void updateBuildingShouldThrowIfUniversityDoesNotExist() { + when(requestDto.universityId()).thenReturn(universityId); + when(buildingService.getById(buildingId)).thenReturn(Optional.of(building)); + when(universityService.getById(universityId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> buildingWebFacade.updateBuilding(buildingId, requestDto)); + + verify(buildingService, never()).save(any(Building.class)); + } + + @Test + void deleteBuildingShouldDeleteBuildingIfFound() { + when(buildingService.getById(buildingId)).thenReturn(Optional.of(building)); + + buildingWebFacade.deleteBuilding(buildingId); + + verify(buildingService).getById(buildingId); + verify(buildingService).delete(building); + } + + @Test + void deleteBuildingShouldThrowIfBuildingDoesNotExist() { + when(buildingService.getById(buildingId)).thenReturn(Optional.empty()); + + assertThrows(ResourceNotFoundException.class, + () -> buildingWebFacade.deleteBuilding(buildingId)); + + verify(buildingService).getById(buildingId); + verify(buildingService, never()).delete(any(Building.class)); + } +} \ 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/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(); }