diff --git a/main/src/main/java/org/sopt/makers/crew/main/entity/lightning/Lightning.java b/main/src/main/java/org/sopt/makers/crew/main/entity/lightning/Lightning.java index 09f102df..d7a987f3 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/entity/lightning/Lightning.java +++ b/main/src/main/java/org/sopt/makers/crew/main/entity/lightning/Lightning.java @@ -39,6 +39,10 @@ public class Lightning extends BaseTimeEntity { @Column(name = "leaderUserId") private Integer leaderUserId; + @NotNull + @Column(name = "meetingId") + private Integer meetingId; + @NotNull @Size(min = 1, max = 30) @Column(name = "title") @@ -93,12 +97,14 @@ public class Lightning extends BaseTimeEntity { private List imageURL; @Builder - public Lightning(Integer leaderUserId, String title, String desc, LightningTimingType lightningTimingType, + public Lightning(Integer leaderUserId, Integer meetingId, String title, String desc, + LightningTimingType lightningTimingType, LocalDateTime startDate, LocalDateTime endDate, LocalDateTime activityStartDate, LocalDateTime activityEndDate, LightningPlaceType lightningPlaceType, String lightningPlace, int minimumCapacity, int maximumCapacity, Integer createdGeneration, List imageURL) { this.leaderUserId = leaderUserId; + this.meetingId = meetingId; this.title = title; this.desc = desc; this.lightningTimingType = lightningTimingType; diff --git a/main/src/main/java/org/sopt/makers/crew/main/entity/meeting/Meeting.java b/main/src/main/java/org/sopt/makers/crew/main/entity/meeting/Meeting.java index ca9d26b7..c2b362c3 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/entity/meeting/Meeting.java +++ b/main/src/main/java/org/sopt/makers/crew/main/entity/meeting/Meeting.java @@ -195,6 +195,35 @@ public Meeting(User user, Integer userId, String title, MeetingCategory category this.joinableParts = joinableParts; } + public static Meeting createLightningMeeting(User user, Integer userId, String title, + List imageURL, LocalDateTime startDate, + LocalDateTime endDate, Integer capacity, String desc, + LocalDateTime mStartDate, LocalDateTime mEndDate, + int createdGeneration, String processDesc, String leaderDesc, String note) { + + return Meeting.builder() + .user(user) + .userId(userId) + .title(title) + .category(MeetingCategory.LIGHTNING) + .imageURL(imageURL) + .startDate(startDate) + .endDate(endDate) + .capacity(capacity) + .desc(desc) + .mStartDate(mStartDate) + .mEndDate(mEndDate) + .createdGeneration(createdGeneration) + .processDesc(processDesc) + .leaderDesc(leaderDesc) + .note(note) + .isMentorNeeded(false) + .canJoinOnlyActiveGeneration(false) + .targetActiveGeneration(null) + .joinableParts(MeetingJoinablePart.values()) + .build(); + } + /** * 모임 모집상태 확인 * diff --git a/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSetting.java b/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSetting.java new file mode 100644 index 00000000..abd75cf2 --- /dev/null +++ b/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSetting.java @@ -0,0 +1,5 @@ +package org.sopt.makers.crew.main.global.config; + +public interface ImageSetting { + String getDefaultLightningImage(); +} diff --git a/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSettingConfig.java b/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSettingConfig.java new file mode 100644 index 00000000..c58cb8c8 --- /dev/null +++ b/main/src/main/java/org/sopt/makers/crew/main/global/config/ImageSettingConfig.java @@ -0,0 +1,15 @@ +package org.sopt.makers.crew.main.global.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ImageSettingConfig implements ImageSetting { + @Value("${img.lightning}") + private String defaultLightningImage; + + @Override + public String getDefaultLightningImage() { + return defaultLightningImage; + } +} diff --git a/main/src/main/java/org/sopt/makers/crew/main/global/exception/ErrorStatus.java b/main/src/main/java/org/sopt/makers/crew/main/global/exception/ErrorStatus.java index 5686f6aa..1cb2349c 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/global/exception/ErrorStatus.java +++ b/main/src/main/java/org/sopt/makers/crew/main/global/exception/ErrorStatus.java @@ -18,10 +18,6 @@ public enum ErrorStatus { VALIDATION_EXCEPTION("CF-001"), VALIDATION_REQUEST_MISSING_EXCEPTION("요청값이 입력되지 않았습니다."), INVALID_INPUT_VALUE_FILTER("요청값 또는 토큰이 올바르지 않습니다."), - NOT_FOUND_MEETING("모임이 없습니다."), - NOT_FOUND_POST("존재하지 않는 게시글입니다."), - NOT_FOUND_USER("존재하지 않는 유저입니다."), - NOT_FOUND_COMMENT("존재하지 않는 댓글입니다."), FULL_MEETING_CAPACITY("정원이 꽉 찼습니다."), ALREADY_APPLIED_MEETING("이미 지원한 모임입니다."), ALREADY_REPORTED_COMMENT("이미 신고한 댓글입니다."), @@ -63,6 +59,15 @@ public enum ErrorStatus { */ FORBIDDEN_EXCEPTION("권한이 없습니다."), + /** + * 404 NOT_FOUND + */ + NOT_FOUND_MEETING("모임이 없습니다."), // 예외 처리 NotFound로 수정 필요 + NOT_FOUND_POST("존재하지 않는 게시글입니다."), // 예외 처리 NotFound로 수정 필요 + NOT_FOUND_USER("존재하지 않는 유저입니다."), // 예외 처리 NotFound로 수정 필요 + NOT_FOUND_COMMENT("존재하지 않는 댓글입니다."), // 예외 처리 NotFound로 수정 필요 + NOT_FOUND_LIGHTNING("번쩍 모임이 없습니다."), // 예외 처리 NotFound로 수정 필요 + /** * 405 METHOD_NOT_ALLOWED */ diff --git a/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/dto/mapper/LightningMapper.java b/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/dto/mapper/LightningMapper.java index d6307259..ba4b6adb 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/dto/mapper/LightningMapper.java +++ b/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/dto/mapper/LightningMapper.java @@ -5,7 +5,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -15,27 +15,25 @@ import org.sopt.makers.crew.main.entity.lightning.enums.LightningTimingType; import org.sopt.makers.crew.main.entity.meeting.vo.ImageUrlVO; import org.sopt.makers.crew.main.global.util.Time; -import org.sopt.makers.crew.main.lightning.v2.dto.request.LightningV2CreateLightningBodyWithoutWelcomeMessageDto; +import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingForLightningResponseDto; @Mapper(componentModel = "spring") public interface LightningMapper { - - @Mapping(source = "lightningBody.files", target = "imageURL", qualifiedByName = "getImageURL") - @Mapping(source = "lightningBody.activityStartDate", target = "activityStartDate", qualifiedByName = "getActivityStartDate") - @Mapping(source = "lightningBody.activityEndDate", target = "activityEndDate", qualifiedByName = "getActivityEndDate") - @Mapping(source = "lightningBody.lightningPlaceType", target = "lightningPlaceType", qualifiedByName = "getLightningPlaceType") - @Mapping(source = "lightningBody.lightningTimingType", target = "lightningTimingType", qualifiedByName = "getLightningTimingType") + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.files", target = "imageURL", qualifiedByName = "getImageURL") @Mapping(target = "startDate", expression = "java(time.now())") - @Mapping(source = "lightningBody.activityStartDate", target = "endDate", qualifiedByName = "getActivityStartDate") - Lightning toLightningEntity(LightningV2CreateLightningBodyWithoutWelcomeMessageDto lightningBody, + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.activityStartDate", target = "endDate", qualifiedByName = "getActivityStartDate") + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.activityStartDate", target = "activityStartDate", qualifiedByName = "getActivityStartDate") + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.activityEndDate", target = "activityEndDate", qualifiedByName = "getActivityEndDate") + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.lightningPlaceType", target = "lightningPlaceType", qualifiedByName = "getLightningPlaceType") + @Mapping(source = "meetingV2CreateMeetingForLightningResponseDto.lightningTimingType", target = "lightningTimingType", qualifiedByName = "getLightningTimingType") + Lightning toLightningEntity( + MeetingV2CreateMeetingForLightningResponseDto meetingV2CreateMeetingForLightningResponseDto, Integer createdGeneration, Integer leaderUserId, Time time); @Named("getImageURL") static List getImageURL(List files) { - AtomicInteger index = new AtomicInteger(0); - - return files.stream() - .map(fileUrl -> new ImageUrlVO(index.getAndIncrement(), fileUrl)) + return IntStream.range(0, files.size()) + .mapToObj(index -> new ImageUrlVO(index, files.get(index))) .toList(); } @@ -47,7 +45,6 @@ static LocalDateTime getActivityStartDate(String date) { @Named("getActivityEndDate") static LocalDateTime getActivityEndDate(String date) { return LocalDateTime.parse(date + DAY_END_TIME, DateTimeFormatter.ofPattern(DAY_TIME_FORMAT)); - } @Named("getLightningPlaceType") diff --git a/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/service/LightningV2ServiceImpl.java b/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/service/LightningV2ServiceImpl.java index b03ae4b4..a3d68dc7 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/service/LightningV2ServiceImpl.java +++ b/main/src/main/java/org/sopt/makers/crew/main/lightning/v2/service/LightningV2ServiceImpl.java @@ -11,6 +11,8 @@ import org.sopt.makers.crew.main.lightning.v2.dto.mapper.LightningMapper; import org.sopt.makers.crew.main.lightning.v2.dto.request.LightningV2CreateLightningBodyDto; import org.sopt.makers.crew.main.lightning.v2.dto.response.LightningV2CreateLightningResponseDto; +import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingForLightningResponseDto; +import org.sopt.makers.crew.main.meeting.v2.service.MeetingV2Service; import org.sopt.makers.crew.main.tag.v2.service.TagV2Service; import org.sopt.makers.crew.main.user.v2.service.UserV2Service; import org.springframework.stereotype.Service; @@ -27,6 +29,7 @@ public class LightningV2ServiceImpl implements LightningV2Service { private final UserV2Service userV2Service; private final TagV2Service tagV2Service; + private final MeetingV2Service meetingV2Service; private final LightningRepository lightningRepository; private final LightningMapper lightningMapper; @@ -47,12 +50,50 @@ public LightningV2CreateLightningResponseDto createLightning( throw new BadRequestException(VALIDATION_EXCEPTION.getErrorCode()); } - Lightning lightning = lightningMapper.toLightningEntity(requestBody.lightningBody(), ACTIVE_GENERATION, - user.getId(), realTime); + MeetingV2CreateMeetingForLightningResponseDto meetingV2CreateMeetingForLightningResponseDto = meetingV2Service.createMeetingForLightning( + userId, requestBody.lightningBody()); + + Lightning lightning = lightningMapper.toLightningEntity(meetingV2CreateMeetingForLightningResponseDto, + ACTIVE_GENERATION, user.getId(), realTime); lightningRepository.save(lightning); tagV2Service.createLightningTag(requestBody.welcomeMessageTypes(), lightning.getId()); return LightningV2CreateLightningResponseDto.from(lightning.getId()); } + + // @Override + // public LightningV2GetLightningByIdResponseDto getLightningById(Integer lightningId, Integer userId) { + // User user = userV2Service.getUserByUserId(userId); + // + // Lightning lightning = lightningRepository.findById(lightningId) + // .orElseThrow(() -> new NotFoundException(NOT_FOUND_LIGHTNING.getErrorCode())); + // + // lightning. + // + // Meeting meeting = meetingReader.getMeetingById(meetingId).toEntity(); + // MeetingCreatorDto meetingLeader = userReader.getMeetingLeader(meeting.getUserId()); + // CoLeaders coLeaders = coLeaderReader.getCoLeaders(meetingId).toEntity(); + // + // Applies applies = new Applies( + // applyRepository.findAllByMeetingIdWithUser(meetingId, List.of(WAITING, APPROVE, REJECT), ORDER_ASC)); + // + // Boolean isHost = meeting.checkMeetingLeader(user.getId()); + // Boolean isApply = applies.isApply(meetingId, user.getId()); + // Boolean isApproved = applies.isApproved(meetingId, user.getId()); + // boolean isCoLeader = coLeaders.isCoLeader(meetingId, userId); + // long approvedCount = applies.getApprovedCount(meetingId); + // + // List applyWholeInfoDtos = new ArrayList<>(); + // if (applies.hasApplies(meetingId)) { + // applyWholeInfoDtos = applies.getAppliesMap().get(meetingId).stream() + // .map(apply -> ApplyWholeInfoDto.of(apply, apply.getUser(), userId)) + // .toList(); + // } + // + // return LightningV2GetLightningByIdResponseDto.of(meetingId, meeting, coLeaders.getCoLeaders(meetingId), + // isCoLeader, + // approvedCount, isHost, isApply, isApproved, + // meetingLeader, applyWholeInfoDtos, realTime.now()); + // } } diff --git a/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/dto/response/MeetingV2CreateMeetingForLightningResponseDto.java b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/dto/response/MeetingV2CreateMeetingForLightningResponseDto.java new file mode 100644 index 00000000..fbdb2664 --- /dev/null +++ b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/dto/response/MeetingV2CreateMeetingForLightningResponseDto.java @@ -0,0 +1,81 @@ +package org.sopt.makers.crew.main.meeting.v2.dto.response; + +import java.util.List; + +import org.sopt.makers.crew.main.lightning.v2.dto.request.LightningV2CreateLightningBodyWithoutWelcomeMessageDto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@Schema(name = "MeetingV2CreateMeetingForLightningResponseDto", description = "번쩍 모임 생성 및 수정 request body dto") +public record MeetingV2CreateMeetingForLightningResponseDto( + @Schema(description = "모임 id", example = "1") + @NotNull + Integer meetingId, + + @Schema(example = "알고보면 쓸데있는 개발 프로세스", description = "번쩍 모임 제목") + @Size(min = 1, max = 30) + @NotNull String title, + + @Schema(example = "api 가 터졌다고? 깃이 터졌다고?", description = "번쩍 소개") + @Size(min = 1, max = 500) + @NotNull + String desc, + + @Schema(example = "예정 기간(협의 후 결정)", description = "번쩍 일정 결정 방식") + @NotNull + String lightningTimingType, + + @Schema(example = "2025.10.29", description = "번쩍 활동 시작 날짜", name = "activityStartDate") + @NotNull + String activityStartDate, + + @Schema(example = "2025.10.30", description = "번쩍 활동 종료 날짜", name = "activityEndDate") + @NotNull + String activityEndDate, + + @Schema(example = "오프라인", description = "모임 장소 Tag") + @NotNull + String lightningPlaceType, + + @Schema(example = "잠실역 5번 출구", description = "모임 장소") + String lightningPlace, + + @Schema(example = "1", description = "최소 모집 인원") + @Min(1) + @NotNull + Integer minimumCapacity, + + @Schema(example = "5", description = "최대 모집 인원") + @Min(1) + @Max(999) + @NotNull + Integer maximumCapacity, + + @Schema(example = "[\n" + + " \"https://makers-web-img.s3.ap-northeast-2.amazonaws.com/meeting/2023/04/12/7bd87736-b557-4b26-a0d5-9b09f1f1d7df\"\n" + + " ]", description = "모임 이미지 리스트, 최대 1개") + @NotNull + @Size(max = 1) + List files +) { + public static MeetingV2CreateMeetingForLightningResponseDto of( + Integer meetingId, LightningV2CreateLightningBodyWithoutWelcomeMessageDto lightningBody) { + return new MeetingV2CreateMeetingForLightningResponseDto( + meetingId, + lightningBody.title(), + lightningBody.desc(), + lightningBody.lightningTimingType(), + lightningBody.activityStartDate(), + lightningBody.activityEndDate(), + lightningBody.lightningPlaceType(), + lightningBody.lightningPlace(), + lightningBody.minimumCapacity(), + lightningBody.maximumCapacity(), + lightningBody.files() + ); + } +} diff --git a/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2Service.java b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2Service.java index f50f2efe..1d87a95d 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2Service.java +++ b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2Service.java @@ -2,6 +2,7 @@ import java.util.List; +import org.sopt.makers.crew.main.lightning.v2.dto.request.LightningV2CreateLightningBodyWithoutWelcomeMessageDto; import org.sopt.makers.crew.main.meeting.v2.dto.query.MeetingGetAppliesQueryDto; import org.sopt.makers.crew.main.meeting.v2.dto.query.MeetingV2GetAllMeetingByOrgUserQueryDto; import org.sopt.makers.crew.main.meeting.v2.dto.query.MeetingV2GetAllMeetingQueryDto; @@ -11,6 +12,7 @@ import org.sopt.makers.crew.main.meeting.v2.dto.response.AppliesCsvFileUrlResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingGetApplyListResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2ApplyMeetingResponseDto; +import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingForLightningResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingByOrgUserDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingDto; @@ -50,4 +52,7 @@ AppliesCsvFileUrlResponseDto getAppliesCsvFileUrl(Integer meetingId, List meetingIds, Integer userId); + + MeetingV2CreateMeetingForLightningResponseDto createMeetingForLightning(Integer userId, + LightningV2CreateLightningBodyWithoutWelcomeMessageDto lightningBody); } diff --git a/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2ServiceImpl.java b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2ServiceImpl.java index 2924c2d5..dcbaaf0e 100644 --- a/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2ServiceImpl.java +++ b/main/src/main/java/org/sopt/makers/crew/main/meeting/v2/service/MeetingV2ServiceImpl.java @@ -1,8 +1,8 @@ package org.sopt.makers.crew.main.meeting.v2.service; +import static org.sopt.makers.crew.main.entity.apply.enums.EnApplyStatus.*; import static org.sopt.makers.crew.main.global.constant.CrewConst.*; import static org.sopt.makers.crew.main.global.exception.ErrorStatus.*; -import static org.sopt.makers.crew.main.entity.apply.enums.EnApplyStatus.*; import java.io.FileOutputStream; import java.io.IOException; @@ -19,27 +19,10 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; -import lombok.RequiredArgsConstructor; - -import org.sopt.makers.crew.main.entity.meeting.CoLeader; -import org.sopt.makers.crew.main.entity.meeting.CoLeaderReader; -import org.sopt.makers.crew.main.entity.meeting.CoLeaderRepository; -import org.sopt.makers.crew.main.entity.meeting.CoLeaders; -import org.sopt.makers.crew.main.entity.meeting.MeetingReader; -import org.sopt.makers.crew.main.entity.meeting.enums.MeetingCategory; -import org.sopt.makers.crew.main.entity.user.UserReader; -import org.sopt.makers.crew.main.global.dto.MeetingCreatorDto; -import org.sopt.makers.crew.main.global.dto.MeetingResponseDto; -import org.sopt.makers.crew.main.global.exception.BadRequestException; -import org.sopt.makers.crew.main.global.exception.ServerException; -import org.sopt.makers.crew.main.global.pagination.dto.PageMetaDto; -import org.sopt.makers.crew.main.global.pagination.dto.PageOptionsDto; -import org.sopt.makers.crew.main.global.util.AdvertisementCustomPageable; -import org.sopt.makers.crew.main.global.util.Time; -import org.sopt.makers.crew.main.global.util.UserPartUtil; import org.sopt.makers.crew.main.entity.apply.Applies; import org.sopt.makers.crew.main.entity.apply.Apply; import org.sopt.makers.crew.main.entity.apply.ApplyRepository; @@ -48,16 +31,35 @@ import org.sopt.makers.crew.main.entity.comment.Comment; import org.sopt.makers.crew.main.entity.comment.CommentRepository; import org.sopt.makers.crew.main.entity.like.LikeRepository; +import org.sopt.makers.crew.main.entity.meeting.CoLeader; +import org.sopt.makers.crew.main.entity.meeting.CoLeaderReader; +import org.sopt.makers.crew.main.entity.meeting.CoLeaderRepository; +import org.sopt.makers.crew.main.entity.meeting.CoLeaders; import org.sopt.makers.crew.main.entity.meeting.Meeting; +import org.sopt.makers.crew.main.entity.meeting.MeetingReader; import org.sopt.makers.crew.main.entity.meeting.MeetingRepository; +import org.sopt.makers.crew.main.entity.meeting.enums.MeetingCategory; import org.sopt.makers.crew.main.entity.meeting.enums.MeetingJoinablePart; +import org.sopt.makers.crew.main.entity.meeting.vo.ImageUrlVO; import org.sopt.makers.crew.main.entity.post.Post; import org.sopt.makers.crew.main.entity.post.PostRepository; import org.sopt.makers.crew.main.entity.user.User; +import org.sopt.makers.crew.main.entity.user.UserReader; import org.sopt.makers.crew.main.entity.user.UserRepository; import org.sopt.makers.crew.main.entity.user.enums.UserPart; import org.sopt.makers.crew.main.entity.user.vo.UserActivityVO; import org.sopt.makers.crew.main.external.s3.service.S3Service; +import org.sopt.makers.crew.main.global.config.ImageSetting; +import org.sopt.makers.crew.main.global.dto.MeetingCreatorDto; +import org.sopt.makers.crew.main.global.dto.MeetingResponseDto; +import org.sopt.makers.crew.main.global.exception.BadRequestException; +import org.sopt.makers.crew.main.global.exception.ServerException; +import org.sopt.makers.crew.main.global.pagination.dto.PageMetaDto; +import org.sopt.makers.crew.main.global.pagination.dto.PageOptionsDto; +import org.sopt.makers.crew.main.global.util.AdvertisementCustomPageable; +import org.sopt.makers.crew.main.global.util.Time; +import org.sopt.makers.crew.main.global.util.UserPartUtil; +import org.sopt.makers.crew.main.lightning.v2.dto.request.LightningV2CreateLightningBodyWithoutWelcomeMessageDto; import org.sopt.makers.crew.main.meeting.v2.dto.ApplyMapper; import org.sopt.makers.crew.main.meeting.v2.dto.MeetingMapper; import org.sopt.makers.crew.main.meeting.v2.dto.query.MeetingGetAppliesQueryDto; @@ -71,6 +73,7 @@ import org.sopt.makers.crew.main.meeting.v2.dto.response.ApplyWholeInfoDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingGetApplyListResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2ApplyMeetingResponseDto; +import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingForLightningResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2CreateMeetingResponseDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingByOrgUserDto; import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingByOrgUserMeetingDto; @@ -89,12 +92,15 @@ import com.opencsv.CSVWriter; +import lombok.RequiredArgsConstructor; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class MeetingV2ServiceImpl implements MeetingV2Service { private static final int ZERO = 0; + private static final String EMPTY_STRING = ""; private final UserRepository userRepository; private final ApplyRepository applyRepository; @@ -112,6 +118,8 @@ public class MeetingV2ServiceImpl implements MeetingV2Service { private final MeetingMapper meetingMapper; private final ApplyMapper applyMapper; + private final ImageSetting imageSetting; + private final Time time; @Override @@ -465,6 +473,38 @@ public MeetingV2GetRecommendDto getRecommendMeetingsByIds(List meetingI return MeetingV2GetRecommendDto.from(meetingResponseDtos); } + @Override + public MeetingV2CreateMeetingForLightningResponseDto createMeetingForLightning(Integer userId, + LightningV2CreateLightningBodyWithoutWelcomeMessageDto lightningBody) { + + User user = userRepository.findByIdOrThrow(userId); + + List imageURL = getImageURL(lightningBody.files()); + LocalDateTime activityStartDate = getActivityStartDate(lightningBody.activityStartDate()); + LocalDateTime activityEndDate = getActivityEndDate((lightningBody.activityStartDate())); + + Meeting lightningMeeting = Meeting.createLightningMeeting( + user, + userId, + lightningBody.title(), + imageURL, + time.now(), + activityStartDate, // 모집 마감일 = 활동 시작일 + lightningBody.maximumCapacity(), + lightningBody.desc(), + activityStartDate, + activityEndDate, + ACTIVE_GENERATION, + EMPTY_STRING, // null 대신 빈 문자열로 NPE 방지 + EMPTY_STRING, // null 대신 빈 문자열로 NPE 방지 + EMPTY_STRING // null 대신 빈 문자열로 NPE 방지 + ); + + meetingRepository.save(lightningMeeting); + + return MeetingV2CreateMeetingForLightningResponseDto.of(lightningMeeting.getId(), lightningBody); + } + private void deleteCsvFile(String filePath) { try { Files.deleteIfExists(Paths.get(filePath)); @@ -614,4 +654,24 @@ private List createCoLeaders(List coLeaders, Meeting savedMeetin .build()) .toList(); } + + private List getImageURL(List files) { + AtomicInteger index = new AtomicInteger(0); + + if (files.isEmpty()) { + files.add(imageSetting.getDefaultLightningImage()); + } + + return files.stream() + .map(fileUrl -> new ImageUrlVO(index.getAndIncrement(), fileUrl)) + .toList(); + } + + private LocalDateTime getActivityStartDate(String date) { + return LocalDateTime.parse(date + DAY_START_TIME, DateTimeFormatter.ofPattern(DAY_TIME_FORMAT)); + } + + private LocalDateTime getActivityEndDate(String date) { + return LocalDateTime.parse(date + DAY_END_TIME, DateTimeFormatter.ofPattern(DAY_TIME_FORMAT)); + } } diff --git a/main/src/main/resources/application-dev.yml b/main/src/main/resources/application-dev.yml index 65b144bf..e3547496 100644 --- a/main/src/main/resources/application-dev.yml +++ b/main/src/main/resources/application-dev.yml @@ -116,3 +116,6 @@ logging: sentry: repository-uri: ${SENTRY_REPOSITORY_URI} environment: dev + +img: + lightning: ${LIGHTNING_IMAGE} diff --git a/main/src/main/resources/application-local.yml b/main/src/main/resources/application-local.yml index 1a61a34e..3c9ada65 100644 --- a/main/src/main/resources/application-local.yml +++ b/main/src/main/resources/application-local.yml @@ -69,7 +69,7 @@ push-notification: push-server-url: ${LOCAL_PUSH_SERVER_URL} notice: - secret-key : ${NOTICE_SECRET_KEY} + secret-key: ${NOTICE_SECRET_KEY} playground: server: @@ -115,4 +115,7 @@ logging: config: classpath:logback-spring.xml sentry: repository-uri: ${LOCAL_SENTRY_REPOSITORY_URI} - environment: local \ No newline at end of file + environment: local + +img: + lightning: ${LIGHTNING_IMAGE} diff --git a/main/src/main/resources/application-prod.yml b/main/src/main/resources/application-prod.yml index 8b76da2b..9542bded 100644 --- a/main/src/main/resources/application-prod.yml +++ b/main/src/main/resources/application-prod.yml @@ -116,3 +116,6 @@ logging: sentry: repository-uri: ${SENTRY_REPOSITORY_URI} environment: prod + +img: + lightning: ${LIGHTNING_IMAGE} diff --git a/main/src/main/resources/application-test.yml b/main/src/main/resources/application-test.yml index 08c2faae..ce3f3a4a 100644 --- a/main/src/main/resources/application-test.yml +++ b/main/src/main/resources/application-test.yml @@ -115,3 +115,6 @@ logging: sentry: repository-uri: ${SENTRY_REPOSITORY_URI} environment: test + +img: + lightning: ${LIGHTNING_IMAGE}