Skip to content

Commit ce6fd8b

Browse files
authored
[feat] 작가 신청 승인/거절 API 구현 **효상님 확인해주시면 감사하겠습니다** (#214)
* [feat] 작가 프로필 관련 Repository, DTO 생성 및 리팩토링 * [refactor] ArtistApplicationAdminServiceTest 리팩토링 및 케이스 추가 * [feat] 작가 신청 승인/거절 API 구현
1 parent dd2c193 commit ce6fd8b

File tree

11 files changed

+454
-59
lines changed

11 files changed

+454
-59
lines changed

src/main/java/com/back/domain/artist/controller/ArtistController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public ResponseEntity<RsData<ArtistApplicationResponse>> getArtistApplicationDet
8585
* 작가 신청 취소/삭제
8686
*/
8787
@DeleteMapping("/application/{applicationId}/cancel")
88+
@Operation(summary = "작가 신청 취소", description = "작가 신청을 취소하거나 삭제합니다. 승인된 신청서는 취소할 수 없습니다.")
8889
public ResponseEntity<RsData<Void>> cancelArtistApplication(
8990
@AuthenticationPrincipal CustomUserDetails userDetails,
9091
@PathVariable Long applicationId) {

src/main/java/com/back/domain/artist/dto/request/ArtistApplicationReviewRequest.java

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.back.domain.artist.dto.request;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.Size;
5+
6+
/**
7+
* 관리자용 작가 신청서 거절 요청 DTO
8+
*/
9+
public record RejectArtistApplicationRequest(
10+
11+
@NotBlank(message = "거절 사유는 필수입니다.")
12+
@Size(min = 10, max = 500, message = "거절 사유는 10자 이상 500자 이하여야 합니다.")
13+
String rejectionReason
14+
) {
15+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.back.domain.artist.dto.request;
2+
3+
import jakarta.validation.constraints.Size;
4+
5+
/**
6+
* 작가 프로필 수정 요청 DTO
7+
*/
8+
public record UpdateArtistProfileRequest(
9+
@Size(max = 500, message = "프로필 이미지 URL은 최대 500자까지 가능합니다.")
10+
String profileImageUrl,
11+
12+
@Size(min = 2, max = 20, message = "작가명은 2자 이상 20자 이하여야 합니다.")
13+
String artistName,
14+
15+
@Size(max = 100, message = "SNS 계정은 최대 100자까지 가능합니다.")
16+
String snsAccount,
17+
18+
@Size(max = 2000, message = "작가 소개는 최대 2000자까지 가능합니다.")
19+
String description,
20+
21+
@Size(max = 200, message = "사업장 주소는 최대 200자까지 가능합니다.")
22+
String businessAddress,
23+
24+
@Size(max = 200, message = "사업장 상세주소는 최대 200자까지 가능합니다.")
25+
String businessAddressDetail,
26+
27+
@Size(max = 10, message = "우편번호는 최대 10자까지 가능합니다.")
28+
String businessZipCode,
29+
30+
@Size(max = 20, message = "예금주명은 최대 20자까지 가능합니다.")
31+
String accountName,
32+
33+
@Size(max = 50, message = "은행명은 최대 50자까지 가능합니다.")
34+
String bankName,
35+
36+
@Size(max = 50, message = "계좌번호는 최대 50자까지 가능합니다.")
37+
String bankAccount,
38+
39+
String managerPhone
40+
) {
41+
42+
/**
43+
* 수정할 필드가 하나라도 있는지 확인
44+
*/
45+
public boolean hasAnyUpdate() {
46+
return profileImageUrl != null ||
47+
artistName != null ||
48+
snsAccount != null ||
49+
description != null ||
50+
businessAddress != null ||
51+
businessAddressDetail != null ||
52+
businessZipCode != null ||
53+
accountName != null ||
54+
bankName != null ||
55+
bankAccount != null ||
56+
managerPhone != null;
57+
}
58+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.back.domain.artist.dto.response;
2+
3+
import com.back.domain.artist.entity.ArtistProfile;
4+
5+
import java.time.LocalDateTime;
6+
7+
public record ArtistProfileResponse(
8+
Long id,
9+
Long userId,
10+
String artistName,
11+
String email, // User에서 가져옴
12+
String phone, // User에서 가져옴
13+
String description,
14+
String profileImageUrl,
15+
String snsAccount,
16+
String mainProducts,
17+
18+
// 사업자 정보
19+
String businessAddress,
20+
String businessAddressDetail,
21+
String businessZipCode,
22+
String managerPhone,
23+
24+
// 은행 정보
25+
String bankName,
26+
String bankAccount,
27+
String accountName,
28+
29+
// 통계 정보
30+
Integer followerCount,
31+
Long totalSales,
32+
Integer productCount,
33+
34+
LocalDateTime createdAt
35+
) {
36+
/**
37+
* Entity -> DTO 변환
38+
*/
39+
public static ArtistProfileResponse from(ArtistProfile profile) {
40+
return new ArtistProfileResponse(
41+
profile.getId(),
42+
profile.getUser().getId(),
43+
profile.getArtistName(),
44+
profile.getEmail(), // User 참조 (자동 동기화)
45+
profile.getPhone(), // User 참조 (자동 동기화)
46+
profile.getDescription(),
47+
profile.getProfileImageUrl(),
48+
profile.getSnsAccount(),
49+
profile.getMainProducts(),
50+
profile.getBusinessAddress(),
51+
profile.getBusinessAddressDetail(),
52+
profile.getBusinessZipCode(),
53+
profile.getManagerPhone(),
54+
profile.getBankName(),
55+
profile.getBankAccount(),
56+
profile.getAccountName(),
57+
profile.getFollowerCount(),
58+
profile.getTotalSales(),
59+
profile.getProductCount(),
60+
profile.getCreateDate()
61+
);
62+
}
63+
}

src/main/java/com/back/domain/artist/entity/ArtistProfile.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ public class ArtistProfile extends BaseEntity {
3434
@Column(nullable = false, length = 20)
3535
private String artistName; // 작가명
3636

37-
@Column(nullable = false, length = 100)
38-
private String email;
39-
40-
@Column(nullable = false, length = 20)
41-
private String phone;
42-
4337
@Column(length = 500)
4438
private String mainProducts; // 주력 상품
4539

@@ -92,17 +86,14 @@ public class ArtistProfile extends BaseEntity {
9286

9387
@Builder
9488
public ArtistProfile(User user, ArtistApplication artistApplication,
95-
String artistName, String email, String phone,
96-
String mainProducts, String snsAccount,
89+
String artistName, String mainProducts, String snsAccount,
9790
String businessAddress, String businessAddressDetail, String businessZipCode,
9891
String managerPhone,
9992
String bankName, String bankAccount, String accountName,
10093
String description, String profileImageUrl) {
10194
this.user = user;
10295
this.artistApplication = artistApplication;
10396
this.artistName = artistName;
104-
this.email = email;
105-
this.phone = phone;
10697
this.mainProducts = mainProducts;
10798
this.snsAccount = snsAccount;
10899
this.businessAddress = businessAddress;
@@ -133,8 +124,6 @@ public static ArtistProfile fromApplication(User user, ArtistApplication applica
133124
.user(user)
134125
.artistApplication(application)
135126
.artistName(application.getArtistName())
136-
.email(application.getEmail())
137-
.phone(application.getPhone())
138127
.mainProducts(application.getMainProducts())
139128
.snsAccount(application.getSnsAccount())
140129
.businessAddress(application.getBusinessAddress())
@@ -177,7 +166,6 @@ public void updateProfile(String profileImageUrl, String artistName, String snsA
177166
if (businessAddress != null && !businessAddress.isBlank()) {
178167
this.businessAddress = businessAddress;
179168
}
180-
181169
if (businessAddressDetail != null && !businessAddressDetail.isBlank()) {
182170
this.businessAddressDetail = businessAddressDetail;
183171
}
@@ -200,7 +188,7 @@ public void updateProfile(String profileImageUrl, String artistName, String snsA
200188
this.bankAccount = bankAccount;
201189
}
202190

203-
// 연락처
191+
// 담당자 연락처
204192
if (managerPhone != null && !managerPhone.isBlank()) {
205193
this.managerPhone = managerPhone;
206194
}
@@ -250,6 +238,24 @@ public void decreaseProductCount() {
250238
}
251239
}
252240

241+
// ==== Getter 메서드 (User 참조) ==== //
242+
243+
/**
244+
* User의 이메일 반환
245+
* - User 엔티티에서 직접 가져옴 (자동 동기화)
246+
*/
247+
public String getEmail() {
248+
return this.user.getEmail();
249+
}
250+
251+
/**
252+
* User의 전화번호 반환
253+
* - User 엔티티에서 직접 가져옴 (자동 동기화)
254+
*/
255+
public String getPhone() {
256+
return this.user.getPhone();
257+
}
258+
253259
// ==== 검증 메서드 ==== //
254260

255261
/**
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.back.domain.artist.repository;
2+
3+
import com.back.domain.artist.entity.ArtistProfile;
4+
import io.lettuce.core.dynamic.annotation.Param;
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.data.jpa.repository.Query;
7+
8+
import java.util.Optional;
9+
10+
public interface ArtistProfileRepository extends JpaRepository<ArtistProfile, Long> {
11+
12+
// User ID로 작가 프로필 조회
13+
Optional<ArtistProfile> findByUserId(Long artistId);
14+
15+
// User ID로 작가 프로필 존재 여부 확인
16+
boolean existsByUserId(Long userId);
17+
18+
// 작가명으로 작가 프로필 조회
19+
Optional<ArtistProfile> findByArtistName(String artistName);
20+
21+
// 작가명으로 작가 프로필 존재 여부 확인
22+
boolean existsByArtistName(String artistName);
23+
24+
// User 엔티티를 함께 페치하여 작가 프로필 조회
25+
@Query("SELECT ap FROM ArtistProfile ap JOIN FETCH ap.user WHERE ap.user.id = :userId")
26+
Optional<ArtistProfile> findByUserIdWithUser(@Param("userId") Long userId);
27+
28+
}

0 commit comments

Comments
 (0)