src/Service/PrestashopApi.php line 205

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Api\PrestaShopWebservice;
  4. use App\Entity\Sale;
  5. use App\Repository\SaleRepository;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Symfony\Component\Console\Style\SymfonyStyle;
  8. class PrestashopApi
  9. {
  10.     private $em;
  11.     private $sr;
  12.     private $geo;
  13.     /**
  14.      * @var PrestaShopWebservice
  15.      */
  16.     private $client;
  17.     public function __construct(EntityManagerInterface $emSaleRepository $srGeocoding $geo)
  18.     {
  19.         $this->em $em;
  20.         $this->sr $sr;
  21.         $this->geo $geo;
  22.     }
  23.     public function init()
  24.     {
  25.         $url $_ENV['PRESTASHOP_API_URL'];
  26.         $key $_ENV['PRESTASHOP_API_KEY'];
  27.         if (!$url || !$key) {
  28.             throw new \InvalidArgumentException('No api url or key set in .env');
  29.         }
  30.         try {
  31.             $this->client = new PrestaShopWebservice($url$keyfalse);
  32.         } catch (\Exception $exception) {
  33.             return false;
  34.         }
  35.         return true;
  36.     }
  37.     public function getOrders($from_dateint $shop_id 1)
  38.     {
  39.         $now date('Y-m-d H:i:s'time() + 7200);
  40.         $opt = [
  41.             'resource' => 'orders',
  42.             'display' => 'full',
  43. //            'filter[current_state]' => '[3]',
  44.             'filter[date_upd]' => '[' $from_date ',' $now ']',
  45.             'date' => '1',
  46.             'id_shop' => $shop_id,
  47.         ];
  48.         $ret $this->client->get($opt);
  49.         return $ret->children()->children();
  50.     }
  51.     public function getOrder($id)
  52.     {
  53.         $opt = [
  54.             'resource' => 'orders',
  55.             'display' => 'full',
  56.             'id' => $id,
  57.         ];
  58.         $ret $this->client->get($opt);
  59.         return $ret->children()->order;
  60.     }
  61.     public function getCustomer($id)
  62.     {
  63.         $opt = [
  64.             'resource' => 'customers',
  65.             'id' => $id,
  66.         ];
  67.         $ret $this->client->get($opt);
  68.         return $ret->children()->children();
  69.     }
  70.     public function getMessage($order)
  71.     {
  72.         try {
  73.             $a $this->client->get([
  74.                 'resource' => 'customer_threads',
  75.                 'filter[id_order]' => '[' . (int)$order->id ']',
  76.             ]);
  77.             if (($thread_id = (int)$a->children()->children()->customer_thread['id']) > 0) {
  78.                 $b $this->client->get([
  79.                     'resource' => 'customer_messages',
  80.                     'display' => 'full',
  81.                     'filter[id_customer_thread]' => '[' $thread_id ']',
  82.                 ]);
  83.                 return (string)$b->children()->children()->customer_message->message;
  84.             }
  85.         } catch (\Exception $e) {
  86.             // do nothing
  87.         }
  88.         return '';
  89.     }
  90.     private $_address_cache = [];
  91.     public function getAddress($id$email)
  92.     {
  93.         if (!isset($this->_address_cache[$id])) {
  94.             $opt = [
  95.                 'resource' => 'addresses',
  96.                 'id' => $id,
  97.             ];
  98.             $a $this->client->get($opt);
  99.             $a $a->children()->children();
  100.             $street = (string)$a->address1;
  101.             $number = (string)$a->address2;
  102.             if ($number) { // if number is in address2, remove it from street
  103.                 $street preg_replace('/,?\s*' preg_quote($number'/') . '$/'''$street);
  104.             }
  105.             $addr = [
  106.                 'address_id' => (int)$a->id,
  107.                 'firstname' => (string)$a->firstname,
  108.                 'lastname' => (string)$a->lastname,
  109.                 'email' => $email,
  110.                 'telephone' => $this->getPhone($a),
  111.                 'street' => $street,
  112.                 'number' => $number,
  113.                 'toevoeging' => '',
  114.                 'postcode' => (string)$a->postcode,
  115.                 'city' => (string)$a->city,
  116.                 'country' => $this->getCountry((int)$a->id_country),
  117.                 'lat' => null,
  118.                 'lng' => null,
  119.             ];
  120.             if (($addr['number'] && $addr['postcode'] && ($addr['country'] === 'NL')) || ($addr['street'] && $addr['postcode'] && $addr['city'])) {
  121.                 [$lat$lng] = $this->geo->getLatLng($addr['street'], $addr['number'], $addr['postcode'], $addr['city'], $addr['country']);
  122.                 $addr['lat'] = $lat;
  123.                 $addr['lng'] = $lng;
  124.             }
  125.             $this->_address_cache[$id] = $addr;
  126.         }
  127.         return $this->_address_cache[$id];
  128.     }
  129.     private function getPhone($a)
  130.     {
  131.         $phone = [];
  132.         (string)$a->phone && $phone[] = (string)$a->phone;
  133.         (string)$a->phone_mobile && $phone[] = (string)$a->phone_mobile;
  134.         return implode(' / '$phone);
  135.     }
  136.     public function getCountry($c)
  137.     {
  138.         $ret 'Nederland?';
  139.         switch ($c) {
  140.             case 3// België
  141.             case 26// Bëlgie-Antwerpen
  142.             case 37// België-Brussel
  143.             case 33// België-Henegouwen
  144.             case 27// Bëlgie-Limburg
  145.             case 32// België-Luik
  146.             case 35// België-Luxemburg
  147.             case 34// België-Namen
  148.             case 28// België-Oost-Vlaanderen
  149.             case 30// België-Vlaams-Brabant
  150.             case 31// België-Waals-Brabant
  151.             case 29// België-West-Vlaanderen
  152.                 $ret 'België';
  153.                 break;
  154.             case 36// Duitsland-Nordrhein-Westfalen
  155.                 $ret 'Duitsland';
  156.                 break;
  157.             case 13// Nederland
  158.             case 18// Nederland-Brabant
  159.             case 14// Nederland-Drenthe
  160.             case 22// Nederland-Flevoland
  161.             case 15// Nederland-Friesland
  162.             case 16// Nederland-Gelderland
  163.             case 25// Nederland-Groningen
  164.             case 24// Nederland-Limburg
  165.             case 19// Nederland-Noord Holland
  166.             case 21// Nederland-Overijsel
  167.             case 17// Nederland-Utrecht
  168.             case 23// Nederland-Zeeland
  169.             case 20// Nederland-Zuid Holland
  170.                 $ret 'Nederland';
  171.                 break;
  172.         }
  173.         return $ret;
  174.     }
  175.     public function sync($from_date nullint $shop_id 1SymfonyStyle $io): void
  176.     {
  177.         try {
  178.             if ($orders $this->getOrders($from_date$shop_id)) {
  179.                 $io->progressStart(\count($orders));
  180.                 foreach ($orders as $order) {
  181.                     $sale $this->sr->get((int)$order->id);
  182.                     if ($sale->getId()) {
  183.                         $this->update($order$sale);
  184.                     } else {
  185.                         $this->create($order$sale);
  186.                     }
  187.                     $io->progressAdvance(1);
  188.                 }
  189.                 $io->progressFinish();
  190.             }
  191.         } catch (\Exception $e) {
  192.             throw new \Exception('error syncing Prestashop: ' $e->getMessage());
  193.         }
  194.     }
  195.     public function syncOrder($idSymfonyStyle $io): void
  196.     {
  197.         if ($order $this->getOrder($id)) {
  198.             $sale $this->sr->get((int)$order->id);
  199.             if ($sale->getId()) {
  200.                 $this->update($order$sale);
  201.                 $io->success('Sync updated order ' $id);
  202.             } else {
  203.                 $this->create($order$sale);
  204.                 $io->success('Sync imported order ' $id);
  205.             }
  206.         } else {
  207.             $io->error('Order ' $id ' does not exist');
  208.         }
  209.     }
  210.     private function create(\SimpleXMLElement $orderSale $sale): void
  211.     {
  212.         $customer $this->getCustomer((int)$order->id_customer);
  213.         
  214.         $ba $this->getAddress((int)$order->id_address_invoice, (string)$customer->email);
  215.         $sa $this->getAddress((int)$order->id_address_delivery, (string)$customer->email);
  216.         $total_paid = (float)$order->total_paid;
  217.         $tax round((float)$order->total_paid_tax_incl - (float)$order->total_paid_tax_excl2);
  218.         $info = [
  219.             'order_id' => (int)$order->id,
  220.             'increment_id' => (int)$order->id,
  221.             'subtotal' => (float)$order->total_products,
  222.             'shipping' => (float)$order->total_shipping,
  223.             'total' => $total_paid,
  224.             'tax' => $tax,
  225.             'total_paid' => $total_paid,
  226.             'total_due' => 0,
  227.             'payment_method' => $this->getPaymentMethod($order),
  228.             'shipping_method' => $this->getShippingMethod($order),
  229.             'description' => $this->getMessage($order),
  230.             'address' => [
  231.                 'billing' => $ba,
  232.                 'shipping' => $sa
  233.             ],
  234.             'company' => false,
  235.             'items' => $this->getItemsFromOrder($order),
  236.         ];
  237.         $sale->setType(Sale::TYPE_PRESTASHOP);
  238.         $sale->setStatus($this->getStatus($order));
  239.         $sale->setInfo($info);
  240.         $sale->setStore(Sale::STORE_VINKBOMEN);
  241.         $sale->setPickup($info['shipping'] === 'ophalen');
  242.         $sale->setCreatedAt(new \DateTime($order['created_at']));
  243.         $this->em->persist($sale);
  244.         $this->em->flush();
  245.         sleep(1);
  246.     }
  247.     private function update(\SimpleXMLElement $orderSale $sale): void
  248.     {
  249.         try {
  250.             $sale->setStatus($this->getStatus($order));
  251.             $info $sale->getInfo();
  252.             $info['total_paid'] = (float)$order->total_paid;
  253. //            $info['total_due'] = (float)$order['total_due'];
  254.             $info['items'] = $this->getItemsFromOrder($order);
  255.             $sale->setInfo($info);
  256.             $this->em->persist($sale);
  257.             $this->em->flush();
  258.         } catch (\Exception $e) {
  259.         }
  260.     }
  261.     private function getItemsFromOrder(\SimpleXMLElement $order): array
  262.     {
  263.         $items = [];
  264.         foreach ($order->associations->order_rows->order_row as $item) {
  265.             $quantity = (int)$item->product_quantity;
  266.             $price round((float)$item->unit_price_tax_incl2);
  267.             $items[] = [
  268.                 'item_id' => (int)$item->id,
  269.                 'product_id' => (int)$item->product_id,
  270.                 'sku' => (string)$item->product_reference,
  271.                 'name' => (string)$item->product_name,
  272.                 'quantity' => $quantity,
  273.                 'price' => $price,
  274.                 'total' => round($price $quantity2),
  275.                 'tax_invoiced' => null,
  276.                 'tax_percent' => null,
  277.             ];
  278.         }
  279.         return $items;
  280.     }
  281.     private function getStatus(\SimpleXMLElement $order)
  282.     {
  283.         /**
  284.          * 0 => Awaiting bank wire payment
  285.          * 1 => Awaiting Cash On Delivery validation
  286.          * 2 => Awaiting check payment
  287.          * 3 => Canceled
  288.          * 4 => Delivered
  289.          * 5 => On backorder (not paid)
  290.          * 6 => On backorder (paid)
  291.          * 7 => Payment accepted
  292.          * 8 => Payment error
  293.          * 9 => Processing in progress
  294.          * 10 => Refunded
  295.          * 11 => Remote payment accepted
  296.          * 12 => Shipped
  297.          */
  298.         switch ((int)$order->current_state) {
  299.             case 1// => Awaiting check payment
  300.             case 10// => Awaiting bank wire payment
  301.             case 11// => Awaiting Paypal payment
  302.             case 14// => Awaiting cod validation
  303.                 return Sale::STATUS_PENDING;
  304.             case 6// => Canceled
  305.             case 7// => Refunded
  306.                 return Sale::STATUS_CANCELLED;
  307.             case 8// => Payment error
  308.             case 13// => On backorder (not paid)
  309.                 return Sale::STATUS_ON_HOLD;
  310.             case 2// => Payment accepted
  311.             case 3// => Processing in progress
  312.             case 9// => On backorder (paid)
  313.             case 12// => Remote payment accepted
  314.                 return Sale::STATUS_PROCESSING;
  315.             case 4// => Shipped
  316.             case 5// => Delivered
  317.                 return Sale::STATUS_CLOSED;
  318. //                return Sale::STATUS_COMPLETED;
  319.         }
  320.         return '?';
  321.     }
  322.     private function getPaymentMethod(\SimpleXMLElement $order)
  323.     {
  324.         switch ((string)$order->module) {
  325.             case 'cashondelivery':
  326.             case 'ps_checkpayment':
  327.                 return 'cashondelivery';
  328.         }
  329.         return 'ideal';
  330. //        return 'pin';
  331. //        return 'ideal';
  332. //        return 'cashondelivery';
  333.     }
  334.     private function getShippingMethod(\SimpleXMLElement $order)
  335.     {
  336.         switch ((int)$order->id_carrier) {
  337.             case 1:
  338.                 return 'ophalen';
  339.             case 2:
  340.                 return 'leveren';
  341.         }
  342.         return 'leveren';
  343.     }
  344. }