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 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 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 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 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); } }