1
0
mirror of synced 2024-12-05 03:06:02 +03:00
This commit is contained in:
ionHaze 2019-12-26 17:47:33 +03:00 committed by 1on
commit 747456f6f5
103 changed files with 11792 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/*.sublime*
/vendor

View File

@ -0,0 +1,99 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Command;
use Doctrine\ORM\Tools\Pagination\Paginator;
use RetailCrm\DeliveryModuleBundle\Exception\AbstractModuleException;
use RetailCrm\DeliveryModuleBundle\Service\AccountManager;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LockableTrait;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class StatusesCommand extends Command
{
use LockableTrait;
/**
* @var ModuleManagerInterface
*/
private $moduleManager;
/**
* @var AccountManager
*/
private $accountManager;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->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(
"<error>Failed to update statuses for account {$account->getCrmUrl()}[{$account->getId()}]</error>"
);
$output->writeln("<error>Error: {$e->getMessage()}</error>");
}
}
$output->writeln("<info>{$count} statuses updated.</info>");
$this->release();
return 0;
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Command;
use Doctrine\ORM\Tools\Pagination\Paginator;
use RetailCrm\DeliveryModuleBundle\Service\AccountManager;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LockableTrait;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class UpdateModuleCommand extends Command
{
use LockableTrait;
/**
* @var ModuleManagerInterface
*/
private $moduleManager;
/**
* @var AccountManager
*/
private $accountManager;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->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(
"<error>Failed to update configuration for account {$account->getCrmUrl()}[{$account->getId()}]</error>"
);
$output->writeln("<error>Error: {$e->getMessage()}</error>");
}
}
$output->writeln("<info>{$count} modules updated.</info>");
$this->release();
return 0;
}
}

View File

