diff --git a/images/profile--1.jpg b/images/profile--1.jpg deleted file mode 100644 index 1eb8cec..0000000 Binary files a/images/profile--1.jpg and /dev/null differ diff --git a/images/profile--10.jpg b/images/profile--10.jpg deleted file mode 100644 index 0a82304..0000000 Binary files a/images/profile--10.jpg and /dev/null differ diff --git a/images/profile--11.jpg b/images/profile--11.jpg deleted file mode 100644 index 12f6884..0000000 Binary files a/images/profile--11.jpg and /dev/null differ diff --git a/images/profile--12.jpg b/images/profile--12.jpg deleted file mode 100644 index cc409d6..0000000 Binary files a/images/profile--12.jpg and /dev/null differ diff --git a/images/profile--13.jpg b/images/profile--13.jpg deleted file mode 100644 index f7be936..0000000 Binary files a/images/profile--13.jpg and /dev/null differ diff --git a/images/profile--14.jpg b/images/profile--14.jpg deleted file mode 100644 index e2864e2..0000000 Binary files a/images/profile--14.jpg and /dev/null differ diff --git a/images/profile--15.jpg b/images/profile--15.jpg deleted file mode 100644 index 9d5d79f..0000000 Binary files a/images/profile--15.jpg and /dev/null differ diff --git a/images/profile--16.jpg b/images/profile--16.jpg deleted file mode 100644 index e040697..0000000 Binary files a/images/profile--16.jpg and /dev/null differ diff --git a/images/profile--17.jpg b/images/profile--17.jpg deleted file mode 100644 index 9543c34..0000000 Binary files a/images/profile--17.jpg and /dev/null differ diff --git a/images/profile--18.jpg b/images/profile--18.jpg deleted file mode 100644 index 07b6a60..0000000 Binary files a/images/profile--18.jpg and /dev/null differ diff --git a/images/profile--19.jpg b/images/profile--19.jpg deleted file mode 100644 index 691e8c8..0000000 Binary files a/images/profile--19.jpg and /dev/null differ diff --git a/images/profile--2.jpg b/images/profile--2.jpg deleted file mode 100644 index d64a583..0000000 Binary files a/images/profile--2.jpg and /dev/null differ diff --git a/images/profile--20.jpg b/images/profile--20.jpg deleted file mode 100644 index 88dd854..0000000 Binary files a/images/profile--20.jpg and /dev/null differ diff --git a/images/profile--21.jpg b/images/profile--21.jpg deleted file mode 100644 index b7ae48b..0000000 Binary files a/images/profile--21.jpg and /dev/null differ diff --git a/images/profile--22.jpg b/images/profile--22.jpg deleted file mode 100644 index 48702e3..0000000 Binary files a/images/profile--22.jpg and /dev/null differ diff --git a/images/profile--23.jpg b/images/profile--23.jpg deleted file mode 100644 index e58964f..0000000 Binary files a/images/profile--23.jpg and /dev/null differ diff --git a/images/profile--24.jpg b/images/profile--24.jpg deleted file mode 100644 index d495869..0000000 Binary files a/images/profile--24.jpg and /dev/null differ diff --git a/images/profile--25.jpg b/images/profile--25.jpg deleted file mode 100644 index a26051f..0000000 Binary files a/images/profile--25.jpg and /dev/null differ diff --git a/images/profile--26.jpg b/images/profile--26.jpg deleted file mode 100644 index c9816f8..0000000 Binary files a/images/profile--26.jpg and /dev/null differ diff --git a/images/profile--3.jpg b/images/profile--3.jpg deleted file mode 100644 index 27435b3..0000000 Binary files a/images/profile--3.jpg and /dev/null differ diff --git a/images/profile--4.jpg b/images/profile--4.jpg deleted file mode 100644 index a2e0224..0000000 Binary files a/images/profile--4.jpg and /dev/null differ diff --git a/images/profile--5.jpg b/images/profile--5.jpg deleted file mode 100644 index 9f1fa1f..0000000 Binary files a/images/profile--5.jpg and /dev/null differ diff --git a/images/profile--6.jpg b/images/profile--6.jpg deleted file mode 100644 index 4ba8b1e..0000000 Binary files a/images/profile--6.jpg and /dev/null differ diff --git a/images/profile--7.jpg b/images/profile--7.jpg deleted file mode 100644 index 68ab88a..0000000 Binary files a/images/profile--7.jpg and /dev/null differ diff --git a/images/profile--8.jpg b/images/profile--8.jpg deleted file mode 100644 index 4a50826..0000000 Binary files a/images/profile--8.jpg and /dev/null differ diff --git a/images/profile--9.jpg b/images/profile--9.jpg deleted file mode 100644 index 385e7ad..0000000 Binary files a/images/profile--9.jpg and /dev/null differ diff --git a/src/main/java/com/example/nto/domain/entity/Passage.java b/src/main/java/com/example/nto/domain/entity/Passage.java index c6b14d0..439a77f 100644 --- a/src/main/java/com/example/nto/domain/entity/Passage.java +++ b/src/main/java/com/example/nto/domain/entity/Passage.java @@ -25,7 +25,7 @@ public class Passage { @Column(name = "passage", unique = true) @NotBlank(message = "Название не может быть пустым!") @Size(max = 100, message = "Максимальная длина названия 100 символов!") - private String passage; + private String passageName; @OneToMany(mappedBy = "passage") private List visits; diff --git a/src/main/java/com/example/nto/domain/entity/Terminal.java b/src/main/java/com/example/nto/domain/entity/Terminal.java index c8d1639..2bacdf8 100644 --- a/src/main/java/com/example/nto/domain/entity/Terminal.java +++ b/src/main/java/com/example/nto/domain/entity/Terminal.java @@ -31,6 +31,7 @@ public class Terminal { // Мне нужна была рандомная генерация кода для терминала, так что я мог сделать кривую реализацию через самописную функцию, // но боялся, что она будет генерировать не уникальные значения. (я очень смутно представляю, как эта штука работает) // Код взят отсюда: https://stackoverflow.com/questions/25082244/auto-generate-unique-random-string-in-spring-mvc-hibernate + // todo: Понять что это такое....................................................................................... @GenericGenerator(name = "uuid-gen", strategy = "uuid") @GeneratedValue(generator = "uuid-gen") @NotBlank(message = "Код не может быть пустым!") diff --git a/src/main/java/com/example/nto/domain/entity/Visit.java b/src/main/java/com/example/nto/domain/entity/Visit.java index 7b30d9f..691cfb6 100644 --- a/src/main/java/com/example/nto/domain/entity/Visit.java +++ b/src/main/java/com/example/nto/domain/entity/Visit.java @@ -30,7 +30,7 @@ public class Visit { private LocalDateTime endVisit; @Column(name = "is_finished", nullable = false) - private final boolean isFinished = false; + private boolean isFinished = false; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "start_terminal_id", referencedColumnName = "code", nullable = false) diff --git a/src/main/java/com/example/nto/domain/exception/AccessDeniedException.java b/src/main/java/com/example/nto/domain/exception/AccessDeniedException.java new file mode 100644 index 0000000..eb0c993 --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/AccessDeniedException.java @@ -0,0 +1,8 @@ +package com.example.nto.domain.exception; + +public class AccessDeniedException extends RuntimeException { + public AccessDeniedException(String message) { + // Доступ запрещен. + super(); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/ConflictResourceException.java b/src/main/java/com/example/nto/domain/exception/ConflictResourceException.java new file mode 100644 index 0000000..9b13b8b --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/ConflictResourceException.java @@ -0,0 +1,8 @@ +package com.example.nto.domain.exception; + +public class ConflictResourceException extends RuntimeException { + public ConflictResourceException(String message) { + // Вызывается, когда данные в таблицах конфликтуют. + super(message); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/ImageSendException.java b/src/main/java/com/example/nto/domain/exception/ImageSendException.java new file mode 100644 index 0000000..478bd44 --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/ImageSendException.java @@ -0,0 +1,8 @@ +package com.example.nto.domain.exception; + +public class ImageSendException extends RuntimeException { + public ImageSendException(String message) { + // Вызывается при ошибке во время отправки изображения. + super(message); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/ImageUploadException.java b/src/main/java/com/example/nto/domain/exception/ImageUploadException.java new file mode 100644 index 0000000..4f48526 --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/ImageUploadException.java @@ -0,0 +1,7 @@ +package com.example.nto.domain.exception; + +public class ImageUploadException extends RuntimeException { + public ImageUploadException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/ResourceNotFoundException.java b/src/main/java/com/example/nto/domain/exception/ResourceNotFoundException.java new file mode 100644 index 0000000..900fdbc --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/ResourceNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.nto.domain.exception; + +public class ResourceNotFoundException extends RuntimeException { + public ResourceNotFoundException(String message) { + // Вызывается, когда что-то не найдено в бд. + super(message); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/advice/ExceptionApiHandler.java b/src/main/java/com/example/nto/domain/exception/advice/ExceptionApiHandler.java new file mode 100644 index 0000000..badc29c --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/advice/ExceptionApiHandler.java @@ -0,0 +1,36 @@ +package com.example.nto.domain.exception.advice; + +import com.amazonaws.SdkBaseException; +import com.amazonaws.SdkClientException; +import com.amazonaws.services.s3.model.AmazonS3Exception; +import com.example.nto.domain.exception.model.ApiError; +import com.example.nto.utils.Utils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.util.concurrent.ExecutionException; + +import static com.example.nto.utils.DataFormatType.DATE_TIME; + +@Slf4j +@ControllerAdvice +public class ExceptionApiHandler { + @ExceptionHandler({AmazonS3Exception.class, SdkClientException.class}) + public ResponseEntity amazonS3Exception(SdkBaseException e) { + return new ResponseEntity<>( + new ApiError("500", "Что-то пошло не так с AWS SDK.", e.getMessage(), Utils.nowTime(DATE_TIME)), + HttpStatus.INTERNAL_SERVER_ERROR + ); + } + + @ExceptionHandler({InterruptedException.class, ExecutionException.class}) + public ResponseEntity runtimeException(RuntimeException e) { + return new ResponseEntity<>( + new ApiError("500", "Один из потоков завершился исключением.", e.getMessage(), Utils.nowTime(DATE_TIME)), + HttpStatus.INTERNAL_SERVER_ERROR + ); + } +} diff --git a/src/main/java/com/example/nto/domain/exception/advice/GlobalExceptionalHandler.java b/src/main/java/com/example/nto/domain/exception/advice/GlobalExceptionalHandler.java index cbe6965..b3b167d 100644 --- a/src/main/java/com/example/nto/domain/exception/advice/GlobalExceptionalHandler.java +++ b/src/main/java/com/example/nto/domain/exception/advice/GlobalExceptionalHandler.java @@ -1,8 +1,7 @@ package com.example.nto.domain.exception.advice; -import com.example.nto.domain.exception.CodeNotFoundException; -import com.example.nto.domain.exception.EmployeeNotFoundException; -import com.example.nto.domain.exception.SomethingWentWrongException; +import com.amazonaws.services.organizations.model.ConstraintViolationException; +import com.example.nto.domain.exception.*; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -27,4 +26,36 @@ public class GlobalExceptionalHandler { public ResponseEntity handlerSomethingWentWrongException(SomethingWentWrongException e) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(AccessDeniedException.class) + public ResponseEntity handlerAccessDeniedException(AccessDeniedException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity handlerAccessDeniedException(ResourceNotFoundException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(ConflictResourceException.class) + public ResponseEntity handlerConflictResourceException(ConflictResourceException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); + } + + @ExceptionHandler(ImageUploadException.class) + public ResponseEntity handlerImageUploadException(ImageUploadException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(ImageSendException.class) + public ResponseEntity handlerImageSendException(ImageSendException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity handlerConstraintViolationException(ConstraintViolationException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } } + + diff --git a/src/main/java/com/example/nto/domain/exception/model/ApiError.java b/src/main/java/com/example/nto/domain/exception/model/ApiError.java new file mode 100644 index 0000000..f3a335e --- /dev/null +++ b/src/main/java/com/example/nto/domain/exception/model/ApiError.java @@ -0,0 +1,14 @@ +package com.example.nto.domain.exception.model; + + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class ApiError { + private String status; // Код статуса HTTP-ответа + private String reason; // Общее описание причины ошибки + private String message; // Сообщение об ошибке + private String timestamp; // Дата и время когда произошла ошибка (в формате "yyyy-MM-dd HH:mm:ss") +} diff --git a/src/main/java/com/example/nto/dto/entity/VisitDTO.java b/src/main/java/com/example/nto/dto/entity/VisitDTO.java index 442963a..0c047f9 100644 --- a/src/main/java/com/example/nto/dto/entity/VisitDTO.java +++ b/src/main/java/com/example/nto/dto/entity/VisitDTO.java @@ -24,4 +24,6 @@ public class VisitDTO { // превратить обратно можно с помощью LocalDateTime.parse(). private String durationVisit; private String officeName; + + private String typePassage; // Строка либо PASSAGE_CARD, либо PASSAGE_TELEPHONE } diff --git a/src/main/java/com/example/nto/dto/entity/employee/EmployeeDTO.java b/src/main/java/com/example/nto/dto/entity/employee/EmployeeDTO.java index ac9698f..7ee995a 100644 --- a/src/main/java/com/example/nto/dto/entity/employee/EmployeeDTO.java +++ b/src/main/java/com/example/nto/dto/entity/employee/EmployeeDTO.java @@ -16,6 +16,7 @@ public class EmployeeDTO { private String name; private String surname; private String patronymic; + private String aboutMe; private String telephone; private String email; @@ -23,7 +24,7 @@ public class EmployeeDTO { private String officeName; private String officeImageUrl; - private String position; // Название должности + private String positionName; // Название должности private String role; // строка либо ROLE_USER, либо ROLE_ADMIN private String profileImageUrl; diff --git a/src/main/java/com/example/nto/dto/mappers/OfficeMapper.java b/src/main/java/com/example/nto/dto/mappers/OfficeMapper.java index 193555d..ae651bb 100644 --- a/src/main/java/com/example/nto/dto/mappers/OfficeMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/OfficeMapper.java @@ -1,4 +1,48 @@ package com.example.nto.dto.mappers; +import com.example.nto.domain.entity.Office; +import com.example.nto.dto.entity.OfficeDTO; +import com.example.nto.dto.mappers.employee.EmployeeItemMapper; +import lombok.experimental.UtilityClass; + +import java.util.stream.Collectors; + +@UtilityClass public class OfficeMapper { + public static OfficeDTO convertToDTO(Office office) { + OfficeDTO officeDTO = new OfficeDTO(); + + officeDTO.setId(office.getId()); + officeDTO.setName(office.getName()); + officeDTO.setDescription(office.getDescription()); + officeDTO.setAddress(office.getAddress()); + officeDTO.setLatitude(office.getLatitude()); + officeDTO.setLongitude(office.getLongitude()); + officeDTO.setLinkLogo(office.getLinkLogo()); + officeDTO.setTelephone(office.getTelephone()); + officeDTO.setEmail(office.getEmail()); + + officeDTO.setEmployees(office.getEmployeeList().stream().map(EmployeeItemMapper::convertToDTO).collect(Collectors.toList())); + officeDTO.setTerminals(office.getTerminals().stream().map(TerminalMapper::convertToDTO).collect(Collectors.toList())); + + return officeDTO; + } + + public static Office convertFromDTO(OfficeDTO officeDTO) { + Office office = new Office(); + + office.setId(officeDTO.getId()); + office.setName(officeDTO.getName()); + office.setDescription(officeDTO.getDescription()); + office.setAddress(officeDTO.getAddress()); + office.setLatitude(officeDTO.getLatitude()); + office.setLongitude(officeDTO.getLongitude()); + office.setLinkLogo(officeDTO.getLinkLogo()); + office.setTelephone(officeDTO.getTelephone()); + office.setEmail(officeDTO.getEmail()); + + // todo: Проверить, возможно, здесь нужно office.setEmployeeList() и office.setTerminals() + + return office; + } } diff --git a/src/main/java/com/example/nto/dto/mappers/PositionMapper.java b/src/main/java/com/example/nto/dto/mappers/PositionMapper.java index 486b848..5ec7a0e 100644 --- a/src/main/java/com/example/nto/dto/mappers/PositionMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/PositionMapper.java @@ -1,4 +1,21 @@ package com.example.nto.dto.mappers; +import com.example.nto.domain.entity.Position; +import com.example.nto.dto.entity.PositionDTO; +import com.example.nto.dto.mappers.employee.EmployeeItemMapper; +import lombok.experimental.UtilityClass; + +import java.util.stream.Collectors; + +@UtilityClass public class PositionMapper { -} + public static PositionDTO convertToDTO(Position position) { + PositionDTO positionDTO = new PositionDTO(); + + positionDTO.setId(position.getId()); + positionDTO.setName(position.getName()); + positionDTO.setEmployeeItemDTOList(position.getEmployees().stream().map(EmployeeItemMapper::convertToDTO).collect(Collectors.toList())); + + return positionDTO; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/dto/mappers/TerminalMapper.java b/src/main/java/com/example/nto/dto/mappers/TerminalMapper.java index 168c442..e9defbf 100644 --- a/src/main/java/com/example/nto/dto/mappers/TerminalMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/TerminalMapper.java @@ -1,4 +1,29 @@ package com.example.nto.dto.mappers; +import com.example.nto.domain.entity.Office; +import com.example.nto.domain.entity.Terminal; +import com.example.nto.dto.entity.TerminalDTO; +import lombok.experimental.UtilityClass; + +@UtilityClass public class TerminalMapper { + public static TerminalDTO convertToDTO(Terminal terminal) { + TerminalDTO terminalDTO = new TerminalDTO(); + + terminalDTO.setId(terminal.getId()); + terminalDTO.setName(terminal.getName()); + terminalDTO.setCode(terminal.getCode()); + terminalDTO.setOfficeName(terminal.getOffice().getName()); + + return terminalDTO; + } + + public static Terminal convertFromDTO(TerminalDTO terminalDTO, Office office) { + Terminal terminal = new Terminal(); + + terminal.setName(terminalDTO.getName()); + terminal.setOffice(office); + + return terminal; + } } diff --git a/src/main/java/com/example/nto/dto/mappers/VisitMapper.java b/src/main/java/com/example/nto/dto/mappers/VisitMapper.java index 8d969c8..98f44f8 100644 --- a/src/main/java/com/example/nto/dto/mappers/VisitMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/VisitMapper.java @@ -1,4 +1,42 @@ package com.example.nto.dto.mappers; + +import com.example.nto.domain.entity.Employee; +import com.example.nto.domain.entity.Passage; +import com.example.nto.domain.entity.Terminal; +import com.example.nto.domain.entity.Visit; +import com.example.nto.dto.entity.VisitDTO; +import com.example.nto.utils.Utils; +import lombok.experimental.UtilityClass; + +import java.time.LocalDateTime; + +@UtilityClass public class VisitMapper { + public static VisitDTO convertToDTO(Visit visit) { + VisitDTO visitDTO = new VisitDTO(); + + visitDTO.setId(visit.getId()); + visitDTO.setStartVisit(visit.getStartVisit().toString()); + visitDTO.setEndVisit(visit.getEndVisit().toString()); + visitDTO.setFinished(visit.isFinished()); + visitDTO.setDurationVisit(Utils.period(visit.getStartVisit(), visit.getEndVisit()).toString()); + visitDTO.setOfficeName(visit.getStartTerminal().getOffice().getName()); + visitDTO.setTypePassage(visit.getPassage().getPassageName()); + + return visitDTO; + } + + public static Visit convertFromDTO(Terminal terminal, Employee employee, Passage passage) { + Visit visit = new Visit(); + + visit.setEmployee(employee); + visit.setStartVisit(LocalDateTime.now()); + visit.setFinished(false); + visit.setStartTerminal(terminal); + visit.setPassage(passage); + + return visit; + } } + diff --git a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeCreateMapper.java b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeCreateMapper.java index 4a2098d..fb751e5 100644 --- a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeCreateMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeCreateMapper.java @@ -26,6 +26,7 @@ public class EmployeeCreateMapper { employee.setPosition(position); employee.setRole(role); employee.setProfileImageUrl(Utils.getRandomUrlProfileImage()); + employee.setBlocked(false); return employee; } diff --git a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeItemMapper.java b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeItemMapper.java index 1fffbe6..68cf90d 100644 --- a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeItemMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeItemMapper.java @@ -1,4 +1,31 @@ package com.example.nto.dto.mappers.employee; +import com.example.nto.domain.entity.Employee; +import com.example.nto.domain.entity.Visit; +import com.example.nto.dto.entity.employee.EmployeeItemDTO; +import com.example.nto.utils.Utils; +import lombok.experimental.UtilityClass; + +import java.util.List; + +@UtilityClass public class EmployeeItemMapper { + public static EmployeeItemDTO convertToDTO(Employee employee) { + EmployeeItemDTO employeeItemDTO = new EmployeeItemDTO(); + employeeItemDTO.setId(employee.getId()); + employeeItemDTO.setName(employee.getName()); + employeeItemDTO.setSurname(employee.getSurname()); + employeeItemDTO.setPatronymic(employee.getPatronymic()); + employeeItemDTO.setProfileImageUrl(employee.getProfileImageUrl()); + employeeItemDTO.setOfficeName(employee.getOffice().getName()); + employeeItemDTO.setPosition(employee.getPosition().getName()); + employeeItemDTO.setBlocked(employee.isBlocked()); + + // todo: Протестировать работу! + + List visitsLast30Days = Utils.filterDateLast30Days(employee.getVisits()); + employeeItemDTO.setVisitStatus(visitsLast30Days.stream().anyMatch(visit -> !visit.isFinished())); + + return employeeItemDTO; + } } diff --git a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeMapper.java b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeMapper.java index 5d3b16b..8504852 100644 --- a/src/main/java/com/example/nto/dto/mappers/employee/EmployeeMapper.java +++ b/src/main/java/com/example/nto/dto/mappers/employee/EmployeeMapper.java @@ -1,4 +1,81 @@ package com.example.nto.dto.mappers.employee; +import com.example.nto.domain.entity.*; +import com.example.nto.dto.entity.employee.EmployeeDTO; +import com.example.nto.utils.Utils; +import lombok.experimental.UtilityClass; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@UtilityClass public class EmployeeMapper { + public static EmployeeDTO convertToDTO(Employee employee) { + EmployeeDTO employeeDTO = new EmployeeDTO(); + + employeeDTO.setId(employee.getId()); + employeeDTO.setName(employee.getName()); + employeeDTO.setSurname(employee.getSurname()); + employeeDTO.setPatronymic(employee.getPatronymic()); + employeeDTO.setAboutMe(employeeDTO.getAboutMe()); + employeeDTO.setTelephone(employee.getTelephone()); + employeeDTO.setEmail(employee.getEmail()); + + employeeDTO.setOfficeId(employee.getOffice().getId()); + employeeDTO.setOfficeName(employee.getOffice().getName()); + employeeDTO.setOfficeImageUrl(employee.getOffice().getLinkLogo()); + employeeDTO.setPositionName(employee.getPosition().getName()); + employeeDTO.setRole(employee.getRole().getRoleName()); + employeeDTO.setRole(employee.getProfileImageUrl()); + employeeDTO.setBlocked(employee.isBlocked()); + + List visitsLast30Days = Utils.filterDateLast30Days(employee.getVisits()); + + boolean visitStatus = false; + String startVisitDateTime = null; + String currentOfficeName = null; + List visitsIdLast30Days = new ArrayList<>(visitsLast30Days.size()); + List> periods = new ArrayList<>(visitsLast30Days.size()); + + for (Visit visit : visitsLast30Days) { + if (!visit.isFinished()) { + if (visitStatus) throw new IllegalStateException("У работника два посещения одновременно!"); + + visitStatus = true; + startVisitDateTime = visit.getStartVisit().toString(); + currentOfficeName = visit.getStartTerminal().getOffice().getName(); + } + visitsIdLast30Days.add(visit.getId()); + periods.add(List.of(visit.getStartVisit(), visit.getEndVisit())); + } + + employeeDTO.setVisitStatus(visitStatus); + employeeDTO.setStartVisitDateTime(startVisitDateTime); + employeeDTO.setCurrentOfficeName(currentOfficeName); + employeeDTO.setVisitsIdLast30Days(visitsIdLast30Days); + employeeDTO.setTotalTimeVisitsLast30Days(Utils.periods(periods)); + employeeDTO.setCreateAt(employee.getCreatedAt().toString()); + + return employeeDTO; + } + + public static Employee convertFromDTO(EmployeeDTO employeeDTO, Office office, Position position, Role role) { + Employee employee = new Employee(); + + employee.setName(employeeDTO.getName()); + employee.setSurname(employeeDTO.getSurname()); + employee.setPatronymic(employeeDTO.getPatronymic()); + employeeDTO.setAboutMe(employee.getAboutMe()); + employee.setTelephone(employeeDTO.getTelephone()); + employee.setEmail(employeeDTO.getEmail()); + employee.setOffice(office); + employee.setPosition(position); + employee.setRole(role); + employee.setProfileImageUrl(employeeDTO.getProfileImageUrl()); + employee.setBlocked(employeeDTO.isBlocked()); + + return employee; + } } + diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java new file mode 100644 index 0000000..55c9604 --- /dev/null +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -0,0 +1,11 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Employee; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface EmployeeRepository extends JpaRepository { + Optional findByEmail(String email); + Optional findByTelephone(String telephone); +} diff --git a/src/main/java/com/example/nto/repository/OfficeRepository.java b/src/main/java/com/example/nto/repository/OfficeRepository.java new file mode 100644 index 0000000..af6c7e5 --- /dev/null +++ b/src/main/java/com/example/nto/repository/OfficeRepository.java @@ -0,0 +1,10 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Office; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface OfficeRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/src/main/java/com/example/nto/repository/PassageRepository.java b/src/main/java/com/example/nto/repository/PassageRepository.java new file mode 100644 index 0000000..bca03b7 --- /dev/null +++ b/src/main/java/com/example/nto/repository/PassageRepository.java @@ -0,0 +1,10 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Passage; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PassageRepository extends JpaRepository { + Optional findByPassageName(String passageName); +} diff --git a/src/main/java/com/example/nto/repository/PositionRepository.java b/src/main/java/com/example/nto/repository/PositionRepository.java new file mode 100644 index 0000000..aba1527 --- /dev/null +++ b/src/main/java/com/example/nto/repository/PositionRepository.java @@ -0,0 +1,10 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Position; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PositionRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/src/main/java/com/example/nto/repository/RoleRepository.java b/src/main/java/com/example/nto/repository/RoleRepository.java new file mode 100644 index 0000000..a3c713d --- /dev/null +++ b/src/main/java/com/example/nto/repository/RoleRepository.java @@ -0,0 +1,10 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface RoleRepository extends JpaRepository { + Optional findByRoleName(String roleName); +} diff --git a/src/main/java/com/example/nto/repository/TerminalRepository.java b/src/main/java/com/example/nto/repository/TerminalRepository.java new file mode 100644 index 0000000..e91bc1d --- /dev/null +++ b/src/main/java/com/example/nto/repository/TerminalRepository.java @@ -0,0 +1,10 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Terminal; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface TerminalRepository extends JpaRepository { + Optional findByCode(String code); +} diff --git a/src/main/java/com/example/nto/repository/VisitRepository.java b/src/main/java/com/example/nto/repository/VisitRepository.java new file mode 100644 index 0000000..196c0b0 --- /dev/null +++ b/src/main/java/com/example/nto/repository/VisitRepository.java @@ -0,0 +1,7 @@ +package com.example.nto.repository; + +import com.example.nto.domain.entity.Visit; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VisitRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java new file mode 100644 index 0000000..743fd45 --- /dev/null +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -0,0 +1,23 @@ +package com.example.nto.service; + +import com.example.nto.dto.entity.employee.EmployeeCreateDTO; +import com.example.nto.dto.entity.employee.EmployeeDTO; +import com.example.nto.dto.entity.employee.EmployeeItemDTO; + +import java.util.List; + +public interface EmployeeService { + List getAll(); + List getWorkingEmployee(boolean isWorking); + + EmployeeDTO getById(long employeeId); + EmployeeDTO getByEmail(String email); + EmployeeDTO getByTelephone(String telephone); + + EmployeeDTO create(EmployeeCreateDTO employeeCreateDTO); + EmployeeDTO update(long employeeId, EmployeeDTO employeeDTO); + void delete(long employeeId); + + void patchProfileImage(long employeeId, String imageUrl); + void patchBlockEmployee(long employeeId, boolean blockStatus); +} diff --git a/src/main/java/com/example/nto/service/OfficeService.java b/src/main/java/com/example/nto/service/OfficeService.java new file mode 100644 index 0000000..d80a22c --- /dev/null +++ b/src/main/java/com/example/nto/service/OfficeService.java @@ -0,0 +1,15 @@ +package com.example.nto.service; + +import com.example.nto.dto.entity.OfficeDTO; + +import java.util.List; + +public interface OfficeService { + List getAllOffice(); + List getAllSortedDistance(double userLatitude, double userLongitude); + OfficeDTO getById(long officeId); + + OfficeDTO create(OfficeDTO officeDTO); + OfficeDTO update(long officeId, OfficeDTO officeDTO); + void delete(long officeId); +} diff --git a/src/main/java/com/example/nto/service/TerminalService.java b/src/main/java/com/example/nto/service/TerminalService.java new file mode 100644 index 0000000..6ac7ae0 --- /dev/null +++ b/src/main/java/com/example/nto/service/TerminalService.java @@ -0,0 +1,16 @@ +package com.example.nto.service; + +import com.example.nto.dto.entity.TerminalDTO; + +import java.util.List; + +public interface TerminalService { + List getAllTerminal(); + TerminalDTO getById(long terminalId); + + TerminalDTO create(TerminalDTO terminalDTO); + TerminalDTO update(long terminalId, TerminalDTO terminalDTO); + void delete(long terminalId); + + TerminalDTO checkCode(String code); +} diff --git a/src/main/java/com/example/nto/service/VisitService.java b/src/main/java/com/example/nto/service/VisitService.java new file mode 100644 index 0000000..83180ee --- /dev/null +++ b/src/main/java/com/example/nto/service/VisitService.java @@ -0,0 +1,21 @@ +package com.example.nto.service; + +import com.example.nto.dto.entity.VisitDTO; + +import java.time.LocalDateTime; +import java.util.List; + +public interface VisitService { + List getAll(); + List getAllVisitByEmployee(long employeeId); + List getAllVisitByPeriod(LocalDateTime start, LocalDateTime stop); + List getAllFinished(boolean isFinished); + + VisitDTO getById(long visitId); + VisitDTO open(long employeeId, long startTerminalId, String passageName); + void exit(long employeeId, long endTerminalId); + + // update не нужен он не будет использоваться :) + + void delete(long visitId); +} diff --git a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java new file mode 100644 index 0000000..4b277c0 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -0,0 +1,156 @@ +package com.example.nto.service.impl; + +import com.example.nto.aspect.annotation.LogExample; +import com.example.nto.domain.entity.*; +import com.example.nto.domain.exception.ConflictResourceException; +import com.example.nto.domain.exception.ResourceNotFoundException; +import com.example.nto.dto.entity.employee.EmployeeCreateDTO; +import com.example.nto.dto.entity.employee.EmployeeDTO; +import com.example.nto.dto.entity.employee.EmployeeItemDTO; +import com.example.nto.dto.mappers.employee.EmployeeCreateMapper; +import com.example.nto.dto.mappers.employee.EmployeeItemMapper; +import com.example.nto.dto.mappers.employee.EmployeeMapper; +import com.example.nto.repository.EmployeeRepository; +import com.example.nto.repository.OfficeRepository; +import com.example.nto.repository.PositionRepository; +import com.example.nto.repository.RoleRepository; +import com.example.nto.service.EmployeeService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class EmployeeServiceImpl implements EmployeeService { + private final EmployeeRepository employeeRepository; + private final OfficeRepository officeRepository; + private final RoleRepository roleRepository; + private final PositionRepository positionRepository; + private final PasswordEncoder passwordEncoder; + + @Override + @LogExample + public List getAll() { + return employeeRepository.findAll().stream().map(EmployeeItemMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public List getWorkingEmployee(boolean isWorking) { + return employeeRepository.findAll().stream().filter(employee -> checkWorking(employee, isWorking)) + .map(EmployeeItemMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public EmployeeDTO getById(long employeeId) { + return employeeRepository.findById(employeeId).map(EmployeeMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + } + + @Override + @LogExample + public EmployeeDTO getByEmail(String email) { + return employeeRepository.findByEmail(email).map(EmployeeMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Работник с email (" + email + ") не найден!")); + } + + @Override + @LogExample + public EmployeeDTO getByTelephone(String telephone) { + return employeeRepository.findByTelephone(telephone).map(EmployeeMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Работник с telephone (" + telephone + ") не найден!")); + } + + @Override + @LogExample + public EmployeeDTO create(EmployeeCreateDTO employeeCreateDTO) { + Optional employeeEmail = employeeRepository.findByEmail(employeeCreateDTO.getEmail()); + Optional employeeTelephone = employeeRepository.findByTelephone(employeeCreateDTO.getTelephone()); + + if (employeeEmail.isPresent() || employeeTelephone.isPresent()) { + throw new ConflictResourceException("Пользователь с таким email или телефоном уже существует!"); + } + + Office office = officeRepository.findByName(employeeCreateDTO.getOfficeName()) + .orElseThrow(() -> new ResourceNotFoundException("Офис с именем (" + employeeCreateDTO.getOfficeName() + ") не найден!")); + Position position = positionRepository.findByName(employeeCreateDTO.getPositionName()) + .orElseThrow(() -> new ResourceNotFoundException("Позиция с именем (" + employeeCreateDTO.getPositionName() + ") не найден!")); + Role role = roleRepository.findByRoleName(employeeCreateDTO.getRole()) + .orElseThrow(() -> new ResourceNotFoundException("Роль с названием (" + employeeCreateDTO.getRole() + ") не найден!")); + + return EmployeeMapper.convertToDTO(employeeRepository.save( + EmployeeCreateMapper.convertFromDTO(employeeCreateDTO, passwordEncoder.encode(employeeCreateDTO.getPassword()), office, position, role))); + } + + @Override + @LogExample + public EmployeeDTO update(long employeeId, EmployeeDTO employeeDTO) { + Employee employee = employeeRepository.findById(employeeId) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + + Optional employeeEmail = employeeRepository.findByEmail(employeeDTO.getEmail()); + Optional employeeTelephone = employeeRepository.findByTelephone(employeeDTO.getTelephone()); + + if (employeeEmail.isPresent() || employeeTelephone.isPresent()) { + throw new ConflictResourceException("Пользователь с таким email или телефоном уже существует!"); + } + + Office office = officeRepository.findByName(employeeDTO.getOfficeName()) + .orElseThrow(() -> new ResourceNotFoundException("Офис с именем (" + employeeDTO.getOfficeName() + ") не найден!")); + Position position = positionRepository.findByName(employeeDTO.getPositionName()) + .orElseThrow(() -> new ResourceNotFoundException("Позиция с именем (" + employeeDTO.getPositionName() + ") не найден!")); + + employee.setName(employeeDTO.getName()); + employee.setSurname(employeeDTO.getSurname()); + employee.setPatronymic(employeeDTO.getPatronymic()); + employee.setAboutMe(employeeDTO.getAboutMe()); + employee.setTelephone(employee.getTelephone()); + employee.setEmail(employee.getEmail()); + employee.setOffice(office); + employee.setPosition(position); + + // profileImageUrl меняется в отдельном эндпоинте + + employee.setBlocked(employeeDTO.isBlocked()); + + return EmployeeMapper.convertToDTO(employeeRepository.save(employee)); + } + + @Override + @LogExample + public void delete(long employeeId) { + employeeRepository.findById(employeeId).orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + employeeRepository.deleteById(employeeId); + } + + @Override + @LogExample + public void patchProfileImage(long employeeId, String imageUrl) { + Employee employee = employeeRepository.findById(employeeId) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + employee.setProfileImageUrl(imageUrl); + employeeRepository.save(employee); + } + + @Override + @LogExample + public void patchBlockEmployee(long employeeId, boolean blockStatus) { + Employee employee = employeeRepository.findById(employeeId) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + employee.setBlocked(blockStatus); + employeeRepository.save(employee); + } + + private static boolean checkWorking(Employee employee, boolean isWorking) { + List visits = employee.getVisits().stream().filter(visit -> !visit.isFinished()).collect(Collectors.toList()); + + if (visits.isEmpty()) return !isWorking; + else if (visits.size() == 1) return isWorking; + else throw new IllegalStateException("Пользователь не может находится в суперпозиции"); + } +} diff --git a/src/main/java/com/example/nto/service/impl/OfficeServiceImpl.java b/src/main/java/com/example/nto/service/impl/OfficeServiceImpl.java new file mode 100644 index 0000000..608d478 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/OfficeServiceImpl.java @@ -0,0 +1,84 @@ +package com.example.nto.service.impl; + +import com.example.nto.aspect.annotation.LogExample; +import com.example.nto.domain.entity.Office; +import com.example.nto.domain.exception.ResourceNotFoundException; +import com.example.nto.dto.entity.OfficeDTO; +import com.example.nto.dto.mappers.OfficeMapper; +import com.example.nto.repository.OfficeRepository; +import com.example.nto.service.OfficeService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.awt.geom.Point2D; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class OfficeServiceImpl implements OfficeService { + private final OfficeRepository officeRepository; + + @Override + @LogExample + public List getAllOffice() { + return officeRepository.findAll().stream().map(OfficeMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public List getAllSortedDistance(double userLatitude, double userLongitude) { + return officeRepository.findAll().stream().map(OfficeMapper::convertToDTO) + .sorted(createComparator(new Point2D.Double(userLatitude, userLongitude))).collect(Collectors.toList()); + } + + @Override + @LogExample + public OfficeDTO getById(long officeId) { + return officeRepository.findById(officeId).map(OfficeMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Офис с id (" + officeId + ") не найден!")); + } + + @Override + @LogExample + public OfficeDTO create(OfficeDTO officeDTO) { + return OfficeMapper.convertToDTO(officeRepository.save(OfficeMapper.convertFromDTO(officeDTO))); + } + + @Override + @LogExample + public OfficeDTO update(long officeId, OfficeDTO officeDTO) { + Office office = officeRepository.findById(officeId) + .orElseThrow(() -> new ResourceNotFoundException("Офис с id (" + officeId + ") не найден!")); + + office.setName(officeDTO.getName()); + office.setDescription(officeDTO.getDescription()); + office.setAddress(officeDTO.getAddress()); + office.setLatitude(officeDTO.getLatitude()); + office.setLongitude(officeDTO.getLongitude()); + + // linkLogo меняется в отдельном запросе + + office.setTelephone(officeDTO.getTelephone()); + office.setEmail(officeDTO.getEmail()); + + return OfficeMapper.convertToDTO(officeRepository.save(office)); + } + + @Override + @LogExample + public void delete(long officeId) { + officeRepository.findById(officeId).orElseThrow(() -> new ResourceNotFoundException("Офис с id (" + officeId + ") не найден!")); + officeRepository.deleteById(officeId); + } + + private static Comparator createComparator(Point2D point) { + return (office0, office1) -> { + Point2D point0 = new Point2D.Double(office0.getLatitude(), office0.getLongitude()); + Point2D point1 = new Point2D.Double(office1.getLatitude(), office1.getLongitude()); + + return Double.compare(point0.distanceSq(point), point1.distanceSq(point)); + }; + } +} diff --git a/src/main/java/com/example/nto/service/impl/TerminalServiceImpl.java b/src/main/java/com/example/nto/service/impl/TerminalServiceImpl.java new file mode 100644 index 0000000..8bb7731 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/TerminalServiceImpl.java @@ -0,0 +1,79 @@ +package com.example.nto.service.impl; + +import com.example.nto.aspect.annotation.LogExample; +import com.example.nto.domain.entity.Office; +import com.example.nto.domain.entity.Terminal; +import com.example.nto.domain.exception.ResourceNotFoundException; +import com.example.nto.dto.entity.TerminalDTO; +import com.example.nto.dto.mappers.TerminalMapper; +import com.example.nto.repository.OfficeRepository; +import com.example.nto.repository.TerminalRepository; +import com.example.nto.service.TerminalService; +import com.example.nto.utils.Utils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class TerminalServiceImpl implements TerminalService { + private final TerminalRepository terminalRepository; + private final OfficeRepository officeRepository; + + @Override + @LogExample + public List getAllTerminal() { + return terminalRepository.findAll().stream().map(TerminalMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public TerminalDTO getById(long terminalId) { + return terminalRepository.findById(terminalId).map(TerminalMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Терминал с id (" + terminalId + ") не найден!")); + } + + @Override + @LogExample + public TerminalDTO create(TerminalDTO terminalDTO) { + Office office = officeRepository.findByName(terminalDTO.getOfficeName()) + .orElseThrow(() -> new ResourceNotFoundException("Офис с названием (" + terminalDTO.getOfficeName() + ") не найден!")); + + Terminal terminal = new Terminal(); + terminal.setName(terminalDTO.getName()); + terminal.setOffice(office); + + return TerminalMapper.convertToDTO(terminalRepository.save(terminal)); + } + + @Override + @LogExample + public TerminalDTO update(long terminalId, TerminalDTO terminalDTO) { + Terminal terminal = terminalRepository.findById(terminalId) + .orElseThrow(() -> new ResourceNotFoundException("Терминал с id (" + terminalId + ") не найден!")); + Office office = officeRepository.findByName(terminalDTO.getOfficeName()) + .orElseThrow(() -> new ResourceNotFoundException("Офис с названием (" + terminalDTO.getOfficeName() + ") не найден!")); + + terminal.setName(terminalDTO.getName()); + terminal.setCode(Utils.generateUniqueName()); + terminal.setOffice(office); + + return TerminalMapper.convertToDTO(terminalRepository.save(terminal)); + } + + @Override + @LogExample + public void delete(long terminalId) { + terminalRepository.findById(terminalId).orElseThrow(() -> new ResourceNotFoundException("Терминал с id (" + terminalId + ") не найден!")); + terminalRepository.deleteById(terminalId); + } + + @Override + @LogExample + public TerminalDTO checkCode(String code) { + return terminalRepository.findByCode(code).map(TerminalMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Терминал с кодом (" + code + ") не найден!")); + } +} diff --git a/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java b/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java index cf8cdb3..511a8d9 100644 --- a/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java @@ -1,14 +1,24 @@ package com.example.nto.service.impl; +import com.example.nto.domain.entity.Employee; +import com.example.nto.repository.EmployeeRepository; +import lombok.AllArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import java.util.Optional; + @Service +@AllArgsConstructor public class UserDetailsServiceImpl implements UserDetailsService { + private final EmployeeRepository employeeRepository; + @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - return null; + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + Optional employee = employeeRepository.findByEmail(email); + if (employee.isEmpty()) throw new UsernameNotFoundException("Employee not found!"); + return employee.get(); } } diff --git a/src/main/java/com/example/nto/service/impl/VisitServiceImpl.java b/src/main/java/com/example/nto/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..0c462f2 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/VisitServiceImpl.java @@ -0,0 +1,125 @@ +package com.example.nto.service.impl; + +import com.example.nto.aspect.annotation.LogExample; +import com.example.nto.domain.entity.Employee; +import com.example.nto.domain.entity.Passage; +import com.example.nto.domain.entity.Terminal; +import com.example.nto.domain.entity.Visit; +import com.example.nto.domain.exception.ResourceNotFoundException; +import com.example.nto.dto.entity.VisitDTO; +import com.example.nto.dto.mappers.VisitMapper; +import com.example.nto.repository.EmployeeRepository; +import com.example.nto.repository.PassageRepository; +import com.example.nto.repository.TerminalRepository; +import com.example.nto.repository.VisitRepository; +import com.example.nto.service.VisitService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class VisitServiceImpl implements VisitService { + private final EmployeeRepository employeeRepository; + private final VisitRepository visitRepository; + private final TerminalRepository terminalRepository; + private final PassageRepository passageRepository; + + @Override + @LogExample + public List getAll() { + return visitRepository.findAll().stream().map(VisitMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public List getAllVisitByEmployee(long employeeId) { + return visitRepository.findAll().stream() + .filter(visit -> checkEmployeeVisit(visit, employeeId)) + .map(VisitMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public List getAllVisitByPeriod(LocalDateTime start, LocalDateTime stop) { + // todo: Доделать если останется время + return List.of(); + } + + @Override + @LogExample + public List getAllFinished(boolean isFinished) { + return visitRepository.findAll().stream() + .filter(visit -> checkFinishVisit(visit, isFinished)) + .map(VisitMapper::convertToDTO).collect(Collectors.toList()); + } + + @Override + @LogExample + public VisitDTO getById(long visitId) { + return visitRepository.findById(visitId).map(VisitMapper::convertToDTO) + .orElseThrow(() -> new ResourceNotFoundException("Посещение с id (" + visitId + ") не найден!")); + } + + @Override + @LogExample + public void delete(long visitId) { + visitRepository.findById(visitId).orElseThrow(() -> new ResourceNotFoundException("Посещение с id (" + visitId + ") не найден!")); + visitRepository.deleteById(visitId); + } + + @Override + @LogExample + public VisitDTO open(long employeeId, long startTerminalId, String passageName) { + Employee employee = employeeRepository.findById(employeeId) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + Terminal terminal = terminalRepository.findById(startTerminalId) + .orElseThrow(() -> new ResourceNotFoundException("Терминал с id (" + startTerminalId + ") не найден!")); + Passage passage = passageRepository.findByPassageName(passageName) + .orElseThrow(() -> new ResourceNotFoundException("Тип входа с названием (" + passageName + ") не найден!")); + + Visit visit = new Visit(); + + visit.setEmployee(employee); + visit.setStartVisit(LocalDateTime.now()); + visit.setFinished(false); + visit.setStartTerminal(terminal); + visit.setPassage(passage); + + return VisitMapper.convertToDTO(visitRepository.save(visit)); + } + + @Override + @LogExample + public void exit(long employeeId, long endTerminalId) { + Employee employee = employeeRepository.findById(employeeId) + .orElseThrow(() -> new ResourceNotFoundException("Работник с id (" + employeeId + ") не найден!")); + Terminal terminal = terminalRepository.findById(endTerminalId) + .orElseThrow(() -> new ResourceNotFoundException("Терминал с id (" + endTerminalId + ") не найден!")); + Visit activeVisit = getActiveVisit(employee); + + activeVisit.setStartVisit(LocalDateTime.now()); + activeVisit.setFinished(true); + activeVisit.setEndTerminal(terminal); + + visitRepository.save(activeVisit); + } + + private static boolean checkEmployeeVisit(Visit visit, long employeeId) { + return visit.getEmployee().getId() == employeeId; + } + + private static boolean checkFinishVisit(Visit visit, boolean isFinished) { + return visit.isFinished() == isFinished; + } + + private static Visit getActiveVisit(Employee employee) { + List visits = employee.getVisits().stream().filter(Visit::isFinished).collect(Collectors.toList()); + + if (visits.size() == 1) return visits.get(0); + else throw new IllegalStateException("Пользователь не может находится в суперпозиции"); + } +}