commit
9c5bf336ec
@ -1,5 +1,10 @@
|
||||
# НТО 2024. II отборочный этап. Командные задания — серверная часть
|
||||
|
||||
## Схема базы данных
|
||||
https://www.drawdb.app/editor?shareId=92ab675631181485a028270c35276710
|
||||
[Архитектура базы данных](static/bd.png)
|
||||
|
||||
|
||||
## 📖 Предыстория
|
||||
|
||||
В компании S контроль доступа в офис осуществляется с помощью СКУД (системы контроля управления доступом). На данный момент у каждого сотрудника компании есть карта-пропуск с NFC меткой. А у каждой входной двери есть считыватель с обеих сторон. При поднесении карты к считывателю, дверь открывается, а информация о времени входа или выхода сотрудника фиксируется в базе данных.
|
122
src/main/java/com/example/nto/domain/entity/Employee.java
Normal file
122
src/main/java/com/example/nto/domain/entity/Employee.java
Normal file
@ -0,0 +1,122 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "employees")
|
||||
public class Employee implements UserDetails {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "name")
|
||||
@NotBlank(message = "Имя пользователя не может быть пустым!")
|
||||
@Size(max = 100, message = "Максимальная длина имени 100 символов!")
|
||||
private String name;
|
||||
|
||||
@Column(name = "surname")
|
||||
@NotBlank(message = "Фамилия пользователя не может быть пустой!")
|
||||
@Size(max = 100, message = "Максимальная длина фамилии 100 символов!")
|
||||
private String surname;
|
||||
|
||||
@Column(name = "patronymic")
|
||||
@Size(max = 100, message = "Максимальная длина отчества 100 символов!")
|
||||
private String patronymic;
|
||||
|
||||
@Column(name = "about_me")
|
||||
@Size(max = 300, message = "Максимальная длина поля 'О себе' 300 символов!")
|
||||
private String aboutMe;
|
||||
|
||||
@Column(name = "telephone", unique = true)
|
||||
@NotBlank(message = "Телефон не может быть пустым!")
|
||||
@Size(max = 20, message = "Максимальная длина телефонного номера 20 символов!")
|
||||
private String telephone;
|
||||
|
||||
@Column(name = "email", unique = true)
|
||||
@NotBlank(message = "Email не может быть пустым!")
|
||||
@Size(max = 255, message = "Максимальная длина email 255 символов")
|
||||
@Email(message = "Email адрес должен быть в формате user@example.com!")
|
||||
private String email;
|
||||
|
||||
@Column(name = "password")
|
||||
@NotBlank(message = "Пароль не может быть пустым!")
|
||||
@Size(max = 300, message = "Максимальная длина пароля 300 символов!")
|
||||
private String password;
|
||||
|
||||
// @ManyToOne(fetch = FetchType.EAGER)
|
||||
// @JoinColumn(name = "office_id", referencedColumnName = "id", nullable = false)
|
||||
// private Office office;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "pos_id", referencedColumnName = "id", nullable = false)
|
||||
private Position position;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "role_id", referencedColumnName = "id", nullable = false)
|
||||
private Role role;
|
||||
|
||||
@Column(name = "profile_image_url", nullable = false)
|
||||
@Size(max = 300, message = "Максимальная длина адреса изображения 300 символов!")
|
||||
private String profileImageUrl;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", columnDefinition = "TIMESTAMP", nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
// @OneToMany(mappedBy = "employee")
|
||||
// private List<Visit> visits = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return List.of(this.role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
68
src/main/java/com/example/nto/domain/entity/Office.java
Normal file
68
src/main/java/com/example/nto/domain/entity/Office.java
Normal file
@ -0,0 +1,68 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "offices")
|
||||
public class Office {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "name", unique = true)
|
||||
@NotBlank(message = "Название не может быть пустым!")
|
||||
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
@NotBlank(message = "Описание не может быть пустым!")
|
||||
@Size(max = 300, message = "Максимальная длина описания 300 символов!")
|
||||
private String description;
|
||||
|
||||
@Column(name = "address")
|
||||
@NotBlank(message = "Адрес не может быть пустым!")
|
||||
@Size(max = 200, message = "Максимальный размер адреса 200 символов!")
|
||||
private String address;
|
||||
|
||||
@Column(name = "latitude")
|
||||
@NotNull(message = "Широта не может быть пустой!")
|
||||
private Double latitude;
|
||||
|
||||
@Column(name = "longitude")
|
||||
@NotNull(message = "Долгота не может быть пустой!")
|
||||
private Double longitude;
|
||||
|
||||
@Column(name = "logo_image_url")
|
||||
@NotBlank(message = "Путь к логотипу не может быть пустой!")
|
||||
@Size(max = 200, message = "Максимальный размер пути к логотипу 200 символов!")
|
||||
private String linkLogo;
|
||||
|
||||
@Column(name = "telephone")
|
||||
@Size(max = 20, message = "Максимальная длина телефонного номера 20 символов!")
|
||||
private String telephone;
|
||||
|
||||
@Column(name = "email")
|
||||
@Size(max = 255, message = "Максимальная длина email 255 символов")
|
||||
@Email(message = "Email адрес должен быть в формате user@example.com!")
|
||||
private String email;
|
||||
|
||||
@OneToMany(mappedBy = "office")
|
||||
private List<Employee> employeeList;
|
||||
|
||||
@OneToMany(mappedBy = "office")
|
||||
private List<Terminal> terminals;
|
||||
}
|
31
src/main/java/com/example/nto/domain/entity/Position.java
Normal file
31
src/main/java/com/example/nto/domain/entity/Position.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "positions")
|
||||
public class Position {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "name", unique = true)
|
||||
@NotBlank(message = "Название не может быть пустым!")
|
||||
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "position")
|
||||
private List<Employee> employees;
|
||||
}
|
37
src/main/java/com/example/nto/domain/entity/Role.java
Normal file
37
src/main/java/com/example/nto/domain/entity/Role.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "roles")
|
||||
public class Role implements GrantedAuthority {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
@Column(name = "role_name", unique = true)
|
||||
@NotBlank(message = "Название роли не может быть пустой!")
|
||||
@Size(max = 100, message = "Максимальная длина роли 100 символов!")
|
||||
private String roleName;
|
||||
|
||||
@OneToMany(mappedBy = "role")
|
||||
private List<Employee> employees;
|
||||
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return this.roleName;
|
||||
}
|
||||
}
|
48
src/main/java/com/example/nto/domain/entity/Terminal.java
Normal file
48
src/main/java/com/example/nto/domain/entity/Terminal.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.UuidGenerator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "terminals")
|
||||
public class Terminal {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "name")
|
||||
@NotBlank(message = "Название не может быть пустым!")
|
||||
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
||||
private String name;
|
||||
|
||||
// Мне нужна была рандомная генерация кода для терминала, так что я мог сделать кривую реализацию через самописную функцию,
|
||||
// но боялся, что она будет генерировать не уникальные значения. (я очень смутно представляю, как эта штука работает)
|
||||
// Код взят отсюда: https://stackoverflow.com/questions/76723290/using-the-new-type-for-uuidgenerator-instead-of-strategy
|
||||
@UuidGenerator
|
||||
@NotBlank(message = "Код не может быть пустым!")
|
||||
@Column(name = "code", nullable = false, unique = true)
|
||||
private String code;
|
||||
|
||||
// todo: Протестировать нужен ли тут каскад тип
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
@OneToMany(mappedBy = "startTerminal")
|
||||
private List<Visit> startVisits;
|
||||
|
||||
@OneToMany(mappedBy = "endTerminal")
|
||||
private List<Visit> endVisits;
|
||||
}
|
43
src/main/java/com/example/nto/domain/entity/Visit.java
Normal file
43
src/main/java/com/example/nto/domain/entity/Visit.java
Normal file
@ -0,0 +1,43 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "visits")
|
||||
public class Visit {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "employee_id", referencedColumnName = "id", nullable = false)
|
||||
private Employee employee;
|
||||
|
||||
@Column(name = "start_visit", columnDefinition = "TIMESTAMP", nullable = false)
|
||||
private LocalDateTime startVisit;
|
||||
|
||||
@Column(name = "end_visit", columnDefinition = "TIMESTAMP")
|
||||
private LocalDateTime endVisit;
|
||||
|
||||
@Column(name = "is_finished", nullable = false)
|
||||
private boolean isFinished = false;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "start_terminal_id", referencedColumnName = "code", nullable = false)
|
||||
private Terminal startTerminal;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "end_terminal_id", referencedColumnName = "code")
|
||||
private Terminal endTerminal;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.example.nto.exception;
|
||||
package com.example.nto.domain.exception;
|
||||
|
||||
public class CodeNotFoundException extends RuntimeException {
|
||||
// Выдаётся, когда код не найден. Нужна, чтобы возвращать клиенту код 401.
|
@ -1,4 +1,4 @@
|
||||
package com.example.nto.exception;
|
||||
package com.example.nto.domain.exception;
|
||||
|
||||
public class EmployeeNotFoundException extends RuntimeException {
|
||||
// Выдаётся, когда работник не найден. Нужна, чтобы возвращать клиенту код 401.
|
@ -1,4 +1,4 @@
|
||||
package com.example.nto.exception;
|
||||
package com.example.nto.domain.exception;
|
||||
|
||||
public class SomethingWentWrongException extends RuntimeException {
|
||||
// Выдаётся, при непредвиденной ошибке. Нужна, чтобы возвращать клиенту код 400.
|
@ -1,8 +1,8 @@
|
||||
package com.example.nto.exception.advice;
|
||||
package com.example.nto.domain.exception.advice;
|
||||
|
||||
import com.example.nto.exception.CodeNotFoundException;
|
||||
import com.example.nto.exception.EmployeeNotFoundException;
|
||||
import com.example.nto.exception.SomethingWentWrongException;
|
||||
import com.example.nto.domain.exception.CodeNotFoundException;
|
||||
import com.example.nto.domain.exception.EmployeeNotFoundException;
|
||||
import com.example.nto.domain.exception.SomethingWentWrongException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
14
src/main/java/com/example/nto/dto/entity/OfficeDTO.java
Normal file
14
src/main/java/com/example/nto/dto/entity/OfficeDTO.java
Normal file
@ -0,0 +1,14 @@
|
||||
package com.example.nto.dto.entity;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OfficeDTO {
|
||||
}
|
22
src/main/java/com/example/nto/dto/entity/PositionDTO.java
Normal file
22
src/main/java/com/example/nto/dto/entity/PositionDTO.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.example.nto.dto.entity;
|
||||
|
||||
|
||||
import com.example.nto.dto.entity.employee.EmployeeItemDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PositionDTO {
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
// Список всех сотрудников с этой должностью.
|
||||
private List<EmployeeItemDTO> employeeItemDTOList;
|
||||
}
|
23
src/main/java/com/example/nto/dto/entity/TerminalDTO.java
Normal file
23
src/main/java/com/example/nto/dto/entity/TerminalDTO.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.example.nto.dto.entity;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TerminalDTO {
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
// ОЧЕНЬ ВАЖНО!!! При создании терминала code не нужен, но отправлять его нужно.
|
||||
// При создании пиши вместо code, что хочешь он будет просто игнорироваться.
|
||||
// Мне просто очень лень делать отдельный TerminalCreateDTO ради одного поля.
|
||||
|
||||
private String code;
|
||||
private String officeName;
|
||||
}
|
27
src/main/java/com/example/nto/dto/entity/VisitDTO.java
Normal file
27
src/main/java/com/example/nto/dto/entity/VisitDTO.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.example.nto.dto.entity;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VisitDTO {
|
||||
private long id;
|
||||
|
||||
// Возвращается время начала и конца посещения в формате LocalDateTime.toString(),
|
||||
// превратить обратно можно с помощью LocalDateTime.parse().
|
||||
private String startVisit;
|
||||
private String endVisit;
|
||||
|
||||
private boolean isFinished;
|
||||
|
||||
// Возвращается длительность посещения в формате LocalDateTime.toString(),
|
||||
// превратить обратно можно с помощью LocalDateTime.parse().
|
||||
private String durationVisit;
|
||||
private String officeName;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.example.nto.dto.entity.employee;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EmployeeCreateDTO {
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.example.nto.dto.entity.employee;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EmployeeDTO {
|
||||
private long id;
|
||||
private String name;
|
||||
private String surname;
|
||||
private String patronymic;
|
||||
private String telephone;
|
||||
private String email;
|
||||
|
||||
private long officeId;
|
||||
private String officeName;
|
||||
private String officeImageUrl;
|
||||
|
||||
private String position; // Название должности
|
||||
private String role; // строка либо ROLE_USER, либо ROLE_ADMIN
|
||||
|
||||
private String profileImageUrl;
|
||||
|
||||
// Текущее состояние входа: false - visit (посещение) ещё не началось, true - visit идёт
|
||||
private boolean visitStatus;
|
||||
|
||||
// Если visitStatus true, то возвращает дату и время начала посещения в формате LocalDateTime.toString(),
|
||||
// превратить обратно можно с помощью LocalDateTime.parse().
|
||||
// Если visitStatus false, то возвращает null.
|
||||
private String startVisitDateTime;
|
||||
private List<Long> visitsIdLast30Days; // Список Id посещений за последние 30 дней.
|
||||
|
||||
// Возвращает количество отработанных часов за последний месяц.
|
||||
private long totalTimeVisitsLast30Days;
|
||||
|
||||
// (Возможно это стоит убрать) Название офиса, в котором сейчас находится работник.
|
||||
// Если visitStatus false, возвращает null.
|
||||
private String currentOfficeName;
|
||||
|
||||
// Возвращает время регистрации в формате LocalDateTime.toString(),
|
||||
// превратить обратно можно с помощью LocalDateTime.parse().
|
||||
private String createAt;
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.example.nto.dto.entity.employee;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EmployeeItemDTO {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers;
|
||||
|
||||
public class OfficeMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers;
|
||||
|
||||
public class PositionMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers;
|
||||
|
||||
public class TerminalMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers;
|
||||
|
||||
public class VisitMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers.employee;
|
||||
|
||||
public class EmployeeCreateMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers.employee;
|
||||
|
||||
public class EmployeeItemMapper {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.nto.dto.mappers.employee;
|
||||
|
||||
public class EmployeeMapper {
|
||||
}
|
5
src/main/java/com/example/nto/utils/DataFormatType.java
Normal file
5
src/main/java/com/example/nto/utils/DataFormatType.java
Normal file
@ -0,0 +1,5 @@
|
||||
package com.example.nto.utils;
|
||||
|
||||
public enum DataFormatType {
|
||||
DATE_TIME, DATE, TIME
|
||||
}
|
59
src/main/java/com/example/nto/utils/Utils.java
Normal file
59
src/main/java/com/example/nto/utils/Utils.java
Normal file
@ -0,0 +1,59 @@
|
||||
package com.example.nto.utils;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@UtilityClass
|
||||
public class Utils {
|
||||
private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
|
||||
public static String profileFileName(long userId) {
|
||||
return "profile--" + userId;
|
||||
}
|
||||
|
||||
public static String generateUniqueName() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public static String nowTime(DataFormatType type) {
|
||||
switch (type) {
|
||||
case DATE_TIME: return LocalDateTime.now().format(DATE_TIME_FORMAT);
|
||||
case DATE: return LocalDateTime.now().format(DATE_FORMAT);
|
||||
case TIME: return LocalDateTime.now().format(TIME_FORMAT);
|
||||
default: return "Произошла ошибка при форматировании даты или времени.";
|
||||
}
|
||||
}
|
||||
public static LocalDateTime period(LocalDateTime dtStart, LocalDateTime dtEnd) {
|
||||
// Возвращает разницу между двумя LocalDateTime
|
||||
Period period = Period.between(dtStart.toLocalDate(), dtEnd.toLocalDate());
|
||||
Duration duration = Duration.between(dtStart.toLocalTime(), dtEnd.toLocalTime());
|
||||
|
||||
LocalDate localDate = LocalDate.of(period.getYears(), period.getMonths(), period.getDays());
|
||||
LocalTime localTime = LocalTime.of(duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart());
|
||||
|
||||
return LocalDateTime.of(localDate, localTime);
|
||||
}
|
||||
|
||||
public static long periods(List<List<LocalDateTime>> periods) {
|
||||
// Количество часов за определенные периоды.
|
||||
long hours = 0;
|
||||
for (List<LocalDateTime> period : periods) {
|
||||
if (period.size() != 2) throw new IllegalStateException("Список с периодом должен содержать 2 элемента!");
|
||||
hours += Duration.between(period.get(0), period.get(1)).toHours();
|
||||
}
|
||||
return hours;
|
||||
}
|
||||
|
||||
public static String convertDistance(float distance) {
|
||||
if (distance > 1000) return String.format("%.1f", distance / 1000) + " км";
|
||||
else return String.format("%.1f", distance) + " м";
|
||||
}
|
||||
}
|
BIN
static/bd.png
Normal file
BIN
static/bd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 KiB |
Loading…
x
Reference in New Issue
Block a user