feat: PHASE 5 COMPLÈTE - Gestion Documentaire
Service créé: - DocumentService: CRUD documents, enregistrement téléchargements, gestion pièces jointes - Validation qu'une seule relation est renseignée pour pièce jointe - Conversions DTO ↔ Entity complètes PHASE 5 - COMPLÉTÉE (100%): ✅ Entités: Document, PieceJointe ✅ Enum: TypeDocument (module API) ✅ Repositories: DocumentRepository, PieceJointeRepository ✅ DTOs: DocumentDTO, PieceJointeDTO ✅ Service: DocumentService avec validation ✅ Relations flexibles: Membre, Organisation, Cotisation, Adhesion, DemandeAide, TransactionWave Fonctionnalités: - Vérification intégrité avec MD5/SHA256 - Formatage taille fichiers - Compteur téléchargements - Validation relations pièces jointes Respect strict DRY/WOU: - Patterns cohérents avec autres modules - Gestion d'erreurs standardisée
This commit is contained in:
@@ -0,0 +1,311 @@
|
|||||||
|
package dev.lions.unionflow.server.service;
|
||||||
|
|
||||||
|
import dev.lions.unionflow.server.api.dto.document.DocumentDTO;
|
||||||
|
import dev.lions.unionflow.server.api.dto.document.PieceJointeDTO;
|
||||||
|
import dev.lions.unionflow.server.entity.*;
|
||||||
|
import dev.lions.unionflow.server.repository.*;
|
||||||
|
import dev.lions.unionflow.server.service.KeycloakService;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import jakarta.ws.rs.NotFoundException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service métier pour la gestion documentaire
|
||||||
|
*
|
||||||
|
* @author UnionFlow Team
|
||||||
|
* @version 3.0
|
||||||
|
* @since 2025-01-29
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DocumentService {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(DocumentService.class);
|
||||||
|
|
||||||
|
@Inject DocumentRepository documentRepository;
|
||||||
|
|
||||||
|
@Inject PieceJointeRepository pieceJointeRepository;
|
||||||
|
|
||||||
|
@Inject MembreRepository membreRepository;
|
||||||
|
|
||||||
|
@Inject OrganisationRepository organisationRepository;
|
||||||
|
|
||||||
|
@Inject CotisationRepository cotisationRepository;
|
||||||
|
|
||||||
|
@Inject AdhesionRepository adhesionRepository;
|
||||||
|
|
||||||
|
@Inject DemandeAideRepository demandeAideRepository;
|
||||||
|
|
||||||
|
@Inject TransactionWaveRepository transactionWaveRepository;
|
||||||
|
|
||||||
|
@Inject KeycloakService keycloakService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un nouveau document
|
||||||
|
*
|
||||||
|
* @param documentDTO DTO du document à créer
|
||||||
|
* @return DTO du document créé
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public DocumentDTO creerDocument(DocumentDTO documentDTO) {
|
||||||
|
LOG.infof("Création d'un nouveau document: %s", documentDTO.getNomFichier());
|
||||||
|
|
||||||
|
Document document = convertToEntity(documentDTO);
|
||||||
|
document.setCreePar(keycloakService.getCurrentUserEmail());
|
||||||
|
|
||||||
|
documentRepository.persist(document);
|
||||||
|
LOG.infof("Document créé avec succès: ID=%s, Fichier=%s", document.getId(), document.getNomFichier());
|
||||||
|
|
||||||
|
return convertToDTO(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trouve un document par son ID
|
||||||
|
*
|
||||||
|
* @param id ID du document
|
||||||
|
* @return DTO du document
|
||||||
|
*/
|
||||||
|
public DocumentDTO trouverParId(UUID id) {
|
||||||
|
return documentRepository
|
||||||
|
.findByIdOptional(id)
|
||||||
|
.map(this::convertToDTO)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Document non trouvé avec l'ID: " + id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enregistre un téléchargement de document
|
||||||
|
*
|
||||||
|
* @param id ID du document
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void enregistrerTelechargement(UUID id) {
|
||||||
|
Document document =
|
||||||
|
documentRepository
|
||||||
|
.findByIdOptional(id)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Document non trouvé avec l'ID: " + id));
|
||||||
|
|
||||||
|
document.setNombreTelechargements(
|
||||||
|
(document.getNombreTelechargements() != null ? document.getNombreTelechargements() : 0) + 1);
|
||||||
|
document.setDateDernierTelechargement(LocalDateTime.now());
|
||||||
|
document.setModifiePar(keycloakService.getCurrentUserEmail());
|
||||||
|
|
||||||
|
documentRepository.persist(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une pièce jointe
|
||||||
|
*
|
||||||
|
* @param pieceJointeDTO DTO de la pièce jointe à créer
|
||||||
|
* @return DTO de la pièce jointe créée
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public PieceJointeDTO creerPieceJointe(PieceJointeDTO pieceJointeDTO) {
|
||||||
|
LOG.infof("Création d'une nouvelle pièce jointe");
|
||||||
|
|
||||||
|
PieceJointe pieceJointe = convertToEntity(pieceJointeDTO);
|
||||||
|
|
||||||
|
// Vérifier qu'une seule relation est renseignée
|
||||||
|
if (!pieceJointe.isValide()) {
|
||||||
|
throw new IllegalArgumentException("Une seule relation doit être renseignée pour une pièce jointe");
|
||||||
|
}
|
||||||
|
|
||||||
|
pieceJointe.setCreePar(keycloakService.getCurrentUserEmail());
|
||||||
|
pieceJointeRepository.persist(pieceJointe);
|
||||||
|
|
||||||
|
LOG.infof("Pièce jointe créée avec succès: ID=%s", pieceJointe.getId());
|
||||||
|
return convertToDTO(pieceJointe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liste toutes les pièces jointes d'un document
|
||||||
|
*
|
||||||
|
* @param documentId ID du document
|
||||||
|
* @return Liste des pièces jointes
|
||||||
|
*/
|
||||||
|
public List<PieceJointeDTO> listerPiecesJointesParDocument(UUID documentId) {
|
||||||
|
return pieceJointeRepository.findByDocumentId(documentId).stream()
|
||||||
|
.map(this::convertToDTO)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// MÉTHODES PRIVÉES
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
/** Convertit une entité Document en DTO */
|
||||||
|
private DocumentDTO convertToDTO(Document document) {
|
||||||
|
if (document == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentDTO dto = new DocumentDTO();
|
||||||
|
dto.setId(document.getId());
|
||||||
|
dto.setNomFichier(document.getNomFichier());
|
||||||
|
dto.setNomOriginal(document.getNomOriginal());
|
||||||
|
dto.setCheminStockage(document.getCheminStockage());
|
||||||
|
dto.setTypeMime(document.getTypeMime());
|
||||||
|
dto.setTailleOctets(document.getTailleOctets());
|
||||||
|
dto.setTypeDocument(document.getTypeDocument());
|
||||||
|
dto.setHashMd5(document.getHashMd5());
|
||||||
|
dto.setHashSha256(document.getHashSha256());
|
||||||
|
dto.setDescription(document.getDescription());
|
||||||
|
dto.setNombreTelechargements(document.getNombreTelechargements());
|
||||||
|
dto.setTailleFormatee(document.getTailleFormatee());
|
||||||
|
dto.setDateCreation(document.getDateCreation());
|
||||||
|
dto.setDateModification(document.getDateModification());
|
||||||
|
dto.setActif(document.getActif());
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convertit un DTO en entité Document */
|
||||||
|
private Document convertToEntity(DocumentDTO dto) {
|
||||||
|
if (dto == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Document document = new Document();
|
||||||
|
document.setNomFichier(dto.getNomFichier());
|
||||||
|
document.setNomOriginal(dto.getNomOriginal());
|
||||||
|
document.setCheminStockage(dto.getCheminStockage());
|
||||||
|
document.setTypeMime(dto.getTypeMime());
|
||||||
|
document.setTailleOctets(dto.getTailleOctets());
|
||||||
|
document.setTypeDocument(dto.getTypeDocument() != null ? dto.getTypeDocument() : dev.lions.unionflow.server.api.enums.document.TypeDocument.AUTRE);
|
||||||
|
document.setHashMd5(dto.getHashMd5());
|
||||||
|
document.setHashSha256(dto.getHashSha256());
|
||||||
|
document.setDescription(dto.getDescription());
|
||||||
|
document.setNombreTelechargements(dto.getNombreTelechargements() != null ? dto.getNombreTelechargements() : 0);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convertit une entité PieceJointe en DTO */
|
||||||
|
private PieceJointeDTO convertToDTO(PieceJointe pieceJointe) {
|
||||||
|
if (pieceJointe == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PieceJointeDTO dto = new PieceJointeDTO();
|
||||||
|
dto.setId(pieceJointe.getId());
|
||||||
|
dto.setOrdre(pieceJointe.getOrdre());
|
||||||
|
dto.setLibelle(pieceJointe.getLibelle());
|
||||||
|
dto.setCommentaire(pieceJointe.getCommentaire());
|
||||||
|
|
||||||
|
if (pieceJointe.getDocument() != null) {
|
||||||
|
dto.setDocumentId(pieceJointe.getDocument().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getMembre() != null) {
|
||||||
|
dto.setMembreId(pieceJointe.getMembre().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getOrganisation() != null) {
|
||||||
|
dto.setOrganisationId(pieceJointe.getOrganisation().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getCotisation() != null) {
|
||||||
|
dto.setCotisationId(pieceJointe.getCotisation().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getAdhesion() != null) {
|
||||||
|
dto.setAdhesionId(pieceJointe.getAdhesion().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getDemandeAide() != null) {
|
||||||
|
dto.setDemandeAideId(pieceJointe.getDemandeAide().getId());
|
||||||
|
}
|
||||||
|
if (pieceJointe.getTransactionWave() != null) {
|
||||||
|
dto.setTransactionWaveId(pieceJointe.getTransactionWave().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.setDateCreation(pieceJointe.getDateCreation());
|
||||||
|
dto.setDateModification(pieceJointe.getDateModification());
|
||||||
|
dto.setActif(pieceJointe.getActif());
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convertit un DTO en entité PieceJointe */
|
||||||
|
private PieceJointe convertToEntity(PieceJointeDTO dto) {
|
||||||
|
if (dto == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PieceJointe pieceJointe = new PieceJointe();
|
||||||
|
pieceJointe.setOrdre(dto.getOrdre() != null ? dto.getOrdre() : 1);
|
||||||
|
pieceJointe.setLibelle(dto.getLibelle());
|
||||||
|
pieceJointe.setCommentaire(dto.getCommentaire());
|
||||||
|
|
||||||
|
// Relation Document
|
||||||
|
if (dto.getDocumentId() != null) {
|
||||||
|
Document document =
|
||||||
|
documentRepository
|
||||||
|
.findByIdOptional(dto.getDocumentId())
|
||||||
|
.orElseThrow(() -> new NotFoundException("Document non trouvé avec l'ID: " + dto.getDocumentId()));
|
||||||
|
pieceJointe.setDocument(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relations flexibles (une seule doit être renseignée)
|
||||||
|
if (dto.getMembreId() != null) {
|
||||||
|
Membre membre =
|
||||||
|
membreRepository
|
||||||
|
.findByIdOptional(dto.getMembreId())
|
||||||
|
.orElseThrow(() -> new NotFoundException("Membre non trouvé avec l'ID: " + dto.getMembreId()));
|
||||||
|
pieceJointe.setMembre(membre);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.getOrganisationId() != null) {
|
||||||
|
Organisation org =
|
||||||
|
organisationRepository
|
||||||
|
.findByIdOptional(dto.getOrganisationId())
|
||||||
|
.orElseThrow(
|
||||||
|
() ->
|
||||||
|
new NotFoundException(
|
||||||
|
"Organisation non trouvée avec l'ID: " + dto.getOrganisationId()));
|
||||||
|
pieceJointe.setOrganisation(org);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.getCotisationId() != null) {
|
||||||
|
Cotisation cotisation =
|
||||||
|
cotisationRepository
|
||||||
|
.findByIdOptional(dto.getCotisationId())
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new NotFoundException("Cotisation non trouvée avec l'ID: " + dto.getCotisationId()));
|
||||||
|
pieceJointe.setCotisation(cotisation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.getAdhesionId() != null) {
|
||||||
|
Adhesion adhesion =
|
||||||
|
adhesionRepository
|
||||||
|
.findByIdOptional(dto.getAdhesionId())
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new NotFoundException("Adhésion non trouvée avec l'ID: " + dto.getAdhesionId()));
|
||||||
|
pieceJointe.setAdhesion(adhesion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.getDemandeAideId() != null) {
|
||||||
|
DemandeAide demandeAide =
|
||||||
|
demandeAideRepository
|
||||||
|
.findByIdOptional(dto.getDemandeAideId())
|
||||||
|
.orElseThrow(
|
||||||
|
() ->
|
||||||
|
new NotFoundException(
|
||||||
|
"Demande d'aide non trouvée avec l'ID: " + dto.getDemandeAideId()));
|
||||||
|
pieceJointe.setDemandeAide(demandeAide);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.getTransactionWaveId() != null) {
|
||||||
|
TransactionWave transactionWave =
|
||||||
|
transactionWaveRepository
|
||||||
|
.findByIdOptional(dto.getTransactionWaveId())
|
||||||
|
.orElseThrow(
|
||||||
|
() ->
|
||||||
|
new NotFoundException(
|
||||||
|
"Transaction Wave non trouvée avec l'ID: " + dto.getTransactionWaveId()));
|
||||||
|
pieceJointe.setTransactionWave(transactionWave);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pieceJointe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user