Skip to content

Commit

Permalink
Merge pull request #119 from Ajou-Hertz/feature/#116-update-amplifier
Browse files Browse the repository at this point in the history
앰프 매물 수정 api 구현
  • Loading branch information
Wo-ogie authored May 18, 2024
2 parents 1e71a01 + 9423e78 commit d09580e
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.ajou.hertz.domain.instrument.amplifier.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.amplifier.constant.AmplifierBrand;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierType;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierUsage;
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 AmplifierUpdateRequest extends InstrumentUpdateRequest {

@NotNull
private AmplifierType type;

@NotNull
private AmplifierBrand brand;

@NotNull
private AmplifierUsage usage;

private AmplifierUpdateRequest(
@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 AmplifierType type,
@Nullable AmplifierBrand brand,
@Nullable AmplifierUsage usage
) {
super(title, progressStatus, tradeAddress, qualityStatus, price, hasAnomaly, description,
deletedImageIds, newImages, deletedHashtagIds, newHashtags);
this.type = type;
this.brand = brand;
this.usage = usage;
}
}
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.dto.response.AcousticAndClassicGuitarResponse;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierFilterConditions;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierUpdateRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.CreateNewAmplifierRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.response.AmplifierResponse;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
Expand Down Expand Up @@ -493,6 +494,29 @@ public AcousticAndClassicGuitarResponse updateAcousticAndClassicGuitarV1(
return InstrumentMapper.toAcousticAndClassicGuitarResponse(acousticAndClassicGuitarDto);
}

@Operation(
summary = "앰프 매물 수정",
description = """
<p>앰프 매물 정보를 수정합니다.
<p>요청 시 <strong>multipart/form-data</strong> content-type으로 요쳥해야 합니다.
<p>변경하고자 하는 매물 정보만 request body에 담아 요청하면 됩니다. 요청 시 보내지 않은 필드는 수정하지 않습니다.
""",
security = @SecurityRequirement(name = "access-token")
)
@PatchMapping("/amplifiers/{AmplifierId}")
public AmplifierResponse updateAmplifiersV1(
@AuthenticationPrincipal UserPrincipal userPrincipal,
@Parameter(description = "수정하고자 하는 악기 매물의 id", example = "2") @PathVariable Long AmplifierId,
@ParameterObject @ModelAttribute @Valid AmplifierUpdateRequest updateRequest
) {
AmplifierDto amplifierDto = instrumentCommandService.updateAmplifier(
userPrincipal.getUserId(),
AmplifierId,
updateRequest
);
return InstrumentMapper.toAmplifierResponse(amplifierDto);
}

