Skip to content

Commit

Permalink
[FU-115] 사진작가측 신청서 상세보기 API 구현 (#21)
Browse files Browse the repository at this point in the history
* FU-115 refactor: 신청서 관련 DTO 클래스명 수정

신청서를 ReservationForm -> Form으로 축약해 사용하기로 결정함

* FU-115 feat: 휴대폰번호 반환 형식 수정

기존: +82 10-0000-0000
변경: 010-0000-0000

* FU-115 feat: ReservationForm 엔티티 희망일정, 고객메모 필드명 변경

* FU-115 feat: 신청서 상세보기 response dto 구성

* FU-115 feat: 사진작가측 신청서 상세보기 API 구현

* FU-115 feat: 신청서 상세보기 서비스로직 리팩토링

* FU-115 feat: 중복된 상품제목으로 상품 등록시 예외처리 추가

* FU-115 feat: 신청서 등록 및 조회 시 참고사진 추가

* FU-115 feat: response dto 필드명 수정

status -> reservationStatus

* FU-115 feat: 신청서 리스트뷰에서 새 신청서 컴포넌트의 반환형식 수정

새 신청서의 경우 희망일정을 반환하지 않음

* FU-115 chore: ToDo 주석 추가
  • Loading branch information
rheeri authored Aug 12, 2024
1 parent 261eaf9 commit 0b18a09
Show file tree
Hide file tree
Showing 31 changed files with 503 additions and 278 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/foru/freebe/FreebeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication(scanBasePackages = "com.foru.freebe")
@EnableJpaAuditing
public class FreebeApplication {
public static void main(String[] args) {
SpringApplication.run(FreebeApplication.class, args);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/foru/freebe/auth/model/KakaoUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public String getEmail() {
}

public String getPhoneNumber() {
return (String)kakaoAccount.get("phone_number");
String phoneNumber = (String)kakaoAccount.get("phone_number");
return "0" + phoneNumber.replace("+82 ", "");
}

public Integer getBirthYear() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ public enum CommonErrorCode implements ErrorCode {

INVALID_PARAMETER(400, "Invalid parameter included"),
RESOURCE_NOT_FOUND(404, "Resource not exists"),
INTERNAL_SERVER_ERROR(500, "Internal server error"),
;
INTERNAL_SERVER_ERROR(500, "Internal server error");

private final int httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
@RequiredArgsConstructor
public enum ProductErrorCode implements ErrorCode {
INVALID_ACTIVE_STATUS(400, "ActiveStatus must be different current stored ActiveStatus"),
PRODUCT_INACTIVE_STATUS(400, "The product is currently inactive, so you can't register a booking form with it");
PRODUCT_INACTIVE_STATUS(400, "The product is currently inactive, so you can't register a booking form with it"),
PRODUCT_ALREADY_EXISTS(400, "The product already exists, so it cannot be registered again");

private final int httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,37 @@

import java.util.List;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.foru.freebe.auth.model.MemberAdapter;
import com.foru.freebe.common.dto.ApiResponse;
import com.foru.freebe.member.entity.Member;
import com.foru.freebe.product.dto.customer.ProductBasicInfoResponse;
import com.foru.freebe.product.dto.customer.ProductResponse;
import com.foru.freebe.product.dto.customer.ProductDetailResponse;
import com.foru.freebe.product.dto.customer.ProductListResponse;
import com.foru.freebe.product.service.CustomerProductService;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/customer/product")
@RequestMapping("/customer")
public class CustomerProductController {
private final CustomerProductService customerProductService;

@GetMapping("/basic-info")
public ApiResponse<List<ProductBasicInfoResponse>> getBasicInfoOfAllProducts(
@AuthenticationPrincipal MemberAdapter memberAdapter) {
Member customer = memberAdapter.getMember();
return customerProductService.getBasicInfoOfAllProducts(customer.getId());
@GetMapping("/product/list/{photographerId}")
public ApiResponse<List<ProductListResponse>> getProductList(
@PathVariable("photographerId") Long photographerId) {
return customerProductService.getProductList(photographerId);
}

@GetMapping("/detail-info")
public ApiResponse<ProductResponse> getDetailedInfoOfProduct(@AuthenticationPrincipal MemberAdapter memberAdapter) {
Member customer = memberAdapter.getMember();
return customerProductService.getDetailedInfoOfProduct(customer.getId());
@GetMapping("/product/details/{productId}")
public ApiResponse<ProductDetailResponse> getProductDetails(@PathVariable("productId") Long productId) {
return customerProductService.getDetailedInfoOfProduct(productId);
}

@GetMapping("/images/{id}")
public ApiResponse<List<String>> getReferenceImages(@PathVariable("id") Long productId) {
@GetMapping("/product/images/{productId}")
public ApiResponse<List<String>> getReferenceImages(@PathVariable("productId") Long productId) {
return customerProductService.getReferenceImages(productId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("/photographer/product")
@RequestMapping("/photographer")
public class PhotographerProductController {
private final PhotographerProductService productService;

@PostMapping("/")
@PostMapping("/product")
public ApiResponse<Void> registerProduct(@AuthenticationPrincipal MemberAdapter memberAdapter,
@Valid @RequestBody ProductRegisterRequest productRegisterRequest) {
Member photographer = memberAdapter.getMember();
return productService.registerProduct(productRegisterRequest, photographer.getId());
}

@GetMapping("/registered-product/{id}")
@GetMapping("/product/list")
public ApiResponse<List<RegisteredProductResponse>> getRegisteredProductList(
@AuthenticationPrincipal MemberAdapter memberAdapter) {
Member photographer = memberAdapter.getMember();
return productService.getRegisteredProductList(photographer.getId());
}

@PutMapping("/update-status")
@PutMapping("/product/status")
public ApiResponse<Void> updateProductActiveStatus(@Valid @RequestBody UpdateProductRequest updateProductRequest) {
return productService.updateProductActiveStatus(updateProductRequest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

@Getter
@NoArgsConstructor
public class ProductResponse {
public class ProductDetailResponse {
@NotNull
private String productTitle;
private String productDescription;
Expand All @@ -25,7 +25,7 @@ public class ProductResponse {
private List<ProductDiscountDto> productDiscounts;

@Builder
public ProductResponse(String productTitle, String productDescription, List<String> productImageUrls,
public ProductDetailResponse(String productTitle, String productDescription, List<String> productImageUrls,
List<ProductComponentDto> productComponents, List<ProductOptionDto> productOptions,
List<ProductDiscountDto> productDiscounts) {
this.productTitle = productTitle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@

@Getter
@NoArgsConstructor
public class ProductBasicInfoResponse {
// TODO 상품 조회 페이지 추가 후 필드 업데이트 요망
public class ProductListResponse {
private Long productId;
private String productTitle;
private String productRepresentativeImageUrl;

@Builder
public ProductBasicInfoResponse(Long productId, String productTitle, String productRepresentativeImageUrl) {
public ProductListResponse(Long productId, String productTitle, String productRepresentativeImageUrl) {
this.productId = productId;
this.productTitle = productTitle;
this.productRepresentativeImageUrl = productRepresentativeImageUrl;
Expand Down
10 changes: 2 additions & 8 deletions src/main/java/com/foru/freebe/product/entity/ProductOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -29,6 +30,7 @@ public class ProductOption extends BaseEntity {
private String title;

@NotNull
@PositiveOrZero
private Integer price;

private String description;
Expand All @@ -43,13 +45,5 @@ private ProductOption(String title, Integer price, String description, Product p
this.price = price;
this.description = description;
this.product = product;

validatePrice(price);
}

private void validatePrice(Integer price) {
if (price <= 0) {
throw new IllegalArgumentException("Price must be greater than 0.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import com.foru.freebe.errors.exception.RestApiException;
import com.foru.freebe.member.entity.Member;
import com.foru.freebe.member.repository.MemberRepository;
import com.foru.freebe.product.dto.customer.ProductBasicInfoResponse;
import com.foru.freebe.product.dto.customer.ProductResponse;
import com.foru.freebe.product.dto.customer.ProductDetailResponse;
import com.foru.freebe.product.dto.customer.ProductListResponse;
import com.foru.freebe.product.dto.photographer.ProductComponentDto;
import com.foru.freebe.product.dto.photographer.ProductDiscountDto;
import com.foru.freebe.product.dto.photographer.ProductOptionDto;
Expand Down Expand Up @@ -53,7 +53,7 @@ public ApiResponse<List<String>> getReferenceImages(Long productId) {
.build();
}

public ApiResponse<ProductResponse> getDetailedInfoOfProduct(Long productId) {
public ApiResponse<ProductDetailResponse> getDetailedInfoOfProduct(Long productId) {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));

Expand All @@ -62,7 +62,7 @@ public ApiResponse<ProductResponse> getDetailedInfoOfProduct(Long productId) {
List<ProductOptionDto> productOptions = getProductOptions(product);
List<ProductDiscountDto> productDiscounts = getProductDiscounts(product);

ProductResponse productResponse = ProductResponse.builder()
ProductDetailResponse productDetailResponse = ProductDetailResponse.builder()
.productTitle(product.getTitle())
.productDescription(product.getDescription())
.productImageUrls(productImageUrls)
Expand All @@ -71,36 +71,36 @@ public ApiResponse<ProductResponse> getDetailedInfoOfProduct(Long productId) {
.productDiscounts(productDiscounts)
.build();

return ApiResponse.<ProductResponse>builder()
return ApiResponse.<ProductDetailResponse>builder()
.status(200)
.message("Good Response")
.data(productResponse)
.data(productDetailResponse)
.build();
}

public ApiResponse<List<ProductBasicInfoResponse>> getBasicInfoOfAllProducts(Long photographerId) {
public ApiResponse<List<ProductListResponse>> getProductList(Long photographerId) {
Member photographer = memberRepository.findById(photographerId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));

List<Product> products = productRepository.findByMember(photographer)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));

List<ProductBasicInfoResponse> productBasicInfoResponseList = new ArrayList<>();
List<ProductListResponse> productListResponseList = new ArrayList<>();
for (Product product : products) {
List<ProductImage> productImage = productImageRepository.findByProduct(product);

ProductBasicInfoResponse productBasicInfoResponse = ProductBasicInfoResponse.builder()
ProductListResponse productListResponse = ProductListResponse.builder()
.productId(product.getId())
.productTitle(product.getTitle())
.productRepresentativeImageUrl(productImage.get(0).getOriginUrl())
.build();

productBasicInfoResponseList.add(productBasicInfoResponse);
productListResponseList.add(productListResponse);
}
return ApiResponse.<List<ProductBasicInfoResponse>>builder()
return ApiResponse.<List<ProductListResponse>>builder()
.status(200)
.message("Good Request")
.data(productBasicInfoResponseList)
.data(productListResponseList)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import com.foru.freebe.common.dto.ApiResponse;
import com.foru.freebe.errors.errorcode.CommonErrorCode;
import com.foru.freebe.errors.errorcode.ProductErrorCode;
import com.foru.freebe.errors.exception.RestApiException;
import com.foru.freebe.member.entity.Member;
import com.foru.freebe.member.repository.MemberRepository;
Expand Down Expand Up @@ -46,25 +47,14 @@ public ApiResponse<Void> registerProduct(ProductRegisterRequest productRegisterR
String productTitle = productRegisterRequestDto.getProductTitle();
String productDescription = productRegisterRequestDto.getProductDescription();

// Active 상태의 product 추가
Product productAsActive;
if (productDescription != null) {
productAsActive = Product.createProductAsActive(productTitle, productDescription, member);
} else {
productAsActive = Product.createProductAsActiveWithoutDescription(productTitle, member);
}
productRepository.save(productAsActive);

Product productAsActive = registerActiveProduct(productRegisterRequestDto, member);
registerProductImage(productRegisterRequestDto.getProductImageUrls(), productAsActive);
registerProductComponent(productRegisterRequestDto.getProductComponents(),
productAsActive);
registerProductComponent(productRegisterRequestDto.getProductComponents(), productAsActive);

// 상품에 옵션이 있을 때 option 추가
if (productRegisterRequestDto.getProductOptions() != null) {
registerProductOption(productRegisterRequestDto.getProductOptions(), productAsActive);
}

// 상품에 할인이 있을 때 discount 추가
if (productRegisterRequestDto.getProductDiscounts() != null) {
registerDiscount(productRegisterRequestDto.getProductDiscounts(), productAsActive);
}
Expand Down Expand Up @@ -111,6 +101,28 @@ public ApiResponse<Void> updateProductActiveStatus(UpdateProductRequest requestD
.build();
}

private Product registerActiveProduct(ProductRegisterRequest productRegisterRequestDto, Member member) {
String productTitle = productRegisterRequestDto.getProductTitle();
String productDescription = productRegisterRequestDto.getProductDescription();

Product productAsActive;
if (productDescription != null) {
productAsActive = Product.createProductAsActive(productTitle, productDescription, member);
} else {
productAsActive = Product.createProductAsActiveWithoutDescription(productTitle, member);
}

validateProductTitle(productTitle);
return productRepository.save(productAsActive);
}

private void validateProductTitle(String productTitle) {
Product product = productRepository.findByTitle(productTitle);
if (product != null) {
throw new RestApiException(ProductErrorCode.PRODUCT_ALREADY_EXISTS);
}
}

private Member getMember(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));
Expand Down Expand Up @@ -161,4 +173,4 @@ private void registerDiscount(List<ProductDiscountDto> productDiscountDtoList, P
productDiscountRepository.save(productDiscount);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.foru.freebe.reservation.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -9,7 +11,8 @@
import com.foru.freebe.auth.model.MemberAdapter;
import com.foru.freebe.common.dto.ApiResponse;
import com.foru.freebe.member.entity.Member;
import com.foru.freebe.reservation.dto.ReservationFormRequest;
import com.foru.freebe.reservation.dto.BasicReservationInfoResponse;
import com.foru.freebe.reservation.dto.FormRegisterRequest;
import com.foru.freebe.reservation.service.CustomerReservationService;

import jakarta.validation.Valid;
Expand All @@ -22,9 +25,16 @@ public class CustomerReservationController {
private final CustomerReservationService customerReservationService;

@PostMapping("/reservation")
public ApiResponse<Void> registerReservationForm(@Valid @RequestBody ReservationFormRequest request,
public ApiResponse<Void> registerReservationForm(@Valid @RequestBody FormRegisterRequest request,
@AuthenticationPrincipal MemberAdapter memberAdapter) {
Member customer = memberAdapter.getMember();
return customerReservationService.registerReservationForm(customer.getId(), request);
}

@GetMapping("/reservation/form/{productId}")
public ApiResponse<BasicReservationInfoResponse> getBasicReservationForm(
@AuthenticationPrincipal MemberAdapter memberAdapter, @Valid @PathVariable("productId") Long productId) {
Member customer = memberAdapter.getMember();
return customerReservationService.getBasicReservationForm(customer.getId(), productId);
}
}
Loading

0 comments on commit 0b18a09

Please sign in to comment.