diff --git a/.travis.yml b/.travis.yml
index 2cff9d1..b90be43 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,9 @@ before_script:
- composer install $flags
script:
- - php vendor/bin/php-cs-fixer fix --diff --dry-run --using-cache no --config .php_cs
+ - php vendor/bin/psalm
+ - php vendor/bin/php-cs-fixer fix --diff --dry-run --using-cache=no --config=.php_cs
+ - php vendor/bin/phpunit -c phpunit.xml
after_success:
- - bash <(curl -s https://codecov.io/bash)
\ No newline at end of file
+ - bash <(curl -s https://codecov.io/bash)
diff --git a/Command/StatusesCommand.php b/Command/StatusesCommand.php
deleted file mode 100644
index 3168b18..0000000
--- a/Command/StatusesCommand.php
+++ /dev/null
@@ -1,99 +0,0 @@
-setName('statuses:update')
- ->setDescription('Update statuses')
- ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all');
- }
-
- public function __construct(ModuleManagerInterface $moduleManager, AccountManager $accountManager)
- {
- $this->moduleManager = $moduleManager;
- $this->accountManager = $accountManager;
-
- parent::__construct();
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if (!$this->lock()) {
- $output->writeln('The command is already running in another process.');
-
- return 0;
- }
-
- $accountId = $input->getArgument('accountId')
- ? (int) $input->getArgument('accountId')
- : null;
-
- $paginator = [];
- if (null !== $accountId) {
- $paginator = [$this->accountManager - find($accountId)];
- } else {
- $accountQuery = $this->accountManager->getRepository()
- ->createQueryBuilder('account')
- ->where('account.active = true')
- ->andWhere('account.freeze != true')
- ->addOrderBy('account.id')
- ->getQuery()
- ->setFirstResult(0)
- ->setMaxResults(100);
- $paginator = new Paginator($accountQuery);
- }
-
- $count = 0;
- foreach ($paginator as $account) {
- try {
- $count += $this->moduleManager
- ->setAccount($account)
- ->updateStatuses()
- ;
- } catch (AbstractModuleException $e) {
- $output->writeln(
- "Failed to update statuses for account {$account->getCrmUrl()}[{$account->getId()}]"
- );
- $output->writeln("Error: {$e->getMessage()}");
- }
- }
-
- $output->writeln("{$count} statuses updated.");
-
- $this->release();
-
- return 0;
- }
-}
diff --git a/Command/UpdateModuleCommand.php b/Command/UpdateModuleCommand.php
deleted file mode 100644
index a5e6632..0000000
--- a/Command/UpdateModuleCommand.php
+++ /dev/null
@@ -1,99 +0,0 @@
-setName('module:update')
- ->setDescription('Update module')
- ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all');
- }
-
- public function __construct(ModuleManagerInterface $moduleManager, AccountManager $accountManager)
- {
- $this->moduleManager = $moduleManager;
- $this->accountManager = $accountManager;
-
- parent::__construct();
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if (!$this->lock()) {
- $output->writeln('The command is already running in another process.');
-
- return 0;
- }
-
- $accountId = $input->getArgument('accountId')
- ? $input->getArgument('accountId')
- : null;
-
- $paginator = [];
- if (null !== $accountId) {
- $paginator = [$this->accountManager->find($accountId)];
- } else {
- $accountQuery = $this->accountManager->getRepository()
- ->createQueryBuilder('account')
- ->where('account.active = true')
- ->andWhere('account.freeze != true')
- ->addOrderBy('account.id')
- ->getQuery()
- ->setFirstResult(0)
- ->setMaxResults(100);
- $paginator = new Paginator($accountQuery);
- }
-
- $count = 0;
- foreach ($paginator as $account) {
- try {
- $this->moduleManager
- ->setAccount($account)
- ->updateModuleConfiguration()
- ;
- ++$count;
- } catch (\Exception $e) {
- $output->writeln(
- "Failed to update configuration for account {$account->getCrmUrl()}[{$account->getId()}]"
- );
- $output->writeln("Error: {$e->getMessage()}");
- }
- }
-
- $output->writeln("{$count} modules updated.");
-
- $this->release();
-
- return 0;
- }
-}
diff --git a/Controller/ApiController.php b/Controller/ApiController.php
deleted file mode 100644
index 86d6121..0000000
--- a/Controller/ApiController.php
+++ /dev/null
@@ -1,462 +0,0 @@
-jmsSerializer = $jmsSerializer;
- $this->moduleManager = $moduleManager;
- $this->accountManager = $accountManager;
- $this->deliveryOrderManager = $deliveryOrderManager;
- }
-
- public function activity(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('activity'))) {
- return $this->getInvalidResponse('Parameter "activity" must be json', 400);
- }
- $activity = $request->request->get('activity');
-
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $activity,
- IntegrationModule::class,
- 'json',
- DeserializationContext::create()->setGroups(['activity'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- $this->moduleManager->getAccount()->setActive($requestModel->active);
- $this->moduleManager->getAccount()->setFreeze($requestModel->freeze);
-
- $systemUrl = $request->request->get('systemUrl');
- $this->moduleManager->getAccount()->setCrmUrl($systemUrl);
-
- $this->accountManager->flush();
-
- return $this->getSucessfullResponse();
- }
-
- public function calculate(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('calculate'))) {
- return $this->getInvalidResponse('Parameter "calculate" must be json', 400);
- }
- $requestData = $request->request->get('calculate');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestCalculate::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- try {
- $responseModel = $this->doCalculate($requestModel);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- $response = new ResponseCalculateSuccessful($responseModel);
- $response->result = $responseModel;
-
- return $this->getSucessfullResponse($response);
- }
-
- public function save(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('save'))) {
- return $this->getInvalidResponse('Parameter "save" must be json', 400);
- }
- $requestData = $request->request->get('save');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestSave::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
- if (null === $requestModel->delivery) {
- return $this->getInvalidResponse('Invalid request format', 400);
- }
-
- $delivery = $this->deliveryOrderManager->findOneBy([
- 'account' => $this->moduleManager->getAccount(),
- 'orderId' => $requestModel->order,
- ]);
-
- // ищем доставки, созданные без заказа в запросе get
- if (null === $delivery) {
- $delivery = $this->deliveryOrderManager
- ->findOneBy([
- 'account' => $this->moduleManager->getAccount(),
- 'externalId' => $requestModel->deliveryId,
- ]);
- }
-
- try {
- $responseModel = $this->doSave($requestModel, $delivery);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- if (null === $delivery) {
- $delivery = $this->deliveryOrderManager->create();
- }
-
- $delivery
- ->setAccount($this->moduleManager->getAccount())
- ->setOrderId($requestModel->order)
- ->setExternalId($responseModel->deliveryId)
- ;
- if ($responseModel->trackNumber) {
- $delivery->setTrackNumber($responseModel->trackNumber);
- }
-
- if (is_array($responseModel->additionalData)) {
- foreach ($responseModel->additionalData as $key => $value) {
- $setter = 'set' . ucfirst($key);
- if (is_callable([$delivery, $setter])) {
- $delivery->$setter($value);
- }
- }
- }
-
- if (empty($delivery->getId())) {
- $this->deliveryOrderManager->persist($delivery);
- }
- $this->deliveryOrderManager->flush();
-
- return $this->getSucessfullResponse($responseModel);
- }
-
- public function getDeliveryOrder(Request $request): JsonResponse
- {
- $externalId = $request->query->get('deliveryId');
- if (null === $externalId || empty($externalId)) {
- return $this->getInvalidResponse('DeliveryId is required', 400);
- }
-
- try {
- $responseModel = $this->doGet($externalId);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- return $this->getSucessfullResponse($responseModel);
- }
-
- public function delete(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('delete'))) {
- return $this->getInvalidResponse('Parameter "delete" must be json', 400);
- }
- $requestData = $request->request->get('delete');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestDelete::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- $delivery = $this->deliveryOrderManager->findOneBy([
- 'account' => $this->moduleManager->getAccount(),
- 'externalId' => $requestModel->deliveryId,
- ]);
-
- if (null === $delivery) {
- return $this->getInvalidResponse("Delivery '{$requestModel->deliveryId}' not found", 404);
- }
-
- try {
- $this->doDelete($requestModel, $delivery);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- $this->deliveryOrderManager->remove($delivery);
- $this->deliveryOrderManager->flush();
-
- return $this->getSucessfullResponse();
- }
-
- public function shipmentPointList(Request $request): JsonResponse
- {
- $requestData = json_encode($request->query->all());
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestShipmentPointList::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- try {
- $responseModel = $this->doShipmentPointList($requestModel);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- $response = new ResponseShipmentPointListSuccessful($responseModel);
- $response->result = $responseModel;
-
- return $this->getSucessfullResponse($response);
- }
-
- public function print(Request $request): Response
- {
- if (!is_string($request->request->get('print'))) {
- return $this->getInvalidResponse('Parameter "print" must be json', 400);
- }
- $requestData = $request->request->get('print');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestPrint::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- try {
- $plateData = $this->doPrint($requestModel);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\NotFoundException $e) {
- return $this->getInvalidResponse($e->getMessage(), 404);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- if (count($plateData) > 1) {
- $tmpFilename = tempnam(sys_get_temp_dir(), 'zip');
- $labelArchive = new \ZipArchive();
- $labelArchive->open($tmpFilename, \ZipArchive::CREATE);
- foreach ($plateData as $fileName => $plate) {
- $labelArchive->addFromString($fileName, $plate);
- }
- $labelArchive->close();
- $contents = file_get_contents($tmpFilename);
- unlink($tmpFilename);
-
- $response = new Response($contents);
- $response->headers->set('Content-Type', 'application/zip');
- } else {
- $response = new Response(reset($plateData));
- $response->headers->set('Content-Type', 'application/pdf');
- }
-
- return $response;
- }
-
- public function shipmentSave(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('shipmentSave'))) {
- return $this->getInvalidResponse('Parameter "shipmentSave" must be json', 400);
- }
- $requestData = $request->request->get('shipmentSave');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestShipmentSave::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- try {
- $responseModel = $this->doShipmentSave($requestModel);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- return $this->getSucessfullResponse($responseModel);
- }
-
- public function shipmentDelete(Request $request): JsonResponse
- {
- if (!is_string($request->request->get('shipmentDelete'))) {
- return $this->getInvalidResponse('Parameter "shipmentDelete" must be json', 400);
- }
- $requestData = $request->request->get('shipmentDelete');
- try {
- $requestModel = $this->jmsSerializer->deserialize(
- $requestData,
- RequestShipmentDelete::class,
- 'json',
- DeserializationContext::create()->setGroups(['get', 'request'])
- );
- } catch (JmsException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- try {
- $this->doShipmentDelete($requestModel);
- } catch (Exception\ServerUnreachableException $e) {
- return $this->getInvalidResponse($e->getMessage(), 521);
- } catch (Exception\AbstractModuleException $e) {
- return $this->getInvalidResponse($e->getMessage(), 400);
- }
-
- return $this->getSucessfullResponse();
- }
-
- protected function getSucessfullResponse(object $responseResult = null): JsonResponse
- {
- if (!$responseResult instanceof AbstractResponseSuccessful) {
- $response = new ResponseSuccessful();
- $response->result = $responseResult;
- } else {
- $response = $responseResult;
- }
-
- $responseData = $this->jmsSerializer
- ->serialize($response, 'json', SerializationContext::create()->setGroups(['response']));
-
- return new JsonResponse(json_decode($responseData, true));
- }
-
- protected function getInvalidResponse(string $message, int $statusCode): JsonResponse
- {
- if ($statusCode >= 500) {
- //корректно отдается в crm только в окружении prod
- throw new SymfonyException\HttpException($statusCode, json_encode(['success' => false, 'errorMsg' => $message]));
- }
-
- return new JsonResponse([
- 'success' => false,
- 'errorMsg' => $message,
- ], $statusCode);
- }
-
- protected function doCalculate(RequestCalculate $requestModel): array
- {
- return $this->moduleManager->calculateDelivery($requestModel);
- }
-
- protected function doGet(string $externalId): ResponseLoadDeliveryData
- {
- return $this->moduleManager->getDelivery($externalId);
- }
-
- protected function doSave(RequestSave $requestModel, DeliveryOrder $delivery = null): ResponseSave
- {
- return $this->moduleManager->saveDelivery($requestModel, $delivery);
- }
-
- protected function doDelete(RequestDelete $requestModel, DeliveryOrder $delivery): bool
- {
- return $this->moduleManager->deleteDelivery($requestModel, $delivery);
- }
-
- protected function doShipmentPointList(RequestShipmentPointList $requestModel): array
- {
- return $this->moduleManager->shipmentPointList($requestModel);
- }
-
- protected function doShipmentSave(RequestShipmentSave $requestModel): ResponseShipmentSave
- {
- return $this->moduleManager->saveShipment($requestModel);
- }
-
- protected function doShipmentDelete(RequestShipmentDelete $requestModel): bool
- {
- return $this->moduleManager->deleteShipment($requestModel);
- }
-
- protected function doPrint(RequestPrint $requestModel)
- {
- return $this->moduleManager->printDocument($requestModel);
- }
-}
diff --git a/Controller/ClientIdSecuredControllerInterface.php b/Controller/ClientIdSecuredControllerInterface.php
deleted file mode 100644
index 6f7b89d..0000000
--- a/Controller/ClientIdSecuredControllerInterface.php
+++ /dev/null
@@ -1,7 +0,0 @@
-getRootNode();
-
- $rootNode
- ->children()
- ->scalarNode('module_manager_class')
- ->cannotBeEmpty()
- ->end()
- ->scalarNode('account_class')
- ->isRequired()
- ->cannotBeEmpty()
- ->end()
- ->scalarNode('delivery_order_class')
- ->isRequired()
- ->cannotBeEmpty()
- ->end()
-
- ->arrayNode('configuration')
- ->children()
- ->scalarNode('integration_code')
- ->cannotBeEmpty()
- ->end()
-
- ->arrayNode('countries')
- ->prototype('scalar')->end()
- ->requiresAtLeastOneElement()
- ->defaultValue(['ru'])
- ->end()
-
- ->arrayNode('locales')
- ->requiresAtLeastOneElement()
- ->useAttributeAsKey('locale')
-
- ->arrayPrototype()
- ->children()
- ->scalarNode('name')
- ->isRequired()
- ->end()
- ->scalarNode('logo')
- ->isRequired()
- ->end()
- ->end()
- ->end()
- ->end()
-
- ->variableNode('parameters')->end()
- ->end()
- ->end()
- ->end()
- ;
-
- return $treeBuilder;
- }
-}
diff --git a/DependencyInjection/RetailCrmDeliveryModuleExtension.php b/DependencyInjection/RetailCrmDeliveryModuleExtension.php
deleted file mode 100644
index f3a76a9..0000000
--- a/DependencyInjection/RetailCrmDeliveryModuleExtension.php
+++ /dev/null
@@ -1,75 +0,0 @@
-load('services.yaml');
-
- $configuration = new Configuration();
- $config = $this->processConfiguration($configuration, $configs);
-
- $container->setParameter(
- 'retailcrm.delivery_module.configuration',
- $config['configuration']
- );
-
- $moduleManagerClass = $config['module_manager_class'];
- if (!class_exists($moduleManagerClass)) {
- throw new \InvalidArgumentException("module_manager_class '{$moduleManagerClass}' does not exists");
- }
- if (!is_subclass_of($moduleManagerClass, ModuleManagerInterface::class)) {
- throw new \InvalidArgumentException("module_manager_class '{$moduleManagerClass}' must implement ModuleManagerInterace");
- }
- $container->setParameter(
- 'retailcrm.delivery_module.module_manager.class',
- $moduleManagerClass
- );
-
- $accountClass = $config['account_class'];
- if (!class_exists($accountClass)) {
- throw new \InvalidArgumentException("account_class'] '{$accountClass}' does not exists");
- }
- if (!is_subclass_of($accountClass, Account::class)) {
- throw new \InvalidArgumentException("account_class '{$accountClass}' must extend " . Account::class);
- }
- $container->setParameter(
- 'retailcrm.delivery_module.account.class',
- $accountClass
- );
-
- $deliveryOrderClass = $config['delivery_order_class'];
- if (!class_exists($deliveryOrderClass)) {
- throw new \InvalidArgumentException("delivery_order_class'] '{$deliveryOrderClass}' does not exists");
- }
- if (!is_subclass_of($deliveryOrderClass, DeliveryOrder::class)) {
- throw new \InvalidArgumentException("delivery_order_class '{$deliveryOrderClass}' must extend " . DeliveryOrder::class);
- }
- $container->setParameter(
- 'retailcrm.delivery_module.delivery_order.class',
- $config['delivery_order_class']
- );
- }
-}
diff --git a/EventSubscriber/ClientIdSubscriber.php b/EventSubscriber/ClientIdSubscriber.php
deleted file mode 100644
index 47193e7..0000000
--- a/EventSubscriber/ClientIdSubscriber.php
+++ /dev/null
@@ -1,72 +0,0 @@
-accountManager = $accountManager;
- $this->moduleManager = $moduleManager;
- }
-
- public static function getSubscribedEvents()
- {
- return [
- KernelEvents::CONTROLLER => 'onKernelController',
- ];
- }
-
- public function onKernelController(ControllerEvent $event)
- {
- $controller = $event->getController();
- if (is_array($controller)) {
- $controller = $controller[0];
- }
-
- if (!$controller instanceof ClientIdSecuredControllerInterface) {
- return;
- }
-
- $request = $event->getRequest();
-
- if ($request->isMethod('post')) {
- $clientId = $request->request->get('clientId');
- } else {
- $clientId = $request->query->get('clientId');
- }
- if (empty($clientId)) {
- throw new AccessDeniedHttpException('ClientId required');
- }
-
- if (!Uuid::isValid($clientId)) {
- throw new AccessDeniedHttpException('ClientId is not valid');
- }
-
- $account = $this->accountManager->findOneBy(['clientId' => $clientId]);
- if (null === $account) {
- throw new AccessDeniedHttpException('ClientId not found');
- }
-
- $this->moduleManager->setAccount($account);
- }
-}
diff --git a/EventSubscriber/SerializeListener.php b/EventSubscriber/SerializeListener.php
deleted file mode 100644
index 9473dfc..0000000
--- a/EventSubscriber/SerializeListener.php
+++ /dev/null
@@ -1,27 +0,0 @@
- Events::PRE_SERIALIZE, 'method' => 'onPreSerialize', 'class' => ResponseResult::class],
- ];
- }
-
- public function onPreSerialize(PreSerializeEvent $event)
- {
- if (is_object($event->getObject())) {
- $event->setType(get_class($event->getObject()));
- } else {
- $event->setType('string');
- }
- }
-}
diff --git a/Exception/AbstractModuleException.php b/Exception/AbstractModuleException.php
deleted file mode 100644
index 6366946..0000000
--- a/Exception/AbstractModuleException.php
+++ /dev/null
@@ -1,7 +0,0 @@
-")
- */
- public $actions;
-
- /**
- * Допустивые типы плательщиков за доставку.
- *
- * @var array
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("payerType")
- * @Serializer\Type("array")
- */
- public $payerType;
-
- /**
- * Максимальное количество заказов при печати документов.
- *
- * @var int
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("platePrintLimit")
- * @Serializer\Type("integer")
- */
- public $platePrintLimit = 100;
-
- /**
- * В методе calculate расчитывается стоимость доставки.
- *
- * @var bool
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("rateDeliveryCost")
- * @Serializer\Type("boolean")
- */
- public $rateDeliveryCost = true;
-
- /**
- * Разрешить использование упаковок.
- *
- * @var bool
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("allowPackages")
- * @Serializer\Type("boolean")
- */
- public $allowPackages = false;
-
- /**
- * Доставка наложенным платежом доступна/не доступна.
- *
- * @var bool
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("codAvailable")
- * @Serializer\Type("boolean")
- */
- public $codAvailable = false;
-
- /**
- * Возможен самопривоз на терминал.
- *
- * @var bool
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("selfShipmentAvailable")
- * @Serializer\Type("boolean")
- */
- public $selfShipmentAvailable = false;
-
- /**
- * Возможность работы с заказом, содержащим несколько позиций с одинаковым торговым предложением
- *
- * @var bool
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("duplicateOrderProductSupported")
- * @Serializer\Type("boolean")
- */
- public $duplicateOrderProductSupported = true;
-
- /**
- * Разрешить отдельно передавать трек номер
- *
- * @var string
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("allowTrackNumber")
- * @Serializer\Type("boolean")
- */
- public $allowTrackNumber;
-
- /**
- * Список стран откуда можно отправить посылку. Если массив пустой, то нет ограничения на страны.
- *
- * @var array
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("availableCountries")
- * @Serializer\Type("array")
- */
- public $availableCountries;
-
- /**
- * Список обязательных полей заказа.
- *
- * @var array
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("requiredFields")
- * @Serializer\Type("array")
- */
- public $requiredFields;
-
- /**
- * Список статусов службы доставки.
- *
- * @var Status[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("statusList")
- * @Serializer\Type("array")
- */
- public $statusList;
-
- /**
- * Список печатных форм, предоставляемых службой.
- *
- * @var Plate[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("plateList")
- * @Serializer\Type("array")
- */
- public $plateList;
-
- /**
- * Список дополнительных полей, необходимых для оформления доставки.
- *
- * @var DeliveryDataField[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("deliveryDataFieldList")
- * @Serializer\Type("array")
- */
- public $deliveryDataFieldList;
-
- /**
- * Список дополнительных полей, необходимых для заявки на отгрузку.
- *
- * @var DeliveryDataField[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("shipmentDataFieldList")
- * @Serializer\Type("array")
- */
- public $shipmentDataFieldList;
-
- /**
- * Массив настроек модуля
- *
- * @var Settings
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("settings")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Settings")
- */
- public $settings;
-}
diff --git a/Model/Contragent.php b/Model/Contragent.php
deleted file mode 100644
index 26a4e21..0000000
--- a/Model/Contragent.php
+++ /dev/null
@@ -1,68 +0,0 @@
-")
- */
- public $phones;
-
- /**
- * E-mail.
- *
- * @var string
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("email")
- * @Serializer\Type("string")
- */
- public $email;
-
- /**
- * Данные контрагента.
- *
- * @var Contragent
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("contragent")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Model\Contragent")
- */
- public $contragent;
-
- public function getNickName(): ?string
- {
- $result = trim(
- $this->lastName . ' ' . $this->firstName . ' ' . $this->patronymic
- );
-
- return $result;
- }
-}
diff --git a/Model/DeliveryAddress.php b/Model/DeliveryAddress.php
deleted file mode 100644
index 8006880..0000000
--- a/Model/DeliveryAddress.php
+++ /dev/null
@@ -1,250 +0,0 @@
-")
- * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"})
- * @Serializer\Accessor(getter="getFrom", setter="setFrom")
- *
- * @var \DateTime|null
- */
- protected $from;
-
- /**
- * Время доставки "до"
- *
- * @Serializer\SerializedName("to")
- * @Serializer\Type("DateTime<'H:i'>")
- * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"})
- * @Serializer\Accessor(getter="getTo", setter="setTo")
- *
- * @var \DateTime|null
- */
- protected $to;
-
- /**
- * Время доставки (произвольный текст)
- *
- * @Serializer\SerializedName("custom")
- * @Serializer\Type("string")
- * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"})
- *
- * @var string|null
- */
- protected $custom;
-
- /**
- * @param string|\DateTime|null $from
- * @param string|\DateTime|null $to
- * @param string|null $custom
- *
- * @return self
- */
- public function __construct($from = null, $to = null, $custom = null)
- {
- $this->setFrom($from);
- $this->setTo($to);
- $this->setCustom($custom);
- }
-
- /**
- * Разбор строки со временем доставки
- *
- * @param string $time
- *
- * @return self
- */
- public static function fromString($time)
- {
- $result = new self();
- $result->setString($time);
-
- return $result;
- }
-
- /**
- * @return \DateTime|null
- */
- public function getFrom()
- {
- if ($this->from) {
- $this->from->setDate(1970, 01, 01);
-
- if ('00:00:00' === $this->from->format('H:i:s')) {
- return null;
- }
- }
-
- return $this->from;
- }
-
- /**
- * @param \DateTime|string|null $from
- *
- * @return $this
- */
- public function setFrom($from)
- {
- $this->from = $this->ensureTime($from);
- $this->ensureConsistency();
-
- return $this;
- }
-
- /**
- * @return \DateTime|null
- */
- public function getTo()
- {
- if ($this->to) {
- $this->to->setDate(1970, 01, 01);
-
- if ('23:59:59' === $this->to->format('H:i:s')) {
- return null;
- }
- }
-
- return $this->to;
- }
-
- /**
- * @param \DateTime|string|null $to
- *
- * @return $this
- */
- public function setTo($to)
- {
- $this->to = $this->ensureTime($to);
- $this->ensureConsistency();
-
- return $this;
- }
-
- /**
- * @return string
- */
- public function getCustom()
- {
- return $this->custom;
- }
-
- /**
- * @param string $custom
- *
- * @return $this
- */
- public function setCustom($custom)
- {
- $this->custom = $custom;
-
- return $this;
- }
-
- /**
- * @param string $time
- *
- * @return $this
- */
- public function setString($time)
- {
- // точное время: 12.30, 12:30
- $exactPattern = '/^в?\s*(\d{2}[:\.]\d{2})$/u';
- // диапазон времени: 12-13, c 12.00 по 13:00
- $rangePattern = '/^с?\s*(?P\d{2}[:\.]?\d{0,2})\s*(-|по|до)\s*(?P\d{2}[:\.]?\d{0,2})/u';
- // диапазон времени: c 12.00
- $rangeFromPattern = '/^с?\s*(?P\d{2}[:\.]?\d{0,2})/u';
- // диапазон времени: до 13:00
- $rangeToPattern = '/^(-|по|до)\s*(?P\d{2}[:\.]?\d{0,2})/u';
-
- if (preg_match($exactPattern, $time, $matches)) {
- $timeObj = new \DateTime($matches[1]);
- $this->setFrom(clone $timeObj);
- $this->setTo(clone $timeObj);
- } elseif (preg_match($rangePattern, $time, $matches)) {
- $from = $matches['from'];
- $to = $matches['to'];
-
- $from = preg_match($exactPattern, $from) ? $from : $from . ':00';
- $to = preg_match($exactPattern, $to) ? $to : $to . ':00';
-
- try {
- $this->setFrom(new \DateTime($from));
- $this->setTo(new \DateTime($to));
- } catch (\Exception $e) {
- $this->setFrom(null);
- $this->setTo(null);
- $this->setCustom($time);
- }
- } elseif (preg_match($rangeFromPattern, $time, $matches)) {
- $from = $matches['from'];
- $from = preg_match($exactPattern, $from) ? $from : $from . ':00';
-
- try {
- $this->setFrom(new \DateTime($from));
- $this->setTo(null);
- } catch (\Exception $e) {
- $this->setFrom(null);
- $this->setTo(null);
- $this->setCustom($time);
- }
- } elseif (preg_match($rangeToPattern, $time, $matches)) {
- $to = $matches['to'];
- $to = preg_match($exactPattern, $to) ? $to : $to . ':00';
-
- try {
- $this->setFrom(null);
- $this->setTo(new \DateTime($to));
- } catch (\Exception $e) {
- $this->setFrom(null);
- $this->setTo(null);
- $this->setCustom($time);
- }
- } else {
- $this->setFrom(null);
- $this->setTo(null);
- $this->setCustom($time);
- }
-
- return $this;
- }
-
- /**
- * @return string
- */
- public function getString()
- {
- $from = $this->getFrom();
- $to = $this->getTo();
- $custom = $this->getCustom();
-
- if (!($from || $to)) {
- return (string) $custom;
- }
-
- $fromPrint = $from ? $from->format('H:i') : null;
- $toPrint = $to ? $to->format('H:i') : null;
-
- if ($fromPrint && $fromPrint === $toPrint) {
- return 'в ' . $fromPrint;
- }
-
- $str = '';
- if ($fromPrint) {
- $str .= 'с ' . $fromPrint;
- }
- if ($toPrint) {
- $str .= ' до ' . $toPrint;
- }
-
- return trim($str);
- }
-
- /**
- * Проверяет, соответствует ли время доставки диапазону из настроек
- *
- * @return bool
- */
- public function equalsRange(array $range)
- {
- $fromEquals = false;
- $toEquals = false;
-
- $from = $this->getFrom();
- $to = $this->getTo();
-
- if ($from) {
- if (isset($range['from'])) {
- $fromEquals = $from->format('H:i') === $range['from'];
- }
- } else {
- if (!isset($range['from']) ||
- !$range['from'] ||
- '00:00' === $range['from'] ||
- '00:00:00' === $range['from']
- ) {
- $fromEquals = true;
- }
- }
-
- if ($to) {
- if (isset($range['to'])) {
- $toEquals = $to->format('H:i') === $range['to'];
- }
- } else {
- if (!isset($range['to']) ||
- !$range['to'] ||
- '23:59' === $range['from'] ||
- '23:59:59' === $range['from']
- ) {
- $toEquals = true;
- }
- }
-
- return $fromEquals && $toEquals;
- }
-
- /**
- * @return bool
- */
- public function isEmpty()
- {
- return !($this->from || $this->to || $this->custom);
- }
-
- /**
- * @return string
- */
- public function __toString()
- {
- return $this->getString();
- }
-
- protected function ensureTime($time)
- {
- if ($time) {
- if (!$time instanceof \DateTime) {
- $time = new \DateTime((string) $time);
- }
- $time->setDate(1970, 01, 01);
- }
-
- return $time;
- }
-
- /**
- * Если для времени доставки указана только одна граница диапазона, то присвоим другой значение по умолчанию
- */
- protected function ensureConsistency()
- {
- $from = $this->getFrom();
- $to = $this->getTo();
-
- if (null === $from && null !== $to) {
- $this->from = new \DateTime('1970-01-01T00:00:00');
- } elseif (null === $to && null !== $from) {
- $this->to = new \DateTime('1970-01-01T23:59:59');
- } elseif (null === $to && null === $from) {
- $this->to = null;
- $this->from = null;
- }
- }
-}
diff --git a/Model/Entity/Account.php b/Model/Entity/Account.php
deleted file mode 100644
index c3d6e4d..0000000
--- a/Model/Entity/Account.php
+++ /dev/null
@@ -1,165 +0,0 @@
-")
- */
- protected $createdAt;
-
- /**
- * @var string
- *
- * @Serializer\Groups({"get", "connect"})
- * @Serializer\Type("string")
- */
- protected $crmUrl;
-
- /**
- * @var string
- *
- * @Serializer\Groups({"get", "connect"})
- * @Serializer\Type("string")
- */
- protected $crmApiKey;
-
- /**
- * @var bool
- */
- protected $active;
-
- /**
- * @var bool
- */
- protected $freeze;
-
- /**
- * @var string
- */
- protected $language;
-
- public function __construct()
- {
- $this->clientId = Uuid::uuid4();
- $this->createdAt = new \DateTime();
- $this->active = false;
- $this->freeze = false;
- }
-
- public function getId(): int
- {
- return $this->id;
- }
-
- public function setClientId(UuidInterface $clientId): self
- {
- $this->clientId = $clientId;
-
- return $this;
- }
-
- public function getClientId(): ?UuidInterface
- {
- return $this->clientId;
- }
-
- public function getCreatedAt(): \DateTime
- {
- return $this->createdAt;
- }
-
- public function setCreatedAt(\DateTime $createdAt): self
- {
- $this->createdAt = $createdAt;
-
- return $this;
- }
-
- public function getCrmUrl(): ?string
- {
- return $this->crmUrl;
- }
-
- public function setCrmUrl(?string $crmUrl): self
- {
- $this->crmUrl = rtrim($crmUrl, '/');
-
- return $this;
- }
-
- public function getCrmApiKey(): ?string
- {
- return $this->crmApiKey;
- }
-
- public function setCrmApiKey(?string $crmApiKey): self
- {
- $this->crmApiKey = $crmApiKey;
-
- return $this;
- }
-
- public function setActive(bool $active): self
- {
- $this->active = $active;
-
- return $this;
- }
-
- public function isActive(): bool
- {
- return $this->active;
- }
-
- public function setFreeze(bool $freeze): self
- {
- $this->freeze = $freeze;
-
- return $this;
- }
-
- public function isFreeze(): bool
- {
- return $this->freeze;
- }
-
- /**
- * @Serializer\VirtualProperty
- * @Serializer\Type("boolean")
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("isEnabled")
- */
- public function isEnabled(): bool
- {
- return !$this->freeze && $this->active;
- }
-
- public function setLanguage(string $language): self
- {
- $this->language = $language;
-
- return $this;
- }
-
- public function getLanguage(): ?string
- {
- return $this->language;
- }
-}
diff --git a/Model/IntegrationModule.php b/Model/IntegrationModule.php
deleted file mode 100644
index c85226d..0000000
--- a/Model/IntegrationModule.php
+++ /dev/null
@@ -1,140 +0,0 @@
-")
- */
- public $actions;
-
- /**
- * Список стран для которых доступен модуль
- *
- * @var array
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("availableCountries")
- * @Serializer\Type("array")
- */
- public $availableCountries;
-
- /**
- * URL настроек модуля
- *
- * @var string
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("accountUrl")
- * @Serializer\Type("string")
- */
- public $accountUrl;
-
- /**
- * Массив конфигураций интеграций
- *
- * @var array
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("integrations")
- * @Serializer\Type("array")
- */
- public $integrations;
-}
diff --git a/Model/Manager.php b/Model/Manager.php
deleted file mode 100644
index e841dc1..0000000
--- a/Model/Manager.php
+++ /dev/null
@@ -1,83 +0,0 @@
-lastName . ' ' . $this->firstName . ' ' . $this->patronymic
- );
-
- return $result;
- }
-}
diff --git a/Model/Package.php b/Model/Package.php
deleted file mode 100644
index 39e6688..0000000
--- a/Model/Package.php
+++ /dev/null
@@ -1,102 +0,0 @@
-")
- */
- public $items;
-
- public function __construct($weight = null, $width = null, $length = null, $height = null)
- {
- $this->weight = $weight;
- $this->width = $width;
- $this->length = $length;
- $this->height = $height;
- }
-
- public function getVolume()
- {
- if (null !== $this->length
- && null !== $this->width
- && null !== $this->height
- ) {
- return $this->length * $this->width * $this->height;
- } else {
- return false;
- }
- }
-
- public static function loadValidatorMetadata(ClassMetadata $metadata)
- {
- $metadata
- ->addPropertyConstraint('weight', new Assert\NotBlank());
- }
-}
diff --git a/Model/PackageItem.php b/Model/PackageItem.php
deleted file mode 100644
index cb01deb..0000000
--- a/Model/PackageItem.php
+++ /dev/null
@@ -1,107 +0,0 @@
-")
- */
- public $properties;
-}
diff --git a/Model/PaymentType.php b/Model/PaymentType.php
deleted file mode 100644
index 61be14c..0000000
--- a/Model/PaymentType.php
+++ /dev/null
@@ -1,22 +0,0 @@
-code = $code;
- $this->label = $label;
- }
-}
diff --git a/Model/Request/RequestCalculate.php b/Model/Request/RequestCalculate.php
deleted file mode 100644
index f0eb59e..0000000
--- a/Model/Request/RequestCalculate.php
+++ /dev/null
@@ -1,121 +0,0 @@
-")
- */
- public $packages;
-
- /**
- * Объявленная стоимость.
- *
- * @var float
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("declaredValue")
- * @Serializer\Type("float")
- */
- public $declaredValue;
-
- /**
- * Наложенный платеж.
- *
- * @var float
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("cod")
- * @Serializer\Type("float")
- */
- public $cod;
-
- /**
- * Плательщик за доставку.
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("payerType")
- * @Serializer\Type("string")
- */
- public $payerType;
-
- /**
- * Дата доставки.
- *
- * @var \DateTime
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("deliveryDate")
- * @Serializer\Type("DateTime<'Y-m-d'>")
- */
- public $deliveryDate;
-
- /**
- * Время доставки.
- *
- * @var DeliveryTime
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("deliveryTime")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $deliveryTime;
-
- /**
- * Валюта.
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("currency")
- * @Serializer\Type("string")
- */
- public $currency;
-
- /**
- * Дополнительные данные доставки.
- *
- * @var array
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-}
diff --git a/Model/Request/RequestDelete.php b/Model/Request/RequestDelete.php
deleted file mode 100644
index 69f8031..0000000
--- a/Model/Request/RequestDelete.php
+++ /dev/null
@@ -1,17 +0,0 @@
-")
- */
- public $packages;
-
- /**
- * Данные доставки
- *
- * @var RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData
- *
- * @Serializer\Groups({"request"})
- * @Serializer\SerializedName("delivery")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData")
- */
- public $delivery;
-
- /**
- * Валюта
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("currency")
- * @Serializer\Type("string")
- */
- public $currency;
-
- public function getFullDeclaredValue()
- {
- $result = 0;
- foreach ($this->packages as $package) {
- foreach ($package->items as $item) {
- $result += $item->declaredValue * $item->quantity;
- }
- }
-
- return $result;
- }
-
- public function getFullItemsCodValue()
- {
- $result = 0;
- foreach ($this->packages as $package) {
- foreach ($package->items as $item) {
- $result += $item->cod * $item->quantity;
- }
- }
-
- return $result;
- }
-}
diff --git a/Model/Request/RequestShipmentDelete.php b/Model/Request/RequestShipmentDelete.php
deleted file mode 100644
index 2541ea7..0000000
--- a/Model/Request/RequestShipmentDelete.php
+++ /dev/null
@@ -1,30 +0,0 @@
-")
- */
- public $date;
-
- /**
- * Время доставки ("custom" не ипользуется)
- *
- * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("time")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $time;
-
- /**
- * Адрес отгрузки
- *
- * @var string
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("address")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $address;
-
- /**
- * Массив идентификаторов оформленных доставок в службе доставки
- *
- * @var array
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("orders")
- * @Serializer\Type("array")
- */
- public $orders;
-
- /**
- * @var string
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("comment")
- * @Serializer\Type("string")
- */
- public $comment;
-
- /**
- * Дополнительные данные отгрузки
- *
- * @var array
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-}
diff --git a/Model/Request/RequestStatusUpdateItem.php b/Model/Request/RequestStatusUpdateItem.php
deleted file mode 100644
index db0dd4f..0000000
--- a/Model/Request/RequestStatusUpdateItem.php
+++ /dev/null
@@ -1,57 +0,0 @@
-")
- */
- public $history;
-
- /**
- * Массив дополнительных данных доставки
- *
- * @var array
- *
- * @Serializer\Groups({"request"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-
- public function __construct()
- {
- $this->history = [];
- }
-}
diff --git a/Model/RequestCalculate.php b/Model/RequestCalculate.php
deleted file mode 100644
index 63acab0..0000000
--- a/Model/RequestCalculate.php
+++ /dev/null
@@ -1,120 +0,0 @@
-")
- */
- public $packages;
-
- /**
- * Объявленная стоимость.
- *
- * @var float
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("declaredValue")
- * @Serializer\Type("float")
- */
- public $declaredValue;
-
- /**
- * Наложенный платеж.
- *
- * @var float
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("cod")
- * @Serializer\Type("float")
- */
- public $cod;
-
- /**
- * Плательщик за доставку.
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("payerType")
- * @Serializer\Type("string")
- */
- public $payerType;
-
- /**
- * Дата доставки.
- *
- * @var \DateTime
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("deliveryDate")
- * @Serializer\Type("DateTime<'Y-m-d'>")
- */
- public $deliveryDate;
-
- /**
- * Время доставки.
- *
- * @var DeliveryTime
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("deliveryTime")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $deliveryTime;
-
- /**
- * Валюта.
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("currency")
- * @Serializer\Type("string")
- */
- public $currency;
-
- /**
- * Дополнительные данные доставки.
- *
- * @var array
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-}
diff --git a/Model/RequestDelete.php b/Model/RequestDelete.php
deleted file mode 100644
index 69f8031..0000000
--- a/Model/RequestDelete.php
+++ /dev/null
@@ -1,17 +0,0 @@
-")
- */
- public $packages;
-
- /**
- * Данные доставки.
- *
- * @var SaveDeliveryData
- *
- * @Serializer\Groups({"request"})
- * @Serializer\SerializedName("delivery")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData")
- */
- public $delivery;
-
- /**
- * Валюта.
- *
- * @var string
- *
- * @Serializer\Groups({"request", "calculate"})
- * @Serializer\SerializedName("currency")
- * @Serializer\Type("string")
- */
- public $currency;
-
- public function getFullDeclaredValue()
- {
- $result = 0;
- foreach ($this->packages as $package) {
- foreach ($package->items as $item) {
- $result += $item->declaredValue * $item->quantity;
- }
- }
-
- return $result;
- }
-
- public function getFullItemsCodValue()
- {
- $result = 0;
- foreach ($this->packages as $package) {
- foreach ($package->items as $item) {
- $result += $item->cod * $item->quantity;
- }
- }
-
- return $result;
- }
-}
diff --git a/Model/RequestShipmentDelete.php b/Model/RequestShipmentDelete.php
deleted file mode 100644
index 2541ea7..0000000
--- a/Model/RequestShipmentDelete.php
+++ /dev/null
@@ -1,30 +0,0 @@
-")
- */
- public $date;
-
- /**
- * Время доставки ("custom" не ипользуется)
- *
- * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("time")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $time;
-
- /**
- * Адрес отгрузки
- *
- * @var string
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("address")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $address;
-
- /**
- * Массив идентификаторов оформленных доставок в службе доставки
- *
- * @var array
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("orders")
- * @Serializer\Type("array")
- */
- public $orders;
-
- /**
- * @var string
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("comment")
- * @Serializer\Type("string")
- */
- public $comment;
-
- /**
- * Дополнительные данные отгрузки
- *
- * @var array
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-}
diff --git a/Model/RequestStatusUpdateItem.php b/Model/RequestStatusUpdateItem.php
deleted file mode 100644
index db0dd4f..0000000
--- a/Model/RequestStatusUpdateItem.php
+++ /dev/null
@@ -1,57 +0,0 @@
-")
- */
- public $history;
-
- /**
- * Массив дополнительных данных доставки
- *
- * @var array
- *
- * @Serializer\Groups({"request"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-
- public function __construct()
- {
- $this->history = [];
- }
-}
diff --git a/Model/Response/ResponseAutocompleteItem.php b/Model/Response/ResponseAutocompleteItem.php
deleted file mode 100644
index 6aac639..0000000
--- a/Model/Response/ResponseAutocompleteItem.php
+++ /dev/null
@@ -1,42 +0,0 @@
-value = $value;
- $this->label = $label;
- $this->description = $description;
- }
-}
diff --git a/Model/Response/ResponseAutocompleteSuccessful.php b/Model/Response/ResponseAutocompleteSuccessful.php
deleted file mode 100644
index 75b38ae..0000000
--- a/Model/Response/ResponseAutocompleteSuccessful.php
+++ /dev/null
@@ -1,26 +0,0 @@
-")
- */
- public $result;
-}
diff --git a/Model/Response/ResponseCalculate.php b/Model/Response/ResponseCalculate.php
deleted file mode 100644
index dffb547..0000000
--- a/Model/Response/ResponseCalculate.php
+++ /dev/null
@@ -1,137 +0,0 @@
-")
- */
- public $pickuppointList;
-
- public function __construct()
- {
- $this->extraData = [];
- }
-}
diff --git a/Model/Response/ResponseCalculateSuccessful.php b/Model/Response/ResponseCalculateSuccessful.php
deleted file mode 100644
index 16b4bd7..0000000
--- a/Model/Response/ResponseCalculateSuccessful.php
+++ /dev/null
@@ -1,26 +0,0 @@
-")
- */
- public $result;
-}
diff --git a/Model/Response/ResponseLoadDeliveryData.php b/Model/Response/ResponseLoadDeliveryData.php
deleted file mode 100644
index e3654a5..0000000
--- a/Model/Response/ResponseLoadDeliveryData.php
+++ /dev/null
@@ -1,148 +0,0 @@
-")
- */
- public $shipmentDate;
-
- /**
- * Дата доставки
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryDate")
- * @Serializer\Type("DateTime<'Y-m-d'>")
- */
- public $deliveryDate;
-
- /**
- * Время доставки
- *
- * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryTime")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $deliveryTime;
-
- /**
- * Код тарифа
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("tariff")
- * @Serializer\Type("string")
- */
- public $tariff;
-
- /**
- * Наименование тарифа
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("tariffName")
- * @Serializer\Type("string")
- */
- public $tariffName;
-
- /**
- * Плательщик за доставку
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("payerType")
- * @Serializer\Type("string")
- */
- public $payerType;
-
- /**
- * Текущий статус достаквки
- *
- * @var StatusInfo
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("status")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\StatusInfo")
- */
- public $status;
-
- /**
- * Дополнительные данные доставки
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-
- /**
- * Адрес отгрузки
- *
- * @var DeliveryAddress
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("shipmentAddress")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $shipmentAddress;
-
- /**
- * Адрес доставки
- *
- * @var DeliveryAddress
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryAddress")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $deliveryAddress;
-
- public $additionalData;
-
- public function __construct()
- {
- $this->extraData = [];
- $this->additionalData = [];
- }
-}
diff --git a/Model/Response/ResponseResult.php b/Model/Response/ResponseResult.php
deleted file mode 100644
index bb0f2c3..0000000
--- a/Model/Response/ResponseResult.php
+++ /dev/null
@@ -1,7 +0,0 @@
-extraData = [];
- $this->additionalData = [];
- }
-}
diff --git a/Model/Response/ResponseShipmentSave.php b/Model/Response/ResponseShipmentSave.php
deleted file mode 100644
index 0dd8d67..0000000
--- a/Model/Response/ResponseShipmentSave.php
+++ /dev/null
@@ -1,38 +0,0 @@
-")
- */
- public $extraData;
-
- public static function loadValidatorMetadata(ClassMetadata $metadata)
- {
- $metadata
- ->addPropertyConstraint('shipmentId', new Assert\NotBlank());
- }
-}
diff --git a/Model/Response/ResponseSuccessful.php b/Model/Response/ResponseSuccessful.php
deleted file mode 100644
index d45bb2f..0000000
--- a/Model/Response/ResponseSuccessful.php
+++ /dev/null
@@ -1,26 +0,0 @@
-value = $value;
- $this->label = $label;
- $this->description = $description;
- }
-}
diff --git a/Model/ResponseAutocompleteSuccessful.php b/Model/ResponseAutocompleteSuccessful.php
deleted file mode 100644
index 75b38ae..0000000
--- a/Model/ResponseAutocompleteSuccessful.php
+++ /dev/null
@@ -1,26 +0,0 @@
-")
- */
- public $result;
-}
diff --git a/Model/ResponseCalculate.php b/Model/ResponseCalculate.php
deleted file mode 100644
index dffb547..0000000
--- a/Model/ResponseCalculate.php
+++ /dev/null
@@ -1,137 +0,0 @@
-")
- */
- public $pickuppointList;
-
- public function __construct()
- {
- $this->extraData = [];
- }
-}
diff --git a/Model/ResponseCalculateSuccessful.php b/Model/ResponseCalculateSuccessful.php
deleted file mode 100644
index 3247e35..0000000
--- a/Model/ResponseCalculateSuccessful.php
+++ /dev/null
@@ -1,17 +0,0 @@
-")
- */
- public $result;
-}
diff --git a/Model/ResponseLoadDeliveryData.php b/Model/ResponseLoadDeliveryData.php
deleted file mode 100644
index e3654a5..0000000
--- a/Model/ResponseLoadDeliveryData.php
+++ /dev/null
@@ -1,148 +0,0 @@
-")
- */
- public $shipmentDate;
-
- /**
- * Дата доставки
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryDate")
- * @Serializer\Type("DateTime<'Y-m-d'>")
- */
- public $deliveryDate;
-
- /**
- * Время доставки
- *
- * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryTime")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $deliveryTime;
-
- /**
- * Код тарифа
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("tariff")
- * @Serializer\Type("string")
- */
- public $tariff;
-
- /**
- * Наименование тарифа
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("tariffName")
- * @Serializer\Type("string")
- */
- public $tariffName;
-
- /**
- * Плательщик за доставку
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("payerType")
- * @Serializer\Type("string")
- */
- public $payerType;
-
- /**
- * Текущий статус достаквки
- *
- * @var StatusInfo
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("status")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\StatusInfo")
- */
- public $status;
-
- /**
- * Дополнительные данные доставки
- *
- * @var string
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-
- /**
- * Адрес отгрузки
- *
- * @var DeliveryAddress
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("shipmentAddress")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $shipmentAddress;
-
- /**
- * Адрес доставки
- *
- * @var DeliveryAddress
- *
- * @Serializer\Groups({"response"})
- * @Serializer\SerializedName("deliveryAddress")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
- */
- public $deliveryAddress;
-
- public $additionalData;
-
- public function __construct()
- {
- $this->extraData = [];
- $this->additionalData = [];
- }
-}
diff --git a/Model/ResponseResult.php b/Model/ResponseResult.php
deleted file mode 100644
index bb0f2c3..0000000
--- a/Model/ResponseResult.php
+++ /dev/null
@@ -1,7 +0,0 @@
-extraData = [];
- $this->additionalData = [];
- }
-}
diff --git a/Model/ResponseShipmentPointListSuccessful.php b/Model/ResponseShipmentPointListSuccessful.php
deleted file mode 100644
index 2bd76c4..0000000
--- a/Model/ResponseShipmentPointListSuccessful.php
+++ /dev/null
@@ -1,17 +0,0 @@
-")
- */
- public $result;
-}
diff --git a/Model/ResponseShipmentSave.php b/Model/ResponseShipmentSave.php
deleted file mode 100644
index 0dd8d67..0000000
--- a/Model/ResponseShipmentSave.php
+++ /dev/null
@@ -1,38 +0,0 @@
-")
- */
- public $extraData;
-
- public static function loadValidatorMetadata(ClassMetadata $metadata)
- {
- $metadata
- ->addPropertyConstraint('shipmentId', new Assert\NotBlank());
- }
-}
diff --git a/Model/ResponseSuccessful.php b/Model/ResponseSuccessful.php
deleted file mode 100644
index f00460a..0000000
--- a/Model/ResponseSuccessful.php
+++ /dev/null
@@ -1,17 +0,0 @@
-")
- */
- public $shipmentDate;
-
- /**
- * Дата доставки.
- *
- * @var \DateTime
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("deliveryDate")
- * @Serializer\Type("DateTime<'Y-m-d'>")
- */
- public $deliveryDate;
-
- /**
- * Время доставки ("custom" не ипользуется).
- *
- * @var \RetailCrm\DeliveryModuleBundle\Model\DeliveryTime
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("deliveryTime")
- * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime")
- */
- public $deliveryTime;
-
- /**
- * Дополнительные данные доставки.
- *
- * @var array
- *
- * @Serializer\Groups({"get"})
- * @Serializer\SerializedName("extraData")
- * @Serializer\Type("array")
- */
- public $extraData;
-}
diff --git a/Model/Settings.php b/Model/Settings.php
deleted file mode 100644
index b97c484..0000000
--- a/Model/Settings.php
+++ /dev/null
@@ -1,96 +0,0 @@
-")
- */
- public $paymentTypes;
-
- /**
- * @var array|ShipmentPoint[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("shipmentPoints")
- * @Serializer\Type("array")
- */
- public $shipmentPoints;
-
- /**
- * @var array|Status[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("statuses")
- * @Serializer\Type("array")
- */
- public $statuses;
-
- /**
- * @var array|ExtraData[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("deliveryExtraData")
- * @Serializer\Type("array")
- */
- public $deliveryExtraData;
-
- /**
- * @var array|ExtraData[]
- *
- * @Serializer\Groups({"set", "get"})
- * @Serializer\SerializedName("shipmentExtraData")
- * @Serializer\Type("array")
- */
- public $shipmentExtraData;
-}
diff --git a/Model/Settings/PaymentType.php b/Model/Settings/PaymentType.php
deleted file mode 100644
index 3b2ff3f..0000000
--- a/Model/Settings/PaymentType.php
+++ /dev/null
@@ -1,35 +0,0 @@
-")
- */
- public $packages;
-}
diff --git a/Model/Status.php b/Model/Status.php
deleted file mode 100644
index e3ec892..0000000
--- a/Model/Status.php
+++ /dev/null
@@ -1,48 +0,0 @@
-code = $code;
- $this->name = $name;
- $this->isEditable = $isEditable;
- }
-}
diff --git a/Model/StatusInfo.php b/Model/StatusInfo.php
deleted file mode 100644
index 9c2b246..0000000
--- a/Model/StatusInfo.php
+++ /dev/null
@@ -1,41 +0,0 @@
-")
- */
- public $updatedAt;
-
- /**
- * Комментарий к статусу
- *
- * @var string
- *
- * @Serializer\Groups({"get", "response"})
- * @Serializer\SerializedName("comment")
- * @Serializer\Type("string")
- */
- public $comment;
-}
diff --git a/Model/Store.php b/Model/Store.php
deleted file mode 100644
index 87c2e96..0000000
--- a/Model/Store.php
+++ /dev/null
@@ -1,26 +0,0 @@
-extraData[$fieldCode])) {
- return null;
- } else {
- return $this->extraData[$fieldCode];
- }
- }
-}
diff --git a/Model/Unit.php b/Model/Unit.php
deleted file mode 100644
index 4f45d32..0000000
--- a/Model/Unit.php
+++ /dev/null
@@ -1,33 +0,0 @@
-= 7.3
+* php-curl
+* php-json
+* php-zip
+* Symfony >= 5.1
+
+Documentation
+-------------
+
+Documentation for this bundle is stored under `doc` in this repository.
+
+[Read the Documentation](doc/index.md)
+
+License
+-------
+
+This bundle is released under the [MIT license](LICENSE)
diff --git a/Resources/config/routing.yaml b/Resources/config/routing.yaml
deleted file mode 100644
index 968e043..0000000
--- a/Resources/config/routing.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
-#############
-# API
-############
-retailcrm_delivery_module_api_base:
- path: /api
- defaults: { _controller: retailcrm.delivery_module.api_controller::index }
-
-retailcrm_delivery_module_api_activity:
- path: /api/activity
- defaults: { _controller: retailcrm.delivery_module.api_controller::activity }
- methods: POST
-
-retailcrm_delivery_module_api_calculate:
- path: /api/calculate
- defaults: { _controller: retailcrm.delivery_module.api_controller::calculate }
- methods: POST
-
-retailcrm_delivery_module_api_save:
- path: /api/save
- defaults: { _controller: retailcrm.delivery_module.api_controller::save }
- methods: POST
-
-retailcrm_delivery_module_api_get:
- path: /api/get
- defaults: { _controller: retailcrm.delivery_module.api_controller::getDeliveryOrder }
- methods: GET
-
-retailcrm_delivery_module_api_delete:
- path: /api/delete
- defaults: { _controller: retailcrm.delivery_module.api_controller::delete }
- methods: POST
-
-retailcrm_delivery_module_api_shipment_point_list:
- path: /api/shipment-point-list
- defaults: { _controller: retailcrm.delivery_module.api_controller::shipmentPointList }
- methods: GET
-
-retailcrm_delivery_module_api_print:
- path: /api/print
- defaults: { _controller: retailcrm.delivery_module.api_controller::print }
- methods: POST
-
-retailcrm_delivery_module_api_shipment_save:
- path: /api/shipment-save
- defaults: { _controller: retailcrm.delivery_module.api_controller::shipmentSave }
- methods: POST
-
-retailcrm_delivery_module_api_shipment_delete:
- path: /api/shipment-delete
- defaults: { _controller: retailcrm.delivery_module.api_controller::shipmentDelete }
- methods: POST
\ No newline at end of file
diff --git a/Resources/config/services.yaml b/Resources/config/services.yaml
deleted file mode 100644
index bf0df93..0000000
--- a/Resources/config/services.yaml
+++ /dev/null
@@ -1,58 +0,0 @@
-parameters:
- retailcrm.delivery_module.api_controller: RetailCrm\DeliveryModuleBundle\Controller\ApiController
-
-services:
- _defaults:
- public: false
- autowire: true
- autoconfigure: true
-
- retailcrm.delivery_module.api_controller:
- public: true
- class: '%retailcrm.delivery_module.api_controller%'
-
- RetailCrm\DeliveryModuleBundle\Service\RetailCrmClientFactoryInterface:
- class: RetailCrm\DeliveryModuleBundle\Service\RetailCrmClientFactory
-
- RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface:
- public: true
- class: '%retailcrm.delivery_module.module_manager.class%'
- arguments:
- - '%retailcrm.delivery_module.configuration%'
- - '@RetailCrm\DeliveryModuleBundle\Service\RetailCrmClientFactoryInterface'
- - '@RetailCrm\DeliveryModuleBundle\Service\DeliveryOrderManager'
- - '@jms_serializer'
- - '@translator'
- - '@router'
-
- RetailCrm\DeliveryModuleBundle\Service\AccountManager:
- class: 'RetailCrm\DeliveryModuleBundle\Service\AccountManager'
- arguments:
- - '%retailcrm.delivery_module.account.class%'
- - '@doctrine.orm.entity_manager'
-
- RetailCrm\DeliveryModuleBundle\Service\DeliveryOrderManager:
- class: 'RetailCrm\DeliveryModuleBundle\Service\DeliveryOrderManager'
- arguments:
- - '%retailcrm.delivery_module.delivery_order.class%'
- - '@doctrine.orm.entity_manager'
-
- RetailCrm\DeliveryModuleBundle\Command\StatusesCommand:
- class: RetailCrm\DeliveryModuleBundle\Command\StatusesCommand
- tags: ['console.command']
-
- RetailCrm\DeliveryModuleBundle\Command\UpdateModuleCommand:
- class: RetailCrm\DeliveryModuleBundle\Command\UpdateModuleCommand
- tags: ['console.command']
-
- RetailCrm\DeliveryModuleBundle\Controller\:
- resource: '../../Controller'
- public: true
- tags: ['controller.service_arguments']
-
- RetailCrm\DeliveryModuleBundle\EventSubscriber\SerializeListener:
- tags:
- - { name: jms_serializer.event_subscriber }
-
- RetailCrm\DeliveryModuleBundle\EventSubscriber\ClientIdSubscriber:
- class: RetailCrm\DeliveryModuleBundle\EventSubscriber\ClientIdSubscriber
diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml
deleted file mode 100644
index 816c98e..0000000
--- a/Resources/translations/messages.en.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-header:
- configureConnection: Configuration of connection with system
- additionalSettings: Additional settings
- adminParcelEdit: 'Edit tracking %trackId%'
- adminParcelCreate: Create tracking
- listConnection: Current connection
- listTracking: Current tracking
- serviceConnect: 'Service connection %delivery%'
- adminConnectionEdit: 'Edit connection data: %uid%'
- adminConnectionCreate: New connection
-
-button:
- activate: Activate
- save: Save
- add: Add
- listConnection: List of connections
- listTracking: Parcel tracking
- addTracking: Add tracking
- updateConfiguration: Update the configuration
-
-label:
- crmUrl: System address
- crmKey: System API key
- debug: Debug mode
- isActive: Integration is active
- isFreeze: Integration is freeze
- language: Language
- account_number: Account number
- token: API token
- isInProduction: Use production server
- id: ID
- connection: ID connection
- orderId: ID order
- trackId: ID tracking
- isClosed: Tracking completed
- connectionId: Connection ID
-
-select_value:
- sender: Sender
- receiver: Receiver
-
-error:
- connect.failed: Data to connect to %delivery% or System API key is entered incorrectly, try again.
Re-enter data
- unknown_country: Unknown country
- unknown_shipping_country: Unknown shipping country
- shipping_country_required: Shipping country must not be empty
- shipper_postal_code_required: Shipper postal code required
- delivery_postal_code_required: Delivery postal code required
- manager_phone_required: Manager`s phone required
- dhl:
- ready_time_required: Ready time required
- dury_payment_type_for_receiver: Duty Payment Type cant be sender for payer type receiver
- receiver_account_number_required: Receiver account number required
-
-plate:
- label: Label
-
-day_short:
- monday: Mon
- tuesday: Tue
- wednesday: Wed
- thursday: Thu
- friday: Fri
- saturday: Sat
- sunday: Sun
-
-pagination.items.name: elements
diff --git a/Resources/translations/messages.es.yml b/Resources/translations/messages.es.yml
deleted file mode 100644
index a66d5b5..0000000
--- a/Resources/translations/messages.es.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-header:
- configureConnection: Configuración de la conexión del sistema
- additionalSettings: Configuración avanzada
- adminParcelEdit: 'Editar seguimiento %trackId%'
- adminParcelCreate: Crear seguimiento
- listConnection: Conexiones actuales
- listTracking: Seguimiento actual
- serviceConnect: 'Conexión de Servicio %delivery%'
- adminConnectionEdit: 'Editar datos del cliente: %uid%'
- adminConnectionCreate: Nueva conexión
-
-button:
- activate: Activar
- save: Guardar
- add: Añadir
- listConnection: A la lista de conexiones
- listTracking: Seguimiento de paquetes
- addTracking: Añadir seguimiento
- updateConfiguration: Actualizar configuración
-
-label:
- crmUrl: Dirección del Sistema
- crmKey: Clave API del sistema
- debug: Modo de depuración
- isActive: Conexión activa
- isFreeze: Conexión congelada
- language: Idioma
- account_number: Número de cuenta
- token: token API
- isInProduction: Utilizar servidor normal
- id: ID
- connection: ID de conexión
- orderId: ID de pedido
- trackId: ID de seguimiento
- isClosed: Seguimiento completado
- connectionId: Id de conexión
-
-select_value:
- sender: Remitente
- receiver: Receptor
-
-error:
- connect.failed: Datos para conectarse a %delivery% o la clave API del sistema son incorrectos, intente de nuevo.
Introducir datos de nuevo
- unknown_country: País desconocido
- unknown_shipping_country: Páis de envio desconocido
- shipping_country_required: Debe especificar el país de envío
- shipper_postal_code_required: Debe especificar el código Postal del remitente
- delivery_postal_code_required: Debe especificar el código Postal del destinatario
- manager_phone_required: Debe especificar el Teléfono del mánager
- dhl:
- ready_time_required: Debe especificar la fecha del envío
- dury_payment_type_for_receiver: El remitente no puede pagar los cargos adicionales si el que paga es el destinatario
- receiver_account_number_required: Debe especificar el número de cuenta del destinatario
-
-plate:
- label: Etiqueta
-
-day_short:
- monday: Lu
- tuesday: Ma
- wednesday: Mie
- thursday: Ju
- friday: Vi
- saturday: Sa
- sunday: Do
-
-pagination.items.name: elementos
diff --git a/Resources/translations/messages.ru.yml b/Resources/translations/messages.ru.yml
deleted file mode 100644
index cfed3d8..0000000
--- a/Resources/translations/messages.ru.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-header:
- configureConnection: Настройка подключения к системе
- additionalSettings: Дополнительные настройки
- adminParcelEdit: 'Редактировать отслеживание %trackId%'
- adminParcelCreate: Создать отслеживание
- listConnection: Текущие подключения
- listTracking: Текущие отслеживания
- serviceConnect: 'Подключение сервиса %delivery%'
- adminConnectionEdit: 'Редактировать данные клиента: %uid%'
- adminConnectionCreate: Новое подключение
-
-button:
- activate: Активировать
- save: Сохранить
- add: Добавить
- listConnection: К списку подключений
- listTracking: Отслеживание посылок
- addTracking: Добавить отслеживание
- updateConfiguration: Обновить конфигурацию
-
-label:
- crmUrl: Адрес системы
- crmKey: API ключ системы
- debug: Режим отладки
- isActive: Подключение активно
- isFreeze: Подключение заморожено
- language: Язык
- account_number: Номер аккаунта
- token: API токен
- isInProduction: Использовать боевой сервер
- id: ID
- connection: ID подключения
- orderId: ID заказа
- trackId: ID отслеживания
- isClosed: Отслеживание завершено
- connectionId: Идентификатор подключения
-
-select_value:
- sender: Отправитель
- receiver: Получатель
-
-error:
- connect.failed: Данные для подключения к %delivery% или API ключ системы введены неверно, попробуйте еще раз.
Ввести данные заново
- unknown_country: Неизвестная страна
- unknown_shipping_country: Неизвестная страна отправки
- shipping_country_required: Необходимо указать страну отправки
- shipper_postal_code_required: Необходимо указать почтовый индекс отправителя
- delivery_postal_code_required: Необходимо указать почтовый индекс получателя
- manager_phone_required: Необходимо указать телефон менеджера
- dhl:
- ready_time_required: Необходимо указать время отгрузки
- dury_payment_type_for_receiver: Отправитель не может быть плательщиком за дополнительные сборы если тип плательщика получатель
- receiver_account_number_required: Необходимо указать номер аккаунта получателя
-
-plate:
- label: Наклейка
-
-day_short:
- monday: Пн
- tuesday: Вт
- wednesday: Ср
- thursday: Чт
- friday: Пт
- saturday: Сб
- sunday: Вс
-
-pagination.items.name: элементов
diff --git a/Resources/translations/validators.en.yaml b/Resources/translations/validators.en.yaml
deleted file mode 100644
index 0c3f989..0000000
--- a/Resources/translations/validators.en.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-integration_module_access:
- server_unreachable_exception: 'Failed to connect to the integration server'
- module_access_exception: 'Invalid login or password'
-
-retailcrm_access:
- access_denied: 'Access to the method "%method%" is denied'
- curl_exception: 'Failed to connect to API'
- service_unavailable: 'Service is temporarily unavailable'
- invalid_json: 'API returned a response in an unsupported format'
- requires_https: 'API address must start with https'
- wrong_api_key: 'Invalid API key'
diff --git a/Resources/translations/validators.es.yaml b/Resources/translations/validators.es.yaml
deleted file mode 100644
index ed0cf55..0000000
--- a/Resources/translations/validators.es.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-integration_module_access:
- server_unreachable_exception: 'No se ha podido conectar al servidor de integración'
- module_access_exception: 'El Usuario o la contraseña no es correcta'
-
-retailcrm_access:
- access_denied: 'Acceso al método "%method%" está prohibido'
- curl_exception: 'No se ha podido conectar al API'
- service_unavailable: 'Servicio no está disponible temporalmente'
- invalid_json: 'API ha devuelto la respuesta en el formato no soportado'
- requires_https: 'Dirección del API tiene que comenzar con https'
- wrong_api_key: 'El API-key no es correcto'
diff --git a/Resources/translations/validators.ru.yaml b/Resources/translations/validators.ru.yaml
deleted file mode 100644
index 432289b..0000000
--- a/Resources/translations/validators.ru.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-integration_module_access:
- server_unreachable_exception: 'Не удалось подключиться к интеграционному серверу'
- module_access_exception: 'Не верный логин или пароль'
-
-retailcrm_access:
- access_denied: 'Доступ к методу "%method%" запрещен'
- curl_exception: 'Не удалось подключиться к API'
- service_unavailable: 'Сервис временно недоступен'
- invalid_json: 'API вернуло ответ в неподдерживаемом формате'
- requires_https: 'Адрес API должен начинаться с https'
- wrong_api_key: 'Неверный API-ключ'
diff --git a/Service/AccountManager.php b/Service/AccountManager.php
deleted file mode 100644
index d9da37c..0000000
--- a/Service/AccountManager.php
+++ /dev/null
@@ -1,55 +0,0 @@
-class = $accountClass;
- $this->entityManager = $entityManager;
- }
-
- public function getClass(): string
- {
- return $this->getRepository()->getClassName();
- }
-
- public function create(): Account
- {
- $class = $this->getClass();
-
- return new $class();
- }
-
- public function find(string $id): ?Account
- {
- return $this->getRepository()->find($id);
- }
-
- public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
- {
- return $this->getRepository()->findBy($criteria, $orderBy, $limit, $offset);
- }
-
- public function findOneBy(array $criteria, array $orderBy = null): ?Account
- {
- return $this->getRepository()->findOneBy($criteria, $orderBy);
- }
-
- public function flush(): void
- {
- $this->entityManager->flush();
- }
-
- public function getRepository(): ObjectRepository
- {
- return $this->entityManager->getRepository($this->class);
- }
-}
diff --git a/Service/DeliveryOrderManager.php b/Service/DeliveryOrderManager.php
deleted file mode 100644
index e68390f..0000000
--- a/Service/DeliveryOrderManager.php
+++ /dev/null
@@ -1,65 +0,0 @@
-class = $deliveryOrderClass;
- $this->entityManager = $entityManager;
- }
-
- public function getClass(): string
- {
- return $this->class;
- }
-
- public function create(): DeliveryOrder
- {
- $class = $this->getClass();
-
- return new $class();
- }
-
- public function find(int $id): ?DeliveryOrder
- {
- return $this->getRepository()->find($id);
- }
-
- public function findBy(array $criteria): array
- {
- return $this->getRepository()->findBy($criteria);
- }
-
- public function findOneBy(array $criteria): ?DeliveryOrder
- {
- return $this->getRepository()->findOneBy($criteria);
- }
-
- public function persist(object $entity): void
- {
- $this->entityManager->persist($entity);
- }
-
- public function remove(object $entity): void
- {
- $this->entityManager->remove($entity);
- }
-
- public function flush(): void
- {
- $this->entityManager->flush();
- }
-
- public function getRepository(): ObjectRepository
- {
- return $this->entityManager->getRepository($this->class);
- }
-}
diff --git a/Service/ModuleManager.php b/Service/ModuleManager.php
deleted file mode 100644
index d20f512..0000000
--- a/Service/ModuleManager.php
+++ /dev/null
@@ -1,355 +0,0 @@
-integrationCode = $moduleParameters['integration_code'];
- $this->moduleParameters = $moduleParameters;
- $this->retailCrmClientFactory = $retailCrmClientFactory;
- $this->deliveryManager = $deliveryManager;
- $this->jmsSerializer = $jmsSerializer;
- $this->translator = $translator;
- $this->router = $router;
- $this->pinbaService = new PinbaService();
- }
-
- public function getAccountCode(): string
- {
- if (null === $this->account) {
- throw new \LogicException('Account is not selected');
- }
-
- return sprintf('%s-%s', $this->integrationCode, $this->account->getId());
- }
-
- public function getAccount(): ?Account
- {
- return $this->account;
- }
-
- public function setAccount(Account $account): ModuleManagerInterface
- {
- $this->account = $account;
-
- if ($this->account && $this->account->getLanguage() && $this->translator) {
- $this->translator->setLocale($this->account->getLanguage());
- }
-
- $this->retailCrmClient = $this->retailCrmClientFactory->createRetailCrmClient($this->account);
-
- return $this;
- }
-
- public function updateModuleConfiguration(): bool
- {
- if (null === $this->account) {
- throw new \LogicException('Account is not selected');
- }
-
- $integrationModule = $this->buildIntegrationModule();
- $integrationModule = $this->jmsSerializer
- ->serialize(
- $integrationModule,
- 'json',
- SerializationContext::create()->setGroups(['get', 'request'])->setSerializeNull(true)
- );
-
- $client = $this->retailCrmClient;
- $response = $this->pinbaService->timerHandler(
- [
- 'api' => 'retailCrm',
- 'method' => 'integrationModulesEdit',
- ],
- static function () use ($client, $integrationModule) {
- return $client->request->integrationModulesEdit(
- json_decode($integrationModule, true)
- );
- }
- );
-
- if ($response['success'] ?? false) {
- return true;
- } else {
- if ($this->logger) {
- $errorMsg = $response['error_msg'] ?? '';
- $this->logger->warning("Failed to update module configuration[account={$this->getAccount()->getCrmUrl()}]:{$errorMsg}");
- }
-
- return false;
- }
- }
-
- protected function buildIntegrationModule(): IntegrationModule
- {
- $integrationModule = new IntegrationModule();
-
- $integrationModule->code = $this->getAccountCode();
- $integrationModule->integrationCode = $this->integrationCode;
- $integrationModule->active = $this->account->isActive();
- $integrationModule->name = $this->moduleParameters['locales'][$this->translator->getLocale()]['name'];
- $integrationModule->logo = $this->moduleParameters['locales'][$this->translator->getLocale()]['logo'];
- $integrationModule->clientId = $this->account->getClientId();
- $integrationModule->availableCountries = $this->moduleParameters['countries'];
- $integrationModule->actions = [
- 'activity' => 'activity',
- ];
-
- $integrationModule->baseUrl = $this->router->generate(
- 'retailcrm_delivery_module_api_base',
- [],
- UrlGeneratorInterface::ABSOLUTE_URL
- );
- $integrationModule->accountUrl = $this->getAccountUrl();
-
- $integrationModule->integrations = ['delivery' => $this->doBuildConfiguration()];
-
- return $integrationModule;
- }
-
- abstract protected function doBuildConfiguration(): Configuration;
-
- abstract protected function getAccountUrl(): string;
-
- public function calculateDelivery(RequestCalculate $data): array
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function saveDelivery(RequestSave $data, DeliveryOrder $delivery = null): ResponseSave
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function getDelivery(string $externalId): ResponseLoadDeliveryData
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function deleteDelivery(RequestDelete $request, DeliveryOrder $delivery): bool
- {
- throw new \LogicException('Method should be implemented');
- }
-
- /**
- * @return \RetailCrm\DeliveryModuleBundle\Model\Terminal[]
- */
- public function shipmentPointList(RequestShipmentPointList $request): array
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function saveShipment(RequestShipmentSave $data): ResponseShipmentSave
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function deleteShipment(RequestShipmentDelete $request): bool
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function printDocument(RequestPrint $request)
- {
- $deliveries = $this->deliveryManager->findBy([
- 'account' => $this->account,
- 'externalId' => $request->deliveryIds,
- ]);
-
- if (empty($deliveries)) {
- throw new NotFoundException('Deliveries not found');
- }
-
- return $this->doPrint($request->type, $deliveries);
- }
-
- protected function doPrint(string $documentType, array $deliveries): array
- {
- throw new \LogicException('Method should be implemented');
- }
-
- public function updateStatuses(): int
- {
- if (null === $this->account) {
- throw new \LogicException('Account is not selected');
- }
-
- $deliveryQuery = $this->deliveryManager->createQueryBuilder('delivery')
- ->select('delivery')
- ->andWhere('delivery.account = :account')
- ->andWhere('delivery.id >= :lastId')
- ->andWhere('delivery.ended = FALSE')
- ->orderBy('delivery.id ASC')
- ->createQuery()
- ->setMaxResults(static::STATUS_UPDATE_LIMIT)
- ->setAccount($this->account)
- ;
-
- $count = 0;
- $lastId = 0;
- while (true) {
- $deliveryQuery->setParameter('lastId', $lastId);
- $deliveries = $deliveryQuery->getResult();
- if (empty($deliveries)) {
- break;
- }
-
- foreach ($deliveries as $delivery) {
- if ($delivery->getId() > $lastId) {
- $lastId = $delivery->getId();
- }
- }
-
- $deliveriesHistory = $this->doUpdateStatuses($deliveries);
- if (!empty($deliveriesHistory)) {
- $this->updateRetailCrmOrderStatuses($deliveriesHistory);
- }
- $count += count($deliveriesHistory);
- $this->deliveryManager->flush();
- }
-
- return $count;
- }
-
- public function getRetailCrmClient(): ApiClient
- {
- if (null === $this->retailCrmClient) {
- throw new \LogicException('Account is not selected');
- }
-
- return $this->retailCrmClient;
- }
-
- /**
- * Получение актуальных статусов доставки от службы доставки.
- *
- * @param \RetailCrm\DeliveryModuleBundle\Entity\Parcel[] $deliveries
- *
- * @return \RetailCrm\DeliveryModuleBundle\Model\RequestStatusUpdateItem[]
- */
- protected function doUpdateStatuses(array $deliveries): array
- {
- throw new \LogicException('Method should be implemented');
- }
-
- /**
- * Обновление статусов в CRM.
- *
- * @param \RetailCrm\DeliveryModuleBundle\Model\RequestStatusUpdateItem[] $deliveriesHistory
- *
- * @throws \Exception
- */
- protected function updateRetailCrmOrderStatuses(array $deliveriesHistory): void
- {
- if (count($deliveriesHistory) > 100) {
- $parts = array_chunk($deliveriesHistory, 100);
- } else {
- $parts = [$deliveriesHistory];
- }
-
- foreach ($parts as $part) {
- $request = $this->jmsSerializer
- ->serialize($part, 'json', SerializationContext::create()->setGroups(['get', 'request']));
-
- $client = $this->retailCrmClient;
- $moduleCode = $this->getAccountCode();
- $response = $this->pinbaService->timerHandler(
- [
- 'api' => 'retailCrm',
- 'method' => 'deliveryTracking',
- ],
- static function () use ($client, $moduleCode, $request) {
- return $client->request->deliveryTracking(
- $moduleCode,
- json_decode($request, true)
- );
- }
- );
- }
- }
-}
diff --git a/Service/ModuleManagerInterface.php b/Service/ModuleManagerInterface.php
deleted file mode 100644
index b168426..0000000
--- a/Service/ModuleManagerInterface.php
+++ /dev/null
@@ -1,52 +0,0 @@
-getCrmUrl())) {
- throw new \LogicException('Crm url is empty');
- }
-
- if (empty($account->getCrmApiKey())) {
- throw new \LogicException('Crm apiKey is empty');
- }
-
- $retailCrmClient = new ApiClient(
- $account->getCrmUrl(),
- $account->getCrmApiKey(),
- ApiClient::V5
- );
- if ($logger) {
- $retailCrmClient->setLogger($logger);
- }
-
- return $retailCrmClient;
- }
-}
diff --git a/Service/RetailCrmClientFactoryInterface.php b/Service/RetailCrmClientFactoryInterface.php
deleted file mode 100644
index 8c0d156..0000000
--- a/Service/RetailCrmClientFactoryInterface.php
+++ /dev/null
@@ -1,12 +0,0 @@
-moduleManager = $moduleManager;
- }
-
- public function validate($account, Constraint $constraint)
- {
- if (!($constraint instanceof IntegrationModuleAccess)) {
- throw new UnexpectedTypeException($constraint, IntegrationModuleAccess::class);
- }
-
- try {
- $this->moduleManager->checkAccess();
- } catch (ServerUnreachableException $e) {
- $this->context
- ->buildViolation('integration_module_access.server_unreachable_exception')
- ->atPath($constraint->path)
- ->addViolation()
- ;
- } catch (AbstractModuleException $e) {
- $this->context
- ->buildViolation('integration_module_access.module_access_exception')
- ->atPath($constraint->path)
- ->addViolation()
- ;
- }
- }
-}
diff --git a/Validator/Constraints/RetailCrmAccess.php b/Validator/Constraints/RetailCrmAccess.php
deleted file mode 100644
index 74811f9..0000000
--- a/Validator/Constraints/RetailCrmAccess.php
+++ /dev/null
@@ -1,23 +0,0 @@
-moduleManager = $moduleManager;
- }
-
- public function validate($account, Constraint $constraint)
- {
- if (!($constraint instanceof RetailCrmAccess)) {
- throw new UnexpectedTypeException($constraint, RetailCrmAccess::class);
- }
-
- $client = $this->moduleManager->getRetailCrmClient();
-
- try {
- $response = $client->request->credentials();
- if (!$response->isSuccessful()) {
- throw new RetailCrmApiException($response->offsetGet('errorMsg'));
- }
-
- $credentials = $response->offsetGet('credentials');
- foreach ($constraint->requiredApiMethods as $method) {
- if (!in_array($method, $credentials)) {
- $this->context
- ->buildViolation('retailcrm_access.access_denied', ['%method%' => $method])
- ->atPath('crmApiKey')
- ->addViolation()
- ;
- }
- }
- } catch (CurlException $e) {
- $this->context
- ->buildViolation('retailcrm_access.curl_exception')
- ->atPath('crmUrl')
- ->addViolation()
- ;
- } catch (LimitException $e) {
- $this->context
- ->buildViolation('retailcrm_access.service_unavailable')
- ->atPath('crmUrl')
- ->addViolation()
- ;
- } catch (InvalidJsonException $e) {
- $this->context
- ->buildViolation('retailcrm_access.invalid_json')
- ->atPath('crmUrl')
- ->addViolation()
- ;
- } catch (\InvalidArgumentException $e) {
- $this->context
- ->buildViolation('retailcrm_access.requires_https')
- ->atPath('crmUrl')
- ->addViolation()
- ;
- } catch (RetailCrmApiException $e) {
- $this->context
- ->buildViolation('retailcrm_access.wrong_api_key')
- ->atPath('crmUrl')
- ->addViolation()
- ;
- }
- }
-}
diff --git a/composer.json b/composer.json
index 77b9f3a..1121ac6 100644
--- a/composer.json
+++ b/composer.json
@@ -1,34 +1,49 @@
{
"name": "retailcrm/delivery-module-bundle",
- "description": "Delivery module skeleton for RetailCrm",
- "license": "MIT",
"type": "symfony-bundle",
- "autoload": {
- "psr-4": {
- "RetailCrm\\DeliveryModuleBundle\\": ""
+ "description": "Delivery module skeleton for RetailCRM",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "RetailCRM",
+ "email": "support@retailcrm.ru"
}
- },
- "config": {
- "sort-packages": true
- },
+ ],
"require": {
"php": "^7.3",
"ext-json": "*",
"ext-zip": "*",
- "doctrine/orm": "^2.7",
- "jms/serializer": "^3.4",
- "jms/serializer-bundle": "^3.5",
- "ramsey/uuid": "^3.9",
- "ramsey/uuid-doctrine": "^1.5",
- "retailcrm/api-client-php": "^5.0.0",
- "symfony/framework-bundle": "^3.4|^4.0|^5.1",
+ "guzzlehttp/guzzle": "^7.0",
+ "psr/log": "^1.1",
+ "symfony/framework-bundle": "^5.1",
"symfony/lock": "^5.1",
+ "symfony/polyfill-uuid": "^1.20",
"symfony/routing": "^5.1",
+ "symfony/serializer": "^5.1",
"symfony/translation": "^5.1",
"symfony/validator": "^5.1"
},
"require-dev": {
- "doctrine/doctrine-fixtures-bundle": "^3.3",
- "friendsofphp/php-cs-fixer": "^2.0"
+ "doctrine/orm": "^2.7",
+ "friendsofphp/php-cs-fixer": "^2.0",
+ "phpunit/phpunit": "^9.4",
+ "vimeo/psalm": "^4.1"
+ },
+ "autoload": {
+ "psr-4": {
+ "RetailCrm\\DeliveryModuleBundle\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "RetailCrm\\DeliveryModuleBundle\\Tests\\": "tests/"
+ }
+ },
+ "scripts": {
+ "test": "vendor/bin/phpunit",
+ "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml"
+ },
+ "config": {
+ "sort-packages": true
}
}
diff --git a/doc/index.md b/doc/index.md
new file mode 100644
index 0000000..a98226c
--- /dev/null
+++ b/doc/index.md
@@ -0,0 +1,284 @@
+Getting started with RetailCrmDeliveryModuleBundle
+==================================================
+
+## Prerequisites
+
+This version of the bundle requires Symfony 5.1.
+
+#### Translations
+
+If you wish to use default texts provided in this bundle, you have to make sure you have translator enabled in your config:
+
+``` yaml
+ # config/packages/translation.yaml
+
+ framework:
+ translator: { fallback: en }
+```
+
+For more information about translations, check [Symfony documentation](http://symfony.com/doc/current/book/translation.html).
+
+
+## Installation
+
+Installation is a 7 steps process:
+
+1. Download RetailCrmDeliveryModuleBundle
+2. Enable the Bundle
+3. Create your model class
+4. Create your integration module factory
+5. Create your delivery service
+6. Create your tracker
+7. Configure the RetailCrmDeliveryModuleBundle
+
+
+### Step 1: Install RetailCrmDeliveryModuleBundle
+
+The preferred way to install this bundle is to rely on [Composer](http://getcomposer.org).
+
+Just check on [Packagist](http://packagist.org/packages/retailcrm/delivery-module-bundle) the version you want to install (in the following example, we used "dev-master") and add it to your `composer.json`:
+
+``` json
+{
+ "require": {
+ // ...
+ "retailcrm/delivery-module-bundle": "dev-master"
+ }
+}
+```
+
+
+### Step 2: Enable the bundle
+
+Finally, enable the bundle in the kernel:
+
+``` php
+ ['all' => true],
+];
+```
+
+
+### Step 3: Create model classes
+
+This bundle needs to persist some classes to a database:
+
+- `Account`
+- `Delivery`
+
+Your first job, then, is to create these classes for your application.
+These classes can look and act however you want: add any properties or methods you find useful.
+
+These classes have just a few requirements:
+
+1. They must extend one of the base classes from the bundle
+2. They must have an `id` field
+
+In the following sections, you'll see examples of how your classes should
+look, depending on how you're storing your data.
+
+Your classes can live inside any bundle in your application.
+
+**Warning:**
+
+> If you override the __construct() method in your classes, be sure to call parent::__construct(), as the base class depends on this to initialize some fields.
+
+
+#### Doctrine ORM classes
+
+If you're persisting your data via the Doctrine ORM, then your classes should live in the `Entity` namespace of your bundle and look like this to start:
+
+``` php
+urlGenerator = $urlGenerator;
+
+ parent::__construct($configuration);
+ }
+
+ protected function getBaseUrl(): string
+ {
+ return $this->urlGenerator->generate('base_url', [], UrlGeneratorInterface::ABSOLUTE_URL);
+ }
+
+ protected function getAccountUrl(): string
+ {
+ return $this->urlGenerator->generate('account_url', [], UrlGeneratorInterface::ABSOLUTE_URL);
+ }
+
+ protected function getDeliveryConfiguration(Account $account): array
+ {
+ $configuration = [];
+
+ $configuration['description'] = sprintf("Account %s[%s] configuration", $account->getUrl(), $account->getClientId());
+
+ $configuration['actions'] = [
+ 'calculate' => 'delivery/calculate',
+ 'save' => 'delivery/save',
+ 'get' => 'delivery/get',
+ 'delete' => 'delivery/delete',
+ 'shipmentPointList' => 'delivery/shipment-point-list',
+ 'shipmentSave' => 'delivery/shipment-save',
+ 'shipmentDelete' => 'delivery/shipment-delete',
+ 'tariffList' => 'delivery/tariff-list',
+ 'print' => 'delivery/print',
+ ];
+
+ $configuration['payerType'] = [
+ 'receiver',
+ 'sender',
+ ];
+
+ // TODO: add your logic
+
+ return $configuration;
+ }
+}
+```
+
+
+### Step 5: Create your delivery service
+The DeliveryService class responsibility is to provide a gateway for delivery API.
+
+Custom delivery service must implement:
+- `RetailCrm\DeliveryModuleBundle\DeliveryService\ProcessableDeliveryServiceInterface` if delivery provides create/delete processing
+- `RetailCrm\DeliveryModuleBundle\DeliveryService\TrackableDeliveryServiceInterface` if delivery provides tracking service
+
+
+### Step 6: Create your tracker
+The Tracker class responsibility is to provide a tracking service.
+
+You can use default tracker `retail_crm_delivery_module.tracker.default` or crete your custom.
+
+Tracker is class must implement the `RetailCrm\DeliveryModuleBundle\Tracking\TrackerInterface`.
+This interface defines one method called `tracking` to perform delivery tracking.
+
+
+### Step 7: Configure RetailCrmDeliveryModuleBundle
+
+Import the routing configuration file in `config/routes.yaml`:
+
+``` yaml
+# config/routes.yaml
+retail_crm_delivery_module_callback_delivery:
+ resource: "@RetailCrmDeliveryModuleBundle/Resources/config/routing/delivery_callback.xml"
+
+retail_crm_delivery_module_callback_integration_module:
+ resource: "@RetailCrmDeliveryModuleBundle/Resources/config/routing/integration_module_callback.xml"
+```
+
+Add RetailCrmDeliveryModuleBundle settings in `config/packages/retail_crm_delivery_module.yaml`:
+
+``` yaml
+# config/packages/retail_crm_delivery_module.yaml
+retail_crm_delivery_module:
+ db_driver: orm # Drivers available: orm or custom
+
+ model:
+ account_class: App\Entity\Account
+ delivery_class: App\Entity\Delivery
+
+ service:
+ manager:
+ account: retail_crm_delivery_module.manager.account.default # Or your custom
+ delivery: retail_crm_delivery_module.manager.delivery.default # Or your custom
+ integration_module_factory: App\IntegrationModule\CustomIntegrationModuleFactory
+ delivery_service: App\DeliveryService\CustomDeliveryService
+ tracker: retail_crm_delivery_module.tracker.default # Or your custom
+```
+
+Update your database schema
+
+Now the bundle is configured, the last thing you need to do is update your database schema because you have added a new entity.
+
+For ORM run the following command.
+
+ $ php bin/console doctrine:schema:update --force
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..93ed756
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000..49b3329
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Command/TrackingCommand.php b/src/Command/TrackingCommand.php
new file mode 100644
index 0000000..9013d87
--- /dev/null
+++ b/src/Command/TrackingCommand.php
@@ -0,0 +1,108 @@
+accountManager = $accountManager;
+ $this->tracker = $tracker;
+
+ parent::__construct($name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure(): void
+ {
+ $this
+ ->setDescription('Delivery tracking')
+ ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all')
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if (!$this->lock()) {
+ $output->writeln('The command is already running in another process.');
+
+ return 1;
+ }
+
+ $startTime = new \DateTime();
+
+ $accountId = $input->hasArgument('accountId')
+ ? (int) $input->getArgument('accountId')
+ : null
+ ;
+
+ $successfulCount = $failureCount = 0;
+
+ $accounts = $this->getActiveAccounts($accountId);
+
+ /** @var Account $account */
+ foreach ($accounts as $account) {
+ try {
+ $this->tracker->tracking($account);
+
+ ++$successfulCount;
+ } catch (\Exception $e) {
+ $output->writeln("Failed to update statuses for account {$account->getCrmUrl()}[{$account->getClientId()}]");
+ $output->writeln("Error: {$e->getMessage()}");
+
+ ++$failureCount;
+ }
+ }
+
+ $this->release();
+
+ $output->writeln(sprintf('Accounts updated successful = %s', $successfulCount));
+ $output->writeln(sprintf('Accounts failed updates = %s', $failureCount));
+ $output->writeln(sprintf('Memory = %s', memory_get_peak_usage()));
+ $output->writeln(sprintf('Time of execution = %s', $startTime->diff(new \DateTime())->format('%I:%S')));
+
+ return 0;
+ }
+
+ protected function getActiveAccounts(int $accountId = null): \Generator
+ {
+ if (null !== $accountId) {
+ $account = $this->accountManager->findActiveAccountById($accountId);
+
+ if (null !== $account) {
+ yield $account;
+ } else {
+ yield from [];
+ }
+ } else {
+ return $this->accountManager->findActiveAccounts();
+ }
+ }
+}
diff --git a/src/Command/UpdateIntegrationModuleCommand.php b/src/Command/UpdateIntegrationModuleCommand.php
new file mode 100644
index 0000000..00b80d1
--- /dev/null
+++ b/src/Command/UpdateIntegrationModuleCommand.php
@@ -0,0 +1,115 @@
+accountManager = $accountManager;
+ $this->integrationModuleFactory = $integrationModuleFactory;
+ $this->crmApiGateway = $crmApiGateway;
+
+ parent::__construct($name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure(): void
+ {
+ $this
+ ->setDescription('Updates integration module')
+ ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all')
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if (!$this->lock()) {
+ $output->writeln('The command is already running in another process.');
+
+ return 1;
+ }
+
+ $startTime = new \DateTime();
+
+ $accountId = $input->hasArgument('accountId')
+ ? (int) $input->getArgument('accountId')
+ : null
+ ;
+
+ $successfulCount = $failureCount = 0;
+
+ $accounts = $this->getActiveAccounts($accountId);
+
+ /** @var Account $account */
+ foreach ($accounts as $account) {
+ $integrationModule = $this->integrationModuleFactory->createIntegrationModule($account);
+
+ try {
+ $this->crmApiGateway->updateIntegrationModule($account, $integrationModule);
+
+ ++$successfulCount;
+ } catch (\Exception $e) {
+ $output->writeln("Failed to update integration module for account {$account->getCrmUrl()}[{$account->getClientId()}]");
+ $output->writeln("{$e->getMessage()}");
+
+ ++$failureCount;
+ }
+ }
+
+ $this->release();
+
+ $output->writeln(sprintf('Accounts updated successful = %s', $successfulCount));
+ $output->writeln(sprintf('Accounts failed updates = %s', $failureCount));
+ $output->writeln(sprintf('Memory = %s', memory_get_peak_usage()));
+ $output->writeln(sprintf('Time of execution = %s', $startTime->diff(new \DateTime())->format('%I:%S')));
+
+ return 0;
+ }
+
+ protected function getActiveAccounts(int $accountId = null): \Generator
+ {
+ if (null !== $accountId) {
+ $account = $this->accountManager->findActiveAccountById($accountId);
+ if (null !== $account) {
+ yield $account;
+ } else {
+ yield from [];
+ }
+ } else {
+ return $this->accountManager->findActiveAccounts();
+ }
+ }
+}
diff --git a/src/Controller/AccountValueResolver.php b/src/Controller/AccountValueResolver.php
new file mode 100644
index 0000000..52348d8
--- /dev/null
+++ b/src/Controller/AccountValueResolver.php
@@ -0,0 +1,42 @@
+accountManager = $accountManager;
+ }
+
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return Account::class === $argument->getType() || is_subclass_of($argument->getType(), Account::class);
+ }
+
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ $clientId = $request->get('clientId');
+ if (empty($clientId)) {
+ throw new AccessDeniedHttpException('Parameter "clientId" is required');
+ }
+
+ $account = $this->accountManager->findAccountByClientId($clientId);
+ if (null === $account) {
+ throw new NotFoundHttpException('Account not found');
+ }
+
+ yield $account;
+ }
+}
diff --git a/src/Controller/DeliveryCallbackController.php b/src/Controller/DeliveryCallbackController.php
new file mode 100644
index 0000000..fe9b280
--- /dev/null
+++ b/src/Controller/DeliveryCallbackController.php
@@ -0,0 +1,341 @@
+decoder = $decoder;
+ $this->tariffAdapter = $tariffAdapter;
+ $this->deliveryAdapter = $deliveryAdapter;
+ $this->shipmentAdapter = $shipmentAdapter;
+ $this->plateAdapter = $plateAdapter;
+ }
+
+ public function onTariffList(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->tariffAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ try {
+ $result = $this->tariffAdapter->getTariffList($account);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onCalculate(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->tariffAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $calculate = $request->request->get('calculate');
+ if (empty($calculate)) {
+ throw new BadRequestHttpException('Parameter "calculate" is required');
+ }
+
+ try {
+ $decodedCalculate = $this->decoder->decode($calculate, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ try {
+ $result = $this->tariffAdapter->calculate($account, $decodedCalculate);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onSave(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->deliveryAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $save = $request->request->get('save');
+ if (empty($save)) {
+ throw new BadRequestHttpException('Parameter "save" is required');
+ }
+
+ try {
+ $decodedSave = $this->decoder->decode($save, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ try {
+ $result = $this->deliveryAdapter->createDelivery($account, $decodedSave);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onGet(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->deliveryAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $deliveryId = $request->query->get('deliveryId');
+ if (empty($deliveryId)) {
+ throw new BadRequestHttpException('Parameter "deliveryId" is required');
+ }
+
+ try {
+ $result = $this->deliveryAdapter->getDelivery($account, $deliveryId);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryNotFoundException $e) {
+ throw new NotFoundHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onDelete(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->deliveryAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $delete = $request->request->get('delete');
+ if (empty($delete)) {
+ throw new BadRequestHttpException('Parameter "delete" is required');
+ }
+
+ try {
+ $decodedDelete = $this->decoder->decode($delete, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ try {
+ $success = $this->deliveryAdapter->deleteDelivery($account, $decodedDelete);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryNotFoundException $e) {
+ throw new NotFoundHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => $success]);
+ }
+
+ public function onShipmentPointList(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->shipmentAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $query = [
+ 'country' => $request->query->get('country'),
+ 'region' => $request->query->get('region'),
+ 'regionId' => $request->query->getInt('regionId'),
+ 'city' => $request->query->get('city'),
+ 'cityId' => $request->query->getInt('cityId'),
+ ];
+
+ try {
+ $result = $this->shipmentAdapter->getShipmentPointList($account, $query);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onShipmentSave(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->shipmentAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $shipmentSave = $request->request->get('shipmentSave');
+ if (empty($shipmentSave)) {
+ throw new BadRequestHttpException('Parameter "shipmentSave" is required');
+ }
+
+ try {
+ $decodedShipmentSave = $this->decoder->decode($shipmentSave, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ try {
+ $result = $this->shipmentAdapter->createShipment($account, $decodedShipmentSave);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => true, 'result' => $result]);
+ }
+
+ public function onShipmentDelete(Request $request, Account $account): JsonResponse
+ {
+ if (null === $this->shipmentAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $shipmentDelete = $request->request->get('shipmentDelete');
+ if (empty($shipmentDelete)) {
+ throw new BadRequestHttpException('Parameter "shipmentDelete" is required');
+ }
+
+ try {
+ $decodedShipmentDelete = $this->decoder->decode($shipmentDelete, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ try {
+ $success = $this->shipmentAdapter->deleteShipment($account, $decodedShipmentDelete);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (ShipmentNotFound $e) {
+ throw new NotFoundHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ return $this->json(['success' => $success]);
+ }
+
+ public function onPrint(Request $request, Account $account): Response
+ {
+ if (null === $this->plateAdapter) {
+ throw new \LogicException('Method is not configured');
+ }
+
+ $print = $request->request->get('print');
+ if (empty($print)) {
+ throw new BadRequestHttpException('Parameter "print" is required');
+ }
+
+ try {
+ $decodedPrint = $this->decoder->decode($print, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage());
+ }
+
+ try {
+ $printedPlates = $this->plateAdapter->getPrintedPlates($account, $decodedPrint);
+ } catch (BadRequestException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ } catch (DeliveryServiceUnavailableException $e) {
+ throw new ServiceUnavailableHttpException($e->getRetryAfter(), $e->getMessage(), $e);
+ } catch (DeliveryServiceException $e) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error', $e);
+ }
+
+ if (empty($printedPlates)) {
+ throw new BadRequestHttpException('Empty printed plate list');
+ }
+
+ if (1 === count($printedPlates)) {
+ return new Response(reset($printedPlates), 200, ['Content-Type' => 'application/pdf']);
+ }
+
+ $tmpFilename = tempnam(sys_get_temp_dir(), 'zip');
+ if (!$tmpFilename) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Failed to create temp file for zip archive');
+ }
+
+ $archive = new \ZipArchive();
+ $archive->open($tmpFilename, \ZipArchive::CREATE);
+ foreach ($printedPlates as $filename => $printedPlate) {
+ $archive->addFromString($filename, $printedPlate);
+ }
+ $archive->close();
+
+ $content = file_get_contents($tmpFilename);
+ if (!$content) {
+ throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Failed to read zip archive');
+ }
+
+ unlink($tmpFilename);
+
+ return new Response($content, 200, ['Content-Type' => 'application/zip']);
+ }
+}
diff --git a/src/Controller/IntegrationModuleCallbackController.php b/src/Controller/IntegrationModuleCallbackController.php
new file mode 100644
index 0000000..a0bba1b
--- /dev/null
+++ b/src/Controller/IntegrationModuleCallbackController.php
@@ -0,0 +1,58 @@
+decoder = $decoder;
+ $this->accountManager = $accountManager;
+ }
+
+ public function onActivity(Request $request, Account $account): JsonResponse
+ {
+ $activity = $request->request->get('activity');
+ if (empty($activity)) {
+ throw new BadRequestHttpException('Parameter "activity" is required');
+ }
+
+ try {
+ $decodedActivity = $this->decoder->decode($activity, self::DATA_FORMAT);
+ } catch (SerializerException $e) {
+ throw new BadRequestHttpException($e->getMessage(), $e);
+ }
+
+ $systemUrl = $request->request->get('systemUrl');
+ if (empty($systemUrl)) {
+ throw new BadRequestHttpException('Parameter "systemUrl" is required');
+ }
+
+ $account
+ ->setActive((bool) $decodedActivity['active'])
+ ->setFrozen((bool) $decodedActivity['freeze'])
+ ->setCrmUrl($systemUrl)
+ ;
+
+ $this->accountManager->saveAccount($account);
+
+ return $this->json(['success' => true]);
+ }
+}
diff --git a/src/DeliveryService/DeliveryAdapterInterface.php b/src/DeliveryService/DeliveryAdapterInterface.php
new file mode 100644
index 0000000..84c3e78
--- /dev/null
+++ b/src/DeliveryService/DeliveryAdapterInterface.php
@@ -0,0 +1,14 @@
+retryAfter = $retryAfter;
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getRetryAfter(): int
+ {
+ return $this->retryAfter;
+ }
+}
diff --git a/src/DeliveryService/Exception/ExceptionInterface.php b/src/DeliveryService/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..ea4339a
--- /dev/null
+++ b/src/DeliveryService/Exception/ExceptionInterface.php
@@ -0,0 +1,7 @@
+getRootNode();
+
+ $rootNode
+ ->children()
+ ->scalarNode('db_driver')
+ ->cannotBeEmpty()
+ ->cannotBeOverwritten()
+ ->validate()
+ ->ifNotInArray(self::AVAILABLE_DRIVERS)
+ ->thenInvalid('The driver %s is not supported. Please choose one of ' . json_encode(self::AVAILABLE_DRIVERS))
+ ->end()
+ ->end()
+
+ ->arrayNode('model')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->scalarNode('account_class')->isRequired()->cannotBeEmpty()->end()
+ ->scalarNode('delivery_class')->isRequired()->cannotBeEmpty()->end()
+ ->end()
+ ->end()
+
+ ->booleanNode('use_tracking')->defaultValue(true)->end()
+
+ ->arrayNode('service')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->arrayNode('manager')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->scalarNode('account')
+ ->defaultValue('retail_crm_delivery_module.manager.account.default')
+ ->end()
+ ->scalarNode('delivery')
+ ->defaultValue('retail_crm_delivery_module.manager.delivery.default')
+ ->end()
+ ->end()
+ ->end()
+
+ ->scalarNode('tracker')
+ ->defaultValue('retail_crm_delivery_module.tracker.default')
+ ->end()
+ ->end()
+ ->end()
+
+ ->arrayNode('integration_module')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->scalarNode('factory')->isRequired()->cannotBeEmpty()->end()
+
+ ->arrayNode('configuration')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->scalarNode('integration_code')->isRequired()->cannotBeEmpty()->end()
+
+ ->arrayNode('locales')
+ ->arrayPrototype()
+ ->children()
+ ->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
+ ->scalarNode('logo')->isRequired()->cannotBeEmpty()->end()
+ ->end()
+ ->end()
+ ->requiresAtLeastOneElement()
+ ->useAttributeAsKey('locale')
+ ->validate()
+ ->ifTrue(function ($v) {
+ return array_diff(array_keys($v), self::AVAILABLE_LOCALES);
+ })
+ ->thenInvalid('The locales is not valid')
+ ->end()
+ ->end()
+
+ ->arrayNode('countries')
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+
+ ->arrayNode('delivery_service')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->arrayNode('adapter')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->scalarNode('tariff')->cannotBeEmpty()->end()
+ ->scalarNode('delivery')->cannotBeEmpty()->end()
+ ->scalarNode('shipment')->cannotBeEmpty()->end()
+ ->scalarNode('plate')->cannotBeEmpty()->end()
+ ->scalarNode('status')->cannotBeEmpty()->end()
+ ->end()
+ ->end()
+
+ ->variableNode('parameters')->end()
+ ->end()
+ ->end()
+ ->end()
+
+ ->validate()
+ ->ifTrue(function ($v) {
+ return 'custom' === $v['db_driver'] && 'retail_crm_delivery_module.manager.account.default' === $v['service']['manager']['account'];
+ })
+ ->thenInvalid('You need to specify your own account manager service when using the "custom" driver')
+ ->end()
+
+ ->validate()
+ ->ifTrue(function ($v) {
+ return 'custom' === $v['db_driver'] && 'retail_crm_delivery_module.manager.delivery.default' === $v['service']['manager']['delivery'];
+ })
+ ->thenInvalid('You need to specify your own delivery manager service when using the "custom" driver')
+ ->end()
+ ;
+
+ return $treeBuilder;
+ }
+}
diff --git a/src/DependencyInjection/RetailCrmDeliveryModuleExtension.php b/src/DependencyInjection/RetailCrmDeliveryModuleExtension.php
new file mode 100644
index 0000000..53f7409
--- /dev/null
+++ b/src/DependencyInjection/RetailCrmDeliveryModuleExtension.php
@@ -0,0 +1,92 @@
+processConfiguration($configuration, $configs);
+
+ $loader = new XmlFileLoader($container, new FileLocator(dirname(__DIR__) . '/Resources/config'));
+
+ if ('custom' !== $config['db_driver']) {
+ $loader->load(sprintf('%s.xml', $config['db_driver']));
+ }
+
+ foreach (self::SERVICES as $service) {
+ $loader->load(sprintf('%s.xml', $service));
+ }
+
+ // Models
+ $container->setParameter('retail_crm_delivery_module.model.account.class', $config['model']['account_class']);
+ $container->setParameter('retail_crm_delivery_module.model.delivery.class', $config['model']['delivery_class']);
+
+ // Services
+ $container->setAlias('retail_crm_delivery_module.manager.account', $config['service']['manager']['account']);
+ $container->getAlias('retail_crm_delivery_module.manager.account')->setPublic(true);
+
+ $container->setAlias('retail_crm_delivery_module.manager.delivery', $config['service']['manager']['delivery']);
+ $container->getAlias('retail_crm_delivery_module.manager.delivery')->setPublic(true);
+
+ if ($config['use_tracking']) {
+ $loader->load('tracker.xml');
+
+ $container->setAlias('retail_crm_delivery_module.tracker', $config['service']['tracker']);
+ $container->getAlias('retail_crm_delivery_module.tracker')->setPublic(true);
+ } else {
+ $container->removeDefinition('retail_crm_delivery_module.command.tacking');
+ }
+
+ // Integration module
+ $container->setAlias('retail_crm_delivery_module.integration_module.factory', $config['integration_module']['factory']);
+ $container->getAlias('retail_crm_delivery_module.integration_module.factory')->setPublic(true);
+
+ $container->setParameter('retail_crm_delivery_module.integration_module.configuration', $config['integration_module']['configuration']);
+
+ // Delivery service
+ if (isset($config['delivery_service']['adapter']['tariff'])) {
+ $container->setAlias('retail_crm_delivery_module.delivery_service.adapter.tariff', $config['delivery_service']['adapter']['tariff']);
+ $container->getAlias('retail_crm_delivery_module.delivery_service.adapter.tariff')->setPublic(true);
+ }
+
+ if (isset($config['delivery_service']['adapter']['delivery'])) {
+ $container->setAlias('retail_crm_delivery_module.delivery_service.adapter.delivery', $config['delivery_service']['adapter']['delivery']);
+ $container->getAlias('retail_crm_delivery_module.delivery_service.adapter.delivery')->setPublic(true);
+ }
+
+ if (isset($config['delivery_service']['adapter']['shipment'])) {
+ $container->setAlias('retail_crm_delivery_module.delivery_service.adapter.shipment', $config['delivery_service']['adapter']['shipment']);
+ $container->getAlias('retail_crm_delivery_module.delivery_service.adapter.shipment')->setPublic(true);
+ }
+
+ if (isset($config['delivery_service']['adapter']['plate'])) {
+ $container->setAlias('retail_crm_delivery_module.delivery_service.adapter.plate', $config['delivery_service']['adapter']['plate']);
+ $container->getAlias('retail_crm_delivery_module.delivery_service.adapter.plate')->setPublic(true);
+ }
+
+ if (isset($config['delivery_service']['adapter']['status'])) {
+ $container->setAlias('retail_crm_delivery_module.delivery_service.adapter.status', $config['delivery_service']['adapter']['status']);
+ $container->getAlias('retail_crm_delivery_module.delivery_service.adapter.status')->setPublic(true);
+ }
+
+ $container->setParameter('retail_crm_delivery_module.delivery_service.parameters', $config['delivery_service']['parameters']);
+ }
+}
diff --git a/src/Entity/Account.php b/src/Entity/Account.php
new file mode 100644
index 0000000..99f117a
--- /dev/null
+++ b/src/Entity/Account.php
@@ -0,0 +1,9 @@
+entityManager = $entityManager;
+ $this->class = $class;
+ }
+
+ public function getClass(): string
+ {
+ return $this->class;
+ }
+
+ public function findAccountBy(array $criteria): ?object
+ {
+ return $this->getRepository()->findOneBy($criteria);
+ }
+
+ public function findAccountById(int $id): ?object
+ {
+ return $this->findAccountBy(['id' => $id]);
+ }
+
+ public function findAccountByClientId(string $clientId): ?object
+ {
+ return $this->findAccountBy(['clientId' => $clientId]);
+ }
+
+ public function findActiveAccountById(int $id): ?object
+ {
+ return $this->findAccountBy(['id' => $id, 'active' => true, 'freeze' => false]);
+ }
+
+ public function findActiveAccountByClientId(string $clientId): ?object
+ {
+ return $this->findAccountBy(['clientId' => $clientId, 'active' => true, 'freeze' => false]);
+ }
+
+ public function findActiveAccounts(): \Generator
+ {
+ $queryBuilder = $this->entityManager->createQueryBuilder();
+
+ $query = $queryBuilder
+ ->select('account')
+ ->from(Account::class, 'account')
+ ->andWhere('account.active = true')
+ ->andWhere('account.freeze = false')
+ ->andWhere('account.id > :lastId')
+ ->addOrderBy('account.id')
+ ->setMaxResults(self::QUERY_MAX_RESULTS)
+ ->getQuery()
+ ;
+
+ $lastId = 0;
+ while (true) {
+ $query->setParameter('lastId', $lastId);
+
+ $result = $query->getResult();
+ if (empty($result)) {
+ yield from [];
+
+ break;
+ }
+
+ /** @var Account $item */
+ foreach ($result as $item) {
+ $lastId = $item->getId();
+
+ yield $item;
+ }
+
+ $this->entityManager->clear();
+ }
+ }
+
+ public function saveAccount(BaseAccount $account): void
+ {
+ $this->entityManager->persist($account);
+ $this->entityManager->flush();
+ }
+
+ protected function getRepository(): ObjectRepository
+ {
+ return $this->entityManager->getRepository($this->getClass());
+ }
+}
diff --git a/src/Entity/Delivery.php b/src/Entity/Delivery.php
new file mode 100644
index 0000000..60b4554
--- /dev/null
+++ b/src/Entity/Delivery.php
@@ -0,0 +1,9 @@
+entityManager = $entityManager;
+ $this->class = $class;
+ }
+
+ public function getClass(): string
+ {
+ return $this->class;
+ }
+
+ public function findDeliveryBy(array $criteria): ?object
+ {
+ return $this->getRepository()->findOneBy($criteria);
+ }
+
+ public function findDeliveryById(int $id): ?object
+ {
+ return $this->findDeliveryBy(['id' => $id]);
+ }
+
+ public function findDeliveryByExternalId(string $externalId): ?object
+ {
+ return $this->findDeliveryBy(['externalId' => $externalId]);
+ }
+
+ public function findActiveDeliveriesByAccount(BaseAccount $account): \Generator
+ {
+ $query = $this->entityManager->createQueryBuilder()
+ ->select('delivery')
+ ->from(Delivery::class, 'delivery')
+ ->andWhere('delivery.ended = FALSE')
+ ->andWhere('delivery.account = :account')
+ ->andWhere('delivery.id > :lastId')
+ ->orderBy('delivery.id ASC')
+ ->setMaxResults(self::QUERY_MAX_RESULTS)
+ ->getQuery()
+ ;
+
+ $query->setParameter('account', $account);
+
+ $lastId = 0;
+ while (true) {
+ $query->setParameter('lastId', $lastId);
+
+ $result = $query->getResult();
+ if (empty($result)) {
+ yield from [];
+
+ break;
+ }
+
+ /** @var Delivery $item */
+ foreach ($result as $item) {
+ $lastId = $item->getId();
+
+ yield $item;
+ }
+
+ $this->entityManager->clear();
+ }
+ }
+
+ public function saveDelivery(BaseDelivery $delivery): void
+ {
+ $this->entityManager->persist($delivery);
+ $this->entityManager->flush();
+ }
+
+ public function removeDelivery(BaseDelivery $delivery): void
+ {
+ $this->entityManager->remove($delivery);
+ $this->entityManager->flush();
+ }
+
+ protected function getRepository(): ObjectRepository
+ {
+ return $this->entityManager->getRepository($this->getClass());
+ }
+}
diff --git a/src/Integration/ApiGatewayExceptionInterface.php b/src/Integration/ApiGatewayExceptionInterface.php
new file mode 100644
index 0000000..8b762bd
--- /dev/null
+++ b/src/Integration/ApiGatewayExceptionInterface.php
@@ -0,0 +1,8 @@
+ [
+ 'api' => [
+ 'version' => 'v5',
+ ],
+ ],
+ ];
+
+ /** @var ClientInterface */
+ private $client;
+
+ public function __construct(ClientInterface $client)
+ {
+ $this->client = $client;
+ }
+
+ public function getCredentials(Account $account): array
+ {
+ $response = $this->request($account, 'GET', 'credentials', ['extra' => ['api' => ['version' => false]]]);
+
+ return $response['credentials'] ?? [];
+ }
+
+ public function getPaymentTypes(Account $account): array
+ {
+ $response = $this->request($account, 'GET', 'reference/payment-types');
+
+ return $response['paymentTypes'] ?? [];
+ }
+
+ public function getSites(Account $account): array
+ {
+ $response = $this->request($account, 'GET', 'reference/sites');
+
+ return $response['sites'] ?? [];
+ }
+
+ public function getStatuses(Account $account): array
+ {
+ $response = $this->request($account, 'GET', 'reference/statuses');
+
+ return $response['statuses'] ?? [];
+ }
+
+ public function getStores(Account $account): array
+ {
+ $response = $this->request($account, 'GET', 'reference/stores');
+
+ return $response['stores'] ?? [];
+ }
+
+ public function updateIntegrationModule(Account $account, array $integrationModule): void
+ {
+ if (empty($integrationModule['code'])) {
+ throw new \LogicException('Parameter "code" is required');
+ }
+
+ $endpoint = sprintf('integration-modules/%s/edit', $integrationModule['code']);
+
+ $options = [
+ 'form_params' => [
+ 'integrationModule' => json_encode($integrationModule),
+ ],
+ ];
+
+ $this->request($account, 'POST', $endpoint, $options);
+ }
+
+ public function updateDeliveryStatuses(Account $account, string $integrationCode, array $statuses): void
+ {
+ if (empty($integrationCode)) {
+ throw new \LogicException('Parameter "integrationCode" is required');
+ }
+
+ $endpoint = sprintf('delivery/generic/%s/tracking', $integrationCode);
+
+ $options = [
+ 'form_params' => [
+ 'statusUpdate' => json_encode($statuses),
+ ],
+ ];
+
+ $this->request($account, 'POST', $endpoint, $options);
+ }
+
+ public function request(Account $account, string $method, string $endpoint, array $options = []): array
+ {
+ $options = array_merge_recursive(
+ static::$defaultOptions,
+ [
+ 'extra' => [
+ 'service_code' => static::getCode(),
+ 'account_id' => $account->getId(),
+ 'client_id' => $account->getClientId(),
+ 'debug' => $account->isDebug(),
+ ],
+ ],
+ $options
+ );
+
+ switch (strtoupper($method)) {
+ case 'GET':
+ $options['query']['apiKey'] = $account->getCrmApiKey();
+
+ break;
+
+ case 'POST':
+ $options['form_params']['apiKey'] = $account->getCrmApiKey();
+
+ break;
+ }
+
+ $uri = $this->buildUri($account, $endpoint, $options);
+
+ try {
+ $response = $this->client->request($method, $uri, $options);
+ } catch (GuzzleClientException $e) {
+ $response = $e->getResponse();
+
+ if (403 === $response->getStatusCode()) {
+ throw new ForbiddenException($e->getMessage(), $e);
+ }
+ } catch (GuzzleServerException $e) {
+ $response = $e->getResponse();
+
+ if (503 === $response->getStatusCode()) {
+ throw new LimitException($e->getMessage(), $e);
+ }
+ } catch (GuzzleHttpException $e) {
+ throw new HttpException($e->getMessage(), $e);
+ }
+
+ $body = json_decode($response->getBody(), true);
+ if (!($body['success'] ?? false)) {
+ throw new ApiGatewayException(
+ $body['errorMsg'] ?? 'An error has occurred while processing your request',
+ $body['errors'] ?? []
+ );
+ }
+
+ return $body;
+ }
+
+ private function buildUri(Account $account, string $endpoint, array $options = []): string
+ {
+ $baseUrl = sprintf('%s/api', $account->getCrmUrl());
+ if ($options['extra']['api']['version'] ?? false) {
+ $baseUrl .= sprintf('/%s', $options['extra']['api']['version']);
+ }
+
+ return sprintf('%s/%s', $baseUrl, $endpoint);
+ }
+}
diff --git a/src/Integration/Crm/ApiGatewayInterface.php b/src/Integration/Crm/ApiGatewayInterface.php
new file mode 100644
index 0000000..9954764
--- /dev/null
+++ b/src/Integration/Crm/ApiGatewayInterface.php
@@ -0,0 +1,25 @@
+errors = $errors;
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getErrors(): array
+ {
+ return $this->errors;
+ }
+}
diff --git a/src/Integration/Crm/Exception/ExceptionInterface.php b/src/Integration/Crm/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..d82424c
--- /dev/null
+++ b/src/Integration/Crm/Exception/ExceptionInterface.php
@@ -0,0 +1,7 @@
+configuration = $configuration;
+ }
+
+ public function createIntegrationModule(Account $account): array
+ {
+ return [
+ 'code' => sprintf('%s-%s', $this->configuration['integration_code'], $account->getId()),
+ 'integrationCode' => $this->configuration['integration_code'],
+ 'active' => $account->isActive(),
+ 'freeze' => $account->isFrozen(),
+ 'name' => $this->configuration['locales'][$account->getLanguage()]['name'],
+ 'logo' => $this->configuration['locales'][$account->getLanguage()]['logo'],
+ 'clientId' => $account->getClientId(),
+ 'baseUrl' => $this->getBaseUrl(),
+ 'actions' => [
+ 'activity' => 'integration-module/activity',
+ ],
+ 'availableCountries' => $this->configuration['countries'],
+ 'accountUrl' => $this->getAccountUrl(),
+ 'integrations' => [
+ 'delivery' => $this->getDeliveryConfiguration($account),
+ ],
+ ];
+ }
+
+ abstract protected function getBaseUrl(): string;
+
+ abstract protected function getAccountUrl(): string;
+
+ abstract protected function getDeliveryConfiguration(Account $account): array;
+}
diff --git a/src/IntegrationModule/IntegrationModuleFactoryInterface.php b/src/IntegrationModule/IntegrationModuleFactoryInterface.php
new file mode 100644
index 0000000..e4d1aa2
--- /dev/null
+++ b/src/IntegrationModule/IntegrationModuleFactoryInterface.php
@@ -0,0 +1,10 @@
+clientId = uuid_create(UUID_TYPE_RANDOM);
+ $this->active = true;
+ $this->frozen = false;
+ $this->debug = false;
+ $this->defaultPayerType = 'sender';
+ $this->costCalculateBy = 'auto';
+ $this->nullDeclaredValue = false;
+ $this->lockedByDefault = false;
+ $this->deliveryExtraData = [];
+ $this->shipmentExtraData = [];
+ $this->createdAt = new \DateTime();
+ }
+
+ public function getId(): ?int
+ {
+ return $this->id;
+ }
+
+ public function getCrmUrl(): ?string
+ {
+ return $this->crmUrl;
+ }
+
+ public function setCrmUrl(string $crmUrl): self
+ {
+ $this->crmUrl = rtrim($crmUrl, '/');
+
+ return $this;
+ }
+
+ public function getCrmApiKey(): ?string
+ {
+ return $this->crmApiKey;
+ }
+
+ public function setCrmApiKey(string $crmApiKey): self
+ {
+ $this->crmApiKey = $crmApiKey;
+
+ return $this;
+ }
+
+ public function getClientId(): ?string
+ {
+ return $this->clientId;
+ }
+
+ public function setClientId(string $clientId): self
+ {
+ $this->clientId = $clientId;
+
+ return $this;
+ }
+
+ public function getLanguage(): ?string
+ {
+ return $this->language;
+ }
+
+ public function setLanguage(string $language): self
+ {
+ $this->language = $language;
+
+ return $this;
+ }
+
+ public function isActive(): bool
+ {
+ return $this->active;
+ }
+
+ public function setActive(bool $active): self
+ {
+ $this->active = $active;
+
+ return $this;
+ }
+
+ public function isFrozen(): bool
+ {
+ return $this->frozen;
+ }
+
+ public function setFrozen(bool $frozen): self
+ {
+ $this->frozen = $frozen;
+
+ return $this;
+ }
+
+ public function isEnabled(): bool
+ {
+ return !$this->frozen && $this->active;
+ }
+
+ public function isDebug(): bool
+ {
+ return $this->debug;
+ }
+
+ public function setDebug(bool $debug): self
+ {
+ $this->debug = $debug;
+
+ return $this;
+ }
+
+ public function getDefaultPayerType(): string
+ {
+ return $this->defaultPayerType;
+ }
+
+ public function setDefaultPayerType(string $defaultPayerType): self
+ {
+ $this->defaultPayerType = $defaultPayerType;
+
+ return $this;
+ }
+
+ public function getCostCalculateBy(): string
+ {
+ return $this->costCalculateBy;
+ }
+
+ public function setCostCalculateBy(string $costCalculateBy): self
+ {
+ $this->costCalculateBy = $costCalculateBy;
+
+ return $this;
+ }
+
+ public function isNullDeclaredValue(): bool
+ {
+ return $this->nullDeclaredValue;
+ }
+
+ public function setNullDeclaredValue(bool $nullDeclaredValue): self
+ {
+ $this->nullDeclaredValue = $nullDeclaredValue;
+
+ return $this;
+ }
+
+ public function isLockedByDefault(): bool
+ {
+ return $this->lockedByDefault;
+ }
+
+ public function setLockedByDefault(bool $lockedByDefault): self
+ {
+ $this->lockedByDefault = $lockedByDefault;
+
+ return $this;
+ }
+
+ public function getDeliveryExtraData(): array
+ {
+ return $this->deliveryExtraData;
+ }
+
+ public function setDeliveryExtraData(array $deliveryExtraData): self
+ {
+ $this->deliveryExtraData = $deliveryExtraData;
+
+ return $this;
+ }
+
+ public function getShipmentExtraData(): array
+ {
+ return $this->shipmentExtraData;
+ }
+
+ public function setShipmentExtraData(array $shipmentExtraData): self
+ {
+ $this->shipmentExtraData = $shipmentExtraData;
+
+ return $this;
+ }
+
+ public function getTrackedAt(): ?\DateTime
+ {
+ return $this->trackedAt;
+ }
+
+ public function setTrackedAt(\DateTime $trackedAt): self
+ {
+ $this->trackedAt = $trackedAt;
+
+ return $this;
+ }
+
+ public function getCreatedAt(): \DateTime
+ {
+ return $this->createdAt;
+ }
+}
diff --git a/src/Model/AccountManager.php b/src/Model/AccountManager.php
new file mode 100644
index 0000000..6c34c05
--- /dev/null
+++ b/src/Model/AccountManager.php
@@ -0,0 +1,13 @@
+getClass();
+
+ return new $class();
+ }
+}
diff --git a/src/Model/AccountManagerInterface.php b/src/Model/AccountManagerInterface.php
new file mode 100644
index 0000000..fe56f73
--- /dev/null
+++ b/src/Model/AccountManagerInterface.php
@@ -0,0 +1,24 @@
+account = $account;
$this->ended = false;
+ $this->createdAt = new \DateTime();
}
- /**
- * @return int
- */
- public function getId()
+ public function getId(): ?int
{
return $this->id;
}
+ public function getAccount(): Account
+ {
+ return $this->account;
+ }
+
public function setAccount(Account $account): self
{
$this->account = $account;
@@ -49,9 +49,9 @@ abstract class DeliveryOrder
return $this;
}
- public function getAccount(): ?Account
+ public function getOrderId(): ?int
{
- return $this->account;
+ return $this->orderId;
}
public function setOrderId(int $orderId): self
@@ -61,9 +61,9 @@ abstract class DeliveryOrder
return $this;
}
- public function getOrderId(): int
+ public function getExternalId(): ?string
{
- return $this->orderId;
+ return $this->externalId;
}
public function setExternalId(string $externalId): self
@@ -73,9 +73,21 @@ abstract class DeliveryOrder
return $this;
}
- public function getExternalId(): string
+ public function getTrackNumber(): ?string
{
- return $this->externalId;
+ return $this->trackNumber;
+ }
+
+ public function setTrackNumber(string $trackNumber): self
+ {
+ $this->trackNumber = $trackNumber;
+
+ return $this;
+ }
+
+ public function isEnded(): bool
+ {
+ return $this->ended;
}
public function setEnded(bool $ended): self
@@ -85,18 +97,8 @@ abstract class DeliveryOrder
return $this;
}
- public function getTrackNumber(): string
+ public function getCreatedAt(): \DateTime
{
- return $this->externalId;
- }
-
- public function setTrackNumber(string $trackNumber): self
- {
- return $this;
- }
-
- public function getEnded(): bool
- {
- return $this->ended;
+ return $this->createdAt;
}
}
diff --git a/src/Model/DeliveryManager.php b/src/Model/DeliveryManager.php
new file mode 100644
index 0000000..6cc19f9
--- /dev/null
+++ b/src/Model/DeliveryManager.php
@@ -0,0 +1,13 @@
+getClass();
+
+ return new $class($account);
+ }
+}
diff --git a/src/Model/DeliveryManagerInterface.php b/src/Model/DeliveryManagerInterface.php
new file mode 100644
index 0000000..ca774b6
--- /dev/null
+++ b/src/Model/DeliveryManagerInterface.php
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/controllers.xml b/src/Resources/config/controllers.xml
new file mode 100644
index 0000000..a0aa4e9
--- /dev/null
+++ b/src/Resources/config/controllers.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/doctrine/Account.orm.xml b/src/Resources/config/doctrine/Account.orm.xml
new file mode 100644
index 0000000..9ba73a5
--- /dev/null
+++ b/src/Resources/config/doctrine/Account.orm.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/doctrine/Delivery.orm.xml b/src/Resources/config/doctrine/Delivery.orm.xml
new file mode 100644
index 0000000..95576be
--- /dev/null
+++ b/src/Resources/config/doctrine/Delivery.orm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/integrations.xml b/src/Resources/config/integrations.xml
new file mode 100644
index 0000000..9166769
--- /dev/null
+++ b/src/Resources/config/integrations.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/orm.xml b/src/Resources/config/orm.xml
new file mode 100644
index 0000000..81e0594
--- /dev/null
+++ b/src/Resources/config/orm.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ RetailCrm\DeliveryModuleBundle\Entity\Account
+ RetailCrm\DeliveryModuleBundle\Entity\Delivery
+
+
+
+
+
+ %retail_crm_delivery_module.model.account.class%
+
+
+
+
+
+ %retail_crm_delivery_module.model.delivery.class%
+
+
+
+
+
diff --git a/src/Resources/config/routing/delivery_callback.xml b/src/Resources/config/routing/delivery_callback.xml
new file mode 100644
index 0000000..792cb54
--- /dev/null
+++ b/src/Resources/config/routing/delivery_callback.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onTariffList
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onCalculate
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onSave
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onGet
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onDelete
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onShipmentPointList
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onShipmentSave
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onShipmentDelete
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\DeliveryCallbackController::onPrint
+
+
+
diff --git a/src/Resources/config/routing/integration_module_callback.xml b/src/Resources/config/routing/integration_module_callback.xml
new file mode 100644
index 0000000..e0455f3
--- /dev/null
+++ b/src/Resources/config/routing/integration_module_callback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ RetailCrm\DeliveryModuleBundle\Controller\IntegrationModuleCallbackController::onActivity
+
+
+
diff --git a/src/Resources/config/serializers.xml b/src/Resources/config/serializers.xml
new file mode 100644
index 0000000..52b2006
--- /dev/null
+++ b/src/Resources/config/serializers.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/tracker.xml b/src/Resources/config/tracker.xml
new file mode 100644
index 0000000..1442403
--- /dev/null
+++ b/src/Resources/config/tracker.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/config/validators.xml b/src/Resources/config/validators.xml
new file mode 100644
index 0000000..0612d28
--- /dev/null
+++ b/src/Resources/config/validators.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/translations/validators.en.yml b/src/Resources/translations/validators.en.yml
new file mode 100644
index 0000000..01b8686
--- /dev/null
+++ b/src/Resources/translations/validators.en.yml
@@ -0,0 +1,6 @@
+crm_access:
+ access_denied: 'Access to the method "%method%" is denied'
+ forbidden_exception: 'Wrong API key'
+ limit_exception: 'Service is temporarily unavailable'
+ http_exception: 'Failed to connect to API'
+ api_gateway_exception: 'An error has occurred while processing your request'
diff --git a/src/Resources/translations/validators.es.yml b/src/Resources/translations/validators.es.yml
new file mode 100644
index 0000000..ef52aa6
--- /dev/null
+++ b/src/Resources/translations/validators.es.yml
@@ -0,0 +1,6 @@
+crm_access:
+ access_denied: 'Acceso al método "%method%" está prohibido'
+ forbidden_exception: 'Clave API incorrecta'
+ limit_exception: 'Servicio no está disponible temporalmente'
+ http_exception: 'No se ha podido conectar al API'
+ api_gateway_exception: 'Ha ocurrido un error al procesar tu solicitud'
diff --git a/src/Resources/translations/validators.ru.yml b/src/Resources/translations/validators.ru.yml
new file mode 100644
index 0000000..7af3cbf
--- /dev/null
+++ b/src/Resources/translations/validators.ru.yml
@@ -0,0 +1,7 @@
+crm_access:
+ access_denied: 'Доступ к методу "%method%" запрещен'
+ forbidden_exception: 'Неверный API-ключ'
+ limit_exception: 'Сервис временно недоступен'
+ http_exception: 'Не удалось подключиться к API'
+ api_gateway_exception: 'Возникла ошибка при обработке запроса'
+
diff --git a/RetailCrmDeliveryModuleBundle.php b/src/RetailCrmDeliveryModuleBundle.php
similarity index 100%
rename from RetailCrmDeliveryModuleBundle.php
rename to src/RetailCrmDeliveryModuleBundle.php
diff --git a/src/Tracking/Tracker.php b/src/Tracking/Tracker.php
new file mode 100644
index 0000000..1ed86b9
--- /dev/null
+++ b/src/Tracking/Tracker.php
@@ -0,0 +1,80 @@
+accountManager = $accountManager;
+ $this->deliveryManager = $deliveryManager;
+ $this->statusAdapter = $statusAdapter;
+ $this->integrationModuleFactory = $integrationModuleFactory;
+ $this->crmApiGateway = $crmApiGateway;
+ }
+
+ public function tracking(Account $account): void
+ {
+ $deliveries = $this->deliveryManager->findActiveDeliveriesByAccount($account);
+
+ $statuses = [];
+ foreach ($deliveries as $delivery) {
+ $statuses[] = $this->statusAdapter->getStatus($delivery);
+
+ if (0 === count($statuses) % self::LIMIT) {
+ $this->updateDeliveryStatuses($account, $statuses);
+
+ $statuses = [];
+ }
+ }
+
+ if (count($statuses) > 0) {
+ $this->updateDeliveryStatuses($account, $statuses);
+ }
+
+ $account->setTrackedAt(new \DateTime());
+
+ $this->accountManager->saveAccount($account);
+ }
+
+ protected function updateDeliveryStatuses(Account $account, array $statuses): void
+ {
+ $integrationModule = $this->integrationModuleFactory->createIntegrationModule($account);
+
+ $integrationCode = $integrationModule['integrationCode'] ?? null;
+ if (null === $integrationCode) {
+ throw new \LogicException('Parameter "integrationCode" is required');
+ }
+
+ $this->crmApiGateway->updateDeliveryStatuses($account, $integrationCode, $statuses);
+ }
+}
diff --git a/src/Tracking/TrackerInterface.php b/src/Tracking/TrackerInterface.php
new file mode 100644
index 0000000..4512075
--- /dev/null
+++ b/src/Tracking/TrackerInterface.php
@@ -0,0 +1,10 @@
+crmApiGateway = $crmApiGateway;
+ }
+
+ public function validate($account, Constraint $constraint): void
+ {
+ if (!($account instanceof Account)) {
+ throw new UnexpectedTypeException($account, Account::class);
+ }
+
+ if (!($constraint instanceof CrmAccess)) {
+ throw new UnexpectedTypeException($constraint, CrmAccess::class);
+ }
+
+ try {
+ $credentials = $this->crmApiGateway->getCredentials($account);
+
+ foreach ($constraint->requiredApiMethods as $method) {
+ if (!in_array($method, $credentials)) {
+ $this->context
+ ->buildViolation('retail_crm_access.access_denied', ['%method%' => $method])
+ ->atPath('crmApiKey')
+ ->addViolation()
+ ;
+ }
+ }
+ } catch (ForbiddenException $e) {
+ $this->context
+ ->buildViolation('crm_access.forbidden_exception')
+ ->setCause($e->getMessage())
+ ->atPath('crmApiKey')
+ ->addViolation()
+ ;
+ } catch (LimitException $e) {
+ $this->context
+ ->buildViolation('crm_access.limit_exception')
+ ->setCause($e->getMessage())
+ ->atPath('crmUrl')
+ ->addViolation()
+ ;
+ } catch (HttpException $e) {
+ $this->context
+ ->buildViolation('crm_access.http_exception')
+ ->setCause($e->getMessage())
+ ->atPath('crmUrl')
+ ->addViolation()
+ ;
+ } catch (ApiGatewayException $e) {
+ $this->context
+ ->buildViolation('crm_access.api_gateway_exception')
+ ->setCause($e->getMessage())
+ ->atPath('crmUrl')
+ ->addViolation()
+ ;
+ }
+ }
+}
diff --git a/tests/.gitkeep b/tests/.gitkeep
new file mode 100644
index 0000000..e69de29