Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

어쿠스틱 & 클래식 기타 매물 수정 api 구현 #118

Merged
merged 1 commit into from
May 16, 2024
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
@@ -0,0 +1,63 @@
package com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request;

import java.util.List;

import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;

import com.ajou.hertz.common.dto.request.AddressRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarBrand;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarModel;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarPickUp;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarWood;
import com.ajou.hertz.domain.instrument.constant.InstrumentProgressStatus;
import com.ajou.hertz.domain.instrument.dto.request.InstrumentUpdateRequest;

import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Setter
@Getter
public class AcousticAndClassicGuitarUpdateRequest extends InstrumentUpdateRequest {

@Nullable
private AcousticAndClassicGuitarBrand brand;

@Nullable
private AcousticAndClassicGuitarModel model;

@NotNull
private AcousticAndClassicGuitarWood wood;

@NotNull
private AcousticAndClassicGuitarPickUp pickUp;

private AcousticAndClassicGuitarUpdateRequest(
@Nullable String title,
@Nullable InstrumentProgressStatus progressStatus,
@Nullable AddressRequest tradeAddress,
@Nullable Short qualityStatus,
@Nullable Integer price,
@Nullable Boolean hasAnomaly,
@Nullable String description,
@Nullable List<Long> deletedImageIds,
@Nullable List<MultipartFile> newImages,
@Nullable List<Long> deletedHashtagIds,
@Nullable List<String> newHashtags,
@Nullable AcousticAndClassicGuitarBrand brand,
@Nullable AcousticAndClassicGuitarModel model,
@Nullable AcousticAndClassicGuitarWood wood,
@Nullable AcousticAndClassicGuitarPickUp pickUp
) {
super(title, progressStatus, tradeAddress, qualityStatus, price, hasAnomaly, description,
deletedImageIds, newImages, deletedHashtagIds, newHashtags);
this.brand = brand;
this.model = model;
this.wood = wood;
this.pickUp = pickUp;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarModel;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarPickUp;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarWood;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.constant.InstrumentProgressStatus;
import com.ajou.hertz.domain.instrument.dto.request.InstrumentUpdateRequest;
import com.ajou.hertz.domain.instrument.entity.Instrument;
import com.ajou.hertz.domain.user.entity.User;

Expand Down Expand Up @@ -81,4 +83,13 @@ public static AcousticAndClassicGuitar create(
price, hasAnomaly, description, brand, model, wood, pickUp
);
}

public void update(InstrumentUpdateRequest updateRequest) {
AcousticAndClassicGuitarUpdateRequest acousticAndClassicGuitarUpdateRequest = (AcousticAndClassicGuitarUpdateRequest)updateRequest;
super.update(updateRequest);
this.brand = acousticAndClassicGuitarUpdateRequest.getBrand();
this.model = acousticAndClassicGuitarUpdateRequest.getModel();
this.wood = acousticAndClassicGuitarUpdateRequest.getWood();
this.pickUp = acousticAndClassicGuitarUpdateRequest.getPickUp();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.ajou.hertz.common.auth.UserPrincipal;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.AcousticAndClassicGuitarDto;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarFilterConditions;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.CreateNewAcousticAndClassicGuitarRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.response.AcousticAndClassicGuitarResponse;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
Expand Down Expand Up @@ -469,6 +470,29 @@ public ElectricGuitarResponse updateElectricGuitarV1(
return InstrumentMapper.toElectricGuitarResponse(electricGuitarDto);
}

@Operation(
summary = "어쿠스틱 기타 매물 수정",
description = """
<p>어쿠스틱 기타 매물 정보를 수정합니다.
<p>요청 시 <strong>multipart/form-data</strong> content-type으로 요쳥해야 합니다.
<p>변경하고자 하는 매물 정보만 request body에 담아 요청하면 됩니다. 요청 시 보내지 않은 필드는 수정하지 않습니다.
""",
security = @SecurityRequirement(name = "access-token")
)
@PatchMapping("/acoustic-and-classic-guitars/{AcousticAndClassicGuitarId}")
public AcousticAndClassicGuitarResponse updateAcousticAndClassicGuitarV1(
@AuthenticationPrincipal UserPrincipal userPrincipal,
@Parameter(description = "수정하고자 하는 악기 매물의 id", example = "2") @PathVariable Long AcousticAndClassicGuitarId,
@ParameterObject @ModelAttribute @Valid AcousticAndClassicGuitarUpdateRequest updateRequest
) {
AcousticAndClassicGuitarDto acousticAndClassicGuitarDto = instrumentCommandService.updateAcousticAndClassicGuitar(
userPrincipal.getUserId(),
AcousticAndClassicGuitarId,
updateRequest
);
return InstrumentMapper.toAcousticAndClassicGuitarResponse(acousticAndClassicGuitarDto);
}

@Operation(
summary = "악기 매물 삭제",
description = "악기 매물을 삭제합니다. 매물 삭제는 판매자만 할 수 있습니다.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.transaction.annotation.Transactional;

import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.AcousticAndClassicGuitarDto;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.CreateNewAcousticAndClassicGuitarRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.entity.AcousticAndClassicGuitar;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.strategy.AcousticAndClassicGuitarCreationStrategy;
Expand Down Expand Up @@ -232,6 +233,22 @@ public ElectricGuitarDto updateElectricGuitar(
return (ElectricGuitarDto)updateInstrument(userId, electricGuitarId, updateRequest);
}

/**
* 어쿠스틱 & 클래식 기타 매물 정보를 수정한다.
*
* @param userId 수정하고자 하는 유저의 id. 악기 판매자와 동일해야 한다.
* @param acousticAndClassicGuitarId 수정할 일렉 기타의 id
* @param updateRequest 수정하고자 하는 정보
* @return 수정된 일렉 기타 매물 정보
*/
public AcousticAndClassicGuitarDto updateAcousticAndClassicGuitar(
Long userId,
Long acousticAndClassicGuitarId,
AcousticAndClassicGuitarUpdateRequest updateRequest
) {
return (AcousticAndClassicGuitarDto)updateInstrument(userId, acousticAndClassicGuitarId, updateRequest);
}

/**
* 악기 매물을 삭제한다.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarWood;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.AcousticAndClassicGuitarDto;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarFilterConditions;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.CreateNewAcousticAndClassicGuitarRequest;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierBrand;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierType;
Expand Down Expand Up @@ -705,6 +706,50 @@ public InstrumentControllerTest(MockMvc mvc) {
verifyEveryMocksShouldHaveNoMoreInteractions();
}

@Test
void 수정할_어쿠스틱기타와_클래식기타_정보가_주어지고_주어진_정보로_매물_정보를_수정한다() throws Exception {
// given
long userId = 1L;
long acousticAndClassicGuitarId = 2L;
AcousticAndClassicGuitarUpdateRequest updateRequest = createAcousticAndClassicGuitarUpdateRequest();
AcousticAndClassicGuitarDto expectedResult = createAcousticAndClassicGuitarDto(acousticAndClassicGuitarId,
userId);
given(instrumentCommandService.updateAcousticAndClassicGuitar(
eq(userId),
eq(acousticAndClassicGuitarId),
any(AcousticAndClassicGuitarUpdateRequest.class)
)).willReturn(expectedResult);

// when & then
mvc.perform(
multipart("/api/instruments/acoustic-and-classic-guitars/{acousticAndClassicGuitarId}",
acousticAndClassicGuitarId)
.header(API_VERSION_HEADER_NAME, 1)
.param("title", updateRequest.getTitle())
.param("progressStatus", String.valueOf(updateRequest.getProgressStatus()))
.param("qualityStatus", String.valueOf(updateRequest.getQualityStatus()))
.param("price", String.valueOf(updateRequest.getPrice()))
.param("hasAnomaly", String.valueOf(updateRequest.getHasAnomaly()))
.param("description", updateRequest.getDescription())
.param("brand", String.valueOf(updateRequest.getBrand()))
.param("model", String.valueOf(updateRequest.getModel()))
.param("wood", String.valueOf(updateRequest.getWood()))
.param("pickUp", String.valueOf(updateRequest.getPickUp()))
.with(user(createTestUser(userId)))
.with(request -> {
request.setMethod("PATCH");
return request;
})
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(expectedResult.getId()));
then(instrumentCommandService)
.should()
.updateAcousticAndClassicGuitar(eq(userId), eq(acousticAndClassicGuitarId),
any(AcousticAndClassicGuitarUpdateRequest.class));
verifyEveryMocksShouldHaveNoMoreInteractions();
}

@Test
void 악기_id가_주어지고_해당하는_악기_매물을_삭제한다() throws Exception {
// given
Expand Down Expand Up @@ -1046,4 +1091,25 @@ private ElectricGuitarUpdateRequest createElectricGuitarUpdateRequest() throws E
GuitarColor.RED
);
}

private AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuitarUpdateRequest() throws Exception {
return ReflectionUtils.createAcousticAndClassicGuitarUpdateRequest(
"Test AcousticAndClassicGuitar",
InstrumentProgressStatus.SOLD_OUT,
createAddressRequest(),
(short)3,
550000,
true,
"description",
null,
null,
null,
null,
AcousticAndClassicGuitarBrand.CRAFTER,
AcousticAndClassicGuitarModel.CUTAWAY,
AcousticAndClassicGuitarWood.SOLID_WOOD,
AcousticAndClassicGuitarPickUp.MAGNETIC
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarPickUp;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarWood;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.AcousticAndClassicGuitarDto;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.CreateNewAcousticAndClassicGuitarRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.entity.AcousticAndClassicGuitar;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierBrand;
Expand Down Expand Up @@ -334,6 +335,35 @@ class InstrumentCommandServiceTest {
assertThat(result.getImages()).hasSize(initialImages.size() - deleteImageIds.size());
}

@Test
void 삭제할_이미지들의_id_리스트가_주어지고_어쿠스틱_매물_정보를_수정하면_악기_이미지들이_삭제된다() throws Exception {
// given
long userId = 1L;
long instrumentId = 2L;
List<Long> deleteImageIds = List.of(3L, 4L);
AcousticAndClassicGuitar AcousticAndClassicGuitar = createAcousticAndClassicGuitar(instrumentId,
createUser(userId));
List<InstrumentImage> initialImages = List.of(
createInstrumentImage(deleteImageIds.get(0), AcousticAndClassicGuitar),
createInstrumentImage(deleteImageIds.get(1), AcousticAndClassicGuitar)
);
AcousticAndClassicGuitar.getImages().addAll(initialImages);
AcousticAndClassicGuitarUpdateRequest updateRequest = createAcousticAndClassicGuitarUpdateRequest(
deleteImageIds, null, null, null);
given(instrumentQueryService.getInstrumentById(instrumentId))
.willReturn(AcousticAndClassicGuitar);
willDoNothing().given(instrumentImageCommandService).deleteAllByIds(deleteImageIds);

// when
AcousticAndClassicGuitarDto result = sut.updateAcousticAndClassicGuitar(userId, instrumentId, updateRequest);

// then
then(instrumentQueryService).should().getInstrumentById(instrumentId);
then(instrumentImageCommandService).should().deleteAllByIds(deleteImageIds);
verifyEveryMocksShouldHaveNoMoreInteractions();
assertThat(result.getImages()).hasSize(initialImages.size() - deleteImageIds.size());
}

@Test
void 추가할_이미지들이_주어지고_매물_정보를_수정하면_새로운_악기_이미지들이_추가된다() throws Exception {
// given
Expand Down Expand Up @@ -749,4 +779,17 @@ private ElectricGuitarUpdateRequest createElectricGuitarUpdateRequest(
null, null, null, null
);
}

private AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuitarUpdateRequest(
@Nullable List<Long> deletedImageIds,
@Nullable List<MultipartFile> newImages,
@Nullable List<Long> deletedHashtagIds,
@Nullable List<String> newHashtags
) throws Exception {
return ReflectionUtils.createAcousticAndClassicGuitarUpdateRequest(
null, null, null, null, null, null, null,
deletedImageIds, newImages, deletedHashtagIds, newHashtags,
null, null, null, null
);
}
}
44 changes: 44 additions & 0 deletions src/test/java/com/ajou/hertz/util/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.constant.AcousticAndClassicGuitarWood;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.AcousticAndClassicGuitarDto;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarFilterConditions;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.AcousticAndClassicGuitarUpdateRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.dto.request.CreateNewAcousticAndClassicGuitarRequest;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.entity.AcousticAndClassicGuitar;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierBrand;
Expand Down Expand Up @@ -882,6 +883,49 @@ public static ElectricGuitarUpdateRequest createElectricGuitarUpdateRequest(
);
}

public static AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuitarUpdateRequest(
@Nullable String title,
@Nullable InstrumentProgressStatus progressStatus,
@Nullable AddressRequest tradeAddress,
@Nullable Short qualityStatus,
@Nullable Integer price,
@Nullable Boolean hasAnomaly,
@Nullable String description,
@Nullable List<Long> deletedImageIds,
@Nullable List<MultipartFile> newImages,
@Nullable List<Long> deletedHashtagIds,
@Nullable List<String> newHashtags,
@Nullable AcousticAndClassicGuitarBrand brand,
@Nullable AcousticAndClassicGuitarModel model,
@Nullable AcousticAndClassicGuitarWood wood,
@Nullable AcousticAndClassicGuitarPickUp pickUp
) throws Exception {
Constructor<AcousticAndClassicGuitarUpdateRequest> constructor = AcousticAndClassicGuitarUpdateRequest.class.getDeclaredConstructor(
String.class, InstrumentProgressStatus.class, AddressRequest.class, Short.class,
Integer.class, Boolean.class, String.class, List.class, List.class, List.class, List.class,
AcousticAndClassicGuitarBrand.class, AcousticAndClassicGuitarModel.class,
AcousticAndClassicGuitarWood.class, AcousticAndClassicGuitarPickUp.class
);
constructor.setAccessible(true);
return constructor.newInstance(
title,
progressStatus,
tradeAddress,
qualityStatus,
price,
hasAnomaly,
description,
deletedImageIds,
newImages,
deletedHashtagIds,
newHashtags,
brand,
model,
wood,
pickUp
);
}

public static SendUserAuthCodeRequest createSendUserAuthCodeRequest(String phoneNumber) throws Exception {
Constructor<SendUserAuthCodeRequest> constructor =
SendUserAuthCodeRequest.class.getDeclaredConstructor(String.class);
Expand Down
Loading