Skip to content
Merged
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 @@ -7,6 +7,7 @@
import life.mosu.mosuserver.global.exception.ErrorCode;
import life.mosu.mosuserver.infra.persistence.s3.S3Service;
import life.mosu.mosuserver.presentation.admin.dto.BannerInfoResponse;
import life.mosu.mosuserver.presentation.admin.dto.BannerInfoResponse.AttachmentResponse;
import life.mosu.mosuserver.presentation.admin.dto.BannerRequest;
import life.mosu.mosuserver.presentation.admin.dto.BannerResponse;
import lombok.RequiredArgsConstructor;
Expand All @@ -29,9 +30,15 @@ public List<BannerResponse> getAll() {
public BannerInfoResponse getByBannerId(Long bannerId) {
BannerJpaEntity banner = bannerJpaRepository.findById(bannerId)
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.BANNER_NOT_FOUND));
String imgUrl = s3Service.getPublicUrl(banner.getS3Key());

String url = null;
if (banner.getS3Key() != null) {
url = s3Service.getPublicUrl(banner.getS3Key());
}

AttachmentResponse attachment = AttachmentResponse.of(banner.getFileName(), url);
return BannerInfoResponse.of(banner.getTitle(), banner.getDeadline(), banner.getLink(),
imgUrl);
attachment);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
package life.mosu.mosuserver.application.event;

import java.util.List;
import life.mosu.mosuserver.domain.event.EventAttachmentRepository;
import life.mosu.mosuserver.domain.event.EventJpaEntity;
import life.mosu.mosuserver.infra.persistence.s3.AttachmentService;
import life.mosu.mosuserver.infra.persistence.s3.FileUploadHelper;
import life.mosu.mosuserver.presentation.common.FileRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class EventAttachmentService implements AttachmentService<EventJpaEntity, FileRequest> {

private final EventAttachmentRepository eventAttachmentRepository;
private final FileUploadHelper fileUploadHelper;

@Override
public void createAttachment(List<FileRequest> request, EventJpaEntity eventEntity) {
if (request == null || request.isEmpty()) {
return;
}
fileUploadHelper.saveAttachments(
request,
eventEntity.getId(),
eventAttachmentRepository,
(fileRequest, eventId) -> fileRequest.toEventAttachmentEntity(eventEntity.getId()),
FileRequest::s3Key
);
}

@Override
public void deleteAttachment(EventJpaEntity entity) {
if (eventAttachmentRepository.findByEventId(entity.getId()).isPresent()) {
eventAttachmentRepository.deleteByEventId(entity.getId());
}
}

}
//package life.mosu.mosuserver.application.event;
//
//import java.util.List;
//import life.mosu.mosuserver.domain.event.EventAttachmentRepository;
//import life.mosu.mosuserver.domain.event.EventJpaEntity;
//import life.mosu.mosuserver.infra.persistence.s3.AttachmentService;
//import life.mosu.mosuserver.infra.persistence.s3.FileUploadHelper;
//import life.mosu.mosuserver.presentation.common.FileRequest;
//import lombok.RequiredArgsConstructor;
//import org.springframework.stereotype.Service;
//
//@Service
//@RequiredArgsConstructor
//public class EventAttachmentService implements AttachmentService<EventJpaEntity, FileRequest> {
//
// private final EventAttachmentRepository eventAttachmentRepository;
// private final FileUploadHelper fileUploadHelper;
//
// @Override
// public void createAttachment(List<FileRequest> request, EventJpaEntity eventEntity) {
// if (request == null || request.isEmpty()) {
// return;
// }
// fileUploadHelper.saveAttachments(
// request,
// eventEntity.getId(),
// eventAttachmentRepository,
// (fileRequest, eventId) -> fileRequest.toEventAttachmentEntity(eventEntity.getId()),
// FileRequest::s3Key
// );
// }
//
// @Override
// public void deleteAttachment(EventJpaEntity entity) {
// if (eventAttachmentRepository.findByEventId(entity.getId()).isPresent()) {
// eventAttachmentRepository.deleteByEventId(entity.getId());
// }
// }
//
//}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import java.util.List;
import life.mosu.mosuserver.domain.event.EventJpaEntity;
import life.mosu.mosuserver.domain.event.EventJpaRepository;
import life.mosu.mosuserver.domain.event.projection.EventWithAttachmentProjection;
import life.mosu.mosuserver.domain.event.EventQueryRepository;
import life.mosu.mosuserver.global.exception.CustomRuntimeException;
import life.mosu.mosuserver.global.exception.ErrorCode;
import life.mosu.mosuserver.global.support.CursorResponse;
import life.mosu.mosuserver.infra.persistence.s3.S3Service;
import life.mosu.mosuserver.presentation.event.dto.EventRequest;
import life.mosu.mosuserver.presentation.event.dto.EventResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,37 +21,48 @@
public class EventService {

private final EventJpaRepository eventJpaRepository;
private final EventAttachmentService attachmentService;
private final EventQueryRepository eventQueryRepository;
// private final EventAttachmentService attachmentService;
private final S3Service s3Service;

@Transactional
public void createEvent(EventRequest request) {
EventJpaEntity eventEntity = eventJpaRepository.save(request.toEntity());
attachmentService.createAttachment(request.optionalAttachment(), eventEntity);
// attachmentService.createAttachment(request.optionalAttachment(), eventEntity);
}

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public List<EventResponse> getEvents() {
List<EventWithAttachmentProjection> events = eventJpaRepository.findAllWithAttachment();
public CursorResponse<EventResponse> getEvents(Long cursorId) {
Slice<EventJpaEntity> eventSlice = eventQueryRepository.findAllByCursorId(cursorId);

return events.stream()
List<EventResponse> events = eventSlice.getContent().stream()
.map(event -> {
String url = event.attachment().s3Key() != null ? s3Service.getPublicUrl(
event.attachment().s3Key()) : null;
String url = event.getS3Key() != null ? s3Service.getPublicUrl(
event.getS3Key()) : null;
return EventResponse.of(event, url);
})
.toList();

Long nextCursor = eventSlice.hasNext()
? eventSlice.getContent().getLast().getId()
: null;

return CursorResponse.of(
events,
eventSlice.isLast(),
eventSlice.getNumberOfElements(),
nextCursor);
}


@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public EventResponse getEventDetail(Long eventId) {
EventWithAttachmentProjection eventEntity = eventJpaRepository.findWithAttachmentById(
EventJpaEntity eventEntity = eventJpaRepository.findById(
eventId)
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.EVENT_NOT_FOUND));

String eventUrl = eventEntity.attachment().s3Key() != null ? s3Service.getPublicUrl(
eventEntity.attachment().s3Key()) : null;
String eventUrl = eventEntity.getS3Key() != null ? s3Service.getPublicUrl(
eventEntity.getS3Key()) : null;

return EventResponse.of(eventEntity, eventUrl);
}
Expand All @@ -59,12 +72,16 @@ public void update(EventRequest request, Long eventId) {
EventJpaEntity eventEntity = eventJpaRepository.findById(eventId)
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.EVENT_NOT_FOUND));

