diff --git a/src/main/java/com/bravo/user/controller/PaymentController.java b/src/main/java/com/bravo/user/controller/PaymentController.java new file mode 100644 index 0000000..2d4065d --- /dev/null +++ b/src/main/java/com/bravo/user/controller/PaymentController.java @@ -0,0 +1,29 @@ +package com.bravo.user.controller; + +import com.bravo.user.annotation.SwaggerController; +import com.bravo.user.model.dto.PaymentDto; +import com.bravo.user.service.PaymentService; +import com.bravo.user.validator.UserValidator; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequestMapping(value = "/payment") +@SwaggerController +public class PaymentController { + + private final PaymentService paymentService; + private final UserValidator userValidator; + + public PaymentController(PaymentService paymentService, UserValidator userValidator) { + this.paymentService = paymentService; + this.userValidator = userValidator; + } + + @GetMapping(value = "/retrieve/{userId}") + @ResponseBody + public List retrieve(final @PathVariable String userId) { + userValidator.validateId(userId); + return paymentService.retrieveByUserId(userId); + } +} \ No newline at end of file diff --git a/src/main/java/com/bravo/user/dao/model/mapper/ResourceMapper.java b/src/main/java/com/bravo/user/dao/model/mapper/ResourceMapper.java index 4a78188..e6eb7c4 100644 --- a/src/main/java/com/bravo/user/dao/model/mapper/ResourceMapper.java +++ b/src/main/java/com/bravo/user/dao/model/mapper/ResourceMapper.java @@ -48,7 +48,8 @@ public > List convertPayments(final T public PaymentDto convertPayment(final Payment payment){ final String cardNumber = payment.getCardNumber(); final PaymentDto dto = mapperFacade.map(payment, PaymentDto.class); - dto.setCardNumberLast4(cardNumber.substring(cardNumber.length() - 5)); + // Modified, substring gave 5 digits instead of 4 digits + dto.setCardNumberLast4(cardNumber.substring(cardNumber.length() - 4)); return dto; } diff --git a/src/main/java/com/bravo/user/dao/repository/PaymentRepository.java b/src/main/java/com/bravo/user/dao/repository/PaymentRepository.java new file mode 100644 index 0000000..53c8da9 --- /dev/null +++ b/src/main/java/com/bravo/user/dao/repository/PaymentRepository.java @@ -0,0 +1,14 @@ +package com.bravo.user.dao.repository; + +import com.bravo.user.dao.model.Payment; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface PaymentRepository extends JpaRepository, JpaSpecificationExecutor { + + List findByUserId(final String userId); +} diff --git a/src/main/java/com/bravo/user/service/PaymentService.java b/src/main/java/com/bravo/user/service/PaymentService.java new file mode 100644 index 0000000..345b3fd --- /dev/null +++ b/src/main/java/com/bravo/user/service/PaymentService.java @@ -0,0 +1,32 @@ +package com.bravo.user.service; + +import com.bravo.user.dao.model.Payment; +import com.bravo.user.dao.model.mapper.ResourceMapper; +import com.bravo.user.dao.repository.PaymentRepository; +import com.bravo.user.model.dto.PaymentDto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class PaymentService { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentService.class); + + private final PaymentRepository paymentRepository; + private final ResourceMapper resourceMapper; + + public PaymentService(PaymentRepository paymentRepository, ResourceMapper resourceMapper) { + this.paymentRepository = paymentRepository; + this.resourceMapper = resourceMapper; + } + + public List retrieveByUserId(final String userId){ + final List paymentList = paymentRepository.findByUserId(userId); + LOGGER.info("found {} payment(s)", paymentList.size()); + + return resourceMapper.convertPayments(paymentList); + } +} diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index da45720..7d5a1d2 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -648,3 +648,9 @@ insert into address (id, user_id, line1, line2, city, state, zip) values ('42f33d30-f3f8-4743-a94e-4db11fdb747d', '008a4215-0b1d-445e-b655-a964039cbb5a', '412 Maple St', null, 'Dowagiac', 'Michigan', '49047'), ('579872ec-46f8-46b5-b809-d0724d965f0e', '00963d9b-f884-485e-9455-fcf30c6ac379', '237 Mountain Ter', 'Apt 10', 'Odenville', 'Alabama', '35120'), ('95a983d0-ba0e-4f30-afb6-667d4724b253', '00963d9b-f884-485e-9455-fcf30c6ac379', '107 Annettes Ct', null, 'Aydlett', 'North Carolina', '27916'); + +insert into payment(id, user_id, card_number, expiry_month, expiry_year) values +('4361116e-bae1-4539-9144-2b17ac76216c', '008a4215-0b1d-445e-b655-a964039cbb5a', '6011836725346986', 09, 2026), +('85b8cf40-2953-4004-8289-82a72110e75c', '008a4215-0b1d-445e-b655-a964039cbb5a', '373996186314348', 11, 2022), +('622ef959-da96-4448-bfa1-0cb82d21af3f', '00963d9b-f884-485e-9455-fcf30c6ac379', '371297579926182', 08, 2023), +('edc49523-1fe8-471e-9fe9-9f7861fb026e', '00bed3ac-5f3c-4a2d-a67b-80376ea9f941', '3559744047486115', 03, 2024); \ No newline at end of file diff --git a/src/test/java/com/bravo/user/controller/PaymentControllerTest.java b/src/test/java/com/bravo/user/controller/PaymentControllerTest.java new file mode 100644 index 0000000..7459ac0 --- /dev/null +++ b/src/test/java/com/bravo/user/controller/PaymentControllerTest.java @@ -0,0 +1,85 @@ +package com.bravo.user.controller; + +import com.bravo.user.App; +import com.bravo.user.model.dto.PaymentDto; +import com.bravo.user.service.PaymentService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ContextConfiguration(classes = { App.class }) +@ExtendWith(SpringExtension.class) +@SpringBootTest() +@AutoConfigureMockMvc +class PaymentControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private PaymentService paymentService; + + private List payments; + + @BeforeEach + public void beforeEach() { + this.payments = IntStream.range(1, 10) + .mapToObj(this::createPaymentDto) + .collect(Collectors.toList()); + } + + @Test + void getRetrieveByUserId() throws Exception { + final String userId = "123a-456b"; + + when(paymentService + .retrieveByUserId(anyString())) + .thenReturn(payments); + + final ResultActions result = this.mockMvc + .perform(get("/payment/retrieve/".concat(userId))) + .andExpect(status().isOk()); + + for(int i = 0; i < payments.size(); i++){ + result.andExpect(jsonPath(String.format("$[%d].id", i)).value(payments.get(i).getId())); + } + + verify(paymentService).retrieveByUserId(userId); + } + + @Test + void getRetrieveByUserId_Space() throws Exception { + this.mockMvc.perform(get("/payment/retrieve/ /")).andExpect(status().isBadRequest()); + } + + @Test + void getRetrieveByUserId_Missing() throws Exception { + this.mockMvc.perform(get("/payment/retrieve")).andExpect(status().isNotFound()); + } + + private PaymentDto createPaymentDto(final int id) { + final PaymentDto payment = new PaymentDto(); + payment.setId(Integer.toString(id)); + return payment; + } + +} diff --git a/src/test/java/com/bravo/user/dao/model/mapper/ResourceMapperTest.java b/src/test/java/com/bravo/user/dao/model/mapper/ResourceMapperTest.java index 2b1e32c..15f4864 100644 --- a/src/test/java/com/bravo/user/dao/model/mapper/ResourceMapperTest.java +++ b/src/test/java/com/bravo/user/dao/model/mapper/ResourceMapperTest.java @@ -1,5 +1,7 @@ package com.bravo.user.dao.model.mapper; +import com.bravo.user.dao.model.Payment; +import com.bravo.user.model.dto.PaymentDto; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -48,4 +50,15 @@ void convertAddressTest( @ConvertWith(MapperArgConverter.class) AddressDto addressDto) { Assertions.assertEquals(addressDto, resourceMapper.convertAddress(address)); } + + @ParameterizedTest + @CsvFileSource( + resources = ("/ResourceMapperTest/convertPaymentTest.csv"), + delimiter = '$', + lineSeparator = ">") + void convertPaymentTest( + @ConvertWith(MapperArgConverter.class) Payment payment, + @ConvertWith(MapperArgConverter.class) PaymentDto paymentDto) { + Assertions.assertEquals(paymentDto, resourceMapper.convertPayment(payment)); + } } \ No newline at end of file diff --git a/src/test/java/com/bravo/user/service/PaymentServiceTest.java b/src/test/java/com/bravo/user/service/PaymentServiceTest.java new file mode 100644 index 0000000..e0f3c23 --- /dev/null +++ b/src/test/java/com/bravo/user/service/PaymentServiceTest.java @@ -0,0 +1,78 @@ +package com.bravo.user.service; + +import com.bravo.user.App; +import com.bravo.user.dao.model.Payment; +import com.bravo.user.dao.model.mapper.ResourceMapper; +import com.bravo.user.dao.repository.PaymentRepository; +import com.bravo.user.model.dto.PaymentDto; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ContextConfiguration(classes = { App.class }) +@ExtendWith(SpringExtension.class) +@SpringBootTest +class PaymentServiceTest { + + @Autowired + private PaymentService paymentService; + + @MockBean + private ResourceMapper resourceMapper; + + @MockBean + private PaymentRepository paymentRepository; + + private List dtoPayments; + + @BeforeEach + public void beforeEach() { + final List daoPayments = IntStream.range(1, 10) + .mapToObj(this::createPayment) + .collect(Collectors.toList()); + + when(paymentRepository.findByUserId(anyString())).thenReturn(daoPayments); + + this.dtoPayments = daoPayments.stream() + .map(this::createPaymentDto) + .collect(Collectors.toList()); + + when(resourceMapper.convertPayments(daoPayments)).thenReturn(dtoPayments); + } + + @Test + void retrieveByUserId() { + final String userId = "123a-456b"; + final List results = paymentService.retrieveByUserId(userId); + assertEquals(dtoPayments, results); + + verify(paymentRepository).findByUserId(userId); + } + + private Payment createPayment(final int id) { + final Payment payment = new Payment(); + payment.setId(Integer.toString(id)); + return payment; + } + + private PaymentDto createPaymentDto(final Payment payment) { + final PaymentDto paymentDta = new PaymentDto(); + paymentDta.setId(payment.getId()); + return paymentDta; + } + +} diff --git a/src/test/resources/ResourceMapperTest/convertPaymentTest.csv b/src/test/resources/ResourceMapperTest/convertPaymentTest.csv new file mode 100644 index 0000000..fe6f061 --- /dev/null +++ b/src/test/resources/ResourceMapperTest/convertPaymentTest.csv @@ -0,0 +1,30 @@ +>{ + "id":"testId", + "userId":"testUserId", + "cardNumber":"3570643196366822", + "expiryMonth":"02", + "expiryYear":"2024", + "updated":"2022-04-13 12:00:00" +} +${ + "id":"testId", + "cardNumberLast4":"6822", + "expiryMonth":"02", + "expiryYear":"2024", + "updated":"2022-04-13 12:00:00" +} +>{ + "id":"testId", + "userId":"testUserId", + "cardNumber":"30353997949251", + "expiryMonth":"09", + "expiryYear":"2023", + "updated":"2022-08-17 12:00:00" +} +${ + "id":"testId", + "cardNumberLast4":"9251", + "expiryMonth":"09", + "expiryYear":"2023", + "updated":"2022-08-17 12:00:00" +}