diff --git a/owner-apigateway-service/src/main/resources/application.yml b/owner-apigateway-service/src/main/resources/application.yml index 194ce76..561969a 100644 --- a/owner-apigateway-service/src/main/resources/application.yml +++ b/owner-apigateway-service/src/main/resources/application.yml @@ -89,7 +89,7 @@ spring: - id: user-service uri: lb://USER-SERVICE predicates: - - Path=/user-service/store-owner + - Path=/user-service/api/owner/store-owner - Method=POST filters: - RewritePath=/user-service/(?.*),/$\{segment} diff --git a/owner-vue/package.json b/owner-vue/package.json index 92af693..8562565 100644 --- a/owner-vue/package.json +++ b/owner-vue/package.json @@ -13,6 +13,7 @@ "core-js": "^3.6.5", "moment": "^2.29.1", "vue": "^2.6.11", + "vue-daum-postcode": "^0.10.0", "vue-router": "^3.2.0", "vuedraggable": "^2.24.3", "vuetify": "^2.4.0" diff --git a/owner-vue/src/api/user.js b/owner-vue/src/api/user.js index 986fd09..5b62d34 100644 --- a/owner-vue/src/api/user.js +++ b/owner-vue/src/api/user.js @@ -1,8 +1,23 @@ import jwt from '../common/jwt.js'; export default { - requestRegisterUser(user) { - return axios.post(process.env.VUE_APP_USER_URL + "/store-owner", user); + requestRegisterUser(user, store) { + const param = { + email: user.email, + password: user.password, + name: user.name, + phoneNumber: user.phoneNumber, + businessNumber: user.businessNumber, + + storeName: store.storeName, + storePhoneNumber: store.storePhoneNumber, + address: store.storeAddress, + zipcode: store.zipcode, + latitude: store.latitude, + longitude: store.longitude, + } + + return axios.post(process.env.VUE_APP_USER_URL + "/api/owner/store-owner", param); }, async requestLoginUser(email, password) { diff --git a/owner-vue/src/main.js b/owner-vue/src/main.js index 4223fab..408e90d 100644 --- a/owner-vue/src/main.js +++ b/owner-vue/src/main.js @@ -57,6 +57,8 @@ axios.interceptors.response.use( } window.location.href = "/"; alert("권한이 없습니다. 다시 로그인해주세요."); + } else { + if (error.response.data.message) alert(error.response.data.message); } return Promise.reject(error); } diff --git a/owner-vue/src/views/RegisterUser.vue b/owner-vue/src/views/RegisterUser.vue index 9d71845..31351bf 100644 --- a/owner-vue/src/views/RegisterUser.vue +++ b/owner-vue/src/views/RegisterUser.vue @@ -1,67 +1,145 @@ diff --git a/store-service/src/docs/asciidoc/api-docs.adoc b/store-service/src/docs/asciidoc/api-docs.adoc index d3fb013..152e3ca 100644 --- a/store-service/src/docs/asciidoc/api-docs.adoc +++ b/store-service/src/docs/asciidoc/api-docs.adoc @@ -108,6 +108,8 @@ operation::store-get[snippets='curl-request,http-request,http-response,path-para operation::api-get-store-byUserId[snippets='curl-request,http-request,http-response,request-headers,response-fields'] === 매장 리스트 조회 operation::stores-get[snippets='curl-request,http-request,http-response,path-parameters,response-fields'] +=== 매장 생성 (점주 서비스) +operation::api-post-store[snippets='curl-request,http-request,http-response,request-headers,request-fields'] == 즐겨찾는 매장 === 즐겨찾는 매장 조회 diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/PostStoreDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/PostStoreDto.java new file mode 100644 index 0000000..52055aa --- /dev/null +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/PostStoreDto.java @@ -0,0 +1,75 @@ +package com.justpickup.storeservice.domain.store.dto; + +import com.justpickup.storeservice.domain.map.entity.Map; +import com.justpickup.storeservice.domain.store.entity.Store; +import com.justpickup.storeservice.global.entity.Address; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PostStoreDto { + private String name; + private String phoneNumber; + private Long userId; + private _PostStoreAddress address; + private _PostStoreMap map; + + @Builder + public PostStoreDto(String name, String phoneNumber, Long userId, _PostStoreAddress address, _PostStoreMap map) { + this.name = name; + this.phoneNumber = phoneNumber; + this.userId = userId; + this.address = address; + this.map = map; + } + + public static PostStoreDto of(Store store) { + PostStoreDto postStoreDto = new PostStoreDto(); + postStoreDto.name = store.getName(); + postStoreDto.phoneNumber = store.getPhoneNumber(); + postStoreDto.userId = store.getUserId(); + postStoreDto.address = _PostStoreAddress.of(store.getAddress()); + postStoreDto.map = _PostStoreMap.of(store.getMap()); + return postStoreDto; + } + + @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class _PostStoreAddress { + private String address; + private String zipcode; + + @Builder + public _PostStoreAddress(String address, String zipcode) { + this.address = address; + this.zipcode = zipcode; + } + + public static _PostStoreAddress of(Address address) { + _PostStoreAddress postStoreAddress = new _PostStoreAddress(); + postStoreAddress.address = address.getAddress(); + postStoreAddress.zipcode = address.getAddress(); + return postStoreAddress; + } + } + + @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class _PostStoreMap { + private Double latitude; + private Double longitude; + + @Builder + public _PostStoreMap(Double latitude, Double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + public static _PostStoreMap of(Map map) { + _PostStoreMap postStoreMap = new _PostStoreMap(); + postStoreMap.latitude = map.getLatitude(); + postStoreMap.longitude = map.getLongitude(); + return postStoreMap; + } + } +} diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/entity/Store.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/entity/Store.java index cfb1862..110b165 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/store/entity/Store.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/entity/Store.java @@ -68,12 +68,13 @@ public class Store extends BaseEntity { item.setStore(this); } - public static Store of(Address address, Map map, Long userId, String name) { + public static Store of(Address address, Map map, Long userId, String name, String phoneNumber) { Store store = new Store(); store.address = address; store.map = map; store.userId = userId; store.name = name; + store.phoneNumber = phoneNumber; return store; } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreService.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreService.java index 56a83ee..4891802 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreService.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreService.java @@ -1,9 +1,6 @@ package com.justpickup.storeservice.domain.store.service; -import com.justpickup.storeservice.domain.store.dto.SearchStoreCondition; -import com.justpickup.storeservice.domain.store.dto.SearchStoreResult; -import com.justpickup.storeservice.domain.store.dto.StoreByUserIdDto; -import com.justpickup.storeservice.domain.store.dto.StoreDto; +import com.justpickup.storeservice.domain.store.dto.*; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; @@ -15,4 +12,5 @@ public interface StoreService { StoreDto findStoreById(Long storeId); StoreByUserIdDto findStoreByUserId(Long userId); List findStoreAllById(Iterable storeIds); + PostStoreDto saveStore(PostStoreDto postStoreDto); } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreServiceImpl.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreServiceImpl.java index aa06ef2..50359fa 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreServiceImpl.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/service/StoreServiceImpl.java @@ -1,18 +1,18 @@ package com.justpickup.storeservice.domain.store.service; import com.justpickup.storeservice.domain.favoritestore.repository.FavoriteStoreCustom; -import com.justpickup.storeservice.domain.store.dto.SearchStoreCondition; -import com.justpickup.storeservice.domain.store.dto.SearchStoreResult; -import com.justpickup.storeservice.domain.store.dto.StoreByUserIdDto; -import com.justpickup.storeservice.domain.store.dto.StoreDto; +import com.justpickup.storeservice.domain.map.entity.Map; +import com.justpickup.storeservice.domain.store.dto.*; import com.justpickup.storeservice.domain.store.entity.Store; import com.justpickup.storeservice.domain.store.exception.NotExistStoreException; import com.justpickup.storeservice.domain.store.repository.StoreRepository; import com.justpickup.storeservice.domain.store.repository.StoreRepositoryCustom; +import com.justpickup.storeservice.global.entity.Address; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; @@ -71,4 +71,20 @@ public class StoreServiceImpl implements StoreService { .map(StoreDto::of) .collect(Collectors.toList()); } + + @Transactional + @Override + public PostStoreDto saveStore(PostStoreDto postStoreDto) { + PostStoreDto._PostStoreAddress postStoreAddress = postStoreDto.getAddress(); + Address address = new Address(postStoreAddress.getAddress(), postStoreAddress.getZipcode()); + + PostStoreDto._PostStoreMap postStoreMap = postStoreDto.getMap(); + Map map = Map.of(postStoreMap.getLatitude(), postStoreMap.getLongitude()); + + Store store = + Store.of(address, map, postStoreDto.getUserId(), postStoreDto.getName(), postStoreDto.getPhoneNumber()); + + Store savedStore = storeRepository.save(store); + return PostStoreDto.of(savedStore); + } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreController.java index 32fa705..e29dd9f 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreController.java @@ -7,9 +7,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.stream.Collectors; diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiController.java index 8e13161..ae36042 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiController.java @@ -1,16 +1,18 @@ package com.justpickup.storeservice.domain.store.web; +import com.justpickup.storeservice.domain.store.dto.PostStoreDto; import com.justpickup.storeservice.domain.store.dto.StoreByUserIdDto; import com.justpickup.storeservice.domain.store.service.StoreService; import com.justpickup.storeservice.global.dto.Result; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import lombok.*; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; @RestController @RequiredArgsConstructor @@ -38,6 +40,47 @@ public class StoreOwnerApiController { this.id = dto.getId(); this.name = dto.getName(); } + } + @PostMapping("/owner/store") + public ResponseEntity postStore(@Valid @RequestBody PostStoreRequest postStoreRequest, + @RequestHeader(value="user-id") String userHeader) { + Long userId = Long.valueOf(userHeader); + + storeService.saveStore(postStoreRequest.toPostStoreDto(userId)); + + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @Data @NoArgsConstructor @AllArgsConstructor @Builder + static class PostStoreRequest { + @NotEmpty + private String name; + @NotEmpty + private String phoneNumber; + @NotEmpty + private String address; + @NotEmpty + private String zipcode; + @NotNull + private Double latitude; + @NotNull + private Double longitude; + + public PostStoreDto toPostStoreDto(Long userId) { + PostStoreDto._PostStoreAddress address = + PostStoreDto._PostStoreAddress.builder().address(this.address).zipcode(this.zipcode).build(); + + PostStoreDto._PostStoreMap map = + PostStoreDto._PostStoreMap.builder().latitude(this.latitude).longitude(this.longitude).build(); + + return PostStoreDto.builder() + .name(this.name) + .phoneNumber(this.phoneNumber) + .userId(userId) + .address(address) + .map(map) + .build(); + } } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/global/SqlCommandLineRunner.java b/store-service/src/main/java/com/justpickup/storeservice/global/SqlCommandLineRunner.java index 58e552d..04c412a 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/global/SqlCommandLineRunner.java +++ b/store-service/src/main/java/com/justpickup/storeservice/global/SqlCommandLineRunner.java @@ -116,7 +116,7 @@ public class SqlCommandLineRunner implements CommandLineRunner { List items = List.of(아메리카노, 카페라떼, 카페모카, 콜드브루, 녹차라떼, 딸기라떼, 녹차, 히비스커스); itemRepository.saveAll(items); - items.forEach(item -> store.addItem(item)); + items.forEach(store::addItem); }); } @@ -136,37 +136,41 @@ public class SqlCommandLineRunner implements CommandLineRunner { void createStores(StoreRepository storeRepository, List stores) { stores.add( Store.of( - new Address("서울시", "마포구 도화동", "201-20"), + new Address("서울시 마포구 도화동", "201-20"), Map.of(37.5398271003404, 126.94769672415691), 1L, - "커피온리 마포역점" + "커피온리 마포역점", + "010-1234-5678" ) ); stores.add( Store.of( - new Address("서울시", "마포구 도화동", "50-10"), + new Address("서울시 마포구 도화동", "50-10"), Map.of(37.54010719003089, 126.94556661330861), 2L, - "만랩커피 마포점" + "만랩커피 마포점", + "010-1234-5678" ) ); stores.add( Store.of( - new Address("서울시", "마포구 도화동", "555"), + new Address("서울시 마포구 도화동", "555"), Map.of(37.539797393793755, 126.9453578838543), 3L, - "이디야커피 마포오벨리스크점" + "이디야커피 마포오벨리스크점", + "010-1234-5678" ) ); stores.add( Store.of( - new Address("서울시", "영등포구 도림로", "31길 2"), + new Address("서울시 영등포구 도림로", "31길 2"), Map.of(37.493033141569505, 126.89593667847592), 4L, - "이디야커피 대림역점" + "이디야커피 대림역점", + "010-1234-5678" ) ); diff --git a/store-service/src/main/java/com/justpickup/storeservice/global/entity/Address.java b/store-service/src/main/java/com/justpickup/storeservice/global/entity/Address.java index 3529837..1ea111d 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/global/entity/Address.java +++ b/store-service/src/main/java/com/justpickup/storeservice/global/entity/Address.java @@ -11,7 +11,6 @@ import javax.persistence.Embeddable; @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Getter public class Address { - private String city; - private String street; + private String address; private String zipcode; } diff --git a/store-service/src/test/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiControllerTest.java b/store-service/src/test/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiControllerTest.java index 598ef1e..d59533d 100644 --- a/store-service/src/test/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiControllerTest.java +++ b/store-service/src/test/java/com/justpickup/storeservice/domain/store/web/StoreOwnerApiControllerTest.java @@ -1,5 +1,6 @@ package com.justpickup.storeservice.domain.store.web; +import com.fasterxml.jackson.databind.ObjectMapper; import com.justpickup.storeservice.config.TestConfig; import com.justpickup.storeservice.domain.store.dto.StoreByUserIdDto; import com.justpickup.storeservice.domain.store.service.StoreService; @@ -11,6 +12,7 @@ import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDoc import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; @@ -20,8 +22,8 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.headerWit import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -36,6 +38,9 @@ class StoreOwnerApiControllerTest { @Autowired MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @MockBean StoreService storeService; @@ -70,6 +75,48 @@ class StoreOwnerApiControllerTest { ) )) ; + } + @Test + @DisplayName("[API] 점주 등록") + void postStore() throws Exception { + // GIVEN + StoreOwnerApiController.PostStoreRequest request = StoreOwnerApiController.PostStoreRequest.builder() + .name("점주 이름") + .phoneNumber("010-1234-5678") + .address("서울특별시 마포구 용강동 123-1길") + .zipcode("129845") + .latitude(30.90199982) + .longitude(112.1298347) + .build(); + + Long userId = 1L; + String content = objectMapper.writeValueAsString(request); + + // THEN + ResultActions actions = mockMvc.perform(post(url + "/owner/store") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header("user-id", String.valueOf(userId)) + ); + + // WHEN + actions.andExpect(status().isCreated()) + .andDo(print()) + .andDo(document("api-post-store", + requestHeaders( + headerWithName("user-id").description("JWT 유저 고유 번호") + ), + requestFields( + fieldWithPath("name").description("매징 이름"), + fieldWithPath("phoneNumber").description("매장 번호"), + fieldWithPath("address").description("매장 주소"), + fieldWithPath("zipcode").description("매장 우편번호"), + fieldWithPath("latitude").description("위도"), + fieldWithPath("longitude").description("경도") + ) + )) + ; } } \ No newline at end of file diff --git a/user-service/src/docs/asciidoc/api-docs.adoc b/user-service/src/docs/asciidoc/api-docs.adoc index cae79a5..6bb9234 100644 --- a/user-service/src/docs/asciidoc/api-docs.adoc +++ b/user-service/src/docs/asciidoc/api-docs.adoc @@ -76,6 +76,4 @@ operation::customers-get[snippets='curl-request,http-request,http-response,path- == 점주 === 회원가입 - 점주 -operation::storeOwner-post[snippets='curl-request,http-request,http-response,request-fields,response-fields'] -=== 회원가입 - 점주 : 중복 이메일 -operation::storeOwner-post-duplicateUserEmailException[snippets='curl-request,http-request,http-response,request-fields,response-fields'] \ No newline at end of file +operation::api-owner-post-store-owner[snippets='curl-request,http-request,http-response,request-fields'] \ No newline at end of file diff --git a/user-service/src/main/java/com/justpickup/userservice/UserServiceApplication.java b/user-service/src/main/java/com/justpickup/userservice/UserServiceApplication.java index e7ad12a..bfefc09 100644 --- a/user-service/src/main/java/com/justpickup/userservice/UserServiceApplication.java +++ b/user-service/src/main/java/com/justpickup/userservice/UserServiceApplication.java @@ -3,8 +3,10 @@ package com.justpickup.userservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication +@EnableFeignClients @EnableEurekaClient public class UserServiceApplication { diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostOwnerDto.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostOwnerDto.java new file mode 100644 index 0000000..05b773f --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostOwnerDto.java @@ -0,0 +1,31 @@ +package com.justpickup.userservice.domain.user.dto; + +import com.justpickup.userservice.domain.user.entity.StoreOwner; +import com.justpickup.userservice.global.client.store.PostStoreRequest; +import lombok.Builder; +import lombok.Getter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + + +@Getter +public class PostOwnerDto { + private String email; + private String password; + private String name; + private String phoneNumber; + private String businessNumber; + + @Builder + public PostOwnerDto(String email, String password, String name, String phoneNumber, String businessNumber) { + this.email = email; + this.password = password; + this.name = name; + this.phoneNumber = phoneNumber; + this.businessNumber = businessNumber; + } + + public StoreOwner toStoreOwner() { + return new StoreOwner(this.email, this.password, this.name, this.phoneNumber, this.businessNumber); + } + +} diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostStoreDto.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostStoreDto.java new file mode 100644 index 0000000..85a590f --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/dto/PostStoreDto.java @@ -0,0 +1,37 @@ +package com.justpickup.userservice.domain.user.dto; + +import com.justpickup.userservice.global.client.store.PostStoreRequest; +import lombok.Builder; +import lombok.Getter; + + +@Getter +public class PostStoreDto { + private String name; + private String phoneNumber; + private String address; + private String zipcode; + private Double latitude; + private Double longitude; + + @Builder + public PostStoreDto(String name, String phoneNumber, String address, String zipcode, Double latitude, Double longitude) { + this.name = name; + this.phoneNumber = phoneNumber; + this.address = address; + this.zipcode = zipcode; + this.latitude = latitude; + this.longitude = longitude; + } + + public PostStoreRequest toPostStoreRequest() { + return PostStoreRequest.builder() + .name(this.name) + .phoneNumber(this.phoneNumber) + .address(this.address) + .zipcode(this.zipcode) + .latitude(this.latitude) + .longitude(this.longitude) + .build(); + } +} diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/entity/User.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/entity/User.java index 757013b..ec79e70 100644 --- a/user-service/src/main/java/com/justpickup/userservice/domain/user/entity/User.java +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/entity/User.java @@ -4,6 +4,7 @@ import com.justpickup.userservice.global.entity.BaseEntity; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import javax.persistence.*; @@ -31,7 +32,7 @@ public abstract class User extends BaseEntity { public User(String email, String password, String name, String phoneNumber) { this.email = email; - this.password = password; + this.password = new BCryptPasswordEncoder().encode(password); this.name = name; this.phoneNumber = phoneNumber; } diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserService.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserService.java index 5a120c6..5f7bc63 100644 --- a/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserService.java +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserService.java @@ -1,13 +1,15 @@ package com.justpickup.userservice.domain.user.service; import com.justpickup.userservice.domain.user.dto.CustomerDto; +import com.justpickup.userservice.domain.user.dto.PostOwnerDto; +import com.justpickup.userservice.domain.user.dto.PostStoreDto; import com.justpickup.userservice.domain.user.dto.StoreOwnerDto; import java.util.List; public interface UserService { CustomerDto findCustomerByUserId(Long userId); - void saveStoreOwner(StoreOwnerDto storeOwnerDto); List findCustomerByUserIds(List userIds); StoreOwnerDto findOwnerById(Long userId); + void saveStoreOwner(PostOwnerDto toPostOwnerDto, PostStoreDto toPostStoreDto); } diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserServiceImpl.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserServiceImpl.java index 1c0aade..254523c 100644 --- a/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserServiceImpl.java +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/service/UserServiceImpl.java @@ -1,6 +1,8 @@ package com.justpickup.userservice.domain.user.service; import com.justpickup.userservice.domain.user.dto.CustomerDto; +import com.justpickup.userservice.domain.user.dto.PostOwnerDto; +import com.justpickup.userservice.domain.user.dto.PostStoreDto; import com.justpickup.userservice.domain.user.dto.StoreOwnerDto; import com.justpickup.userservice.domain.user.entity.Customer; import com.justpickup.userservice.domain.user.entity.StoreOwner; @@ -10,13 +12,13 @@ import com.justpickup.userservice.domain.user.exception.NotExistUserException; import com.justpickup.userservice.domain.user.repository.CustomerRepository; import com.justpickup.userservice.domain.user.repository.StoreOwnerRepository; import com.justpickup.userservice.domain.user.repository.UserRepository; +import com.justpickup.userservice.global.client.store.StoreClient; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -35,7 +37,7 @@ public class UserServiceImpl implements UserService, UserDetailsService { private final CustomerRepository customerRepository; private final StoreOwnerRepository storeOwnerRepository; private final UserRepository userRepository; - private final PasswordEncoder passwordEncoder; + private final StoreClient storeClient; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { @@ -55,22 +57,6 @@ public class UserServiceImpl implements UserService, UserDetailsService { return new CustomerDto(customer); } - @Override - @Transactional - public void saveStoreOwner(StoreOwnerDto storeOwnerDto) { - String email = storeOwnerDto.getEmail(); - boolean exists = userRepository.existsByEmail(email); - - if (exists) throw new DuplicateUserEmail(email + "은 중복된 이메일입니다."); - - String encode = passwordEncoder.encode(storeOwnerDto.getPassword()); - - StoreOwner storeOwner = new StoreOwner(email, encode, storeOwnerDto.getName(), - storeOwnerDto.getPhoneNumber(), storeOwnerDto.getBusinessNumber()); - - userRepository.save(storeOwner); - } - @Override public List findCustomerByUserIds(List userIds) { return customerRepository.findAllById(userIds) @@ -87,4 +73,21 @@ public class UserServiceImpl implements UserService, UserDetailsService { return StoreOwnerDto.of(storeOwner); } + @Transactional + @Override + public void saveStoreOwner(PostOwnerDto postOwnerDto, PostStoreDto postStoreDto) { + + StoreOwner storeOwner = postOwnerDto.toStoreOwner(); + + String email = storeOwner.getEmail(); + if (userRepository.existsByEmail(email)) { + throw new DuplicateUserEmail(email + "은 중복된 이메일 입니다."); + } + + StoreOwner savedOwner = storeOwnerRepository.save(storeOwner); + + Long userId = savedOwner.getId(); + storeClient.postStore(postStoreDto.toPostStoreRequest(), userId); + + } } diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserController.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserController.java index 52392f4..15882b7 100644 --- a/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserController.java +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserController.java @@ -11,11 +11,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotEmpty; import java.util.List; import java.util.stream.Collectors; @@ -109,37 +110,4 @@ public class UserController { this.name = dto.getName(); } } - - @PostMapping("/store-owner") - public ResponseEntity joinStoreOwner(@Valid @RequestBody JoinStoreOwnerRequest joinRequest) { - // 회원 가입 - userService.saveStoreOwner(joinRequest.toStoreOwnerDto()); - - return ResponseEntity.status(HttpStatus.CREATED) - .body(Result.createSuccessResult(null)); - } - - @Data @NoArgsConstructor @AllArgsConstructor - static class JoinStoreOwnerRequest { - @Email(message = "email 형식이 아닙니다.") - @NotEmpty - private String email; - @NotEmpty - private String password; - @NotEmpty - private String name; - @NotEmpty - private String phoneNumber; - @NotEmpty - private String businessNumber; - - public StoreOwnerDto toStoreOwnerDto() { - return StoreOwnerDto.builder() - .email(email).password(password).name(name) - .password(password).businessNumber(businessNumber) - .build(); - } - } - - } diff --git a/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserOwnerApiController.java b/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserOwnerApiController.java new file mode 100644 index 0000000..a6f025f --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/domain/user/web/UserOwnerApiController.java @@ -0,0 +1,86 @@ +package com.justpickup.userservice.domain.user.web; + +import com.justpickup.userservice.domain.user.dto.PostOwnerDto; +import com.justpickup.userservice.domain.user.dto.PostStoreDto; +import com.justpickup.userservice.domain.user.service.UserService; +import com.justpickup.userservice.global.dto.Result; +import lombok.*; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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 javax.validation.Valid; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class UserOwnerApiController { + + private final UserService userService; + + @PostMapping("/owner/store-owner") + public ResponseEntity postStoreOwner(@Valid @RequestBody PostStoreOwnerRequest postStoreOwnerRequest) { + + userService.saveStoreOwner( + postStoreOwnerRequest.toPostOwnerDto(), postStoreOwnerRequest.toPostStoreDto() + ); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(Result.createSuccessResult(null)); + } + + @Data @NoArgsConstructor @AllArgsConstructor @Builder + static class PostStoreOwnerRequest { + @Email(message = "email 형식이 아닙니다.") + @NotEmpty + private String email; + @NotEmpty + private String password; + @NotEmpty + private String name; + @NotEmpty + private String phoneNumber; + @NotEmpty + private String businessNumber; + + @NotEmpty + private String storeName; + @NotEmpty + private String storePhoneNumber; + @NotEmpty + private String address; + @NotEmpty + private String zipcode; + @NotNull + private Double latitude; + @NotNull + private Double longitude; + + public PostOwnerDto toPostOwnerDto() { + return PostOwnerDto.builder() + .email(this.email) + .password(this.password) + .name(this.name) + .phoneNumber(this.phoneNumber) + .businessNumber(this.businessNumber) + .build(); + } + + public PostStoreDto toPostStoreDto() { + return PostStoreDto.builder() + .name(this.storeName) + .phoneNumber(this.phoneNumber) + .address(this.address) + .zipcode(this.zipcode) + .latitude(this.latitude) + .longitude(this.longitude) + .build(); + } + } +} diff --git a/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientException.java b/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientException.java new file mode 100644 index 0000000..57c0803 --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientException.java @@ -0,0 +1,11 @@ +package com.justpickup.userservice.global.client.exception; + +import com.justpickup.userservice.global.exception.CustomException; +import org.springframework.http.HttpStatus; + +public class FeignClientException extends CustomException { + + public FeignClientException(HttpStatus status, String message) { + super(status, message); + } +} diff --git a/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientExceptionErrorDecoder.java b/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientExceptionErrorDecoder.java new file mode 100644 index 0000000..4d26d5d --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/global/client/exception/FeignClientExceptionErrorDecoder.java @@ -0,0 +1,38 @@ +package com.justpickup.userservice.global.client.exception; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.justpickup.userservice.global.dto.Result; +import feign.Response; +import feign.codec.ErrorDecoder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@RequiredArgsConstructor +@Slf4j +public class FeignClientExceptionErrorDecoder implements ErrorDecoder { + + private final ObjectMapper objectMapper; + + @Override + public Exception decode(String methodKey, Response response) { + String message = null; + if (response.body() != null) { + try { + Result result = objectMapper.readValue(response.body().asInputStream(), Result.class); + message = result.getMessage(); + } catch (IOException e) { + String catchErrorMessage = "Error Deserializing response body from failed feign request response."; + log.warn(methodKey + catchErrorMessage, e); + + return new FeignClientException(HttpStatus.INTERNAL_SERVER_ERROR, "고객센터로 문의해주세요."); + } + } + + return new FeignClientException(HttpStatus.INTERNAL_SERVER_ERROR, message); + } +} \ No newline at end of file diff --git a/user-service/src/main/java/com/justpickup/userservice/global/client/store/PostStoreRequest.java b/user-service/src/main/java/com/justpickup/userservice/global/client/store/PostStoreRequest.java new file mode 100644 index 0000000..50265f6 --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/global/client/store/PostStoreRequest.java @@ -0,0 +1,33 @@ +package com.justpickup.userservice.global.client.store; + +import lombok.Builder; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Data +public class PostStoreRequest { + @NotEmpty + private String name; + @NotEmpty + private String phoneNumber; + @NotEmpty + private String address; + @NotEmpty + private String zipcode; + @NotNull + private Double latitude; + @NotNull + private Double longitude; + + @Builder + public PostStoreRequest(String name, String phoneNumber, String address, String zipcode, Double latitude, Double longitude) { + this.name = name; + this.phoneNumber = phoneNumber; + this.address = address; + this.zipcode = zipcode; + this.latitude = latitude; + this.longitude = longitude; + } +} diff --git a/user-service/src/main/java/com/justpickup/userservice/global/client/store/StoreClient.java b/user-service/src/main/java/com/justpickup/userservice/global/client/store/StoreClient.java new file mode 100644 index 0000000..f2cae96 --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/global/client/store/StoreClient.java @@ -0,0 +1,18 @@ +package com.justpickup.userservice.global.client.store; + +import com.justpickup.userservice.global.dto.Result; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; + +import javax.validation.Valid; + +@FeignClient("STORE-SERVICE") +public interface StoreClient { + + @PostMapping("/api/owner/store") + ResponseEntity postStore(@Valid @RequestBody PostStoreRequest postStoreRequest, + @RequestHeader("user-id") Long userId); +} diff --git a/user-service/src/main/java/com/justpickup/userservice/global/config/FeignClientConfig.java b/user-service/src/main/java/com/justpickup/userservice/global/config/FeignClientConfig.java new file mode 100644 index 0000000..d4b4e7b --- /dev/null +++ b/user-service/src/main/java/com/justpickup/userservice/global/config/FeignClientConfig.java @@ -0,0 +1,14 @@ +package com.justpickup.userservice.global.config; + +import feign.Logger; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FeignClientConfig { + + @Bean + public Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } +} diff --git a/user-service/src/main/java/com/justpickup/userservice/global/exception/GlobalExceptionHandler.java b/user-service/src/main/java/com/justpickup/userservice/global/exception/GlobalExceptionHandler.java index e1e6473..a15e4b2 100644 --- a/user-service/src/main/java/com/justpickup/userservice/global/exception/GlobalExceptionHandler.java +++ b/user-service/src/main/java/com/justpickup/userservice/global/exception/GlobalExceptionHandler.java @@ -27,6 +27,8 @@ public class GlobalExceptionHandler { HttpStatus status = ce.getStatus(); Result errorResult = ce.getErrorResult(); + log.warn("[CustomException] {}, {}", status, errorResult); + return ResponseEntity.status(status) .body(errorResult); } diff --git a/user-service/src/main/java/com/justpickup/userservice/global/security/SecurityConfig.java b/user-service/src/main/java/com/justpickup/userservice/global/security/SecurityConfig.java index 1f573a5..535a575 100644 --- a/user-service/src/main/java/com/justpickup/userservice/global/security/SecurityConfig.java +++ b/user-service/src/main/java/com/justpickup/userservice/global/security/SecurityConfig.java @@ -2,9 +2,8 @@ package com.justpickup.userservice.global.security; import com.justpickup.userservice.domain.jwt.service.OAuthService; import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl; -import com.justpickup.userservice.global.utils.JwtTokenProvider; -import com.justpickup.userservice.domain.user.service.UserService; import com.justpickup.userservice.global.utils.CookieProvider; +import com.justpickup.userservice.global.utils.JwtTokenProvider; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -14,16 +13,14 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; - private final BCryptPasswordEncoder bCryptPasswordEncoder; + private final PasswordEncoder bCryptPasswordEncoder; private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenServiceImpl refreshTokenServiceImpl; private final CookieProvider cookieProvider; diff --git a/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserControllerTest.java b/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserControllerTest.java index 0575454..a69462c 100644 --- a/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserControllerTest.java +++ b/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserControllerTest.java @@ -3,7 +3,6 @@ package com.justpickup.userservice.domain.user.web; import com.fasterxml.jackson.databind.ObjectMapper; import com.justpickup.userservice.config.TestConfig; import com.justpickup.userservice.domain.user.dto.CustomerDto; -import com.justpickup.userservice.domain.user.exception.DuplicateUserEmail; import com.justpickup.userservice.domain.user.exception.NotExistUserException; import com.justpickup.userservice.domain.user.service.UserService; import com.justpickup.userservice.global.dto.Code; @@ -20,8 +19,6 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Import; -import org.springframework.http.MediaType; -import org.springframework.restdocs.headers.HeaderDocumentation; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; @@ -29,15 +26,13 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willThrow; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -185,74 +180,6 @@ class UserControllerTest { ; } - @Test - @DisplayName("회원가입 - 점주") - void registerStoreOwner() throws Exception { - UserController.JoinStoreOwnerRequest requestBody = - new UserController.JoinStoreOwnerRequest("test@naver.com", "1234", "Park", - "010-1234-5678", "1234"); - - ResultActions actions = mockMvc.perform(post("/store-owner") - .content(objectMapper.writeValueAsString(requestBody)) - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - ); - - actions.andExpect(status().isCreated()) - .andDo(print()) - .andDo(document("storeOwner-post", - requestFields( - fieldWithPath("email").description("이메일"), - fieldWithPath("password").description("비밀번호"), - fieldWithPath("name").description("이름"), - fieldWithPath("phoneNumber").description("휴대폰번호"), - fieldWithPath("businessNumber").description("사업자등록번호") - ), - responseFields( - fieldWithPath("code").description("결과코드 SUCCESS/ERROR"), - fieldWithPath("message").description("메시지"), - fieldWithPath("data").description("데이터") - ) - )) - ; - } - - @Test - @DisplayName("회원가입 - 점주 : 존재하는 회원 이메일") - void registerStoreOwnerDuplicateUserEmailException() throws Exception { - String email = "test@naver.com"; - UserController.JoinStoreOwnerRequest requestBody = - new UserController.JoinStoreOwnerRequest(email, "1234", "Park", - "010-1234-5678", "1234"); - - willThrow(new DuplicateUserEmail(email + "은 중복된 이메일입니다.")) - .given(userService).saveStoreOwner(any()); - - ResultActions actions = mockMvc.perform(post("/store-owner") - .content(objectMapper.writeValueAsString(requestBody)) - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - ); - - actions.andExpect(status().isConflict()) - .andDo(print()) - .andDo(document("storeOwner-post-duplicateUserEmailException", - requestFields( - fieldWithPath("email").description("이메일"), - fieldWithPath("password").description("비밀번호"), - fieldWithPath("name").description("이름"), - fieldWithPath("phoneNumber").description("휴대폰번호"), - fieldWithPath("businessNumber").description("사업자등록번호") - ), - responseFields( - fieldWithPath("code").description("결과코드 SUCCESS/ERROR"), - fieldWithPath("message").description("메시지"), - fieldWithPath("data").description("데이터") - ) - )) - ; - } - @Test @DisplayName("[GET] 고객 리스트 조회") void getCustomers() throws Exception { diff --git a/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserOwnerApiControllerTest.java b/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserOwnerApiControllerTest.java new file mode 100644 index 0000000..8447ead --- /dev/null +++ b/user-service/src/test/java/com/justpickup/userservice/domain/user/web/UserOwnerApiControllerTest.java @@ -0,0 +1,96 @@ +package com.justpickup.userservice.domain.user.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.justpickup.userservice.config.TestConfig; +import com.justpickup.userservice.domain.user.service.UserService; +import com.justpickup.userservice.global.security.SecurityConfig; +import com.justpickup.userservice.global.utils.CookieProvider; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = UserOwnerApiController.class, + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)} +) +@AutoConfigureMockMvc(addFilters = false) +@Import(TestConfig.class) +@AutoConfigureRestDocs(uriHost = "admin.just-pickup.com", uriPort = 8001) +class UserOwnerApiControllerTest { + + @Autowired + MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @SpyBean + CookieProvider cookieProvider; + + @MockBean + UserService userService; + + @Test + @DisplayName("점주 서비스 회원가입") + void postStoreOwner() throws Exception { + // GIVEN + UserOwnerApiController.PostStoreOwnerRequest requestBody + = UserOwnerApiController.PostStoreOwnerRequest.builder() + .email("test@gmail.com") + .password("1234") + .name("테스트 이름") + .phoneNumber("010-1234-5678") + .businessNumber("03124") + .storeName("테스트 매장") + .storePhoneNumber("010-1234-5678") + .address("충북 청주시 서원구 1순환로 627") + .zipcode("28562") + .latitude(36.6375346629654) + .longitude(127.459726819858) + .build(); + String content = objectMapper.writeValueAsString(requestBody); + // THEN + ResultActions actions = mockMvc.perform(post("/api/owner/store-owner") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(content) + ); + // WHEN + actions.andExpect(status().isCreated()) + .andDo(print()) + .andDo(document("api-owner-post-store-owner", + requestFields( + fieldWithPath("email").description("이메일"), + fieldWithPath("password").description("비밀번호"), + fieldWithPath("name").description("이름"), + fieldWithPath("phoneNumber").description("핸드폰 번호"), + fieldWithPath("businessNumber").description("사업자번호"), + fieldWithPath("storeName").description("매장 이름"), + fieldWithPath("storePhoneNumber").description("매장 번호"), + fieldWithPath("address").description("매장 주소"), + fieldWithPath("zipcode").description("매장 우편번호"), + fieldWithPath("latitude").description("위도"), + fieldWithPath("longitude").description("경도") + ) + ) + ) + ; + } +} \ No newline at end of file