721 lines
28 KiB
PHP
721 lines
28 KiB
PHP
<?php
|
|
|
|
namespace KupShop\DropshipBundle\Transfer;
|
|
|
|
use KupShop\AdminBundle\Util\ActivityLog;
|
|
use KupShop\DropshipBundle\TransferInterface;
|
|
use KupShop\DropshipBundle\Util\TransferWorker;
|
|
use KupShop\KupShopBundle\Context\ContextManager;
|
|
use KupShop\KupShopBundle\Context\CountryContext;
|
|
use KupShop\KupShopBundle\Context\CurrencyContext;
|
|
use KupShop\KupShopBundle\Context\LanguageContext;
|
|
use KupShop\KupShopBundle\Query\JsonOperator;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
use KupShop\KupShopBundle\Util\StringUtil;
|
|
use KupShop\OrderingBundle\Event\OrderEvent;
|
|
use KupShop\OrderingBundle\Util\Order\OrderInfo;
|
|
use KupShop\OrderingBundle\Util\Order\OrderItemInfo;
|
|
use Psr\Log\LoggerInterface;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
class ChannableTransfer extends AbstractTransfer implements TransferInterface
|
|
{
|
|
protected static string $type = 'channable';
|
|
protected static string $name = 'Channable';
|
|
|
|
public const API_URL_START = 'https://api.channable.com/v1/companies/';
|
|
|
|
public ContextManager $contextManager;
|
|
|
|
private HttpClientInterface $httpClient;
|
|
/** @required */
|
|
public TransferWorker $transferWorker;
|
|
|
|
protected LoggerInterface $logger;
|
|
|
|
public function __construct(HttpClientInterface $httpClient, LoggerInterface $logger)
|
|
{
|
|
$this->httpClient = $httpClient;
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
#[Required]
|
|
final public function setContextManager(ContextManager $contextManager)
|
|
{
|
|
$this->contextManager = $contextManager;
|
|
}
|
|
|
|
public function sendTrackingInfoToChannable(): void
|
|
{
|
|
$qb = $this->getOrdersForUpdate();
|
|
|
|
foreach ($qb->execute() as $item) {
|
|
$order = new \Order();
|
|
$order->createFromDB($item['id']);
|
|
|
|
$connectionData = $this->getConnectionData();
|
|
|
|
if (!$connectionData) {
|
|
$this->addActivityLog('V nastavení dropshipmentu chybí potřebné údaje pro komunikaci s Channable',
|
|
severity: ActivityLog::SEVERITY_WARNING);
|
|
|
|
return;
|
|
}
|
|
|
|
$orderInfo = ServiceContainer::getService(OrderInfo::class);
|
|
$delivery = $order->getDeliveryType()->getDelivery()->class;
|
|
$packages = array_keys($orderInfo->getPackages($order));
|
|
|
|
$connectionData['url'] .= '/'.$item['channable_id'].'/shipment';
|
|
|
|
// load order items
|
|
$connectionData['body']['products'] = json_decode($order->note_admin, true)['channable']['channable_item_ids'] ?? [];
|
|
$connectionData['body']['packages'] = $packages[0];
|
|
$connectionData['body']['delivery'] = $delivery;
|
|
|
|
if ($this->sendTrackingInfo($connectionData)) {
|
|
$order->logHistory('Informace o balíku byly odeslány do Channable');
|
|
$this->addActivityLog('Informace o balíku byly odeslány do Channable - objednávka: '.$order->order_no, $connectionData['body'], severity: ActivityLog::SEVERITY_SUCCESS);
|
|
|
|
sqlQuery('UPDATE order_dropshipment SET data = JSON_OBJECT("trackingSent", "Y")
|
|
WHERE id_order = :order_id AND id_dropshipment = :id_dropshipment',
|
|
['order_id' => $item['id'], 'id_dropshipment' => $this->dropshipment['id']]);
|
|
continue;
|
|
}
|
|
|
|
$this->addActivityLog('Nepodařilo se odestal informace o balíku do Channable u objednávky č. '.$order->order_no);
|
|
$order->logHistory('Nepodařilo se odestal informace o balíku do Channable');
|
|
}
|
|
}
|
|
|
|
protected function getExternalData(\SimpleXMLElement $xml): array
|
|
{
|
|
// TODO: Implement getExternalData() method.
|
|
return [];
|
|
}
|
|
|
|
protected function getDeliveryTypeByConfiguration(\SimpleXMLElement $order): ?\DeliveryType
|
|
{
|
|
// TODO: Implement getDeliveryTypeByConfiguration() method.
|
|
return null;
|
|
}
|
|
|
|
public function in(array $config): void
|
|
{
|
|
$ordersJson = $this->getOrders();
|
|
$orders = json_decode($ordersJson, true)['orders'] ?? [];
|
|
|
|
$countryContext = Contexts::get(CountryContext::class);
|
|
|
|
foreach ($orders as $orderData) {
|
|
$this->contextManager->activateContexts([CountryContext::class => $orderData['data']['billing']['country_code'] ?? $countryContext->getDefaultId()],
|
|
function () use ($orderData) {
|
|
// log incoming order to Kibana
|
|
$this->logger->notice(self::$name.' IN', $orderData);
|
|
|
|
$externalId = $orderData['channel_id'];
|
|
if (!$externalId) {
|
|
$this->addActivityLog(
|
|
'Nepodařilo se naimportovat objednávku do e-shopu, protože nemá externí ID. V odpovědi z Channable chybí ID',
|
|
$orderData
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
// hledame i podle platform_id, protoze nektere objednavky to maji nastavene jako id_external
|
|
$order = $this->getOrderByExternalId($externalId) ?? $this->getOrderByExternalId($orderData['platform_id'] ?? '');
|
|
|
|
if ($order) {
|
|
$this->updateChannableOrder($order, $orderData);
|
|
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$order = sqlGetConnection()->transactional(function () use ($externalId, $orderData) {
|
|
$currencyInfo = $this->getCurrencyInfo($orderData['data']['price']['currency']);
|
|
|
|
$data = $this->getOrderBaseData($orderData);
|
|
$data['currency_rate'] = $currencyInfo->rate->asFloat();
|
|
|
|
$order = $this->createChannableOrder($data, $externalId);
|
|
|
|
$orderItems = [];
|
|
foreach ($orderData['data']['products'] as $item) {
|
|
[$code, $ean] = $this->getProductFromItem($item);
|
|
[$productId, $variationId] = $this->getProductByCode($code, $ean ?? null);
|
|
|
|
$pieces = toDecimal($item['quantity']);
|
|
$piecePrice = $this->convertPrice(toDecimal($item['price']), $currencyInfo);
|
|
$totalPrice = $this->convertPrice(toDecimal($item['price'])->mul($pieces), $currencyInfo);
|
|
|
|
if ($productId) {
|
|
$product = \Variation::createProductOrVariation($productId, $variationId);
|
|
$product->createFromDB();
|
|
$product->sell($variationId, $pieces->asFloat());
|
|
|
|
$piecePrice = $piecePrice->removeVat($product->vat);
|
|
$totalPrice = $totalPrice->removeVat($product->vat);
|
|
}
|
|
|
|
$productTitle = empty($product->title) ? $item['title'] : $product->title;
|
|
|
|
$itemData = [
|
|
'id_order' => $order->id,
|
|
'id_product' => $product->id ?? null,
|
|
'id_variation' => $variationId,
|
|
'pieces' => $pieces->asFloat(),
|
|
'piece_price' => $piecePrice->asFloat(),
|
|
'total_price' => $totalPrice->asFloat(),
|
|
'descr' => $productTitle,
|
|
'tax' => $item['tax'] ?? $product->vat ?? '',
|
|
];
|
|
|
|
sqlQueryBuilder()
|
|
->insert('order_items')
|
|
->directValues($itemData)
|
|
->execute();
|
|
$itemData['id'] = sqlInsertId();
|
|
|
|
$orderItems[] = $itemData;
|
|
|
|
$this->itemCreatedEvent(
|
|
product: $product ?? null,
|
|
idVariation: (int) $variationId,
|
|
piecePrice: $piecePrice,
|
|
pieces: $pieces->asInteger(),
|
|
data: [
|
|
'row' => $itemData,
|
|
'items_table' => 'order_items',
|
|
],
|
|
order: $order
|
|
);
|
|
|
|
unset($product);
|
|
}
|
|
|
|
$this->insertDeliveryItem($order, $orderData, $orderItems ?? []);
|
|
$order->recalculate(round: false);
|
|
|
|
if (!$order->isPaid() && $data['status_payed'] == 1) {
|
|
$this->payDropshipOrder($order);
|
|
}
|
|
|
|
return $order;
|
|
});
|
|
} catch (\Throwable $e) {
|
|
$this->transferWorker->logException($e, $this);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public function out(array $config): void
|
|
{
|
|
if (isDevelopment()) {
|
|
return;
|
|
}
|
|
|
|
$this->sendTrackingInfoToChannable();
|
|
$this->sendCancelledOrders();
|
|
}
|
|
|
|
protected function sendCancelledOrders()
|
|
{
|
|
$configuration = $this->getConfiguration();
|
|
|
|
if ($configuration['do_not_storno_orders'] == 'Y' ?? false) {
|
|
return;
|
|
}
|
|
|
|
$qb = $this->getCancelledOrders();
|
|
|
|
foreach ($qb->execute() as $cancelledOrder) {
|
|
$order = new \Order();
|
|
$order->createFromDB($cancelledOrder['id']);
|
|
|
|
$connectionData = $this->getConnectionData();
|
|
|
|
if (!$connectionData) {
|
|
$this->addActivityLog('V nastavení dropshipmentu chybí potřebné údaje pro komunikaci s Channable',
|
|
severity: ActivityLog::SEVERITY_WARNING);
|
|
|
|
return;
|
|
}
|
|
|
|
$connectionData['url'] .= '/'.$cancelledOrder['channable_id'].'/cancel';
|
|
|
|
$connectionData['body']['products'] = json_decode($order->note_admin, true)['channable']['channable_item_ids'] ?? [];
|
|
|
|
if ($this->sendCancelledOrder($connectionData)) {
|
|
$order->logHistory('Informace o zrušení objednávky byly odeslány do Channable');
|
|
sqlQuery('UPDATE order_dropshipment SET data = JSON_OBJECT("cancelSent", "Y")
|
|
WHERE id_order = :order_id AND id_dropshipment = :id_dropshipment',
|
|
['order_id' => $cancelledOrder['id'], 'id_dropshipment' => $this->dropshipment['id']]);
|
|
continue;
|
|
}
|
|
|
|
$this->addActivityLog('Nepodařilo se odeslat informace o zrušení objednávky do Channable u objednávky č. '.$order->order_no);
|
|
|
|
$order->logHistory('Nepodařilo se odeslat informace o zrušení objednávky do Channable');
|
|
}
|
|
}
|
|
|
|
protected function getOrders(): ?string
|
|
{
|
|
$connectionData = $this->getConnectionData();
|
|
|
|
if (!$connectionData) {
|
|
$this->addActivityLog('V nastavení dropshipmentu chybí potřebné údaje pro komunikaci s Channable',
|
|
severity: ActivityLog::SEVERITY_WARNING);
|
|
|
|
return null;
|
|
}
|
|
|
|
$lastSyncTime = $this->getLastSyncTime();
|
|
|
|
// potrebuju prevest $lastSyncTime na UTC cas, jinak se stavalo, ze se objednavky vubec na shop nedostavaly
|
|
$time = new \DateTime($lastSyncTime);
|
|
$time->setTimezone(new \DateTimeZone('UTC'));
|
|
|
|
$lastSyncTime = $time->format('Y-m-d H:i:s');
|
|
|
|
$response = $this->httpClient->request(
|
|
'GET',
|
|
$connectionData['url'],
|
|
[
|
|
'headers' => [
|
|
'Authorization' => $connectionData['api_key'],
|
|
],
|
|
'query' => [
|
|
'last_modified_after' => $lastSyncTime ?? date('Y-m-d H:i:s', strtotime('-1 day')),
|
|
],
|
|
]
|
|
);
|
|
|
|
if ($response->getStatusCode() != 200) {
|
|
$this->addActivityLog('Nepodařilo se načíst objednávky z Channable', [$response->getContent(false)]);
|
|
|
|
return '';
|
|
}
|
|
|
|
$logData = ['last_sync_time' => $lastSyncTime];
|
|
$this->addActivityLog('Načtení objednávek z Channable proběhlo úspěšně', data: $logData, severity: ActivityLog::SEVERITY_SUCCESS);
|
|
|
|
return $response->getContent(false);
|
|
}
|
|
|
|
protected function sendTrackingInfo(array $data): bool
|
|
{
|
|
$response = $this->httpClient->request(
|
|
'POST',
|
|
$data['url'],
|
|
[
|
|
'headers' => [
|
|
'Authorization' => $data['api_key'],
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
'body' => json_encode([
|
|
'order_item_ids' => $data['body']['products'],
|
|
'tracking_code' => (string) $data['body']['packages'],
|
|
]),
|
|
]
|
|
);
|
|
|
|
if ($response->getStatusCode() != 200) {
|
|
$this->addActivityLog('[Channable] Odesílání informací o doručení - chybná response', [$response->getContent(false)]);
|
|
$this->addActivityLog('Nepodařilo se odeslat informace o balíku do Channable', [$response->getContent(false)]);
|
|
|
|
return false;
|
|
}
|
|
|
|
$this->addActivityLog('[Channable] Odesílání informací o doručení - response', [$response->getContent(false)], severity: ActivityLog::SEVERITY_SUCCESS);
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function sendCancelledOrder(array $data): bool
|
|
{
|
|
$response = $this->httpClient->request(
|
|
'POST',
|
|
$data['url'],
|
|
[
|
|
'headers' => [
|
|
'Authorization' => $data['api_key'],
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
'body' => json_encode([
|
|
'order_item_ids' => $data['body']['products'],
|
|
]),
|
|
]
|
|
);
|
|
|
|
if ($response->getStatusCode() != 200) {
|
|
$this->addActivityLog('Nepodařilo se odeslat informace o zrušení objednávky do Channable', [$response->getContent(false)]);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function updateChannableOrder(\Order $order, array $orderData): void
|
|
{
|
|
$data = $this->getOrderBaseData($orderData);
|
|
|
|
if (!$order->isPaid() && $data['status_payed'] == 1) {
|
|
sqlQueryBuilder()
|
|
->update('orders')
|
|
->directValues(['status_payed' => 1])
|
|
->where(Operator::equals(['id' => $order->id]))
|
|
->execute();
|
|
|
|
$this->payDropshipOrder($order);
|
|
}
|
|
}
|
|
|
|
protected function getOrderBaseData(array $order): array
|
|
{
|
|
$configuration = $this->getConfiguration();
|
|
|
|
$data = [];
|
|
|
|
$useMarketplaceOrderNo = $configuration['use_marketplace_order_no'] ?? 'N';
|
|
if ($useMarketplaceOrderNo === 'Y') {
|
|
$data['order_no'] = $order['channel_id'];
|
|
}
|
|
$data['note_invoice'] = $order['channel_id'];
|
|
|
|
$data['date_created'] = $this->dateTimeConvertor($order['created']);
|
|
$data['date_updated'] = $this->dateTimeConvertor($order['modified']);
|
|
$data['currency'] = $order['data']['price']['currency'];
|
|
$data['status'] = 0;
|
|
$data['status_payed'] = $order['status_paid'] === 'paid' ? 1 : 0;
|
|
|
|
$data['total_price'] = 0.0000; // 0 => RECALCULATE
|
|
|
|
// INVOICE
|
|
$data['invoice_name'] = $order['data']['billing']['first_name'].' '.$order['data']['billing']['middle_name'];
|
|
$data['invoice_surname'] = $order['data']['billing']['last_name'] ?? '';
|
|
$data['invoice_firm'] = $order['data']['billing']['company'] ?? '';
|
|
$data['invoice_dic'] = $order['data']['billing']['vat_number'] ?? '';
|
|
$data['invoice_street'] = $order['data']['billing']['address1'] ?? '';
|
|
$data['invoice_city'] = $order['data']['billing']['city'] ?? '';
|
|
$data['invoice_zip'] = $order['data']['billing']['zip_code'] ?? '';
|
|
$data['invoice_country'] = $order['data']['billing']['country_code'] ?? '';
|
|
$data['invoice_email'] = $order['data']['billing']['email'] ?? '';
|
|
$data['invoice_phone'] = $order['data']['customer']['phone'] ?? '';
|
|
|
|
// DELIVERY
|
|
$data['delivery_name'] = $order['data']['shipping']['first_name'].' '.$order['data']['shipping']['middle_name'];
|
|
$data['delivery_surname'] = $order['data']['shipping']['last_name'] ?? '';
|
|
$data['delivery_firm'] = $order['data']['shipping']['company'] ?? '';
|
|
$data['delivery_street'] = $order['data']['shipping']['address1'] ?? '';
|
|
$data['delivery_city'] = $order['data']['shipping']['city'] ?? '';
|
|
$data['delivery_zip'] = $order['data']['shipping']['zip_code'] ?? '';
|
|
$data['delivery_country'] = $order['data']['shipping']['country_code'] ?? '';
|
|
$data['delivery_phone'] = $order['data']['customer']['phone'] ?? '';
|
|
|
|
$deliveryType = $this->getDelivery($order);
|
|
$data['delivery_type'] = $deliveryType->name ?? '';
|
|
$data['id_delivery'] = $deliveryType->id ?? null;
|
|
|
|
$data['id_language'] = $this->getOrderLanguage($order, $configuration);
|
|
|
|
$channableOrderItemIds = [];
|
|
foreach ($order['data']['products'] as $item) {
|
|
$channableOrderItemIds[] = $item['channable_order_item_id'] ?? null;
|
|
}
|
|
|
|
$data['note_admin'] = json_encode(
|
|
[
|
|
'channable' => [
|
|
'id' => $order['id'],
|
|
'channel_name' => $order['channel_name'],
|
|
'platform_name' => $order['platform_name'],
|
|
'project_id' => $order['project_id'],
|
|
'order_config_id' => $order['order_config_id'],
|
|
'platform_id' => $order['platform_id'],
|
|
'channel_id' => $order['channel_id'],
|
|
'channable_item_ids' => $channableOrderItemIds,
|
|
],
|
|
],
|
|
);
|
|
|
|
$flags = ['DSC'];
|
|
$data['flags'] = implode(',', $flags);
|
|
|
|
return $data;
|
|
}
|
|
|
|
protected function createChannableOrder(array $data, int|string $externalId)
|
|
{
|
|
/** @var \Order $order */
|
|
$order = sqlGetConnection()->transactional(function () use ($data) {
|
|
sqlQueryBuilder()
|
|
->insert('orders')
|
|
->directValues(array_merge(['source' => OrderInfo::ORDER_SOURCE_DROPSHIP], $data))
|
|
->execute();
|
|
|
|
$order = \Order::get((int) sqlInsertId());
|
|
|
|
// dispatch order created event - order no is generated in event subscriber
|
|
$this->eventDispatcher->dispatch(new OrderEvent($order), OrderEvent::ORDER_CREATED);
|
|
|
|
return $order;
|
|
});
|
|
|
|
// vytvorim mapovani na dropshipment
|
|
sqlQueryBuilder()
|
|
->insert('order_dropshipment')
|
|
->directValues(
|
|
[
|
|
'id_order' => $order->id,
|
|
'id_dropshipment' => $this->dropshipment['id'],
|
|
'id_external' => $externalId,
|
|
]
|
|
)->execute();
|
|
|
|
// zalogovat informaci o vytvoreni objednavky
|
|
$order->logHistory(
|
|
sprintf('[Dropshipment] <a href="javascript:nw(\'Dropshipment\', %s);">%s</a>: %s',
|
|
$this->dropshipment['id'],
|
|
'channable',
|
|
$externalId)
|
|
);
|
|
|
|
return $order;
|
|
}
|
|
|
|
protected function getDelivery(array $order): ?\DeliveryType
|
|
{
|
|
$channelConfiguration = $this->getChannelConfiguration($order);
|
|
|
|
$deliveryId = null;
|
|
$country = $order['data']['shipping']['country_code'];
|
|
foreach ($channelConfiguration['deliveries'] ?? [] as $delivery) {
|
|
if (empty($delivery['country']) || $delivery['country'] === $country) {
|
|
$deliveryId = (int) $delivery['id_delivery'];
|
|
}
|
|
}
|
|
|
|
$paymentId = empty($channelConfiguration['payments']['default']) ? null : (int) $channelConfiguration['payments']['default'];
|
|
|
|
return $this->findDeliveryType($deliveryId, $paymentId);
|
|
}
|
|
|
|
protected function getChannelConfiguration(array $order): array
|
|
{
|
|
$configuration = $this->getConfiguration();
|
|
$channelName = $order['channel_name'];
|
|
|
|
$channelConfiguration = null;
|
|
$default = null;
|
|
|
|
foreach ($configuration['marketplaces'] ?? [] as $marketplace) {
|
|
if (StringUtil::slugify($marketplace['name']) === StringUtil::slugify($channelName)) {
|
|
$channelConfiguration = $marketplace;
|
|
break;
|
|
}
|
|
|
|
if (empty($marketplace['name'])) {
|
|
$default = $marketplace;
|
|
}
|
|
}
|
|
|
|
if (!$channelConfiguration && $default) {
|
|
$channelConfiguration = $default;
|
|
}
|
|
|
|
return $channelConfiguration ?: [];
|
|
}
|
|
|
|
protected function insertDeliveryItem(\Order $order, array $data, array $orderItems): void
|
|
{
|
|
$dbcfg = \Settings::getDefault();
|
|
|
|
$deliveryPrice = $this->getDeliveryPrice($order);
|
|
|
|
$tax = ($dbcfg->delivery_config['from_products'] ?? 'N') == 'Y' ?
|
|
$this->getDeliveryVatFromProducts($orderItems)
|
|
: $deliveryPrice->getVat() ?? \DecimalConstants::zero();
|
|
|
|
$shippingPrice = toDecimal($data['data']['price']['shipping']) ?? $deliveryPrice->getPriceWithVat() ?? \DecimalConstants::zero();
|
|
$shippingPrice = $shippingPrice->removeVat($tax);
|
|
|
|
$insertData = [
|
|
'id_order' => $order->id,
|
|
'id_product' => null,
|
|
'id_variation' => null,
|
|
'pieces' => 1,
|
|
'pieces_reserved' => 1,
|
|
'piece_price' => $shippingPrice ?? $deliveryPrice->getPriceWithoutVat(),
|
|
'total_price' => $shippingPrice ?? $deliveryPrice->getPriceWithoutVat(),
|
|
'tax' => $tax ?? 0,
|
|
'descr' => 'Doprava a platba',
|
|
'note' => json_encode(['item_type' => OrderItemInfo::TYPE_DELIVERY]),
|
|
];
|
|
|
|
sqlQueryBuilder()
|
|
->insert('order_items')
|
|
->directValues($insertData)
|
|
->execute();
|
|
}
|
|
|
|
protected function getDeliveryPrice(\Order $order)
|
|
{
|
|
$deliveryType = $order->getDeliveryType();
|
|
|
|
$deliveryPrice = $this->contextManager->activateContexts(
|
|
[
|
|
CurrencyContext::class => $order->currency,
|
|
],
|
|
function () use ($deliveryType) {
|
|
return $deliveryType->getPrice();
|
|
}
|
|
);
|
|
|
|
return $deliveryPrice;
|
|
}
|
|
|
|
protected function getOrdersForUpdate(): QueryBuilder
|
|
{
|
|
$qb = parent::getOrdersForUpdate();
|
|
$qb->addSelect('JSON_VALUE(o.note_admin, "$.channable.id") as channable_id');
|
|
$qb->andWhere(
|
|
Operator::equalsNullable([JsonOperator::value('od.data', 'trackingSent') => null])
|
|
)
|
|
->andWhere(
|
|
Operator::not(Operator::equalsNullable([JsonOperator::value('o.note_admin', 'channable.*') => null]))
|
|
)
|
|
->andWhere(Operator::inIntArray([(int) str_replace('"', '', $this->getConfigurationStatus())], 'o.status'));
|
|
|
|
return $qb;
|
|
}
|
|
|
|
protected function getConfigurationStatus(): string
|
|
{
|
|
return sqlQueryBuilder()
|
|
->select('JSON_EXTRACT(configuration, "$.statuses[0]") as statuses')
|
|
->from('dropshipment')
|
|
->where(Operator::equals(['id' => $this->dropshipment['id']]))
|
|
->execute()->fetchOne();
|
|
}
|
|
|
|
protected function getCancelledOrders(): QueryBuilder
|
|
{
|
|
return sqlQueryBuilder()
|
|
->select('o.id as id, od.id_external as id_external, JSON_VALUE(o.note_admin, "$.channable.id") as channable_id')
|
|
->from('orders', 'o')
|
|
->join('o', 'order_dropshipment', 'od', 'o.id = od.id_order AND od.id_dropshipment = :dropshipment_id')
|
|
->where('o.status_storno = 1')
|
|
->andWhere(Operator::equalsNullable([JsonOperator::value('od.data', 'cancelSent') => null]))
|
|
->andWhere(Operator::equalsNullable([JsonOperator::value('od.data', 'trackingSent') => null]))
|
|
->setParameter('dropshipment_id', $this->dropshipment['id']);
|
|
}
|
|
|
|
public function prepareConfigurationData(array $data): array
|
|
{
|
|
foreach ($data['marketplaces'] ?? [] as $key => $marketplace) {
|
|
// zpracovani mapovani doprav
|
|
foreach ($marketplace['deliveries'] ?? [] as $dKey => $delivery) {
|
|
$delivery = array_filter($delivery);
|
|
|
|
if (!empty($delivery['delete'])) {
|
|
unset($data['marketplaces'][$key]['deliveries'][$dKey]);
|
|
continue;
|
|
}
|
|
|
|
if ($dKey <= 0) {
|
|
if (!empty($delivery['id_delivery'])) {
|
|
$data['marketplaces'][$key]['deliveries'][] = $delivery;
|
|
}
|
|
|
|
unset($data['marketplaces'][$key]['deliveries'][$dKey]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$data['marketplaces'] = array_values($data['marketplaces'] ?? []);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function getConnectionData(): ?array
|
|
{
|
|
$url = self::API_URL_START;
|
|
$data = $this->getChannableData();
|
|
|
|
$companyId = str_replace('"', '', $data['company_id']);
|
|
$project_id = str_replace('"', '', $data['project_id']);
|
|
|
|
if (!$data['company_id'] || !$data['project_id'] || !$data['api_key']) {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'url' => $url.(int) $companyId.'/projects/'.(int) $project_id.'/orders',
|
|
'api_key' => 'Bearer '.$data['api_key'],
|
|
];
|
|
}
|
|
|
|
protected function getChannableData()
|
|
{
|
|
return sqlQueryBuilder()
|
|
->select('JSON_EXTRACT(data, \'$.company_id\') as company_id, JSON_EXTRACT(data, \'$.project_id\') as project_id, source_url as api_key')
|
|
->from('dropshipment')
|
|
->where(Operator::equals(['id' => $this->dropshipment['id']]))
|
|
->execute()
|
|
->fetchAssociative();
|
|
}
|
|
|
|
protected function getOrderLanguage(array $order, array $configuration): string
|
|
{
|
|
$languageContext = Contexts::get(LanguageContext::class);
|
|
$marketplace = array_filter($configuration['marketplaces'], fn ($marketplace) => strtolower($marketplace['name']) === strtolower($order['channel_name'])) ?? [];
|
|
$marketplace = reset($marketplace);
|
|
|
|
return $marketplace['settings']['id_language'] ?? $languageContext->getDefaultId();
|
|
}
|
|
|
|
protected function getProductFromItem(array $item): array
|
|
{
|
|
$return = [null, null];
|
|
|
|
if ($item['id']) {
|
|
$return[0] = $item['id'];
|
|
}
|
|
|
|
if ($item['ean']) {
|
|
$return[1] = $item['ean'];
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
protected function getDeliveryVatFromProducts(array $orderItems): int
|
|
{
|
|
return array_reduce($orderItems, function ($maxVat, $product) {
|
|
$vat = (int) $product['tax'] ?? 0;
|
|
|
|
return ($vat > $maxVat) ? $vat : $maxVat;
|
|
}, 0);
|
|
}
|
|
|
|
/**
|
|
* Converts datetime to specific timezone.
|
|
*/
|
|
private function dateTimeConvertor(string $datetime, string $timezone = 'Europe/Prague')
|
|
{
|
|
$date = new \DateTime($datetime);
|
|
$date->setTimezone(new \DateTimeZone($timezone));
|
|
|
|
return $date->format('Y-m-d H:i:s');
|
|
}
|
|
}
|