Skip to content

Commit 1b44ed7

Browse files
committed
Hotfix : 파티 대표 이미지 로직 수정 및 대표 이미지 설정 api 추가
1 parent fd1ceb9 commit 1b44ed7

4 files changed

Lines changed: 120 additions & 11 deletions

File tree

src/main/java/ita/tinybite/domain/party/controller/PartyController.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import ita.tinybite.domain.party.dto.request.PartyCreateRequest;
1212
import ita.tinybite.domain.party.dto.request.PartyListRequest;
1313
import ita.tinybite.domain.party.dto.request.PartyQueryListResponse;
14+
import ita.tinybite.domain.party.dto.request.PartyThumbnailUpdateRequest;
1415
import ita.tinybite.domain.party.dto.request.PartyUpdateRequest;
1516
import ita.tinybite.domain.party.dto.response.ChatRoomResponse;
1617
import ita.tinybite.domain.party.dto.response.PartyDetailResponse;
@@ -523,6 +524,52 @@ public ResponseEntity<Void> updateParty(
523524
return ResponseEntity.ok().build();
524525
}
525526

527+
/**
528+
* 파티 대표 이미지 설정
529+
*/
530+
@Operation(
531+
summary = "파티 대표 이미지 설정",
532+
description = """
533+
파티의 대표 이미지(썸네일)를 설정합니다.
534+
535+
**설정 권한**
536+
- 파티 호스트만 설정 가능
537+
538+
**동작 방식**
539+
- thumbnailImage와 thumbnailImageDetail에 동일한 이미지가 설정됩니다.
540+
"""
541+
)
542+
@ApiResponses({
543+
@ApiResponse(
544+
responseCode = "200",
545+
description = "대표 이미지 설정 성공"
546+
),
547+
@ApiResponse(
548+
responseCode = "400",
549+
description = "잘못된 요청 (이미지 URL 누락)",
550+
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
551+
),
552+
@ApiResponse(
553+
responseCode = "403",
554+
description = "파티장 권한 없음",
555+
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
556+
),
557+
@ApiResponse(
558+
responseCode = "404",
559+
description = "파티를 찾을 수 없음",
560+
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
561+
)
562+
})
563+
@PatchMapping("/{partyId}/thumbnail")
564+
public ResponseEntity<Void> updateThumbnail(
565+
@PathVariable Long partyId,
566+
@AuthenticationPrincipal Long userId,
567+
@Valid @RequestBody PartyThumbnailUpdateRequest request) {
568+
569+
partyService.updateThumbnail(partyId, userId, request.getThumbnailImage());
570+
return ResponseEntity.ok().build();
571+
}
572+
526573
/**
527574
* 파티 삭제
528575
*/
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ita.tinybite.domain.party.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotBlank;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@NoArgsConstructor
10+
@Schema(description = "파티 대표 이미지 설정 요청")
11+
public class PartyThumbnailUpdateRequest {
12+
13+
@NotBlank(message = "대표 이미지 URL은 필수입니다")
14+
@Schema(description = "대표 이미지 URL", example = "https://example.com/image.jpg")
15+
private String thumbnailImage;
16+
}

src/main/java/ita/tinybite/domain/party/entity/Party.java

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ public String getTimeAgo() {
150150
}
151151

