dev add method link
Test Workflow / test (push) Has been cancelled

This commit is contained in:
2026-05-08 11:42:59 +07:00
parent 9dd174eb60
commit ff44763f88
5 changed files with 162 additions and 1 deletions
+5
View File
@@ -73,6 +73,11 @@ dependencies {
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'io.github.resilience4j:resilience4j-spring-boot3'
implementation 'org.springframework.boot:spring-boot-starter-aop'
}
tasks.named('test') {
@@ -2,6 +2,9 @@ package ru.soune.nocopy.dto.user;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import ru.soune.nocopy.entity.user.SubscriptionType;
import java.time.LocalDate;
@Data
public class UserAdditionalInfoBody {
@@ -17,4 +20,37 @@ public class UserAdditionalInfoBody {
@JsonProperty("user_agent")
private String userAgent;
@JsonProperty("page")
private int page = 0;
@JsonProperty("size")
private int size = 5;
@JsonProperty("sort_by")
private String sortBy;
@JsonProperty("sort_direction")
private String sortDirection = "desc";
@JsonProperty("full_name")
private String fullName;
@JsonProperty("email")
private String email;
@JsonProperty("is_active")
private Boolean isActive;
@JsonProperty("email_verified")
private Boolean emailVerified;
@JsonProperty("sub_type")
private SubscriptionType subscriptionType;
@JsonProperty("date_from")
private LocalDate dateFrom;
@JsonProperty("date_to")
private LocalDate dateTo;
}
@@ -3,6 +3,11 @@ package ru.soune.nocopy.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
@@ -10,11 +15,14 @@ import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.user.UserAdditionalInfoBody;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.entity.user.UserAdditionalInfo;
import ru.soune.nocopy.entity.user.UserAdditionalInfoAnswer;
import ru.soune.nocopy.entity.user.UserAdditionalInfoListAnswer;
import ru.soune.nocopy.exception.UserAdditionalInfoNotFound;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.user.AdditionalInfoService;
import ru.soune.nocopy.service.user.UserSpecifications;
import java.util.List;
@@ -28,8 +36,11 @@ import java.util.stream.Collectors;
public class UserInfoHandler implements RequestHandler {
private final AdditionalInfoService additionalInfoService;
private final ObjectMapper objectMapper;
private final UserRepository userRepository;
@Override
public BaseResponse handle(BaseRequest request) throws Exception {
try {
@@ -40,6 +51,7 @@ public class UserInfoHandler implements RequestHandler {
return switch (body.getAction()) {
case "getAll" -> getAllAdditionalInfos(request);
case "getAllWithPagination" -> getAllAdditionalInfoWithPagination(request, body);
case "getById" -> getAdditionalInfoById(request, body.getUserId());
case "update" -> updateAdditionalInfo(request, body);
case "delete" -> deleteAdditionalInfo(request, body.getUserId());
@@ -96,6 +108,44 @@ public class UserInfoHandler implements RequestHandler {
);
}
private BaseResponse getAllAdditionalInfoWithPagination(BaseRequest request, UserAdditionalInfoBody req) {
Sort.Direction direction =
Sort.Direction.fromString(req.getSortDirection() != null ? req.getSortDirection() : "desc");
String sortBy = req.getSortBy() != null ? req.getSortBy() : "createdAt";
Pageable pageable = PageRequest.of(req.getPage(), req.getSize(), Sort.by(direction, sortBy));
Specification<User> spec = (root, query, cb) -> cb.conjunction();
if (req.getFullName() != null) {
spec = spec.and(UserSpecifications.byFullName(req.getFullName()));
}
if (req.getEmail() != null) {
spec = spec.and(UserSpecifications.byEmail(req.getEmail()));
}
if (req.getIsActive() != null) {
spec = spec.and(UserSpecifications.byIsActive(req.getIsActive()));
}
if (req.getEmailVerified() != null) {
spec = spec.and(UserSpecifications.byEmailVerified(req.getEmailVerified()));
}
if (req.getSubscriptionType() != null) {
spec = spec.and(UserSpecifications.bySubscriptionType(req.getSubscriptionType()));
}
if (req.getDateFrom() != null || req.getDateTo() != null) {
spec = spec.and(UserSpecifications.byCreatedAtRange(req.getDateFrom(), req.getDateTo()));
}
Page<User> allUsers = userRepository.findAll(spec, pageable);
return new BaseResponse(
request.getMsgId(),
MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(),
allUsers);
}
private BaseResponse getAdditionalInfoById(BaseRequest request, Long userId) {
log.info("Getting additional info for user: {}", userId);
@@ -1,7 +1,10 @@
package ru.soune.nocopy.repository;
import jakarta.validation.constraints.Size;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.soune.nocopy.entity.tarif.TariffInfo;
@@ -10,12 +13,17 @@ import ru.soune.nocopy.entity.user.User;
import java.util.List;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
User findByEmail(String email);
boolean existsByEmail(String email);
boolean existsByPhone(@Size(min = 11, max = 14) String phone);
List<User> findByCompanyId(String companyId);
long countByCompanyId(String companyId);
User findByPersonalTariffInfo(TariffInfo tariffInfo);
@Query("SELECT COUNT(u.Id) FROM User u")
@@ -48,4 +56,7 @@ public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u.email FROM User u WHERE u.company.id = :company")
List<String> emailsByCompany(@Param("company") String company);
@Query("SELECT u FROM User u LEFT JOIN u.personalTariffInfo t")
Page<User> findAllWithTariff(Pageable pageable);
}
@@ -0,0 +1,59 @@
package ru.soune.nocopy.service.user;
import org.springframework.data.jpa.domain.Specification;
import ru.soune.nocopy.entity.user.SubscriptionType;
import ru.soune.nocopy.entity.user.User;
import java.time.LocalDate;
public class UserSpecifications {
public static Specification<User> byFullName(String fullName) {
return (root, query, cb) -> {
if (fullName == null || fullName.isEmpty()) return null;
return cb.like(cb.lower(root.get("fullName")), "%" + fullName.toLowerCase() + "%");
};
}
public static Specification<User> byEmail(String email) {
return (root, query, cb) -> {
if (email == null || email.isEmpty()) return null;
return cb.like(cb.lower(root.get("email")), "%" + email.toLowerCase() + "%");
};
}
public static Specification<User> byIsActive(Boolean isActive) {
return (root, query, cb) -> {
if (isActive == null) return null;
return cb.equal(root.get("isActive"), isActive);
};
}
public static Specification<User> byEmailVerified(Boolean emailVerified) {
return (root, query, cb) -> {
if (emailVerified == null) return null;
return cb.equal(root.get("emailVerified"), emailVerified);
};
}
public static Specification<User> bySubscriptionType(SubscriptionType type) {
return (root, query, cb) -> {
if (type == null) return null;
return cb.equal(root.get("subscriptionType"), type);
};
}
public static Specification<User> byCreatedAtRange(LocalDate from, LocalDate to) {
return (root, query, cb) -> {
if (from == null && to == null) return null;
if (from != null && to != null) {
return cb.between(root.get("createdAt"),
from.atStartOfDay(), to.atTime(23, 59, 59));
} else if (from != null) {
return cb.greaterThanOrEqualTo(root.get("createdAt"), from.atStartOfDay());
} else {
return cb.lessThanOrEqualTo(root.get("createdAt"), to.atTime(23, 59, 59));
}
};
}
}