Skip to content

음향장비 매물 수정 api 구현 #126

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

Merged
merged 1 commit into from
May 18, 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,45 @@
package com.ajou.hertz.domain.instrument.audio_equipment.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.audio_equipment.constant.AudioEquipmentType;
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 AudioEquipmentUpdateRequest extends InstrumentUpdateRequest {

@NotNull
private AudioEquipmentType type;

private AudioEquipmentUpdateRequest(
@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 AudioEquipmentType type
) {
super(title, progressStatus, tradeAddress, qualityStatus, price, hasAnomaly, description,
deletedImageIds, newImages, deletedHashtagIds, newHashtags);
this.type = type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.ajou.hertz.common.entity.Address;
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
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 @@ -57,4 +59,10 @@ public static AudioEquipment create(
qualityStatus, price, hasAnomaly, description, type
);
}

public void update(InstrumentUpdateRequest updateRequest) {
AudioEquipmentUpdateRequest audioEquipmentUpdateRequest = (AudioEquipmentUpdateRequest)updateRequest;
super.update(updateRequest);
this.type = audioEquipmentUpdateRequest.getType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.ajou.hertz.domain.instrument.amplifier.dto.response.AmplifierResponse;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentFilterConditions;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.CreateNewAudioEquipmentRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.response.AudioEquipmentResponse;
import com.ajou.hertz.domain.instrument.bass_guitar.dto.BassGuitarDto;
Expand Down Expand Up @@ -541,6 +542,29 @@ public EffectorResponse updateEffectorV1(
return InstrumentMapper.toEffectorResponse(effectorDto);
}

@Operation(
summary = "음향장비 매물 수정",
description = """
<p>음향장비 매물 정보를 수정합니다.
<p>요청 시 <strong>multipart/form-data</strong> content-type으로 요쳥해야 합니다.
<p>변경하고자 하는 매물 정보만 request body에 담아 요청하면 됩니다. 요청 시 보내지 않은 필드는 수정하지 않습니다.
""",
security = @SecurityRequirement(name = "access-token")
)
@PatchMapping("/audio-equipments/{audioEquipmentsId}")
public AudioEquipmentResponse updateAudioEquipmentsV1(
@AuthenticationPrincipal UserPrincipal userPrincipal,
@Parameter(description = "수정하고자 하는 악기 매물의 id", example = "2") @PathVariable Long audioEquipmentsId,
@ParameterObject @ModelAttribute @Valid AudioEquipmentUpdateRequest updateRequest
) {
AudioEquipmentDto audioEquipmentDto = instrumentCommandService.updateAudioEquipment(
userPrincipal.getUserId(),
audioEquipmentsId,
updateRequest
);
return InstrumentMapper.toAudioEquipmentResponse(audioEquipmentDto);
}

@Operation(
summary = "악기 매물 삭제",
description = "악기 매물을 삭제합니다. 매물 삭제는 판매자만 할 수 있습니다.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package com.ajou.hertz.domain.instrument.service;

import java.util.Collection;
import java.util.List;

import org.springframework.stereotype.Service;
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;
Expand All @@ -11,6 +17,7 @@
import com.ajou.hertz.domain.instrument.amplifier.entity.Amplifier;
import com.ajou.hertz.domain.instrument.amplifier.strategy.AmplifierCreationStrategy;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.CreateNewAudioEquipmentRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.entity.AudioEquipment;
import com.ajou.hertz.domain.instrument.audio_equipment.strategy.AudioEquipmentCreationStrategy;
Expand Down Expand Up @@ -41,12 +48,8 @@
import com.ajou.hertz.domain.instrument.strategy.InstrumentCreationStrategy;
import com.ajou.hertz.domain.user.entity.User;
import com.ajou.hertz.domain.user.service.UserQueryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Transactional
Expand Down Expand Up @@ -281,14 +284,30 @@ public EffectorDto updateEffector(
return (EffectorDto)updateInstrument(userId, effectorId, updateRequest);
}

/**
* 음향장비 매물 정보를 수정한다.
*
* @param userId 수정하고자 하는 유저의 id. 악기 판매자와 동일해야 한다.
* @param audioEquipmentsId 수정할 일렉 기타의 id
* @param updateRequest 수정하고자 하는 정보
* @return 수정된 일렉 기타 매물 정보
*/
public AudioEquipmentDto updateAudioEquipment(
Long userId,
Long audioEquipmentsId,
AudioEquipmentUpdateRequest updateRequest
) {
return (AudioEquipmentDto)updateInstrument(userId, audioEquipmentsId, updateRequest);
}

/**
* 판매자가 <code>sellerId</code>와 일치하는 모든 악기 매물 데이터에서 판매자를 제거한다. (회원 탈퇴 시 사용)
*
* @param sellerId id of seller(user)
*/
public void removeSellerFromInstruments(Long sellerId) {
instrumentRepository.findAllBySellerId(sellerId)
.forEach(Instrument::removeSeller);
.forEach(Instrument::removeSeller);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentFilterConditions;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.CreateNewAudioEquipmentRequest;
import com.ajou.hertz.domain.instrument.bass_guitar.constant.BassGuitarBrand;
import com.ajou.hertz.domain.instrument.bass_guitar.constant.BassGuitarPickUp;
Expand Down Expand Up @@ -833,6 +834,45 @@ public InstrumentControllerTest(MockMvc mvc) {
verifyEveryMocksShouldHaveNoMoreInteractions();
}

@Test
void 수정할_음향장비_정보가_주어지고_주어진_정보로_매물_정보를_수정한다() throws Exception {
// given
long userId = 1L;
long audioEquipmentsId = 2L;
AudioEquipmentUpdateRequest updateRequest = createAudioEquipmentUpdateRequest();
AudioEquipmentDto expectedResult = createAudioEquipmentDto(audioEquipmentsId, userId);
given(instrumentCommandService.updateAudioEquipment(
eq(userId),
eq(audioEquipmentsId),
any(AudioEquipmentUpdateRequest.class)
)).willReturn(expectedResult);

// when & then
mvc.perform(
multipart("/api/instruments/audio-equipments/{audioEquipmentsId}", audioEquipmentsId)
.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("type", String.valueOf(updateRequest.getType()))
.with(user(createTestUser(userId)))
.with(request -> {
request.setMethod("PATCH");
return request;
})
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(expectedResult.getId()));
then(instrumentCommandService)
.should()
.updateAudioEquipment(eq(userId), eq(audioEquipmentsId),
any(AudioEquipmentUpdateRequest.class));
verifyEveryMocksShouldHaveNoMoreInteractions();
}

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

private AudioEquipmentUpdateRequest createAudioEquipmentUpdateRequest() throws Exception {
return ReflectionUtils.createAudioEquipmentUpdateRequest(
"Test AudioEquipment",
InstrumentProgressStatus.SOLD_OUT,
createAddressRequest(),
(short)3,
550000,
true,
"description",
null,
null,
null,
null,
AudioEquipmentType.AUDIO_EQUIPMENT
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.ajou.hertz.domain.instrument.amplifier.entity.Amplifier;
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.CreateNewAudioEquipmentRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.entity.AudioEquipment;
import com.ajou.hertz.domain.instrument.bass_guitar.constant.BassGuitarBrand;
Expand Down Expand Up @@ -456,6 +457,36 @@ class InstrumentCommandServiceTest {
assertThat(result.getImages()).hasSize(newImages.size());
}

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

// when
AudioEquipmentDto result = sut.updateAudioEquipment(userId, instrumentId, updateRequest);

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

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

private AudioEquipmentUpdateRequest createAudioEquipmentUpdateRequest(
@Nullable List<Long> deletedImageIds,
@Nullable List<MultipartFile> newImages,
@Nullable List<Long> deletedHashtagIds,
@Nullable List<String> newHashtags
) throws Exception {
return ReflectionUtils.createAudioEquipmentUpdateRequest(
null, null, null, null, null, null, null,
deletedImageIds, newImages, deletedHashtagIds, newHashtags,
null
);
}
}
37 changes: 37 additions & 0 deletions src/test/java/com/ajou/hertz/util/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.ajou.hertz.domain.instrument.audio_equipment.constant.AudioEquipmentType;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.AudioEquipmentDto;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentFilterConditions;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentUpdateRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.CreateNewAudioEquipmentRequest;
import com.ajou.hertz.domain.instrument.audio_equipment.entity.AudioEquipment;
import com.ajou.hertz.domain.instrument.bass_guitar.constant.BassGuitarBrand;
Expand Down Expand Up @@ -1139,6 +1140,42 @@ public static EffectorUpdateRequest createEffectorUpdateRequest(
);
}

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

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