Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Customer id 변경 #58

Merged
merged 12 commits into from
Aug 15, 2024
8 changes: 6 additions & 2 deletions src/main/java/camp/woowak/lab/customer/domain/Customer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package camp.woowak.lab.customer.domain;

import java.util.UUID;

import camp.woowak.lab.customer.exception.InvalidCreationException;
import camp.woowak.lab.payaccount.domain.PayAccount;
import camp.woowak.lab.web.authentication.PasswordEncoder;
Expand All @@ -10,14 +12,16 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.Getter;

@Entity
@Getter
@Table(name = "Customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(nullable = false, length = 50)
private String name;
@Column(unique = true, nullable = false, length = 100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import camp.woowak.lab.payaccount.repository.PayAccountRepository;
import camp.woowak.lab.web.authentication.PasswordEncoder;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SignUpCustomerService {
private final CustomerRepository customerRepository;
Expand All @@ -32,18 +34,18 @@ public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRe
* @throws DuplicateEmailException 이메일이 중복되는 경우
*/
@Transactional
public Long signUp(SignUpCustomerCommand cmd) {
public String signUp(SignUpCustomerCommand cmd) {
PayAccount payAccount = new PayAccount();
payAccountRepository.save(payAccount);

Customer newCustomer = new Customer(cmd.name(), cmd.email(), cmd.password(), cmd.phone(), payAccount,
passwordEncoder);

try {
customerRepository.save(newCustomer);
return customerRepository.saveAndFlush(newCustomer).getId().toString();
} catch (DataIntegrityViolationException e) {
log.error("데이터 무결성 위반");
throw new DuplicateEmailException();
}
return newCustomer.getId();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package camp.woowak.lab.payaccount.repository;

import java.util.Optional;
import java.util.UUID;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
Expand All @@ -13,5 +14,5 @@
public interface PayAccountRepository extends JpaRepository<PayAccount, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT pa FROM PayAccount pa LEFT JOIN Customer c on c.payAccount = pa where c.id = :customerId")
Optional<PayAccount> findByCustomerIdForUpdate(@Param("customerId") Long customerId);
Optional<PayAccount> findByCustomerIdForUpdate(@Param("customerId") UUID customerId);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package camp.woowak.lab.payaccount.service.command;

import java.util.UUID;

public record PayAccountChargeCommand(
Long customerId,
UUID customerId,
long amount) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public SignUpCustomerResponse signUp(@Valid @RequestBody SignUpCustomerRequest r
SignUpCustomerCommand command =
new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone());

Long registeredId = signUpCustomerService.signUp(command);
String registeredId = signUpCustomerService.signUp(command);

response.setHeader("Location", "/customers/" + registeredId);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package camp.woowak.lab.web.authentication;

import java.util.UUID;

public class LoginCustomer implements LoginMember {
private final Long id;
private final UUID id;

public LoginCustomer(Long id) {
public LoginCustomer(UUID id) {
this.id = id;
}

@Override
public Long getId() {
public UUID getId() {
return id;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package camp.woowak.lab.web.dto.response.customer;

public record SignUpCustomerResponse(Long id) {
public record SignUpCustomerResponse(String id) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;

import camp.woowak.lab.customer.exception.DuplicateEmailException;
import camp.woowak.lab.customer.exception.InvalidCreationException;
import camp.woowak.lab.customer.repository.CustomerRepository;
import camp.woowak.lab.customer.service.command.SignUpCustomerCommand;
import camp.woowak.lab.payaccount.repository.PayAccountRepository;
Expand All @@ -27,7 +27,7 @@ class SignUpCustomerServiceIntegrationTest {

@Test
@DisplayName("이메일 중복 시 롤백 테스트")
void testRollbackOnDuplicateEmail() throws InvalidCreationException, DuplicateEmailException {
void testRollbackOnDuplicateEmail() {
// given
SignUpCustomerCommand command1 = new SignUpCustomerCommand("name1", "[email protected]", "password",
"010-1234-5678");
Expand All @@ -43,10 +43,11 @@ void testRollbackOnDuplicateEmail() throws InvalidCreationException, DuplicateEm
// then
try {
service.signUp(command2);
fail("중복 이메일 예외가 발생해야 합니다.");
} catch (DuplicateEmailException e) {
assertEquals(1, customerRepository.count());
assertEquals(1, payAccountRepository.count());
} catch (DataIntegrityViolationException e) {
fail("DataIntegrityViolationException이 발생했습니다.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static org.mockito.BDDMockito.*;

import java.util.UUID;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -14,13 +16,11 @@

import camp.woowak.lab.customer.domain.Customer;
import camp.woowak.lab.customer.exception.DuplicateEmailException;
import camp.woowak.lab.customer.exception.InvalidCreationException;
import camp.woowak.lab.customer.repository.CustomerRepository;
import camp.woowak.lab.customer.service.command.SignUpCustomerCommand;
import camp.woowak.lab.fixture.CustomerFixture;
import camp.woowak.lab.payaccount.domain.PayAccount;
import camp.woowak.lab.payaccount.repository.PayAccountRepository;
import camp.woowak.lab.web.authentication.NoOpPasswordEncoder;
import camp.woowak.lab.web.authentication.PasswordEncoder;

@ExtendWith(MockitoExtension.class)
Expand All @@ -40,13 +40,14 @@ class SignUpCustomerServiceTest implements CustomerFixture {

@Test
@DisplayName("구매자 회원가입 테스트")
void testSignUp() throws InvalidCreationException, DuplicateEmailException {
void testSignUp() {
// given
given(passwordEncoder.encode(Mockito.anyString())).willReturn("password");
PayAccount payAccount = createPayAccount();
Customer customer = createCustomer(payAccount, new NoOpPasswordEncoder());
Customer customerMock = Mockito.mock(Customer.class);
given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(payAccount);
given(customerRepository.save(Mockito.any(Customer.class))).willReturn(customer);
given(customerRepository.saveAndFlush(Mockito.any(Customer.class))).willReturn(customerMock);
when(customerMock.getId()).thenReturn(UUID.randomUUID());

// when
SignUpCustomerCommand command =
Expand All @@ -55,7 +56,7 @@ void testSignUp() throws InvalidCreationException, DuplicateEmailException {

// then
then(payAccountRepository).should().save(Mockito.any(PayAccount.class));
then(customerRepository).should().save(Mockito.any(Customer.class));
then(customerRepository).should().saveAndFlush(Mockito.any(Customer.class));
}

@Test
Expand All @@ -64,7 +65,8 @@ void testSignUpWithExistingEmail() {
// given
given(passwordEncoder.encode(Mockito.anyString())).willReturn("password");
given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(createPayAccount());
when(customerRepository.save(Mockito.any(Customer.class))).thenThrow(DataIntegrityViolationException.class);
when(customerRepository.saveAndFlush(Mockito.any(Customer.class))).thenThrow(
DataIntegrityViolationException.class);

// when
SignUpCustomerCommand command =
Expand All @@ -73,6 +75,6 @@ void testSignUpWithExistingEmail() {
// then
Assertions.assertThrows(DuplicateEmailException.class, () -> service.signUp(command));
then(payAccountRepository).should().save(Mockito.any(PayAccount.class));
then(customerRepository).should().save(Mockito.any(Customer.class));
then(customerRepository).should().saveAndFlush(Mockito.any(Customer.class));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.assertj.core.api.Assertions.*;

import java.util.Optional;
import java.util.UUID;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand Down Expand Up @@ -71,7 +72,7 @@ void withdrawAccount() {
@DisplayName("없는 AccountId를 호출하면 NotFoundAccountException을 던진다. 잔고는 유지된다.")
void withdrawAccountNotFound() {
//given
Long unknownAccountId = Long.MAX_VALUE;
UUID unknownAccountId = UUID.randomUUID();
long amount = 100L;
PayAccountChargeCommand command = new PayAccountChargeCommand(unknownAccountId, amount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.Optional;
import java.util.UUID;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -102,9 +103,9 @@ void successTest() throws Exception {

//when & then
mvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.data.balance").value(amount + originBalance));
Expand All @@ -122,9 +123,9 @@ void dailyLimitExceededTest() throws Exception {

//when & then
ResultActions actions = mvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.andDo(print())
.andExpect(status().isBadRequest());

Expand All @@ -136,16 +137,16 @@ void dailyLimitExceededTest() throws Exception {
void notExistsAccountIdTest() throws Exception {
//given
long amount = 1000L;
Long notExistsId = Long.MAX_VALUE;
UUID notExistsId = UUID.randomUUID();
MockHttpSession notExistsSession = new MockHttpSession();
notExistsSession.setAttribute(SessionConst.SESSION_CUSTOMER_KEY, new LoginCustomer(notExistsId));
PayAccountChargeRequest command = new PayAccountChargeRequest(amount);

//when & then
ResultActions actions = mvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(notExistsSession))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(notExistsSession))
.andExpect(status().isNotFound());

validateErrorResponseWithErrorCode(actions, PayAccountErrorCode.ACCOUNT_NOT_FOUND);
Expand All @@ -159,9 +160,9 @@ void nullAmountTest() throws Exception {

//when & then
ResultActions actions = mvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.andExpect(status().isBadRequest());

verificationPersistedBalance(payAccount.getId(), originBalance);
Expand All @@ -176,9 +177,9 @@ void negativeAmountTest() throws Exception {

//when & then
ResultActions actions = mvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsBytes(command))
.session(session))
.andExpect(status().isBadRequest());

validateErrorResponseWithErrorCode(actions, PayAccountErrorCode.INVALID_TRANSACTION_AMOUNT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.UUID;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -38,9 +40,10 @@ class CustomerApiControllerTest {
@DisplayName("구매자 회원가입 테스트 - 성공")
void testSignUpCustomer() throws Exception {
// given
String customerId = UUID.randomUUID().toString();
SignUpCustomerRequest request = new SignUpCustomerRequest("name", "[email protected]", "password123",
"010-1234-5678");
given(signUpCustomerService.signUp(any())).willReturn(1L);
given(signUpCustomerService.signUp(any())).willReturn(customerId);

// when & then
mockMvc.perform(post("/customers")
Expand Down