1
0
Fork 0
mirror of synced 2025-04-20 01:21:01 +00:00

WIP: Customer builder with corresponding test

This commit is contained in:
Pavel 2020-07-29 18:03:10 +03:00
parent ff71571e46
commit bf9a552c11
15 changed files with 426 additions and 14 deletions

View file

@ -15,7 +15,8 @@
],
"require": {
"ext-json": "*",
"ext-mbstring": "*"
"ext-mbstring": "*",
"ext-tokenizer": "*"
},
"require-dev": {
"phpunit/phpunit": "^7",

View file

@ -78,7 +78,7 @@ class RetailCrmUser
return $customer;
}
public static function customerEdit($arFields, $api, $optionsSitesList = array()){
public static function customerEdit($arFields, $api, $optionsSitesList = array()) {
if (empty($arFields)) {
RCrmActions::eventLog('RetailCrmUser::customerEdit', 'empty($arFields)', 'incorrect customer');
return false;

View file

@ -29,6 +29,15 @@ class CorporateCustomerBuilder implements BuilderInterface
return $this;
}
/**
* @inheritDoc
*/
public function reset(): BuilderInterface
{
// TODO: Implement reset() method.
return $this;
}
/**
* @inheritDoc
*/
@ -36,4 +45,4 @@ class CorporateCustomerBuilder implements BuilderInterface
{
// TODO: Implement getResult() method.
}
}
}

View file

@ -11,6 +11,15 @@
*/
namespace Intaro\RetailCrm\Component\Builder\Api;
use Intaro\RetailCrm\Component\Builder\Exception\BuilderException;
use Intaro\RetailCrm\Component\CollectorCookieExtractor;
use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Component\Converter\DateTimeConverter;
use Intaro\RetailCrm\Model\Api\Address;
use Intaro\RetailCrm\Model\Api\Contragent;
use Intaro\RetailCrm\Model\Api\Customer;
use Intaro\RetailCrm\Model\Api\Phone;
use Intaro\RetailCrm\Model\Bitrix\User;
use Intaro\RetailCrm\Component\Builder\BuilderInterface;
/**
@ -20,20 +29,159 @@ use Intaro\RetailCrm\Component\Builder\BuilderInterface;
*/
class CustomerBuilder implements BuilderInterface
{
/** @var \Intaro\RetailCrm\Model\Bitrix\User $user */
private $user;
/** @var \Intaro\RetailCrm\Model\Api\Customer $customer */
private $customer;
/** @var string $personTypeId */
private $personTypeId;
/**
* @inheritDoc
*/
public function build(): BuilderInterface
{
// TODO: Implement build() method.
$contragentType = ConfigProvider::getContragentTypeForPersonType($this->personTypeId);
if (null === $contragentType) {
throw new BuilderException(sprintf(
'Cannot find corresponding contragent type for PERSON_TYPE_ID `%s`',
$this->personTypeId
));
}
$this->buildBase($contragentType);
$this->buildNames();
$this->buildPhones();
$this->buildAddress();
$this->buildDaemonCollectorId();
return $this;
}
/**
* Create base customer with initial data.
*
* @param string $contragentType
*/
protected function buildBase(string $contragentType): void
{
$this->customer = new Customer();
$this->customer->contragent = new Contragent();
$this->customer->contragent->contragentType = $contragentType;
$this->customer->externalId = $this->user->getId();
$this->customer->email = $this->user->getEmail();
$this->customer->createdAt = DateTimeConverter::bitrixToPhp($this->user->getDateRegister());
$this->customer->subscribed = false;
}
/**
* Build names.
*/
protected function buildNames(): void
{
$this->customer->firstName = $this->user->getName();
$this->customer->lastName = $this->user->getLastName();
$this->customer->patronymic = $this->user->getSecondName();
}
/**
* Build phones.
*/
protected function buildPhones(): void
{
$this->customer->phones = [];
if (!empty($this->user->getPersonalPhone())) {
$this->addPhone($this->user->getPersonalPhone());
}
if (!empty($this->user->getWorkPhone())) {
$this->addPhone($this->user->getWorkPhone());
}
}
/**
* Build address.
*/
protected function buildAddress(): void
{
$address = new Address();
if (!empty($this->user->getPersonalCity())) {
$address->city = $this->user->getPersonalCity();
}
if (!empty($this->user->getPersonalStreet())) {
$address->text = $this->user->getPersonalStreet();
}
if (!empty($this->user->getPersonalZip())) {
$address->index = $this->user->getPersonalZip();
}
$this->customer->address = $address;
}
/**
* Integrated Daemon Collector cookie (if it's present).
*/
protected function buildDaemonCollectorId(): void
{
if (CollectorCookieExtractor::extractCookie()) {
$this->customer->browserId = CollectorCookieExtractor::extractCookie();
}
}
/**
* @param string $number
*/
protected function addPhone(string $number): void
{
$phone = new Phone();
$phone->number = $number;
$this->customer->phones[] = $phone;
}
/**
* @inheritDoc
*/
public function reset(): BuilderInterface
{
$this->user = null;
$this->customer = null;
}
/**
* @inheritDoc
*/
public function getResult()
{
// TODO: Implement getResult() method.
return $this->customer;
}
/**
* @param \Intaro\RetailCrm\Model\Bitrix\User $user
*
* @return CustomerBuilder
*/
public function setUser(User $user): CustomerBuilder
{
$this->user = $user;
return $this;
}
/**
* @param string $personTypeId
*
* @return CustomerBuilder
*/
public function setPersonTypeId(string $personTypeId): CustomerBuilder
{
$this->personTypeId = $personTypeId;
return $this;
}
}

