From 3f1bd057412410e2ea019133419cfc4c5685cce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Wed, 18 Mar 2026 13:19:29 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20Activity=20API=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/controller/ActivityApi.java | 29 --------- .../controller/ActivityController.java | 25 -------- .../activity/dto/ActivitiesResponse.java | 14 ----- .../domain/activity/dto/ActivityResponse.java | 61 ------------------- .../koin/domain/activity/model/Activity.java | 58 ------------------ .../repository/ActivityRepository.java | 19 ------ .../activity/service/ActivityService.java | 52 ---------------- 7 files changed, 258 deletions(-) delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/controller/ActivityApi.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/controller/ActivityController.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/dto/ActivitiesResponse.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/dto/ActivityResponse.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/model/Activity.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/repository/ActivityRepository.java delete mode 100644 src/main/java/in/koreatech/koin/domain/activity/service/ActivityService.java diff --git a/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityApi.java b/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityApi.java deleted file mode 100644 index bd9176f1df..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package in.koreatech.koin.domain.activity.controller; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import in.koreatech.koin.domain.activity.dto.ActivitiesResponse; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "(Normal) Activity", description = "BCSDLab 활동") -public interface ActivityApi { - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200", description = "성공적으로 활동 목록을 조회함"), - @ApiResponse(responseCode = "404", description = "해당하는 활동이 없음", content = @Content(schema = @Schema(hidden = true))), - } - ) - @Operation(summary = "BCSD Lab 활동 조회") - @GetMapping("/activities") - ResponseEntity getActivities( - @RequestParam(required = false) String year - ); -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityController.java b/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityController.java deleted file mode 100644 index e356f83858..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/controller/ActivityController.java +++ /dev/null @@ -1,25 +0,0 @@ -package in.koreatech.koin.domain.activity.controller; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import in.koreatech.koin.domain.activity.dto.ActivitiesResponse; -import in.koreatech.koin.domain.activity.service.ActivityService; -import lombok.RequiredArgsConstructor; - -@RestController -@RequiredArgsConstructor -public class ActivityController implements ActivityApi { - - private final ActivityService activityService; - - @GetMapping("/activities") - public ResponseEntity getActivities( - @RequestParam(required = false) String year - ) { - ActivitiesResponse response = activityService.getActivities(year); - return ResponseEntity.ok(response); - } -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/dto/ActivitiesResponse.java b/src/main/java/in/koreatech/koin/domain/activity/dto/ActivitiesResponse.java deleted file mode 100644 index 46835c0889..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/dto/ActivitiesResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package in.koreatech.koin.domain.activity.dto; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public record ActivitiesResponse( - @JsonProperty("Activities") - List activities -) { - public ActivitiesResponse(List activities) { - this.activities = activities; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/dto/ActivityResponse.java b/src/main/java/in/koreatech/koin/domain/activity/dto/ActivityResponse.java deleted file mode 100644 index 40c0be1b1c..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/dto/ActivityResponse.java +++ /dev/null @@ -1,61 +0,0 @@ -package in.koreatech.koin.domain.activity.dto; - -import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; -import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; -import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.annotation.JsonNaming; - -import in.koreatech.koin.domain.activity.model.Activity; -import io.swagger.v3.oas.annotations.media.Schema; - -@JsonNaming(value = SnakeCaseStrategy.class) -public record ActivityResponse( - @Schema(description = "활동 날짜", example = "2019-07-29", requiredMode = REQUIRED) - @JsonFormat(pattern = "yyyy-MM-dd") - LocalDate date, - - @Schema(description = "삭제 여부", example = "false", requiredMode = REQUIRED) - Boolean isDeleted, - - @Schema(description = "최근 업데이트 일시", example = "2019-08-16 23:01:52", requiredMode = REQUIRED) - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - LocalDateTime updatedAt, - - @Schema(description = "초기 생성 일시", example = "2019-08-16 23:01:52", requiredMode = REQUIRED) - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - LocalDateTime createdAt, - - @Schema(description = "활동 설명", example = "더 편리한 서비스 제공을 위해 시간표 기능을 추가했습니다.", requiredMode = REQUIRED) - String description, - - @Schema(description = "이미지 URL 목록", example = """ - ["https://test2.com.png", "https://test3.com.png"] - """, requiredMode = NOT_REQUIRED) - List imageUrls, - - @Schema(description = "고유 식별자", example = "1", requiredMode = REQUIRED) - Integer id, - - @Schema(description = "제목", example = "코인 시간표 기능 추가", requiredMode = REQUIRED) - String title -) { - - public static ActivityResponse of(Activity activity, List imageUrls) { - return new ActivityResponse( - activity.getDate(), - activity.isDeleted(), - activity.getUpdatedAt(), - activity.getCreatedAt(), - activity.getDescription(), - imageUrls, - activity.getId(), - activity.getTitle() - ); - } -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/model/Activity.java b/src/main/java/in/koreatech/koin/domain/activity/model/Activity.java deleted file mode 100644 index e06b42e82d..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/model/Activity.java +++ /dev/null @@ -1,58 +0,0 @@ -package in.koreatech.koin.domain.activity.model; - -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import java.time.LocalDate; - -import in.koreatech.koin.common.model.BaseEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Entity -@Table(name = "activities") -@NoArgsConstructor(access = PROTECTED) -public class Activity extends BaseEntity { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "id") - private Integer id; - - @Column(name = "title", nullable = false) - private String title; - - @Column(name = "description") - private String description; - - @Column(name = "image_urls") - private String imageUrls; - - @Column(name = "date") - private LocalDate date; - - @Column(name = "is_deleted") - private boolean isDeleted = false; - - @Builder - private Activity( - String title, - String description, - String imageUrls, - LocalDate date, - boolean isDeleted - ) { - this.title = title; - this.description = description; - this.imageUrls = imageUrls; - this.date = date; - this.isDeleted = isDeleted; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/repository/ActivityRepository.java b/src/main/java/in/koreatech/koin/domain/activity/repository/ActivityRepository.java deleted file mode 100644 index df6696ea00..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/repository/ActivityRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package in.koreatech.koin.domain.activity.repository; - -import java.util.List; - -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.Repository; -import org.springframework.data.repository.query.Param; - -import in.koreatech.koin.domain.activity.model.Activity; - -public interface ActivityRepository extends Repository { - - @Query(value = "SELECT * FROM activities WHERE is_deleted = 0 AND YEAR(date) = :year", nativeQuery = true) - List getActivitiesByYear(@Param("year") String year); - - List findAllByIsDeleted(boolean isDeleted); - - Activity save(Activity activity); -} diff --git a/src/main/java/in/koreatech/koin/domain/activity/service/ActivityService.java b/src/main/java/in/koreatech/koin/domain/activity/service/ActivityService.java deleted file mode 100644 index 076a3fad40..0000000000 --- a/src/main/java/in/koreatech/koin/domain/activity/service/ActivityService.java +++ /dev/null @@ -1,52 +0,0 @@ -package in.koreatech.koin.domain.activity.service; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import in.koreatech.koin.domain.activity.dto.ActivitiesResponse; -import in.koreatech.koin.domain.activity.dto.ActivityResponse; -import in.koreatech.koin.domain.activity.model.Activity; -import in.koreatech.koin.domain.activity.repository.ActivityRepository; -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class ActivityService { - - private final ActivityRepository activityRepository; - - public ActivitiesResponse getActivities(String year) { - List activities; - - if (year == null) { - activities = activityRepository.findAllByIsDeleted(false); - } else { - activities = activityRepository.getActivitiesByYear(year); - } - - List activityResponseList = activities.stream() - .map(activity -> { - List imageUrlsList = parseImageUrls(activity.getImageUrls()); - return ActivityResponse.of(activity, imageUrlsList); - }) - .toList(); - - return new ActivitiesResponse(activityResponseList); - } - - private List parseImageUrls(String imageUrls) { - if (imageUrls == null || imageUrls.trim().isEmpty()) { - return Collections.emptyList(); - } - - return Arrays.stream(imageUrls.split(",")) - .map(String::strip) - .map(url -> url.replace("\n", "").replace("\r", "")) // 개행 문자 제거 - .toList(); - } -} From 4000f06802edf2058937eb219933a81155450a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Wed, 18 Mar 2026 13:19:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20Activity=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/domain/ActivityApiTest.java | 167 ------------------ .../fixture/ActivityAcceptanceFixture.java | 70 -------- 2 files changed, 237 deletions(-) delete mode 100644 src/test/java/in/koreatech/koin/acceptance/domain/ActivityApiTest.java delete mode 100644 src/test/java/in/koreatech/koin/acceptance/fixture/ActivityAcceptanceFixture.java diff --git a/src/test/java/in/koreatech/koin/acceptance/domain/ActivityApiTest.java b/src/test/java/in/koreatech/koin/acceptance/domain/ActivityApiTest.java deleted file mode 100644 index a1d98cfbf7..0000000000 --- a/src/test/java/in/koreatech/koin/acceptance/domain/ActivityApiTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package in.koreatech.koin.acceptance.domain; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.time.LocalDate; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; - -import in.koreatech.koin.acceptance.AcceptanceTest; -import in.koreatech.koin.acceptance.fixture.ActivityAcceptanceFixture; - -class ActivityApiTest extends AcceptanceTest { - - @Autowired - protected ActivityAcceptanceFixture activityFixture; - - @Test - void BCSDLab_활동_내역을_조회한다() throws Exception { - activityFixture.builder() - .title("BCSD/KAP 통합") - .description("BCSD와 KAP가 통합되었습니다.") - .imageUrls("https://test.com.png") - .date(LocalDate.of(2018, 9, 12)) - .isDeleted(false) - .build(); - - activityFixture.builder() - .title("19-3기 모집") - .description("BCSD Lab과 함께 성장해나갈 인재를 모집했습니다.") - .imageUrls(""" - https://test2.com.png, - https://test3.com.png - """) - .date(LocalDate.of(2019, 7, 29)) - .isDeleted(false) - .build(); - - activityFixture.builder() - .title("코인 시간표 기능 추가") - .description("더 편리한 서비스 제공을 위해 시간표 기능을 추가했습니다") - .imageUrls("https://test4.com.png") - .date(LocalDate.of(2019, 8, 20)) - .isDeleted(false) - .build(); - - mockMvc.perform( - get("/activities") - .param("year", "2019") - .contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk()) - .andExpect(content().json(""" - { - "Activities": [ - { - "date": "2019-07-29", - "is_deleted": false, - "updated_at": "2024-01-15 12:00:00", - "created_at": "2024-01-15 12:00:00", - "description": "BCSD Lab과 함께 성장해나갈 인재를 모집했습니다.", - "image_urls": [ - "https://test2.com.png", - "https://test3.com.png" - ], - "id": 2, - "title": "19-3기 모집" - }, - { - "date": "2019-08-20", - "is_deleted": false, - "updated_at": "2024-01-15 12:00:00", - "created_at": "2024-01-15 12:00:00", - "description": "더 편리한 서비스 제공을 위해 시간표 기능을 추가했습니다", - "image_urls": [ - "https://test4.com.png" - ], - "id": 3, - "title": "코인 시간표 기능 추가" - } - ] - } - """)); - } - - @Test - void BCSDLab_활동_내역을_조회한다_파라미터가_없는_경우_전체조회() throws Exception { - activityFixture.builder() - .title("BCSD/KAP 통합") - .description("BCSD와 KAP가 통합되었습니다.") - .imageUrls("https://test.com.png") - .date(LocalDate.of(2018, 9, 12)) - .isDeleted(false) - .build(); - - activityFixture.builder() - .title("19-3기 모집") - .description("BCSD Lab과 함께 성장해나갈 인재를 모집했습니다.") - .imageUrls(""" - https://test2.com.png, - https://test3.com.png - """) - .date(LocalDate.of(2019, 7, 29)) - .isDeleted(false) - .build(); - - activityFixture.builder() - .title("코인 시간표 기능 추가") - .description("더 편리한 서비스 제공을 위해 시간표 기능을 추가했습니다") - .imageUrls("https://test4.com.png") - .date(LocalDate.of(2019, 8, 20)) - .isDeleted(false) - .build(); - - mockMvc.perform( - get("/activities") - .contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk()) - .andExpect(content().json(""" - { - "Activities": [ - { - "date": "2018-09-12", - "is_deleted": false, - "updated_at": "2024-01-15 12:00:00", - "created_at": "2024-01-15 12:00:00", - "description": "BCSD와 KAP가 통합되었습니다.", - "image_urls": [ - "https://test.com.png" - ], - "id": 1, - "title": "BCSD/KAP 통합" - }, - { - "date": "2019-07-29", - "is_deleted": false, - "updated_at": "2024-01-15 12:00:00", - "created_at": "2024-01-15 12:00:00", - "description": "BCSD Lab과 함께 성장해나갈 인재를 모집했습니다.", - "image_urls": [ - "https://test2.com.png", - "https://test3.com.png" - ], - "id": 2, - "title": "19-3기 모집" - }, - { - "date": "2019-08-20", - "is_deleted": false, - "updated_at": "2024-01-15 12:00:00", - "created_at": "2024-01-15 12:00:00", - "description": "더 편리한 서비스 제공을 위해 시간표 기능을 추가했습니다", - "image_urls": [ - "https://test4.com.png" - ], - "id": 3, - "title": "코인 시간표 기능 추가" - } - ] - } - """)); - } -} diff --git a/src/test/java/in/koreatech/koin/acceptance/fixture/ActivityAcceptanceFixture.java b/src/test/java/in/koreatech/koin/acceptance/fixture/ActivityAcceptanceFixture.java deleted file mode 100644 index 067f6e0db1..0000000000 --- a/src/test/java/in/koreatech/koin/acceptance/fixture/ActivityAcceptanceFixture.java +++ /dev/null @@ -1,70 +0,0 @@ -package in.koreatech.koin.acceptance.fixture; - -import java.time.LocalDate; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import in.koreatech.koin.domain.activity.model.Activity; -import in.koreatech.koin.domain.activity.repository.ActivityRepository; - -@Component -public final class ActivityAcceptanceFixture { - - private final ActivityRepository activityRepository; - - @Autowired - public ActivityAcceptanceFixture(ActivityRepository activityRepository) { - this.activityRepository = activityRepository; - } - - public ActivityFixtureBuilder builder() { - return new ActivityFixtureBuilder(); - } - - public final class ActivityFixtureBuilder { - - private String title; - private String description; - private String imageUrls; - private LocalDate date; - private boolean isDeleted; - - public ActivityFixtureBuilder title(String title) { - this.title = title; - return this; - } - - public ActivityFixtureBuilder description(String description) { - this.description = description; - return this; - } - - public ActivityFixtureBuilder imageUrls(String imageUrls) { - this.imageUrls = imageUrls; - return this; - } - - public ActivityFixtureBuilder date(LocalDate date) { - this.date = date; - return this; - } - - public ActivityFixtureBuilder isDeleted(boolean isDeleted) { - this.isDeleted = isDeleted; - return this; - } - - public Activity build() { - return activityRepository.save( - Activity.builder() - .title(title) - .description(description) - .imageUrls(imageUrls) - .date(date) - .isDeleted(isDeleted) - .build() - ); - } - } -}