the first working version #2
@ -2,7 +2,7 @@
|
||||
|
||||
## Схема базы данных
|
||||
https://www.drawdb.app/editor?shareId=92ab675631181485a028270c35276710
|
||||
[Архитектура базы данных](static/bd.png)
|
||||
[Архитектура базы данных](docs/static/bd.png)
|
||||
|
||||
|
||||
## 📖 Предыстория
|
||||
|
BIN
docs/static/bd.png
vendored
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
images/profile--1.jpg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
images/profile--10.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/profile--11.jpg
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
images/profile--12.jpg
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
images/profile--13.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/profile--14.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/profile--15.jpg
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
images/profile--16.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/profile--17.jpg
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
images/profile--18.jpg
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
images/profile--19.jpg
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
images/profile--2.jpg
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
images/profile--20.jpg
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
images/profile--21.jpg
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
images/profile--22.jpg
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
images/profile--23.jpg
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
images/profile--24.jpg
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
images/profile--25.jpg
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
images/profile--26.jpg
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
images/profile--3.jpg
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/profile--4.jpg
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
images/profile--5.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
images/profile--6.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/profile--7.jpg
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
images/profile--8.jpg
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
images/profile--9.jpg
Normal file
After Width: | Height: | Size: 8.8 KiB |
2
pom.xml
@ -22,7 +22,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>2.7.10</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.example.nto.config;
|
||||
|
||||
import com.amazonaws.SdkClientException;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Configuration
|
||||
public class ObjectStorageConfig {
|
||||
@Value("${yandex.cloud.region}")
|
||||
private String region;
|
||||
@Value("${yandex.cloud.s3_endpoint}")
|
||||
private String s3Endpoint;
|
||||
|
||||
@Value("${yandex.cloud.bucket}")
|
||||
private String bucketName;
|
||||
@Value("${yandex.cloud.key_id}")
|
||||
private String accessKeyId;
|
||||
@Value("${yandex.cloud.secret_key}")
|
||||
private String secretAccessKey;
|
||||
|
||||
|
||||
public AmazonS3 createAmazonS3() {
|
||||
// Создание клиента AmazonS3 с подключением к Object Storage
|
||||
try {
|
||||
return AmazonS3ClientBuilder.standard()
|
||||
.withEndpointConfiguration(new com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration(s3Endpoint, region))
|
||||
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKeyId, secretAccessKey)))
|
||||
.build();
|
||||
} catch (SdkClientException e) {
|
||||
log.error("Ошибка при создании клиента для хранения объектов с помощью AWS SDK. Причина: {}", e.getMessage());
|
||||
throw new SdkClientException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
20
src/main/java/com/example/nto/config/SwaggerConfig.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.example.nto.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
@Bean
|
||||
public Docket api() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.example.preparation"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
}
|
53
src/main/java/com/example/nto/config/WebSecurityConfig.java
Normal file
@ -0,0 +1,53 @@
|
||||
package com.example.nto.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/h2-console/**").permitAll()
|
||||
.antMatchers("/api/v1/images/**").permitAll()
|
||||
.antMatchers("/api/v1/volunteers/login").permitAll()
|
||||
.antMatchers("/api/v1/volunteers/register").permitAll()
|
||||
|
||||
.antMatchers("/api/v1/**").permitAll()
|
||||
//.antMatchers("/api/v1/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.headers().frameOptions().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web.ignoring().antMatchers("/api/v1/volunteers/images");
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
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;
|
||||
@ -12,8 +9,11 @@ import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@ -62,9 +62,9 @@ public class Employee implements UserDetails {
|
||||
@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 = "office_id", referencedColumnName = "id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "pos_id", referencedColumnName = "id", nullable = false)
|
||||
@ -78,12 +78,15 @@ public class Employee implements UserDetails {
|
||||
@Size(max = 300, message = "Максимальная длина адреса изображения 300 символов!")
|
||||
private String profileImageUrl;
|
||||
|
||||
@Column(name = "is_blocked")
|
||||
private boolean isBlocked;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", columnDefinition = "TIMESTAMP", nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
// @OneToMany(mappedBy = "employee")
|
||||
// private List<Visit> visits = new ArrayList<>();
|
||||
@OneToMany(mappedBy = "employee")
|
||||
private List<Visit> visits;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
@ -92,7 +95,7 @@ public class Employee implements UserDetails {
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "";
|
||||
return this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,15 +1,16 @@
|
||||
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 javax.persistence.*;
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
|
32
src/main/java/com/example/nto/domain/entity/Passage.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "passages")
|
||||
public class Passage {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(name = "passage", unique = true)
|
||||
@NotBlank(message = "Название не может быть пустым!")
|
||||
@Size(max = 100, message = "Максимальная длина названия 100 символов!")
|
||||
private String passage;
|
||||
|
||||
@OneToMany(mappedBy = "passage")
|
||||
private List<Visit> visits;
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
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 javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
|
@ -1,14 +1,15 @@
|
||||
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 javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
|
@ -1,14 +1,15 @@
|
||||
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 org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ -29,8 +30,9 @@ public class Terminal {
|
||||
|
||||
// Мне нужна была рандомная генерация кода для терминала, так что я мог сделать кривую реализацию через самописную функцию,
|
||||
// но боялся, что она будет генерировать не уникальные значения. (я очень смутно представляю, как эта штука работает)
|
||||
// Код взят отсюда: https://stackoverflow.com/questions/76723290/using-the-new-type-for-uuidgenerator-instead-of-strategy
|
||||
@UuidGenerator
|
||||
// Код взят отсюда: https://stackoverflow.com/questions/25082244/auto-generate-unique-random-string-in-spring-mvc-hibernate
|
||||
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
|
||||
@GeneratedValue(generator = "uuid-gen")
|
||||
@NotBlank(message = "Код не может быть пустым!")
|
||||
@Column(name = "code", nullable = false, unique = true)
|
||||
private String code;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.example.nto.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@ -30,7 +30,7 @@ public class Visit {
|
||||
private LocalDateTime endVisit;
|
||||
|
||||
@Column(name = "is_finished", nullable = false)
|
||||
private boolean isFinished = false;
|
||||
private final boolean isFinished = false;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "start_terminal_id", referencedColumnName = "code", nullable = false)
|
||||
@ -39,5 +39,9 @@ public class Visit {
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "end_terminal_id", referencedColumnName = "code")
|
||||
private Terminal endTerminal;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "type_passage", referencedColumnName = "id", nullable = false)
|
||||
private Passage passage;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,29 @@
|
||||
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 OfficeDTO {
|
||||
private long id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String address;
|
||||
private Double latitude;
|
||||
private Double longitude;
|
||||
private String linkLogo;
|
||||
private String telephone;
|
||||
private String email;
|
||||
|
||||
private List<EmployeeItemDTO> employees;
|
||||
private List<TerminalDTO> terminals;
|
||||
}
|
||||
|
@ -10,4 +10,17 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EmployeeCreateDTO {
|
||||
private String name;
|
||||
private String surname;
|
||||
private String patronymic;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private String password;
|
||||
private boolean isBlocked;
|
||||
|
||||
private String officeName; // Имя офиса, к которому присоединится работник.
|
||||
private String positionName; // Должность работника.
|
||||
private String role; // строка либо ROLE_USER, либо ROLE_ADMIN
|
||||
|
||||
// Изображение профиля выберется рандомно из заготовок.
|
||||
}
|
@ -27,6 +27,7 @@ public class EmployeeDTO {
|
||||
private String role; // строка либо ROLE_USER, либо ROLE_ADMIN
|
||||
|
||||
private String profileImageUrl;
|
||||
private boolean isBlocked;
|
||||
|
||||
// Текущее состояние входа: false - visit (посещение) ещё не началось, true - visit идёт
|
||||
private boolean visitStatus;
|
||||
|
@ -11,4 +11,16 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EmployeeItemDTO {
|
||||
private long id;
|
||||
private String name;
|
||||
private String surname;
|
||||
private String patronymic;
|
||||
private String profileImageUrl;
|
||||
private boolean isBlocked;
|
||||
|
||||
private String officeName;
|
||||
private String position; // Название должности
|
||||
|
||||
// Текущее состояние входа: false - visit (посещение) ещё не началось, true - visit идёт
|
||||
private boolean visitStatus;
|
||||
}
|
||||
|
@ -1,4 +1,32 @@
|
||||
package com.example.nto.dto.mappers.employee;
|
||||
|
||||
import com.example.nto.domain.entity.Employee;
|
||||
import com.example.nto.domain.entity.Office;
|
||||
import com.example.nto.domain.entity.Position;
|
||||
import com.example.nto.domain.entity.Role;
|
||||
import com.example.nto.dto.entity.employee.EmployeeCreateDTO;
|
||||
import com.example.nto.utils.Utils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public class EmployeeCreateMapper {
|
||||
public static Employee convertFromDTO(
|
||||
EmployeeCreateDTO employeeDTO, String password, Office office,
|
||||
Position position, Role role
|
||||
) {
|
||||
Employee employee = new Employee();
|
||||
|
||||
employee.setName(employeeDTO.getName());
|
||||
employee.setSurname(employeeDTO.getSurname());
|
||||
employee.setPatronymic(employeeDTO.getPatronymic());
|
||||
employee.setTelephone(employeeDTO.getTelephone());
|
||||
employee.setEmail(employeeDTO.getEmail());
|
||||
employee.setPassword(password);
|
||||
employee.setOffice(office);
|
||||
employee.setPosition(position);
|
||||
employee.setRole(role);
|
||||
employee.setProfileImageUrl(Utils.getRandomUrlProfileImage());
|
||||
|
||||
return employee;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.example.nto.service.impl;
|
||||
|
||||
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;
|
||||
|
||||
@Service
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.example.nto.utils;
|
||||
|
||||
import com.example.nto.config.ObjectStorageConfig;
|
||||
import com.example.nto.domain.entity.Visit;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.time.*;
|
||||
@ -7,6 +9,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
@UtilityClass
|
||||
@ -15,6 +18,8 @@ public class Utils {
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
|
||||
private static final ObjectStorageConfig storageConfig = new ObjectStorageConfig();
|
||||
|
||||
public static String profileFileName(long userId) {
|
||||
return "profile--" + userId;
|
||||
}
|
||||
@ -25,12 +30,17 @@ public class Utils {
|
||||
|
||||
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 "Произошла ошибка при форматировании даты или времени.";
|
||||
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());
|
||||
@ -52,6 +62,23 @@ public class Utils {
|
||||
return hours;
|
||||
}
|
||||
|
||||
public static List<Visit> filterDateLast30Days(List<Visit> visits) {
|
||||
final LocalDateTime referenceDate = LocalDateTime.now();
|
||||
List<Visit> result = new ArrayList<>();
|
||||
|
||||
for (Visit visit : visits) {
|
||||
long daysBetween = ChronoUnit.DAYS.between(visit.getStartVisit(), referenceDate);
|
||||
if (daysBetween >= 0 && daysBetween <= 30) result.add(visit);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getRandomUrlProfileImage() {
|
||||
int max = 26, min = 1;
|
||||
String fileName = profileFileName(new Random().nextInt(max - min + 1) + min) + ".jpg";
|
||||
return storageConfig.getS3Endpoint() + "/" + storageConfig.getBucketName() + "/standard/" + fileName;
|
||||
}
|
||||
|
||||
public static String convertDistance(float distance) {
|
||||
if (distance > 1000) return String.format("%.1f", distance / 1000) + " км";
|
||||
else return String.format("%.1f", distance) + " м";
|
||||
|
7
src/main/resources/application.properties
Normal file
@ -0,0 +1,7 @@
|
||||
spring.servlet.multipart.max-file-size=10MB
|
||||
spring.servlet.multipart.max-request-size=10MB
|
||||
yandex.cloud.region=ru-central1
|
||||
yandex.cloud.s3_endpoint=https://storage.yandexcloud.net
|
||||
yandex.cloud.key_id=YCAJEIOy-pmwxonO9XLqdhAVI
|
||||
yandex.cloud.secret_key=YCNJMJf9VGP9OmFiPs5XbnfKzzarBl1B1ymGz1uu
|
||||
yandex.cloud.bucket=spring-boot-final-nto-bacet
|
@ -1,28 +1,25 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: ${MAX_FILE_SIZE:8MB}
|
||||
max-request-size: ${MAX_REQUEST_SIZE:8MB}
|
||||
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb
|
||||
url: jdbc:h2:mem:database
|
||||
|
||||
h2:
|
||||
console:
|
||||
#enabled: false
|
||||
enabled: true
|
||||
|
||||
liquibase:
|
||||
enabled: true
|
||||
change-log: classpath:db.changelog/db.changelog-master.xml
|
||||
|
||||
jpa:
|
||||
#generate-ddl: false
|
||||
generate-ddl: true
|
||||
|
||||
generate-ddl: false
|
||||
hibernate:
|
||||
#ddl-auto: none
|
||||
ddl-auto: create-drop
|
||||
|
||||
# Показываем запросы
|
||||
ddl-auto: none
|
||||
show-sql: true
|
||||
|
||||
# Своевременный запуск data.sql
|
||||
defer-datasource-initialization: true
|
||||
|
||||
spring-doc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
operationsSorter: method
|
@ -1,14 +0,0 @@
|
||||
INSERT INTO employee (id, login, name, photo, position, last_visit)
|
||||
VALUES
|
||||
(1, 'pivanov', 'Иванов Петр Федорович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-12T08:30'),
|
||||
(2, 'ipetrov', 'Петров Иван Константинович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Аналитик', '2024-02-13T08:35'),
|
||||
(3, 'asemenov', 'Семенов Анатолий Анатольевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-13T08:31'),
|
||||
(4, 'afedorov', 'Федоров Александр Сергеевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Тестировщик', '2024-02-12T08:36');
|
||||
|
||||
INSERT INTO code (value)
|
||||
VALUES
|
||||
(1234567890123456789),
|
||||
(9223372036854775807),
|
||||
(1122334455667788990),
|
||||
(998877665544332211),
|
||||
(5566778899001122334);
|
4
src/main/resources/db.changelog/db.changelog-master.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
|
||||
</databaseChangeLog>
|
BIN
static/bd.png
Before Width: | Height: | Size: 135 KiB |