OdooHelper.php 11.2 KB
<?php
    
    namespace artbox\odoo\components;
    
    use artbox\catalog\models\Category;
    use artbox\catalog\models\Product;
    use artbox\odoo\models\OdooToCategory;
    use artbox\odoo\models\OdooToOrder;
    use artbox\odoo\models\OdooToProduct;
    use artbox\order\models\Order;
    use yii\base\Object;
    use yii\helpers\ArrayHelper;
    
    class OdooHelper extends Object
    {
        /**
         * @var \artbox\odoo\components\Connection $db
         */
        protected $db;
        
        /**
         * OdooHelper constructor.
         *
         * @param array $config
         */
        public function __construct(array $config = [])
        {
            $this->db = \Yii::$app->get('odoo');
            parent::__construct($config);
        }
        
        /**
         * Create new partner for order
         *
         * @param \artbox\order\models\Order $order
         *
         * @return int
         */
        public function ensurePartner(Order $order): int
        {
            $builder = new Builder($this->db);
            /**
             * @var integer $result
             */
            $result = $builder->setParam('name', $order->name)
                              ->setParam('address', $order->address)
                              ->setParam('phone', $order->phone)
                              ->setParam('email', $order->email)
                              ->create('res.partner')
                              ->execute();
            return $result;
        }
        
        /**
         * Return OdooToOrder for current Order
         *
         * @param \artbox\order\models\Order $order
         *
         * @return \artbox\odoo\models\OdooToOrder
         */
        public function ensureOrder(Order $order): OdooToOrder
        {
            /**
             * @var OdooToOrder $result
             */
            $result = OdooToOrder::find()
                                 ->where(
                                     [
                                         'order_id' => $order->id,
                                     ]
                                 )
                                 ->one();
            if ($result && $this->validateOrder($result)) {
                return $result;
            }
            $builder = new Builder($this->db);
            $partnerId = $this->ensurePartner($order);
            $builder->setParam('partner_id', $partnerId);
            $orderId = $builder->create('sale.order')
                               ->execute();
            $result = new OdooToOrder(
                [
                    'order_id'  => $order->id,
                    'remote_id' => $orderId,
                ]
            );
            $result->save(false);
            return $result;
        }
        
        /**
         * Return OdooToProduct for current Product
         *
         * @param \artbox\catalog\models\Product $product
         *
         * @return \artbox\odoo\models\OdooToProduct
         */
        public function ensureProduct(Product $product): OdooToProduct
        {
            /**
             * @var OdooToProduct $result
             */
            $result = OdooToProduct::find()
                                   ->where(
                                       [
                                           'product_id' => $product->id,
                                       ]
                                   )
                                   ->one();
            if ($result && $this->validateProduct($result)) {
                return $result;
            }
            $builder = new Builder($this->db);
            $builder->setParam('name', $product->lang->title)
                    ->setParam('sale_ok', true)
                    ->setParam('purchase_ok', true)
                    ->setParam('list_price', $product->variant->price)
                    ->setParam('default_code', $product->variant->sku);
            if (!empty($product->category)) {
                $odooToCategory = $this->ensureCategory($product->category);
                $categoryId = $odooToCategory->category_id;
                $builder->setParam('categ_id[]', $categoryId);
            } else {
                $categoryId = null;
                $builder->setParam('categ_id[]', 1);
            }
            $productId = $builder->create('product.template')
                                 ->execute();
            $result = new OdooToProduct(
                [
                    'product_id' => $product->id,
                    'remote_id'  => $productId,
                ]
            );
            $result->save(false);
            return $result;
        }
        
        /**
         * Return OdooToCategory for current Category
         *
         * @param \artbox\catalog\models\Category $category
         *
         * @return \artbox\odoo\models\OdooToCategory
         */
        public function ensureCategory(Category $category): OdooToCategory
        {
            /**
             * @var OdooToCategory $result
             */
            $result = OdooToCategory::find()
                                    ->where(
                                        [
                                            'category_id' => $category->id,
                                        ]
                                    )
                                    ->one();
            if ($result && $this->validateCategory($result)) {
                return $result;
            }
            $builder = new Builder($this->db);
            $builder->setParam('name', $category->lang->title);
            $categoryId = $builder->create('product.category')
                                  ->execute();
            $result = new OdooToCategory(
                [
                    'category_id' => $category->id,
                    'remote_id'   => $categoryId,
                ]
            );
            $result->save(false);
            return $result;
        }
        
        /**
         * Write products from current Order to sale.order.line
         *
         * @param \artbox\order\models\Order $order
         */
        public function ensureSaleOrderLine(Order $order)
        {
            $odooToOrder = $this->ensureOrder($order);
            $orderProductIds = ArrayHelper::getColumn(
                ( new Query() )->from('sale.order.line')
                               ->where(
                                   [
                                       'order_id',
                                       '=',
                                       $odooToOrder->remote_id,
                                   ]
                               )
                               ->all(),
                'id'
            );
            foreach ($orderProductIds as $orderProductId) {
                $builder = new Builder($this->db);
                $builder->addId($orderProductId)
                        ->delete('sale.order.line')
                        ->execute();
            }
            foreach ($order->orderProducts as $orderProduct) {
                $builder = new Builder($this->db);
                $odooToProduct = $this->ensureProduct($orderProduct->variant->product);
                $productId = ( new Query() )->from('product.product')
                                            ->where(
                                                [
                                                    'product_tmpl_id',
                                                    '=',
                                                    $odooToProduct->remote_id,
                                                ]
                                            )
                                            ->one()[ 'id' ];
                $builder->setParam('order_id', $odooToOrder->remote_id)
                        ->setParam(
                            'product_id',
                            $productId
                        )//                            ->setParam('product_uom', 6)
                        ->setParam('product_uom_qty', $orderProduct->count)
                        ->setParam('price_unit', $orderProduct->price)
                        ->setParam('name', $orderProduct->variant->product->lang->title)
                        ->create('sale.order.line')
                        ->execute();
            }
        }
        
        /**
         * Validate OdooToOrder in sale.order
         *
         * @param \artbox\odoo\models\OdooToOrder $order
         * @param bool                            $delete
         *
         * @return bool
         */
        public function validateOrder(OdooToOrder $order, bool $delete = true): bool
        {
            $result = ( new Query() )->from('sale.order')
                                     ->where(
                                         [
                                             'id',
                                             '=',
                                             $order->remote_id,
                                         ]
                                     )
                                     ->one();
            if ($result) {
                return true;
            } else {
                if ($delete) {
                    $order->delete();
                }
                return false;
            }
        }
        
        /**
         * Validate OdooToProduct in product.template
         *
         * @param \artbox\odoo\models\OdooToProduct $product
         * @param bool                              $delete
         *
         * @return bool
         */
        public function validateProduct(OdooToProduct $product, bool $delete = true): bool
        {
            $result = ( new Query() )->from('product.template')
                                     ->where(
                                         [
                                             'id',
                                             '=',
                                             $product->remote_id,
                                         ]
                                     )
                                     ->one();
            if ($result) {
                return true;
            } else {
                if ($delete) {
                    $product->delete();
                }
                return false;
            }
        }
        
        /**
         * Validate OdooToCategory in product.category
         *
         * @param \artbox\odoo\models\OdooToCategory $category
         * @param bool                               $delete
         *
         * @return bool
         */
        public function validateCategory(OdooToCategory $category, bool $delete = true): bool
        {
            $result = ( new Query() )->from('product.category')
                                     ->where(
                                         [
                                             'id',
                                             '=',
                                             $category->remote_id,
                                         ]
                                     )
                                     ->one();
            if ($result) {
                return true;
            } else {
                if ($delete) {
                    $category->delete();
                }
                return false;
            }
        }
    }