@Operation(
summary = "악기 매물 삭제",
description = "악기 매물을 삭제합니다. 매물 삭제는 판매자만 할 수 있습니다.",
Expand All @@ -510,4 +534,5 @@ public ResponseEntity<Void> deleteInstrumentV1(
instrumentCommandService.deleteInstrumentById(userPrincipal.getUserId(), instrumentId);
return ResponseEntity.noContent().build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.entity.AcousticAndClassicGuitar;
import com.ajou.hertz.domain.instrument.acoustic_and_classic_guitar.strategy.AcousticAndClassicGuitarCreationStrategy;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierUpdateRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.CreateNewAmplifierRequest;
import com.ajou.hertz.domain.instrument.amplifier.entity.Amplifier;
import com.ajou.hertz.domain.instrument.amplifier.strategy.AmplifierCreationStrategy;
Expand Down Expand Up @@ -249,6 +250,22 @@ public AcousticAndClassicGuitarDto updateAcousticAndClassicGuitar(
return (AcousticAndClassicGuitarDto)updateInstrument(userId, acousticAndClassicGuitarId, updateRequest);
}

/**
* 앰프 매물 정보를 수정한다.
*
* @param userId 수정하고자 하는 유저의 id. 악기 판매자와 동일해야 한다.
* @param amplifierId 수정할 일렉 기타의 id
* @param updateRequest 수정하고자 하는 정보
* @return 수정된 일렉 기타 매물 정보
*/
public AmplifierDto updateAmplifier(
Long userId,
Long amplifierId,
AmplifierUpdateRequest updateRequest
) {
return (AmplifierDto)updateInstrument(userId, amplifierId, updateRequest);
}

/**
* 악기 매물을 삭제한다.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierUsage;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierFilterConditions;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierUpdateRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.CreateNewAmplifierRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
Expand Down Expand Up @@ -750,6 +751,48 @@ public InstrumentControllerTest(MockMvc mvc) {
verifyEveryMocksShouldHaveNoMoreInteractions();
}

@Test
void 수정할_앰프_정보가_주어지고_주어진_정보로_매물_정보를_수정한다() throws Exception {
// given
long userId = 1L;
long amplifierId = 2L;
AmplifierUpdateRequest updateRequest = createAmplifierUpdateRequest();
AmplifierDto expectedResult = createAmplifierDto(amplifierId, userId);
given(instrumentCommandService.updateAmplifier(
eq(userId),
eq(amplifierId),
any(AmplifierUpdateRequest.class)
)).willReturn(expectedResult);

// when & then
mvc.perform(
multipart("/api/instruments/amplifiers/{amplifierId}", amplifierId)
.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("type", String.valueOf(updateRequest.getType()))
.param("brand", String.valueOf(updateRequest.getBrand()))
.param("usage", String.valueOf(updateRequest.getUsage()))
.with(user(createTestUser(userId)))
.with(request -> {
request.setMethod("PATCH");
return request;
})
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(expectedResult.getId()));
then(instrumentCommandService)
.should()
.updateAmplifier(eq(userId), eq(amplifierId),
any(AmplifierUpdateRequest.class));
verifyEveryMocksShouldHaveNoMoreInteractions();
}

@Test
void 악기_id가_주어지고_해당하는_악기_매물을_삭제한다() throws Exception {
// given
Expand Down Expand Up @@ -1112,4 +1155,23 @@ private AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuitarUpda
);
}

private AmplifierUpdateRequest createAmplifierUpdateRequest() throws Exception {
return ReflectionUtils.createAmplifierUpdateRequest(
"Test Amplifier",
InstrumentProgressStatus.SOLD_OUT,
createAddressRequest(),
(short)3,
550000,
true,
"description",
null,
null,
null,
null,
AmplifierType.GUITAR,
AmplifierBrand.FENDER,
AmplifierUsage.HOME
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierType;
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierUsage;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierUpdateRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.CreateNewAmplifierRequest;
import com.ajou.hertz.domain.instrument.amplifier.entity.Amplifier;
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
Expand Down Expand Up @@ -394,6 +395,36 @@ class InstrumentCommandServiceTest {
assertThat(result.getImages()).hasSize(newImages.size());
}

@Test
void 추가할_이미지들이_주어지고_앰프_정보를_수정하면_새로운_악기_이미지들이_추가된다() throws Exception {
// given
long userId = 1L;
long instrumentId = 2L;
Amplifier amplifier = createAmplifier(instrumentId, createUser(userId));
List<MultipartFile> newImages = List.of(
createMultipartFile(),
createMultipartFile()
);
List<InstrumentImage> newInstrumentImages = List.of(
createInstrumentImage(3L, amplifier),
createInstrumentImage(4L, amplifier)
);
AmplifierUpdateRequest updateRequest = createAmplifierUpdateRequest(List.of(), newImages, null, null);
given(instrumentQueryService.getInstrumentById(instrumentId))
.willReturn(amplifier);
given(instrumentImageCommandService.saveImages(amplifier, updateRequest.getNewImages()))
.willReturn(newInstrumentImages);

// when
AmplifierDto result = sut.updateAmplifier(userId, instrumentId, updateRequest);

// then
then(instrumentQueryService).should().getInstrumentById(instrumentId);
then(instrumentImageCommandService).should().saveImages(amplifier, updateRequest.getNewImages());
verifyEveryMocksShouldHaveNoMoreInteractions();
assertThat(result.getImages()).hasSize(newImages.size());
}

@Test
void 삭제할_해시태그들의_id_리스트가_주어지고_매물_정보를_수정하면_해시태그가_삭제된다() throws Exception {
long userId = 1L;
Expand Down Expand Up @@ -792,4 +823,17 @@ private AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuitarUpda
null, null, null, null
);
}

private AmplifierUpdateRequest createAmplifierUpdateRequest(
@Nullable List<Long> deletedImageIds,
@Nullable List<MultipartFile> newImages,
@Nullable List<Long> deletedHashtagIds,
@Nullable List<String> newHashtags
) throws Exception {
return ReflectionUtils.createAmplifierUpdateRequest(
null, null, null, null, null, null, null,
deletedImageIds, newImages, deletedHashtagIds, newHashtags,
null, null, null
);
}
}
51 changes: 46 additions & 5 deletions src/test/java/com/ajou/hertz/util/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.List;
import java.util.Set;

import com.ajou.hertz.domain.user.controller.UpdatePasswordWithoutAuthenticationRequest;
import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;

Expand Down Expand Up @@ -42,6 +41,7 @@
import com.ajou.hertz.domain.instrument.amplifier.constant.AmplifierUsage;
import com.ajou.hertz.domain.instrument.amplifier.dto.AmplifierDto;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierFilterConditions;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.AmplifierUpdateRequest;
import com.ajou.hertz.domain.instrument.amplifier.dto.request.CreateNewAmplifierRequest;
import com.ajou.hertz.domain.instrument.amplifier.entity.Amplifier;
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
Expand Down Expand Up @@ -84,6 +84,7 @@
import com.ajou.hertz.domain.practice_room.entity.PracticeRoomImage;
import com.ajou.hertz.domain.user.constant.Gender;
import com.ajou.hertz.domain.user.constant.RoleType;
import com.ajou.hertz.domain.user.controller.UpdatePasswordWithoutAuthenticationRequest;
import com.ajou.hertz.domain.user.dto.UserDto;
import com.ajou.hertz.domain.user.dto.request.SignUpRequest;
import com.ajou.hertz.domain.user.entity.User;
Expand Down Expand Up @@ -669,12 +670,12 @@ public static SignUpRequest createSignUpRequest(
}

public static UpdatePasswordWithoutAuthenticationRequest createUpdatePasswordWithoutAuthenticationRequest(
String phoneNumber,
String password,
String userAuthCode
String phoneNumber,
String password,
String userAuthCode
) throws Exception {
Constructor<UpdatePasswordWithoutAuthenticationRequest> constructor = UpdatePasswordWithoutAuthenticationRequest.class.getDeclaredConstructor(
String.class, String.class, String.class
String.class, String.class, String.class
);
constructor.setAccessible(true);
return constructor.newInstance(phoneNumber, password, userAuthCode);
Expand Down Expand Up @@ -1059,6 +1060,46 @@ public static AcousticAndClassicGuitarUpdateRequest createAcousticAndClassicGuit
);
}

public static AmplifierUpdateRequest createAmplifierUpdateRequest(
@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 AmplifierType type,
@Nullable AmplifierBrand brand,
@Nullable AmplifierUsage usage
) throws Exception {
Constructor<AmplifierUpdateRequest> constructor = AmplifierUpdateRequest.class.getDeclaredConstructor(
String.class, InstrumentProgressStatus.class, AddressRequest.class, Short.class,
Integer.class, Boolean.class, String.class, List.class, List.class, List.class, List.class,
AmplifierType.class, AmplifierBrand.class, AmplifierUsage.class
);
constructor.setAccessible(true);
return constructor.newInstance(
title,
progressStatus,
tradeAddress,
qualityStatus,
price,
hasAnomaly,
description,
deletedImageIds,
newImages,
deletedHashtagIds,
newHashtags,
type,
brand,
usage
);
}

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

0 comments on commit d09580e

Please sign in to comment.