eventEntity.update(request.title(), request.duration().toDurationJpaVO(),
eventEntity.update(
request.attachment().fileName(),
request.attachment().s3Key(),
request.title(),
request.duration().toDurationJpaVO(),
request.eventLink());
eventJpaRepository.save(eventEntity);

attachmentService.deleteAttachment(eventEntity);
attachmentService.createAttachment(request.optionalAttachment(), eventEntity);
// attachmentService.deleteAttachment(eventEntity);
// attachmentService.createAttachment(request.optionalAttachment(), eventEntity);
}

@Transactional
Expand All @@ -73,7 +90,6 @@ public void deleteEvent(Long eventId) {
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.FILE_NOT_FOUND));

eventJpaRepository.delete(eventEntity);
attachmentService.deleteAttachment(eventEntity);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class ExamService {

public void register(ExamRequest request) {
ExamJpaEntity exam = request.toEntity();
ExamJpaEntity savedExam = examJpaRepository.save(exam);
examJpaRepository.save(exam);
}

public List<ExamResponse> getByArea(String areaName) {
Expand All @@ -29,7 +29,7 @@ public List<ExamResponse> getByArea(String areaName) {
return foundExams.stream()
.map(exam -> {
Long count = examQuotaCacheManager.getCurrentApplications(
exam.getSchoolName()).orElse(0L);
exam.getSchoolName()).orElse(null);
return ExamResponse.of(exam, count);
})
.toList();
Expand All @@ -46,10 +46,13 @@ public List<ExamResponse> getExams() {
return exams.stream()
.map(exam -> {
Long count = examQuotaCacheManager.getCurrentApplications(
exam.getSchoolName()).orElse(0L);
return ExamResponse.of(exam, 3L);
exam.getSchoolName()).orElse(null);
return ExamResponse.of(exam, count);
})
.toList();
}

public void delete(Long examId) {
examJpaRepository.deleteById(examId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public void deleteInquiryAnswer(Long postId) {
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.INQUIRY_ANSWER_NOT_FOUND));

inquiryAnswerJpaRepository.delete(answerEntity);
answerAttachmentService.deleteAttachment(answerEntity);
inquiryEntity.updateStatusToPending();
}

Expand All @@ -73,7 +72,7 @@ public void updateInquiryAnswer(Long postId, InquiryAnswerUpdateRequest request)
answerEntity.update(request.title(), request.content());
inquiryAnswerJpaRepository.save(answerEntity);

answerAttachmentService.deleteAttachment(answerEntity);
// answerAttachmentService.deleteAttachment(answerEntity);
answerAttachmentService.createAttachment(request.attachments(), answerEntity);
Comment on lines +75 to 76

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic for updating attachments is incorrect after the changes. By commenting out answerAttachmentService.deleteAttachment(answerEntity), old attachments will no longer be removed when new ones are provided during an update. This will lead to an accumulation of attachments for the same answer over multiple updates, creating data inconsistencies. The line to delete old attachments should be restored to ensure that only the latest attachments are associated with the answer.

Suggested change
// answerAttachmentService.deleteAttachment(answerEntity);
answerAttachmentService.createAttachment(request.attachments(), answerEntity);
answerAttachmentService.deleteAttachment(answerEntity);
answerAttachmentService.createAttachment(request.attachments(), answerEntity);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void deleteInquiry(UserJpaEntity user, Long postId) {
inquiryAnswerService.deleteInquiryAnswer(postId);
});

