diff --git a/cakk-api/src/main/java/com/cakk/api/dto/request/user/CertificationRequest.java b/cakk-api/src/main/java/com/cakk/api/dto/request/user/CertificationRequest.java index 9a0c3c6d..4f771dbf 100644 --- a/cakk-api/src/main/java/com/cakk/api/dto/request/user/CertificationRequest.java +++ b/cakk-api/src/main/java/com/cakk/api/dto/request/user/CertificationRequest.java @@ -1,6 +1,7 @@ package com.cakk.api.dto.request.user; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import com.cakk.domain.mysql.dto.param.user.CertificationParam; import com.cakk.domain.mysql.entity.user.User; @@ -10,6 +11,7 @@ public record CertificationRequest( String businessRegistrationImageUrl, @NotBlank String idCardImageUrl, + @NotNull Long cakeShopId, @NotBlank String emergencyContact, diff --git a/cakk-api/src/main/java/com/cakk/api/mapper/ShopMapper.java b/cakk-api/src/main/java/com/cakk/api/mapper/ShopMapper.java index 98c0d741..22c91fd3 100644 --- a/cakk-api/src/main/java/com/cakk/api/mapper/ShopMapper.java +++ b/cakk-api/src/main/java/com/cakk/api/mapper/ShopMapper.java @@ -55,12 +55,6 @@ public static BusinessInformation supplyBusinessInformationBy(final CreateShopRe .build(); } - public static BusinessInformation supplyBusinessInformationBy() { - return BusinessInformation.builder() - .cakeShop(CakeShop.builder().build()) - .build(); - } - public static List supplyCakeShopOperationsBy( final CakeShop cakeShop, final List operationDays diff --git a/cakk-api/src/main/java/com/cakk/api/service/shop/ShopService.java b/cakk-api/src/main/java/com/cakk/api/service/shop/ShopService.java index eda45b0b..b67a1b19 100644 --- a/cakk-api/src/main/java/com/cakk/api/service/shop/ShopService.java +++ b/cakk-api/src/main/java/com/cakk/api/service/shop/ShopService.java @@ -123,15 +123,10 @@ public CakeShopByMineResponse getMyBusinessId(final User user) { @Transactional(readOnly = true) public void requestCertificationBusinessOwner(final CertificationParam param) { - BusinessInformation businessInformation; + final BusinessInformation businessInformation = cakeShopReader.findBusinessInformationByCakeShopId(param.cakeShopId()); + final CertificationEvent certificationEvent = verificationPolicy + .requestCertificationBusinessOwner(businessInformation, param); - if (nonNull(param.cakeShopId())) { - businessInformation = cakeShopReader.findBusinessInformationByCakeShopId(param.cakeShopId()); - } else { - businessInformation = ShopMapper.supplyBusinessInformationBy(); - } - - final CertificationEvent certificationEvent = businessInformation.getRequestCertificationMessage(param); publisher.publishEvent(certificationEvent); } diff --git a/cakk-api/src/test/java/com/cakk/api/integration/shop/ShopIntegrationTest.java b/cakk-api/src/test/java/com/cakk/api/integration/shop/ShopIntegrationTest.java index dc7df64a..a3a8d395 100644 --- a/cakk-api/src/test/java/com/cakk/api/integration/shop/ShopIntegrationTest.java +++ b/cakk-api/src/test/java/com/cakk/api/integration/shop/ShopIntegrationTest.java @@ -8,7 +8,6 @@ import java.util.Set; import java.util.stream.Collectors; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; @@ -27,14 +26,12 @@ import com.cakk.api.dto.param.operation.ShopOperationParam; import com.cakk.api.dto.request.link.UpdateLinkRequest; import com.cakk.api.dto.request.operation.UpdateShopOperationRequest; -import com.cakk.api.dto.request.shop.CreateShopRequest; import com.cakk.api.dto.request.shop.UpdateShopAddressRequest; import com.cakk.api.dto.request.shop.UpdateShopRequest; import com.cakk.api.dto.request.user.CertificationRequest; import com.cakk.api.dto.response.like.HeartResponse; import com.cakk.api.dto.response.shop.CakeShopByMapResponse; import com.cakk.api.dto.response.shop.CakeShopByMineResponse; -import com.cakk.api.dto.response.shop.CakeShopCreateResponse; import com.cakk.api.dto.response.shop.CakeShopDetailResponse; import com.cakk.api.dto.response.shop.CakeShopInfoResponse; import com.cakk.api.dto.response.shop.CakeShopOwnerResponse; @@ -244,31 +241,6 @@ void detail2() { assertEquals(ReturnCode.NOT_EXIST_CAKE_SHOP.getMessage(), response.getReturnMessage()); } - @TestWithDisplayName("로그인한 사용자는 자신의 케이크샵이 존재하지 않은 상태에서 사장님 인증을 요청한다") - void request1() { - final String url = "%s%d%s".formatted(BASE_URL, port, API_URL); - final UriComponents uriComponents = UriComponentsBuilder - .fromUriString(url) - .path("/certification") - .build(); - CertificationRequest request = getConstructorMonkey().giveMeBuilder(CertificationRequest.class) - .set("businessRegistrationImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(40).ofMinLength(1)) - .set("idCardImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(40).ofMinLength(1)) - .setNull("cakeShopId") - .set("emergencyContact", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(11).ofMinLength(1)) - .set("message", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)).sample(); - - HttpEntity entity = new HttpEntity<>(request, getAuthHeader()); - - final ResponseEntity responseEntity = restTemplate.postForEntity(uriComponents.toUriString(), entity, - ApiResponse.class); - final ApiResponse response = objectMapper.convertValue(responseEntity.getBody(), ApiResponse.class); - - assertEquals(HttpStatusCode.valueOf(200), responseEntity.getStatusCode()); - assertEquals(ReturnCode.SUCCESS.getCode(), response.getReturnCode()); - assertEquals(ReturnCode.SUCCESS.getMessage(), response.getReturnMessage()); - } - @TestWithDisplayName("로그인한 사용자는 자신의 케이크샵이 존재하는 상태에서 사장님 인증을 요청한다") void request2() { final String url = "%s%d%s".formatted(BASE_URL, port, API_URL); diff --git a/cakk-api/src/test/java/com/cakk/api/service/shop/ShopServiceTest.java b/cakk-api/src/test/java/com/cakk/api/service/shop/ShopServiceTest.java index bc400f4a..b496b7e4 100644 --- a/cakk-api/src/test/java/com/cakk/api/service/shop/ShopServiceTest.java +++ b/cakk-api/src/test/java/com/cakk/api/service/shop/ShopServiceTest.java @@ -29,6 +29,7 @@ import com.cakk.api.mapper.PointMapper; import com.cakk.api.mapper.ShopMapper; import com.cakk.common.enums.ReturnCode; +import com.cakk.common.enums.VerificationStatus; import com.cakk.common.exception.CakkException; import com.cakk.domain.mysql.bo.user.VerificationPolicy; import com.cakk.domain.mysql.dto.param.shop.CakeShopDetailParam; @@ -109,6 +110,12 @@ private BusinessInformation getBusinessInformationFixture() { return getConstructorMonkey().giveMeBuilder(BusinessInformation.class) .set("businessNumber", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) .set("cakeShop", getCakeShopFixture()) + .set("verificationStatus", VerificationStatus.UNREQUESTED) + .sample(); + } + + private CertificationEvent getCertificationEventFixture() { + return getConstructorMonkey().giveMeBuilder(CertificationEvent.class) .sample(); } @@ -229,8 +236,9 @@ void promoteUser() { void requestCertificationEventWithInfo() { //given CertificationParam param = getCertificationParamFixture(false); - doReturn(getBusinessInformationFixture()) - .when(cakeShopReader).findBusinessInformationByCakeShopId(param.cakeShopId()); + doReturn(getBusinessInformationFixture()).when(cakeShopReader).findBusinessInformationByCakeShopId(param.cakeShopId()); + when(verificationPolicy.requestCertificationBusinessOwner(any(BusinessInformation.class), any(CertificationParam.class))) + .thenReturn(getCertificationEventFixture()); //when shopService.requestCertificationBusinessOwner(param); @@ -240,19 +248,6 @@ void requestCertificationEventWithInfo() { verify(publisher, times(1)).publishEvent(any(CertificationEvent.class)); } - @TestWithDisplayName("cakeShopId가 존재하지 않는다면, 요청 정보로만 이벤트를 발행한다") - void requestCertificationEventWithParam() { - //given - CertificationParam param = getCertificationParamFixture(true); - - //when - shopService.requestCertificationBusinessOwner(param); - - //verify - verify(cakeShopReader, times(0)).findBusinessInformationByCakeShopId(any()); - verify(publisher, times(1)).publishEvent(any(CertificationEvent.class)); - } - @TestWithDisplayName("id로 케이크 샵을 상세정보를 조회한다.") void searchInfoById1() { // given diff --git a/cakk-api/src/test/resources/sql/insert-business-information.sql b/cakk-api/src/test/resources/sql/insert-business-information.sql index 85ec4f02..c8f106bc 100644 --- a/cakk-api/src/test/resources/sql/insert-business-information.sql +++ b/cakk-api/src/test/resources/sql/insert-business-information.sql @@ -2,13 +2,14 @@ SET @g1 = 'Point(37.197734 127.098190)'; SET @g2 = 'Point(37.201623 127.091568)'; SET @g3 = 'Point(37.209769 127.100107)'; -insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, linked_flag, - created_at, updated_at) -values (1, 'thumbnail_url1', '케이크 맛집1', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, false, now(), now()), - (2, 'thumbnail_url2', '케이크 맛집2', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, false, now(), now()), - (3, 'thumbnail_url3', '케이크 맛집3', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, false, now(), now()); +insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, created_at, updated_at) +values (1, 'thumbnail_url1', '케이크 맛집1', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, now(), now()), + (2, 'thumbnail_url2', '케이크 맛집2', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, now(), now()), + (3, 'thumbnail_url3', '케이크 맛집3', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, now(), now()); insert into business_information(business_number, business_registration_image_url, id_card_image_url, emergency_contact, shop_id, user_id) -values ('010-3375-5555', 'https://business_registration_image_url1', 'https://id_card_image_url1', '010-0000-0000', 1, 1), - ('010-3375-5556', 'https://business_registration_image_url2', 'https://id_card_image_url2', '010-0000-0001', 2, 2), - ('010-3375-5557', 'https://business_registration_image_url3', 'https://id_card_image_url3', '010-0000-0002', 3, 3); \ No newline at end of file +values ('010-3375-5556', 'https://business_registration_image_url2', 'https://id_card_image_url2', '010-0000-0001', 2, 2), + ('010-3375-5557', 'https://business_registration_image_url3', 'https://id_card_image_url3', '010-0000-0002', 3, 3); + +insert into business_information(business_number, business_registration_image_url, id_card_image_url, emergency_contact, shop_id, user_id, verification_status) +values ('010-3375-5555', 'https://business_registration_image_url1', 'https://id_card_image_url1', '010-0000-0000', 1, 1, 3); \ No newline at end of file diff --git a/cakk-api/src/test/resources/sql/insert-cake-shop.sql b/cakk-api/src/test/resources/sql/insert-cake-shop.sql index d4698261..9830e844 100644 --- a/cakk-api/src/test/resources/sql/insert-cake-shop.sql +++ b/cakk-api/src/test/resources/sql/insert-cake-shop.sql @@ -9,19 +9,18 @@ SET @g8 = 'Point(37.541530 127.054164)'; SET @g9 = 'Point(37.543343 127.052609)'; SET @g10 = 'Point(37.541530 127.054164)'; -insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, linked_flag, - created_at, updated_at) -values (1, 'thumbnail_url1', '케이크 맛집1', '케이크 맛집입니다.', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, false, now(), now()), - (2, 'thumbnail_url2', '케이크 맛집2', '케이크 맛집입니다.', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, false, now(), now()), - (3, 'thumbnail_url3', '케이크 맛집3', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, false, now(), now()), - (4, 'thumbnail_url4', '케이크 맛집4', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g4, 4326), 0, 0, false, now(), now()), - (5, 'thumbnail_url5', '케이크 맛집5', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g5, 4326), 0, 0, false, now(), now()), - (6, 'thumbnail_url6', '케이크 맛집6', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g6, 4326), 0, 0, false, now(), now()), - (7, 'thumbnail_url7', '케이크 맛집7', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g7, 4326), 0, 0, false, now(), now()), - (8, 'thumbnail_url8', '케이크 맛집8', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g8, 4326), 0, 0, false, now(), now()), - (9, 'thumbnail_url9', '케이크 맛집9', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g9, 4326), 0, 0, false, now(), now()), - (10, 'thumbnail_url10', '케이크 맛집10', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, false, now(), now()), - (11, 'thumbnail_url10', '케이크 맛집11', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, false, now(), now()); +insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, created_at, updated_at) +values (1, 'thumbnail_url1', '케이크 맛집1', '케이크 맛집입니다.', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, now(), now()), + (2, 'thumbnail_url2', '케이크 맛집2', '케이크 맛집입니다.', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, now(), now()), + (3, 'thumbnail_url3', '케이크 맛집3', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, now(), now()), + (4, 'thumbnail_url4', '케이크 맛집4', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g4, 4326), 0, 0, now(), now()), + (5, 'thumbnail_url5', '케이크 맛집5', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g5, 4326), 0, 0, now(), now()), + (6, 'thumbnail_url6', '케이크 맛집6', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g6, 4326), 0, 0, now(), now()), + (7, 'thumbnail_url7', '케이크 맛집7', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g7, 4326), 0, 0, now(), now()), + (8, 'thumbnail_url8', '케이크 맛집8', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g8, 4326), 0, 0, now(), now()), + (9, 'thumbnail_url9', '케이크 맛집9', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g9, 4326), 0, 0, now(), now()), + (10, 'thumbnail_url10', '케이크 맛집10', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, now(), now()), + (11, 'thumbnail_url10', '케이크 맛집11', '케이크 맛집입니다.', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, now(), now()); insert into cake (cake_id, shop_id, cake_image_url, heart_count, created_at, updated_at) values (1, 1, 'cake_image_url1', 0, now(), now()), @@ -86,15 +85,17 @@ values (1, 1, 'web', 'https://www.cake-shop1.com', now(), now()), (6, 3, 'web', 'https://www.cake-shop3.com', now(), now()), (7, 3, 'kakaotalk', 'https://www.kakaotalk.com/cake-shop3', now(), now()); -insert into business_information(business_number, shop_id, user_id) -values ('010-3375-5555', 1, 1), - ('010-3375-5555', 2, 2), - ('010-3375-5555', 3, 3), - ('010-3375-5555', 4, 4), - ('010-3375-5555', 5, 5), - ('010-3375-5555', 6, 6), - ('010-3375-5555', 7, 7), - ('010-3375-5555', 8, 8), - ('010-3375-5555', 9, 9), - ('010-3375-5555', 10, 10), - ('010-3375-5555', 11, null); +insert into business_information(business_number, business_registration_image_url, id_card_image_url, emergency_contact, shop_id, user_id) +values ('010-3375-5555', NULL, NULL, NULL, 2, 2), + ('010-3375-5555', NULL, NULL, NULL, 3, 3), + ('010-3375-5555', NULL, NULL, NULL, 4, 4), + ('010-3375-5555', NULL, NULL, NULL, 5, 5), + ('010-3375-5555', NULL, NULL, NULL, 6, 6), + ('010-3375-5555', NULL, NULL, NULL, 7, 7), + ('010-3375-5555', NULL, NULL, NULL, 8, 8), + ('010-3375-5555', NULL, NULL, NULL, 9, 9), + ('010-3375-5555', NULL, NULL, NULL, 10, 10), + ('010-3375-5555', NULL, NULL, NULL, 11, null); + +insert into business_information(business_number, business_registration_image_url, id_card_image_url, emergency_contact, shop_id, user_id, verification_status) +values ('010-3375-5555', NULL, NULL, NULL, 1, 1, 1); diff --git a/cakk-api/src/test/resources/sql/insert-cake.sql b/cakk-api/src/test/resources/sql/insert-cake.sql index 42393f4d..f059a36b 100644 --- a/cakk-api/src/test/resources/sql/insert-cake.sql +++ b/cakk-api/src/test/resources/sql/insert-cake.sql @@ -9,18 +9,17 @@ SET @g8 = 'Point(37.541530 127.054164)'; SET @g9 = 'Point(37.543343 127.052609)'; SET @g10 = 'Point(37.541530 127.054164)'; -insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, linked_flag, - created_at, updated_at) -values (1, 'thumbnail_url1', '케이크 맛집1', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, false, now(), now()), - (2, 'thumbnail_url2', '케이크 맛집2', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, false, now(), now()), - (3, 'thumbnail_url3', '케이크 맛집3', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, false, now(), now()), - (4, 'thumbnail_url4', '케이크 맛집4', '서울시 강남구 어쩌고로4', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g4, 4326), 0, 0, false, now(), now()), - (5, 'thumbnail_url5', '케이크 맛집5', '서울시 강남구 어쩌고로5', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g5, 4326), 0, 0, false, now(), now()), - (6, 'thumbnail_url6', '케이크 맛집6', '서울시 강남구 어쩌고로6', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g6, 4326), 0, 0, false, now(), now()), - (7, 'thumbnail_url7', '케이크 맛집7', '서울시 강남구 어쩌고로7', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g7, 4326), 0, 0, false, now(), now()), - (8, 'thumbnail_url8', '케이크 맛집8', '서울시 강남구 어쩌고로8', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g8, 4326), 0, 0, false, now(), now()), - (9, 'thumbnail_url9', '케이크 맛집9', '서울시 강남구 어쩌고로9', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g9, 4326), 0, 0, false, now(), now()), - (10, 'thumbnail_url10', '케이크 맛집10', '서울시 강남구 어쩌고로10', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, false, now(), now()); +insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_address, shop_bio, shop_description, location, like_count, heart_count, created_at, updated_at) +values (1, 'thumbnail_url1', '케이크 맛집1', '서울시 강남구 어쩌고로1', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, now(), now()), + (2, 'thumbnail_url2', '케이크 맛집2', '서울시 강남구 어쩌고로2', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g2, 4326), 0, 0, now(), now()), + (3, 'thumbnail_url3', '케이크 맛집3', '서울시 강남구 어쩌고로3', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g3, 4326), 0, 0, now(), now()), + (4, 'thumbnail_url4', '케이크 맛집4', '서울시 강남구 어쩌고로4', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g4, 4326), 0, 0, now(), now()), + (5, 'thumbnail_url5', '케이크 맛집5', '서울시 강남구 어쩌고로5', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g5, 4326), 0, 0, now(), now()), + (6, 'thumbnail_url6', '케이크 맛집6', '서울시 강남구 어쩌고로6', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g6, 4326), 0, 0, now(), now()), + (7, 'thumbnail_url7', '케이크 맛집7', '서울시 강남구 어쩌고로7', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g7, 4326), 0, 0, now(), now()), + (8, 'thumbnail_url8', '케이크 맛집8', '서울시 강남구 어쩌고로8', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g8, 4326), 0, 0, now(), now()), + (9, 'thumbnail_url9', '케이크 맛집9', '서울시 강남구 어쩌고로9', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g9, 4326), 0, 0, now(), now()), + (10, 'thumbnail_url10', '케이크 맛집10', '서울시 강남구 어쩌고로10', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g10, 4326), 0, 0, now(), now()); insert into cake_shop_operation (operation_id, shop_id, operation_day, start_time, end_time, created_at, updated_at) values (1, 1, 0, '10:00:00', '22:00:00', now(), now()), @@ -62,10 +61,12 @@ values (1, 1, 'cake_image_url1', 0, now(), now()), (19, 10, 'cake_image_url19', 0, now(), now()); insert into business_information(business_number, shop_id, user_id) -values ('010-3375-5555', 1, 1), - ('010-3375-5555', 2, 2), +values ('010-3375-5555', 2, 2), ('010-3375-5555', 3, 3); +insert into business_information(business_number, shop_id, user_id, verification_status) +values ('010-3375-5555', 1, 1, 1); + insert into tag(tag_id, tag_name, created_at) values (1, 'tag_name1', now()), (2, 'tag_name2', now()), diff --git a/cakk-api/src/test/resources/sql/insert-heart-for-concurrency-test.sql b/cakk-api/src/test/resources/sql/insert-heart-for-concurrency-test.sql index 6ed30920..fe0c9375 100644 --- a/cakk-api/src/test/resources/sql/insert-heart-for-concurrency-test.sql +++ b/cakk-api/src/test/resources/sql/insert-heart-for-concurrency-test.sql @@ -106,9 +106,9 @@ VALUES -- cake_shop SET @g1 = 'Point(37.197734 127.098190)'; -insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_bio, shop_description, location, like_count, heart_count, linked_flag, +insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_bio, shop_description, location, like_count, heart_count, created_at, updated_at) -values (1, 'thumbnail_url', '케이크 맛집', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, false, now(), now()); +values (1, 'thumbnail_url', '케이크 맛집', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, now(), now()); -- cake insert into cake (cake_id, shop_id, cake_image_url, heart_count, created_at, updated_at) diff --git a/cakk-api/src/test/resources/sql/insert-like-for-concurrency-test.sql b/cakk-api/src/test/resources/sql/insert-like-for-concurrency-test.sql index 47f86241..8cdeb8e6 100644 --- a/cakk-api/src/test/resources/sql/insert-like-for-concurrency-test.sql +++ b/cakk-api/src/test/resources/sql/insert-like-for-concurrency-test.sql @@ -7,6 +7,6 @@ VALUES -- cake_shop SET @g1 = 'Point(37.197734 127.098190)'; -insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_bio, shop_description, location, like_count, heart_count, linked_flag, +insert into cake_shop (shop_id, thumbnail_url, shop_name, shop_bio, shop_description, location, like_count, heart_count, created_at, updated_at) -values (1, 'thumbnail_url', '케이크 맛집', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, false, now(), now()); +values (1, 'thumbnail_url', '케이크 맛집', '케이크 맛집입니다.', '케이크 맛집입니다.', ST_GeomFromText(@g1, 4326), 0, 0, now(), now()); diff --git a/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java b/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java index d4ad58d8..7bde698c 100644 --- a/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java +++ b/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java @@ -30,6 +30,7 @@ public enum ReturnCode { // 케이크 샵 에러 (1300 ~ 1350) NOT_EXIST_CAKE_SHOP("1300", "존재하지 않는 케이크 샵 입니다"), NOT_CAKE_SHOP_OWNER("1301", "케이크샵 주인이 아닙니다"), + CAKE_SHOP_CERTIFICATED_ISSUE("1302", "케이크 샵 인증 요청에 문제가 있습니다"), // 케이크 에러 (1350 ~ 1400) NOT_EXIST_CAKE("1350", "존재하지 않는 케이크 입니다"), diff --git a/cakk-common/src/main/java/com/cakk/common/enums/Role.java b/cakk-common/src/main/java/com/cakk/common/enums/Role.java index ad927f0b..e909e6dd 100644 --- a/cakk-common/src/main/java/com/cakk/common/enums/Role.java +++ b/cakk-common/src/main/java/com/cakk/common/enums/Role.java @@ -2,7 +2,7 @@ public enum Role { - ADMIN, BUSINESS_OWNER, USER; + ADMIN, USER; public String getSecurityRole() { return "ROLE_" + this; diff --git a/cakk-common/src/main/java/com/cakk/common/enums/VerificationStatus.java b/cakk-common/src/main/java/com/cakk/common/enums/VerificationStatus.java index 233bffcc..fd0ce63d 100644 --- a/cakk-common/src/main/java/com/cakk/common/enums/VerificationStatus.java +++ b/cakk-common/src/main/java/com/cakk/common/enums/VerificationStatus.java @@ -2,9 +2,10 @@ public enum VerificationStatus { - PENDING(0), + UNREQUESTED(0), APPROVED(1), - REJECTED(2); + REJECTED(2), + PENDING(3); private final Integer code; @@ -17,11 +18,27 @@ public Integer getCode() { } public boolean isCandidate() { - return code == 0; + return code == 3; } - public static VerificationStatus makeApproved() { + public boolean isNotCandidate() { + return code != 3; + } + + public boolean isApproved() { + return code == 1; + } + + public boolean isRejected() { + return code == 2; + } + + public VerificationStatus makeApproved() { return VerificationStatus.APPROVED; } + + public VerificationStatus makePending() { + return VerificationStatus.PENDING; + } } diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/DefaultVerificationPolicy.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/DefaultVerificationPolicy.java index 6beeff67..952a280c 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/DefaultVerificationPolicy.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/DefaultVerificationPolicy.java @@ -2,21 +2,46 @@ import org.springframework.stereotype.Component; +import com.cakk.common.enums.ReturnCode; import com.cakk.common.enums.VerificationStatus; -import com.cakk.domain.mysql.entity.user.User; +import com.cakk.common.exception.CakkException; +import com.cakk.domain.mysql.dto.param.user.CertificationParam; +import com.cakk.domain.mysql.entity.user.BusinessInformation; +import com.cakk.domain.mysql.event.shop.CertificationEvent; @Component public class DefaultVerificationPolicy implements VerificationPolicy { @Override - public boolean isCandidate(User user, VerificationStatus verificationStatus) { - return !user.isBusinessOwner() && verificationStatus.isCandidate(); + public boolean isCandidate(VerificationStatus verificationStatus) { + return verificationStatus.isCandidate(); } @Override - public VerificationStatus approveToBusinessOwner(User user) { - user.upgradedBusinessOwner(); - return VerificationStatus.makeApproved(); + public VerificationStatus approveToBusinessOwner(VerificationStatus verificationStatus) { + validateVerificationStatusPending(verificationStatus); + return verificationStatus.makeApproved(); + } + + @Override + public CertificationEvent requestCertificationBusinessOwner( + BusinessInformation businessInformation, + CertificationParam param + ) { + validateRequestCertificationBusinessOwner(businessInformation); + return businessInformation.registerCertificationInformation(param); + } + + private void validateRequestCertificationBusinessOwner(BusinessInformation businessInformation) { + if (businessInformation.isImPossibleRequestCertification()) { + throw new CakkException(ReturnCode.CAKE_SHOP_CERTIFICATED_ISSUE); + } + } + + private void validateVerificationStatusPending(VerificationStatus verificationStatus) { + if (verificationStatus.isNotCandidate()) { + throw new CakkException(ReturnCode.CAKE_SHOP_CERTIFICATED_ISSUE); + } } } diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/VerificationPolicy.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/VerificationPolicy.java index 3f265d71..d2eae20e 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/VerificationPolicy.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/bo/user/VerificationPolicy.java @@ -1,12 +1,16 @@ package com.cakk.domain.mysql.bo.user; import com.cakk.common.enums.VerificationStatus; -import com.cakk.domain.mysql.entity.user.User; +import com.cakk.domain.mysql.dto.param.user.CertificationParam; +import com.cakk.domain.mysql.entity.user.BusinessInformation; +import com.cakk.domain.mysql.event.shop.CertificationEvent; public interface VerificationPolicy { - boolean isCandidate(User user, VerificationStatus verificationStatus); + boolean isCandidate(VerificationStatus verificationStatus); - VerificationStatus approveToBusinessOwner(User user); + VerificationStatus approveToBusinessOwner(VerificationStatus verificationStatus); + + CertificationEvent requestCertificationBusinessOwner(BusinessInformation businessInformation, CertificationParam param); } diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/shop/CakeShop.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/shop/CakeShop.java index 9127380c..78527da6 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/shop/CakeShop.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/shop/CakeShop.java @@ -67,10 +67,6 @@ public class CakeShop extends AuditEntity { @Column(name = "heart_count", nullable = false, columnDefinition = "MEDIUMINT") private Integer heartCount; - @ColumnDefault("false") - @Column(name = "linked_flag", nullable = false, columnDefinition = "TINYINT(1)") - private Boolean linkedFlag; - @ColumnDefault("null") @Column(name = "deleted_at") private LocalDateTime deletedAt; @@ -105,11 +101,6 @@ public CakeShop( this.location = location; this.heartCount = 0; this.likeCount = 0; - this.linkedFlag = false; - } - - public void ownedByUser() { - linkedFlag = true; } public void increaseLikeCount() { diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/BusinessInformation.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/BusinessInformation.java index 90e50214..0f463261 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/BusinessInformation.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/BusinessInformation.java @@ -56,7 +56,7 @@ public class BusinessInformation extends AuditEntity { @ColumnDefault("0") @Convert(converter = VerificationStatusConverter.class) @Column(name = "verification_status", nullable = false) - private VerificationStatus verificationStatus = VerificationStatus.PENDING; + private VerificationStatus verificationStatus = VerificationStatus.UNREQUESTED; @OneToOne @MapsId @@ -77,28 +77,40 @@ public BusinessInformation( this.cakeShop = cakeShop; this.businessNumber = businessNumber; this.user = user; - this.verificationStatus = VerificationStatus.PENDING; - } - - public CertificationEvent getRequestCertificationMessage(final CertificationParam param) { - if (isExistMyCakeShop()) { - return EventMapper.supplyCertificationInfoWithCakeShopInfo(param, cakeShop); - } - return EventMapper.supplyCertificationInfo(param); - + this.verificationStatus = VerificationStatus.UNREQUESTED; } public void updateBusinessOwner(final VerificationPolicy verificationPolicy, final User businessOwner) { user = businessOwner; - verificationStatus = verificationPolicy.approveToBusinessOwner(user); + verificationStatus = verificationPolicy.approveToBusinessOwner(verificationStatus); } public boolean isBusinessOwnerCandidate(VerificationPolicy verificationPolicy) { - return verificationPolicy.isCandidate(Objects.requireNonNull(user), Objects.requireNonNull(verificationStatus)); + return verificationPolicy.isCandidate(Objects.requireNonNull(verificationStatus)); } - private boolean isExistMyCakeShop() { - return cakeShop != null && user == null; + public CertificationEvent registerCertificationInformation(CertificationParam param) { + businessRegistrationImageUrl = param.businessRegistrationImageUrl(); + idCardImageUrl = param.idCardImageUrl(); + emergencyContact = param.emergencyContact(); + verificationStatus = verificationStatus.makePending(); + return EventMapper.supplyCertificationInfoWithCakeShopInfo(param, cakeShop); } + public boolean isImPossibleRequestCertification() { + return isAlreadyApproved() || isProcessingVerification() || isRejectVerification(); + } + + private boolean isAlreadyApproved() { + return verificationStatus.isApproved(); + } + + private boolean isProcessingVerification() { + return verificationStatus.isCandidate(); + } + + private boolean isRejectVerification() { + return verificationStatus.isRejected(); + } } + diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/User.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/User.java index 72d06dad..793f958b 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/User.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/entity/user/User.java @@ -14,7 +14,6 @@ import org.hibernate.annotations.ColumnDefault; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; @@ -106,10 +105,6 @@ public User( this.role = role; } - public void upgradedBusinessOwner() { - role = Role.BUSINESS_OWNER; - } - public void updateProfile(final ProfileUpdateParam param) { this.profileImageUrl = param.profileImageUrl(); this.nickname = param.nickname(); @@ -117,9 +112,4 @@ public void updateProfile(final ProfileUpdateParam param) { this.gender = param.gender(); this.birthday = param.birthday(); } - - @JsonIgnore - public boolean isBusinessOwner() { - return role == Role.BUSINESS_OWNER; - } } diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/mapper/EventMapper.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/mapper/EventMapper.java index aaf9c7b4..777c3579 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/mapper/EventMapper.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/mapper/EventMapper.java @@ -24,17 +24,6 @@ public static CertificationEvent supplyCertificationInfoWithCakeShopInfo(Certifi .build(); } - public static CertificationEvent supplyCertificationInfo(CertificationParam param) { - return CertificationEvent.builder() - .idCardImageUrl(param.idCardImageUrl()) - .businessRegistrationImageUrl(param.businessRegistrationImageUrl()) - .emergencyContact(param.emergencyContact()) - .message(param.message()) - .userId(param.user().getId()) - .userEmail(param.user().getEmail()) - .build(); - } - public static CakeIncreaseViewsEvent supplyCakeIncreaseViewsEvent(Long cakeId) { return new CakeIncreaseViewsEvent(cakeId); } diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/jpa/BusinessInformationJpaRepository.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/jpa/BusinessInformationJpaRepository.java index fb815a4d..97028b13 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/jpa/BusinessInformationJpaRepository.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/jpa/BusinessInformationJpaRepository.java @@ -17,8 +17,6 @@ public interface BusinessInformationJpaRepository extends JpaRepository findBusinessInformationWithCakeShop(@Param("cakeShopId") Long cakeShopId); - Optional findBusinessInformationByCakeShopId(Long cakeShopId); - List findAllByUser(User user); Boolean existsBusinessInformationByUserAndCakeShop_Id(User owner, Long cakeShopId); diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeQueryRepository.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeQueryRepository.java index d90b4ddc..c0e8ec36 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeQueryRepository.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeQueryRepository.java @@ -28,6 +28,7 @@ import com.cakk.common.enums.CakeDesignCategory; import com.cakk.common.enums.Role; +import com.cakk.common.enums.VerificationStatus; import com.cakk.domain.mysql.dto.param.cake.CakeDetailParam; import com.cakk.domain.mysql.dto.param.cake.CakeImageResponseParam; import com.cakk.domain.mysql.dto.param.tag.TagParam; @@ -128,7 +129,8 @@ public Optional searchWithCakeTagsAndCakeCategories(final Long cakeId, fin BooleanExpression userCondition = null; if (owner.getRole() != Role.ADMIN) { - userCondition = businessInformation.user.eq(owner); + userCondition = businessInformation.user.eq(owner) + .and(businessInformation.verificationStatus.eq(VerificationStatus.APPROVED)); } JPQLQuery query = queryFactory diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeShopQueryRepository.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeShopQueryRepository.java index 7b3047dd..47d78047 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeShopQueryRepository.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/query/CakeShopQueryRepository.java @@ -5,7 +5,6 @@ import static com.cakk.domain.mysql.entity.shop.QCakeShopLink.*; import static com.cakk.domain.mysql.entity.shop.QCakeShopOperation.*; import static com.cakk.domain.mysql.entity.user.QBusinessInformation.*; -import static com.cakk.domain.mysql.entity.user.QUser.*; import static com.querydsl.core.group.GroupBy.*; import static java.util.Objects.*; @@ -26,6 +25,7 @@ import lombok.RequiredArgsConstructor; import com.cakk.common.enums.Role; +import com.cakk.common.enums.VerificationStatus; import com.cakk.domain.mysql.dto.param.shop.CakeShopByLocationParam; import com.cakk.domain.mysql.dto.param.shop.CakeShopDetailParam; import com.cakk.domain.mysql.dto.param.shop.CakeShopInfoParam; @@ -115,16 +115,20 @@ public List searchByKeywordWithLocation( } public Optional searchWithBusinessInformationAndOwnerById(User owner, Long cakeShopId) { - JPQLQuery query = queryFactory - .selectFrom(cakeShop) - .innerJoin(cakeShop.businessInformation, businessInformation).fetchJoin(); + BooleanExpression userCondition = null; if (owner.getRole() != Role.ADMIN) { - query.innerJoin(businessInformation.user, user) - .where(businessInformation.user.eq(owner)); + userCondition = businessInformation.user.eq(owner) + .and(businessInformation.verificationStatus.eq(VerificationStatus.APPROVED)); } + JPQLQuery query = queryFactory + .selectFrom(cakeShop) + .innerJoin(cakeShop.businessInformation, businessInformation).fetchJoin() + .where(cakeShop.id.eq(cakeShopId)); - query.where(cakeShop.id.eq(cakeShopId)); + if (nonNull(userCondition)) { + query.where(userCondition); + } return Optional.ofNullable(query.fetchOne()); } @@ -133,7 +137,8 @@ public Optional searchWithShopLinks(User owner, Long cakeShopId) { BooleanExpression userCondition = null; if (owner.getRole() != Role.ADMIN) { - userCondition = businessInformation.user.eq(owner); + userCondition = businessInformation.user.eq(owner) + .and(businessInformation.verificationStatus.eq(VerificationStatus.APPROVED)); } JPQLQuery query = queryFactory @@ -153,7 +158,8 @@ public Optional searchWithOperations(User owner, Long cakeShopId) { BooleanExpression userCondition = null; if (owner.getRole() != Role.ADMIN) { - userCondition = businessInformation.user.eq(owner); + userCondition = businessInformation.user.eq(owner) + .and(businessInformation.verificationStatus.eq(VerificationStatus.APPROVED)); } JPQLQuery query = queryFactory diff --git a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/reader/CakeShopReader.java b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/reader/CakeShopReader.java index af109e09..2fd16a2a 100644 --- a/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/reader/CakeShopReader.java +++ b/cakk-domain/mysql/src/main/java/com/cakk/domain/mysql/repository/reader/CakeShopReader.java @@ -71,7 +71,7 @@ public BusinessInformation findBusinessInformationWithShop(final Long cakeShopId } public BusinessInformation findBusinessInformationByCakeShopId(final Long cakeShopId) { - return businessInformationJpaRepository.findBusinessInformationByCakeShopId(cakeShopId) + return businessInformationJpaRepository.findBusinessInformationWithCakeShop(cakeShopId) .orElseThrow(() -> new CakkException(ReturnCode.NOT_EXIST_CAKE_SHOP)); } diff --git a/cakk-domain/mysql/src/test/java/com/cakk/domain/base/DomainTest.java b/cakk-domain/mysql/src/test/java/com/cakk/domain/base/DomainTest.java index f4b2c19b..25fef877 100644 --- a/cakk-domain/mysql/src/test/java/com/cakk/domain/base/DomainTest.java +++ b/cakk-domain/mysql/src/test/java/com/cakk/domain/base/DomainTest.java @@ -11,11 +11,16 @@ import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.customizer.Values; import com.navercorp.fixturemonkey.jakarta.validation.plugin.JakartaValidationPlugin; import com.cakk.common.enums.Role; +import com.cakk.common.enums.VerificationStatus; import com.cakk.domain.mysql.bo.user.DefaultVerificationPolicy; import com.cakk.domain.mysql.bo.user.VerificationPolicy; +import com.cakk.domain.mysql.dto.param.user.CertificationParam; +import com.cakk.domain.mysql.entity.shop.CakeShop; +import com.cakk.domain.mysql.entity.user.BusinessInformation; import com.cakk.domain.mysql.entity.user.User; public abstract class DomainTest { @@ -63,4 +68,36 @@ protected User getUserFixture(Role role) { protected VerificationPolicy getVerificationPolicy() { return new DefaultVerificationPolicy(); } + + protected CakeShop getCakeShopFixture() { + return getConstructorMonkey().giveMeBuilder(CakeShop.class) + .set("shopName", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(30)) + .set("shopBio", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(40)) + .set("shopDescription", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(500)) + .set("location", supplyPointBy( + Arbitraries.doubles().between(-90, 90).sample(), + Arbitraries.doubles().between(-180, 180).sample()) + ) + .sample(); + } + + protected BusinessInformation getBusinessInformationFixtureWithCakeShop(VerificationStatus verificationStatus) { + return getConstructorMonkey().giveMeBuilder(BusinessInformation.class) + .set("businessNumber", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) + .set("cakeShop", Values.just(getCakeShopFixture())) + .set("verificationStatus", verificationStatus) + .setNull("user") + .sample(); + } + + protected CertificationParam getCertificationParamFixtureWithUser(User user) { + return getBuilderMonkey().giveMeBuilder(CertificationParam.class) + .set("businessRegistrationImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) + .set("idCardImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) + .set("cakeShopId", Arbitraries.longs().greaterOrEqual(0)) + .set("emergencyContact", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) + .set("message", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) + .set("user", user) + .sample(); + } } diff --git a/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/BusinessInformationTest.java b/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/BusinessInformationTest.java index 4769af54..6406ca7b 100644 --- a/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/BusinessInformationTest.java +++ b/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/BusinessInformationTest.java @@ -14,7 +14,6 @@ import com.cakk.domain.base.DomainTest; import com.cakk.domain.mysql.bo.user.VerificationPolicy; import com.cakk.domain.mysql.dto.param.user.CertificationParam; -import com.cakk.domain.mysql.entity.shop.CakeShop; import com.cakk.domain.mysql.entity.user.BusinessInformation; import com.cakk.domain.mysql.entity.user.User; import com.cakk.domain.mysql.event.shop.CertificationEvent; @@ -22,27 +21,6 @@ class BusinessInformationTest extends DomainTest { - - private CakeShop getCakeShopFixture() { - return getConstructorMonkey().giveMeBuilder(CakeShop.class) - .set("shopName", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(30)) - .set("shopBio", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(40)) - .set("shopDescription", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(500)) - .set("location", supplyPointBy( - Arbitraries.doubles().between(-90, 90).sample(), - Arbitraries.doubles().between(-180, 180).sample()) - ) - .sample(); - } - - private BusinessInformation getBusinessInformationFixture() { - return getConstructorMonkey().giveMeBuilder(BusinessInformation.class) - .set("businessNumber", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) - .setNull("cakeShop") - .setNull("user") - .sample(); - } - private BusinessInformation getBusinessInformationFixtureWithUser(VerificationStatus verificationStatus, Role role) { return getConstructorMonkey().giveMeBuilder(BusinessInformation.class) .setNotNull("businessNumber") @@ -53,57 +31,26 @@ private BusinessInformation getBusinessInformationFixtureWithUser(VerificationSt .sample(); } - private BusinessInformation getBusinessInformationFixtureWithCakeShop(VerificationStatus verificationStatus) { - return getConstructorMonkey().giveMeBuilder(BusinessInformation.class) - .set("businessNumber", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) - .set("cakeShop", Values.just(getCakeShopFixture())) - .set("verificationStatus", verificationStatus) - .setNull("user") - .sample(); - } - - private CertificationParam getCertificationParamFixtureWithUser(User user) { - return getBuilderMonkey().giveMeBuilder(CertificationParam.class) - .set("businessRegistrationImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) - .set("idCardImageUrl", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) - .set("cakeShopId", Arbitraries.longs().greaterOrEqual(0)) - .set("emergencyContact", Arbitraries.strings().withCharRange('a', 'z').ofMinLength(1).ofMaxLength(20)) - .set("message", Arbitraries.strings().withCharRange('a', 'z').ofMaxLength(20)) - .set("user", user) - .sample(); - } - @Test - @DisplayName("케이크샵이 존재한다면 가게 정보와 함께 서비스에 인증요청을 한다") - void getRequestCertificationMessage() { + @DisplayName("사장님 인증되지 않은 케이크 샵이 존재할 때, 가게 정보와 함께 서비스에 인증요청을 한다") + void registerCertificationInformation1() { //given - BusinessInformation businessInformation = getBusinessInformationFixtureWithCakeShop(VerificationStatus.PENDING); + BusinessInformation businessInformation = getBusinessInformationFixtureWithCakeShop(VerificationStatus.UNREQUESTED); User user = getUserFixture(Role.USER); CertificationParam param = getCertificationParamFixtureWithUser(user); String shopName = businessInformation.getCakeShop().getShopName(); //when - CertificationEvent certificationEvent = businessInformation.getRequestCertificationMessage(param); + CertificationEvent certificationEvent = businessInformation.registerCertificationInformation(param); //then + assertThat(businessInformation.getVerificationStatus()).isEqualTo(VerificationStatus.PENDING); + assertThat(businessInformation.getBusinessRegistrationImageUrl()).isEqualTo(param.businessRegistrationImageUrl()); + assertThat(businessInformation.getIdCardImageUrl()).isEqualTo(param.idCardImageUrl()); + assertThat(businessInformation.getEmergencyContact()).isEqualTo(param.emergencyContact()); assertThat(certificationEvent.shopName()).isEqualTo(shopName); } - @Test - @DisplayName("케이크샵이 존재하지 않는다면 가게 정보 없이 서비스에 인증요청을 한다") - void getRequestCertificationMessage2() { - //given - BusinessInformation businessInformation = getBusinessInformationFixture(); - User user = getUserFixture(Role.USER); - CertificationParam param = getCertificationParamFixtureWithUser(user); - - //when - CertificationEvent certificationEvent = businessInformation.getRequestCertificationMessage(param); - - //then - assertThat(certificationEvent.shopName()).isNull(); - } - @Test @DisplayName("사용자는 케이크샵의 주인으로 승격된다") void promotedByBusinessOwner() { @@ -117,7 +64,7 @@ void promotedByBusinessOwner() { //then assertThat(businessInformation.getUser()).isNotNull(); - assertThat(businessInformation.getUser().getRole()).isEqualTo(Role.BUSINESS_OWNER); + assertThat(businessInformation.getUser().getRole()).isEqualTo(Role.USER); assertThat(businessInformation.getVerificationStatus()).isEqualTo(VerificationStatus.APPROVED); } @@ -136,7 +83,7 @@ void isPendingVerificationTrue() { @DisplayName("예비 사장님 여부 검사에서 인증 완료 상태라면, False를 반환한다") void isPendingVerificationFalse1() { //given - BusinessInformation businessInformation = getBusinessInformationFixtureWithUser(VerificationStatus.APPROVED, Role.BUSINESS_OWNER); + BusinessInformation businessInformation = getBusinessInformationFixtureWithUser(VerificationStatus.APPROVED, Role.USER); VerificationPolicy verificationPolicy = getVerificationPolicy(); //then @@ -155,10 +102,10 @@ void isPendingVerificationFalse2() { } @Test - @DisplayName("예비 사장님 여부 검사에서 인증 완료 상태라면, False를 반환한다") + @DisplayName("예비 사장님 여부 검사에서 인증 요청 상태도 아니라면, False를 반환한다") void isPendingVerificationFalse3() { //given - BusinessInformation businessInformation = getBusinessInformationFixtureWithUser(VerificationStatus.PENDING, Role.BUSINESS_OWNER); + BusinessInformation businessInformation = getBusinessInformationFixtureWithUser(VerificationStatus.UNREQUESTED, Role.USER); VerificationPolicy verificationPolicy = getVerificationPolicy(); //then diff --git a/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/VerificationPolicyTest.java b/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/VerificationPolicyTest.java index 42b86fc0..383e0849 100644 --- a/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/VerificationPolicyTest.java +++ b/cakk-domain/mysql/src/test/java/com/cakk/domain/entity/user/VerificationPolicyTest.java @@ -2,13 +2,17 @@ import static org.assertj.core.api.Assertions.*; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import com.cakk.common.enums.Role; import com.cakk.common.enums.VerificationStatus; +import com.cakk.common.exception.CakkException; import com.cakk.domain.base.DomainTest; import com.cakk.domain.mysql.bo.user.VerificationPolicy; +import com.cakk.domain.mysql.dto.param.user.CertificationParam; +import com.cakk.domain.mysql.entity.user.BusinessInformation; import com.cakk.domain.mysql.entity.user.User; public class VerificationPolicyTest extends DomainTest { @@ -17,11 +21,9 @@ public class VerificationPolicyTest extends DomainTest { @DisplayName("인증 정책은 사용자를 케이크샵 주인으로 승격시켜준다") void approveToBusinessOwner() { VerificationPolicy verificationPolicy = getVerificationPolicy(); - User user = getUserFixture(Role.USER); - VerificationStatus verificationStatus = verificationPolicy.approveToBusinessOwner(user); + VerificationStatus verificationStatus = verificationPolicy.approveToBusinessOwner(VerificationStatus.PENDING); - assertThat(user.isBusinessOwner()).isTrue(); assertThat(verificationStatus).isEqualTo(VerificationStatus.APPROVED); } @@ -29,9 +31,50 @@ void approveToBusinessOwner() { @DisplayName("인증 정책은 사용자의 권한이 BUSINESS_OWNER가 아니고 인증 진행중이라면 케이크샵 주인 후보임을 알려준다") void isCandidate() { VerificationPolicy verificationPolicy = getVerificationPolicy(); + + assertThat(verificationPolicy.isCandidate(VerificationStatus.PENDING)).isTrue(); + } + + @Test + @DisplayName("사장님 인증된 케이크 샵이 존재할 때, 인증 요청에 실패한다") + void registerCertificationInformation2() { + //given + VerificationPolicy verificationPolicy = getVerificationPolicy(); + BusinessInformation businessInformation = getBusinessInformationFixtureWithCakeShop(VerificationStatus.APPROVED); + User user = getUserFixture(Role.USER); + CertificationParam param = getCertificationParamFixtureWithUser(user); + + //when, then + Assertions.assertThrowsExactly(CakkException.class, + () -> verificationPolicy.requestCertificationBusinessOwner(businessInformation, param)); + } + + @Test + @DisplayName("사장님 인증 요청이 진행중일 때, 인증 요청에 실패한다") + void registerCertificationInformation3() { + //given + VerificationPolicy verificationPolicy = getVerificationPolicy(); + BusinessInformation businessInformation = getBusinessInformationFixtureWithCakeShop(VerificationStatus.PENDING); + User user = getUserFixture(Role.USER); + CertificationParam param = getCertificationParamFixtureWithUser(user); + + //when, then + Assertions.assertThrowsExactly(CakkException.class, + () -> verificationPolicy.requestCertificationBusinessOwner(businessInformation, param)); + } + + @Test + @DisplayName("사장님 인증 요청이 거절 됐을 때, 인증 요청에 실패한다") + void registerCertificationInformation4() { + //given + VerificationPolicy verificationPolicy = getVerificationPolicy(); + BusinessInformation businessInformation = getBusinessInformationFixtureWithCakeShop(VerificationStatus.REJECTED); User user = getUserFixture(Role.USER); + CertificationParam param = getCertificationParamFixtureWithUser(user); - assertThat(verificationPolicy.isCandidate(user, VerificationStatus.PENDING)).isTrue(); + //when, then + Assertions.assertThrowsExactly(CakkException.class, + () -> verificationPolicy.requestCertificationBusinessOwner(businessInformation, param)); } }