Skip to content

Commit

Permalink
feat: 매장 등록 기능 추가
Browse files Browse the repository at this point in the history
매장 등록 기능을 구현했습니다.
  • Loading branch information
akfrdma0125 committed Aug 3, 2023
1 parent fd0b611 commit b61ede2
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ public enum BaseExceptionResponseStatus implements ResponseStatus {
/**
* 8000: 가게 오류
*/
COORDINATE_NOT_FOUND(8000,HttpStatus.BAD_REQUEST.value(), "좌표를 찾을 수 없습니다."),
DUPLICATE_STORE_NAME(8001,HttpStatus.BAD_REQUEST.value(), "중복된 지점이 존재합니다."),
NEARBY_STORE_NOT_FOUND(8002,HttpStatus.BAD_REQUEST.value(), "좌표 기준 주변 가게가 없습니다."),
INVALID_STORE_VALUE(8000,HttpStatus.BAD_REQUEST.value(), "가게 등록에 유효하지 않은 정보입니다."),
COORDINATE_NOT_FOUND(8001,HttpStatus.BAD_REQUEST.value(), "좌표를 찾을 수 없습니다."),
DUPLICATE_STORE_NAME(8002,HttpStatus.BAD_REQUEST.value(), "중복된 지점이 존재합니다."),
NEARBY_STORE_NOT_FOUND(8003,HttpStatus.BAD_REQUEST.value(), "좌표 기준 주변 가게가 없습니다."),

/**
* 9000: 쿠폰 오류
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
package com.example.couphoneserver.controller;

import com.example.couphoneserver.common.exception.StoreException;
import com.example.couphoneserver.common.response.BaseResponse;
import com.example.couphoneserver.dto.store.PostStoreRequest;
import com.example.couphoneserver.dto.store.PostStoreResponse;
import com.example.couphoneserver.service.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static com.example.couphoneserver.common.response.status.BaseExceptionResponseStatus.INVALID_STORE_VALUE;
import static com.example.couphoneserver.utils.BindingResultUtils.getErrorMessages;

@Tag(name = "store", description = "가게 관련 API 입니다.")
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/stores")
public class StoreController {
private final StoreService storeService;

@PostMapping("")
@Operation(summary = "가게 등록", description = "Request Body에 브랜드 아이디, 매장명, 위도, 경도, 주소를 담아서 보내주세요!")
public BaseResponse<PostStoreResponse> postBrand(@Validated @RequestBody PostStoreRequest request,
BindingResult bindingResult){
if (bindingResult.hasErrors()){
throw new StoreException(INVALID_STORE_VALUE,getErrorMessages(bindingResult));
}
return new BaseResponse<>(storeService.save(request));
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/example/couphoneserver/domain/entity/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.couphoneserver.domain.StoreStatus;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -25,4 +26,14 @@ public class Store extends BaseTimeEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "brand_id")
private Brand brand; // 해당 매장의 브랜드

@Builder
public Store(String name, String address, Double longitude, Double latitude, StoreStatus status, Brand brand) {
this.name = name;
this.address = address;
this.longitude = longitude;
this.latitude = latitude;
this.status = status;
this.brand = brand;
}
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
package com.example.couphoneserver.dto.store;

import com.example.couphoneserver.domain.StoreStatus;
import com.example.couphoneserver.domain.entity.Brand;
import com.example.couphoneserver.domain.entity.Store;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PostStoreRequest {
@NotNull
@Range(min=1,message="bid: 브랜드 아이디는 {min} 이상부터 가능합니다.")
@NotNull(message = "bid: {NotNull}")
@Range(min=1,message="bid: 브랜드 아이디는 {min} 이상부터 가능합니다")
@Schema(example="1", description = "브랜드 등록 후 응답값으로 받은 브랜드 아이디를 넣어주세요.")
private Long bid;
@NotNull
@Size(min=1,max=100,message = "name: 가게 이름의 길이는 {min} 이상, {max} 이하 가능합니다.")

@NotBlank(message = "name: {NotBlank}")
@Size(min=1,max=100,message = "name: 가게 이름의 길이는 {min} 이상, {max} 이하 가능합니다")
@Schema(example="건국대학교 서울캠퍼스",description = "브랜드 이름+공백+지점명으로 보내주세요.")
private String name;
@NotNull
@NotBlank(message = "address: {NotBlank}")
@Schema(example = "서울특별시 광진구 능동로 120")
private String address;
@NotNull
@NotNull(message = "longitude: {NotNull}")
@Schema(example = "123456.111111")
private Double longitude;
@NotNull
@NotNull(message = "latitude: {NotNull}")
@Schema(example = "123456.111111")
private Double latitude;
@Nullable
@Enumerated(EnumType.STRING)
private StoreStatus status = StoreStatus.ACTIVE;


public Store toEntity(Brand brand) {
return Store.builder()
.name(name)
.address(address)
.longitude(longitude)
.latitude(latitude)
.status(StoreStatus.ACTIVE)
.brand(brand)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
package com.example.couphoneserver.dto.store;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;



@Data
public class PostStoreResponse {
@Schema(example = "1", description = "회원 아이디")
private Long id;

public PostStoreResponse(Long id) {
this.id = id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@
public interface StoreRepository extends JpaRepository<Store, Long> {
//TODO 1. 가게 등록
//TODO 2. 최단 거리 가게 조회

boolean existsByName(String name);

}
34 changes: 32 additions & 2 deletions src/main/java/com/example/couphoneserver/service/StoreService.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
package com.example.couphoneserver.service;

import com.example.couphoneserver.common.exception.BrandException;
import com.example.couphoneserver.common.exception.StoreException;
import com.example.couphoneserver.domain.entity.Brand;
import com.example.couphoneserver.domain.entity.Store;
import com.example.couphoneserver.dto.store.PostStoreRequest;
import com.example.couphoneserver.dto.store.PostStoreResponse;
import com.example.couphoneserver.repository.BrandRepository;
import com.example.couphoneserver.repository.StoreRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

import static com.example.couphoneserver.common.response.status.BaseExceptionResponseStatus.BRAND_NOT_FOUND;
import static com.example.couphoneserver.common.response.status.BaseExceptionResponseStatus.DUPLICATE_STORE_NAME;

@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class StoreService {
private final StoreRepository storeRepository;
private final BrandRepository brandRepository;

/*
가게 등록
*/
@Transactional
public PostStoreResponse save(PostStoreRequest postStoreRequest) {
return null;
public PostStoreResponse save(PostStoreRequest request) {
//매장 브랜드 찾기
Brand brandOfStore = validateBrand(request.getBid());
//지점명 중복 확인
validateStoreName(request);
//매장 등록
Store store = storeRepository.save(request.toEntity(brandOfStore));
return new PostStoreResponse(store.getId());
}

private void validateStoreName(PostStoreRequest postStoreRequest) {
// log.info("[StoreService.validateStoreName]");
if(storeRepository.existsByName(postStoreRequest.getName()))
throw new StoreException(DUPLICATE_STORE_NAME);
}

private Brand validateBrand(Long brandId) {
// log.info("[StoreService.validateBrand]");
Optional<Brand> brand = brandRepository.findById(brandId);
if(brand.isEmpty()) throw new BrandException(BRAND_NOT_FOUND);
return brand.get();
}

/*
Expand Down

0 comments on commit b61ede2

Please sign in to comment.