From db2e4f26425f7d18a97380b3e9cc5a9c9a30dfee Mon Sep 17 00:00:00 2001 From: Scott Winters Date: Fri, 31 Mar 2023 15:32:21 -0400 Subject: [PATCH 1/4] [13-0013] - add payment method retrieve api --- .../user/controller/PaymentController.java | 121 ++++++++++++++++++ .../dao/repository/PaymentRepository.java | 14 ++ .../bravo/user/service/PaymentService.java | 32 +++++ src/main/resources/data.sql | 5 + .../user/service/PaymentServiceTest.java | 86 +++++++++++++ 5 files changed, 258 insertions(+) create mode 100644 src/main/java/com/bravo/user/controller/PaymentController.java create mode 100644 src/main/java/com/bravo/user/dao/repository/PaymentRepository.java create mode 100644 src/main/java/com/bravo/user/service/PaymentService.java create mode 100644 src/test/java/com/bravo/user/service/PaymentServiceTest.java 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..f7ad5c7 --- /dev/null +++ b/src/main/java/com/bravo/user/controller/PaymentController.java @@ -0,0 +1,121 @@ +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.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +@RequestMapping(value = "/payment") +@SwaggerController +public class PaymentController { + + private final UserValidator userValidator; + private final PaymentService paymentService; + + public PaymentController(UserValidator userValidator, PaymentService paymentService) { + this.userValidator = userValidator; + this.paymentService = paymentService; + } + + /* + public List retrieve(final @PathVariable String userId) { + userValidator.validateId(userId); + return addressService.retrieveByUserId(userId); + } + */ + + //private final PaymentService paymentService; + @GetMapping(value = "/retrieve/{userId}") + @ResponseBody + public List retrieve(final @PathVariable String userId) { + userValidator.validateId(userId); + return paymentService.retrieveByUserId(userId); + } + + +} + + +/* +@RequestMapping(value = "/user") +@SwaggerController +public class UserController { + + private final UserService userService; + private final UserValidator userValidator; + + public UserController(UserService userService, UserValidator userValidator) { + this.userService = userService; + this.userValidator = userValidator; + } + + @PostMapping(value = "/create") + @ResponseBody + public UserReadDto create(final @RequestBody UserSaveDto request, final BindingResult errors) + throws BindException { + userValidator.validate(Crud.CREATE, request, errors); + return userService.create(request); + } + + @GetMapping(value = "/retrieve") + @ResponseBody + public List retrieve( + final @RequestParam(required = false) String id, + final @RequestParam(required = false) String name, + final @RequestParam(required = false) Integer page, + final @RequestParam(required = false) Integer size, + final HttpServletResponse httpResponse + ) { + if(id != null){ + userValidator.validateId(id); + return Collections.singletonList(userService.retrieve(id)); + } + else if(name != null){ + userValidator.validateName(ValidatorUtil.removeControlCharacters(name)); + final PageRequest pageRequest = PageUtil.createPageRequest(page, size); + return userService.retrieveByName(name, pageRequest, httpResponse); + } + else { + throw new BadRequestException("'id' or 'name' is required!"); + } + } + + @PostMapping(value = "/retrieve") + @ResponseBody + public List retrieve( + final @RequestBody UserFilter filter, + final @RequestParam(required = false) Integer page, + final @RequestParam(required = false) Integer size, + final HttpServletResponse httpResponse + ) { + final PageRequest pageRequest = PageUtil.createPageRequest(page, size); + return userService.retrieve(filter, pageRequest, httpResponse); + } + + @PatchMapping(value = "/update/{id}") + @ResponseBody + public UserReadDto update( + final @PathVariable String id, + final @RequestBody UserSaveDto request, + final BindingResult errors + ) throws BindException { + userValidator.validateId(id); + userValidator.validate(Crud.UPDATE, request, errors); + return userService.update(id, request); + } + + @DeleteMapping(value = "/delete/{id}") + @ResponseBody + public boolean delete(final @PathVariable String id) { + userValidator.validateId(id); + return userService.delete(id); + } +} + + */ \ No newline at end of file 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..c4ae5a8 --- /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..e0525ab --- /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 id) { + final List payments = paymentRepository.findByUserId(id); + + LOGGER.info("found {} payment(s)", payments.size()); + return resourceMapper.convertPayments(payments); + } +} diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index da45720..6d38323 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -648,3 +648,8 @@ 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 +('42f33d30-f3f8-4743-a94e-4db11fdb747d', '008a4215-0b1d-445e-b655-a964039cbb5a', '1234456789123456', '01', '24'), +('579872ec-46f8-46b5-b809-d0724d965f0e', '00963d9b-f884-485e-9455-fcf30c6ac379', '7891234567891234', '02', '25'), +('95a983d0-ba0e-4f30-afb6-667d4724b253', '00963d9b-f884-485e-9455-fcf30c6ac379', '5678912345678912', '03', '26'); 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..4de74ab --- /dev/null +++ b/src/test/java/com/bravo/user/service/PaymentServiceTest.java @@ -0,0 +1,86 @@ +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.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ContextConfiguration(classes = {App.class}) +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class PaymentServiceTest { + + @Autowired + private PaymentService paymentService; + + @MockBean + private ResourceMapper resourceMapper; + + @MockBean + private PaymentRepository paymentRepository; + + private List dtoPayments; + + @BeforeEach + public void beforeEach() { + final List ids = IntStream.range(1, 10).boxed().collect(Collectors.toList()); + + final List daoPayments = ids.stream() + .map(id -> createPayment(Integer.toString(id))).collect(Collectors.toList()); + + when(paymentRepository.findByUserId("123a-456b")).thenReturn(daoPayments); + + this.dtoPayments = ids.stream().map(id -> createPaymentDto(Integer.toString(id))) + .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); + } + + @Test + void retrieveByUserIdNoResults() { + final String userId = "456b-789c"; + final List results = paymentService.retrieveByUserId(userId); + assertTrue(results.isEmpty()); + + verify(paymentRepository).findByUserId(userId); + } + + private Payment createPayment(final String id) { + final Payment payment = new Payment(); + payment.setId(id); + return payment; + } + + private PaymentDto createPaymentDto(final String id) { + final PaymentDto payment = new PaymentDto(); + payment.setId(id); + return payment; + } +} From 4b767fbe0dcf257c372806c08b3c447e2998c35c Mon Sep 17 00:00:00 2001 From: Scott Winters Date: Fri, 31 Mar 2023 15:35:21 -0400 Subject: [PATCH 2/4] [13-0013] - cleanup whoooops --- .../user/controller/PaymentController.java | 88 ------------------- 1 file changed, 88 deletions(-) diff --git a/src/main/java/com/bravo/user/controller/PaymentController.java b/src/main/java/com/bravo/user/controller/PaymentController.java index f7ad5c7..28859a9 100644 --- a/src/main/java/com/bravo/user/controller/PaymentController.java +++ b/src/main/java/com/bravo/user/controller/PaymentController.java @@ -22,15 +22,6 @@ public PaymentController(UserValidator userValidator, PaymentService paymentServ this.userValidator = userValidator; this.paymentService = paymentService; } - - /* - public List retrieve(final @PathVariable String userId) { - userValidator.validateId(userId); - return addressService.retrieveByUserId(userId); - } - */ - - //private final PaymentService paymentService; @GetMapping(value = "/retrieve/{userId}") @ResponseBody public List retrieve(final @PathVariable String userId) { @@ -40,82 +31,3 @@ public List retrieve(final @PathVariable String userId) { } - - -/* -@RequestMapping(value = "/user") -@SwaggerController -public class UserController { - - private final UserService userService; - private final UserValidator userValidator; - - public UserController(UserService userService, UserValidator userValidator) { - this.userService = userService; - this.userValidator = userValidator; - } - - @PostMapping(value = "/create") - @ResponseBody - public UserReadDto create(final @RequestBody UserSaveDto request, final BindingResult errors) - throws BindException { - userValidator.validate(Crud.CREATE, request, errors); - return userService.create(request); - } - - @GetMapping(value = "/retrieve") - @ResponseBody - public List retrieve( - final @RequestParam(required = false) String id, - final @RequestParam(required = false) String name, - final @RequestParam(required = false) Integer page, - final @RequestParam(required = false) Integer size, - final HttpServletResponse httpResponse - ) { - if(id != null){ - userValidator.validateId(id); - return Collections.singletonList(userService.retrieve(id)); - } - else if(name != null){ - userValidator.validateName(ValidatorUtil.removeControlCharacters(name)); - final PageRequest pageRequest = PageUtil.createPageRequest(page, size); - return userService.retrieveByName(name, pageRequest, httpResponse); - } - else { - throw new BadRequestException("'id' or 'name' is required!"); - } - } - - @PostMapping(value = "/retrieve") - @ResponseBody - public List retrieve( - final @RequestBody UserFilter filter, - final @RequestParam(required = false) Integer page, - final @RequestParam(required = false) Integer size, - final HttpServletResponse httpResponse - ) { - final PageRequest pageRequest = PageUtil.createPageRequest(page, size); - return userService.retrieve(filter, pageRequest, httpResponse); - } - - @PatchMapping(value = "/update/{id}") - @ResponseBody - public UserReadDto update( - final @PathVariable String id, - final @RequestBody UserSaveDto request, - final BindingResult errors - ) throws BindException { - userValidator.validateId(id); - userValidator.validate(Crud.UPDATE, request, errors); - return userService.update(id, request); - } - - @DeleteMapping(value = "/delete/{id}") - @ResponseBody - public boolean delete(final @PathVariable String id) { - userValidator.validateId(id); - return userService.delete(id); - } -} - - */ \ No newline at end of file From 1089a8c190ada56f8c6a6d6bf9f3541e2349af25 Mon Sep 17 00:00:00 2001 From: Scott Winters Date: Fri, 31 Mar 2023 16:25:36 -0400 Subject: [PATCH 3/4] [0013] forgot controller tests --- .../controller/PaymentControllerTest.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/test/java/com/bravo/user/controller/PaymentControllerTest.java 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..10499a1 --- /dev/null +++ b/src/test/java/com/bravo/user/controller/PaymentControllerTest.java @@ -0,0 +1,84 @@ +package com.bravo.user.controller; + +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; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import com.bravo.user.dao.model.Payment; +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 com.bravo.user.App; + +@ContextConfiguration(classes = { App.class }) +@ExtendWith(SpringExtension.class) +@SpringBootTest() +@AutoConfigureMockMvc +public class PaymentControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private PaymentService paymentService; + + private List payments; + + @BeforeEach + public void beforeEach() { + final List ids = IntStream.range(1, 10).boxed().collect(Collectors.toList()); + + this.payments = ids.stream().map(id -> createPaymentDto(Integer.toString(id))) + .collect(Collectors.toList()); + } + + private PaymentDto createPaymentDto(final String id) { + final PaymentDto payment = new PaymentDto(); + payment.setId(id); + return payment; + } + + @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()); + } +} From 32888568e93e8ad8cfcfd2ab64b17c68968bf82b Mon Sep 17 00:00:00 2001 From: Scott Winters Date: Fri, 31 Mar 2023 16:27:05 -0400 Subject: [PATCH 4/4] actually run auto format on the controller test --- .../controller/PaymentControllerTest.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/bravo/user/controller/PaymentControllerTest.java b/src/test/java/com/bravo/user/controller/PaymentControllerTest.java index 10499a1..80d0b63 100644 --- a/src/test/java/com/bravo/user/controller/PaymentControllerTest.java +++ b/src/test/java/com/bravo/user/controller/PaymentControllerTest.java @@ -1,17 +1,6 @@ package com.bravo.user.controller; -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; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import com.bravo.user.dao.model.Payment; +import com.bravo.user.App; import com.bravo.user.model.dto.PaymentDto; import com.bravo.user.service.PaymentService; import org.junit.jupiter.api.BeforeEach; @@ -26,9 +15,18 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; -import com.bravo.user.App; +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 }) +@ContextConfiguration(classes = {App.class}) @ExtendWith(SpringExtension.class) @SpringBootTest() @AutoConfigureMockMvc