@@ -37,7 +37,8 @@ public class HandlerConfig {
|
||||
UserInfoHandler userInfoHandler,
|
||||
NotificationHandler notificationHandler,
|
||||
UserVerificationHandler userVerificationHandler,
|
||||
LawCaseHandler lawCaseHandler
|
||||
LawCaseHandler lawCaseHandler,
|
||||
TokenOperationHandler tokenOperationHandler
|
||||
) {
|
||||
Map<Integer, RequestHandler> map = new HashMap<>();
|
||||
map.put(20001, login);
|
||||
@@ -66,6 +67,7 @@ public class HandlerConfig {
|
||||
map.put(30015, notificationHandler);
|
||||
map.put(30016, userVerificationHandler);
|
||||
map.put(30017, lawCaseHandler);
|
||||
map.put(30018, tokenOperationHandler);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class PaymentController {
|
||||
}
|
||||
|
||||
paymentService.changeAutoRenewal(authService.useUserAuthToken(tokenHeader), renewal);
|
||||
return ResponseEntity.ok(Map.of("message", "Auto-renewal disabled"));
|
||||
return ResponseEntity.ok(Map.of("message", "Auto-renewal changed:" + renewal));
|
||||
} catch (UserNotFoundException e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(Map.of("error", e.getMessage()));
|
||||
|
||||
@@ -48,6 +48,7 @@ public enum MessageCode {
|
||||
TARIFF_IS_NOT_FOUND(0, "Tariff is not found"),
|
||||
VALIDATION_ERROR(2, "Validation error"),
|
||||
RESOURCE_NOT_FOUND(4, "Resource not found"),
|
||||
OPERATION_NOT_FOUND(4, "Operation not found"),
|
||||
INTERNAL_ERROR(4, "Internal server error"),
|
||||
COMPANY_NOT_FOUND(4, "Company not found"),
|
||||
PAYMENT_NOT_FOUND(4, "Payment not found"),
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package ru.soune.nocopy.dto.tokenoperation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import ru.soune.nocopy.entity.tokenoperation.TokenOperation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class TokenOperationPageDto {
|
||||
|
||||
@JsonProperty("content")
|
||||
private List<TokenOperation> content;
|
||||
|
||||
@JsonProperty("page_number")
|
||||
private int pageNumber;
|
||||
|
||||
@JsonProperty("page_size")
|
||||
private int pageSize;
|
||||
|
||||
@JsonProperty("total_elements")
|
||||
private long totalElements;
|
||||
|
||||
@JsonProperty("total_pages")
|
||||
private int totalPages;
|
||||
|
||||
@JsonProperty("is_last")
|
||||
private boolean last;
|
||||
|
||||
@JsonProperty("is_first")
|
||||
private boolean first;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package ru.soune.nocopy.dto.tokenoperation;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
|
||||
@Data
|
||||
public class TokenOperationRequest {
|
||||
|
||||
@JsonProperty("action")
|
||||
private String action;
|
||||
|
||||
@JsonProperty("token")
|
||||
private String token;
|
||||
|
||||
@JsonProperty("operation_id")
|
||||
private Long operationId;
|
||||
|
||||
@JsonProperty("operation_type")
|
||||
private OperationType operationType;
|
||||
|
||||
@JsonProperty("spent")
|
||||
private Long spent;
|
||||
|
||||
@JsonProperty("page")
|
||||
private Integer page = 0;
|
||||
|
||||
@JsonProperty("size")
|
||||
private Integer size = 20;
|
||||
|
||||
@JsonProperty("sort_by")
|
||||
private String sortBy = "createdAt";
|
||||
|
||||
@JsonProperty("sort_direction")
|
||||
private String sortDirection = "desc";
|
||||
|
||||
@JsonProperty("min_spent")
|
||||
private Long minSpent;
|
||||
|
||||
@JsonProperty("max_spent")
|
||||
private Long maxSpent;
|
||||
|
||||
@JsonProperty("updates")
|
||||
private Object updates;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package ru.soune.nocopy.dto.tokenoperation;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class TokenOperationResponse {
|
||||
|
||||
@JsonProperty("success")
|
||||
private Boolean success;
|
||||
|
||||
@JsonProperty("message")
|
||||
private String message;
|
||||
|
||||
@JsonProperty("data")
|
||||
private Object data;
|
||||
|
||||
@JsonProperty("total_elements")
|
||||
private Long totalElements;
|
||||
|
||||
@JsonProperty("total_pages")
|
||||
private Integer totalPages;
|
||||
|
||||
@JsonProperty("current_page")
|
||||
private Integer currentPage;
|
||||
|
||||
@JsonProperty("page_size")
|
||||
private Integer pageSize;
|
||||
|
||||
@JsonProperty("statistics")
|
||||
private Map<String, Object> statistics;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package ru.soune.nocopy.entity.tokenoperation;
|
||||
|
||||
public enum OperationType {
|
||||
SEARCH("search"), MONITORING("monitoring"), CREATE_LEGAL_CASE("legal_case"),
|
||||
FILE_UPLOAD("file_upload"), GLOBAL_SEARCH("global_search");
|
||||
|
||||
private final String name;
|
||||
|
||||
private OperationType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ru.soune.nocopy.entity.tokenoperation;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Table(name = "token_operation")
|
||||
@Entity
|
||||
@Setter @Getter
|
||||
@NoArgsConstructor
|
||||
public class TokenOperation {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "operation_type")
|
||||
private OperationType operationType;
|
||||
|
||||
@Column(name = "user_id")
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "spent")
|
||||
private Long spent;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(name = "created_at", updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import ru.soune.nocopy.dto.MessageCode;
|
||||
import ru.soune.nocopy.dto.file.ImageSearchRequest;
|
||||
import ru.soune.nocopy.dto.file.YandexSearchResponse;
|
||||
import ru.soune.nocopy.entity.file.FileEntity;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||
import ru.soune.nocopy.repository.FileEntityRepository;
|
||||
import ru.soune.nocopy.service.file.CheckCounterService;
|
||||
@@ -117,7 +118,8 @@ public class ImageFoundRequestHandler implements RequestHandler {
|
||||
log.info("Results only from Yandex: {} images", allUniqueImages.size());
|
||||
}
|
||||
|
||||
tariffInfoService.writeOffTokens(fileEntity.getUserId(), TariffConstants.TOKEN_VALUE_FOR_SEARCH);
|
||||
tariffInfoService.writeOffTokens(fileEntity.getUserId(), TariffConstants.TOKEN_VALUE_FOR_SEARCH,
|
||||
OperationType.SEARCH);
|
||||
checkCounterService.incrementCheckCount(fileEntity.getUserId(), fileEntity.getMimeType());
|
||||
|
||||
int page = imageSearchRequest.getPage() != null ? imageSearchRequest.getPage() : 1;
|
||||
|
||||
@@ -15,6 +15,7 @@ import ru.soune.nocopy.dto.complaint.PaginatedResponse;
|
||||
import ru.soune.nocopy.entity.complaint.LawCase;
|
||||
import ru.soune.nocopy.entity.complaint.LawCasePriority;
|
||||
import ru.soune.nocopy.entity.complaint.LawCaseType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||
import ru.soune.nocopy.exception.TariffNotFoundException;
|
||||
@@ -114,7 +115,7 @@ public class LawCaseHandler implements RequestHandler {
|
||||
|
||||
private BaseResponse createLawCase(Long userId, LawCaseRequest lawCaseRequest, BaseRequest request) {
|
||||
try {
|
||||
tariffInfoService.writeOffTokens(userId, TariffConstants.LEGAL_COST);
|
||||
tariffInfoService.writeOffTokens(userId, TariffConstants.LEGAL_COST, OperationType.CREATE_LEGAL_CASE);
|
||||
} catch (TariffNotFoundException e) {
|
||||
return new BaseResponse(request.getMsgId(), MessageCode.USER_NOT_HAVE_TOKEN.getCode(),
|
||||
MessageCode.USER_NOT_HAVE_TOKEN.getDescription(),
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
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.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.tokenoperation.TokenOperationPageDto;
|
||||
import ru.soune.nocopy.dto.tokenoperation.TokenOperationRequest;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.TokenOperation;
|
||||
import ru.soune.nocopy.service.register.AuthService;
|
||||
import ru.soune.nocopy.service.tokenoperation.TokenOperationService;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TokenOperationHandler implements RequestHandler {
|
||||
private final TokenOperationService tokenOperationService;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Override
|
||||
public BaseResponse handle(BaseRequest request) throws Exception {
|
||||
log.info("Handling TokenOperation request: msg_id={}, version={}",
|
||||
request.getMsgId(), request.getVersion());
|
||||
|
||||
try {
|
||||
TokenOperationRequest tokenRequest = objectMapper.convertValue(
|
||||
request.getMessageBody(),
|
||||
TokenOperationRequest.class
|
||||
);
|
||||
|
||||
String action = tokenRequest.getAction();
|
||||
if (action == null) {
|
||||
return new BaseResponse(
|
||||
request.getMsgId(),
|
||||
MessageCode.INVALID_ACTION.getCode(),
|
||||
MessageCode.INVALID_ACTION.getDescription(),
|
||||
Map.of("error", "Action is required")
|
||||
);
|
||||
}
|
||||
|
||||
switch (action.toLowerCase()) {
|
||||
case "get_list":
|
||||
return handleGetList(request.getMsgId(), tokenRequest);
|
||||
case "get_by_id":
|
||||
return handleGetById(request.getMsgId(), tokenRequest);
|
||||
case "get_by_user":
|
||||
return handleGetByUser(request.getMsgId(), tokenRequest);
|
||||
case "create":
|
||||
return handleCreate(request.getMsgId(), tokenRequest);
|
||||
case "update":
|
||||
return handleUpdate(request.getMsgId(), tokenRequest);
|
||||
case "delete":
|
||||
return handleDelete(request.getMsgId(), tokenRequest);
|
||||
case "delete_all_by_user":
|
||||
return handleDeleteAllByUser(request.getMsgId(), tokenRequest);
|
||||
case "get_stats":
|
||||
return handleGetStats(request.getMsgId(), tokenRequest);
|
||||
case "filter":
|
||||
return handleFilter(request.getMsgId(), tokenRequest);
|
||||
default:
|
||||
return new BaseResponse(
|
||||
request.getMsgId(),
|
||||
MessageCode.INVALID_ACTION.getCode(),
|
||||
MessageCode.INVALID_ACTION.getDescription(),
|
||||
Map.of("available_actions",
|
||||
"get_list, get_by_id, get_by_user, create, update, " +
|
||||
"delete, delete_all_by_user, get_stats, filter")
|
||||
);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error handling TokenOperation request", e);
|
||||
return new BaseResponse(
|
||||
request.getMsgId(),
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleGetList(Integer msgId, TokenOperationRequest request) {
|
||||
if (request.getToken() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.USER_NOT_FOUND.getCode(),
|
||||
MessageCode.USER_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
Long userId = authService.useUserAuthToken(request.getToken());
|
||||
|
||||
try {
|
||||
Page<TokenOperation> page = tokenOperationService.findByUserId(
|
||||
userId,
|
||||
request.getPage() != null ? request.getPage() : 0,
|
||||
request.getSize() != null ? request.getSize() : 20
|
||||
);
|
||||
|
||||
TokenOperationPageDto pageDto = TokenOperationPageDto.builder()
|
||||
.content(page.getContent())
|
||||
.pageNumber(page.getNumber())
|
||||
.pageSize(page.getSize())
|
||||
.totalElements(page.getTotalElements())
|
||||
.totalPages(page.getTotalPages())
|
||||
.last(page.isLast())
|
||||
.first(page.isFirst())
|
||||
.build();
|
||||
|
||||
Map<String, Object> responseData = new HashMap<>();
|
||||
responseData.put("operations", pageDto);
|
||||
responseData.put("total_elements", page.getTotalElements());
|
||||
responseData.put("total_pages", page.getTotalPages());
|
||||
responseData.put("current_page", page.getNumber());
|
||||
responseData.put("page_size", page.getSize());
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
responseData
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting token operations list", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error getting operations: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleGetById(Integer msgId, TokenOperationRequest request) {
|
||||
log.info("Getting token operation by id: {}", request.getOperationId());
|
||||
|
||||
if (request.getOperationId() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.OPERATION_NOT_FOUND.getCode(),
|
||||
MessageCode.OPERATION_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
TokenOperation operation = tokenOperationService.findById(request.getOperationId());
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
operation
|
||||
);
|
||||
|
||||
} catch (jakarta.persistence.EntityNotFoundException e) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.NOT_FOUND.getCode(),
|
||||
MessageCode.NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation not found with id: " + request.getOperationId())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting token operation by id", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleGetByUser(Integer msgId, TokenOperationRequest request) {
|
||||
return handleGetList(msgId, request);
|
||||
}
|
||||
|
||||
private BaseResponse handleCreate(Integer msgId, TokenOperationRequest request) {
|
||||
if (request.getToken() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(),
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
Long userId = authService.useUserAuthToken(request.getToken());
|
||||
|
||||
try {
|
||||
TokenOperation operation = tokenOperationService.create(
|
||||
request.getOperationType(),
|
||||
userId,
|
||||
request.getSpent()
|
||||
);
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
operation
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error creating token operation", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error creating operation: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleUpdate(Integer msgId, TokenOperationRequest request) {
|
||||
log.info("Updating token operation: {}", request.getOperationId());
|
||||
|
||||
if (request.getOperationId() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.OPERATION_NOT_FOUND.getCode(),
|
||||
MessageCode.OPERATION_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
TokenOperation existing = tokenOperationService.findById(request.getOperationId());
|
||||
|
||||
if (request.getOperationType() != null) {
|
||||
existing.setOperationType(request.getOperationType());
|
||||
}
|
||||
if (request.getSpent() != null) {
|
||||
existing.setSpent(request.getSpent());
|
||||
}
|
||||
|
||||
TokenOperation updated = tokenOperationService.update(request.getOperationId(), existing);
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
updated
|
||||
);
|
||||
|
||||
} catch (jakarta.persistence.EntityNotFoundException e) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.NOT_FOUND.getCode(),
|
||||
MessageCode.NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation not found with id: " + request.getOperationId())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("Error updating token operation", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error updating operation: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleDelete(Integer msgId, TokenOperationRequest request) {
|
||||
log.info("Deleting token operation: {}", request.getOperationId());
|
||||
|
||||
if (request.getOperationId() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.OPERATION_NOT_FOUND.getCode(),
|
||||
MessageCode.OPERATION_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
tokenOperationService.deleteById(request.getOperationId());
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
Map.of("message", "Operation deleted successfully",
|
||||
"operation_id", request.getOperationId())
|
||||
);
|
||||
|
||||
} catch (jakarta.persistence.EntityNotFoundException e) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.NOT_FOUND.getCode(),
|
||||
MessageCode.NOT_FOUND.getDescription(),
|
||||
Map.of("error", "Operation not found with id: " + request.getOperationId())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("Error deleting token operation", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error deleting operation: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleDeleteAllByUser(Integer msgId, TokenOperationRequest request) {
|
||||
if (request.getToken() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(),
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
Long userId = authService.useUserAuthToken(request.getToken());
|
||||
|
||||
try {
|
||||
tokenOperationService.deleteByUserId(userId);
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
Map.of("message", "All operations deleted successfully for user",
|
||||
"user_id", userId)
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error deleting all operations for user", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error deleting operations: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleGetStats(Integer msgId, TokenOperationRequest request) {
|
||||
if (request.getToken() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(),
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
Long userId = authService.useUserAuthToken(request.getToken());
|
||||
|
||||
if (userId == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.USER_NOT_FOUND.getCode(),
|
||||
MessageCode.USER_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
Map<String, Long> statsByType = new HashMap<>();
|
||||
long totalSpent = 0L;
|
||||
|
||||
for (OperationType type : OperationType.values()) {
|
||||
Long spent = tokenOperationService.getTotalSpentByUserAndType(userId, type);
|
||||
statsByType.put(type.name().toLowerCase(), spent != null ? spent : 0L);
|
||||
totalSpent += spent != null ? spent : 0L;
|
||||
}
|
||||
|
||||
Map<String, Object> statistics = new HashMap<>();
|
||||
statistics.put("user_id", userId);
|
||||
statistics.put("total_spent", totalSpent);
|
||||
statistics.put("total_operations", tokenOperationService.countByUserId(userId));
|
||||
statistics.put("stats_by_type", statsByType);
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
statistics
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting statistics", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error getting statistics: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseResponse handleFilter(Integer msgId, TokenOperationRequest request) {
|
||||
if (request.getToken() == null) {
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(),
|
||||
MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(),
|
||||
Map.of("error", "User ID is required")
|
||||
);
|
||||
}
|
||||
|
||||
Long userId = authService.useUserAuthToken(request.getToken());
|
||||
|
||||
try {
|
||||
Page<TokenOperation> page = tokenOperationService.findByFilters(
|
||||
userId,
|
||||
request.getOperationType(),
|
||||
request.getMinSpent(),
|
||||
request.getMaxSpent(),
|
||||
request.getPage() != null ? request.getPage() : 0,
|
||||
request.getSize() != null ? request.getSize() : 20,
|
||||
request.getSortBy() != null ? request.getSortBy() : "createdAt",
|
||||
request.getSortDirection() != null ? request.getSortDirection() : "desc"
|
||||
);
|
||||
|
||||
TokenOperationPageDto pageDto = TokenOperationPageDto.builder()
|
||||
.content(page.getContent())
|
||||
.pageNumber(page.getNumber())
|
||||
.pageSize(page.getSize())
|
||||
.totalElements(page.getTotalElements())
|
||||
.totalPages(page.getTotalPages())
|
||||
.last(page.isLast())
|
||||
.first(page.isFirst())
|
||||
.build();
|
||||
|
||||
Map<String, Object> responseData = new HashMap<>();
|
||||
responseData.put("operations", pageDto);
|
||||
responseData.put("total_elements", page.getTotalElements());
|
||||
responseData.put("total_pages", page.getTotalPages());
|
||||
responseData.put("current_page", page.getNumber());
|
||||
responseData.put("page_size", page.getSize());
|
||||
|
||||
responseData.put("applied_filters", Map.of(
|
||||
"user_id",userId != null ? userId : "all",
|
||||
"operation_type", request.getOperationType() != null ? request.getOperationType() : "all",
|
||||
"min_spent", request.getMinSpent() != null ? request.getMinSpent() : "none",
|
||||
"max_spent", request.getMaxSpent() != null ? request.getMaxSpent() : "none"
|
||||
));
|
||||
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.SUCCESS.getCode(),
|
||||
MessageCode.SUCCESS.getDescription(),
|
||||
responseData
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error filtering operations", e);
|
||||
return new BaseResponse(
|
||||
msgId,
|
||||
MessageCode.INTERNAL_ERROR.getCode(),
|
||||
MessageCode.INTERNAL_ERROR.getDescription(),
|
||||
Map.of("error", "Error filtering operations: " + e.getMessage())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package ru.soune.nocopy.repository;
|
||||
|
||||
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.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.TokenOperation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface TokenOperationRepository extends JpaRepository<TokenOperation, Long> {
|
||||
Page<TokenOperation> findAll(Pageable pageable);
|
||||
|
||||
List<TokenOperation> findByUserId(Long userId);
|
||||
|
||||
Page<TokenOperation> findByUserId(Long userId, Pageable pageable);
|
||||
|
||||
Page<TokenOperation> findByOperationType(OperationType operationType, Pageable pageable);
|
||||
|
||||
@Query("SELECT t FROM TokenOperation t WHERE " +
|
||||
"(:userId IS NULL OR t.userId = :userId) AND " +
|
||||
"(:operationType IS NULL OR t.operationType = :operationType) AND " +
|
||||
"(:minSpent IS NULL OR t.spent >= :minSpent) AND " +
|
||||
"(:maxSpent IS NULL OR t.spent <= :maxSpent)")
|
||||
Page<TokenOperation> findByFilters(
|
||||
@Param("userId") Long userId,
|
||||
@Param("operationType") OperationType operationType,
|
||||
@Param("minSpent") Long minSpent,
|
||||
@Param("maxSpent") Long maxSpent,
|
||||
Pageable pageable
|
||||
);
|
||||
|
||||
@Query("SELECT SUM(t.spent) FROM TokenOperation t WHERE t.userId = :userId AND t.operationType = :operationType")
|
||||
Long sumSpentByUserAndType(@Param("userId") Long userId, @Param("operationType") OperationType operationType);
|
||||
|
||||
Long countByUserId(Long userId);
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import ru.soune.nocopy.dto.file.UploadProgressResponse;
|
||||
import ru.soune.nocopy.entity.file.*;
|
||||
import ru.soune.nocopy.entity.notification.NotificationType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.exception.*;
|
||||
import ru.soune.nocopy.repository.FileEntityRepository;
|
||||
import ru.soune.nocopy.repository.FileUploadSessionRepository;
|
||||
@@ -441,7 +442,7 @@ public class FileUploadServiceImpl implements FileUploadService {
|
||||
if (status != FileStatus.TEMP) {
|
||||
String fileType = session.getFileType();
|
||||
|
||||
tariffInfoService.writeOffTokens(session.getUserId(), costService.protectFileCost(fileType));
|
||||
tariffInfoService.writeOffTokens(session.getUserId(), costService.protectFileCost(fileType), OperationType.FILE_UPLOAD);
|
||||
}
|
||||
} else {
|
||||
sessionRepository.save(session);
|
||||
|
||||
@@ -15,6 +15,7 @@ import ru.soune.nocopy.entity.notification.NotificationMessage;
|
||||
import ru.soune.nocopy.entity.notification.NotificationType;
|
||||
import ru.soune.nocopy.entity.tarif.TariffInfo;
|
||||
import ru.soune.nocopy.entity.tarif.TariffType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.TariffNotFoundException;
|
||||
import ru.soune.nocopy.repository.FileMonitoringRepository;
|
||||
@@ -66,7 +67,7 @@ public class MonitoringSearchService {
|
||||
TariffDTO tariffMonitoring = tariffService.getTariffByType(TariffType.valueOf(monitoringType.name()));
|
||||
|
||||
try {
|
||||
tariffInfoService.writeOffTokens(monitoring.getUserId(), tariffMonitoring.getTokens());
|
||||
tariffInfoService.writeOffTokens(monitoring.getUserId(), tariffMonitoring.getTokens(), OperationType.MONITORING);
|
||||
|
||||
boolean useYandex = searchProperties.getEngines().getOrDefault("yandex",
|
||||
new SearchProperties.EngineConfig()).isEnabled();
|
||||
|
||||
@@ -12,6 +12,7 @@ import ru.soune.nocopy.entity.notification.NotificationType;
|
||||
import ru.soune.nocopy.entity.search.GlobalSearchResult;
|
||||
import ru.soune.nocopy.entity.search.GlobalSearchTask;
|
||||
import ru.soune.nocopy.entity.search.SearchStatus;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.repository.FileEntityRepository;
|
||||
import ru.soune.nocopy.repository.GlobalSearchResultRepository;
|
||||
import ru.soune.nocopy.repository.GlobalSearchTaskRepository;
|
||||
@@ -59,7 +60,7 @@ public class GlobalSearchAsyncProcessor {
|
||||
FileEntity file = fileEntityRepository.findById(uuid)
|
||||
.orElseThrow(() -> new RuntimeException("File not found: " + uuid));
|
||||
|
||||
tariffInfoService.writeOffTokens(userId, TariffConstants.TOKEN_VALUE_FOR_SEARCH);
|
||||
tariffInfoService.writeOffTokens(userId, TariffConstants.TOKEN_VALUE_FOR_SEARCH, OperationType.GLOBAL_SEARCH);
|
||||
GlobalSearchResult result = processFile(file, taskId, userId);
|
||||
globalSearchResultRepository.save(result);
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@ import ru.soune.nocopy.entity.tarif.Tariff;
|
||||
import ru.soune.nocopy.entity.tarif.TariffInfo;
|
||||
import ru.soune.nocopy.entity.tarif.TariffStatus;
|
||||
import ru.soune.nocopy.entity.tarif.TariffType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.TariffNotFoundException;
|
||||
import ru.soune.nocopy.repository.TariffInfoRepository;
|
||||
import ru.soune.nocopy.repository.TariffRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
import ru.soune.nocopy.service.mail.EmailService;
|
||||
import ru.soune.nocopy.service.tokenoperation.TokenOperationService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -35,6 +37,8 @@ public class TariffInfoService {
|
||||
|
||||
private EmailService emailService;
|
||||
|
||||
private TokenOperationService tokenOperationService;
|
||||
|
||||
public TariffInfo createTariffInfo(LocalDateTime startTariff, LocalDateTime endTariff, TariffStatus tariffStatus,
|
||||
Integer tokens) {
|
||||
TariffInfo tariffInfo = new TariffInfo();
|
||||
@@ -48,7 +52,7 @@ public class TariffInfoService {
|
||||
}
|
||||
|
||||
// @Transactional
|
||||
public void writeOffTokens(long userId, Integer value) throws MessagingException, IOException {
|
||||
public void writeOffTokens(long userId, Integer value, OperationType operationType) throws MessagingException, IOException {
|
||||
User user = userRepository.findById(userId).orElseThrow();
|
||||
|
||||
TariffInfo activeTariffInfo;
|
||||
@@ -60,6 +64,8 @@ public class TariffInfoService {
|
||||
}
|
||||
|
||||
writeOffTokensForTariff(activeTariffInfo, value);
|
||||
|
||||
tokenOperationService.create(operationType, userId, Long.valueOf(value));
|
||||
}
|
||||
|
||||
public void writeOffTokensForTariff(TariffInfo activeTariffInfo, Integer value) throws MessagingException, IOException {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package ru.soune.nocopy.service.tokenoperation;
|
||||
|
||||
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.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.entity.tokenoperation.OperationType;
|
||||
import ru.soune.nocopy.entity.tokenoperation.TokenOperation;
|
||||
import ru.soune.nocopy.repository.TokenOperationRepository;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class TokenOperationService {
|
||||
|
||||
private final TokenOperationRepository repository;
|
||||
|
||||
@Transactional
|
||||
public TokenOperation create(OperationType operationType, Long userId, Long spent) {
|
||||
TokenOperation tokenOperation = new TokenOperation();
|
||||
|
||||
tokenOperation.setOperationType(operationType);
|
||||
tokenOperation.setUserId(userId);
|
||||
tokenOperation.setSpent(spent);
|
||||
tokenOperation.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
return repository.save(tokenOperation);
|
||||
}
|
||||
|
||||
public TokenOperation findById(Long id) {
|
||||
log.debug("Finding token operation by id: {}", id);
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("TokenOperation not found with id: " + id));
|
||||
}
|
||||
|
||||
public Page<TokenOperation> findAll(int page, int size, String sortBy, String direction) {
|
||||
log.debug("Finding all operations with pagination: page={}, size={}, sortBy={}, dir={}",
|
||||
page, size, sortBy, direction);
|
||||
|
||||
Sort sort = direction.equalsIgnoreCase("desc")
|
||||
? Sort.by(sortBy).descending()
|
||||
: Sort.by(sortBy).ascending();
|
||||
|
||||
Pageable pageable = PageRequest.of(page, size, sort);
|
||||
return repository.findAll(pageable);
|
||||
}
|
||||
|
||||
public Page<TokenOperation> findByFilters(
|
||||
Long userId,
|
||||
OperationType operationType,
|
||||
Long minSpent,
|
||||
Long maxSpent,
|
||||
int page,
|
||||
int size,
|
||||
String sortBy,
|
||||
String direction) {
|
||||
|
||||
log.debug("Finding by filters: userId={}, type={}, minSpent={}, maxSpent={}",
|
||||
userId, operationType, minSpent, maxSpent);
|
||||
|
||||
Sort sort = Sort.by(Sort.Direction.fromString(direction), sortBy);
|
||||
Pageable pageable = PageRequest.of(page, size, sort);
|
||||
|
||||
return repository.findByFilters(userId, operationType, minSpent, maxSpent, pageable);
|
||||
}
|
||||
|
||||
public Page<TokenOperation> findByUserId(Long userId, int page, int size) {
|
||||
log.debug("Finding operations for user id: {}", userId);
|
||||
Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending());
|
||||
return repository.findByUserId(userId, pageable);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TokenOperation update(Long id, TokenOperation updatedOperation) {
|
||||
log.info("Updating token operation with id: {}", id);
|
||||
|
||||
TokenOperation existing = findById(id);
|
||||
|
||||
existing.setOperationType(updatedOperation.getOperationType());
|
||||
existing.setUserId(updatedOperation.getUserId());
|
||||
existing.setSpent(updatedOperation.getSpent());
|
||||
|
||||
return repository.save(existing);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteById(Long id) {
|
||||
log.info("Deleting token operation with id: {}", id);
|
||||
|
||||
if (!repository.existsById(id)) {
|
||||
throw new EntityNotFoundException("TokenOperation not found with id: " + id);
|
||||
}
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteByUserId(Long userId) {
|
||||
log.warn("Deleting all operations for user id: {}", userId);
|
||||
List<TokenOperation> userOps = repository.findByUserId(userId);
|
||||
repository.deleteAll(userOps);
|
||||
}
|
||||
|
||||
public Long getTotalSpentByUserAndType(Long userId, OperationType type) {
|
||||
Long sum = repository.sumSpentByUserAndType(userId, type);
|
||||
return sum != null ? sum : 0L;
|
||||
}
|
||||
|
||||
public Long countByUserId(Long userId) {
|
||||
return repository.countByUserId(userId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user