From 04c30dd718ea1872d0b2cb84be95fbfcb864d98c Mon Sep 17 00:00:00 2001 From: Hoyeon Lee <89958157+howooyeon@users.noreply.github.com> Date: Wed, 13 May 2026 00:57:26 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat=20:=20=ED=95=99=ED=9A=8C=20=EC=86=8C?= =?UTF-8?q?=EA=B0=9C=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=ED=99=95=EC=9E=A5=20?= =?UTF-8?q?=EB=B0=8F=20=EC=8B=A0=EA=B7=9C=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/introduction/entity/Activity.java | 44 ++++++++++++++ .../introduction/entity/IntroMeetupImage.java | 31 ++++++++++ .../introduction/entity/Introduction.java | 58 ++++++++++++++++--- .../introduction/entity/PartnerLogo.java | 31 ++++++++++ .../domain/introduction/entity/Sponsor.java | 31 ++++++++++ .../repository/ActivityRepository.java | 9 +++ .../repository/ExpertLectureRepository.java | 2 + .../IntroMeetupImageRepository.java | 9 +++ .../repository/ManageTeamRepository.java | 2 + .../repository/OBLectureRepository.java | 2 + .../repository/PartnerLogoRepository.java | 9 +++ .../repository/SponsorRepository.java | 9 +++ 12 files changed, 230 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/kusitms/website/domain/introduction/entity/Activity.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/entity/IntroMeetupImage.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/entity/PartnerLogo.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/entity/Sponsor.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/repository/ActivityRepository.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/repository/IntroMeetupImageRepository.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/repository/PartnerLogoRepository.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/repository/SponsorRepository.java diff --git a/src/main/java/com/kusitms/website/domain/introduction/entity/Activity.java b/src/main/java/com/kusitms/website/domain/introduction/entity/Activity.java new file mode 100644 index 0000000..fbaa757 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/entity/Activity.java @@ -0,0 +1,44 @@ +package com.kusitms.website.domain.introduction.entity; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Activity { + @Id + @Column(name = "activity_id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long activityId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "introduction_id") + private Introduction introduction; + + @Column(nullable = false) + private String name; + + @Column(name = "image_url1") + private String imageUrl1; + + @Column(name = "image_url2") + private String imageUrl2; + + @Column(length = 500) + private String description; + + @Builder + public Activity(Introduction introduction, String name, String imageUrl1, + String imageUrl2, String description) { + this.introduction = introduction; + this.name = name; + this.imageUrl1 = imageUrl1; + this.imageUrl2 = imageUrl2; + this.description = description; + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/entity/IntroMeetupImage.java b/src/main/java/com/kusitms/website/domain/introduction/entity/IntroMeetupImage.java new file mode 100644 index 0000000..2ecc07a --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/entity/IntroMeetupImage.java @@ -0,0 +1,31 @@ +package com.kusitms.website.domain.introduction.entity; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class IntroMeetupImage { + @Id + @Column(name = "meetup_image_id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long meetupImageId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "introduction_id") + private Introduction introduction; + + @Column(name = "image_url") + private String imageUrl; + + @Builder + public IntroMeetupImage(Introduction introduction, String imageUrl) { + this.introduction = introduction; + this.imageUrl = imageUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/entity/Introduction.java b/src/main/java/com/kusitms/website/domain/introduction/entity/Introduction.java index 2ea8dd4..343e739 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/entity/Introduction.java +++ b/src/main/java/com/kusitms/website/domain/introduction/entity/Introduction.java @@ -24,6 +24,10 @@ public class Introduction { @Column(name = "banner_status") @Enumerated(EnumType.STRING) private BannerStatus bannerStatus; + @Column(name = "slogan", length = 50) + private String slogan; + @Column(name = "banner_image_url") + private String bannerImageUrl; // 학회 정보 @Column(name = "member_count") @@ -37,10 +41,20 @@ public class Introduction { @Column(name = "intro_youtube_link") private String introYoutubeLink; - // 파트너사 이미지 + // 파트너사 이미지 (기존 단일 필드 유지 — 하위호환) @Column(name = "partner_image_url") private String partnerImageUrl; + // 함께하는 큐밀리 이미지 + @Column(name = "planning_image_url") + private String planningImageUrl; + @Column(name = "design_image_url") + private String designImageUrl; + @Column(name = "frontend_image_url") + private String frontendImageUrl; + @Column(name = "backend_image_url") + private String backendImageUrl; + // 운영진 소개 @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) private List manageTeam = new ArrayList<>(); @@ -53,32 +67,62 @@ public class Introduction { @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) private List obLecture = new ArrayList<>(); + // 파트너사 로고 목록 (배열) + @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) + private List partnerLogos = new ArrayList<>(); + + // 밋업 이미지 목록 + @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) + private List meetupImages = new ArrayList<>(); + + // 활동 소개 + @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) + private List activities = new ArrayList<>(); + + // 후원사 + @OneToMany(mappedBy = "introduction", cascade = CascadeType.ALL) + private List sponsors = new ArrayList<>(); @Builder - public Introduction(Long bannerCardinal, BannerStatus bannerStatus, + public Introduction(Long bannerCardinal, BannerStatus bannerStatus, String slogan, String bannerImageUrl, Long memberCount, Long projectCount, Long universityCount, - String partnerImageUrl, String introYoutubeLink) + String partnerImageUrl, String introYoutubeLink, + String planningImageUrl, String designImageUrl, + String frontendImageUrl, String backendImageUrl) { this.bannerCardinal = bannerCardinal; this.bannerStatus = bannerStatus; + this.slogan = slogan; + this.bannerImageUrl = bannerImageUrl; this.memberCount = memberCount; this.projectCount = projectCount; this.universityCount = universityCount; this.partnerImageUrl = partnerImageUrl; this.introYoutubeLink = introYoutubeLink; + this.planningImageUrl = planningImageUrl; + this.designImageUrl = designImageUrl; + this.frontendImageUrl = frontendImageUrl; + this.backendImageUrl = backendImageUrl; } - public void update(Long bannerCardinal, BannerStatus bannerStatus, + public void update(Long bannerCardinal, BannerStatus bannerStatus, String slogan, String bannerImageUrl, Long memberCount, Long projectCount, Long universityCount, - String partnerImageUrl, String introYoutubeLink) + String partnerImageUrl, String introYoutubeLink, + String planningImageUrl, String designImageUrl, + String frontendImageUrl, String backendImageUrl) { this.bannerCardinal = bannerCardinal; this.bannerStatus = bannerStatus; + this.slogan = slogan; + this.bannerImageUrl = bannerImageUrl; this.memberCount = memberCount; this.projectCount = projectCount; this.universityCount = universityCount; this.partnerImageUrl = partnerImageUrl; this.introYoutubeLink = introYoutubeLink; + this.planningImageUrl = planningImageUrl; + this.designImageUrl = designImageUrl; + this.frontendImageUrl = frontendImageUrl; + this.backendImageUrl = backendImageUrl; } - -} +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/entity/PartnerLogo.java b/src/main/java/com/kusitms/website/domain/introduction/entity/PartnerLogo.java new file mode 100644 index 0000000..bfbeab4 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/entity/PartnerLogo.java @@ -0,0 +1,31 @@ +package com.kusitms.website.domain.introduction.entity; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PartnerLogo { + @Id + @Column(name = "partner_logo_id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long partnerLogoId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "introduction_id") + private Introduction introduction; + + @Column(name = "image_url") + private String imageUrl; + + @Builder + public PartnerLogo(Introduction introduction, String imageUrl) { + this.introduction = introduction; + this.imageUrl = imageUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/entity/Sponsor.java b/src/main/java/com/kusitms/website/domain/introduction/entity/Sponsor.java new file mode 100644 index 0000000..22d6277 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/entity/Sponsor.java @@ -0,0 +1,31 @@ +package com.kusitms.website.domain.introduction.entity; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Sponsor { + @Id + @Column(name = "sponsor_id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long sponsorId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "introduction_id") + private Introduction introduction; + + @Column(name = "image_url") + private String imageUrl; + + @Builder + public Sponsor(Introduction introduction, String imageUrl) { + this.introduction = introduction; + this.imageUrl = imageUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/ActivityRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/ActivityRepository.java new file mode 100644 index 0000000..957bfc3 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/ActivityRepository.java @@ -0,0 +1,9 @@ +package com.kusitms.website.domain.introduction.repository; + +import com.kusitms.website.domain.introduction.entity.Activity; +import com.kusitms.website.domain.introduction.entity.Introduction; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ActivityRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/ExpertLectureRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/ExpertLectureRepository.java index a1e210a..e91d0d7 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/repository/ExpertLectureRepository.java +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/ExpertLectureRepository.java @@ -1,7 +1,9 @@ package com.kusitms.website.domain.introduction.repository; import com.kusitms.website.domain.introduction.entity.ExpertLecture; +import com.kusitms.website.domain.introduction.entity.Introduction; import org.springframework.data.jpa.repository.JpaRepository; public interface ExpertLectureRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); } diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/IntroMeetupImageRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/IntroMeetupImageRepository.java new file mode 100644 index 0000000..cd141f6 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/IntroMeetupImageRepository.java @@ -0,0 +1,9 @@ +package com.kusitms.website.domain.introduction.repository; + +import com.kusitms.website.domain.introduction.entity.IntroMeetupImage; +import com.kusitms.website.domain.introduction.entity.Introduction; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface IntroMeetupImageRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/ManageTeamRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/ManageTeamRepository.java index 180c6b1..73a38fc 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/repository/ManageTeamRepository.java +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/ManageTeamRepository.java @@ -1,7 +1,9 @@ package com.kusitms.website.domain.introduction.repository; +import com.kusitms.website.domain.introduction.entity.Introduction; import com.kusitms.website.domain.introduction.entity.ManageTeam; import org.springframework.data.jpa.repository.JpaRepository; public interface ManageTeamRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); } diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/OBLectureRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/OBLectureRepository.java index 67231d2..9ce009f 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/repository/OBLectureRepository.java +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/OBLectureRepository.java @@ -1,7 +1,9 @@ package com.kusitms.website.domain.introduction.repository; +import com.kusitms.website.domain.introduction.entity.Introduction; import com.kusitms.website.domain.introduction.entity.OBLecture; import org.springframework.data.jpa.repository.JpaRepository; public interface OBLectureRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); } diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/PartnerLogoRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/PartnerLogoRepository.java new file mode 100644 index 0000000..ab2bc34 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/PartnerLogoRepository.java @@ -0,0 +1,9 @@ +package com.kusitms.website.domain.introduction.repository; + +import com.kusitms.website.domain.introduction.entity.Introduction; +import com.kusitms.website.domain.introduction.entity.PartnerLogo; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PartnerLogoRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/repository/SponsorRepository.java b/src/main/java/com/kusitms/website/domain/introduction/repository/SponsorRepository.java new file mode 100644 index 0000000..d4f218a --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/repository/SponsorRepository.java @@ -0,0 +1,9 @@ +package com.kusitms.website.domain.introduction.repository; + +import com.kusitms.website.domain.introduction.entity.Introduction; +import com.kusitms.website.domain.introduction.entity.Sponsor; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SponsorRepository extends JpaRepository { + void deleteByIntroduction(Introduction introduction); +} \ No newline at end of file From 8d608a6517c2f6bb829dedbb6846d74f6971fea7 Mon Sep 17 00:00:00 2001 From: Hoyeon Lee <89958157+howooyeon@users.noreply.github.com> Date: Wed, 13 May 2026 00:57:35 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat=20:=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=ED=95=99=ED=9A=8C=20=EC=86=8C=EA=B0=9C=20=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?API=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../website/domain/admin/AdminController.java | 10 + .../domain/introduction/IntroService.java | 251 ++++++++++++++---- .../dto/request/ActivityRequest.java | 36 +++ .../dto/request/IntroRequest.java | 57 +++- .../dto/response/ActivityResponse.java | 35 +++ .../dto/response/AdminIntroResponse.java | 118 ++++++++ .../dto/response/IntroResponse.java | 71 ++++- 7 files changed, 503 insertions(+), 75 deletions(-) create mode 100644 src/main/java/com/kusitms/website/domain/introduction/dto/request/ActivityRequest.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/dto/response/ActivityResponse.java create mode 100644 src/main/java/com/kusitms/website/domain/introduction/dto/response/AdminIntroResponse.java diff --git a/src/main/java/com/kusitms/website/domain/admin/AdminController.java b/src/main/java/com/kusitms/website/domain/admin/AdminController.java index 17e1a35..2db0631 100644 --- a/src/main/java/com/kusitms/website/domain/admin/AdminController.java +++ b/src/main/java/com/kusitms/website/domain/admin/AdminController.java @@ -29,6 +29,16 @@ public class AdminController { private final AdminService adminService; private final JwtTokenProvider jwtTokenProvider; + @GetMapping("/admin/introductions") + @Operation(summary = "학회 소개 정보 조회", description = "학회 소개 페이지의 현재 저장된 정보를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "500", description = "INTER SERVER ERROR", content = @Content(schema = @Schema(implementation = BaseResponse.class))), + }) + public ResponseEntity getIntroduction() { + return ResponseEntity.ok(new BaseResponse(introService.getAdminIntroduction())); + } + @Hidden @PostMapping(value = "/admin/introductions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity addIntroduction(@ModelAttribute IntroRequest request) { diff --git a/src/main/java/com/kusitms/website/domain/introduction/IntroService.java b/src/main/java/com/kusitms/website/domain/introduction/IntroService.java index 516f36d..f173002 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/IntroService.java +++ b/src/main/java/com/kusitms/website/domain/introduction/IntroService.java @@ -1,28 +1,22 @@ package com.kusitms.website.domain.introduction; import com.kusitms.website.domain.file.S3Service; +import com.kusitms.website.domain.introduction.dto.request.ActivityRequest; import com.kusitms.website.domain.introduction.dto.request.ExpertLectureRequest; import com.kusitms.website.domain.introduction.dto.request.IntroRequest; import com.kusitms.website.domain.introduction.dto.request.ManagementTeamRequest; import com.kusitms.website.domain.introduction.dto.request.OBLectureRequest; -import com.kusitms.website.domain.introduction.dto.response.ExpertLectureResponse; -import com.kusitms.website.domain.introduction.dto.response.IntroResponse; -import com.kusitms.website.domain.introduction.dto.response.ManagementTeamResponse; -import com.kusitms.website.domain.introduction.dto.response.OBLectureResponse; -import com.kusitms.website.domain.introduction.entity.ExpertLecture; -import com.kusitms.website.domain.introduction.entity.Introduction; -import com.kusitms.website.domain.introduction.entity.ManageTeam; -import com.kusitms.website.domain.introduction.entity.OBLecture; -import com.kusitms.website.domain.introduction.repository.ExpertLectureRepository; -import com.kusitms.website.domain.introduction.repository.IntroRepository; -import com.kusitms.website.domain.introduction.repository.ManageTeamRepository; -import com.kusitms.website.domain.introduction.repository.OBLectureRepository; +import com.kusitms.website.domain.introduction.dto.response.*; +import com.kusitms.website.domain.introduction.entity.*; +import com.kusitms.website.domain.introduction.repository.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import java.util.List; import java.util.stream.Collectors; +import javax.persistence.EntityNotFoundException; @Service @RequiredArgsConstructor @@ -34,90 +28,241 @@ public class IntroService { private final ManageTeamRepository manageTeamRepository; private final ExpertLectureRepository expertLectureRepository; private final OBLectureRepository obLectureRepository; - + private final PartnerLogoRepository partnerLogoRepository; + private final IntroMeetupImageRepository introMeetupImageRepository; + private final ActivityRepository activityRepository; + private final SponsorRepository sponsorRepository; private final String dirName = "intro"; @Transactional(readOnly = true) public IntroResponse getIntroduction() { - // 학회 소개 페이지 정보는 단일 - Introduction intro = introRepository.findAll().get(0); + Introduction intro = introRepository.findAll().stream().findFirst() + .orElseThrow(() -> new EntityNotFoundException("학회 소개 정보가 존재하지 않습니다.")); List managementTeamResponses = intro.getManageTeam().stream() - .map(ManagementTeamResponse :: fromEntity) + .map(ManagementTeamResponse::fromEntity) .collect(Collectors.toList()); List expertLectureResponses = intro.getExpertLecture().stream() - .map(ExpertLectureResponse :: fromEntity) + .map(ExpertLectureResponse::fromEntity) .collect(Collectors.toList()); List obLectureResponses = intro.getObLecture().stream() - .map(OBLectureResponse :: fromEntity) + .map(OBLectureResponse::fromEntity) + .collect(Collectors.toList()); + + List partnerLogoUrls = intro.getPartnerLogos().stream() + .map(PartnerLogo::getImageUrl) .collect(Collectors.toList()); - return IntroResponse.fromEntity(intro, managementTeamResponses, expertLectureResponses, obLectureResponses); + List meetupImageUrls = intro.getMeetupImages().stream() + .map(IntroMeetupImage::getImageUrl) + .collect(Collectors.toList()); + + List activityResponses = intro.getActivities().stream() + .map(ActivityResponse::fromEntity) + .collect(Collectors.toList()); + + List sponsorImageUrls = intro.getSponsors().stream() + .map(Sponsor::getImageUrl) + .collect(Collectors.toList()); + + return IntroResponse.fromEntity(intro, partnerLogoUrls, meetupImageUrls, + managementTeamResponses, expertLectureResponses, obLectureResponses, + activityResponses, sponsorImageUrls); } - @Transactional() - public void save(IntroRequest request) { - String partnerImageUrl = s3Service.uploadFile(request.getPartnerLogoFile(), dirName); - Introduction introduction = IntroRequest.from(request, partnerImageUrl); - introRepository.save(introduction); + @Transactional(readOnly = true) + public AdminIntroResponse getAdminIntroduction() { + Introduction intro = introRepository.findAll().stream().findFirst() + .orElseThrow(() -> new EntityNotFoundException("학회 소개 정보가 존재하지 않습니다.")); + + List teams = intro.getManageTeam().stream() + .map(ManagementTeamResponse::fromEntity) + .collect(Collectors.toList()); - List manageTeam = request.getTeams().stream() - .map(team -> ManagementTeamRequest.from(team, s3Service.uploadFile(team.getImageFile(), dirName), introduction)) + List expertLectures = intro.getExpertLecture().stream() + .map(ExpertLectureResponse::fromEntity) .collect(Collectors.toList()); - List expertLecture = request.getExpertLecture().stream() - .map(lecture -> ExpertLectureRequest.from(lecture, s3Service.uploadFile(lecture.getImageFile(), dirName), introduction)) + List obLectures = intro.getObLecture().stream() + .map(OBLectureResponse::fromEntity) .collect(Collectors.toList()); - List obLecture = request.getObLecture().stream() - .map(lecture -> OBLectureRequest.from(lecture, s3Service.uploadFile(lecture.getImageFile(), dirName), introduction)) + List partnerLogoUrls = intro.getPartnerLogos().stream() + .map(PartnerLogo::getImageUrl) .collect(Collectors.toList()); - manageTeamRepository.saveAll(manageTeam); - expertLectureRepository.saveAll(expertLecture); - obLectureRepository.saveAll(obLecture); + List meetupImageUrls = intro.getMeetupImages().stream() + .map(IntroMeetupImage::getImageUrl) + .collect(Collectors.toList()); + + List activityResponses = intro.getActivities().stream() + .map(ActivityResponse::fromEntity) + .collect(Collectors.toList()); + + List sponsorImageUrls = intro.getSponsors().stream() + .map(Sponsor::getImageUrl) + .collect(Collectors.toList()); + + return AdminIntroResponse.fromEntity(intro, partnerLogoUrls, meetupImageUrls, + activityResponses, teams, expertLectures, obLectures, sponsorImageUrls); + } + + @Transactional + public void save(IntroRequest request) { + String bannerImageUrl = uploadIfPresent(request.getBannerImageFile()); + String planningImageUrl = uploadIfPresent(request.getPlanningImage()); + String designImageUrl = uploadIfPresent(request.getDesignImage()); + String frontendImageUrl = uploadIfPresent(request.getFrontendImage()); + String backendImageUrl = uploadIfPresent(request.getBackendImage()); + + Introduction introduction = IntroRequest.from(request, null, + bannerImageUrl, planningImageUrl, designImageUrl, frontendImageUrl, backendImageUrl); + introRepository.save(introduction); - return; + saveManageTeams(request, introduction); + saveExpertLectures(request, introduction); + saveOBLectures(request, introduction); + savePartnerLogos(request.getPartnerLogoFiles(), introduction); + saveMeetupImages(request.getMeetupImages(), introduction); + saveActivities(request.getActivities(), introduction); + saveSponsors(request.getSponsors(), introduction); } - @Transactional() + @Transactional public void updateIntroduction(IntroRequest request) { - String partnerImageUrl = s3Service.uploadFile(request.getPartnerLogoFile(), dirName); - Introduction introduction = introRepository.findAll().get(0); + Introduction introduction = introRepository.findAll().stream().findFirst() + .orElseThrow(() -> new EntityNotFoundException("학회 소개 정보가 존재하지 않습니다.")); + + String bannerImageUrl = uploadOrKeep(request.getBannerImageFile(), introduction.getBannerImageUrl()); + String planningImageUrl = uploadOrKeep(request.getPlanningImage(), introduction.getPlanningImageUrl()); + String designImageUrl = uploadOrKeep(request.getDesignImage(), introduction.getDesignImageUrl()); + String frontendImageUrl = uploadOrKeep(request.getFrontendImage(), introduction.getFrontendImageUrl()); + String backendImageUrl = uploadOrKeep(request.getBackendImage(), introduction.getBackendImageUrl()); + introduction.update(request.getBannerCardinal(), request.getBannerStatus(), + request.getSlogan(), + bannerImageUrl, request.getMemberCount(), request.getProjectCount(), request.getUniversityCount(), - partnerImageUrl, - request.getIntroYoutubeLink()); + null, + request.getIntroYoutubeLink(), + planningImageUrl, + designImageUrl, + frontendImageUrl, + backendImageUrl); introRepository.save(introduction); - manageTeamRepository.deleteAll(); - expertLectureRepository.deleteAll(); - obLectureRepository.deleteAll(); + manageTeamRepository.deleteByIntroduction(introduction); + expertLectureRepository.deleteByIntroduction(introduction); + obLectureRepository.deleteByIntroduction(introduction); + partnerLogoRepository.deleteByIntroduction(introduction); + introMeetupImageRepository.deleteByIntroduction(introduction); + activityRepository.deleteByIntroduction(introduction); + sponsorRepository.deleteByIntroduction(introduction); + + saveManageTeams(request, introduction); + saveExpertLectures(request, introduction); + saveOBLectures(request, introduction); + savePartnerLogos(request.getPartnerLogoFiles(), introduction); + saveMeetupImages(request.getMeetupImages(), introduction); + saveActivities(request.getActivities(), introduction); + saveSponsors(request.getSponsors(), introduction); + } + + private void saveManageTeams(IntroRequest request, Introduction introduction) { + if (request.getTeams() == null) return; + List manageTeams = request.getTeams().stream() + .map(team -> { + String imageUrl = uploadIfPresent(team.getImageFile()); + return ManagementTeamRequest.from(team, imageUrl, introduction); + }) + .collect(Collectors.toList()); + manageTeamRepository.saveAll(manageTeams); + } + + private void saveExpertLectures(IntroRequest request, Introduction introduction) { + if (request.getExpertLecture() == null) return; + List expertLectures = request.getExpertLecture().stream() + .map(lecture -> { + String imageUrl = uploadIfPresent(lecture.getImageFile()); + return ExpertLectureRequest.from(lecture, imageUrl, introduction); + }) + .collect(Collectors.toList()); + expertLectureRepository.saveAll(expertLectures); + } - List manageTeam = request.getTeams().stream() - .map(team -> ManagementTeamRequest.from(team, s3Service.uploadFile(team.getImageFile(), dirName), introduction)) + private void saveOBLectures(IntroRequest request, Introduction introduction) { + if (request.getObLecture() == null) return; + List obLectures = request.getObLecture().stream() + .map(lecture -> { + String imageUrl = uploadIfPresent(lecture.getImageFile()); + return OBLectureRequest.from(lecture, imageUrl, introduction); + }) .collect(Collectors.toList()); + obLectureRepository.saveAll(obLectures); + } - List expertLecture = request.getExpertLecture().stream() - .map(lecture -> ExpertLectureRequest.from(lecture, s3Service.uploadFile(lecture.getImageFile(), dirName), introduction)) + private void savePartnerLogos(List files, Introduction introduction) { + if (files == null) return; + List logos = files.stream() + .filter(f -> f != null && !f.isEmpty()) + .map(f -> PartnerLogo.builder() + .introduction(introduction) + .imageUrl(s3Service.uploadFile(f, dirName)) + .build()) .collect(Collectors.toList()); + partnerLogoRepository.saveAll(logos); + } - List obLecture = request.getObLecture().stream() - .map(lecture -> OBLectureRequest.from(lecture, s3Service.uploadFile(lecture.getImageFile(), dirName), introduction)) + private void saveMeetupImages(List files, Introduction introduction) { + if (files == null) return; + List images = files.stream() + .filter(f -> f != null && !f.isEmpty()) + .map(f -> IntroMeetupImage.builder() + .introduction(introduction) + .imageUrl(s3Service.uploadFile(f, dirName)) + .build()) .collect(Collectors.toList()); + introMeetupImageRepository.saveAll(images); + } - manageTeamRepository.saveAll(manageTeam); - expertLectureRepository.saveAll(expertLecture); - obLectureRepository.saveAll(obLecture); + private void saveActivities(List activityRequests, Introduction introduction) { + if (activityRequests == null) return; + List activities = activityRequests.stream() + .map(req -> { + String imageUrl1 = uploadIfPresent(req.getImageFile1()); + String imageUrl2 = uploadIfPresent(req.getImageFile2()); + return ActivityRequest.from(req, imageUrl1, imageUrl2, introduction); + }) + .collect(Collectors.toList()); + activityRepository.saveAll(activities); + } - return; + private void saveSponsors(List files, Introduction introduction) { + if (files == null) return; + List sponsors = files.stream() + .filter(f -> f != null && !f.isEmpty()) + .map(f -> Sponsor.builder() + .introduction(introduction) + .imageUrl(s3Service.uploadFile(f, dirName)) + .build()) + .collect(Collectors.toList()); + sponsorRepository.saveAll(sponsors); } -} + private String uploadIfPresent(MultipartFile file) { + if (file == null || file.isEmpty()) return null; + return s3Service.uploadFile(file, dirName); + } + + private String uploadOrKeep(MultipartFile file, String existingUrl) { + if (file == null || file.isEmpty()) return existingUrl; + return s3Service.uploadFile(file, dirName); + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/dto/request/ActivityRequest.java b/src/main/java/com/kusitms/website/domain/introduction/dto/request/ActivityRequest.java new file mode 100644 index 0000000..128dff5 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/dto/request/ActivityRequest.java @@ -0,0 +1,36 @@ +package com.kusitms.website.domain.introduction.dto.request; + +import com.kusitms.website.domain.introduction.entity.Activity; +import com.kusitms.website.domain.introduction.entity.Introduction; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import org.springframework.web.multipart.MultipartFile; + +@Getter +@Setter +@Schema +public class ActivityRequest { + @Schema(description = "활동명", example = "밋업데이") + private String name; + + @Schema(description = "활동 이미지 1") + private MultipartFile imageFile1; + + @Schema(description = "활동 이미지 2") + private MultipartFile imageFile2; + + @Schema(description = "활동 설명글", example = "밋업데이는 ~입니다.") + private String description; + + public static Activity from(ActivityRequest request, String imageUrl1, String imageUrl2, + Introduction introduction) { + return Activity.builder() + .name(request.getName()) + .imageUrl1(imageUrl1) + .imageUrl2(imageUrl2) + .description(request.getDescription()) + .introduction(introduction) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/dto/request/IntroRequest.java b/src/main/java/com/kusitms/website/domain/introduction/dto/request/IntroRequest.java index 97d7ee7..cbdc618 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/dto/request/IntroRequest.java +++ b/src/main/java/com/kusitms/website/domain/introduction/dto/request/IntroRequest.java @@ -7,20 +7,25 @@ import lombok.Setter; import org.springframework.web.multipart.MultipartFile; -import java.util.ArrayList; import java.util.List; @Getter @Setter -@Schema +@Schema(description = "학회 소개 요청") public class IntroRequest { @Schema(description = "배너 내에 삽입되는 기수", example = "27") private Long bannerCardinal; - @Schema(description = "배너 상태 (대문자 영문 코드)", example = "CLOSE/MANAGEMENT_RECRUIT/MEMBER_RECRUIT") + @Schema(description = "배너 상태 (대문자 영문 코드)", example = "CLOSE") private BannerStatus bannerStatus; - @Schema(description = "누적 학회원 수 ", example = "1432") + @Schema(description = "슬로건", example = "큐시즘, 함께 성장하는 IT 학회") + private String slogan; + + @Schema(description = "배너 이미지 파일") + private MultipartFile bannerImageFile; + + @Schema(description = "누적 학회원 수", example = "1432") private Long memberCount; @Schema(description = "누적 프로젝트 결과물 수", example = "322") @@ -32,27 +37,57 @@ public class IntroRequest { @Schema(description = "학회 소개 영상", example = "https://www.youtube.com/") private String introYoutubeLink; + @Schema(description = "기획 이미지 파일") + private MultipartFile planningImage; + + @Schema(description = "디자인 이미지 파일") + private MultipartFile designImage; + + @Schema(description = "프론트 이미지 파일") + private MultipartFile frontendImage; + + @Schema(description = "백엔드 이미지 파일") + private MultipartFile backendImage; + @Schema(description = "학회 운영진 소개") - private List teams = new ArrayList<>();; + private List teams; @Schema(description = "전문가 초청 강연자 소개") - private List expertLecture = new ArrayList<>(); + private List expertLecture; + + @Schema(description = "OB 초청 강연자 소개") + private List obLecture; + + @Schema(description = "파트너사 로고 이미지 파일 목록") + private List partnerLogoFiles; + + @Schema(description = "밋업 이미지 파일 목록") + private List meetupImages; - @Schema(description = "ob 초청 강연자 소개") - private List obLecture = new ArrayList<>(); + @Schema(description = "활동 소개 목록") + private List activities; - @Schema(description = "파트너사 소개 이미지 파일") - private MultipartFile partnerLogoFile; + @Schema(description = "후원사 이미지 파일 목록") + private List sponsors; - public static Introduction from(IntroRequest request, String partnerImageUrl) { + public static Introduction from(IntroRequest request, String partnerImageUrl, + String bannerImageUrl, + String planningImageUrl, String designImageUrl, + String frontendImageUrl, String backendImageUrl) { return Introduction.builder() .bannerCardinal(request.getBannerCardinal()) .bannerStatus(request.getBannerStatus()) + .slogan(request.getSlogan()) + .bannerImageUrl(bannerImageUrl) .memberCount(request.getMemberCount()) .projectCount(request.getProjectCount()) .universityCount(request.getUniversityCount()) .introYoutubeLink(request.getIntroYoutubeLink()) .partnerImageUrl(partnerImageUrl) + .planningImageUrl(planningImageUrl) + .designImageUrl(designImageUrl) + .frontendImageUrl(frontendImageUrl) + .backendImageUrl(backendImageUrl) .build(); } } diff --git a/src/main/java/com/kusitms/website/domain/introduction/dto/response/ActivityResponse.java b/src/main/java/com/kusitms/website/domain/introduction/dto/response/ActivityResponse.java new file mode 100644 index 0000000..ae39821 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/dto/response/ActivityResponse.java @@ -0,0 +1,35 @@ +package com.kusitms.website.domain.introduction.dto.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.kusitms.website.domain.introduction.entity.Activity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@Schema +public class ActivityResponse { + @Schema(description = "활동명", example = "밋업데이") + private String name; + + @JsonProperty("image_url1") + @Schema(description = "활동 이미지 1 URL") + private String imageUrl1; + + @JsonProperty("image_url2") + @Schema(description = "활동 이미지 2 URL") + private String imageUrl2; + + @Schema(description = "활동 설명글") + private String description; + + public static ActivityResponse fromEntity(Activity activity) { + return ActivityResponse.builder() + .name(activity.getName()) + .imageUrl1(activity.getImageUrl1()) + .imageUrl2(activity.getImageUrl2()) + .description(activity.getDescription()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/dto/response/AdminIntroResponse.java b/src/main/java/com/kusitms/website/domain/introduction/dto/response/AdminIntroResponse.java new file mode 100644 index 0000000..cb0d9a9 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/introduction/dto/response/AdminIntroResponse.java @@ -0,0 +1,118 @@ +package com.kusitms.website.domain.introduction.dto.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.kusitms.website.domain.introduction.entity.Introduction; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +@Schema +public class AdminIntroResponse { + @JsonProperty("banner_cardinal") + @Schema(description = "배너 기수") + private Long bannerCardinal; + + @JsonProperty("banner_status") + @Schema(description = "배너 상태") + private String bannerStatus; + + @Schema(description = "슬로건") + private String slogan; + + @JsonProperty("banner_image_url") + @Schema(description = "배너 이미지 URL") + private String bannerImageUrl; + + @JsonProperty("member_count") + @Schema(description = "누적 학회원 수") + private Long memberCount; + + @JsonProperty("project_count") + @Schema(description = "누적 프로젝트 수") + private Long projectCount; + + @JsonProperty("university_count") + @Schema(description = "참여 대학 수") + private Long universityCount; + + @JsonProperty("intro_youtube_link") + @Schema(description = "학회 소개 영상") + private String introYoutubeLink; + + @JsonProperty("planning_image_url") + @Schema(description = "기획 이미지 URL") + private String planningImageUrl; + + @JsonProperty("design_image_url") + @Schema(description = "디자인 이미지 URL") + private String designImageUrl; + + @JsonProperty("frontend_image_url") + @Schema(description = "프론트 이미지 URL") + private String frontendImageUrl; + + @JsonProperty("backend_image_url") + @Schema(description = "백엔드 이미지 URL") + private String backendImageUrl; + + @JsonProperty("partner_logo_urls") + @Schema(description = "파트너사 로고 이미지 URL 목록") + private List partnerLogoUrls; + + @JsonProperty("meetup_image_urls") + @Schema(description = "밋업 이미지 URL 목록") + private List meetupImageUrls; + + @Schema(description = "활동 소개 목록") + private List activities; + + @Schema(description = "운영진 소개") + private List teams; + + @JsonProperty("expert_lecture") + @Schema(description = "전문가 초청 강연자 소개") + private List expertLecture; + + @JsonProperty("ob_lecture") + @Schema(description = "OB 초청 강연자 소개") + private List obLecture; + + @JsonProperty("sponsor_image_urls") + @Schema(description = "후원사 이미지 URL 목록") + private List sponsorImageUrls; + + public static AdminIntroResponse fromEntity(Introduction intro, + List partnerLogoUrls, + List meetupImageUrls, + List activities, + List teams, + List expertLecture, + List obLecture, + List sponsorImageUrls) { + return AdminIntroResponse.builder() + .bannerCardinal(intro.getBannerCardinal()) + .bannerStatus(intro.getBannerStatus() != null ? intro.getBannerStatus().name() : null) + .slogan(intro.getSlogan()) + .bannerImageUrl(intro.getBannerImageUrl()) + .memberCount(intro.getMemberCount()) + .projectCount(intro.getProjectCount()) + .universityCount(intro.getUniversityCount()) + .introYoutubeLink(intro.getIntroYoutubeLink()) + .planningImageUrl(intro.getPlanningImageUrl()) + .designImageUrl(intro.getDesignImageUrl()) + .frontendImageUrl(intro.getFrontendImageUrl()) + .backendImageUrl(intro.getBackendImageUrl()) + .partnerLogoUrls(partnerLogoUrls) + .meetupImageUrls(meetupImageUrls) + .activities(activities) + .teams(teams) + .expertLecture(expertLecture) + .obLecture(obLecture) + .sponsorImageUrls(sponsorImageUrls) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kusitms/website/domain/introduction/dto/response/IntroResponse.java b/src/main/java/com/kusitms/website/domain/introduction/dto/response/IntroResponse.java index 8220775..2a0c1c1 100644 --- a/src/main/java/com/kusitms/website/domain/introduction/dto/response/IntroResponse.java +++ b/src/main/java/com/kusitms/website/domain/introduction/dto/response/IntroResponse.java @@ -20,6 +20,13 @@ public class IntroResponse { @Schema(description = "배너 내용", example = "KUSITMS 27기 리크루팅 종료") private String bannerContent; + @Schema(description = "슬로건") + private String slogan; + + @JsonProperty("banner_image_url") + @Schema(description = "배너 이미지 URL") + private String bannerImageUrl; + @JsonProperty("member_count") @Schema(description = "누적 학회원 수", example = "1432") private Long memberCount; @@ -36,9 +43,29 @@ public class IntroResponse { @Schema(description = "학회 소개 영상", example = "https://www.youtube.com/") private String introYoutubeLink; - @JsonProperty("parent_logo_url") - @Schema(description = "파트너사 소개 이미지 URL") - private String partnerLogoUrl; + @JsonProperty("planning_image_url") + @Schema(description = "기획 이미지 URL") + private String planningImageUrl; + + @JsonProperty("design_image_url") + @Schema(description = "디자인 이미지 URL") + private String designImageUrl; + + @JsonProperty("frontend_image_url") + @Schema(description = "프론트 이미지 URL") + private String frontendImageUrl; + + @JsonProperty("backend_image_url") + @Schema(description = "백엔드 이미지 URL") + private String backendImageUrl; + + @JsonProperty("partner_logo_urls") + @Schema(description = "파트너사 로고 이미지 URL 목록") + private List partnerLogoUrls; + + @JsonProperty("meetup_image_urls") + @Schema(description = "밋업 이미지 URL 목록") + private List meetupImageUrls; @Schema(description = "학회 운영진 소개") private List teams; @@ -51,21 +78,43 @@ public class IntroResponse { @Schema(description = "ob 초청 강연자 소개") private List obLecture; - public static IntroResponse fromEntity(Introduction introduction, List managementTeam, - List expertLecture, List obLecture) { + @Schema(description = "활동 소개 목록") + private List activities; + + @JsonProperty("sponsor_image_urls") + @Schema(description = "후원사 이미지 URL 목록") + private List sponsorImageUrls; + + public static IntroResponse fromEntity(Introduction introduction, + List partnerLogoUrls, + List meetupImageUrls, + List managementTeam, + List expertLecture, + List obLecture, + List activities, + List sponsorImageUrls) { return IntroResponse.builder() - .bannerStatus(introduction.getBannerStatus().getName()) - .bannerContent("KUSITMS" - + introduction.getBannerCardinal() + "기 " - + introduction.getBannerStatus().getContent()) + .bannerStatus(introduction.getBannerStatus() != null ? introduction.getBannerStatus().getName() : null) + .bannerContent(introduction.getBannerStatus() != null + ? "KUSITMS" + introduction.getBannerCardinal() + "기 " + introduction.getBannerStatus().getContent() + : null) + .slogan(introduction.getSlogan()) + .bannerImageUrl(introduction.getBannerImageUrl()) .memberCount(introduction.getMemberCount()) .projectCount(introduction.getProjectCount()) .universityCount(introduction.getUniversityCount()) .introYoutubeLink(introduction.getIntroYoutubeLink()) - .partnerLogoUrl(introduction.getPartnerImageUrl()) + .planningImageUrl(introduction.getPlanningImageUrl()) + .designImageUrl(introduction.getDesignImageUrl()) + .frontendImageUrl(introduction.getFrontendImageUrl()) + .backendImageUrl(introduction.getBackendImageUrl()) + .partnerLogoUrls(partnerLogoUrls) + .meetupImageUrls(meetupImageUrls) .teams(managementTeam) .expertLecture(expertLecture) .obLecture(obLecture) + .activities(activities) + .sponsorImageUrls(sponsorImageUrls) .build(); } -} +} \ No newline at end of file From 1e60c5cce441ce266019878a77611be70b5248ad Mon Sep 17 00:00:00 2001 From: Hoyeon Lee <89958157+howooyeon@users.noreply.github.com> Date: Wed, 13 May 2026 01:08:17 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat=20:=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=EB=B0=8B=EC=97=85=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/admin/entity/TMPMeetupProject.java | 9 +- .../project/dto/request/MeetupRequest.java | 4 + .../dto/response/MeetupDetailResponse.java | 1 + .../dto/response/MeetupTeamResponse.java | 151 +++++------------- 4 files changed, 54 insertions(+), 111 deletions(-) diff --git a/src/main/java/com/kusitms/website/domain/admin/entity/TMPMeetupProject.java b/src/main/java/com/kusitms/website/domain/admin/entity/TMPMeetupProject.java index c6fb552..fb5b31e 100644 --- a/src/main/java/com/kusitms/website/domain/admin/entity/TMPMeetupProject.java +++ b/src/main/java/com/kusitms/website/domain/admin/entity/TMPMeetupProject.java @@ -49,6 +49,9 @@ public class TMPMeetupProject { @Column(name = "app_url") private String appUrl; + @Column(name = "behance_url") + private String behanceUrl; + @Column(name = "start_date", nullable = false) private LocalDate startDate; @@ -64,7 +67,7 @@ public class TMPMeetupProject { @Builder public TMPMeetupProject(int cardinal, String name, String intro, ProjectType type, String oneLineIntro, String logoUrl, String posterUrl, String instagramUrl, String githubUrl, String appUrl, - LocalDate startDate, LocalDate endDate, String teamName) { + String behanceUrl, LocalDate startDate, LocalDate endDate, String teamName) { this.cardinal = cardinal; this.name = name; this.intro = intro; @@ -75,6 +78,7 @@ public TMPMeetupProject(int cardinal, String name, String intro, ProjectType typ this.instagramUrl = instagramUrl; this.githubUrl = githubUrl; this.appUrl = appUrl; + this.behanceUrl = behanceUrl; this.startDate = startDate; this.endDate = endDate; this.teamName = teamName; @@ -82,7 +86,7 @@ public TMPMeetupProject(int cardinal, String name, String intro, ProjectType typ public void update(int cardinal, String name, String intro, ProjectType type, String oneLineIntro, String logoUrl, String posterUrl, String instagramUrl, String githubUrl, String appUrl, - LocalDate startDate, LocalDate endDate, String teamName) { + String behanceUrl, LocalDate startDate, LocalDate endDate, String teamName) { this.cardinal = cardinal; this.name = name; this.intro = intro; @@ -93,6 +97,7 @@ public void update(int cardinal, String name, String intro, ProjectType type, St this.instagramUrl = instagramUrl; this.githubUrl = githubUrl; this.appUrl = appUrl; + this.behanceUrl = behanceUrl; this.startDate = startDate; this.endDate = endDate; this.teamName = teamName; diff --git a/src/main/java/com/kusitms/website/domain/project/dto/request/MeetupRequest.java b/src/main/java/com/kusitms/website/domain/project/dto/request/MeetupRequest.java index a743b18..c473cf5 100644 --- a/src/main/java/com/kusitms/website/domain/project/dto/request/MeetupRequest.java +++ b/src/main/java/com/kusitms/website/domain/project/dto/request/MeetupRequest.java @@ -43,6 +43,9 @@ public class MeetupRequest { @Schema(description = "프로젝트 결과물 URL", example = "https://github.com/kusitms-com") private String appUrl; + @Schema(description = "비핸스 URL", example = "https://www.behance.net/") + private String behanceUrl; + @Schema(description = "프로젝트 시작 날짜", example = "2022-02-12") private String startDate; @@ -86,6 +89,7 @@ public static TMPMeetupProject from(MeetupRequest request, String logoUrl, Strin .instagramUrl(request.getInstagramUrl()) .githubUrl(request.getGithubUrl()) .appUrl(request.getAppUrl()) + .behanceUrl(request.getBehanceUrl()) .startDate(LocalDate.parse(request.getStartDate(), DateTimeFormatter.ISO_DATE)) .endDate(LocalDate.parse(request.getEndDate(), DateTimeFormatter.ISO_DATE)) .logoUrl(logoUrl) diff --git a/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupDetailResponse.java b/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupDetailResponse.java index 985cd25..69a40e1 100644 --- a/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupDetailResponse.java +++ b/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupDetailResponse.java @@ -114,6 +114,7 @@ public MeetupDetailResponse(TMPMeetupProject meetup, boolean isDetail) { this.posterUrl = s3Url + meetup.getPosterUrl(); this.logoUrl = s3Url + meetup.getLogoUrl(); this.oneLineIntro = meetup.getOneLineIntro(); + this.behanceUrl = meetup.getBehanceUrl(); this.instagramUrl = meetup.getInstagramUrl(); this.githubUrl = meetup.getGithubUrl(); this.appUrl = meetup.getAppUrl(); diff --git a/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupTeamResponse.java b/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupTeamResponse.java index 59b7e51..3e02457 100644 --- a/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupTeamResponse.java +++ b/src/main/java/com/kusitms/website/domain/project/dto/response/MeetupTeamResponse.java @@ -2,6 +2,7 @@ import com.kusitms.website.domain.admin.entity.TMPMeetupTeam; import com.kusitms.website.domain.project.entity.MeetupTeam; +import com.kusitms.website.domain.project.entity.Team; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; @@ -29,123 +30,55 @@ public class MeetupTeamResponse { public MeetupTeamResponse(List team, String name) { this.name = name; - getMember(team); + for (MeetupTeam t : team) { + addMember(t.getTeam(), t.getName()); + } + sortAll(); } public MeetupTeamResponse(String name, List team) { this.name = name; - getTMPMember(team); - } - - private void getMember(List team) { - for(MeetupTeam t : team) { - switch(t.getTeam()) { - case PLANNER: - if(planner == null) { - planner = new ArrayList<>(); - } - planner.add(t.getName()); - break; - case DESIGNER: - if(designer == null) { - designer = new ArrayList<>(); - } - designer.add(t.getName()); - break; - case FRONTEND: - if(frontend == null) { - frontend = new ArrayList<>(); - } - frontend.add(t.getName()); - break; - case BACKEND: - if(backend == null) { - backend = new ArrayList<>(); - } - backend.add(t.getName()); - break; - case IOS: - if(ios == null) { - ios = new ArrayList<>(); - } - ios.add(t.getName()); - break; - case ANDROID: - if(aos == null) { - aos = new ArrayList<>(); - } - aos.add(t.getName()); - break; - } - } - - Collections.sort(planner); - Collections.sort(designer); - Collections.sort(backend); - if(frontend != null) { - Collections.sort(frontend); - } - if(ios != null) { - Collections.sort(ios); - } - if(aos != null) { - Collections.sort(aos); + for (TMPMeetupTeam t : team) { + addMember(t.getTeam(), t.getName()); } + sortAll(); } - private void getTMPMember(List team) { - for(TMPMeetupTeam t : team) { - switch(t.getTeam()) { - case PLANNER: - if(planner == null) { - planner = new ArrayList<>(); - } - planner.add(t.getName()); - break; - case DESIGNER: - if(designer == null) { - designer = new ArrayList<>(); - } - designer.add(t.getName()); - break; - case FRONTEND: - if(frontend == null) { - frontend = new ArrayList<>(); - } - frontend.add(t.getName()); - break; - case BACKEND: - if(backend == null) { - backend = new ArrayList<>(); - } - backend.add(t.getName()); - break; - case IOS: - if(ios == null) { - ios = new ArrayList<>(); - } - ios.add(t.getName()); - break; - case ANDROID: - if(aos == null) { - aos = new ArrayList<>(); - } - aos.add(t.getName()); - break; - } + private void addMember(Team team, String memberName) { + switch (team) { + case PLANNER: + if (planner == null) planner = new ArrayList<>(); + planner.add(memberName); + break; + case DESIGNER: + if (designer == null) designer = new ArrayList<>(); + designer.add(memberName); + break; + case FRONTEND: + if (frontend == null) frontend = new ArrayList<>(); + frontend.add(memberName); + break; + case BACKEND: + if (backend == null) backend = new ArrayList<>(); + backend.add(memberName); + break; + case IOS: + if (ios == null) ios = new ArrayList<>(); + ios.add(memberName); + break; + case ANDROID: + if (aos == null) aos = new ArrayList<>(); + aos.add(memberName); + break; } + } - Collections.sort(planner); - Collections.sort(designer); - Collections.sort(backend); - if(frontend != null) { - Collections.sort(frontend); - } - if(ios != null) { - Collections.sort(ios); - } - if(aos != null) { - Collections.sort(aos); - } + private void sortAll() { + if (planner != null) Collections.sort(planner); + if (designer != null) Collections.sort(designer); + if (frontend != null) Collections.sort(frontend); + if (backend != null) Collections.sort(backend); + if (ios != null) Collections.sort(ios); + if (aos != null) Collections.sort(aos); } } From 44f2a89a0a3b3354b87a42b5ff3f12e8219c8e9d Mon Sep 17 00:00:00 2001 From: Hoyeon Lee <89958157+howooyeon@users.noreply.github.com> Date: Wed, 13 May 2026 01:10:15 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat=20:=20=EB=B0=8B=EC=97=85=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=AF=B8=EB=B3=80=EA=B2=BD=20URL?= =?UTF-8?q?=20=EC=9C=A0=EC=A7=80=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kusitms/website/domain/admin/AdminService.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/kusitms/website/domain/admin/AdminService.java b/src/main/java/com/kusitms/website/domain/admin/AdminService.java index 6e34562..2f8a5f7 100644 --- a/src/main/java/com/kusitms/website/domain/admin/AdminService.java +++ b/src/main/java/com/kusitms/website/domain/admin/AdminService.java @@ -19,14 +19,13 @@ import com.kusitms.website.domain.review.dto.request.ReviewRequest; import com.kusitms.website.domain.review.dto.response.ReviewDetailResponse; import com.kusitms.website.domain.review.dto.response.ReviewResponse; -import com.kusitms.website.domain.review.entity.Review; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -131,8 +130,8 @@ public void saveMeetup(MeetupRequest request) { public void updateMeetup(MeetupRequest request) { TMPMeetupProject meetup = meetupRepository.findById(request.getMeetupId()).orElseThrow(); - String logoUrl = s3Service.uploadFile(request.getLogoFile(), "meetup"); - String posterUrl = s3Service.uploadFile(request.getPosterFile(), "meetup"); + String logoUrl = uploadOrKeep(request.getLogoFile(), meetup.getLogoUrl(), "meetup"); + String posterUrl = uploadOrKeep(request.getPosterFile(), meetup.getPosterUrl(), "meetup"); meetup.update(request.getCardinal(), request.getName(), @@ -144,6 +143,7 @@ public void updateMeetup(MeetupRequest request) { request.getInstagramUrl(), request.getGithubUrl(), request.getAppUrl(), + request.getBehanceUrl(), LocalDate.parse(request.getStartDate(), DateTimeFormatter.ISO_DATE), LocalDate.parse(request.getEndDate(), DateTimeFormatter.ISO_DATE), request.getTeamName()); @@ -281,4 +281,9 @@ public void updateReview(ReviewRequest request) { public void deleteReview(Long reviewId) { reviewRepository.deleteById(reviewId); } + + private String uploadOrKeep(MultipartFile file, String existingUrl, String dirName) { + if (file == null || file.isEmpty()) return existingUrl; + return s3Service.uploadFile(file, dirName); + } }