dev add reason entity
Test Workflow / test (push) Successful in 2s

This commit is contained in:
vladp
2026-03-27 17:54:04 +07:00
parent 9a8a4a72f4
commit 067b967a17
16 changed files with 1 additions and 552 deletions
@@ -1,184 +0,0 @@
package ru.soune.nocopy.service.file.moderation;
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.dto.file.ModerationReasonResponse;
import ru.soune.nocopy.entity.file.FileStatus;
import ru.soune.nocopy.entity.file.moderation.ModerationReason;
import ru.soune.nocopy.exception.ModerationReasonInUseException;
import ru.soune.nocopy.exception.ModerationReasonNotFoundException;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.repository.ModerationReasonRepository;
import java.util.Arrays;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class ModerationReasonService {
private final ModerationReasonRepository moderationReasonRepository;
private final FileEntityRepository fileEntityRepository;
private static final List<FileStatus> BLOCKED_STATUSES = Arrays.asList(
FileStatus.BLOCKED,
FileStatus.VIOLATION,
FileStatus.MODERATION
);
/**
* Создание новой причины модерации
*/
@Transactional
public ModerationReasonResponse createReason(String reasonText) {
if (reasonText == null || reasonText.trim().isEmpty()) {
throw new IllegalArgumentException("Reason text cannot be empty");
}
if (moderationReasonRepository.findByReasonText(reasonText.trim()).isPresent()) {
throw new IllegalArgumentException("Reason with this text already exists");
}
ModerationReason reason = ModerationReason.builder()
.reasonText(reasonText.trim())
.build();
ModerationReason saved = moderationReasonRepository.save(reason);
log.info("Created new moderation reason: id={}, text={}", saved.getId(), saved.getReasonText());
return convertToResponse(saved, false, 0L);
}
/**
* Обновление причины модерации
*/
@Transactional
public ModerationReasonResponse updateReason(Long reasonId, String newReasonText) {
ModerationReason reason = moderationReasonRepository.findById(reasonId)
.orElseThrow(() -> new ModerationReasonNotFoundException(reasonId));
if (newReasonText == null || newReasonText.trim().isEmpty()) {
throw new IllegalArgumentException("Reason text cannot be empty");
}
moderationReasonRepository.findByReasonText(newReasonText.trim())
.ifPresent(existingReason -> {
if (!existingReason.getId().equals(reasonId)) {
throw new IllegalArgumentException("Reason with this text already exists");
}
});
String oldText = reason.getReasonText();
reason.setReasonText(newReasonText.trim());
ModerationReason updated = moderationReasonRepository.save(reason);
log.info("Updated moderation reason: id={}, oldText={}, newText={}",
reasonId, oldText, newReasonText);
long usageCount = getReasonUsageCount(reasonId);
return convertToResponse(updated, usageCount > 0, usageCount);
}
/**
* Удаление причины модерации
*/
@Transactional
public void deleteReason(Long reasonId) {
ModerationReason reason = moderationReasonRepository.findById(reasonId)
.orElseThrow(() -> new ModerationReasonNotFoundException(reasonId));
long usageCount = getReasonUsageCount(reasonId);
if (usageCount > 0) {
throw new ModerationReasonInUseException(reasonId, usageCount);
}
moderationReasonRepository.deleteById(reasonId);
log.info("Deleted moderation reason: id={}, text={}", reasonId, reason.getReasonText());
}
/**
* Получение причины по ID
*/
@Transactional(readOnly = true)
public ModerationReasonResponse getReasonById(Long reasonId) {
ModerationReason reason = moderationReasonRepository.findById(reasonId)
.orElseThrow(() -> new ModerationReasonNotFoundException(reasonId));
long usageCount = getReasonUsageCount(reasonId);
return convertToResponse(reason, usageCount > 0, usageCount);
}
/**
* Получение всех причин с пагинацией
*/
@Transactional(readOnly = true)
public Page<ModerationReasonResponse> getAllReasons(int page, int size, String searchQuery) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
Page<ModerationReason> reasonsPage;
if (searchQuery != null && !searchQuery.trim().isEmpty()) {
reasonsPage = moderationReasonRepository.searchByText(searchQuery.trim(), pageable);
} else {
reasonsPage = moderationReasonRepository.findAll(pageable);
}
return reasonsPage.map(reason -> {
long usageCount = getReasonUsageCount(reason.getId());
return convertToResponse(reason, usageCount > 0, usageCount);
});
}
/**
* Получение списка всех причин (без пагинации, для выпадающих списков)
*/
@Transactional(readOnly = true)
public List<ModerationReasonResponse> getAllReasonsList() {
List<ModerationReason> reasons = moderationReasonRepository.findAll(Sort.by("reasonText").ascending());
return reasons.stream()
.map(reason -> {
long usageCount = getReasonUsageCount(reason.getId());
return convertToResponse(reason, usageCount > 0, usageCount);
})
.collect(java.util.stream.Collectors.toList());
}
/**
* Подсчет количества файлов, заблокированных по данной причине
*/
private long getReasonUsageCount(Long reasonId) {
return fileEntityRepository.countByModerationReasonIdAndStatusIn(reasonId, BLOCKED_STATUSES);
}
/**
* Проверка, используется ли причина в активных блокировках
*/
public boolean isReasonInUse(Long reasonId) {
return getReasonUsageCount(reasonId) > 0;
}
private ModerationReasonResponse convertToResponse(ModerationReason reason, boolean isUsed, long usageCount) {
return ModerationReasonResponse.builder()
.id(reason.getId())
.reasonText(reason.getReasonText())
.createdAt(reason.getCreatedAt())
.updatedAt(reason.getUpdatedAt())
.isUsed(isUsed)
.usageCount(usageCount)
.build();
}
}
@@ -57,14 +57,13 @@ public class ModerationService {
.oldStatus(file.getStatus())
.newStatus(request.getNewStatus())
.reason(request.getComment())
.moderationReasonId(request.getModerationReasonId())
.comment(request.getComment())
.build();
moderationLogRepository.save(log);
file.setStatus(request.getNewStatus());
file.setModerationReasonId(request.getModerationReasonId());
fileEntityRepository.save(file);
if (request.getNewStatus() == FileStatus.BLOCKED ||
@@ -107,7 +106,6 @@ public class ModerationService {
.additionalInfo(request.getAdditionalInfo())
.status(AppealStatus.PENDING)
.moderationBeforeStatus(file.getStatus())
.moderationReasonId(file.getModerationReasonId())
.build();
FileAppeal saved = fileAppealRepository.save(appeal);
@@ -137,7 +135,6 @@ public class ModerationService {
if (approve) {
file.setStatus(FileStatus.ACTIVE);
file.setModerationReasonId(null);
}
ModerationLog log = ModerationLog.builder()