Merge pull request 'develop' (#3) from develop into master
Reviewed-on: #3
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.8 KiB |
@ -25,7 +25,7 @@ public class Passage {
|
|||||||
@Column(name = "passage", unique = true)
|
@Column(name = "passage", unique = true)
|
||||||
@NotBlank(message = "Название не может быть пустым!")
|
@NotBlank(message = "Название не может быть пустым!")
|
||||||
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
||||||
private String passage;
|
private String passageName;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "passage")
|
@OneToMany(mappedBy = "passage")
|
||||||
private List<Visit> visits;
|
private List<Visit> visits;
|
||||||
|
@ -31,6 +31,7 @@ public class Terminal {
|
|||||||
// Мне нужна была рандомная генерация кода для терминала, так что я мог сделать кривую реализацию через самописную функцию,
|
// Мне нужна была рандомная генерация кода для терминала, так что я мог сделать кривую реализацию через самописную функцию,
|
||||||
// но боялся, что она будет генерировать не уникальные значения. (я очень смутно представляю, как эта штука работает)
|
// но боялся, что она будет генерировать не уникальные значения. (я очень смутно представляю, как эта штука работает)
|
||||||
// Код взят отсюда: https://stackoverflow.com/questions/25082244/auto-generate-unique-random-string-in-spring-mvc-hibernate
|
// Код взят отсюда: https://stackoverflow.com/questions/25082244/auto-generate-unique-random-string-in-spring-mvc-hibernate
|
||||||
|
// todo: Понять что это такое.......................................................................................
|
||||||
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
|
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
|
||||||
@GeneratedValue(generator = "uuid-gen")
|
@GeneratedValue(generator = "uuid-gen")
|
||||||
@NotBlank(message = "Код не может быть пустым!")
|
@NotBlank(message = "Код не может быть пустым!")
|
||||||
|
@ -30,7 +30,7 @@ public class Visit {
|
|||||||
private LocalDateTime endVisit;
|
private LocalDateTime endVisit;
|
||||||
|
|
||||||
@Column(name = "is_finished", nullable = false)
|
@Column(name = "is_finished", nullable = false)
|
||||||
private final boolean isFinished = false;
|
private boolean isFinished = false;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER)
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
@JoinColumn(name = "start_terminal_id", referencedColumnName = "code", nullable = false)
|
@JoinColumn(name = "start_terminal_id", referencedColumnName = "code", nullable = false)
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.nto.domain.exception;
|
||||||
|
|
||||||
|
public class AccessDeniedException extends RuntimeException {
|
||||||
|
public AccessDeniedException(String message) {
|
||||||
|
// Доступ запрещен.
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.nto.domain.exception;
|
||||||
|
|
||||||
|
public class ConflictResourceException extends RuntimeException {
|
||||||
|
public ConflictResourceException(String message) {
|
||||||
|
// Вызывается, когда данные в таблицах конфликтуют.
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.nto.domain.exception;
|
||||||
|
|
||||||
|
public class ImageSendException extends RuntimeException {
|
||||||
|
public ImageSendException(String message) {
|
||||||
|
// Вызывается при ошибке во время отправки изображения.
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.example.nto.domain.exception;
|
||||||
|
|
||||||
|
public class ImageUploadException extends RuntimeException {
|
||||||
|
public ImageUploadException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.nto.domain.exception;
|
||||||
|
|
||||||
|
public class ResourceNotFoundException extends RuntimeException {
|
||||||
|
public ResourceNotFoundException(String message) {
|
||||||
|
// Вызывается, когда что-то не найдено в бд.
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -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<ApiError> 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<ApiError> runtimeException(RuntimeException e) {
|
||||||
|
return new ResponseEntity<>(
|
||||||
|
new ApiError("500", "Один из потоков завершился исключением.", e.getMessage(), Utils.nowTime(DATE_TIME)),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package com.example.nto.domain.exception.advice;
|
package com.example.nto.domain.exception.advice;
|
||||||
|
|
||||||
import com.example.nto.domain.exception.CodeNotFoundException;
|
import com.amazonaws.services.organizations.model.ConstraintViolationException;
|
||||||
import com.example.nto.domain.exception.EmployeeNotFoundException;
|
import com.example.nto.domain.exception.*;
|
||||||
import com.example.nto.domain.exception.SomethingWentWrongException;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
@ -27,4 +26,36 @@ public class GlobalExceptionalHandler {
|
|||||||
public ResponseEntity<HttpStatus> handlerSomethingWentWrongException(SomethingWentWrongException e) {
|
public ResponseEntity<HttpStatus> handlerSomethingWentWrongException(SomethingWentWrongException e) {
|
||||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(AccessDeniedException.class)
|
||||||
|
public ResponseEntity<String> handlerAccessDeniedException(AccessDeniedException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ResourceNotFoundException.class)
|
||||||
|
public ResponseEntity<String> handlerAccessDeniedException(ResourceNotFoundException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConflictResourceException.class)
|
||||||
|
public ResponseEntity<String> handlerConflictResourceException(ConflictResourceException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ImageUploadException.class)
|
||||||
|
public ResponseEntity<String> handlerImageUploadException(ImageUploadException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ImageSendException.class)
|
||||||
|
public ResponseEntity<String> handlerImageSendException(ImageSendException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConstraintViolationException.class)
|
||||||
|
public ResponseEntity<String> handlerConstraintViolationException(ConstraintViolationException e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
}
|
@ -24,4 +24,6 @@ public class VisitDTO {
|
|||||||
// превратить обратно можно с помощью LocalDateTime.parse().
|
// превратить обратно можно с помощью LocalDateTime.parse().
|
||||||
private String durationVisit;
|
private String durationVisit;
|
||||||
private String officeName;
|
private String officeName;
|
||||||
|
|
||||||
|
private String typePassage; // Строка либо PASSAGE_CARD, либо PASSAGE_TELEPHONE
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ public class EmployeeDTO {
|
|||||||
private String name;
|
private String name;
|
||||||
private String surname;
|
private String surname;
|
||||||
private String patronymic;
|
private String patronymic;
|
||||||
|
private String aboutMe;
|
||||||
private String telephone;
|
private String telephone;
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ public class EmployeeDTO {
|
|||||||
private String officeName;
|
private String officeName;
|
||||||
private String officeImageUrl;
|
private String officeImageUrl;
|
||||||
|
|
||||||
private String position; // Название должности
|
private String positionName; // Название должности
|
||||||
private String role; // строка либо ROLE_USER, либо ROLE_ADMIN
|
private String role; // строка либо ROLE_USER, либо ROLE_ADMIN
|
||||||
|
|
||||||
private String profileImageUrl;
|
private String profileImageUrl;
|
||||||
|
@ -1,4 +1,48 @@
|
|||||||
package com.example.nto.dto.mappers;
|
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 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
package com.example.nto.dto.mappers;
|
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 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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,29 @@
|
|||||||
package com.example.nto.dto.mappers;
|
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 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,42 @@
|
|||||||
package com.example.nto.dto.mappers;
|
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 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ public class EmployeeCreateMapper {
|
|||||||
employee.setPosition(position);
|
employee.setPosition(position);
|
||||||
employee.setRole(role);
|
employee.setRole(role);
|
||||||
employee.setProfileImageUrl(Utils.getRandomUrlProfileImage());
|
employee.setProfileImageUrl(Utils.getRandomUrlProfileImage());
|
||||||
|
employee.setBlocked(false);
|
||||||
|
|
||||||
return employee;
|
return employee;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
package com.example.nto.dto.mappers.employee;
|
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 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<Visit> visitsLast30Days = Utils.filterDateLast30Days(employee.getVisits());
|
||||||
|
employeeItemDTO.setVisitStatus(visitsLast30Days.stream().anyMatch(visit -> !visit.isFinished()));
|
||||||
|
|
||||||
|
return employeeItemDTO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,81 @@
|
|||||||
package com.example.nto.dto.mappers.employee;
|
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 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<Visit> visitsLast30Days = Utils.filterDateLast30Days(employee.getVisits());
|
||||||
|
|
||||||
|
boolean visitStatus = false;
|
||||||
|
String startVisitDateTime = null;
|
||||||
|
String currentOfficeName = null;
|
||||||
|
List<Long> visitsIdLast30Days = new ArrayList<>(visitsLast30Days.size());
|
||||||
|
List<List<LocalDateTime>> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<Employee, Long> {
|
||||||
|
Optional<Employee> findByEmail(String email);
|
||||||
|
Optional<Employee> findByTelephone(String telephone);
|
||||||
|
}
|
@ -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<Office, Long> {
|
||||||
|
Optional<Office> findByName(String name);
|
||||||
|
}
|
@ -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<Passage, Long> {
|
||||||
|
Optional<Passage> findByPassageName(String passageName);
|
||||||
|
}
|
@ -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<Position, Long> {
|
||||||
|
Optional<Position> findByName(String name);
|
||||||
|
}
|
10
src/main/java/com/example/nto/repository/RoleRepository.java
Normal file
@ -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<Role, Long> {
|
||||||
|
Optional<Role> findByRoleName(String roleName);
|
||||||
|
}
|
@ -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<Terminal, Long> {
|
||||||
|
Optional<Terminal> findByCode(String code);
|
||||||
|
}
|
@ -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<Visit, Long> {
|
||||||
|
}
|
23
src/main/java/com/example/nto/service/EmployeeService.java
Normal file
@ -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<EmployeeItemDTO> getAll();
|
||||||
|
List<EmployeeItemDTO> 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);
|
||||||
|
}
|
15
src/main/java/com/example/nto/service/OfficeService.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.example.nto.service;
|
||||||
|
|
||||||
|
import com.example.nto.dto.entity.OfficeDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface OfficeService {
|
||||||
|
List<OfficeDTO> getAllOffice();
|
||||||
|
List<OfficeDTO> getAllSortedDistance(double userLatitude, double userLongitude);
|
||||||
|
OfficeDTO getById(long officeId);
|
||||||
|
|
||||||
|
OfficeDTO create(OfficeDTO officeDTO);
|
||||||
|
OfficeDTO update(long officeId, OfficeDTO officeDTO);
|
||||||
|
void delete(long officeId);
|
||||||
|
}
|
16
src/main/java/com/example/nto/service/TerminalService.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.example.nto.service;
|
||||||
|
|
||||||
|
import com.example.nto.dto.entity.TerminalDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface TerminalService {
|
||||||
|
List<TerminalDTO> getAllTerminal();
|
||||||
|
TerminalDTO getById(long terminalId);
|
||||||
|
|
||||||
|
TerminalDTO create(TerminalDTO terminalDTO);
|
||||||
|
TerminalDTO update(long terminalId, TerminalDTO terminalDTO);
|
||||||
|
void delete(long terminalId);
|
||||||
|
|
||||||
|
TerminalDTO checkCode(String code);
|
||||||
|
}
|
21
src/main/java/com/example/nto/service/VisitService.java
Normal file
@ -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<VisitDTO> getAll();
|
||||||
|
List<VisitDTO> getAllVisitByEmployee(long employeeId);
|
||||||
|
List<VisitDTO> getAllVisitByPeriod(LocalDateTime start, LocalDateTime stop);
|
||||||
|
List<VisitDTO> 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);
|
||||||
|
}
|
@ -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<EmployeeItemDTO> getAll() {
|
||||||
|
return employeeRepository.findAll().stream().map(EmployeeItemMapper::convertToDTO).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@LogExample
|
||||||
|
public List<EmployeeItemDTO> 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<Employee> employeeEmail = employeeRepository.findByEmail(employeeCreateDTO.getEmail());
|
||||||
|
Optional<Employee> 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<Employee> employeeEmail = employeeRepository.findByEmail(employeeDTO.getEmail());
|
||||||
|
Optional<Employee> 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<Visit> 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("Пользователь не может находится в суперпозиции");
|
||||||
|
}
|
||||||
|
}
|
@ -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<OfficeDTO> getAllOffice() {
|
||||||
|
return officeRepository.findAll().stream().map(OfficeMapper::convertToDTO).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@LogExample
|
||||||
|
public List<OfficeDTO> 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<OfficeDTO> 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));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -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<TerminalDTO> 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 + ") не найден!"));
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,24 @@
|
|||||||
package com.example.nto.service.impl;
|
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.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
|
private final EmployeeRepository employeeRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
|
||||||
return null;
|
Optional<Employee> employee = employeeRepository.findByEmail(email);
|
||||||
|
if (employee.isEmpty()) throw new UsernameNotFoundException("Employee not found!");
|
||||||
|
return employee.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
125
src/main/java/com/example/nto/service/impl/VisitServiceImpl.java
Normal file
@ -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<VisitDTO> getAll() {
|
||||||
|
return visitRepository.findAll().stream().map(VisitMapper::convertToDTO).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@LogExample
|
||||||
|
public List<VisitDTO> getAllVisitByEmployee(long employeeId) {
|
||||||
|
return visitRepository.findAll().stream()
|
||||||
|
.filter(visit -> checkEmployeeVisit(visit, employeeId))
|
||||||
|
.map(VisitMapper::convertToDTO).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@LogExample
|
||||||
|
public List<VisitDTO> getAllVisitByPeriod(LocalDateTime start, LocalDateTime stop) {
|
||||||
|
// todo: Доделать если останется время
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@LogExample
|
||||||
|
public List<VisitDTO> 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<Visit> visits = employee.getVisits().stream().filter(Visit::isFinished).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (visits.size() == 1) return visits.get(0);
|
||||||
|
else throw new IllegalStateException("Пользователь не может находится в суперпозиции");
|
||||||
|
}
|
||||||
|
}
|