1
0
mirror of synced 2024-11-21 12:56:08 +03:00

Add customer-interaction

This commit is contained in:
Alex Komarichev 2024-07-31 18:24:22 +03:00
parent 8b677de616
commit a7cffe45da
12 changed files with 796 additions and 0 deletions

View File

@ -18,6 +18,7 @@ use RetailCrm\Api\Interfaces\RequestTransformerInterface;
use RetailCrm\Api\Interfaces\ResponseTransformerInterface; use RetailCrm\Api\Interfaces\ResponseTransformerInterface;
use RetailCrm\Api\ResourceGroup\Api; use RetailCrm\Api\ResourceGroup\Api;
use RetailCrm\Api\ResourceGroup\Costs; use RetailCrm\Api\ResourceGroup\Costs;
use RetailCrm\Api\ResourceGroup\CustomerInteraction;
use RetailCrm\Api\ResourceGroup\Customers; use RetailCrm\Api\ResourceGroup\Customers;
use RetailCrm\Api\ResourceGroup\CustomersCorporate; use RetailCrm\Api\ResourceGroup\CustomersCorporate;
use RetailCrm\Api\ResourceGroup\CustomFields; use RetailCrm\Api\ResourceGroup\CustomFields;
@ -67,6 +68,9 @@ class Client
/** @var \RetailCrm\Api\ResourceGroup\CustomFields */ /** @var \RetailCrm\Api\ResourceGroup\CustomFields */
public $customFields; public $customFields;
/** @var \RetailCrm\Api\ResourceGroup\CustomerInteraction */
public $customerInteraction;
/** @var \RetailCrm\Api\ResourceGroup\Customers */ /** @var \RetailCrm\Api\ResourceGroup\Customers */
public $customers; public $customers;
@ -187,6 +191,14 @@ class Client
$eventDispatcher, $eventDispatcher,
$logger $logger
); );
$this->customerInteraction = new CustomerInteraction(
$url,
$httpClient,
$requestTransformer,
$responseTransformer,
$eventDispatcher,
$logger
);
$this->customers = new Customers( $this->customers = new Customers(
$url, $url,
$httpClient, $httpClient,

22
src/Enum/BySite.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* PHP version 7.3
*
* @category BySite
* @package RetailCrm\Api\Enum
*/
namespace RetailCrm\Api\Enum;
/**
* Class BySite
*
* @category BySite
* @package RetailCrm\Api\Enum
*/
final class BySite
{
public const ID = 'id';
public const CODE = 'code';
}

View File

@ -0,0 +1,86 @@
<?php
/**
* PHP version 7.3
*
* @category Cart
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Entity\CustomerInteraction;
use DateTime;
use RetailCrm\Api\Component\Serializer\Annotation as JMS;
/**
* Class Cart
*
* @category Cart
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
class Cart
{
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("currency")
*/
public $currency;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("externalId")
*/
public $externalId;
/**
* @var DateTime
*
* @JMS\Type("DateTime<'Y-m-d H:i:sP'>")
* @JMS\SerializedName("droppedAt")
*/
public $droppedAt;
/**
* @var DateTime
*
* @JMS\Type("DateTime<'Y-m-d H:i:sP'>")
* @JMS\SerializedName("clearedAt")
*/
public $clearedAt;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("link")
*/
public $link;
/**
* @var \RetailCrm\Api\Model\Entity\CustomerInteraction\CartCustomer
*
* @JMS\Type("RetailCrm\Api\Model\Entity\CustomerInteraction\CartCustomer")
* @JMS\SerializedName("customer")
*/
public $customer;
/**
* @var \RetailCrm\Api\Model\Entity\CustomerInteraction\CartItem[]
*
* @JMS\Type("array<RetailCrm\Api\Model\Entity\CustomerInteraction\CartItem>")
* @JMS\SerializedName("items")
*/
public $items;
/**
* @var \RetailCrm\Api\Model\Entity\CustomerInteraction\CartOrder
*
* @JMS\Type("RetailCrm\Api\Model\Entity\CustomerInteraction\CartOrder")
* @JMS\SerializedName("order")
*/
public $order;
}

View File

@ -0,0 +1,61 @@
<?php
/**
* PHP version 7.3
*
* @category CartCustomer
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Entity\CustomerInteraction;
use RetailCrm\Api\Component\Serializer\Annotation as JMS;
/**
* Class CartCustomer
*
* @category CartCustomer
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
class CartCustomer
{
/**
* @var int
*
* @JMS\Type("int")
* @JMS\SerializedName("id")
*/
public $id;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("externalId")
*/
public $externalId;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("browserId")
*/
public $browserId;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("site")
*/
public $site;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("gaClientId")
*/
public $gaClientId;
}

View File

@ -0,0 +1,53 @@
<?php
/**
* PHP version 7.3
*
* @category CartItem
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Entity\CustomerInteraction;
use RetailCrm\Api\Component\Serializer\Annotation as JMS;
/**
* Class CartItem
*
* @category CartItem
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
class CartItem
{
/**
* @var int
*
* @JMS\Type("int")
* @JMS\SerializedName("id")
*/
public $id;
/**
* @var \RetailCrm\Api\Model\Entity\Orders\Items\Offer
*
* @JMS\Type("RetailCrm\Api\Model\Entity\Orders\Items\Offer")
* @JMS\SerializedName("offer")
*/
public $offer;
/**
* @var float
*
* @JMS\Type("float")
* @JMS\SerializedName("quantity")
*/
public $quantity;
/**
* @var float
*
* @JMS\Type("float")
* @JMS\SerializedName("price")
*/
public $price;
}

View File

@ -0,0 +1,45 @@
<?php
/**
* PHP version 7.3
*
* @category CartOrder
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Entity\CustomerInteraction;
use RetailCrm\Api\Component\Serializer\Annotation as JMS;
/**
* Class CartOrder
*
* @category CartOrder
* @package RetailCrm\Api\Model\Entity\CustomerInteraction
*/
class CartOrder
{
/**
* @var int
*
* @JMS\Type("int")
* @JMS\SerializedName("id")
*/
public $id;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("externalId")
*/
public $externalId;
/**
* @var string
*
* @JMS\Type("string")
* @JMS\SerializedName("number")
*/
public $number;
}

View File

@ -0,0 +1,55 @@
<?php
/**
* PHP version 7.3
*
* @category ByAndSiteByRequest
* @package RetailCrm\Api\Model\Request
*/
namespace RetailCrm\Api\Model\Request;
use RetailCrm\Api\Component\FormData\Mapping as Form;
use RetailCrm\Api\Interfaces\RequestInterface;
/**
* Class ByAndSiteByRequest
*
* @category ByAndSiteByRequest
* @package RetailCrm\Api\Model\Request
*/
class ByAndSiteByRequest implements RequestInterface
{
/**
* @var string
*
* @Form\Type("string")
* @Form\SerializedName("by")
*/
public $by;
/**
* @var string
*
* @Form\Type("string")
* @Form\SerializedName("siteBy")
*/
public $siteBy;
/**
* BySiteRequest constructor.
*
* @param string $by
* @param string $siteBy
*/
public function __construct(string $by = '', string $siteBy = '')
{
if ('' !== $by) {
$this->by = $by;
}
if ('' !== $siteBy) {
$this->siteBy = $siteBy;
}
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* PHP version 7.3
*
* @category CustomerInteractionCartClearRequest
* @package RetailCrm\Api\Model\Request\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Request\CustomerInteraction;
use RetailCrm\Api\Component\FormData\Mapping as Form;
use RetailCrm\Api\Interfaces\RequestInterface;
/**
* Class CustomerInteractionCartClearRequest
*
* @category CustomerInteractionCartClearRequest
* @package RetailCrm\Api\Model\Request\CustomerInteraction
*/
class CustomerInteractionCartClearRequest implements RequestInterface
{
/**
* @var string
*
* @Form\Type("string")
* @Form\SerializedName("siteBy")
*/
public $siteBy;
/**
* @var \RetailCrm\Api\Model\Entity\CustomerInteraction\Cart
*
* @Form\Type("RetailCrm\Api\Model\Entity\CustomerInteraction\Cart")
* @Form\SerializedName("cart")
* @Form\JsonField()
*/
public $cart;
}

View File

@ -0,0 +1,20 @@
<?php
/**
* PHP version 7.3
*
* @category CustomerInteractionCartSetRequest
* @package RetailCrm\Api\Model\Request\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Request\CustomerInteraction;
/**
* Class CustomerInteractionCartSetRequest
*
* @category CustomerInteractionCartSetRequest
* @package RetailCrm\Api\Model\Request\CustomerInteraction
*/
class CustomerInteractionCartSetRequest extends CustomerInteractionCartClearRequest
{
}

View File

@ -0,0 +1,30 @@
<?php
/**
* PHP version 7.3
*
* @category CustomerInteractionCartGetResponse
* @package RetailCrm\Api\Model\Response\CustomerInteraction
*/
namespace RetailCrm\Api\Model\Response\CustomerInteraction;
use RetailCrm\Api\Component\Serializer\Annotation as JMS;
use RetailCrm\Api\Model\Response\SuccessResponse;
/**
* Class CustomerInteractionCartGetResponse
*
* @category CustomerInteractionCartGetResponse
* @package RetailCrm\Api\Model\Response\CustomerInteraction
*/
class CustomerInteractionCartGetResponse extends SuccessResponse
{
/**
* @var \RetailCrm\Api\Model\Entity\CustomerInteraction\Cart
*
* @JMS\Type("RetailCrm\Api\Model\Entity\CustomerInteraction\Cart")
* @JMS\SerializedName("cart")
*/
public $cart;
}

View File

@ -0,0 +1,238 @@
<?php
/**
* PHP version 7.3
*
* @category CustomerInteraction
* @package RetailCrm\Api\ResourceGroup
*/
namespace RetailCrm\Api\ResourceGroup;
use RetailCrm\Api\Enum\RequestMethod;
use RetailCrm\Api\Model\Request\ByAndSiteByRequest;
use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartClearRequest;
use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartSetRequest;
use RetailCrm\Api\Model\Response\CustomerInteraction\CustomerInteractionCartGetResponse;
use RetailCrm\Api\Model\Response\SuccessResponse;
/**
* Class CustomerInteraction
*
* @category CustomerInteraction
* @package RetailCrm\Api\ResourceGroup
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CustomerInteraction extends AbstractApiResourceGroup
{
/**
* Makes POST "/api/v5/customer-interaction/{site}/cart/clear" request.
*
* Example:
* ```php
* use RetailCrm\Api\Enum\BySite;
* use RetailCrm\Api\Factory\SimpleClientFactory;
* use RetailCrm\Api\Interfaces\ApiExceptionInterface;
* use RetailCrm\Api\Model\Entity\CustomerInteraction\Cart;
* use RetailCrm\Api\Model\Entity\CustomerInteraction\CartCustomer;
* use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartClearRequest;
*
* $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey');
*
* $cart = new Cart();
* $cart->clearedAt = new DateTime('now');
* $cart->customer = new CartCustomer();
* $cart->customer->id = 4770;
* $cart->customer->browserId = 'browserId';
* $cart->customer->gaClientId = 'gaClientId';
*
* $request = new CustomerInteractionCartClearRequest();
* $request->cart = $cart;
* $request->siteBy = BySite::CODE;
*
* try {
* $response = $client->customerInteraction->cartClear('testSite', $request);
* } catch (ApiExceptionInterface $exception) {
* echo sprintf(
* 'Error from RetailCRM API (status code: %d): %s',
* $exception->getStatusCode(),
* $exception->getMessage()
* );
*
* if (count($exception->getErrorResponse()->errors) > 0) {
* echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors);
* }
*
* return;
* }
* ```
*
* @param string|int $site
* @param \RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartClearRequest $request
*
* @return \RetailCrm\Api\Model\Response\SuccessResponse
* @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface
* @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface
* @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException
* @throws \RetailCrm\Api\Exception\Api\ApiErrorException
* @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException
* @throws \RetailCrm\Api\Exception\Api\MissingParameterException
* @throws \RetailCrm\Api\Exception\Api\ValidationException
* @throws \RetailCrm\Api\Exception\Client\HandlerException
* @throws \RetailCrm\Api\Exception\Client\HttpClientException
*/
public function cartClear($site, CustomerInteractionCartClearRequest $request): SuccessResponse
{
/** @var SuccessResponse $response */
$response = $this->sendRequest(
RequestMethod::POST,
'customer-interaction/' . $site . '/cart/clear',
$request,
SuccessResponse::class
);
return $response;
}
/**
* Makes POST "/api/v5/customer-interaction/{site}/cart/set" request.
*
* Example:
* ```php
* use RetailCrm\Api\Enum\BySite;
* use RetailCrm\Api\Factory\SimpleClientFactory;
* use RetailCrm\Api\Interfaces\ApiExceptionInterface;
* use RetailCrm\Api\Model\Entity\CustomerInteraction\Cart;
* use RetailCrm\Api\Model\Entity\CustomerInteraction\CartCustomer;
* use RetailCrm\Api\Model\Entity\CustomerInteraction\CartItem;
* use RetailCrm\Api\Model\Entity\Orders\Items\Offer;
* use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartSetRequest;
*
* $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey');
*
* $customer = new CartCustomer();
* $customer->id = 4770;
*
* $cartItem = new CartItem();
* $cartItem->price = 24.99;
* $cartItem->quantity = 2;
* $cartItem->offer = new Offer();
* $cartItem->offer->externalId = '47701234567890';
*
* $cart = new Cart();
* $cart->items[] = $cartItem;
* $cart->customer = $customer;
*
* $request = new CustomerInteractionCartSetRequest();
* $request->cart = $cart;
* $request->siteBy = BySite::CODE;
*
* try {
* $response = $client->customerInteraction->cartSet('testSite', $request);
* } catch (ApiExceptionInterface $exception) {
* echo sprintf(
* 'Error from RetailCRM API (status code: %d): %s',
* $exception->getStatusCode(),
* $exception->getMessage()
* );
*
* if (count($exception->getErrorResponse()->errors) > 0) {
* echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors);
* }
*
* return;
* }
* ```
*
* @param string|int $site
* @param \RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartSetRequest $request
*
* @return \RetailCrm\Api\Model\Response\SuccessResponse
* @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface
* @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface
* @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException
* @throws \RetailCrm\Api\Exception\Api\ApiErrorException
* @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException
* @throws \RetailCrm\Api\Exception\Api\MissingParameterException
* @throws \RetailCrm\Api\Exception\Api\ValidationException
* @throws \RetailCrm\Api\Exception\Client\HandlerException
* @throws \RetailCrm\Api\Exception\Client\HttpClientException
*/
public function cartSet($site, CustomerInteractionCartSetRequest $request): SuccessResponse
{
/** @var SuccessResponse $response */
$response = $this->sendRequest(
RequestMethod::POST,
'customer-interaction/' . $site . '/cart/set',
$request,
SuccessResponse::class
);
return $response;
}
/**
* Makes GET "/api/v5/customer-interaction/{site}/cart/{customerId}" request.
*
* Example:
* ```php
* use RetailCrm\Api\Enum\ByIdentifier;
* use RetailCrm\Api\Enum\BySite;
* use RetailCrm\Api\Factory\SimpleClientFactory;
* use RetailCrm\Api\Interfaces\ApiExceptionInterface;
* use RetailCrm\Api\Model\Request\ByAndSiteByRequest;
*
* $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey');
*
* try {
* $response = $client->customerInteraction->cartGet(
* 'testSite',
* 4200,
* new ByAndSiteByRequest(ByIdentifier::ID, BySite::CODE)
* );
* } catch (ApiExceptionInterface $exception) {
* echo sprintf(
* 'Error from RetailCRM API (status code: %d): %s',
* $exception->getStatusCode(),
* $exception->getMessage()
* );
*
* if (count($exception->getErrorResponse()->errors) > 0) {
* echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors);
* }
*
* return;
* }
*
* echo 'Cart: ' . print_r($response->cart, true);
* ```
*
* @param string|int $site
* @param string|int $customerId
* @param \RetailCrm\Api\Model\Request\ByAndSiteByRequest|null $request
*
* @return \RetailCrm\Api\Model\Response\CustomerInteraction\CustomerInteractionCartGetResponse
* @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface
* @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface
* @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException
* @throws \RetailCrm\Api\Exception\Api\ApiErrorException
* @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException
* @throws \RetailCrm\Api\Exception\Api\MissingParameterException
* @throws \RetailCrm\Api\Exception\Api\ValidationException
* @throws \RetailCrm\Api\Exception\Client\HandlerException
* @throws \RetailCrm\Api\Exception\Client\HttpClientException
*/
public function cartGet(
$site,
$customerId,
?ByAndSiteByRequest $request = null
): CustomerInteractionCartGetResponse {
/** @var CustomerInteractionCartGetResponse $response */
$response = $this->sendRequest(
RequestMethod::GET,
'customer-interaction/' . $site . '/cart/' . $customerId,
$request,
CustomerInteractionCartGetResponse::class
);
return $response;
}
}

View File

@ -0,0 +1,135 @@
<?php
namespace RetailCrm\Tests\ResourceGroup;
use DateTime;
use RetailCrm\Api\Enum\ByIdentifier;
use RetailCrm\Api\Enum\BySite;
use RetailCrm\Api\Enum\RequestMethod;
use RetailCrm\Api\Model\Entity\CustomerInteraction\Cart;
use RetailCrm\Api\Model\Entity\CustomerInteraction\CartCustomer;
use RetailCrm\Api\Model\Entity\CustomerInteraction\CartItem;
use RetailCrm\Api\Model\Entity\Orders\Items\Offer;
use RetailCrm\Api\Model\Request\ByAndSiteByRequest;
use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartClearRequest;
use RetailCrm\Api\Model\Request\CustomerInteraction\CustomerInteractionCartSetRequest;
use RetailCrm\TestUtils\Factory\TestClientFactory;
use RetailCrm\TestUtils\TestCase\AbstractApiResourceGroupTestCase;
class CustomerInteractionTest extends AbstractApiResourceGroupTestCase
{
public static function testCustomerInteractionCartClear(): void
{
$json = <<<'EOF'
{
"success": true
}
EOF;
$cart = new Cart();
$cart->clearedAt = new DateTime('now');
$cart->customer = new CartCustomer();
$cart->customer->id = 4770;
$cart->customer->browserId = 'browserId';
$cart->customer->gaClientId = 'gaClientId';
$request = new CustomerInteractionCartClearRequest();
$request->cart = $cart;
$request->siteBy = BySite::CODE;
$mock = static::createApiMockBuilder('customer-interaction/testSite/cart/clear');
$mock->matchMethod(RequestMethod::POST)
->matchBody(static::encodeForm($request))
->reply(200)
->withBody($json);
$client = TestClientFactory::createClient($mock->getClient());
$response = $client->customerInteraction->cartClear('testSite', $request);
self::assertModelEqualsToResponse($json, $response);
}
public static function testCustomerInteractionCartSet(): void
{
$json = <<<'EOF'
{
"success": true
}
EOF;
$customer = new CartCustomer();
$customer->id = 4770;
$cartItem = new CartItem();
$cartItem->price = 24.99;
$cartItem->quantity = 2;
$cartItem->offer = new Offer();
$cartItem->offer->externalId = '47701234567890';
$cart = new Cart();
$cart->items[] = $cartItem;
$cart->customer = $customer;
$request = new CustomerInteractionCartSetRequest();
$request->cart = $cart;
$request->siteBy = BySite::CODE;
$mock = static::createApiMockBuilder('customer-interaction/testSite/cart/set');
$mock->matchMethod(RequestMethod::POST)
->matchBody(static::encodeForm($request))
->reply(200)
->withBody($json);
$client = TestClientFactory::createClient($mock->getClient());
$response = $client->customerInteraction->cartSet('testSite', $request);
self::assertModelEqualsToResponse($json, $response);
}
public static function testCustomerInteractionCartGet(): void
{
$json = <<<'EOF'
{
"success": true,
"cart": {
"externalId": "12345678901234",
"droppedAt": "2024-05-08 15:10:30-05:00",
"link": "https:/shop.myshopify.com/recover?key=1234",
"items": [
{
"id": "1",
"offer": {
"displayName": "Some sample product",
"id": 11,
"externalId": "01234567890123",
"name": "Some sample product",
"vatRate": "20.00",
"properties": [],
"unit": {
"code": "pc",
"name": "Piece",
"sym": "pc"
}
},
"quantity": 2,
"price": 24.99
}
],
"currency": "EUR"
}
}
EOF;
$request = new ByAndSiteByRequest(ByIdentifier::ID, BySite::CODE);
$mock = static::createApiMockBuilder('customer-interaction/testSite/cart/4770');
$mock->matchMethod(RequestMethod::GET)
->matchQuery(static::encodeFormArray($request))
->reply(200)
->withBody($json);
$client = TestClientFactory::createClient($mock->getClient());
$response = $client->customerInteraction->cartGet('testSite', 4770, $request);
self::assertModelEqualsToResponse($json, $response);
}
}