View file

@ -21,10 +21,18 @@ interface BuilderInterface
/**
* Builds result
*
* @return mixed
* @return \Intaro\RetailCrm\Component\Builder\BuilderInterface
* @throws \Intaro\RetailCrm\Component\Builder\Exception\BuilderException
*/
public function build(): BuilderInterface;
/**
* Resets builder
*
* @return \Intaro\RetailCrm\Component\Builder\BuilderInterface
*/
public function reset(): BuilderInterface;
/**
* Returns builder result
*

View file

@ -0,0 +1,21 @@
<?php
/**
* PHP version 7.1
*
* @category Integration
* @package Intaro\RetailCrm\Component\Builder\Exception
* @author retailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://retailcrm.ru/docs
*/
namespace Intaro\RetailCrm\Component\Builder\Exception;
/**
* Class BuilderException
*
* @package Intaro\RetailCrm\Component\Builder\Exception
*/
class BuilderException extends \Exception
{
}

View file

@ -0,0 +1,30 @@
<?php
/**
* PHP version 7.1
*
* @category Integration
* @package Intaro\RetailCrm\Component
* @author retailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://retailcrm.ru/docs
*/
namespace Intaro\RetailCrm\Component;
/**
* Class CollectorCookieExtractor
*
* @package Intaro\RetailCrm\Component
*/
class CollectorCookieExtractor
{
/**
* Extracts daemon collector cookie if it's present.
*
* @return string|null
*/
public static function extractCookie(): ?string
{
return (isset($_COOKIE['_rc']) && $_COOKIE['_rc'] != '') ? $_COOKIE['_rc'] : null;
}
}

View file

@ -305,6 +305,25 @@ class ConfigProvider
return static::$contragentTypes;
}
/**
* Returns contragent type for provided person type (PERSON_TYPE_ID in the Bitrix order).
* Returns null if nothing was found.
*
* @param string $personTypeId
*
* @return string|null
*/
public static function getContragentTypeForPersonType(string $personTypeId): ?string
{
$personTypes = static::getContragentTypes();
if (!empty($personTypes[$personTypeId])) {
return $personTypes[$personTypeId];
}
return null;
}
/**
* getCustomFields
*

View file

@ -0,0 +1,54 @@
<?php
/**
* PHP version 7.1
*
* @category Integration
* @package Intaro\RetailCrm\Component\Converter
* @author retailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://retailcrm.ru/docs
*/
namespace Intaro\RetailCrm\Component\Converter;
use Bitrix\Main\Type\DateTime as BitrixDateTime;
/**
* Class DateTimeConverter
*
* @package Intaro\RetailCrm\Component\Converter
*/
class DateTimeConverter
{
/**
* Intermediate format for converting Bitrix DateTime to PHP DateTime
*/
const INTERMEDIATE_FORMAT = 'U';
/**
* Converts Bitrix DateTime to php version
*
* @param \Bitrix\Main\Type\DateTime $dateTime
*
* @return \DateTime
*/
public static function bitrixToPhp(BitrixDateTime $dateTime): \DateTime
{
return \DateTime::createFromFormat(
static::INTERMEDIATE_FORMAT,
$dateTime->format(static::INTERMEDIATE_FORMAT)
);
}
/**
* Converts PHP DateTime to Bitrix version
*
* @param \DateTime $dateTime
*
* @return \Bitrix\Main\Type\DateTime
*/
public static function phpToBitrix(\DateTime $dateTime): BitrixDateTime
{
return BitrixDateTime::createFromPhp($dateTime);
}
}

View file

