WIP: Customer builder with corresponding test
This commit is contained in:
parent
ff71571e46
commit
bf9a552c11
15 changed files with 426 additions and 14 deletions
|
@ -15,7 +15,8 @@
|
|||
],
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*"
|
||||
"ext-mbstring": "*",
|
||||
"ext-tokenizer": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
30
intaro.retailcrm/lib/component/collectorcookieextractor.php
Normal file
30
intaro.retailcrm/lib/component/collectorcookieextractor.php
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* Является ли клиент контактным лицом корпоративного клиента
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
64
tests/lib/component/builder/api/CustomerBuilderTest.php
Normal file
64
tests/lib/component/builder/api/CustomerBuilderTest.php
Normal 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];
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue