diff --git a/mdx-models/src/main/java/com/mx/path/model/mdx/accessor/p2p_transfer/P2PTransferBaseAccessor.java b/mdx-models/src/main/java/com/mx/path/model/mdx/accessor/p2p_transfer/P2PTransferBaseAccessor.java index a388e7c8..7e79c972 100644 --- a/mdx-models/src/main/java/com/mx/path/model/mdx/accessor/p2p_transfer/P2PTransferBaseAccessor.java +++ b/mdx-models/src/main/java/com/mx/path/model/mdx/accessor/p2p_transfer/P2PTransferBaseAccessor.java @@ -4,9 +4,13 @@ import lombok.Getter; import com.mx.path.core.common.accessor.API; +import com.mx.path.core.common.accessor.AccessorMethodNotImplementedException; import com.mx.path.core.common.gateway.GatewayAPI; import com.mx.path.core.common.gateway.GatewayClass; import com.mx.path.gateway.accessor.Accessor; +import com.mx.path.gateway.accessor.AccessorResponse; +import com.mx.path.model.mdx.model.MdxList; +import com.mx.path.model.mdx.model.p2p_transfer.P2PTransfer; /** * Accessor base for p2p transfer operations @@ -31,6 +35,69 @@ public class P2PTransferBaseAccessor extends Accessor { @Getter(AccessLevel.PROTECTED) private RecipientBaseAccessor recipients; + public P2PTransferBaseAccessor() { + } + + /** + * Create a P2P transfer + * + * @param p2pTransfer + * @return + */ + @GatewayAPI + @API(description = "Create a P2P transfer") + public AccessorResponse create(P2PTransfer p2pTransfer) { + throw new AccessorMethodNotImplementedException(); + } + + /** + * Delete a P2P transfer + * + * @param id + * @return + */ + @GatewayAPI + @API(description = "Delete a P2P transfer") + public AccessorResponse delete(String id) { + throw new AccessorMethodNotImplementedException(); + } + + /** + * Get a P2P Transfer + * + * @param id + * @return + */ + @GatewayAPI + @API(description = "Get a P2P transfer") + public AccessorResponse get(String id) { + throw new AccessorMethodNotImplementedException(); + } + + /** + * List all P2P transfers + * + * @return + */ + @GatewayAPI + @API(description = "List all P2P transfers") + public AccessorResponse> list() { + throw new AccessorMethodNotImplementedException(); + } + + /** + * Update a P2P transfer + * + * @param id + * @param p2pTransfer + * @return + */ + @GatewayAPI + @API(description = "Update a P2P transfer") + public AccessorResponse update(String id, P2PTransfer p2pTransfer) { + throw new AccessorMethodNotImplementedException(); + } + /** * Accessor for account operations * diff --git a/mdx-models/src/main/java/com/mx/path/model/mdx/model/Resources.java b/mdx-models/src/main/java/com/mx/path/model/mdx/model/Resources.java index 48fe529f..25565518 100644 --- a/mdx-models/src/main/java/com/mx/path/model/mdx/model/Resources.java +++ b/mdx-models/src/main/java/com/mx/path/model/mdx/model/Resources.java @@ -62,6 +62,7 @@ import com.mx.path.model.mdx.model.ondemand.mixins.TransactionsPageMixin; import com.mx.path.model.mdx.model.origination.Origination; import com.mx.path.model.mdx.model.p2p_transfer.Duration; +import com.mx.path.model.mdx.model.p2p_transfer.P2PTransfer; import com.mx.path.model.mdx.model.payment.Bill; import com.mx.path.model.mdx.model.payment.Enrollment; import com.mx.path.model.mdx.model.payment.Merchant; @@ -392,6 +393,10 @@ private static void registerP2PTransferModels(GsonBuilder builder) { builder.registerTypeAdapter(com.mx.path.model.mdx.model.p2p_transfer.Recipient.class, new ModelWrappableSerializer("recipient")); builder.registerTypeAdapter(new TypeToken>() { }.getType(), new ModelWrappableSerializer("recipients")); + // P2P Transfers + builder.registerTypeAdapter(P2PTransfer.class, new ModelWrappableSerializer("p2p_transfer")); + builder.registerTypeAdapter(new TypeToken>() { + }.getType(), new ModelWrappableSerializer("p2p_transfers")); } private static void registerPaymentsModels(GsonBuilder builder) { diff --git a/mdx-models/src/main/java/com/mx/path/model/mdx/model/p2p_transfer/P2PTransfer.java b/mdx-models/src/main/java/com/mx/path/model/mdx/model/p2p_transfer/P2PTransfer.java new file mode 100644 index 00000000..69ccdf60 --- /dev/null +++ b/mdx-models/src/main/java/com/mx/path/model/mdx/model/p2p_transfer/P2PTransfer.java @@ -0,0 +1,29 @@ +package com.mx.path.model.mdx.model.p2p_transfer; + +import java.math.BigDecimal; +import java.time.LocalDate; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import com.mx.path.model.mdx.model.MdxBase; +import com.mx.path.model.mdx.model.MdxList; +import com.mx.path.model.mdx.model.challenges.Challenge; + +@Data +@EqualsAndHashCode(callSuper = true) +public class P2PTransfer extends MdxBase { + private String id; + private String accountId; + private BigDecimal amount; + private MdxList challenges; + private String confirmationId; + private String deliveryMethod; + private String memo; + private String recipientId; + private String recipientVerificationAnswer; + private String recipientVerificationQuestion; + private LocalDate sendOn; + private LocalDate sentOn; + private String status; +} diff --git a/mdx-web/src/main/java/com/mx/path/model/mdx/web/controller/P2PTransfersController.java b/mdx-web/src/main/java/com/mx/path/model/mdx/web/controller/P2PTransfersController.java new file mode 100644 index 00000000..1a6b754a --- /dev/null +++ b/mdx-web/src/main/java/com/mx/path/model/mdx/web/controller/P2PTransfersController.java @@ -0,0 +1,47 @@ +package com.mx.path.model.mdx.web.controller; + +import com.mx.path.gateway.accessor.AccessorResponse; +import com.mx.path.model.mdx.model.MdxList; +import com.mx.path.model.mdx.model.p2p_transfer.P2PTransfer; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(value = "{clientId}", produces = BaseController.MDX_MEDIA) +public class P2PTransfersController extends BaseController { + @RequestMapping(value = "/users/{userId}/p2p_transfers", method = RequestMethod.POST, consumes = BaseController.MDX_MEDIA) + public final ResponseEntity create(@RequestBody P2PTransfer p2pTransferRequest) { + AccessorResponse response = gateway().p2pTransfers().create(p2pTransferRequest); + return new ResponseEntity<>(response.getResult().wrapped(), createMultiMapForResponse(response.getHeaders()), HttpStatus.OK); + } + + @RequestMapping(value = "/users/{userId}/p2p_transfers/{id}", method = RequestMethod.DELETE) + public final ResponseEntity delete(@PathVariable("id") String p2pTransferId) { + AccessorResponse response = gateway().p2pTransfers().delete(p2pTransferId); + return new ResponseEntity<>(createMultiMapForResponse(response.getHeaders()), HttpStatus.NO_CONTENT); + } + + @RequestMapping(value = "/users/{userId}/p2p_transfers/{id}", method = RequestMethod.GET) + public final ResponseEntity get(@PathVariable("id") String p2pTransferId) { + AccessorResponse response = gateway().p2pTransfers().get(p2pTransferId); + return new ResponseEntity<>(response.getResult().wrapped(), createMultiMapForResponse(response.getHeaders()), HttpStatus.OK); + } + + @RequestMapping(value = "/users/{userId}/p2p_transfers", method = RequestMethod.GET) + public final ResponseEntity> list() { + AccessorResponse> response = gateway().p2pTransfers().list(); + return new ResponseEntity<>(response.getResult().wrapped(), createMultiMapForResponse(response.getHeaders()), HttpStatus.OK); + } + + @RequestMapping(value = "/users/{userId}/p2p_transfers/{id}", method = RequestMethod.PUT, consumes = BaseController.MDX_MEDIA) + public final ResponseEntity update(@PathVariable("id") String p2pTransferId, @RequestBody P2PTransfer p2pTransferRequest) { + AccessorResponse response = gateway().p2pTransfers().update(p2pTransferId, p2pTransferRequest); + return new ResponseEntity<>(response.getResult().wrapped(), createMultiMapForResponse(response.getHeaders()), HttpStatus.OK); + } +} diff --git a/mdx-web/src/test/groovy/com/mx/path/model/mdx/web/controller/P2PTransfersControllerTest.groovy b/mdx-web/src/test/groovy/com/mx/path/model/mdx/web/controller/P2PTransfersControllerTest.groovy new file mode 100644 index 00000000..ba8e4cdb --- /dev/null +++ b/mdx-web/src/test/groovy/com/mx/path/model/mdx/web/controller/P2PTransfersControllerTest.groovy @@ -0,0 +1,110 @@ +package com.mx.path.model.mdx.web.controller + +import static org.mockito.Mockito.doReturn +import static org.mockito.Mockito.mock +import static org.mockito.Mockito.spy +import static org.mockito.Mockito.verify + +import com.mx.path.gateway.accessor.AccessorResponse +import com.mx.path.gateway.api.Gateway +import com.mx.path.gateway.api.p2p_transfer.P2PTransferGateway +import com.mx.path.model.mdx.model.MdxList +import com.mx.path.model.mdx.model.p2p_transfer.P2PTransfer + +import org.springframework.http.HttpStatus + +import spock.lang.Specification + +class P2PTransfersControllerTest extends Specification { + P2PTransfersController subject + Gateway gateway + P2PTransferGateway p2pTransferGateway + + def setup() { + subject = new P2PTransfersController() + p2pTransferGateway = mock(P2PTransferGateway) + gateway = spy(Gateway.builder().clientId("client-1234").p2pTransfers(p2pTransferGateway).build()) + } + + def cleanup() { + BaseController.clearGateway() + } + + def "create interacts with gateway"() { + given: + BaseController.setGateway(gateway) + def p2pTransfer = new P2PTransfer() + doReturn(new AccessorResponse().withResult(p2pTransfer)).when(p2pTransferGateway).create(p2pTransfer) + + when: + def result = subject.create(p2pTransfer) + + then: + HttpStatus.OK == result.statusCode + result.body == p2pTransfer + verify(p2pTransferGateway).create(p2pTransfer) || true + } + + def "delete interacts with gateway"() { + given: + BaseController.setGateway(gateway) + def id = "transfer-1234" + doReturn(new AccessorResponse()).when(p2pTransferGateway).delete(id) + + when: + def result = subject.delete(id) + + then: + HttpStatus.NO_CONTENT == result.statusCode + verify(p2pTransferGateway).delete(id) || true + } + + def "get interacts with gateway"() { + given: + BaseController.setGateway(gateway) + def id = "transfer-1234" + def p2pTransfer = new P2PTransfer() + doReturn(new AccessorResponse().withResult(p2pTransfer)).when(p2pTransferGateway).get(id) + + when: + def result = subject.get(id) + + then: + HttpStatus.OK == result.statusCode + result.body == p2pTransfer + verify(p2pTransferGateway).get(id) || true + } + + def "list interacts with gateway"() { + given: + BaseController.setGateway(gateway) + def p2pTransfers = new MdxList().tap { + add(new P2PTransfer()) + } + doReturn(new AccessorResponse>().withResult(p2pTransfers)).when(p2pTransferGateway).list() + + when: + def result = subject.list() + + then: + HttpStatus.OK == result.statusCode + result.body == p2pTransfers + verify(p2pTransferGateway).list() || true + } + + def "update interacts with gateway"() { + given: + BaseController.setGateway(gateway) + def id = "transfer-1234" + def p2pTransfer = new P2PTransfer() + doReturn(new AccessorResponse().withResult(p2pTransfer)).when(p2pTransferGateway).update(id, p2pTransfer) + + when: + def result = subject.update(id, p2pTransfer) + + then: + HttpStatus.OK == result.statusCode + result.body == p2pTransfer + verify(p2pTransferGateway).update(id, p2pTransfer) || true + } +}