@ -31,7 +31,7 @@ class Deserializer
*
* @return mixed
*/
public static function deserialize(string $type, $json)
public static function deserialize(string $json, string $type)
{
$result = json_decode($json, true);
@ -39,7 +39,7 @@ class Deserializer
throw new InvalidJsonException(json_last_error_msg(), json_last_error());
}
return static::deserializeArray($type, $result);
return static::deserializeArray($result, $type);
}
/**
@ -48,7 +48,7 @@ class Deserializer
*
* @return mixed
*/
public static function deserializeArray(string $type, array $value)
public static function deserializeArray(array $value, string $type)
{
$result = StrategyFactory::deserializeStrategyByType($type)->deserialize($type, $value);

View file

@ -63,13 +63,33 @@ class Customer extends AbstractApiModel
/**
* Контактное лицо корпоративного клиента является основным
*
* @var string $isMain
* @var bool $isMain
*
* @Mapping\Type("boolean")
* @Mapping\SerializedName("isMain")
*/
public $isMain;
/**
* Индикатор подписки на рассылку
*
* @var bool $subscribed
*
* @Mapping\Type("boolean")
* @Mapping\SerializedName("subscribed")
*/
public $subscribed;
/**
* Кука Daemon Collector
*
* @var bool $browserId
*
* @Mapping\Type("string")
* @Mapping\SerializedName("browserId")
*/
public $browserId;
/**
* Является ли клиент контактным лицом корпоративного клиента
*

View file

@ -72,7 +72,7 @@ use Bitrix\Main\ORM\Data\Result;
* @method string sysMethodToFieldCase($methodName)
* @method string sysFieldToMethodCase($fieldName)
*/
class AbstractModelProxy implements \ArrayAccess
abstract class AbstractModelProxy implements \ArrayAccess
{
/** @var \Bitrix\Main\ORM\Objectify\EntityObject */
protected $entity;
@ -80,11 +80,11 @@ class AbstractModelProxy implements \ArrayAccess
/**
* AbstractModelProxy constructor.
*
* @param \Bitrix\Main\ORM\Objectify\EntityObject $entity
* @param \Bitrix\Main\ORM\Objectify\EntityObject|null $entity
*/
public function __construct(EntityObject $entity)
public function __construct($entity = null)
{
$this->entity = $entity;
$this->entity = $entity instanceof EntityObject ? $entity : static::createNewEntityObject();
}
/**
@ -219,4 +219,20 @@ class AbstractModelProxy implements \ArrayAccess
throw new \RuntimeException('Cannot find method "' . $name . '"');
}
/**
* @return \Bitrix\Main\ORM\Objectify\EntityObject
*/
protected static function createNewEntityObject(): EntityObject
{
$object = static::newObject();
if ($object instanceof EntityObject) {
return $object;
}
throw new \RuntimeException('Cannot create correspondent EntityObject');
}
abstract protected static function newObject(): ?EntityObject;
}

View file

@ -11,7 +11,9 @@
*/
namespace Intaro\RetailCrm\Model\Bitrix;
use Bitrix\Main\ORM\Objectify\EntityObject;
use Bitrix\Main\Type\DateTime;
use Bitrix\Sale\FuserTable;
/**
* Class Fuser
@ -33,4 +35,13 @@ use Bitrix\Main\Type\DateTime;
*/
class Fuser extends AbstractModelProxy
{
/**
* @return \Bitrix\Main\ORM\Objectify\EntityObject|null
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\SystemException
*/
protected static function newObject(): ?EntityObject
{
return FuserTable::createObject();
}
}

View file

@ -11,7 +11,9 @@
*/
namespace Intaro\RetailCrm\Model\Bitrix;
use Bitrix\Main\ORM\Objectify\EntityObject;
use Bitrix\Main\Type\DateTime;
use Bitrix\Main\UserTable;
/**
* Class User
@ -143,4 +145,13 @@ use Bitrix\Main\Type\DateTime;
*/
class User extends AbstractModelProxy
{
/**
* @return \Bitrix\Main\ORM\Objectify\EntityObject|null
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\SystemException
*/
protected static function newObject(): ?EntityObject
{
return UserTable::createObject();
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Tests\Intaro\RetailCrm\Component\Builder\Api;
use Bitrix\Main\Type\DateTime;
use Intaro\RetailCrm\Component\Builder\Api\CustomerBuilder;
use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Model\Api\Customer;
use Intaro\RetailCrm\Model\Bitrix\User;
use PHPUnit\Framework\TestCase;
class CustomerBuilderTest extends TestCase
{
protected function setUp(): void
{
$class = new \ReflectionClass(ConfigProvider::class);
$property = $class->getProperty('contragentTypes');
$property->setAccessible(true);
$property->setValue([
'individual' => 'individual'
]);
}
/**
* @throws \Intaro\RetailCrm\Component\Builder\Exception\BuilderException
* @var User $entity
* @dataProvider userData
*/
public function testBuild($entity): void
{
$this->assertTrue($entity instanceof User);
$builder = new CustomerBuilder();
$result = $builder
->setPersonTypeId('individual')
->setUser($entity)
->build()
->getResult();
$this->assertTrue($result instanceof Customer);
$this->assertEquals($entity->getId(), $result->externalId);
}
/**
* @return \Intaro\RetailCrm\Model\Bitrix\User[]
*/
public function userData()
{
$entity = new User();
$entity->setId(21);
$entity->setEmail('vovka@narod.ru');
$entity->setDateRegister(DateTime::createFromPhp(new \DateTime()));
$entity->setName('First');
$entity->setLastName('Last');
$entity->setSecondName('Second');
$entity->setPersonalPhone('88005553535');
$entity->setWorkPhone('88005553536');
$entity->setPersonalCity('city');
$entity->setPersonalStreet('street');
$entity->setPersonalZip('344000');
return [$entity];
}
}