7 Commits
Author SHA1 Message Date
backdev d29258855e dev merge
Test Workflow / test (push) Has been cancelled
2026-04-22 16:24:43 +07:00
backdev cbcd16d376 Merge branch 'NCBACK-35' into dev 2026-04-22 16:03:28 +07:00
backdev eb223c2ecb dev add new action
Test Workflow / test (push) Has been cancelled
2026-04-22 12:38:05 +07:00
backdev bb96e3ac93 dev add new action
Test Workflow / test (push) Has been cancelled
2026-04-22 12:16:37 +07:00
backdev 572255c066 dev add monitoring statistic
Test Workflow / test (push) Has been cancelled
2026-04-20 16:15:08 +07:00
backdev d01ea6e2bd dev fix save to storage
Test Workflow / test (push) Has been cancelled
2026-04-20 15:35:24 +07:00
backdev d1a91fec1a dev add user_id for find all complaints
Test Workflow / test (push) Has been cancelled
2026-04-17 22:00:33 +07:00
21 changed files with 407 additions and 12 deletions
@@ -46,7 +46,8 @@ public class HandlerConfig {
StatisticViolationHandler statisticViolationHandler, StatisticViolationHandler statisticViolationHandler,
StatisticSubscriberHandler statisticSubscriberHandler, StatisticSubscriberHandler statisticSubscriberHandler,
StatisticTokenHandler statisticTokenHandler, StatisticTokenHandler statisticTokenHandler,
StatisticIncomeHandler statisticIncomeHandler StatisticIncomeHandler statisticIncomeHandler,
MonitoringStatisticHandler monitoringStatisticHandler
) { ) {
Map<Integer, RequestHandler> map = new HashMap<>(); Map<Integer, RequestHandler> map = new HashMap<>();
@@ -85,6 +86,7 @@ public class HandlerConfig {
map.put(30024, statisticSubscriberHandler); map.put(30024, statisticSubscriberHandler);
map.put(30025, statisticTokenHandler); map.put(30025, statisticTokenHandler);
map.put(30026, statisticIncomeHandler); map.put(30026, statisticIncomeHandler);
map.put(30027, monitoringStatisticHandler);
return map; return map;
} }
@@ -0,0 +1,41 @@
package ru.soune.nocopy.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.soune.nocopy.migration.S3MigrationTool;
import java.util.concurrent.CompletableFuture;
@RestController
@RequestMapping("/api/admin/migration")
@RequiredArgsConstructor
@Slf4j
public class MigrationController {
private final S3MigrationTool migrationTool;
@PostMapping("/start")
public ResponseEntity<String> startMigration() {
log.info("Migration triggered via API");
CompletableFuture.runAsync(() -> {
try {
migrationTool.migrationFilesToS3();
} catch (Exception e) {
log.error("Migration failed", e);
}
});
return ResponseEntity.ok("Migration started. Check logs for progress.");
}
@PostMapping("/status")
public ResponseEntity<String> getStatus() {
return ResponseEntity.ok("Check application logs and migration_failed.txt for details");
}
}
@@ -35,4 +35,7 @@ public class ComplaintRequest {
@JsonProperty("sort_direction") @JsonProperty("sort_direction")
private String sortDirection; private String sortDirection;
@JsonProperty("token")
private String token;
} }
@@ -36,4 +36,7 @@ public class ComplaintResponse {
@JsonProperty("not_moderated") @JsonProperty("not_moderated")
private Boolean notModerated; private Boolean notModerated;
@JsonProperty("file_id")
private String fileId;
} }
@@ -1,5 +1,6 @@
package ru.soune.nocopy.dto.complaint; package ru.soune.nocopy.dto.complaint;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import ru.soune.nocopy.entity.complaint.LawCase; import ru.soune.nocopy.entity.complaint.LawCase;
@@ -14,19 +15,43 @@ import java.util.List;
@Builder @Builder
public class LawCaseResponse { public class LawCaseResponse {
private Long id; private Long id;
private String name; private String name;
private String description; private String description;
private BigDecimal amount; private BigDecimal amount;
private LawCasePriority priority; private LawCasePriority priority;
private LawCaseType type; private LawCaseType type;
private String lawyer; private String lawyer;
@JsonProperty("created_at")
private LocalDateTime createdAt; private LocalDateTime createdAt;
@JsonProperty("updated_at")
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
@JsonProperty("page_number")
private int pageNumber; private int pageNumber;
@JsonProperty("page_size")
private int pageSize; private int pageSize;
@JsonProperty("total_elements")
private long totalElements; private long totalElements;
@JsonProperty("total_pages")
private int totalPages; private int totalPages;
@JsonProperty("violation_id")
private long violationId; private long violationId;
@JsonProperty("file_id")
private String fileId;
private List<LawCaseResponse> content; private List<LawCaseResponse> content;
public static LawCaseResponse fromEntity(LawCase lawCase) { public static LawCaseResponse fromEntity(LawCase lawCase) {
@@ -0,0 +1,8 @@
package ru.soune.nocopy.dto.statistic;
import lombok.Data;
@Data
public class MonitoringStatisticRequest {
private String authToken;
}
@@ -0,0 +1,20 @@
package ru.soune.nocopy.dto.statistic;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class MonitoringStatisticResponse {
@JsonProperty("day")
private Long everyDay;
@JsonProperty("month")
private Long everyMonth;
@JsonProperty("weekly")
private Long everyWeekly;
}
@@ -1,12 +1,22 @@
package ru.soune.nocopy.dto.violation; package ru.soune.nocopy.dto.violation;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.Data;
@Data @Data
public class ViolationNotionRequest { public class ViolationNotionRequest {
@JsonProperty("token")
private String token; private String token;
@JsonProperty("action")
private String action; private String action;
@JsonProperty("violation_id")
private Long violationId; private Long violationId;
@JsonProperty("notion_id")
private Long notionId; private Long notionId;
@JsonProperty("message")
private String message; private String message;
} }
@@ -13,8 +13,14 @@ import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.complaint.ComplaintRequest; import ru.soune.nocopy.dto.complaint.ComplaintRequest;
import ru.soune.nocopy.dto.complaint.ComplaintResponse; import ru.soune.nocopy.dto.complaint.ComplaintResponse;
import ru.soune.nocopy.entity.complaint.ComplaintStatus; import ru.soune.nocopy.entity.complaint.ComplaintStatus;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.complaint.ComplaintEntityService; import ru.soune.nocopy.service.complaint.ComplaintEntityService;
import ru.soune.nocopy.service.register.AuthService;
import ru.soune.nocopy.service.user.UserService;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
@@ -25,11 +31,31 @@ public class ComplaintEntityHandler implements RequestHandler {
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
private final UserRepository userRepository;
private final UserService userService;
private final AuthService authService;
@Override @Override
public BaseResponse handle(BaseRequest request) throws Exception { public BaseResponse handle(BaseRequest request) throws Exception {
Integer msgId = request.getMsgId(); Integer msgId = request.getMsgId();
ComplaintRequest complaintRequest = objectMapper.convertValue(request.getMessageBody(), ComplaintRequest.class); ComplaintRequest complaintRequest = objectMapper.convertValue(request.getMessageBody(), ComplaintRequest.class);
String action = complaintRequest.getAction(); String action = complaintRequest.getAction();
String token = complaintRequest.getToken();
Long userId = authService.useUserAuthToken(token);
User user = userRepository.findById(userId).orElse(null);
if (user == null) {
return new BaseResponse(
request.getMsgId(),
MessageCode.USER_NOT_FOUND.getCode(),
MessageCode.USER_NOT_FOUND.getDescription(),
Map.of("token: ", token));
}
List<String> emails = user.getCompany() == null ? List.of(user.getEmail()):
userService.getUsersCompanyEmails(user.getCompany().getId());
try { try {
switch (action.toLowerCase()) { switch (action.toLowerCase()) {
@@ -38,7 +64,7 @@ public class ComplaintEntityHandler implements RequestHandler {
case "get": case "get":
return handleGet(msgId, complaintRequest); return handleGet(msgId, complaintRequest);
case "get_all": case "get_all":
return handleGetAll(msgId, complaintRequest); return handleGetAll(msgId, complaintRequest, emails);
case "get_by_violation": case "get_by_violation":
return handleGetByViolation(msgId, complaintRequest); return handleGetByViolation(msgId, complaintRequest);
case "update_status": case "update_status":
@@ -74,14 +100,15 @@ public class ComplaintEntityHandler implements RequestHandler {
return successResponse(msgId, "Complaint retrieved successfully", response); return successResponse(msgId, "Complaint retrieved successfully", response);
} }
private BaseResponse handleGetAll(Integer msgId, ComplaintRequest req) { private BaseResponse handleGetAll(Integer msgId, ComplaintRequest req, List<String> emails) {
Pageable pageable = PageRequest.of( Pageable pageable = PageRequest.of(
req.getPage() != null ? req.getPage() : 0, req.getPage() != null ? req.getPage() : 0,
req.getSize() != null ? req.getSize() : 5, req.getSize() != null ? req.getSize() : 5,
Sort.by(Sort.Direction.fromString(req.getSortDirection() != null ? req.getSortDirection() : "desc"), Sort.by(Sort.Direction.fromString(req.getSortDirection() != null ? req.getSortDirection() : "desc"),
req.getSortBy() != null ? req.getSortBy() : "updatedAt")); req.getSortBy() != null ? req.getSortBy() : "updatedAt"));
var page = complaintService.getAllComplaints(pageable); var page = complaintService.getAllComplaintsByEmail(pageable, emails);
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new HashMap<>();
data.put("content", page.getContent()); data.put("content", page.getContent());
data.put("page", page.getNumber()); data.put("page", page.getNumber());
@@ -6,12 +6,21 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest; import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse; import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.search.GlobalSearchStatisticsRequest; import ru.soune.nocopy.dto.search.GlobalSearchStatisticsRequest;
import ru.soune.nocopy.dto.search.GlobalSearchStatisticsResponse; import ru.soune.nocopy.dto.search.GlobalSearchStatisticsResponse;
import ru.soune.nocopy.entity.company.Company;
import ru.soune.nocopy.entity.user.AuthToken; import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.repository.AuthTokenRepository; import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.CompanyService;
import ru.soune.nocopy.service.search.GlobalSearchStatisticsService; import ru.soune.nocopy.service.search.GlobalSearchStatisticsService;
import ru.soune.nocopy.service.user.UserService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
@Slf4j @Slf4j
@@ -17,6 +17,7 @@ import ru.soune.nocopy.entity.complaint.LawCasePriority;
import ru.soune.nocopy.entity.complaint.LawCaseType; import ru.soune.nocopy.entity.complaint.LawCaseType;
import ru.soune.nocopy.entity.tokenoperation.OperationType; import ru.soune.nocopy.entity.tokenoperation.OperationType;
import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.entity.violation.Violation;
import ru.soune.nocopy.exception.NotValidFieldException; import ru.soune.nocopy.exception.NotValidFieldException;
import ru.soune.nocopy.exception.TariffNotFoundException; import ru.soune.nocopy.exception.TariffNotFoundException;
import ru.soune.nocopy.exception.UserNotFoundException; import ru.soune.nocopy.exception.UserNotFoundException;
@@ -25,8 +26,10 @@ import ru.soune.nocopy.service.complaint.LawCaseService;
import ru.soune.nocopy.service.register.AuthService; import ru.soune.nocopy.service.register.AuthService;
import ru.soune.nocopy.service.tariff.TariffConstants; import ru.soune.nocopy.service.tariff.TariffConstants;
import ru.soune.nocopy.service.tariff.TariffInfoService; import ru.soune.nocopy.service.tariff.TariffInfoService;
import ru.soune.nocopy.service.violation.ViolationService;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -46,6 +49,8 @@ public class LawCaseHandler implements RequestHandler {
private final TariffInfoService tariffInfoService; private final TariffInfoService tariffInfoService;
private final ViolationService violationService;
@Override @Override
public BaseResponse handle(BaseRequest request) throws Exception { public BaseResponse handle(BaseRequest request) throws Exception {
@@ -84,9 +89,17 @@ public class LawCaseHandler implements RequestHandler {
lawCaseRequest.getSortBy(), lawCaseRequest.getSortBy(),
lawCaseRequest.getSortDir()); lawCaseRequest.getSortDir());
List<LawCaseResponse> responses = lawCases.getContent().stream() List<LawCaseResponse> responses = new ArrayList<>();
.map(LawCaseResponse::fromEntity) List<LawCase> content = lawCases.getContent();
.collect(Collectors.toList());
for (LawCase lawCase: content) {
LawCaseResponse lawCaseResponse = LawCaseResponse.fromEntity(lawCase);
Violation violation = violationService.getById(lawCase.getViolationId());
if (violation != null) lawCaseResponse.setFileId(violation.getFileEntity().getId());
responses.add(lawCaseResponse);
}
PaginatedResponse<LawCaseResponse> paginatedResponse = new PaginatedResponse<>( PaginatedResponse<LawCaseResponse> paginatedResponse = new PaginatedResponse<>(
responses, responses,
@@ -0,0 +1,72 @@
package ru.soune.nocopy.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.statistic.MonitoringStatisticRequest;
import ru.soune.nocopy.dto.statistic.MonitoringStatisticResponse;
import ru.soune.nocopy.entity.company.Company;
import ru.soune.nocopy.entity.monitoring.MonitoringType;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.repository.FileMonitoringRepository;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.register.AuthService;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class MonitoringStatisticHandler implements RequestHandler {
private final ObjectMapper objectMapper;
private final AuthService authService;
private final FileMonitoringRepository fileMonitoringRepository;
private final UserRepository userRepository;
@Override
public BaseResponse handle(BaseRequest request) throws Exception {
MonitoringStatisticRequest monitoringStatisticRequest = objectMapper.convertValue(request.getMessageBody(),
MonitoringStatisticRequest.class);
try {
String authToken = monitoringStatisticRequest.getAuthToken();
Long userId = authService.useUserAuthToken(authToken);
User user = userRepository.findById(userId).orElseThrow();
Company company = user.getCompany();
List<Long> userIds = company == null ? List.of(userId) :
user.getCompany()
.getUsers()
.stream()
.map(User::getId).toList();
MonitoringStatisticResponse monitoringStatisticResponse = MonitoringStatisticResponse.builder()
.everyDay(fileMonitoringRepository.countByUserIdsAndMonitoringType(userIds,
MonitoringType.MONITORING_DAILY))
.everyMonth(fileMonitoringRepository.countByUserIdsAndMonitoringType(userIds,
MonitoringType.MONITORING_MONTHLY))
.everyWeekly(fileMonitoringRepository.countByUserIdsAndMonitoringType(userIds,
MonitoringType.MONITORING_WEEKLY))
.build();
return new BaseResponse(
request.getMsgId(),
MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(),
monitoringStatisticResponse);
} catch (Exception e) {
return new BaseResponse(
request.getMsgId(),
MessageCode.INVALID_JSON_BODY.getCode(),
MessageCode.INVALID_JSON_BODY.getDescription(),
null);
}
}
}
@@ -25,6 +25,7 @@ import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
@Component @Component
@Slf4j @Slf4j
@@ -115,11 +116,21 @@ public class ViolationHandler implements RequestHandler {
violationRequest.getPage(), violationRequest.getSize(), violationRequest.getSortDirection() violationRequest.getPage(), violationRequest.getSize(), violationRequest.getSortDirection()
); );
} }
ViolationResponse.ViolationDto firstShowViolation = null;
List<Violation> content = violationPage.getContent(); List<Violation> content = violationPage.getContent();
List<ViolationResponse.ViolationDto> violationDtos = new ArrayList<>(); List<ViolationResponse.ViolationDto> violationDtos = new ArrayList<>();
if ("getByViolationId".equals(violationRequest.getAction())) {
Violation violation = violationService.getById(violationRequest.getViolationId());
if (violation != null) {
firstShowViolation = ViolationResponse.ViolationDto.fromEntity(violation);
violationDtos.add(firstShowViolation);
}
}
for (Violation violation : content) { for (Violation violation : content) {
if (firstShowViolation != null && Objects.equals(firstShowViolation.getId(), violation.getId())) continue;
ViolationResponse.ViolationDto violationDto = ViolationResponse.ViolationDto.fromEntity(violation); ViolationResponse.ViolationDto violationDto = ViolationResponse.ViolationDto.fromEntity(violation);
violationDto.setCountry(geoCountryService.getCountryName(violation.getPageUrl())); violationDto.setCountry(geoCountryService.getCountryName(violation.getPageUrl()));
violationDto.setCountryCode(geoCountryService.getCountryCode(violation.getPageUrl())); violationDto.setCountryCode(geoCountryService.getCountryCode(violation.getPageUrl()));
@@ -0,0 +1,119 @@
package ru.soune.nocopy.migration;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
@RequiredArgsConstructor
public class S3MigrationTool {
private final FileEntityRepository fileEntityRepository;
private final CloudStorageService cloudStorageService;
private static final Path FAILED_LOG = Paths.get("migration_failed.txt");
public void migrationFilesToS3() {
log.info("=== START MIGRATION ===");
clearLogFile();
List<FileEntity> allFiles = fileEntityRepository.findAll();
log.info("Total files: {}", allFiles.size());
int success = 0;
List<String> failedIds = new ArrayList<>();
for (FileEntity file : allFiles) {
if (migrateFile(file)) {
success++;
} else {
failedIds.add(file.getId());
}
}
log.info("=== COMPLETED: success {}, failed {} ===", success, failedIds.size());
if (!failedIds.isEmpty()) {
log.info("Failed file IDs: {}", String.join(", ", failedIds));
log.info("Details saved to: {}", FAILED_LOG.toAbsolutePath());
}
}
private boolean migrateFile(FileEntity file) {
StringBuilder errors = new StringBuilder();
try {
cloudStorageService.saveFilesToStorage(
file.getMimeType(), file.getFileExtension(), file.getFilePath()
);
} catch (Exception e) {
errors.append("main:").append(e.getMessage()).append("; ");
}
if ("image".equals(file.getMimeType())) {
try {
cloudStorageService.saveFilesToStorage(
file.getMimeType(), file.getFileExtension(), file.getMediumPath()
);
} catch (Exception e) {
errors.append("medium:").append(e.getMessage()).append("; ");
}
try {
cloudStorageService.saveFilesToStorage(
file.getMimeType(), file.getFileExtension(), file.getThumbnailPath()
);
} catch (Exception e) {
errors.append("thumb:").append(e.getMessage()).append("; ");
}
}
if (file.getProtectedFilePath() != null) {
try {
cloudStorageService.saveFilesToStorage(
file.getMimeType() != null ? file.getMimeType() : "application",
file.getFileExtension(),
file.getProtectedFilePath()
);
} catch (Exception e) {
errors.append("protected:").append(e.getMessage()).append("; ");
}
}
if (errors.length() > 0) {
writeToFile(String.format("%s | %s | %s",
file.getId(), file.getOriginalFileName(), errors));
log.warn("Failed to migrate: {} | {}", file.getId(), file.getOriginalFileName());
return false;
}
return true;
}
private void clearLogFile() {
try {
Files.deleteIfExists(FAILED_LOG);
} catch (IOException e) {
log.warn("Failed to clear log file");
}
}
private void writeToFile(String line) {
try {
Files.write(FAILED_LOG, (line + "\n").getBytes(),
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (IOException e) {
log.error("Failed to write to log file", e);
}
}
}
@@ -5,6 +5,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.soune.nocopy.entity.complaint.ComplaintEntity; import ru.soune.nocopy.entity.complaint.ComplaintEntity;
@@ -37,4 +38,7 @@ public interface ComplaintEntityRepository extends JpaRepository<ComplaintEntity
) )
""") """)
Long getComplaintsWithoutLawCaseCount(); Long getComplaintsWithoutLawCaseCount();
@Query("SELECT c FROM ComplaintEntity c WHERE c.email IN :emails")
Page<ComplaintEntity> getComplaintsByUserEmails(@Param("emails") List<String> emails, Pageable pageable);
} }
@@ -22,4 +22,11 @@ public interface FileMonitoringRepository extends JpaRepository<FileMonitoringEn
List<FileMonitoringEntity> findReadyForRun(@Param("now") LocalDateTime now); List<FileMonitoringEntity> findReadyForRun(@Param("now") LocalDateTime now);
List<FileMonitoringEntity> findByMonitoringTypeAndIsActiveTrue(MonitoringType type); List<FileMonitoringEntity> findByMonitoringTypeAndIsActiveTrue(MonitoringType type);
@Query("SELECT COUNT(m) FROM FileMonitoringEntity m " +
"WHERE m.userId IN :userIds " +
"AND m.monitoringType = :monitoringType " +
"AND m.isActive = true")
long countByUserIdsAndMonitoringType(@Param("userIds") List<Long> userIds,
@Param("monitoringType") MonitoringType monitoringType);
} }
@@ -45,4 +45,7 @@ public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.personalTariffInfo.id = :tariffInfoId") @Query("SELECT u FROM User u WHERE u.personalTariffInfo.id = :tariffInfoId")
Optional<User> findByPersonalTariffInfoId(@Param("tariffInfoId") String tariffInfoId); Optional<User> findByPersonalTariffInfoId(@Param("tariffInfoId") String tariffInfoId);
@Query("SELECT u.email FROM User u WHERE u.company = :company")
List<String> emailsByCompany(@Param("company") String company);
} }
@@ -62,6 +62,12 @@ public class ComplaintEntityService {
return mapToResponse(complaintRepository.save(complaint)); return mapToResponse(complaintRepository.save(complaint));
} }
@Transactional(readOnly = true)
public Page<ComplaintResponse> getAllComplaintsByEmail(Pageable pageable, List<String> emails) {
return complaintRepository.getComplaintsByUserEmails(emails, pageable)
.map(this::mapToResponse);
}
@Transactional(readOnly = true) @Transactional(readOnly = true)
public ComplaintResponse getComplaintById(Long id) { public ComplaintResponse getComplaintById(Long id) {
return complaintRepository.findById(id) return complaintRepository.findById(id)
@@ -121,13 +127,15 @@ public class ComplaintEntityService {
} }
private ComplaintResponse mapToResponse(ComplaintEntity entity) { private ComplaintResponse mapToResponse(ComplaintEntity entity) {
Violation violation = entity.getViolation();
return ComplaintResponse.builder() return ComplaintResponse.builder()
.id(entity.getId()) .id(entity.getId())
.status(entity.getStatus() != null ? entity.getStatus().name() : null) .status(entity.getStatus() != null ? entity.getStatus().name() : null)
.complaintText(entity.getComplaintText()) .complaintText(entity.getComplaintText())
.email(entity.getEmail()) .email(entity.getEmail())
.violationId(entity.getViolation() != null ? entity.getViolation().getId() : null) .violationId(violation != null ? violation.getId() : null)
.fileId(violation != null ? violation.getFileEntity().getId() : null)
.createdAt(entity.getCreatedAt() != null ? entity.getCreatedAt().format(DATE_FORMATTER) : null) .createdAt(entity.getCreatedAt() != null ? entity.getCreatedAt().format(DATE_FORMATTER) : null)
.updatedAt(entity.getUpdatedAt() != null ? entity.getUpdatedAt().format(DATE_FORMATTER) : null) .updatedAt(entity.getUpdatedAt() != null ? entity.getUpdatedAt().format(DATE_FORMATTER) : null)
.notModerated(entity.getNot_moderated_file() != null ? entity.getNot_moderated_file() : null) .notModerated(entity.getNot_moderated_file() != null ? entity.getNot_moderated_file() : null)
@@ -44,13 +44,13 @@ public class GlobalSearchService {
task.setProcessedFiles(0); task.setProcessedFiles(0);
task.setCreatedAt(LocalDateTime.now()); task.setCreatedAt(LocalDateTime.now());
globalSearchTaskRepository.save(task); GlobalSearchTask save = globalSearchTaskRepository.save(task);
List<String> fileIds = filesToProcess.stream().map(FileEntity::getId).toList(); List<String> fileIds = filesToProcess.stream().map(FileEntity::getId).toList();
asyncProcessor.processFilesAsync(task.getTaskId(), fileIds, userId); asyncProcessor.processFilesAsync(save.getTaskId(), fileIds, userId);
return task.getTaskId(); return save.getTaskId();
} }
public List<FileEntity> getFilesToProcess(GlobalSearchStartRequest request, Long userId) { public List<FileEntity> getFilesToProcess(GlobalSearchStartRequest request, Long userId) {
@@ -13,6 +13,7 @@ import ru.soune.nocopy.exception.NotValidationPasswordException;
import ru.soune.nocopy.exception.UserNotFoundException; import ru.soune.nocopy.exception.UserNotFoundException;
import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.repository.UserRepository;
import java.util.List;
import java.util.Optional; import java.util.Optional;
@Service @Service
@@ -46,6 +47,11 @@ public class UserService {
return mapToDTO(updatedUser); return mapToDTO(updatedUser);
} }
@Transactional
public List<String> getUsersCompanyEmails(String company) {
return userRepository.emailsByCompany(company);
}
@Transactional @Transactional
public User activateAndVerifyUser(long userId) { public User activateAndVerifyUser(long userId) {
Optional<User> users = userRepository.findById(userId); Optional<User> users = userRepository.findById(userId);
@@ -56,6 +56,10 @@ public class ViolationService {
} }
} }
public Violation getById(Long violationId) {
return violationRepository.findById(violationId).orElse(null);
}
public List<FileViolationSummaryDTO> getFileViolationsSummary(Long userId) { public List<FileViolationSummaryDTO> getFileViolationsSummary(Long userId) {
List<FileEntity> userFiles = fileEntityService.getAllUserFiles(userId); List<FileEntity> userFiles = fileEntityService.getAllUserFiles(userId);
List<Violation> violations = violationRepository.findByFileEntityIn(userFiles); List<Violation> violations = violationRepository.findByFileEntityIn(userFiles);