@ -0,0 +1,394 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Controller;
use Doctrine\Common\Persistence\ObjectManager;
use Knp\Component\Pager\PaginatorInterface;
use RetailCrm\DeliveryModuleBundle\Entity\Connection;
use RetailCrm\DeliveryModuleBundle\Service;
use RetailCrm\DeliveryModuleBundle\Service\BaseDelivery;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
abstract class AdminController extends AbstractController
{
/**
* Базовый роут
*
* @return string
*/
abstract protected function getRoute();
/**
* Сервис для работы с апи службы доставки.
*
* @return BaseDelivery
*/
abstract protected function getDeliveryApi();
/**
* @var ObjectManager
*/
protected $entityManager;
/**
* @var PaginatorInterface
*/
protected $knpPaginator;
/**
* @var Service\OpenSsl
*/
protected $openSsl;
/**
* @var FlashBagInterface
*/
protected $flashBag;
/**
* AdminController constructor.
*/
public function __construct(
ObjectManager $entityManager,
PaginatorInterface $knpPaginator,
Service\OpenSsl $openSsl,
FlashBagInterface $flashBag
) {
$this->entityManager = $entityManager;
$this->knpPaginator = $knpPaginator;
$this->openSsl = $openSsl;
$this->flashBag = $flashBag;
}
/**
* @return string
*/
private function getShortBundle()
{
return strtr('Intaro\DeliveryModuleBundle', ['\\' => '']);
}
/**
* @return string
*/
private function getNameService()
{
$bundle = explode('\\', 'Intaro\DeliveryModuleBundle');
return strtr(end($bundle), ['Bundle' => '']);
}
/**
* @return Response
*/
public function listAction(Request $request)
{
$clientsQuery = $this->entityManager->createQuery('
SELECT connection
FROM ' . $this->getConnectionClass() . ' connection
');
$pagination = $this->knpPaginator->paginate(
$clientsQuery,
$request->query->getInt('page', 1),
20
);
return $this->render(
$this->getShortBundle() . ':Connection:list.html.twig',
['pagination' => $pagination, 'route' => $this->getRoute()]
);
}
/**
* @return Response
*/
public function newAction(Request $request)
{
$this->denyAccessUnlessGranted('ROLE_DEVELOPER');
$connectionClass = $this->getConnectionClass();
$connection = new $connectionClass();
$connection->setEncoder($this->openSsl);
$connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType';
$form = $this->createForm($connectionTypeClass, $connection, [
'container' => $this->container,
'is_admin' => true,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$connection->generateClientId();
$this->actualizeWebhooks($connection);
$this->entityManager->persist($connection);
$this->entityManager->flush();
return $this->redirectToRoute($this->getRoute() . '_admin_edit', [
'connectionId' => $connection->getId(),
]);
}
return $this->render(
$this->getShortBundle() . ':Connection:edit.html.twig',
['route' => $this->getRoute(), 'form' => $form->createView()]
);
}
/**
* @param string $connectionId
*
* @return Response
*/
public function editAction(Request $request, $connectionId)
{
$connection = $this->entityManager
->getRepository($this->getConnectionClass())
->find($connectionId);
if (null === $connection) {
throw $this->createNotFoundException();
}
$connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType';
$form = $this->createForm($connectionTypeClass, $connection, [
'container' => $this->container,
'is_admin' => true,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->actualizeWebhooks($connection);
$this->entityManager->flush();
return $this->redirectToRoute($this->getRoute() . '_admin_edit', [
'connectionId' => $connection->getId(),
]);
}
return $this->render(
$this->getShortBundle() . ':Connection:edit.html.twig',
[
'route' => $this->getRoute(),
'connection' => $connection,
'form' => $form->createView(),
]
);
}
/**
* @param string $connectionId
*
* @return Response
*
* @throws \Exception
*/
public function updateConfigurationAction(Request $request, $connectionId)
{
$this->denyAccessUnlessGranted('ROLE_DEVELOPER');
$api = $this->getDeliveryApi();
$connection = $this->entityManager
->getRepository($this->getConnectionClass())
->find($connectionId);
$api->setConnection($connection);
$result = $api->updateConfiguration();
if (isset($result['success']) && $result['success']) {
$this->flashBag->add('notice', 'ChangesWereSaved');
} else {
$this->flashBag->add('error', 'ChangesWereNotSaved');
}
return $this->redirectToRoute($this->getRoute() . '_admin_edit', [
'connectionId' => $connection->getId(),
]);
}
/**
* @return Response
*/
public function parcelListAction(Request $request)
{
$parcelsQuery = $this->entityManager->createQuery('
SELECT parcel
FROM ' . $this->getParcelClass() . ' parcel
');
$pagination = $this->knpPaginator->paginate(
$parcelsQuery,
$request->query->getInt('page', 1),
20
);
return $this->render(
$this->getShortBundle() . ':Parcel:list.html.twig',
['route' => $this->getRoute(), 'pagination' => $pagination]
);
}
/**
* @return Response
*/
public function parcelNewAction(Request $request)
{
$this->denyAccessUnlessGranted('ROLE_DEVELOPER');
$parcelClass = $this->getParcelClass();
$parcel = new $parcelClass();
$parcelTypeClass = 'Intaro\DeliveryModuleBundle\Form\ParcelType';
$form = $this->createForm($parcelTypeClass, $parcel, [
'connection_class' => $this->getConnectionClass(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($parcel);
$this->entityManager->flush();
return $this->redirectToRoute($this->getRoute() . '_admin_parcel_list');
}
return $this->render(
$this->getShortBundle() . ':Parcel:edit.html.twig',
['form' => $form->createView(), 'parcel' => $parcel]
);
}
/**
* @param string $parcelId
*
* @return Response
*/
public function parcelEditAction(Request $request, $parcelId)
{
$parcel = $this->entityManager
->getRepository($this->getParcelClass())
->find(['id' => $parcelId]);
$parcelTypeClass = 'Intaro\DeliveryModuleBundle\Form\ParcelType';
$form = $this->createForm($parcelTypeClass, $parcel, [
'connection_class' => $this->getConnectionClass(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->flush();
return $this->redirectToRoute($this->getRoute() . '_admin_parcel_list');
}
return $this->render(
$this->getShortBundle() . ':Parcel:edit.html.twig',
['form' => $form->createView(), 'parcel' => $parcel]
);
}
/**
* @return Response
*
* @throws \Exception
*/
public function connectAction(Request $request)
{
$api = $this->getDeliveryApi();
$referer = $request->headers->get('referer');
$account = $request->query->get('account');
$accountUrl = null;
if (!empty($account)) {
$accountUrl = null === parse_url($account, PHP_URL_HOST)
? null : 'https://' . parse_url($account, PHP_URL_HOST);
}
if (
!empty($request->request->get('clientId'))
|| !empty($request->attributes->get('clientId'))
) {
if (!empty($request->request->get('clientId'))) {
$clientId = $request->request->get('clientId');
} else {
$clientId = $request->attributes->get('clientId');
}
$connection = $this->entityManager
->getRepository($this->getConnectionClass())
->findOneBy([
'clientId' => $clientId,
]);
$accountUrl = $connection->getCrmUrl();
} else {
$class = $this->getConnectionClass();
$connection = new $class();
$connection
->setLanguage($request->getLocale())
->setEncoder($this->openSsl);
}
$connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType';
$form = $this->createForm($connectionTypeClass, $connection, [
'container' => $this->container,
'is_admin' => false,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$connectionIsCreated = true;
if (empty($connection->getClientId())) {
$connection->generateClientId();
$connectionIsCreated = false;
}
$api->setConnection($connection);
$this->actualizeWebhooks($connection);
$result = $api->updateConfiguration();
if (isset($result['success']) && $result['success']) {
if (!$connectionIsCreated) {
$this->entityManager->persist($connection);
}
$this->entityManager->flush();
return $this->redirect($connection->getCrmUrl() . '/admin/integration/list');
} else {
$srcLogo = $request->getUriForPath(
'/bundles/delivery'
. strtolower($this->getNameService())
. '/images/'
. strtolower($this->getNameService())
. '.svg'
);
return $this->render(
'DeliveryCoreBundle:Connection:configure_error.html.twig',
[
'referer' => $referer,
'errors' => $result,
'title_delivery' => $this->getNameService(),
'src_logo_delivery' => $srcLogo,
]
);
}
}
return $this->render(
$this->getShortBundle() . ':Connection:configure.html.twig',
[
'route' => $this->getRoute(),
'form' => $form->createView(),
'account' => $accountUrl,
]
);
}
/**
* Actualize webhooks.
*/
protected function actualizeWebhooks(Connection $connection)
{
}
}

View File

@ -0,0 +1,462 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Controller;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\Exception\Exception as JmsException;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use RetailCrm\DeliveryModuleBundle\Exception;
use RetailCrm\DeliveryModuleBundle\Model\AbstractResponseSuccessful;
use RetailCrm\DeliveryModuleBundle\Model\Calculate;
use RetailCrm\DeliveryModuleBundle\Model\Entity\DeliveryOrder;
use RetailCrm\DeliveryModuleBundle\Model\IntegrationModule;
use RetailCrm\DeliveryModuleBundle\Model\RequestCalculate;
use RetailCrm\DeliveryModuleBundle\Model\RequestDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestPrint;
use RetailCrm\DeliveryModuleBundle\Model\RequestSave;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentPointList;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseCalculateSuccessful;
use RetailCrm\DeliveryModuleBundle\Model\ResponseLoadDeliveryData;
use RetailCrm\DeliveryModuleBundle\Model\ResponseSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseShipmentPointListSuccessful;
use RetailCrm\DeliveryModuleBundle\Model\ResponseShipmentSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseSuccessful;
use RetailCrm\DeliveryModuleBundle\Service\AccountManager;
use RetailCrm\DeliveryModuleBundle\Service\DeliveryOrderManager;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManager;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception as SymfonyException;
class ApiController extends AbstractController implements ClientIdSecuredControllerInterface
{
/**
* @var SerializerInterface
*/
protected $jmsSerializer;
/**
* @var ModuleManager
*/
protected $moduleManager;
/**
* @var AccountManager
*/
protected $accountManager;
/**
* @var DeliveryOrderManager
*/
protected $deliveryOrderManager;
public function __construct(
SerializerInterface $jmsSerializer,
ModuleManagerInterface $moduleManager,
AccountManager $accountManager,
DeliveryOrderManager $deliveryOrderManager,
RequestStack $requestStack
) {
$this->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);
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Controller;
interface ClientIdSecuredControllerInterface
{
}

View File

@ -0,0 +1,70 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
protected static $availableLocales = ['ru', 'en', 'es'];
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('retail_crm_delivery_module');
$rootNode = $treeBuilder->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;
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\DependencyInjection;
use RetailCrm\DeliveryModuleBundle\Model\Entity\Account;
use RetailCrm\DeliveryModuleBundle\Model\Entity\DeliveryOrder;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class RetailCrmDeliveryModuleExtension extends Extension
{
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader(
$container,
new FileLocator(dirname(__DIR__) . '/Resources/config')
);
$loader->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']
);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\EventListener;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use RetailCrm\DeliveryModuleBundle\Model\ResponseResult;
class SerializeListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
['event' => 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');
}
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\EventSubscriber;
use Ramsey\Uuid\Uuid;
use RetailCrm\DeliveryModuleBundle\Controller\ClientIdSecuredControllerInterface;
use RetailCrm\DeliveryModuleBundle\Service\AccountManager;
use RetailCrm\DeliveryModuleBundle\Service\ModuleManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
class ClientIdSubscriber implements EventSubscriberInterface
{
/**
* @var AccountManager
*/
private $accountManager;
/**
* @var ModuleManagerInterface
*/
private $moduleManager;
public function __construct(AccountManager $accountManager, ModuleManagerInterface $moduleManager)
{
$this->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');
}
if (!$account->isActive()) {
throw new AccessDeniedHttpException('Account is not active');
}
if ($account->isFreeze()) {
throw new AccessDeniedHttpException('Account is freezed');
}
$this->moduleManager->setAccount($account);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\EventSubscriber;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use RetailCrm\DeliveryModuleBundle\Model\ResponseResult;
class SerializeListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
['event' => 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');
}
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Exception;
abstract class AbstractModuleException extends \Exception
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Exception;
class ApiException extends AbstractModuleException
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Exception;
class NotFoundException extends AbstractModuleException
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Exception;
class ServerUnreachableException extends AbstractModuleException
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Exception;
class ValidationException extends AbstractModuleException
{
}

View File

@ -0,0 +1,36 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ConfigureEditType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*
* @return void
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('connectionId', null, [
'label' => 'label.connectionId',
'required' => true,
'attr' => [
'placeholder' => 'label.connectionId'
]
])
->add('crmKey', null, [
'label' => 'label.crmKey',
'required' => true,
'attr' => [
'placeholder' => 'label.crmKey'
]
]);
}
}

78
Form/ConnectionType.php Normal file
View File

@ -0,0 +1,78 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ConnectionType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*
* @return void
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('crmUrl', TextType::class, [
'label' => 'label.crmUrl',
'required' => true,
'attr' => [
'placeholder' => 'label.crmUrl',
'pattern' => '^(https?:\/\/)?([\da-z0-9\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$',
],
'translation_domain' => 'messages'
])
->add('crmKey', TextType::class, [
'label' => 'label.crmKey',
'required' => true,
'attr' => [
'placeholder' => 'label.crmKey'
],
'translation_domain' => 'messages'
])
->add('isActive', CheckboxType::class, [
'label' => 'label.isActive',
'required' => false,
'translation_domain' => 'messages'
])
->add('language', ChoiceType::class, [
'label' => 'label.language',
'choices' => [
'RU' => 'ru',
'EN' => 'en',
'ES' => 'es'
],
'required' => true,
'translation_domain' => 'messages'
])
->add('isFreeze', CheckboxType::class, [
'label' => 'label.isFreeze',
'required' => false,
'translation_domain' => 'messages'
]);
if ($options['is_admin']) {
$builder
->add('debug', CheckboxType::class, [
'label' => 'label.debug',
'required' => false,
'translation_domain' => 'messages'
]);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['container', 'is_admin']);
}
}

63
Form/ParcelType.php Normal file
View File

@ -0,0 +1,63 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Form;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
abstract class ParcelType extends AbstractType
{
/**
* {@inheritDoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'connection',
EntityType::class,
[
'class' => $options['connection_class'],
'label' => 'label.connection',
'translation_domain' => 'messages'
]
)
->add(
'orderId',
TextType::class,
[
'label' => 'label.orderId',
'translation_domain' => 'messages'
]
)
->add(
'trackId',
TextType::class,
[
'label' => 'label.trackId',
'translation_domain' => 'messages'
]
)
->add(
'isClosed',
CheckboxType::class,
[
'required' => false,
'label' => 'label.isClosed',
'translation_domain' => 'messages'
]
);
}
/**
* {@inheritDoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['connection_class']);
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
abstract class AbstractResponseSuccessful
{
/**
* @var bool
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("success")
* @Serializer\Type("boolean")
*/
public $success = true;
}

185
Model/Configuration.php Normal file
View File

@ -0,0 +1,185 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Configuration
{
const PAYER_TYPE_RECEIVER = 'receiver';
const PAYER_TYPE_SENDER = 'sender';
const ACTION_CALCULATE = 'calculate';
const ACTION_SAVE = 'save';
const ACTION_GET = 'get';
const ACTION_DELETE = 'delete';
const ACTION_PRINT = 'print';
const ACTION_SHIPMENT_SAVE = 'shipmentSave';
const ACTION_SHIPMENT_DELETE = 'shipmentDelete';
const ACTION_SHIPMENT_POINT_LIST = 'shipmentPointList';
/**
* Описание подключения.
*
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("description")
* @Serializer\Type("string")
*/
public $description;
/**
* Относительные пути от базового URL до конкретных методов.
*
* @var array
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("actions")
* @Serializer\Type("array<string, string>")
*/
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 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<RetailCrm\DeliveryModuleBundle\Model\Status>")
*/
public $statusList;
/**
* Список печатных форм, предоставляемых службой.
*
* @var Plate[]
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("plateList")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Plate>")
*/
public $plateList;
/**
* Список дополнительных полей, необходимых для оформления доставки.
*
* @var DeliveryDataField[]
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("deliveryDataFieldList")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\DeliveryDataField>")
*/
public $deliveryDataFieldList;
/**
* Список дополнительных полей, необходимых для заявки на отгрузку.
*
* @var DeliveryDataField[]
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("shipmentDataFieldList")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\DeliveryDataField>")
*/
public $shipmentDataFieldList;
}

68
Model/Contragent.php Normal file
View File

@ -0,0 +1,68 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Contragent
{
const TYPE_INDIVIDUAL = 'individual'; // физ. лицо
const TYPE_LEGAL_ENTITY = 'legal-entity'; // юр. лицо
const TYPE_ENTERPRENEUR = 'enterpreneur'; // инд. предприниматель
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("legalName")
* @Serializer\Type("string")
*/
public $legalName;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("legalAddress")
* @Serializer\Type("string")
*/
public $legalAddress;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("INN")
* @Serializer\Type("string")
*/
public $INN;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("OKPO")
* @Serializer\Type("string")
*/
public $OKPO;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("KPP")
* @Serializer\Type("string")
*/
public $KPP;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("OGRN")
* @Serializer\Type("string")
*/
public $OGRN;
/**
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("OGRNIP")
* @Serializer\Type("string")
*/
public $OGRNIP;
}

28
Model/Coordinates.php Normal file
View File

@ -0,0 +1,28 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Coordinates
{
/**
* Широта
* @var float
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("latitude")
* @Serializer\Type("float")
*/
public $latitude;
/**
* Долгота
* @var float
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("longitude")
* @Serializer\Type("float")
*/
public $longitude;
}

94
Model/Customer.php Normal file
View File

@ -0,0 +1,94 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Customer
{
/**
* Идентификатор покупателя.
*
* @var int
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("id")
* @Serializer\Type("integer")
*/
public $id;
/**
* Фамилия.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("lastName")
* @Serializer\Type("string")
*/
public $lastName;
/**
* Имя.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("firstName")
* @Serializer\Type("string")
*/
public $firstName;
/**
* Отчество.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("patronymic")
* @Serializer\Type("string")
*/
public $patronymic;
/**
* Телефоны.
*
* @var array
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("phones")
* @Serializer\Type("array<string>")
*/
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;
}
}

250
Model/DeliveryAddress.php Normal file
View File

@ -0,0 +1,250 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class DeliveryAddress
{
/**
* Почтовый индекс
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("index")
* @Serializer\Type("string")
*/
public $index;
/**
* ISO код страны (ISO 3166-1 alpha-2).
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("countryIso")
* @Serializer\Type("string")
*/
public $country;
/**
* Область/край.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("region")
* @Serializer\Type("string")
*/
public $region;
/**
* Идентификатор региона в Geohelper.
*
* @var int
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("regionId")
* @Serializer\Type("integer")
*/
public $regionId;
/**
* Город.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("city")
* @Serializer\Type("string")
*/
public $city;
/**
* Идентификатор города в Geohelper.
*
* @var int
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("cityId")
* @Serializer\Type("integer")
*/
public $cityId;
/**
* Тип населенного пункта.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("cityType")
* @Serializer\Type("string")
*/
public $cityType;
/**
* Название улицы, шоссе, проспекта, проезда.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("street")
* @Serializer\Type("string")
*/
public $street;
/**
* Идентификатор улицы в Geohelper.
*
* @var int
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("streetId")
* @Serializer\Type("integer")
*/
public $streetId;
/**
* Тип улицы.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("streetType")
* @Serializer\Type("string")
*/
public $streetType;
/**
* Дом
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("building")
* @Serializer\Type("string")
*/
public $building;
/**
* Номер квартиры или офиса.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("flat")
* @Serializer\Type("string")
*/
public $flat;
/**
* Код домофона.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("intercomCode")
* @Serializer\Type("string")
*/
public $intercomCode;
/**
* Этаж.
*
* @var int
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("floor")
* @Serializer\Type("integer")
*/
public $floor;
/**
* Подъезд.
*
* @var int
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("block")
* @Serializer\Type("integer")
*/
public $block;
/**
* Строение.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("house")
* @Serializer\Type("string")
*/
public $house;
/**
* Корпус
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("housing")
* @Serializer\Type("string")
*/
public $housing;
/**
* Метро.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("metro")
* @Serializer\Type("string")
*/
public $metro;
/**
* Дополнительные заметки.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("notes")
* @Serializer\Type("string")
*/
public $notes;
/**
* Адрес в виде строки.
*
* @var string
*
* @Serializer\Groups({"get", "set", "response"})
* @Serializer\SerializedName("text")
* @Serializer\Type("string")
*/
public $text;
/**
* Код терминала отгрузки/доставки.
*
* @var string
*
* @Serializer\Groups({"get", "request", "response"})
* @Serializer\SerializedName("terminal")
* @Serializer\Type("string")
*/
public $terminal;
/**
* Данные терминала.
*
* @var Terminal
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("terminalData")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Terminal")
*/
public $terminalData;
}

157
Model/DeliveryDataField.php Normal file
View File

@ -0,0 +1,157 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class DeliveryDataField
{
const TYPE_INTEGER = 'integer';
const TYPE_TEXT = 'text';
const TYPE_AUTOCOMPLETE = 'autocomplete';
const TYPE_CHECKBOX = 'checkbox';
const TYPE_CHOICE = 'choice';
const TYPE_DATE = 'date';
/**
* Код поля.
*
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Имя поля.
*
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("label")
* @Serializer\Type("string")
*/
public $label;
/**
* Пояснение к полю.
*
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("hint")
* @Serializer\Type("string")
*/
public $hint;
/**
* Тип поля. Возможны варианты (
* integer - числовое поле,
* text - текстовое поле,
* autocomplete - автокомплит поле,
* checkbox,
* choice - выпадающий список,
* date - поле с датой).
*
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* Указывается для типа поля choice. Означает что можно выбирать несколько вариантов.
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("multiple")
* @Serializer\Type("boolean")
*/
public $multiple = false;
/**
* Указывается для типа поля choice. Список возможных вариантов в выпадающем списке. Обязателен если тип поля choice.
*
* @var array
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("choices")
* @Serializer\Type("array")
*/
public $choices;
/**
* Указывается для типа поля autocomplete. Адрес, по окторому можно получить данные для автокомплит поля.
*
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("autocompleteUrl")
* @Serializer\Type("string")
*/
public $autocompleteUrl;
/**
* Указывается для типа поля autocomplete. Можно искать без указания строки поиска
* (при нажатии на поле сразу вывалится список с вариантами).
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("allowedEmptyTerm")
* @Serializer\Type("boolean")
*/
public $allowedEmptyTerm = false;
/**
* Видимость поля на форме.
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("visible")
* @Serializer\Type("boolean")
*/
public $isVisible = true;
/**
* Поле обязательно для заполнения.
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("required")
* @Serializer\Type("boolean")
*/
public $isRequired = false;
/**
* Поле влияет на стоимость доставки. Если true - значение поля используется в методе calculate.
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("affectsCost")
* @Serializer\Type("boolean")
*/
public $isAffectsCost = false;
/**
* Разрешено ли редактировать поле.
* Если false - поле информационное - заполняется только данными,
* полученными напрямую от службы доставки (
* например стоимость страховки - может заполняться после оформления доставки или при расчете стоимости).
*
* @var bool
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("editable")
* @Serializer\Type("boolean")
*/
public $isEditable = true;
}

340
Model/DeliveryTime.php Normal file
View File

@ -0,0 +1,340 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class DeliveryTime
{
/**
* Время доставки "с"
*
* @Serializer\SerializedName("from")
* @Serializer\Type("DateTime<'H:i'>")
* @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 null|string|\DateTime $from
* @param null|string|\DateTime $to
* @param null|string $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<from>\d{2}[:\.]?\d{0,2})\s*(-|по|до)\s*(?P<to>\d{2}[:\.]?\d{0,2})/u';
// диапазон времени: c 12.00
$rangeFromPattern = '/^с?\s*(?P<from>\d{2}[:\.]?\d{0,2})/u';
// диапазон времени: до 13:00
$rangeToPattern = '/^(-|по|до)\s*(?P<to>\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);
}
/**
* Проверяет, соответствует ли время доставки диапазону из настроек
*
* @param array $range
* @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'] ||
$range['from'] === '00:00' ||
$range['from'] === '00:00:00'
) {
$fromEquals = true;
}
}
if ($to) {
if (isset($range['to'])) {
$toEquals = $to->format('H:i') === $range['to'];
}
} else {
if (!isset($range['to']) ||
!$range['to'] ||
$range['from'] === '23:59' ||
$range['from'] === '23:59:59'
) {
$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 ($from === null && $to !== null) {
$this->from = new \DateTime('1970-01-01T00:00:00');
} elseif ($to === null && $from !== null) {
$this->to = new \DateTime('1970-01-01T23:59:59');
} elseif ($to === null && $from === null) {
$this->to = null;
$this->from = null;
}
}
}

165
Model/Entity/Account.php Normal file
View File

@ -0,0 +1,165 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model\Entity;
use JMS\Serializer\Annotation as Serializer;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
abstract class Account
{
/**
* @Serializer\Groups({"get"})
* @Serializer\Type("string")
*/
protected $id;
protected $clientId;
/**
* @var \DateTime
*
* @Serializer\Groups({"get"})
* @Serializer\Type("DateTime<'Y-m-d H:i:s'>")
*/
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;
}
}

View File

@ -0,0 +1,102 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model\Entity;
abstract class DeliveryOrder
{
/**
* @var int
*/
protected $id;
/**
* @var Account
*/
protected $account;
/**
* @var int
*/
protected $orderId;
/**
* @var string
*/
protected $externalId;
/**
* @var bool
*/
protected $ended;
public function __construct()
{
$this->ended = false;
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
public function setAccount(Account $account): self
{
$this->account = $account;
return $this;
}
public function getAccount(): ?Account
{
return $this->account;
}
public function setOrderId(int $orderId): self
{
$this->orderId = $orderId;
return $this;
}
public function getOrderId(): int
{
return $this->orderId;
}
public function setExternalId(string $externalId): self
{
$this->externalId = $externalId;
return $this;
}
public function getExternalId(): string
{
return $this->externalId;
}
public function setEnded(bool $ended): self
{
$this->ended = $ended;
return $this;
}
public function getTrackNumber(): string
{
return $this->externalId;
}
public function setTrackNumber(string $trackNumber): self
{
return $this;
}
public function getEnded(): bool
{
return $this->ended;
}
}

128
Model/IntegrationModule.php Normal file
View File

@ -0,0 +1,128 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class IntegrationModule
{
/**
* Код экземпляра модуля
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Общий символьный код модуля
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("integrationCode")
* @Serializer\Type("string")
*/
public $integrationCode;
/**
* Ключ активности модуля
* @var boolean
*
* @Serializer\Groups({"set", "get", "activity"})
* @Serializer\SerializedName("active")
* @Serializer\Type("boolean")
*/
public $active;
/**
* Работа модуля заморожена
* @var boolean
*
* @Serializer\Groups({"activity"})
* @Serializer\SerializedName("freeze")
* @Serializer\Type("boolean")
*/
public $freeze;
/**
* Наименование модуля
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Ссылка на svg логотип модуля
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("logo")
* @Serializer\Type("string")
*/
public $logo;
/**
* ID подключения
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("clientId")
* @Serializer\Type("string")
*/
public $clientId;
/**
* Базовый url, на который делает запросы RetailCRM
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("baseUrl")
* @Serializer\Type("string")
*/
public $baseUrl;
/**
* Относительные пути от базового URL до конкретных методов
* @var array
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("actions")
* @Serializer\Type("array<string, string>")
*/
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;
}

83
Model/Manager.php Normal file
View File

@ -0,0 +1,83 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Manager
{
/**
* Идентификатор менеджера.
*
* @var int
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("id")
* @Serializer\Type("integer")
*/
public $id;
/**
* Фамилия.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("lastName")
* @Serializer\Type("string")
*/
public $lastName;
/**
* Имя.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("firstName")
* @Serializer\Type("string")
*/
public $firstName;
/**
* Отчество.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("patronymic")
* @Serializer\Type("string")
*/
public $patronymic;
/**
* Телефон.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("phone")
* @Serializer\Type("string")
*/
public $phone;
/**
* E-mail.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("email")
* @Serializer\Type("string")
*/
public $email;
public function getNickName(): ?string
{
$result = trim(
$this->lastName . ' ' . $this->firstName . ' ' . $this->patronymic
);
return $result;
}
}

96
Model/Package.php Normal file
View File

@ -0,0 +1,96 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
class Package
{
/**
* Идентификатор упаковки
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("packageId")
* @Serializer\Type("string")
*/
public $packageId;
/**
* Вес г.
* @var float
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("weight")
* @Serializer\Type("float")
*/
public $weight;
/**
* Ширина мм.
* @var integer
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("width")
* @Serializer\Type("integer")
*/
public $width;
/**
* Длина мм.
* @var integer
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("length")
* @Serializer\Type("integer")
*/
public $length;
/**
* Высота мм.
* @var integer
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("height")
* @Serializer\Type("integer")
*/
public $height;
/**
* Содержимое упаковки
* @var PackageItem[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("items")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\PackageItem>")
*/
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 (!is_null($this->length)
&& !is_null($this->width)
&& !is_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());
}
}

107
Model/PackageItem.php Normal file
View File

@ -0,0 +1,107 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class PackageItem
{
/**
* Идентификатор товара.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("offerId")
* @Serializer\Type("string")
*/
public $offerId;
/**
* Наименование товара.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Объявленная стоимость за единицу товара.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("declaredValue")
* @Serializer\Type("float")
*/
public $declaredValue;
/**
* Наложенный платеж за единицу товара.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("cod")
* @Serializer\Type("float")
*/
public $cod;
/**
* Ставка НДС
*
* @var float
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("vatRate")
* @Serializer\Type("float")
*/
public $vatRate;
/**
* Количество товара в упаковке.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("quantity")
* @Serializer\Type("float")
*/
public $quantity;
/**
* Единица измерения товара.
*
* @var Unit
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("unit")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Unit")
*/
public $unit;
/**
* Стоимость товара.
*
* @var float
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Свойства товара.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("properties")
* @Serializer\Type("array<string, array>")
*/
public $properties;
}

22
Model/PaymentType.php Normal file
View File

@ -0,0 +1,22 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class PaymentType
{
/**
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public string $code;
/**
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public string $name;
}

34
Model/Plate.php Normal file
View File

@ -0,0 +1,34 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Plate
{
/**
* Код печатной формы
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Наименование печатной формы
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("label")
* @Serializer\Type("string")
*/
public $label;
public function __construct($code, $label)
{
$this->code = $code;
$this->label = $label;
}
}

View File

@ -0,0 +1,121 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Intaro\CRMBundle\Entity\Model\DeliveryTime;
use JMS\Serializer\Annotation as Serializer;
class RequestCalculate
{
use Traits\ExtraDataTrait;
/**
* Адрес отгрузки.
*
* @var RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("shipmentAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $shipmentAddress;
/**
* Адрес доставки.
*
* @var string
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("deliveryAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $deliveryAddress;
/**
* Набор упаковок.
*
* @var Intaro\CRMDeliveryBundle\Form\Model\Package[]
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("packages")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Package>")
*/
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;
}

View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestDelete
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
}

View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestPrint
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* @var string[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryIds")
* @Serializer\Type("array")
*/
public $deliveryIds;
}

View File

@ -0,0 +1,144 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
class RequestSave
{
/**
* Идентификатор доставки в службе доставки. Передается если требуется отредактировать уже оформленную доставку
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Id заказа
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("order")
* @Serializer\Type("string")
*/
public $order;
/**
* Номер заказа
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("orderNumber")
* @Serializer\Type("string")
*/
public $orderNumber;
/**
* Код магазина
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("site")
* @Serializer\Type("string")
*/
public $site;
/**
* Название магазина
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("siteName")
* @Serializer\Type("string")
*/
public $siteName;
/**
* Наименование юр.лица
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("legalEntity")
* @Serializer\Type("string")
*/
public $legalEntity;
/**
* Покупатель
* @var Customer
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("customer")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Customer")
*/
public $customer;
/**
* Менеджер, работающий с покупателем
* @var Manager
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("manager")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Manager")
*/
public $manager;
/**
* Набор упаковок
* @var RetailCrm\DeliveryModuleBundle\Model\Package[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("packages")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Package>")
*/
public $packages;
/**
* Данные доставки
* @var RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("delivery")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData")
*/
public $delivery;
/**
* Валюта
* @var string $currency
*
* @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;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestShipmentDelete
{
/**
* Идентификатор отгрузки в службе доставки
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Дополнительные данные отгрузки
* @var array
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
}

View File

@ -0,0 +1,89 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestShipmentSave
{
use Traits\ExtraDataTrait;
/**
* Идентификатор отгрузки в службе доставки. Передается если требуется отредактировать уже оформленную отгрузку
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Менеджер, отвечающий за отгрузку
* @var Manager
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("manager")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Manager")
*/
public $manager;
/**
* Дата отгрузки
* @var DateTime
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("date")
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
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<RetailCrm\DeliveryModuleBundle\Model\ShipmentOrder>")
*/
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;
}

View File

@ -0,0 +1,53 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestStatusUpdateItem
{
/**
* Идентификатор доставки с СД
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Трек номер
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* История смены статусов доставки
* @var StatusInfo[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("history")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\StatusInfo>")
*/
public $history;
/**
* Массив дополнительных данных доставки
* @var array
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
public function __construct()
{
$this->history = [];
}
}

120
Model/RequestCalculate.php Normal file
View File

@ -0,0 +1,120 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestCalculate
{
use Traits\ExtraDataTrait;
/**
* Адрес отгрузки.
*
* @var RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("shipmentAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $shipmentAddress;
/**
* Адрес доставки.
*
* @var string
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("deliveryAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $deliveryAddress;
/**
* Набор упаковок.
*
* @var RetailCrm\DeliveryModuleBundle\Model\Package[]
*
* @Serializer\Groups({"request", "calculate"})
* @Serializer\SerializedName("packages")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Package>")
*/
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;
}

17
Model/RequestDelete.php Normal file
View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestDelete
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
}

26
Model/RequestPrint.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestPrint
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* @var string[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryIds")
* @Serializer\Type("array")
*/
public $deliveryIds;
}

164
Model/RequestSave.php Normal file
View File

@ -0,0 +1,164 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestSave
{
/**
* Идентификатор доставки в службе доставки. Передается если требуется отредактировать уже оформленную доставку.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Id заказа.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("order")
* @Serializer\Type("string")
*/
public $order;
/**
* Номер заказа.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("orderNumber")
* @Serializer\Type("string")
*/
public $orderNumber;
/**
* Код магазина.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("site")
* @Serializer\Type("string")
*/
public $site;
/**
* Название магазина.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("siteName")
* @Serializer\Type("string")
*/
public $siteName;
/**
* Склад.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("store")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Store")
*/
public $store;
/**
* Наименование юр.лица.
*
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("legalEntity")
* @Serializer\Type("string")
*/
public $legalEntity;
/**
* Покупатель.
*
* @var Customer
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("customer")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Customer")
*/
public $customer;
/**
* Менеджер, работающий с покупателем
*
* @var Manager
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("manager")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Manager")
*/
public $manager;
/**
* Набор упаковок.
*
* @var Package[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("packages")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Package>")
*/
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;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestShipmentDelete
{
/**
* Идентификатор отгрузки в службе доставки
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Дополнительные данные отгрузки
* @var array
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
}

View File

@ -0,0 +1,49 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestShipmentPointList
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("country")
* @Serializer\Type("string")
*/
public $country;
/**
* @var string
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("region")
* @Serializer\Type("string")
*/
public $region;
/**
* @var int
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("regionId")
* @Serializer\Type("integer")
*/
public $regionId;
/**
* @var string
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("city")
* @Serializer\Type("string")
*/
public $city;
/**
* @var int
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("cityId")
* @Serializer\Type("integer")
*/
public $cityId;
}

View File

@ -0,0 +1,89 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestShipmentSave
{
use Traits\ExtraDataTrait;
/**
* Идентификатор отгрузки в службе доставки. Передается если требуется отредактировать уже оформленную отгрузку
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Менеджер, отвечающий за отгрузку
* @var Manager
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("manager")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Manager")
*/
public $manager;
/**
* Дата отгрузки
* @var DateTime
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("date")
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
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<RetailCrm\DeliveryModuleBundle\Model\ShipmentOrder>")
*/
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;
}

View File

@ -0,0 +1,53 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class RequestStatusUpdateItem
{
/**
* Идентификатор доставки с СД
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Трек номер
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* История смены статусов доставки
* @var StatusInfo[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("history")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\StatusInfo>")
*/
public $history;
/**
* Массив дополнительных данных доставки
* @var array
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
public function __construct()
{
$this->history = [];
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseAutocompleteItem
{
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("value")
* @Serializer\Type("string")
*/
public $value;
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("label")
* @Serializer\Type("string")
*/
public $label;
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("description")
* @Serializer\Type("string")
*/
public $description;
public function __construct($value, $label, $description = null)
{
$this->value = $value;
$this->label = $label;
$this->description = $description;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseAutocompleteSuccessful
{
/**
* @var boolean
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("success")
* @Serializer\Type("boolean")
*/
public $success = true;
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\ResponseAutocompleteItem>")
*/
public $result;
}

View File

@ -0,0 +1,126 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseCalculate
{
const TARIFF_COURIER = 'courier';
const TARIFF_SELF_DELIVERY = 'selfDelivery';
/**
* Код тарифа
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Группа тарифов
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("group")
* @Serializer\Type("string")
*/
public $group;
/**
* Наименование тарифа
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Тип тарифа (курьерская доставка или самовывоз)
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* Описание
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("description")
* @Serializer\Type("string")
*/
public $description;
/**
* Стоимость доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Минимальный срок доставки
* @var integer
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("minTerm")
* @Serializer\Type("integer")
*/
public $minTerm;
/**
* Максимальный срок доставки
* @var integer
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("maxTerm")
* @Serializer\Type("integer")
*/
public $maxTerm;
/**
* Дополнительные данные доставки
* @var array
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
/**
* Возможные дополнительные данные доставки
* @var array
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraDataAvailable")
* @Serializer\Type("array")
*/
public $extraDataAvailable;
/**
* Список доступных терминалов выдачи посылки
* @var Terminal[]
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("pickuppointList")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Terminal>")
*/
public $pickuppointList;
public function __construct()
{
$this->extraData = [];
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseCalculateSuccessful
{
/**
* @var boolean
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("success")
* @Serializer\Type("boolean")
*/
public $success = true;
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\ResponseCalculate>")
*/
public $result;
}

View File

@ -0,0 +1,138 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
class ResponseLoadDeliveryData
{
/**
* Трек номер
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* Стоимость доставки
* @var float
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Дата отгрузки
* @var \DateTime
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("shipmentDate")
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
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 = [];
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
class ResponseResult
{
}

View File

@ -0,0 +1,70 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
use Intaro\CRMDeliveryBundle\Delivery\Generic\Generic;
class ResponseSave
{
/**
* Идентификатор доставки в службе доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Трек номер
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* Стоимость доставки
* @var float
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Код статуса доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("status")
* @Serializer\Type("string")
*/
public $status;
/**
* Дополнительные данные доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
public $additionalData;
public function __construct()
{
$this->extraData = [];
$this->additionalData = [];
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
class ResponseShipmentSave
{
/**
* Идентификатор отгрузки в службе доставки.
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Дополнительные данные доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array<string, string>")
*/
public $extraData;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata
->addPropertyConstraint('shipmentId', new Assert\NotBlank());
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseSuccessful
{
/**
* @var boolean
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("success")
* @Serializer\Type("boolean")
*/
public $success = true;
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\ResponseResult")
*/
public $result;
}

View File

@ -0,0 +1,42 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseAutocompleteItem
{
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("value")
* @Serializer\Type("string")
*/
public $value;
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("label")
* @Serializer\Type("string")
*/
public $label;
/**
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("description")
* @Serializer\Type("string")
*/
public $description;
public function __construct($value, $label, $description = null)
{
$this->value = $value;
$this->label = $label;
$this->description = $description;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseAutocompleteSuccessful
{
/**
* @var boolean
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("success")
* @Serializer\Type("boolean")
*/
public $success = true;
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\ResponseAutocompleteItem>")
*/
public $result;
}

126
Model/ResponseCalculate.php Normal file
View File

@ -0,0 +1,126 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseCalculate
{
const TARIFF_COURIER = 'courier';
const TARIFF_SELF_DELIVERY = 'selfDelivery';
/**
* Код тарифа
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Группа тарифов
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("group")
* @Serializer\Type("string")
*/
public $group;
/**
* Наименование тарифа
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Тип тарифа (курьерская доставка или самовывоз)
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("type")
* @Serializer\Type("string")
*/
public $type;
/**
* Описание
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("description")
* @Serializer\Type("string")
*/
public $description;
/**
* Стоимость доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Минимальный срок доставки
* @var integer
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("minTerm")
* @Serializer\Type("integer")
*/
public $minTerm;
/**
* Максимальный срок доставки
* @var integer
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("maxTerm")
* @Serializer\Type("integer")
*/
public $maxTerm;
/**
* Дополнительные данные доставки
* @var array
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
/**
* Возможные дополнительные данные доставки
* @var array
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraDataAvailable")
* @Serializer\Type("array")
*/
public $extraDataAvailable;
/**
* Список доступных терминалов выдачи посылки
* @var Terminal[]
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("pickuppointList")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Terminal>")
*/
public $pickuppointList;
public function __construct()
{
$this->extraData = [];
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseCalculateSuccessful extends AbstractResponseSuccessful
{
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\ResponseCalculate>")
*/
public $result;
}

View File

@ -0,0 +1,138 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
class ResponseLoadDeliveryData
{
/**
* Трек номер
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* Стоимость доставки
* @var float
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Дата отгрузки
* @var \DateTime
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("shipmentDate")
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
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 = [];
}
}

7
Model/ResponseResult.php Normal file
View File

@ -0,0 +1,7 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
class ResponseResult
{
}

72
Model/ResponseSave.php Normal file
View File

@ -0,0 +1,72 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseSave
{
/**
* Идентификатор доставки в службе доставки.
*
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Трек номер
*
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("trackNumber")
* @Serializer\Type("string")
*/
public $trackNumber;
/**
* Стоимость доставки.
*
* @var float
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Код статуса доставки.
*
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("status")
* @Serializer\Type("string")
*/
public $status;
/**
* Дополнительные данные доставки.
*
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
public $additionalData;
public $saveDataHash;
public function __construct()
{
$this->extraData = [];
$this->additionalData = [];
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseShipmentPointListSuccessful extends AbstractResponseSuccessful
{
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Terminal>")
*/
public $result;
}

View File

@ -0,0 +1,36 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
class ResponseShipmentSave
{
/**
* Идентификатор отгрузки в службе доставки.
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("shipmentId")
* @Serializer\Type("string")
*/
public $shipmentId;
/**
* Дополнительные данные доставки
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array<string, string>")
*/
public $extraData;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata
->addPropertyConstraint('shipmentId', new Assert\NotBlank());
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ResponseSuccessful extends AbstractResponseSuccessful
{
/**
* @var mixed
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("result")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\ResponseResult")
*/
public $result;
}

151
Model/SaveDeliveryData.php Normal file
View File

@ -0,0 +1,151 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class SaveDeliveryData
{
/**
* Адрес отгрузки.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("shipmentAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $shipmentAddress;
/**
* Адрес доставки.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("deliveryAddress")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress")
*/
public $deliveryAddress;
/**
* Тип оплаты для наложенного платежа.
*
* @var PaymentType
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("codPaymentType")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\PaymentType")
*/
public $codPaymentType;
/**
* Доставка наложенным платежом
*
* @var bool
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("withCod")
* @Serializer\Type("boolean")
*/
public $withCod;
/**
* Величина наложенного платежа за услуги доставки.
*
* @var float
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("cod")
* @Serializer\Type("float")
*/
public $cod;
/**
* Стоимость доставки (указывается в накладной в случае предоплаты).
*
* @var float
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Ставка НДС для услуги доставки.
*
* @var float
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("vatRate")
* @Serializer\Type("float")
*/
public $vatRate;
/**
* Код тарифа.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("tariff")
* @Serializer\Type("string")
*/
public $tariff;
/**
* Плательщик за услуги доставки.
*
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("payerType")
* @Serializer\Type("string")
*/
public $payerType;
/**
* Дата отгрузки.
*
* @var \DateTime
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("shipmentDate")
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
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;
}

30
Model/ShipmentOrder.php Normal file
View File

@ -0,0 +1,30 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class ShipmentOrder
{
/**
* Идентификатор оформленной доставки в службе доставки.
*
* @var array
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("deliveryId")
* @Serializer\Type("string")
*/
public $deliveryId;
/**
* Набор упаковок.
*
* @var Package[]
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("packages")
* @Serializer\Type("array<RetailCrm\DeliveryModuleBundle\Model\Package>")
*/
public $packages;
}

45
Model/Status.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Status
{
/**
* Код статуса доставки
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Наименование статуса
* @var string
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Если заказ находится в статусе у которого isEditable:true, это означает можно редактировать данные доставки
* @var bool
*
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("isEditable")
* @Serializer\Type("boolean")
*/
public $isEditable = false;
public function __construct($code, $name, $isEditable)
{
$this->code = $code;
$this->name = $name;
$this->isEditable = $isEditable;
}
}

38
Model/StatusInfo.php Normal file
View File

@ -0,0 +1,38 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class StatusInfo
{
/**
* Код статуса доставки
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Дата обновления статуса доставки
* @var \DateTime
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("updatedAt")
* @Serializer\Type("DateTime<'Y-m-d\TH:i:sP'>")
*/
public $updatedAt;
/**
* Комментарий к статусу
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("comment")
* @Serializer\Type("string")
*/
public $comment;
}

26
Model/Store.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Store
{
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* @var string
*
* @Serializer\Groups({"request"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
}

96
Model/Terminal.php Normal file
View File

@ -0,0 +1,96 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
use JMS\Serializer\Annotation as Serializer;
class Terminal
{
/**
* Код терминала.
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* Стоимость доставки до терминала, если она отличается от стоимости в целом по тарифу.
*
* @var string
*
* @Serializer\Groups({"response"})
* @Serializer\SerializedName("cost")
* @Serializer\Type("float")
*/
public $cost;
/**
* Наименование терминала.
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* Адрес
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("address")
* @Serializer\Type("string")
*/
public $address;
/**
* Режим работы.
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("schedule")
* @Serializer\Type("string")
*/
public $schedule;
/**
* Телефон.
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("phone")
* @Serializer\Type("string")
*/
public $phone;
/**
* Дополнительные данные.
*
* @var string
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("extraData")
* @Serializer\Type("array")
*/
public $extraData;
/**
* Координаты.
*
* @var Coordinates
*
* @Serializer\Groups({"get", "response"})
* @Serializer\SerializedName("coordinates")
* @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Coordinates")
*/
public $coordinates;
}

View File

@ -0,0 +1,15 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model\Traits;
trait ExtraDataTrait
{
public function getExtraData($fieldCode)
{
if (!isset($this->extraData[$fieldCode])) {
return null;
} else {
return $this->extraData[$fieldCode];
}
}
}

33
Model/Unit.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Model;
class Unit
{
/**
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("code")
* @Serializer\Type("string")
*/
public $code;
/**
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
public $name;
/**
* @var string
*
* @Serializer\Groups({"get", "set"})
* @Serializer\SerializedName("sym")
* @Serializer\Type("string")
*/
public $sym;
}

0
README.md Normal file
View File

View File

@ -0,0 +1,101 @@
retailcrm_delivery_module_connect:
path: /{_locale}/connect
defaults: { _controller: :Admin:connect }
requirements:
_locale: en|ru
retailcrm_delivery_module_connect_edit:
path: /{_locale}/connect/{clientId}/edit
defaults: { _controller: :Admin:connect }
requirements:
_locale: en|ru
############
# Admin
############
retailcrm_delivery_module_admin_list:
path: /omega
defaults: { _controller: :Admin:list }
retailcrm_delivery_module_admin_new:
path: /omega/new
defaults: { _controller: :Admin:new }
retailcrm_delivery_module_admin_edit:
path: /omega/{connectionId}/edit
defaults: { _controller: :Admin:edit }
requirements:
connectionId: \d+
retailcrm_delivery_module_admin_update_configuration:
path: /omega/{connectionId}/update-configuration
defaults: { _controller: :Admin:updateConfiguration }
requirements:
connectionId: \d+
retailcrm_delivery_module_admin_parcel_list:
path: /omega/parcels
defaults: { _controller: :Admin:parcelList }
retailcrm_delivery_module_admin_parcel_new:
path: /omega/parcels/new
defaults: { _controller: :Admin:parcelNew }
retailcrm_delivery_module_admin_parcel_edit:
path: /omega/parcels/{parcelId}/edit
defaults: { _controller: :Admin:parcelEdit }
requirements:
parcelId: \d+
#############
# 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

View File

@ -0,0 +1,58 @@
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

View File

@ -0,0 +1,67 @@
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.<br/><br/><a href="%href%">Re-enter data</a>
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

View File

@ -0,0 +1,67 @@
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.<br/><br/><a href="%href%">Introducir datos de nuevo</a>
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

View File

@ -0,0 +1,67 @@
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 ключ системы введены неверно, попробуйте еще раз.<br/><br/><a href="%href%">Ввести данные заново</a>
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: элементов

View File

@ -0,0 +1,68 @@
{% form_theme form 'DeliveryCoreBundle:Form:configure.html.twig' %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
{% block title %}{% endblock %}
</title>
<link rel="stylesheet" href="{{ asset('bundles/coreautomate/css/connect.css') }}" />
<link rel="shortcut icon" href="{{ asset('favicon.ico') }}" type="image/x-icon">
</head>
<body>
<div class="wrapper" style="width:100%;">
<div class="top">
<div class="header">
<div>
{% block logo %}{% endblock %}
</div>
</div>
<div class="blue_line"></div>
</div>
<div class="content">
<div class="form-style-5">
{% block form %}
<div style="text-align: justify; margin-bottom: 10px;">
{{ form_errors(form) }}
</div>
<form name="connection" method="post" {{ form.vars.data.clientId is not empty ? ('action="' ~ path(route ~ '_configure_edit', {'clientId': form.vars.data.clientId}) ~ '"')|raw }} >
{{ form_start(form) }}
{% block form_delivery %}
{% endblock %}
<fieldset>
<legend class="header_form_text">{{ 'header.configureConnection'|trans }}</legend>
{{ form_widget(form.crmUrl, {'attr': {'value': account}}) }}
{{ form_errors(form.crmUrl) }}
{{ form_widget(form.crmKey) }}
{{ form_errors(form.crmKey) }}
{{ form_widget(form.language) }}
{{ form_errors(form.language) }}
</fieldset>
{% block form_delivery_after %}
{% endblock %}
<div style="display: none">
{{ form_rest(form) }}
</div>
<input type="submit" value="{{ (form.vars.data.clientId is not empty ? 'button.save' : 'button.activate')|trans }}" />
{{ form_end(form) }}
{% endblock %}
</div>
</div>
<div class="footer">
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
{% extends 'CoreAutomateBundle:Layout:connect.html.twig' %}
{% block title %}
{{ 'header.serviceConnect'|trans({'%delivery%': title_delivery})|raw }}
{% endblock %}
{% block logo %}
<img style="height: 60px" src="{{ src_logo_delivery }}" alt="{{ title_delivery }}">
{% endblock %}
{% block form %}
{{ 'error.connect.failed'|trans({'%delivery%': title_delivery, '%href%': referer})|raw }}
{% endblock %}

View File

@ -0,0 +1,60 @@
{% extends 'CoreOmegaBundle:Layout:base.html.twig' %}
{% form_theme form 'DeliveryCoreBundle:Form:admin.html.twig' %}
{% block content %}
<div class="header-main">
<h1 style="margin: 10px 0 10px 0;">
{% if connection is defined %}
{{ 'header.adminConnectionEdit'|trans({'%uid%': '<a target="_blank" href="'~connection.crmUrl~'">'~connection.crmUrl~'</a>'})|raw }}
{% else %}
{{ 'header.adminConnectionCreate'|trans()|raw }}
{% endif %}
</h1>
</div>
<div class="main">
<div class="m-box mn-or-info">
{{ form_start(form) }}
{{ form_errors(form) }}
<div class="field-for-group cleared">
{{ form_row(form.crmUrl) }}
{{ form_row(form.crmKey) }}
{{ form_row(form.isActive) }}
{% if form.language is defined %}
{{ form_row(form.language) }}
{% endif %}
{{ form_row(form.isFreeze) }}
</div>
{% block form_appendix %}
{% endblock %}
<div class="field-for-group cleared">
{{ form_row(form.debug) }}
</div>
<div class="field-for-group cleared">
<div class="input-group cleared">
<input type="submit" name="submit" value="{{ 'button.save'|trans()|raw }}" class="btn small btn-save"/>
</div>
{% if is_granted('ROLE_DEVELOPER') %}
{% if connection is defined %}
<div class="input-group cleared">
<a href="{{ path(route ~ '_admin_update_configuration', {'connectionId': connection.id}) }}" class="btn small btn-save">
{{ 'button.updateConfiguration'|trans()|raw }}
</a>
</div>
{% endif %}
{% endif %}
</div>
{{ form_end(form) }}
</div>
<div id="push"></div>
</div>
{% endblock %}

View File

@ -0,0 +1,61 @@
{% extends 'CoreOmegaBundle:Layout:base.html.twig' %}
{% block content %}
<div class="header-main">
<h1 style="margin: 10px 0 10px 0;">{{ 'header.listConnection'|trans()|raw }}</h1>
</div>
<div class="main">
<div style="margin: 5px 0 15px 0;">
{% if is_granted('ROLE_DEVELOPER') %}
<a href="{{ path(route ~ '_admin_new') }}" class="btn small btn-save">
{{ 'button.add'|trans()|raw }}
</a>
{% endif %}
<a href="{{ path(route ~ '_admin_parcel_list') }}" class="btn small btn-save">
{{ 'button.listTracking'|trans()|raw }}
</a>
</div>
<table class="modern-table">
<tr>
<th style="text-align: left">{{ 'label.id'|trans()|raw }}</th>
<th>{{ 'label.crmUrl'|trans()|raw }}</th>
<th style="text-align: center">{{ 'label.isActive'|trans()|raw }}</th>
</tr>
{% for client in pagination %}
<tr>
<td style="text-align: left">
<a href="{{ path(route ~ '_admin_edit', {'connectionId': client.id}) }}">{{ client.clientId }}</a>
</td>
<td>
{% if client.crmUrl is not empty %}
<a target="_blank" href="{{ client.crmUrl }}">
{{ client.crmUrl }}
</a>
{% endif %}
</td>
<td style="text-align: center">
{% if client.isActive %}
<img src="{{ asset('bundles/coreomega/images/mark-yes.svg') }}" style="width: 20px; height: 20px;"/>
{% else %}
<img src="{{ asset('bundles/coreomega/images/mark-no.svg') }}" style="width: 20px; height: 20px;" />
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<div class="list-bottom">
<div class="list-total-stripe">
<span id="list-total-count">
{{ pagination.getTotalItemCount }} <span>{{ 'pagination.items.name'|trans()|raw }}</span>
</span>
</div>
<div class="paginator">
{{ knp_pagination_render(pagination) }}
</div>
</div>
<div id="push"></div>
</div>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends "form_div_layout.html.twig" %}
{% block form_row %}
{% spaceless %}
<div class="input-group cleared">
{{ form_label(form, null, {'label_attr' : {'class': 'label-common'}}) }}
{{ form_errors(form) }}
{% if not attr or not attr.class|default(null) %}
{% set attr = attr|default({})|merge({
'class': 'input-field',
'style': 'max-width: 320px;'
}) %}
{% endif %}
{{ form_widget(form, { 'attr': attr }) }}
</div>
{% endspaceless %}
{% endblock form_row %}

View File

@ -0,0 +1,13 @@
{% extends "form_div_layout.html.twig" %}
{% block form_errors %}
{% spaceless %}
{% if errors|length > 0 %}
{% for error in errors %}
<div class="form_error_message">
<span style="color: #ff0000;">{{ error.message }}</span>
</div>
{% endfor %}
{% endif %}
{% endspaceless %}
{% endblock form_errors %}

View File

@ -0,0 +1,61 @@
{% extends 'CoreOmegaBundle:Layout:base.html.twig' %}
{% block content %}
<div class="header-main">
<h1 style="margin: 10px 0 10px 0;">
{% if parcel.id is not empty %}
{{ 'header.adminParcelEdit' |trans({'%trackId%': parcel.trackId})|raw }}
{% else %}
{{ 'header.adminParcelCreate' |trans()|raw }}
{% endif %}
</h1>
</div>
<div class="main">
<div class="m-box mn-or-info">
{{ form_start(form) }}
{{ form_errors(form) }}
<div class="field-for-group cleared">
<div class="input-group cleared">
{{ form_label(form.connection, null, {'label_attr' : {'class': 'label-common'}}) }}
{{ form_errors(form.connection) }}
{{ form_widget(form.connection, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }}
</div>
<div class="input-group cleared">
{{ form_label(form.orderId, null, {'label_attr' : {'class': 'label-common'}}) }}
{{ form_errors(form.orderId) }}
{{ form_widget(form.orderId, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }}
</div>
</div>
<div class="field-for-group cleared">
<div class="input-group cleared">
{{ form_label(form.trackId, null, {'label_attr' : {'class': 'label-common'}}) }}
{{ form_errors(form.trackId) }}
{{ form_widget(form.trackId, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }}
</div>
<div class="input-group cleared">
{{ form_label(form.isClosed, null, {'label_attr' : {'class': 'label-common'}}) }}
{{ form_errors(form.isClosed) }}
{{ form_widget(form.isClosed) }}
</div>
</div>
{% block form_appendix %}
{% endblock %}
<div class="field-for-group cleared">
<div class="input-group cleared">
<input type="submit" name="submit" value="{{ 'button.save' |trans()|raw }}" class="btn small btn-save"/>
</div>
</div>
{{ form_end(form) }}
</div>
<div id="push"></div>
</div>
{% endblock%}

View File

@ -0,0 +1,60 @@
{% extends 'CoreOmegaBundle:Layout:base.html.twig' %}
{% block content %}
<div class="header-main">
<h1 style="margin: 10px 0 10px 0;">{{ 'header.listConnection'|trans()|raw }}</h1>
</div>
<div class="main">
<div style="margin: 5px 0 15px 0;">
<a href="{{ path(route ~ '_admin_list') }}" class="btn small btn-save">
{{ 'button.listConnection'|trans()|raw }}
</a>
{% if is_granted('ROLE_DEVELOPER') %}
<a href="{{ path(route ~ '_admin_parcel_new') }}" class="btn small btn-save">
{{ 'button.addTracking'|trans()|raw }}
</a>
{% endif %}
</div>
<table class="modern-table">
<tr>
<th style="text-align: left">{{ 'label.trackId'|trans()|raw }}</th>
<th style="text-align: left">{{ 'label.orderId'|trans()|raw }}</th>
<th style="text-align: left">{{ 'label.connection'|trans()|raw }}</th>
<th style="text-align: center">{{ 'label.isClosed'|trans()|raw }}</th>
</tr>
{% for track in pagination %}
<tr>
<td style="text-align: left">
<a href="{{ path(route ~ '_admin_parcel_edit', {'parcelId': track.id}) }}">{{ track.trackId}}</a>
</td>
<td style="text-align: left">
{{ track.orderId}}
</td>
<td style="text-align: left">
<a href="{{ path(route ~ '_admin_edit', {'connectionId': track.connection.id}) }}">{{ track.clientId}}</a>
</td>
<td style="text-align: center">
{% if track.isClosed %}
<img src="{{ asset('bundles/coreomega/images/mark-yes.svg') }}" style="width: 20px; height: 20px;"/>
{% else %}
<img src="{{ asset('bundles/coreomega/images/mark-no.svg') }}" style="width: 20px; height: 20px;" />
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<div class="list-bottom">
<div class="list-total-stripe">
<span id="list-total-count">
{{ pagination.getTotalItemCount }} <span>{{ 'pagination.items.name'|trans()|raw }}</span>
</span>
</div>
<div class="paginator">
{{ knp_pagination_render(pagination) }}
</div>
</div>
<div id="push"></div>
</div>
{% endblock%}

View File

@ -0,0 +1,9 @@
<?php
namespace RetailCrm\DeliveryModuleBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class RetailCrmDeliveryModuleBundle extends Bundle
{
}

View File

@ -0,0 +1,55 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectRepository;
use RetailCrm\DeliveryModuleBundle\Model\Entity\Account;
class AccountManager
{
protected $class;
public function __construct(string $accountClass, ObjectManager $entityManager)
{
$this->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);
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectRepository;
use RetailCrm\DeliveryModuleBundle\Model\Entity\DeliveryOrder;
class DeliveryOrderManager
{
protected $class;
public function __construct(string $deliveryOrderClass, ObjectManager $entityManager)
{
$this->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);
}
}

378
Service/ModuleManager.php Normal file
View File

@ -0,0 +1,378 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use GuzzleHttp\Handler\MockHandler;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Psr\Log\LoggerInterface;
use RetailCrm\ApiClient;
use RetailCrm\DeliveryModuleBundle\Exception\NotFoundException;
use RetailCrm\DeliveryModuleBundle\Model\Configuration;
use RetailCrm\DeliveryModuleBundle\Model\Entity\Account;
use RetailCrm\DeliveryModuleBundle\Model\Entity\DeliveryOrder;
use RetailCrm\DeliveryModuleBundle\Model\IntegrationModule;
use RetailCrm\DeliveryModuleBundle\Model\RequestCalculate;
use RetailCrm\DeliveryModuleBundle\Model\RequestDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestPrint;
use RetailCrm\DeliveryModuleBundle\Model\RequestSave;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentPointList;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseLoadDeliveryData;
use RetailCrm\DeliveryModuleBundle\Model\ResponseSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseShipmentSave;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
abstract class ModuleManager implements ModuleManagerInterface
{
/**
* @var string
*/
protected $integrationCode;
/**
* @var array
*/
protected $moduleParameters;
/**
* @var RetailCrmClientFactoryInterface
*/
protected $retailCrmClientFactory;
/**
* @var Account
*/
protected $account;
/**
* @var MockHandler
*/
protected $mockHandler;
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* @var DeliveryOrderManager
*/
protected $deliveryManager;
/**
* @var SerializerInterface
*/
protected $jmsSerializer;
/**
* @var UrlGeneratorInterface
*/
protected $router;
/**
* @var PinbaService
*/
protected $pinbaService;
/**
* @var ApiClient
*/
private $retailCrmClient;
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(
array $moduleParameters,
RetailCrmClientFactoryInterface $retailCrmClientFactory,
DeliveryOrderManager $deliveryManager,
SerializerInterface $jmsSerializer,
TranslatorInterface $translator,
UrlGeneratorInterface $router
) {
$this->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, $this->logger);
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']));
$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 {
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->getId();
$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->router->generate(
'retailcrm_delivery_module_connect',
['_locale' => $this->account->getLanguage()],
UrlGeneratorInterface::ABSOLUTE_URL
);
$integrationModule->integrations = ['delivery' => $this->doBuildConfiguration()];
return $integrationModule;
}
abstract protected function doBuildConfiguration(): Configuration;
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)
);
}
);
}
}
private function createRetailCrmClient(): void
{
if (null === $this->account) {
throw new \LogicException('Account is not selected');
}
if (empty($this->account->getCrmUrl())) {
throw new \LogicException('Crm url is empty');
}
if (empty($this->account->getCrmApiKey())) {
throw new \LogicException('Crm apiKey is empty');
}
$this->retailCrmClient = new ApiClient(
$this->account->getCrmUrl(),
$this->account->getCrmApiKey(),
ApiClient::V5
);
if ($this->logger) {
$this->retailCrmClient->setLogger($this->logger);
}
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use RetailCrm\ApiClient;
use RetailCrm\DeliveryModuleBundle\Model\Entity\Account;
use RetailCrm\DeliveryModuleBundle\Model\Entity\DeliveryOrder;
use RetailCrm\DeliveryModuleBundle\Model\RequestCalculate;
use RetailCrm\DeliveryModuleBundle\Model\RequestDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestPrint;
use RetailCrm\DeliveryModuleBundle\Model\RequestSave;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentDelete;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentPointList;
use RetailCrm\DeliveryModuleBundle\Model\RequestShipmentSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseSave;
use RetailCrm\DeliveryModuleBundle\Model\ResponseShipmentSave;
interface ModuleManagerInterface
{
const STATUS_UPDATE_LIMIT = 100;
public function getAccountCode(): string;
public function getAccount(): ?Account;
public function setAccount(Account $account): self;
public function updateModuleConfiguration(): bool;
public function calculateDelivery(RequestCalculate $data): array;
public function saveDelivery(RequestSave $data, DeliveryOrder $delivery = null): ResponseSave;
public function deleteDelivery(RequestDelete $request, DeliveryOrder $delivery): bool;
/**
* @return \RetailCrm\DeliveryModuleBundle\Model\Terminal[]
*/
public function shipmentPointList(RequestShipmentPointList $request): array;
public function saveShipment(RequestShipmentSave $data): ResponseShipmentSave;
public function deleteShipment(RequestShipmentDelete $request): bool;
public function printDocument(RequestPrint $request);
public function updateStatuses(): int;
public function getRetailCrmClient(): ApiClient;
}

25
Service/PinbaService.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
class PinbaService
{
/**
* @param array $tags
* @param \Closure $handler
*
* @return mixed
*/
public function timerHandler(array $tags, \Closure $handler)
{
if (function_exists('pinba_timer_start')) {
$timer = pinba_timer_start($tags);
$response = $handler();
pinba_timer_stop($timer);
} else {
$response = $handler();
}
return $response;
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use App\Entity\Account;
use Psr\Log\LoggerInterface;
use RetailCrm\ApiClient;
class RetailCrmClientFactory implements RetailCrmClientFactoryInterface
{
public function createRetailCrmClient(Account $account, ?LoggerInterface $logger = null): ApiClient
{
if (null === $account) {
throw new \LogicException('Account is not selected');
}
if (empty($account->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;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace RetailCrm\DeliveryModuleBundle\Service;
use App\Entity\Account;
use Psr\Log\LoggerInterface;
use RetailCrm\ApiClient;
interface RetailCrmClientFactoryInterface
{
public function createRetailCrmClient(Account $account, ?LoggerInterface $logger = null): ApiClient;
}

33
composer.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "retailcrm/delivery-module-bundle",
"description": "Delivery module skeleton for RetailCrm",
"license": "MIT",
"type": "symfony-bundle",
"autoload": {
"psr-4": {
"RetailCrm\\DeliveryModuleBundle\\": ""
}
},
"require": {
"php": "^7.3",
"ramsey/uuid": "^3.9",
"ramsey/uuid-doctrine": "^1.5",
"symfony/framework-bundle": "^3.4|^4.0|^5.0",
"jms/serializer": "^3.4",
"jms/serializer-bundle": "^3.5",
"doctrine/orm": "^2.7",
"symfony/lock": "^5.0",
"retailcrm/api-client-php": "dev-add-logger@dev",
"symfony/translation": "^5.0",
"symfony/routing": "^5.0"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/raulleo/api-client-php.git"
}
],
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3"
}
}

Some files were not shown because too many files have changed in this diff Show More