Skip to content

Commit

Permalink
[MERGE] feat/#293 -> dev
Browse files Browse the repository at this point in the history
[FEAT/#293] 배너 수정 API 구현
  • Loading branch information
sung-silver authored Jan 18, 2025
2 parents b5b9d26 + b310e0c commit f5fc166
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import org.sopt.makers.operation.dto.BaseResponse;

import org.sopt.makers.operation.web.banner.dto.request.*;
import org.sopt.makers.operation.web.banner.dto.request.BannerRequest;
import org.springframework.http.ResponseEntity;

public interface BannerApi {
Expand Down Expand Up @@ -129,6 +129,24 @@ public interface BannerApi {
)
}
)
ResponseEntity<BaseResponse<?>> createBanner(BannerRequest.BannerCreate request);
ResponseEntity<BaseResponse<?>> createBanner(BannerRequest.BannerCreateOrModify request);

@Operation(
summary = "배너 수정 API",
responses = {
@ApiResponse(
responseCode = "200",
description = "배너 수정 성공"
),
@ApiResponse(
responseCode = "400",
description = "잘못된 요청"
),
@ApiResponse(
responseCode = "500",
description = "서버 내부 오류"
)
}
)
ResponseEntity<BaseResponse<?>> updateBanner(Long bannerId, BannerRequest.BannerCreateOrModify request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

import org.springframework.web.bind.annotation.*;

import static org.sopt.makers.operation.code.success.web.BannerSuccessCode.SUCCESS_CREATE_BANNER;
import static org.sopt.makers.operation.code.success.web.BannerSuccessCode.SUCCESS_GET_BANNER_DETAIL;
import static org.sopt.makers.operation.code.success.web.BannerSuccessCode.SUCCESS_GET_BANNER_IMAGE_PRE_SIGNED_URL;
import static org.sopt.makers.operation.code.success.web.BannerSuccessCode.SUCCESS_UPDATE_BANNER;

@RestController
@RequestMapping("/api/v1/banners")
@RequiredArgsConstructor
Expand All @@ -37,6 +42,20 @@ public ResponseEntity<BaseResponse<?>> getBannerDetail(
return ApiResponseUtil.success(SUCCESS_GET_BANNER_DETAIL, response);
}

@PostMapping
@Override
public ResponseEntity<BaseResponse<?>> createBanner(@RequestBody BannerRequest.BannerCreateOrModify request) {
val response = bannerService.createBanner(request);
return ApiResponseUtil.success(SUCCESS_CREATE_BANNER, response);
}

@PutMapping("/{bannerId}")
@Override
public ResponseEntity<BaseResponse<?>> updateBanner(@PathVariable("bannerId") Long bannerId, BannerRequest.BannerCreateOrModify request) {
val response = bannerService.updateBanner(bannerId, request);
return ApiResponseUtil.success(SUCCESS_UPDATE_BANNER, response);
}

@Override
@GetMapping
public ResponseEntity<BaseResponse<?>> getBanners(
Expand Down Expand Up @@ -81,13 +100,4 @@ public ResponseEntity<BaseResponse<?>> getIssuedPreSignedUrlForPutImage(
imageExtension, contentType);
return ApiResponseUtil.success(SUCCESS_GET_BANNER_IMAGE_PRE_SIGNED_URL, response);
}

@PostMapping
@Override
public ResponseEntity<BaseResponse<?>> createBanner(
@RequestBody BannerRequest.BannerCreate request
) {
val response = bannerService.createBanner(request);
return ApiResponseUtil.success(SUCCESS_CREATE_BANNER, response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@RequiredArgsConstructor(access = PRIVATE)
public class BannerRequest {

public record BannerCreate(
public record BannerCreateOrModify(
@JsonProperty("location") String bannerLocation,
@JsonProperty("content_type") String bannerType,
@JsonProperty("publisher") String publisher,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.sopt.makers.operation.web.banner.service;

import org.sopt.makers.operation.web.banner.dto.request.BannerRequest;

import java.util.Arrays;
import java.util.List;

import org.sopt.makers.operation.code.failure.BannerFailureCode;
import org.sopt.makers.operation.exception.BannerException;
import org.sopt.makers.operation.web.banner.dto.request.*;
import org.sopt.makers.operation.web.banner.dto.response.BannerResponse;
import org.sopt.makers.operation.web.banner.dto.response.BannerResponse.BannerImageUrl;

Expand All @@ -19,7 +20,9 @@ public interface BannerService {

BannerResponse.ImagePreSignedUrl getIssuedPreSignedUrlForPutImage(String contentName, String imageType, String imageExtension, String contentType);

BannerResponse.BannerDetail createBanner(BannerRequest.BannerCreate request);
BannerResponse.BannerDetail createBanner(BannerRequest.BannerCreateOrModify request);

BannerResponse.BannerDetail updateBanner(Long bannerId, BannerRequest.BannerCreateOrModify request);

List<BannerResponse.BannerSimple> getBanners(final FilterCriteria status, final SortCriteria sort);

Expand Down Expand Up @@ -62,5 +65,4 @@ public static SortCriteria fromParameter(String parameter) {
.findAny().orElseThrow(() -> new BannerException(BannerFailureCode.INVALID_BANNER_SORT_CRITERIA_PARAMETER));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.sopt.makers.operation.code.failure.BannerFailureCode;
import org.sopt.makers.operation.config.ValueConfig;
import org.sopt.makers.operation.exception.BannerException;
import org.sopt.makers.operation.web.banner.dto.request.BannerRequest.*;
import org.sopt.makers.operation.web.banner.dto.request.*;
import org.sopt.makers.operation.web.banner.dto.response.BannerResponse;
import org.sopt.makers.operation.web.banner.dto.response.BannerResponse.*;
import org.springframework.stereotype.Service;
Expand All @@ -27,7 +27,9 @@
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BannerServiceImpl implements BannerService {

private static final String SLASH = "/";
private static final String PROTOCOL_SEPARATOR = "//";
private static final int PROTOCOL_END_OFFSET = 2;
private final BannerRepository bannerRepository;
private final S3Service s3Service;
private final ValueConfig valueConfig;
Expand Down Expand Up @@ -84,7 +86,7 @@ private String getBannerImageName(String location, String contentName, String im

@Transactional
@Override
public BannerDetail createBanner(BannerCreate request) {
public BannerDetail createBanner(BannerRequest.BannerCreateOrModify request) {
val period = getPublishPeriod(request.startDate(), request.endDate());
val image = getBannerImage(request.pcImage(), request.mobileImage());
val newBanner = Banner.builder()
Expand All @@ -100,6 +102,31 @@ public BannerDetail createBanner(BannerCreate request) {
return BannerResponse.BannerDetail.fromEntity(banner);
}

@Transactional
@Override
public BannerDetail updateBanner(Long bannerId, BannerRequest.BannerCreateOrModify request) {
var banner = getBannerById(bannerId);
val period = getPublishPeriod(request.startDate(), request.endDate());
val image = getBannerImage(request.pcImage(), request.mobileImage());

deleteExistImage(banner.getImage().getPcImageUrl());
deleteExistImage(banner.getImage().getMobileImageUrl());
banner.updatePublisher(request.publisher());
banner.updateLink(request.link());
banner.updateContentType(ContentType.getByValue(request.bannerType()));
banner.updateLocation(PublishLocation.getByValue(request.bannerLocation()));
banner.updatePeriod(period);
banner.updateImage(image);
return BannerResponse.BannerDetail.fromEntity(banner);
}

private void deleteExistImage(String url) {
val protocolEndIndex = url.indexOf(PROTOCOL_SEPARATOR) + PROTOCOL_END_OFFSET;
val firstSlashIndex = url.indexOf(SLASH, protocolEndIndex);
val extractedPath = url.substring(firstSlashIndex);
s3Service.deleteFile(valueConfig.getBannerBucket(), extractedPath);
}

@Override
public List<BannerSimple> getBanners(FilterCriteria filter, SortCriteria sort) {
val allBanners = bannerRepository.findAll();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ class CreateBannerTests {
@DisplayName("(POST) New Banner")
void createNewBanner() throws Exception {
// given
BannerCreate bannerCreate = new BannerCreate("pg_community", "product", "publisher",
BannerCreateOrModify bannerCreate = new BannerCreateOrModify("pg_community", "product", "publisher",
LocalDate.of(2024, 1, 1), LocalDate.of(2024, 12, 31), "link", "image-url-pc", "image-url-mobile");
BannerResponse.BannerDetail mockBannerDetail = new BannerResponse.BannerDetail(
MOCK_BANNER_ID, "in_progress", "pg_community", "product", "publisher", "link",
LocalDate.of(2024, 1, 1), LocalDate.of(2024, 12, 31), "image-url-pc", "image-url-mobile");
String request = objectMapper.writeValueAsString(bannerCreate);
when(bannerService.createBanner(any(BannerCreate.class))).thenReturn(mockBannerDetail);
when(bannerService.createBanner(any(BannerCreateOrModify.class))).thenReturn(mockBannerDetail);

// when
mockMvc.perform(post("/api/v1/banners")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public enum BannerSuccessCode implements SuccessCode {
SUCCESS_DELETE_BANNER(HttpStatus. NO_CONTENT, "배너 삭제 성공"),
SUCCESS_GET_EXTERNAL_BANNERS(HttpStatus.OK, "외부 배너 조회 성공"),
SUCCESS_GET_BANNER_IMAGE_PRE_SIGNED_URL(HttpStatus.OK, "이미지 업로드 pre signed url 조회에 성공했습니다"),
SUCCESS_UPDATE_BANNER(HttpStatus.OK, "배너 수정에 성공했습니다"),
SUCCESS_CREATE_BANNER(HttpStatus.CREATED, "배너 생성에 성공했습니다")
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,10 @@ public void updateContentType(ContentType contentType) {
public void updatePublisher(String publisher) {
this.publisher = publisher;
}

public void updateLink(String link) { this.link = link;}

public void updatePeriod(PublishPeriod period) { this.period = period; }

public void updateImage(BannerImage image) { this.image = image; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ public interface S3Service {
String createPreSignedUrlForPutObject(String bucketName, String fileName);

String getUrl(String bucketName, String fileName);

void deleteFile(String bucketName, String fileName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public String getUrl(String bucketName, String fileName) {
}
}

public void deleteFile(String bucketName, String fileName){
@Override
public void deleteFile(String bucketName, String fileName) {
s3Client.deleteObject(b -> b.bucket(bucketName).key(fileName));
}
}

0 comments on commit f5fc166

Please sign in to comment.