Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package gg.agit.konect.domain.club.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;

import gg.agit.konect.domain.club.dto.ClubInformationUpdateRequestDto;
import gg.agit.konect.domain.club.dto.ClubRegistrationRequestDto;
import io.swagger.v3.oas.annotations.parameters.RequestBody;

Expand All @@ -10,4 +12,9 @@ public interface ClubRegistrationRequestApi {
ResponseEntity<Void> registerClub(
@RequestBody ClubRegistrationRequestDto request
);

ResponseEntity<Void> requestClubInformationUpdate(
@PathVariable(name = "clubId") Integer clubId,
@RequestBody ClubInformationUpdateRequestDto request
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import gg.agit.konect.domain.club.dto.ClubInformationUpdateRequestDto;
import gg.agit.konect.domain.club.dto.ClubRegistrationRequestDto;
import gg.agit.konect.domain.club.service.ClubRegistrationRequestService;
import gg.agit.konect.global.auth.annotation.PublicApi;
Expand All @@ -24,7 +26,10 @@ public class ClubRegistrationRequestController implements ClubRegistrationReques
private final ClubRegistrationRequestService clubRegistrationRequestService;

@Override
@Operation(summary = "동아리 등록 요청", description = "비로그인 사용자가 새 동아리 등록을 요청합니다.")
@Operation(
summary = "동아리 등록 요청",
description = "비로그인 사용자가 새 동아리 등록을 요청합니다."
)
@PostMapping("/registration-requests")
@PublicApi
public ResponseEntity<Void> registerClub(
Expand All @@ -33,4 +38,19 @@ public ResponseEntity<Void> registerClub(
clubRegistrationRequestService.register(request);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@Override
@Operation(
summary = "동아리 정보 수정 요청",
description = "비로그인 사용자가 기존 동아리 정보 수정을 요청합니다."
)
@PostMapping("/{clubId}/information-update-requests")
@PublicApi
public ResponseEntity<Void> requestClubInformationUpdate(
@PathVariable(name = "clubId") Integer clubId,
@Valid @RequestBody ClubInformationUpdateRequestDto request
) {
clubRegistrationRequestService.requestInformationUpdate(clubId, request);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package gg.agit.konect.domain.club.dto;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import java.util.List;

import gg.agit.konect.domain.club.enums.ClubCategory;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

@Schema(name = "ClubInformationUpdateRequest", description = "동아리 정보 수정 요청")
public record ClubInformationUpdateRequestDto(

@Schema(description = "대학교 명", example = "한국기술교육대학교", requiredMode = REQUIRED)
@NotBlank(message = "대학교 명은 필수입니다.")
String universityName,

@Schema(description = "동아리 명", example = "BCSD Lab", requiredMode = REQUIRED)
@NotBlank(message = "동아리 명은 필수입니다.")
@Size(max = 50, message = "동아리 명은 최대 50자입니다.")
String clubName,

@Schema(description = "동아리 분과", example = "ACADEMIC", requiredMode = REQUIRED)
@NotNull(message = "동아리 분과는 필수입니다.")
ClubCategory clubCategory,

@Schema(description = "동아리 주제", example = "코딩", requiredMode = REQUIRED)
@NotBlank(message = "동아리 주제는 필수입니다.")
@Size(max = 20, message = "동아리 주제는 최대 20자입니다.")
String clubTopic,

@Schema(description = "동아리 이모지", example = "💻", requiredMode = REQUIRED)
@NotBlank(message = "동아리 이모지는 필수입니다.")
@Size(max = 10, message = "동아리 이모지는 최대 10자입니다.")
String clubEmoji,

@Schema(
description = "한 줄 소개 (최대 30자)",
example = "코딩 동아리입니다.",
requiredMode = REQUIRED
)
@NotBlank(message = "한 줄 소개는 필수입니다.")
@Size(max = 30, message = "한 줄 소개는 최대 30자입니다.")
String shortDescription,

@Schema(
description = "동아리 소개 (최대 2000자)",
example = "상세한 동아리 소개 내용...",
requiredMode = REQUIRED
)
@NotBlank(message = "동아리 소개는 필수입니다.")
@Size(max = 2000, message = "동아리 소개는 최대 2000자입니다.")
String fullIntroduction,

@Schema(
description = "사진 및 영상 URL 목록 (최대 5개)",
example = "[\"https://example.com/image1.jpg\"]"
)
@Size(max = 5, message = "사진 및 영상은 최대 5개까지 업로드 가능합니다.")
List<
@NotBlank(message = "이미지 URL은 필수입니다.")
@Size(max = 500, message = "이미지 URL은 최대 500자입니다.")
String> imageUrls
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gg.agit.konect.domain.club.event;

import java.util.List;

import gg.agit.konect.domain.club.model.ClubInformationUpdateRequest;

public record ClubInformationUpdateRequestedEvent(
Integer requestId,
Integer clubId,
String currentUniversityName,
String requestedUniversityName,
String currentClubName,
String requestedClubName,
String currentCategory,
String requestedCategory,
String currentTopic,
String requestedTopic,
String requestedEmoji,
String currentDescription,
String requestedDescription,
String currentFullIntroduction,
String requestedFullIntroduction,
String currentImageUrl,
List<String> requestedImageUrls
) {

public static ClubInformationUpdateRequestedEvent from(ClubInformationUpdateRequest request) {
return new ClubInformationUpdateRequestedEvent(
request.getId(),
request.getClub().getId(),
request.getClub().getUniversity().getKoreanName(),
request.getUniversityName(),
request.getClub().getName(),
request.getClubName(),
request.getClub().getClubCategory().getDescription(),
request.getClubCategory().getDescription(),
request.getClub().getTopic(),
request.getClubTopic(),
request.getClubEmoji(),
request.getClub().getDescription(),
request.getShortDescription(),
request.getClub().getIntroduce(),
request.getFullIntroduction(),
request.getClub().getImageUrl(),
request.getImages().stream()
.map(image -> image.getImageUrl())
.toList()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package gg.agit.konect.domain.club.model;

import static jakarta.persistence.CascadeType.ALL;
import static jakarta.persistence.EnumType.STRING;
import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import java.util.ArrayList;
import java.util.List;

import gg.agit.konect.domain.club.enums.ClubCategory;
import gg.agit.konect.domain.website.model.WebClub;
import gg.agit.konect.global.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderBy;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Getter
@ToString
@Entity
@Table(name = "club_information_update_request")
@NoArgsConstructor(access = PROTECTED)
public class ClubInformationUpdateRequest extends BaseEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", nullable = false, updatable = false, unique = true)
private Integer id;

@NotNull
@ToString.Exclude
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "web_club_id", nullable = false)
private WebClub club;

@NotNull
@Column(name = "university_name", nullable = false)
private String universityName;

@NotNull
@Column(name = "club_name", length = 50, nullable = false)
private String clubName;

@NotNull
@Enumerated(value = STRING)
@Column(name = "club_category", nullable = false)
private ClubCategory clubCategory;

@NotNull
@Column(name = "club_topic", length = 20, nullable = false)
private String clubTopic;

@NotNull
@Column(name = "club_emoji", length = 10, nullable = false)
private String clubEmoji;

@NotNull
@Column(name = "short_description", length = 30, nullable = false)
private String shortDescription;

@NotNull
@Column(name = "full_introduction", columnDefinition = "TEXT", nullable = false)
private String fullIntroduction;

@OneToMany(mappedBy = "request", cascade = ALL, orphanRemoval = true)
@OrderBy("displayOrder ASC")
private List<ClubInformationUpdateRequestImage> images = new ArrayList<>();

@NotNull
@Enumerated(value = STRING)
@Column(name = "status", length = 20, nullable = false)
private UpdateRequestStatus status;

@Builder
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
private ClubInformationUpdateRequest(
Integer id,
WebClub club,
String universityName,
String clubName,
ClubCategory clubCategory,
String clubTopic,
String clubEmoji,
String shortDescription,
String fullIntroduction,
UpdateRequestStatus status
) {
this.id = id;
this.club = club;
this.universityName = universityName;
this.clubName = clubName;
this.clubCategory = clubCategory;
this.clubTopic = clubTopic;
this.clubEmoji = clubEmoji;
this.shortDescription = shortDescription;
this.fullIntroduction = fullIntroduction;
this.status = status != null ? status : UpdateRequestStatus.PENDING;
}

public void addImages(List<String> imageUrls) {
for (int i = 0; i < imageUrls.size(); i++) {
ClubInformationUpdateRequestImage image = ClubInformationUpdateRequestImage.builder()
.request(this)
.imageUrl(imageUrls.get(i))
.displayOrder(i)
.build();
this.images.add(image);
}
}

public enum UpdateRequestStatus {
PENDING, APPROVED, REJECTED
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package gg.agit.konect.domain.club.model;

import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import gg.agit.konect.global.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Entity
@Table(name = "club_information_update_request_image")
@NoArgsConstructor(access = PROTECTED)
public class ClubInformationUpdateRequestImage extends BaseEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", nullable = false, updatable = false, unique = true)
private Integer id;

@NotNull
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "request_id", nullable = false)
private ClubInformationUpdateRequest request;

@NotNull
@Column(name = "image_url", length = 500, nullable = false)
private String imageUrl;

@NotNull
@Column(name = "display_order", nullable = false)
private Integer displayOrder;

@Builder
private ClubInformationUpdateRequestImage(
Integer id,
ClubInformationUpdateRequest request,
String imageUrl,
Integer displayOrder
) {
this.id = id;
this.request = request;
this.imageUrl = imageUrl;
this.displayOrder = displayOrder;
}

public static class ClubInformationUpdateRequestImageBuilder {

@Override
public String toString() {
return "ClubInformationUpdateRequestImage.ClubInformationUpdateRequestImageBuilder("
+ "id=" + id
+ ", imageUrl=" + imageUrl
+ ", displayOrder=" + displayOrder
+ ")";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package gg.agit.konect.domain.club.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import gg.agit.konect.domain.club.model.ClubInformationUpdateRequest;

public interface ClubInformationUpdateRequestRepository
extends JpaRepository<ClubInformationUpdateRequest, Integer> {
}
Loading
Loading