152152
public void updateAllFields(String title, Integer price, Integer maxParticipants,
153-
PickupLocation pickupLocation, String productLink, String description, List<String> images) {
153+
PickupLocation pickupLocation, String productLink, String description,
154+
List<String> images, String defaultThumbnail, String defaultThumbnailDetail) {
154155
this.title = title != null ? title : this.title;
155156
this.price = price != null ? price : this.price;
156157
this.maxParticipants = maxParticipants != null ? maxParticipants : this.maxParticipants;
@@ -166,18 +167,35 @@ public void updateAllFields(String title, Integer price, Integer maxParticipants
166167

167168
this.description = description != null ? description : this.description;
168169

169-
if (images != null && !images.isEmpty()) {
170-
this.images = images;
171-
this.thumbnailImage = images.get(0);
170+
if (images != null) {
171+
if (!images.isEmpty()) {
172+
this.images = images;
173+
this.thumbnailImage = images.get(0);
174+
this.thumbnailImageDetail = images.get(0);
175+
} else {
176+
// 빈 리스트면 이미지 삭제하고 기본 이미지로 설정
177+
this.images = null;
178+
this.thumbnailImage = defaultThumbnail;
179+
this.thumbnailImageDetail = defaultThumbnailDetail;
180+
}
172181
}
173182
}
174183

175-
public void updateLimitedFields(String description, List<String> images) {
184+
public void updateLimitedFields(String description, List<String> images,
185+
String defaultThumbnail, String defaultThumbnailDetail) {
176186
this.description = description != null ? description : this.description;
177187

178-
if (images != null && !images.isEmpty()) {
179-
this.images = images;
180-
this.thumbnailImage = images.get(0);
188+
if (images != null) {
189+
if (!images.isEmpty()) {
190+
this.images = images;
191+
this.thumbnailImage = images.get(0);
192+
this.thumbnailImageDetail = images.get(0);
193+
} else {
194+
// 빈 리스트면 이미지 삭제하고 기본 이미지로 설정
195+
this.images = null;
196+
this.thumbnailImage = defaultThumbnail;
197+
this.thumbnailImageDetail = defaultThumbnailDetail;
198+
}
181199
}
182200
}
183201

@@ -204,4 +222,12 @@ public void updatePartyLocation(PickupLocation pickupLocation, String location)
204222
this.pickupLocation = pickupLocation;
205223
this.town = location;
206224
}
225+
226+
/**
227+
* 대표 이미지 설정 (thumbnailImage, thumbnailImageDetail 동일하게 설정)
228+
*/
229+
public void updateThumbnail(String thumbnailImage) {
230+
this.thumbnailImage = thumbnailImage;
231+
this.thumbnailImageDetail = thumbnailImage;
232+
}
207233
}

src/main/java/ita/tinybite/domain/party/service/PartyService.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,9 @@ public void updateParty(Long partyId, Long userId, PartyUpdateRequest request) {
462462
// 다른 승인된 파티원이 있는 경우: 설명과 이미지만 수정 가능
463463
party.updateLimitedFields(
464464
request.getDescription(),
465-
request.getImages()
465+
request.getImages(),
466+
getThumbnailIfPresent(null, party.getCategory()),
467+
getThumbnailDetailIfPresent(null, party.getCategory())
466468
);
467469
} else {
468470
// 승인된 파티원이 없는 경우, 호스트 혼자인 경우: 모든 항목 수정 가능
@@ -474,7 +476,9 @@ public void updateParty(Long partyId, Long userId, PartyUpdateRequest request) {
474476
updatedPickupLocation,
475477
request.getProductLink(),
476478
request.getDescription(),
477-
request.getImages()
479+
request.getImages(),
480+
getThumbnailIfPresent(null, party.getCategory()),
481+
getThumbnailDetailIfPresent(null, party.getCategory())
478482
);
479483

480484
// pickupLocation이 변경된 경우에만 town 업데이트
@@ -706,6 +710,22 @@ public void settleParty(Long partyId, Long hostId) {
706710
notificationFacade.notifyPartyComplete(memberIds, party.getId());
707711
}
708712

713+
/**
714+
* 파티 대표 이미지 설정
715+
*/
716+
@Transactional
717+
public void updateThumbnail(Long partyId, Long userId, String thumbnailImage) {
718+
Party party = partyRepository.findById(partyId)
719+
.orElseThrow(() -> new IllegalArgumentException("파티를 찾을 수 없습니다"));
720+
721+
// 파티장 권한 확인
722+
if (!party.getHost().getUserId().equals(userId)) {
723+
throw new IllegalStateException("파티장만 대표 이미지를 설정할 수 있습니다");
724+
}
725+
726+
party.updateThumbnail(thumbnailImage);
727+
}
728+
709729
// ========== Private Methods ==========
710730

711731
private void validateJoinRequest(Party party, User user) {
@@ -809,7 +829,7 @@ private String getThumbnailDetailIfPresent(List<String> images, PartyCategory ca
809829
case DELIVERY -> defaultDeliveryDetailImage;
810830
case GROCERY -> defaultGroceryDetailImage;
811831
case HOUSEHOLD -> defaultHouseholdDetailImage;
812-
default -> throw new IllegalArgumentException("존재하지 않는 카테고리입니다: " + category);
832+
default -> throw new IllegalArgumentException("존f재하지 않는 카테고리입니다: " + category);
813833
};
814834
}
815835

0 commit comments

Comments
 (0)