inquiryAttachmentService.deleteAttachment(inquiry);
// inquiryAttachmentService.deleteAttachment(inquiry);

inquiryJpaRepository.delete(inquiry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import life.mosu.mosuserver.infra.persistence.s3.S3Service;
import life.mosu.mosuserver.presentation.common.FileRequest;
import life.mosu.mosuserver.presentation.notice.dto.NoticeDetailResponse;
import life.mosu.mosuserver.presentation.notice.dto.NoticeResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -41,18 +40,18 @@ public void deleteAttachment(NoticeJpaEntity entity) {
noticeAttachmentJpaRepository.deleteAll(attachments);
}

public List<NoticeResponse.AttachmentResponse> toAttachmentResponses(NoticeJpaEntity notice) {

List<NoticeAttachmentJpaEntity> attachments = noticeAttachmentJpaRepository.findAllByNoticeId(
notice.getId());

return attachments.stream()
.map(attachment -> new NoticeResponse.AttachmentResponse(
attachment.getFileName(),
fileUrl(attachment.getS3Key())
))
.toList();
}
// public List<NoticeResponse.AttachmentResponse> toAttachmentResponses(NoticeJpaEntity notice) {
//
// List<NoticeAttachmentJpaEntity> attachments = noticeAttachmentJpaRepository.findAllByNoticeId(
// notice.getId());
//
// return attachments.stream()
// .map(attachment -> new NoticeResponse.AttachmentResponse(
// attachment.getFileName(),
// fileUrl(attachment.getS3Key())
// ))
// .toList();
// }

public List<NoticeDetailResponse.AttachmentDetailResponse> toDetailAttResponses(
NoticeJpaEntity notice) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import life.mosu.mosuserver.presentation.notice.dto.NoticeResponse;
import life.mosu.mosuserver.presentation.notice.dto.NoticeUpdateRequest;
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;
Expand All @@ -18,6 +19,7 @@
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class NoticeService {
Expand All @@ -32,7 +34,7 @@ public void createNotice(NoticeCreateRequest request) {
}

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public List<NoticeResponse> getNoticeWithAttachments(int page, int size) {
public List<NoticeResponse> getNotices(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("id"));
Page<NoticeJpaEntity> noticePage = noticeJpaRepository.findAll(pageable);

Expand All @@ -52,7 +54,6 @@ public NoticeDetailResponse getNoticeDetail(Long noticeId) {
public void deleteNotice(Long noticeId) {
NoticeJpaEntity noticeEntity = getNoticeOrThrow(noticeId);
noticeJpaRepository.delete(noticeEntity);
attachmentService.deleteAttachment(noticeEntity);
}

@Transactional
Expand All @@ -65,7 +66,7 @@ public void updateNotice(Long noticeId, NoticeUpdateRequest request) {
}

private NoticeResponse toNoticeResponse(NoticeJpaEntity notice) {
return NoticeResponse.of(notice, attachmentService.toAttachmentResponses(notice));
return NoticeResponse.of(notice);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import life.mosu.mosuserver.domain.base.BaseTimeEntity;
import life.mosu.mosuserver.domain.base.BaseDeleteEntity;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SoftDelete;

@Entity
@Table(name = "application")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SoftDelete
public class ApplicationJpaEntity extends BaseTimeEntity {
public class ApplicationJpaEntity extends BaseDeleteEntity {
Comment on lines 15 to +19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The @SoftDelete annotation is missing from this entity. While it now extends BaseDeleteEntity, which provides the deleted flag, Hibernate's soft delete mechanism is only activated by the @SoftDelete annotation on the entity class itself. Without it, any delete operation on this entity will result in a hard delete from the database, which goes against the main goal of this pull request.

Suggested change
@Entity
@Table(name = "application")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SoftDelete
public class ApplicationJpaEntity extends BaseTimeEntity {
public class ApplicationJpaEntity extends BaseDeleteEntity {
@Entity
@Table(name = "application")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SoftDelete
public class ApplicationJpaEntity extends BaseDeleteEntity {


@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Loading