UploadDocumentService.java

package com.tdmconsult.ete.documents;

import static com.tdmconsult.ete.documents.DocumentAuthorizationService.AUTH_FINANCIAL_DOCUMENT_SHOW_OWN;

import com.tdmconsult.ete.configuration.CustomJwtAuthenticationToken;
import com.tdmconsult.ete.exceptions.DocumentNotFound;
import com.tdmconsult.ete.services.mattermost.MattermostService;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
@Transactional
public class UploadDocumentService {

    private final FinancialDocumentRepository financialDocumentRepository;
    private final MattermostService mattermostService;

    public String createUploadDocument(
            final DocumentCreationRequestDto requestDto,
            final CustomJwtAuthenticationToken.CustomUserPrincipal userPrincipal) throws IOException {

        final var entity = new FinancialDocument();
        entity.setPublicId(UUID.randomUUID().toString());
        entity.setDateReceived(requestDto.dateReceived());
        entity.setTypeOfDocument(requestDto.typeOfDocument());
        entity.setUploadBy(userPrincipal.username());
        entity.setState(FinancialDocument.State.UPLOADED);

        for (final var d : requestDto.documentUploadFiles()) {
            Attachment.of(entity)
                    .setUploadBy(userPrincipal.username())
                    .setFileContentType(d.getContentType())
                    .setFileSize(d.getSize())
                    .setFileName(d.getOriginalFilename())
                    .setFileData(d.getBytes());
        }

        financialDocumentRepository.saveAndFlush(entity);

        mattermostService.informAboutNewDocument(
                entity.getPublicId(),
                entity.getUploadBy(),
                entity.getTypeOfDocument(),
                entity.getDateReceived());

        return entity.getPublicId();
    }

    public List<DocumentIndexDto> getUploadDocumentIndex(
            final CustomJwtAuthenticationToken.CustomUserPrincipal userDetails) {

        final var showOwnOnly = userDetails.hasAuthority(AUTH_FINANCIAL_DOCUMENT_SHOW_OWN);
        return financialDocumentRepository.findAllUploadSummaries().stream()
                .filter(d -> !showOwnOnly || d.getUploadBy().equals(userDetails.username()))
                .map(d -> new DocumentIndexDto(
                        d.getPublicId(),
                        d.getTypeOfDocument(),
                        d.getDateReceived(),
                        d.getCreatedAt(),
                        d.getUploadBy(),
                        d.getState(),
                        d.getNumberOfAttachments()))
                .toList();
    }

    public DocumentDto getUploadDocument(
            final String publicId,
            final Boolean excludeContent) {

        final var document = financialDocumentRepository.findByPublicIdOrThrow(publicId);
        return new DocumentDto(
                publicId,
                document.getTypeOfDocument(),
                document.getDateReceived(),
                document.getCreatedAt(),
                document.getUploadBy(),
                document.getState(),
                document.getAttachments().stream()
                        .map(a -> new DocumentAttachmentDto(
                                a.getPublicId(),
                                a.getFileName(),
                                a.getFileSize(),
                                a.getFileContentType(),
                                a.getUploadBy(),
                                Boolean.TRUE.equals(excludeContent) ? null : a.getFileData()
                        )).toList());
    }

    public DocumentAttachmentDto getAttachment(
            final String publicId,
            final String attachmentPublicId) {

        final var document = financialDocumentRepository.findByPublicIdOrThrow(publicId);
        final var a = document.getAttachments().stream()
                .filter(d -> d.getPublicId().equals(attachmentPublicId))
                .findFirst().orElseThrow();

        return new DocumentAttachmentDto(
                a.getPublicId(),
                a.getFileName(),
                a.getFileSize(),
                a.getFileContentType(),
                a.getUploadBy(),
                a.getFileData());
    }

    public void updateUploadDocument(
            final String publicId,
            final DocumentUpdateRequestDto requestDto,
            final Map<String, MultipartFile> attachmentsByPublicId,
            final CustomJwtAuthenticationToken.CustomUserPrincipal userDetails) throws IOException {

        final var document = financialDocumentRepository.findByPublicIdOrThrow(publicId);
        document.setTypeOfDocument(requestDto.typeOfDocument());
        document.setDateReceived(requestDto.dateReceived());

        for (final DocumentUpdateRequestDto.AttachmentAction action : requestDto.actions()) {
            switch (action.action()) {
                case CREATE -> {
                    final var attachment = Objects.requireNonNull(attachmentsByPublicId.get(action.publicId()));
                    Attachment.of(document)
                            .setUploadBy(userDetails.username())
                            .setFileContentType(attachment.getContentType())
                            .setFileSize(attachment.getSize())
                            .setFileName(attachment.getOriginalFilename())
                            .setFileData(attachment.getBytes());
                }
                case UPDATE -> {
                    final var attachment = Objects.requireNonNull(attachmentsByPublicId.get(action.publicId()));
                    final var entity = document.getAttachments().stream()
                            .filter(d -> d.getPublicId().equals(action.publicId()))
                            .findFirst()
                            .orElseThrow(() -> new DocumentNotFound("xxx"));
                    entity.setUploadBy(userDetails.username());
                    entity.setFileContentType(attachment.getContentType());
                    entity.setFileSize(attachment.getSize());
                    entity.setFileName(attachment.getOriginalFilename());
                    entity.setFileData(attachment.getBytes());
                }
                case DELETE -> {
                    document.getAttachments().removeIf(d -> d.getPublicId().equals(action.publicId()));
                }
                default -> {}
            }
        }
    }

    public void deleteUploadDocument(final String publicId) {
        financialDocumentRepository.delete(financialDocumentRepository.findByPublicIdOrThrow(publicId));
    }
}