diff --git a/src/main/java/com/stumeet/server/common/model/ApiResponse.java b/src/main/java/com/stumeet/server/common/model/ApiResponse.java index 9fb3527f..ecea7f9e 100644 --- a/src/main/java/com/stumeet/server/common/model/ApiResponse.java +++ b/src/main/java/com/stumeet/server/common/model/ApiResponse.java @@ -4,6 +4,8 @@ import com.stumeet.server.common.exception.error.Error; import com.stumeet.server.common.response.ErrorCode; import com.stumeet.server.common.exception.error.ErrorField; +import com.stumeet.server.common.response.SuccessCode; + import java.util.List; import org.springframework.validation.BindingResult; @@ -13,17 +15,9 @@ public record ApiResponse( @JsonInclude(value = JsonInclude.Include.NON_NULL) T data ) { - public static ApiResponse success(int code, String message, T data) { - return new ApiResponse<>(code, message, data); - } - public static ApiResponse success(int code, String message) { - return new ApiResponse<>(code, message, null); - } - - // TODO: 삭제 예정 메서드 : 해당 메서드를 사용 부분 수정 요망 - public static ApiResponse fail(int code, String message) { - return new ApiResponse<>(code, message, null); + public static ApiResponse success(SuccessCode code, T data) { + return new ApiResponse<>(code.getHttpStatusCode(), code.getMessage(), data); } public static ApiResponse fail(ErrorCode errorCode) { @@ -41,4 +35,19 @@ public static ApiResponse> fail(ErrorCode errorCode, BindingResult b ErrorField.toErrors(bindingResult) ); } + + // TODO: 삭제 예정 메서드 : 해당 메서드를 사용 부분 수정 요망 + + public static ApiResponse success(int code, String message, T data) { + return new ApiResponse<>(code, message, data); + } + + public static ApiResponse success(int code, String message) { + return new ApiResponse<>(code, message, null); + } + + public static ApiResponse fail(int code, String message) { + return new ApiResponse<>(code, message, null); + } + } diff --git a/src/main/java/com/stumeet/server/common/response/ErrorCode.java b/src/main/java/com/stumeet/server/common/response/ErrorCode.java index 6226136a..f481cd4e 100644 --- a/src/main/java/com/stumeet/server/common/response/ErrorCode.java +++ b/src/main/java/com/stumeet/server/common/response/ErrorCode.java @@ -30,6 +30,11 @@ public enum ErrorCode { */ ACCESS_DENIED_EXCEPTION(HttpStatus.FORBIDDEN, "유효하지 않은 요청입니다."), + /* + 404 - NOT FOUND + */ + STUDY_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 스터디 입니다."), + /* 500 - INTERNAL SERVER ERROR */ diff --git a/src/main/java/com/stumeet/server/common/response/SuccessCode.java b/src/main/java/com/stumeet/server/common/response/SuccessCode.java index c728779b..a418d466 100644 --- a/src/main/java/com/stumeet/server/common/response/SuccessCode.java +++ b/src/main/java/com/stumeet/server/common/response/SuccessCode.java @@ -9,6 +9,7 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) public enum SuccessCode { + GET_SUCCESS(HttpStatus.OK, "조회에 성공했습니다."), SIGN_UP_SUCCESS(HttpStatus.CREATED, "회원가입에 성공했습니다.") ; diff --git a/src/main/java/com/stumeet/server/study/adapter/in/web/StudyQueryApi.java b/src/main/java/com/stumeet/server/study/adapter/in/web/StudyQueryApi.java new file mode 100644 index 00000000..cd239f72 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/in/web/StudyQueryApi.java @@ -0,0 +1,30 @@ +package com.stumeet.server.study.adapter.in.web; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.stumeet.server.common.annotation.WebAdapter; +import com.stumeet.server.common.model.ApiResponse; +import com.stumeet.server.common.response.SuccessCode; +import com.stumeet.server.study.adapter.in.web.response.StudyDetailResponse; +import com.stumeet.server.study.application.port.in.StudyQueryUseCase; + +import lombok.RequiredArgsConstructor; + +@WebAdapter +@RequestMapping("/api/v1/studies") +@RequiredArgsConstructor +public class StudyQueryApi { + + private final StudyQueryUseCase studyQueryUseCase; + + @GetMapping("/{id}") + public ResponseEntity> getStudy( + @PathVariable(name = "id") Long id + ) { + StudyDetailResponse response = studyQueryUseCase.getStudyDetailById(id); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.GET_SUCCESS, response)); + } +} diff --git a/src/main/java/com/stumeet/server/study/adapter/in/web/response/StudyDetailResponse.java b/src/main/java/com/stumeet/server/study/adapter/in/web/response/StudyDetailResponse.java new file mode 100644 index 00000000..5b1e480b --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/in/web/response/StudyDetailResponse.java @@ -0,0 +1,24 @@ +package com.stumeet.server.study.adapter.in.web.response; + +import java.time.LocalDateTime; +import java.util.List; + +import lombok.Builder; + +@Builder +public record StudyDetailResponse( + Long id, + String field, + String name, + List topics, + String intro, + String region, + String rule, + String mainImage, + int headCount, + LocalDateTime startDate, + LocalDateTime endDate, + boolean isFinished, + boolean isDeleted +) { +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/JpaStudyRepository.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/JpaStudyRepository.java new file mode 100644 index 00000000..02207a99 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/JpaStudyRepository.java @@ -0,0 +1,8 @@ +package com.stumeet.server.study.adapter.out.persistance; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.stumeet.server.study.adapter.out.persistance.entity.StudyJpaEntity; + +public interface JpaStudyRepository extends JpaRepository { +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyPersistenceAdapter.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyPersistenceAdapter.java new file mode 100644 index 00000000..f404ea27 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyPersistenceAdapter.java @@ -0,0 +1,23 @@ +package com.stumeet.server.study.adapter.out.persistance; + +import com.stumeet.server.common.annotation.PersistenceAdapter; +import com.stumeet.server.study.adapter.out.persistance.entity.StudyJpaEntity; +import com.stumeet.server.study.adapter.out.persistance.mapper.StudyPersistenceMapper; +import com.stumeet.server.study.application.port.out.StudyQueryPort; +import com.stumeet.server.study.domain.Study; + +import lombok.RequiredArgsConstructor; + +@PersistenceAdapter +@RequiredArgsConstructor +public class StudyPersistenceAdapter implements StudyQueryPort { + + private final StudyRepository studyRepository; + private final StudyPersistenceMapper studyPersistenceMapper; + + @Override + public Study getById(Long id) { + StudyJpaEntity entity = studyRepository.findById(id); + return studyPersistenceMapper.toDomain(entity); + } +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepository.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepository.java new file mode 100644 index 00000000..b139fbb7 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepository.java @@ -0,0 +1,9 @@ +package com.stumeet.server.study.adapter.out.persistance; + +import com.stumeet.server.study.adapter.out.persistance.entity.StudyJpaEntity; + +public interface StudyRepository { + + StudyJpaEntity findById(Long id); + +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepositoryImpl.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepositoryImpl.java new file mode 100644 index 00000000..4ea34c28 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/StudyRepositoryImpl.java @@ -0,0 +1,22 @@ +package com.stumeet.server.study.adapter.out.persistance; + +import org.springframework.stereotype.Repository; + +import com.stumeet.server.common.exception.model.BusinessException; +import com.stumeet.server.common.response.ErrorCode; +import com.stumeet.server.study.adapter.out.persistance.entity.StudyJpaEntity; + +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class StudyRepositoryImpl implements StudyRepository { + + private final JpaStudyRepository jpaStudyRepository; + + @Override + public StudyJpaEntity findById(Long id) { + return jpaStudyRepository.findById(id) + .orElseThrow(() -> new BusinessException(ErrorCode.STUDY_NOT_FOUND)); + } +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyFieldJpaEntity.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyFieldJpaEntity.java new file mode 100644 index 00000000..39ef9154 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyFieldJpaEntity.java @@ -0,0 +1,33 @@ +package com.stumeet.server.study.adapter.out.persistance.entity; + +import org.hibernate.annotations.Comment; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "study_field") +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class StudyFieldJpaEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Comment("스터디 분야 아이디") + private Long id; + + @Column(name = "name", length = 20) + @Comment("분야명") + private String name; +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyJpaEntity.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyJpaEntity.java new file mode 100644 index 00000000..36e901d4 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/entity/StudyJpaEntity.java @@ -0,0 +1,100 @@ +package com.stumeet.server.study.adapter.out.persistance.entity; + +import java.time.LocalDateTime; + +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.Comment; + +import com.stumeet.server.common.model.BaseTimeEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "study") +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class StudyJpaEntity extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Comment("스터디 그룹 아이디") + private Long id; + + @ManyToOne + @JoinColumn(name = "study_field_id", nullable = false) + @Comment("분야") + private StudyFieldJpaEntity studyField; + + @Column(name = "name", length = 20, nullable = false) + @Comment("스터디명") + private String name; + + @Column(name = "topics") + @Comment("주제") + private String topics; + + @Column(name = "intro", length = 100, nullable = false) + @Comment("소개") + private String intro; + + @Column(name = "region", length = 50, nullable = false) + @Comment("지역") + private String region; + + @Column(name = "rule", length = 100) + @Comment("규칙") + private String rule; + + @Column(name = "main_image", length = 500) + @Comment("메인 이미지") + private String mainImage; + + @Column(name = "head_count", length = 100, nullable = false) + @ColumnDefault("1") + @Comment("현재 인원") + private int headCount; + + @Column(name = "start_date", nullable = false) + @Comment("시작일") + private LocalDateTime startDate; + + @Column(name = "end_date", nullable = false) + @Comment("종료일") + private LocalDateTime endDate; + + @Column(name = "is_finished", nullable = false) + @ColumnDefault("false") + @Comment("완료 여부") + private boolean isFinished; + + @Column(name = "is_deleted", nullable = false) + @ColumnDefault("false") + @Comment("삭제 여부") + private boolean isDeleted; + + @Column(name = "deleted_at") + @Comment("삭제된 시간") + private LocalDateTime deletedAt; + + public Boolean getIsFinished() { + return this.isFinished; + } + + public Boolean getIsDeleted() { + return this.isDeleted; + } +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyFieldPersistenceMapper.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyFieldPersistenceMapper.java new file mode 100644 index 00000000..ae4ce012 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyFieldPersistenceMapper.java @@ -0,0 +1,24 @@ +package com.stumeet.server.study.adapter.out.persistance.mapper; + +import org.springframework.stereotype.Component; + +import com.stumeet.server.study.adapter.out.persistance.entity.StudyFieldJpaEntity; +import com.stumeet.server.study.domain.StudyField; + +@Component +public class StudyFieldPersistenceMapper { + + public StudyFieldJpaEntity toEntity(StudyField domain) { + return StudyFieldJpaEntity.builder() + .id(domain.getId()) + .name(domain.getName()) + .build(); + } + + public StudyField toDomain(StudyFieldJpaEntity entity) { + return StudyField.builder() + .id(entity.getId()) + .name(entity.getName()) + .build(); + } +} diff --git a/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyPersistenceMapper.java b/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyPersistenceMapper.java new file mode 100644 index 00000000..3cb456e2 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/adapter/out/persistance/mapper/StudyPersistenceMapper.java @@ -0,0 +1,53 @@ +package com.stumeet.server.study.adapter.out.persistance.mapper; + +import org.springframework.stereotype.Component; + +import com.stumeet.server.study.adapter.out.persistance.entity.StudyJpaEntity; +import com.stumeet.server.study.domain.Study; +import com.stumeet.server.study.domain.StudyHeadCount; +import com.stumeet.server.study.domain.StudyPeriod; +import com.stumeet.server.study.domain.StudyTopics; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class StudyPersistenceMapper { + + private final StudyFieldPersistenceMapper studyFieldPersistenceMapper; + + public StudyJpaEntity toEntity(Study domain) { + return StudyJpaEntity.builder() + .id(domain.getId()) + .name(domain.getName()) + .studyField(studyFieldPersistenceMapper.toEntity(domain.getStudyField())) + .topics(domain.getAssembledTopics()) + .region(domain.getRegion()) + .intro(domain.getIntro()) + .rule(domain.getRule()) + .startDate(domain.getStartDate()) + .endDate(domain.getEndDate()) + .headCount(domain.getHeadCountNumber()) + .mainImage(domain.getMainImage()) + .isFinished(domain.getIsFinished()) + .isDeleted(domain.getIsDeleted()) + .build(); + } + + public Study toDomain(StudyJpaEntity entity) { + return Study.builder() + .id(entity.getId()) + .name(entity.getName()) + .studyField(studyFieldPersistenceMapper.toDomain(entity.getStudyField())) + .studyTopics(StudyTopics.from(entity.getTopics())) + .region(entity.getRegion()) + .intro(entity.getIntro()) + .rule(entity.getRule()) + .period(StudyPeriod.of(entity.getStartDate(), entity.getEndDate())) + .headCount(StudyHeadCount.from(entity.getHeadCount())) + .mainImage(entity.getMainImage()) + .isFinished(entity.getIsFinished()) + .isDeleted(entity.getIsDeleted()) + .build(); + } +} diff --git a/src/main/java/com/stumeet/server/study/application/port/in/StudyQueryUseCase.java b/src/main/java/com/stumeet/server/study/application/port/in/StudyQueryUseCase.java new file mode 100644 index 00000000..b2972b0f --- /dev/null +++ b/src/main/java/com/stumeet/server/study/application/port/in/StudyQueryUseCase.java @@ -0,0 +1,8 @@ +package com.stumeet.server.study.application.port.in; + +import com.stumeet.server.study.adapter.in.web.response.StudyDetailResponse; + +public interface StudyQueryUseCase { + + StudyDetailResponse getStudyDetailById(Long id); +} diff --git a/src/main/java/com/stumeet/server/study/application/port/out/StudyQueryPort.java b/src/main/java/com/stumeet/server/study/application/port/out/StudyQueryPort.java new file mode 100644 index 00000000..98b4d6b9 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/application/port/out/StudyQueryPort.java @@ -0,0 +1,8 @@ +package com.stumeet.server.study.application.port.out; + +import com.stumeet.server.study.domain.Study; + +public interface StudyQueryPort { + + Study getById(Long id); +} diff --git a/src/main/java/com/stumeet/server/study/application/port/out/mapper/StudyUseCaseMapper.java b/src/main/java/com/stumeet/server/study/application/port/out/mapper/StudyUseCaseMapper.java new file mode 100644 index 00000000..d8d55e09 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/application/port/out/mapper/StudyUseCaseMapper.java @@ -0,0 +1,28 @@ +package com.stumeet.server.study.application.port.out.mapper; + +import org.springframework.stereotype.Component; + +import com.stumeet.server.study.adapter.in.web.response.StudyDetailResponse; +import com.stumeet.server.study.domain.Study; + +@Component +public class StudyUseCaseMapper { + + public StudyDetailResponse toStudyDetailResponse(Study study) { + return StudyDetailResponse.builder() + .id(study.getId()) + .name(study.getName()) + .field(study.getStudyFieldName()) + .topics(study.getStudyTopics().getTopics()) + .region(study.getRegion()) + .intro(study.getIntro()) + .rule(study.getRule()) + .startDate(study.getStartDate()) + .endDate(study.getEndDate()) + .headCount(study.getHeadCountNumber()) + .mainImage(study.getMainImage()) + .isFinished(study.getIsFinished()) + .isDeleted(study.getIsDeleted()) + .build(); + } +} diff --git a/src/main/java/com/stumeet/server/study/application/service/StudyQueryService.java b/src/main/java/com/stumeet/server/study/application/service/StudyQueryService.java new file mode 100644 index 00000000..d39da283 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/application/service/StudyQueryService.java @@ -0,0 +1,24 @@ +package com.stumeet.server.study.application.service; + +import com.stumeet.server.common.annotation.UseCase; +import com.stumeet.server.study.adapter.in.web.response.StudyDetailResponse; +import com.stumeet.server.study.application.port.in.StudyQueryUseCase; +import com.stumeet.server.study.application.port.out.StudyQueryPort; +import com.stumeet.server.study.application.port.out.mapper.StudyUseCaseMapper; +import com.stumeet.server.study.domain.Study; + +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class StudyQueryService implements StudyQueryUseCase { + + private final StudyQueryPort studyQueryPort; + private final StudyUseCaseMapper studyUseCaseMapper; + + @Override + public StudyDetailResponse getStudyDetailById(Long id) { + Study study = studyQueryPort.getById(id); + return studyUseCaseMapper.toStudyDetailResponse(study); + } +} diff --git a/src/main/java/com/stumeet/server/study/domain/Study.java b/src/main/java/com/stumeet/server/study/domain/Study.java new file mode 100644 index 00000000..a3f59542 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/domain/Study.java @@ -0,0 +1,59 @@ +package com.stumeet.server.study.domain; + +import java.time.LocalDateTime; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Getter +public class Study { + + private Long id; + + private String name; + + private StudyField studyField; + + private StudyTopics studyTopics; + + private String region; + + private String intro; + + private String rule; + + private StudyPeriod period; + + private StudyHeadCount headCount; + + private String mainImage; + + private Boolean isFinished; + + private Boolean isDeleted; + + public String getStudyFieldName() { + return studyField.getName(); + } + + public String getAssembledTopics() { + return studyTopics.assemble(); + } + + public int getHeadCountNumber() { + return headCount.getNumber(); + } + + public LocalDateTime getStartDate() { + return period.getStartDate(); + } + + public LocalDateTime getEndDate() { + return period.getEndDate(); + } +} + diff --git a/src/main/java/com/stumeet/server/study/domain/StudyField.java b/src/main/java/com/stumeet/server/study/domain/StudyField.java new file mode 100644 index 00000000..7cb01c6d --- /dev/null +++ b/src/main/java/com/stumeet/server/study/domain/StudyField.java @@ -0,0 +1,16 @@ +package com.stumeet.server.study.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Getter +public class StudyField { + + private Long id; + + private String name; +} diff --git a/src/main/java/com/stumeet/server/study/domain/StudyHeadCount.java b/src/main/java/com/stumeet/server/study/domain/StudyHeadCount.java new file mode 100644 index 00000000..b17d4e07 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/domain/StudyHeadCount.java @@ -0,0 +1,17 @@ +package com.stumeet.server.study.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class StudyHeadCount { + + private int number; + + public static StudyHeadCount from(int number) { + return new StudyHeadCount(number); + } +} + diff --git a/src/main/java/com/stumeet/server/study/domain/StudyPeriod.java b/src/main/java/com/stumeet/server/study/domain/StudyPeriod.java new file mode 100644 index 00000000..82e87774 --- /dev/null +++ b/src/main/java/com/stumeet/server/study/domain/StudyPeriod.java @@ -0,0 +1,20 @@ +package com.stumeet.server.study.domain; + +import java.time.LocalDateTime; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class StudyPeriod { + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + public static StudyPeriod of(LocalDateTime startDate, LocalDateTime endDate) { + return new StudyPeriod(startDate, endDate); + } +} diff --git a/src/main/java/com/stumeet/server/study/domain/StudyTopics.java b/src/main/java/com/stumeet/server/study/domain/StudyTopics.java new file mode 100644 index 00000000..34b3369d --- /dev/null +++ b/src/main/java/com/stumeet/server/study/domain/StudyTopics.java @@ -0,0 +1,35 @@ +package com.stumeet.server.study.domain; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import lombok.Getter; + +@Getter +public class StudyTopics { + + private static final String TOPIC_DELIMITER = ";"; + + private final List topics; + + private StudyTopics(List topics) { + this.topics = topics; + } + + public static StudyTopics from(String rawTopics) { + List topics = splitTopicsIntoList(rawTopics); + return new StudyTopics(topics); + } + + private static List splitTopicsIntoList(String rawTopics) { + if (rawTopics != null) { + return Arrays.stream(rawTopics.split(TOPIC_DELIMITER)).toList(); + } + return Collections.emptyList(); + } + + protected String assemble() { + return String.join(";", topics); + } +} diff --git a/src/main/resources/db/migration/V1.4__add_study_table.sql b/src/main/resources/db/migration/V1.4__add_study_table.sql new file mode 100644 index 00000000..1a8a7b20 --- /dev/null +++ b/src/main/resources/db/migration/V1.4__add_study_table.sql @@ -0,0 +1,33 @@ + CREATE TABLE `study_field` + ( + `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '스터디 분야 ID', + `name` VARCHAR(50) NOT NULL COMMENT '분야명' + ) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + + CREATE TABLE `study` + ( + `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '스터디 ID', + `study_field_id` BIGINT NULL COMMENT '스터디 분야 ID', + `name` VARCHAR(255) NOT NULL COMMENT '스터디명', + `region` VARCHAR(50) NOT NULL COMMENT '활동 지역', + `topic` VARCHAR(100) NULL COMMENT '주제', + `intro` VARCHAR(100) NOT NULL COMMENT '소개', + `rule` VARCHAR(100) NULL COMMENT '규칙', + `image` VARCHAR(500) NOT NULL COMMENT '스터디 이미지의 URL', + `headcount` TINYINT(50) NOT NULL DEFAULT 1 COMMENT '인원 수', + `start_date` DATETIME NOT NULL COMMENT '시작일', + `end_date` DATETIME NOT NULL COMMENT '종료일', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 시간', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정 시간', + `is_finished` TINYINT(1) NOT NULL DEFAULT FALSE COMMENT '스터디 완료 여부', + `is_deleted` TINYINT(1) NOT NULL DEFAULT FALSE COMMENT '스터디 삭제 여부', + `deleted_at` DATETIME NULL COMMENT '스터디 삭제 일자', + + CONSTRAINT fk_study_field FOREIGN KEY (study_field_id) + REFERENCES study_field (id) + ON DELETE SET NULL ON UPDATE CASCADE + ) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; \ No newline at end of file diff --git a/src/main/resources/db/migration/V1.5_insert_dummy_study_data.sql b/src/main/resources/db/migration/V1.5_insert_dummy_study_data.sql new file mode 100644 index 00000000..baef8555 --- /dev/null +++ b/src/main/resources/db/migration/V1.5_insert_dummy_study_data.sql @@ -0,0 +1,7 @@ +insert into study_field value (1, 'IT'); + +INSERT INTO study (study_field_id, name, region, topic, intro, rule, image, start_date, end_date) +VALUES (1, '[임시] 프로그래밍 스터디', '서울', 'java;springboot;프로그래밍;', + '프로그래밍 스터디 입니다.', '- 매주 목요일 8시\n- 장소: 안암역\n- 제시간에 제출하기!', + 'https://stumeet.s3.ap-northeast-2.amazonaws.com/study/1/mainImage/2023062711172178420.png', + '2024-04-01', '2024-05-01'); \ No newline at end of file