Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public class FaqAttachmentService implements AttachmentService<FaqJpaEntity, Fil
private final S3Properties s3Properties;


/**
* Saves multiple file attachments associated with the specified FAQ entity.
*
* Each file request is processed and stored as an attachment linked to the given FAQ entity.
*
* @param requests the list of file requests to be attached
* @param faqEntity the FAQ entity to associate the attachments with
*/
@Override
public void createAttachment(List<FileRequest> requests, FaqJpaEntity faqEntity) {
fileUploadHelper.saveAttachments(
Expand All @@ -41,6 +49,11 @@ public void createAttachment(List<FileRequest> requests, FaqJpaEntity faqEntity)
);
}

/**
* Deletes all attachments associated with the specified FAQ entity.
*
* @param entity the FAQ entity whose attachments will be deleted
*/
@Override
public void deleteAttachment(FaqJpaEntity entity) {
List<FaqAttachmentJpaEntity> attachments = faqAttachmentRepository.findAllByFaqId(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public class InquiryAnswerAttachmentService implements
private final FileUploadHelper fileUploadHelper;
private final S3Service s3Service;

/**
* Saves a list of file attachments associated with the specified inquiry answer entity.
*
* Each file request is converted into an attachment entity and persisted, linking it to the given inquiry answer.
*
* @param requests the list of file requests to be attached
* @param answerEntity the inquiry answer entity to associate the attachments with
*/
@Override
public void createAttachment(List<FileRequest> requests, InquiryAnswerJpaEntity answerEntity) {
fileUploadHelper.saveAttachments(
Expand Down Expand Up @@ -73,6 +81,12 @@ private InquiryDetailResponse.AttachmentResponse createAttachResponse(
);
}

/**
* Creates an attachment detail response containing the file name, a presigned S3 URL, and the S3 key for the given attachment entity.
*
* @param attachment the attachment entity to convert
* @return an AttachmentDetailResponse with file name, presigned URL, and S3 key
*/
private InquiryDetailResponse.AttachmentDetailResponse createAttachDetailResponse(
InquiryAnswerAttachmentEntity attachment) {
String presignedUrl = s3Service.getPreSignedUrl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public class InquiryAttachmentService implements AttachmentService<InquiryJpaEnt
private final S3Service s3Service;
private final S3Properties s3Properties;

/**
* Saves a list of file attachments associated with the specified inquiry entity.
*
* Each file request is converted into an attachment entity and persisted using the repository.
*
* @param requests the list of file requests to attach to the inquiry
* @param inquiryEntity the inquiry entity to associate the attachments with
*/
@Override
public void createAttachment(List<FileRequest> requests, InquiryJpaEntity inquiryEntity) {
fileUploadHelper.saveAttachments(
Expand All @@ -38,6 +46,11 @@ public void createAttachment(List<FileRequest> requests, InquiryJpaEntity inquir
);
}

/**
* Deletes all attachments associated with the specified inquiry entity.
*
* @param entity the inquiry entity whose attachments should be deleted
*/
@Override
public void deleteAttachment(InquiryJpaEntity entity) {
List<InquiryAttachmentJpaEntity> attachments = inquiryAttachmentRepository.findAllByInquiryId(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public class NoticeAttachmentService implements AttachmentService<NoticeJpaEntit
private final S3Service s3Service;
private final S3Properties s3Properties;

/**
* Saves a list of file attachments associated with the specified notice entity.
*
* Each file request is converted into a notice attachment entity and persisted using the attachment repository.
*
* @param requests the list of file requests to be attached to the notice
* @param noticeEntity the notice entity to which the attachments will be linked
*/
@Override
public void createAttachment(List<FileRequest> requests, NoticeJpaEntity noticeEntity) {
fileUploadHelper.saveAttachments(
Expand All @@ -41,13 +49,25 @@ public void createAttachment(List<FileRequest> requests, NoticeJpaEntity noticeE
);
}

/**
* Deletes all attachments associated with the specified notice entity.
*
* @param entity the notice entity whose attachments will be deleted
*/
@Override
public void deleteAttachment(NoticeJpaEntity entity) {
List<NoticeAttachmentJpaEntity> attachments = noticeAttachmentRepository.findAllByNoticeId(
entity.getId());
noticeAttachmentRepository.deleteAll(attachments);
}

/**
* Converts all attachments of the specified notice entity into a list of response DTOs,
* each containing the file name and a pre-signed URL for secure access.
*
* @param notice the notice entity whose attachments are to be converted
* @return a list of attachment response DTOs with file names and pre-signed URLs
*/
public List<NoticeResponse.AttachmentResponse> toAttachmentResponses(NoticeJpaEntity notice) {

List<NoticeAttachmentJpaEntity> attachments = noticeAttachmentRepository.findAllByNoticeId(
Expand All @@ -64,6 +84,14 @@ public List<NoticeResponse.AttachmentResponse> toAttachmentResponses(NoticeJpaEn
.toList();
}

/**
* Converts all attachments associated with the given notice entity into a list of detailed attachment response DTOs.
*
* Each response includes the file name, a pre-signed URL for accessing the file, and the S3 key.
*
* @param notice the notice entity whose attachments are to be converted
* @return a list of detailed attachment response DTOs for the notice
*/
public List<NoticeDetailResponse.AttachmentDetailResponse> toDetailAttResponses(
NoticeJpaEntity notice) {

Expand All @@ -80,6 +108,12 @@ public List<NoticeDetailResponse.AttachmentDetailResponse> toDetailAttResponses(
.toList();
}

/**
* Generates a pre-signed URL for the specified S3 key with an expiration time defined in the S3 properties.
*
* @param s3Key the S3 object key for which to generate the pre-signed URL
* @return a pre-signed URL granting temporary access to the S3 object
*/
private String fileUrl(String s3Key) {
return s3Service.getPreSignedUrl(
s3Key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,24 @@ public class NoticeService {
private final NoticeRepository noticeRepository;
private final NoticeAttachmentService attachmentService;

/**
* Creates a new notice and its associated attachments.
*
* Persists a notice entity based on the provided request and delegates attachment creation to the attachment service.
*/
@Transactional
public void createNotice(NoticeCreateRequest request) {
NoticeJpaEntity noticeEntity = noticeRepository.save(request.toEntity());
attachmentService.createAttachment(request.attachments(), noticeEntity);
}

/**
* Retrieves a paginated list of notices, each including its associated attachments.
*
* @param page the zero-based page index to retrieve
* @param size the number of notices per page
* @return a list of notice responses with their attachments
*/
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public List<NoticeResponse> getNoticeWithAttachments(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("id"));
Expand All @@ -41,13 +53,27 @@ public List<NoticeResponse> getNoticeWithAttachments(int page, int size) {
.toList();
}

/**
* Retrieves detailed information for a specific notice, including its attachments.
*
* @param noticeId the unique identifier of the notice to retrieve
* @return a detailed response containing notice information and its attachments
* @throws CustomRuntimeException if the notice with the given ID is not found
*/
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public NoticeDetailResponse getNoticeDetail(Long noticeId) {
NoticeJpaEntity notice = getNoticeOrThrow(noticeId);

return toNoticeDetailResponse(notice);
}

/**
* Deletes a notice and its associated attachments by notice ID.
*
* Throws a {@code CustomRuntimeException} with {@code ErrorCode.FILE_NOT_FOUND} if the notice does not exist.
*
* @param noticeId the ID of the notice to delete
*/
@Transactional
public void deleteNotice(Long noticeId) {
NoticeJpaEntity noticeEntity = noticeRepository.findById(noticeId)
Expand All @@ -56,6 +82,15 @@ public void deleteNotice(Long noticeId) {
attachmentService.deleteAttachment(noticeEntity);
}

/**
* Updates the title, content, and attachments of an existing notice.
*
* Replaces the notice's current attachments with the new attachments provided in the request.
*
* @param noticeId the ID of the notice to update
* @param request the update request containing new title, content, and attachments
* @throws CustomRuntimeException if the notice is not found
*/
@Transactional
public void updateNotice(Long noticeId, NoticeUpdateRequest request) {
NoticeJpaEntity noticeEntity = noticeRepository.findById(noticeId)
Expand All @@ -66,18 +101,37 @@ public void updateNotice(Long noticeId, NoticeUpdateRequest request) {
attachmentService.createAttachment(request.attachments(), noticeEntity);
}

/**
* Converts a notice entity to a response DTO, including its attachments.
*
* @param notice the notice entity to convert
* @return the response DTO representing the notice and its attachments
*/
private NoticeResponse toNoticeResponse(NoticeJpaEntity notice) {
return NoticeResponse.of(notice, attachmentService.toAttachmentResponses(notice));
}


/**
* Converts a notice entity to a detailed response DTO, including detailed attachment information.
*
* @param notice the notice entity to convert
* @return a detailed response DTO representing the notice and its attachments
*/
private NoticeDetailResponse toNoticeDetailResponse(NoticeJpaEntity notice) {
return NoticeDetailResponse.of(
notice,
attachmentService.toDetailAttResponses(notice)
);
}

/**
* Retrieves a notice entity by its ID or throws a {@code CustomRuntimeException} if not found.
*
* @param noticeId the ID of the notice to retrieve
* @return the {@code NoticeJpaEntity} corresponding to the given ID
* @throws CustomRuntimeException if the notice does not exist
*/
private NoticeJpaEntity getNoticeOrThrow(Long noticeId) {
return noticeRepository.findById(noticeId)
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.NOTICE_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@

public interface NoticeAttachmentRepository extends JpaRepository<NoticeAttachmentJpaEntity, Long> {

List<NoticeAttachmentJpaEntity> findAllByNoticeId(Long id);
/**
* Retrieves all notice attachment entities associated with the specified notice ID.
*
* @param id the unique identifier of the notice
* @return a list of notice attachment entities linked to the given notice ID
*/
List<NoticeAttachmentJpaEntity> findAllByNoticeId(Long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public class NoticeJpaEntity extends BaseTimeEntity {
@Column(name = "user_id", nullable = false)
private Long userId;

/**
* Constructs a new NoticeJpaEntity with the specified title, content, and user ID.
*
* @param title the title of the notice
* @param content the content of the notice
* @param userId the ID of the user associated with the notice
*/
@Builder
public NoticeJpaEntity(
final String title,
Expand All @@ -43,6 +50,12 @@ public NoticeJpaEntity(
this.userId = userId;
}

/**
* Updates the title and content of this notice entity.
*
* @param title the new title for the notice
* @param content the new content for the notice
*/
public void update(
final String title,
final String content
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/life/mosu/mosuserver/global/util/FileRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ public record FileRequest(
String s3Key
) {

/**
* Creates a FaqAttachmentJpaEntity with the specified file name, S3 key, and FAQ ID, setting its visibility to public.
*
* @param fileName the name of the file to associate with the FAQ attachment
* @param s3Key the S3 storage key for the file
* @param faqId the identifier of the FAQ to which the attachment belongs
* @return a new FaqAttachmentJpaEntity instance with public visibility
*/
public FaqAttachmentJpaEntity toFaqAttachmentEntity(String fileName, String s3Key, Long faqId) {
return FaqAttachmentJpaEntity.builder()
.fileName(fileName)
Expand All @@ -21,6 +29,14 @@ public FaqAttachmentJpaEntity toFaqAttachmentEntity(String fileName, String s3Ke
.build();
}

/**
* Creates a NoticeAttachmentJpaEntity with the specified file name, S3 key, and notice ID, setting its visibility to public.
*
* @param fileName the name of the file to associate with the notice attachment
* @param s3Key the S3 storage key for the file
* @param noticeId the identifier of the notice to which the attachment belongs
* @return a NoticeAttachmentJpaEntity configured with the provided details and public visibility
*/
public NoticeAttachmentJpaEntity toNoticeAttachmentEntity(String fileName, String s3Key,
Long noticeId) {
return NoticeAttachmentJpaEntity.builder()
Expand All @@ -31,6 +47,14 @@ public NoticeAttachmentJpaEntity toNoticeAttachmentEntity(String fileName, Strin
.build();
}

/**
* Creates an InquiryAttachmentJpaEntity with the specified file name, S3 key, and inquiry ID, setting the visibility to private.
*
* @param fileName the name of the file to associate with the inquiry attachment
* @param s3Key the S3 storage key for the file
* @param inquiryId the ID of the inquiry to which the attachment belongs
* @return a new InquiryAttachmentJpaEntity configured with the provided values and private visibility
*/
public InquiryAttachmentJpaEntity toInquiryAttachmentEntity(String fileName, String s3Key,
Long inquiryId) {
return InquiryAttachmentJpaEntity.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,28 @@ public class FileUploadHelper {

private final S3Service s3Service;

/**
* Marks the file identified by the given S3 key as active in S3 storage.
*
* @param s3Key the S3 key of the file to update
*/
public void updateTag(String s3Key) {
s3Service.updateFileTagToActive(s3Key);
}

/**
* Processes a list of request objects by marking their associated S3 files as active and saving corresponding entities to the database.
*
* For each request, extracts the S3 key, updates the file's tag to active in S3, maps the request and parent ID to an entity, and persists the entity using the provided repository.
*
* No action is taken if the request list is null or empty.
*
* @param requests the list of request objects to process
* @param parentId the identifier to associate with each entity
* @param repository the JPA repository used to save entities
* @param toEntityMapper a function that maps a request and parent ID to an entity
* @param getKey a function that extracts the S3 key from a request
*/
public <R, E> void saveAttachments(
List<R> requests,
Long parentId,
Expand Down
Loading