HEX
Server: Apache
System: Linux srv13.cpanelhost.cl 3.10.0-962.3.2.lve1.5.38.el7.x86_64 #1 SMP Thu Jun 18 05:28:41 EDT 2020 x86_64
User: cca63905 (4205)
PHP: 7.3.20
Disabled: NONE
Upload Files
File: /home4/cca63905/www/nueva/modules/roja45quotationsprofree/classes/RojaQuotation.php
<?php
/**
 * RojaQuotation.
 *
 * @author    Roja45
 * @copyright 2016 Roja45
 * @license   license.txt
 * @category  RojaQuotation
 *
 * @link      http://www.roja45.com/
 *
 * 2016 ROJA45 - All rights reserved.
 *
 * DISCLAIMER
 * Changing this file will render any support provided by us null and void.
 */

/**
 * RojaQuotation.
 *
 * @author    Roja45
 * @copyright 2016 Roja45
 * @license   license.txt
 * @category  Class
 *
 * 2016 ROJA45 - All rights reserved.
 *
 * DISCLAIMER
 * Changing this file will render any support provided by us null and void.
 */

class RojaQuotation extends ObjectModel
{
    public $id_roja45_quotation;
    public $id_roja45_quotation_status;
    public $id_lang;
    public $id_shop;
    public $id_currency;
    public $id_country;
    public $id_state;
    public $id_address;
    public $id_carrier;
    public $date_add;
    public $date_upd;
    public $valid_days;
    public $expiry_date;
    public $email;
    public $firstname;
    public $lastname;
    public $form_data;
    public $reference;
    public $calculate_taxes;
    public $modified;
    public $quote_sent;
    public $id_customer;
    public $tmp_password;
    public $id_cart;
    public $id_order;
    public $purchase_date;
    public $id_employee;
    public $total_to_pay;
    public $total_to_pay_wt;
    public $total_products;
    public $total_products_wt;
    public $total_shipping;
    public $total_shipping_wt;
    public $total_handling;
    public $total_handling_wt;
    public $total_wrapping;
    public $total_discount;
    public $total_discount_wt;
    public $total_charges;
    public $total_charges_wt;

    protected $_taxCalculationMethod = PS_TAX_EXC;
    private $is_dirty;
    private $quotation_total_shipping;
    private $quotation_total_handling;
    private $quotation_total_charges;
    private $quotation_total_discount;
    private $quotation_total_products;
    private $quotation_total;

    const ROUND_ITEM = 1;
    const ROUND_LINE = 2;
    const ROUND_TOTAL = 3;


    /**
     * @see ObjectModel::$definition
     */
    public static $definition = array(
        'table' => 'roja45_quotationspro',
        'primary' => 'id_roja45_quotation',
        'multilang' => false,
        'fields' => array(
            'id_roja45_quotation_status' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
            'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
            'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
            'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'id_address' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true),
            'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true),
            'valid_days' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'expiry_date' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'),
            'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 128),
            'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'size' => 128),
            'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName',  'size' => 128),
            'form_data' => array('type' => self::TYPE_STRING),
            'reference' => array('type' => self::TYPE_STRING),
            'calculate_taxes' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'modified' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'quote_sent' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'tmp_password' => array('type' => self::TYPE_STRING, 'required' => false, 'size' => 8),
            'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'purchase_date' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'),
            'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'total_to_pay' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_to_pay_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_products' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_products_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_shipping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_shipping_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_handling' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_handling_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_wrapping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_discount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_discount_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_charges' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
            'total_charges_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'),
        ),
    );

    const ONLY_PRODUCTS = 1;
    const ONLY_DISCOUNTS = 2;
    const ONLY_CHARGES = 9;
    const BOTH = 3;
    const BOTH_WITHOUT_SHIPPING = 4;
    const ONLY_SHIPPING = 5;
    const ONLY_WRAPPING = 6;
    const ONLY_PRODUCTS_WITHOUT_SHIPPING = 7;
    const ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING = 8;
    const TAX_RATE = 10;
    const TOTAL_BEFORE_DISCOUNT = 11;
    const TOTAL_AFTER_DISCOUNT = 12;
    const ONLY_HANDLING = 13;

    public function __construct($id = null, $id_lang = null)
    {
        parent::__construct($id, $id_lang);
        $this->_taxCalculationMethod = Group::getDefaultPriceDisplayMethod();
    }

    public static function getQuotations($id_lang)
    {
        $cache_id = 'QuotationStatus::getQuotations' . (int)$id_lang;
        if (!Cache::isStored($cache_id)) {
            $sql = new DbQuery();
            $sql->select('*');
            $sql->from('roja45_quotationspro', 'q');
            $sql->leftJoin(
                'roja45_quotationspro_status_lang',
                'qsl',
                '(qa.`id_roja45_quotation_status` = qsl.`id_roja45_quotation_status`
                AND qsl.`id_lang` = ' . (int)$id_lang . ')'
            );
            $sql->orderBy('qs.id_roja45_quotation_status ASC');
            $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
            Cache::store($cache_id, $result);
        }
        return Cache::retrieve($cache_id);
    }

    public function isRemovable()
    {
        return true;
    }

    public function isLocked()
    {
        return false;
    }

    public function getTaxCalculationMethod()
    {
        return (int)($this->_taxCalculationMethod);
    }

    public function getAddress()
    {
        if (!$this->id_address) {
            $address = new Address();
            if ($this->id_country) {
                $address->id_country = $this->id_country;
            } else {
                $country = new Country(Configuration::get('PS_COUNTRY_DEFAULT'));
                $address->id_country = $country->id;
            }
            if ($this->id_state) {
                $address->id_state = $this->id_state;
            }
            $address->alias = $this->reference;
            $address->firstname = $this->firstname;
            $address->lastname = $this->lastname;
            $address->address1 = 'TBC';
            $address->city = 'TBC';

            $return = $address->save();
            if ($return) {
                $this->id_address = $address->id;
                $this->save();
            }
            return $address;
        } else {
            $address = new Address($this->id_address);
            return $address;
        }
    }

    public function deleteAddress($id)
    {
        $address = new Address($id);
        $address->delete();
    }

    public function getCarriers()
    {
        $_carriers = array();
        if ($this->id_country) {
            $country = new Country($this->id_country);
        } else {
            $country = new Country(Configuration::get('PS_COUNTRY_DEFAULT'));
        }

        $products = $this->getProducts();

        if ((int)$this->id_customer) {
            $customer = new Customer((int)$this->id_customer);
            $result = Carrier::getCarriers(
                (int) Configuration::get('PS_LANG_DEFAULT'),
                true,
                false,
                (int)$country->id_zone,
                $customer->getGroups()
            );
            unset($customer);
        } else {
            $result = Carrier::getCarriers(
                (int) Configuration::get('PS_LANG_DEFAULT'),
                true,
                false,
                (int) $country->id_zone
            );
        }

        $total = $this->getQuotationTotal(true, Cart::ONLY_PRODUCTS);
        foreach ($result as $k => $row) {
            //if ($row['id_carrier'] == Configuration::get('PS_CARRIER_DEFAULT')) {
            //    continue;
            //}

            /** @var Carrier $carrier */
            $_carriers[$row['id_carrier']]['carrier'] = new Carrier((int)$row['id_carrier']);
            $carrier = $_carriers[$row['id_carrier']]['carrier'];
            $shipping_method = $carrier->getShippingMethod();
            // Get only carriers that are compliant with shipping method
            if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $carrier->getMaxDeliveryPriceByWeight((int)$country->id_zone) === false)
                || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $carrier->getMaxDeliveryPriceByPrice((int)$country->id_zone) === false)
            ) {
                unset($result[$k]);
                continue;
            }

            // If out-of-range behavior carrier is set on "Desactivate carrier"
            if ($row['range_behavior']) {
                $check_delivery_price_by_weight = Carrier::checkDeliveryPriceByWeight(
                    $row['id_carrier'],
                    $this->getTotalWeight(),
                    (int)$country->id_zone
                );
                $check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice(
                    $row['id_carrier'],
                    $total,
                    (int)$country->id_zone,
                    (int)$this->id_currency
                );
                // Get only carriers that have a range compatible with cart
                if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !$check_delivery_price_by_weight)
                    || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !$check_delivery_price_by_price)
                ) {
                    unset($result[$k]);
                    continue;
                }
            }

            if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) {
                $shipping = $carrier->getDeliveryPriceByWeight(
                    $this->getTotalWeight($products),
                    (int)$country->id_zone
                );
            } else {
                $shipping = $carrier->getDeliveryPriceByPrice($total, (int)$country->id_zone, (int)$this->id_currency);
            }

            $_carriers[$row['id_carrier']]['shipping'] = $shipping;
        }
        $return = array();
        $return['carriers'] = $_carriers;

        return $return;
    }

    public function getTotalWeight($products = null)
    {
        if (!is_null($products)) {
            $total_weight = 0;
            foreach ($products as $product) {
                if (!isset($product['weight_attribute']) || is_null($product['weight_attribute'])) {
                    $total_weight += $product['weight'] * $product['qty'];
                } else {
                    $total_weight += $product['weight_attribute'] * $product['qty'];
                }
            }
            return $total_weight;
        }

        if (Combination::isFeatureActive()) {
            $weight_product_with_attribute = Db::getInstance()->getValue('
            SELECT SUM((p.`weight` + pa.`weight`) * cp.`quantity`) as nb
            FROM `' . _DB_PREFIX_ . 'cart_product` cp
            LEFT JOIN `' . _DB_PREFIX_ . 'product` p
            ON (cp.`id_product` = p.`id_product`)
            LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
            ON (cp.`id_product_attribute` = pa.`id_product_attribute`)
            WHERE (cp.`id_product_attribute` IS NOT NULL AND cp.`id_product_attribute` != 0)
            AND cp.`id_cart` = ' . (int)$this->id);
        } else {
            $weight_product_with_attribute = 0;
        }

        $weight_product_without_attribute = Db::getInstance()->getValue('
        SELECT SUM(p.`weight` * cp.`quantity`) as nb
        FROM `' . _DB_PREFIX_ . 'cart_product` cp
        LEFT JOIN `' . _DB_PREFIX_ . 'product` p ON (cp.`id_product` = p.`id_product`)
        WHERE (cp.`id_product_attribute` IS NULL OR cp.`id_product_attribute` = 0)
        AND cp.`id_cart` = ' . (int)$this->id);

        $_totalWeight = round((float)$weight_product_with_attribute + (float)$weight_product_without_attribute, 3);

        return $_totalWeight;
    }

    public function getTaxesAverage()
    {
        if (!Configuration::get('PS_TAX')) {
            return 0;
        }

        $products = $this->getProducts();
        $total_products_moy = 0;
        $ratio_tax = 0;

        if (!count($products)) {
            return 0;
        }

        foreach ($products as $product) {
            // products refer to the cart details
            $total_products_moy += $product['unit_price_tax_excl'];
            $ratio_tax += $product['unit_price_tax_excl'] * Tax::getProductTaxRate((int)$product['id_product']);
        }

        if ($total_products_moy > 0) {
            return $ratio_tax / $total_products_moy;
        }

        return 0;
    }

    public static function getQuotationsForCustomer($id_customer)
    {
        $sql = new DbQuery();
        $sql->select('id_roja45_quotation');
        $sql->from('roja45_quotationspro', 'q');
        $sql->where('q.id_customer=' . (int)$id_customer);
        $sql->where('q.id_roja45_quotation_status != (
                SELECT qs.id_roja45_quotation_status
                FROM `' . _DB_PREFIX_ . 'roja45_quotationspro_status` qs 
                WHERE qs.code = "'.pSQL(QuotationStatus::$DLTD).'"
            )'
        );
        $sql->orderBy('last_update DESC');
        return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
    }

    public static function getQuotationsForCart($id_cart)
    {
        if ($id_cart) {
            $sql = new DbQuery();
            $sql->select('id_roja45_quotation');
            $sql->from('roja45_quotationspro', 'q');
            $sql->where('q.id_cart=' . (int)$id_cart);
            $sql->where('q.quote_sent=1');
            $sql->where('q.id_roja45_quotation_status != (
                SELECT qs.id_roja45_quotation_status
                FROM `' . _DB_PREFIX_ . 'roja45_quotationspro_status` qs 
                WHERE qs.code = "'.pSQL(QuotationStatus::$DLTD).'"
            )'
            );
            return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
        } else {
            return false;
        }
    }

    public static function getQuotationsForStatus($status)
    {
        $sql = new DbQuery();
        $sql->select('id_roja45_quotation');
        $sql->from('roja45_quotationspro', 'q');
        $sql->where('q.id_roja45_quotation_status = (
                SELECT qs.id_roja45_quotation_status
                FROM `' . _DB_PREFIX_ . 'roja45_quotationspro_status` qs 
                WHERE qs.code = "'.pSQL(QuotationStatus::$DLTD).'"
            )'
        );
        return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
    }

    public function getProducts($id_lang = null, $id_currency = null)
    {
        if (!$id_lang) {
            $id_lang = $this->id_lang;
        }
        if (!$id_currency) {
            $id_currency = $this->id_currency;
        }

        $sql = new DbQuery();
        $sql->select('*');
        $sql->from('roja45_quotationspro_product', 'qp');
        $sql->leftJoin(
            'product',
            'p',
            'p.id_product = qp.id_product'
        );
        $sql->leftJoin(
            'product_lang',
            'pl',
            'p.id_product = pl.id_product AND pl.id_lang = ' . (int) $id_lang
        );
        $sql->leftJoin(
            'product_shop',
            'ps',
            'ps.id_product = p.id_product AND ps.id_shop = qp.id_shop'
        );
        $sql->where('qp.`id_roja45_quotation` = ' . (int) $this->id);
        $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

        $currency = Currency::getCurrencyInstance($id_currency);
        $resultArray = array();
        foreach ($products as &$product) {
            $id_product_attribute = null;
            if ($product['id_product_attribute'] > 0) {
                $id_product_attribute = $product['id_product_attribute'];
                $combinations = new Combination($product['id_product_attribute']);
                $combo_str = '';
                $combinations = $combinations->getAttributesName($id_lang);
                foreach ($combinations as $combination) {
                    $combo_str = $combo_str . ' [' . $combination['name'] . ']';
                }
                $product['product_title'] = $product['name'] . $combo_str;
            }
            //$product['unit_price_tax_incl'] = $product['unit_price_tax_incl'];
            //$product['unit_price_tax_excl'] = $product['unit_price_tax_excl'];
            //$product['list_price_excl'] = $product['price'];
            $product['list_price_excl'] = Product::getPriceStatic(
                $product['id_product'],
                false,
                $id_product_attribute,
                Roja45QuotationsProFree::DEFAULT_PRECISION
            );

            $product['list_price_incl'] = Product::getPriceStatic(
                $product['id_product'],
                true,
                $id_product_attribute,
                Roja45QuotationsProFree::DEFAULT_PRECISION
            );

            $product['image'] = null;
            $product['image_size'] = null;
            $id_image = Product::getCover($product['id_product'], Context::getContext());
            if ($id_image) {
                $product['image'] = new Image($id_image['id_image'], Context::getContext()->language->id);
            }

            if ($product['image'] != null) {
                $name =
                    'product_mini_' .
                    (int)$product['id_product'] .
                    (isset($product['product_attribute_id']) ? '_' . (int)$product['product_attribute_id'] : '') .
                    '.jpg';
                $product['image_url'] = Context::getContext()->link->getImageLink(
                    $product['link_rewrite'],
                    $product['image']->id,
                    ImageType::getFormatedName('cart')
                );
                if (file_exists(_PS_TMP_IMG_DIR_ . $name)) {
                    $product['image_size'] = getimagesize(_PS_TMP_IMG_DIR_ . $name);
                } else {
                    $product['image_size'] = false;
                }
            }

            if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')
                && (int)$product['advanced_stock_management'] == 1
                && (int)$product['id_warehouse'] > 0
            ) {
                $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities(
                    $product['id_product'],
                    $product['id_product_attribute'],
                    (int)$product['id_warehouse'],
                    true
                );
            } else {
                $product['current_stock'] = StockAvailable::getQuantityAvailableByProduct(
                    $product['id_product'],
                    $product['id_product_attribute'],
                    (int)$this->id_shop
                );
            }

            if (isset($product['download_hash']) && !empty($product['download_hash'])) {
                $product['filename'] = ProductDownload::getFilenameFromIdProduct((int)$product['id_product']);
                $product['display_filename'] = ProductDownload::getFilenameFromFilename($product['filename']);
            }
            $id_image = null;
            $product['unit_price_tax_excl_formatted'] = Tools::displayPrice(
                Tools::convertPrice(
                    $product['unit_price_tax_excl'],
                    $currency,
                    true
                ),
                $currency
            );

            $product['unit_price_tax_incl_formatted'] = Tools::displayPrice(
                Tools::convertPrice(
                    $product['unit_price_tax_incl'],
                    $currency,
                    true
                ),
                $currency
            );
            $product['product_price_subtotal_excl'] = $product['unit_price_tax_excl']*$product['qty'];
            $product['product_price_subtotal_excl_formatted'] = Tools::displayPrice(
                Tools::convertPrice(
                    $product['product_price_subtotal_excl'],
                    $currency,
                    true
                ),
                $currency
            );
            $product['product_price_subtotal_incl'] = $product['unit_price_tax_incl']*$product['qty'];
            $product['product_price_subtotal_incl_formatted'] = Tools::displayPrice(
                Tools::convertPrice(
                    $product['product_price_subtotal_incl'],
                    $currency,
                    true
                ),
                $currency
            );
            $product['link'] = Context::getContext()->link->getProductLink(
                $product['id_product'],
                $product['link_rewrite']
            );
            $product['request_qty'] = $product['qty'];
            $resultArray[$product['id_product'] . '-' . $product['id_product_attribute']] = $product;
        }

        return $resultArray;
    }

    public function getQuotationProductList()
    {
        return QuotationProduct::getList($this->id);
    }

    public function getQuotationChargeList($type = null)
    {
        return QuotationCharge::getList($this->id, $type);
    }

    public function getQuotationAllCharges()
    {
        return QuotationCharge::getAllCharges($this->id);
    }

    public function getQuotationAllDiscounts()
    {
        return QuotationCharge::getAllDiscounts($this->id);
    }

    public function getQuotationNotesList()
    {
        return QuotationNote::getList($this->id);
    }

    public function getQuotationMessageList()
    {
        return QuotationMessage::getList($this->id);
    }

    public function getQuotationAnswersList($id_lang = null)
    {
        if (!$id_lang) {
            $id_lang = Context::getContext()->language->id;
        }
        return QuotationAnswer::getQuotationAnswers($id_lang);
    }

    public function addProduct($product, $combination, $qty = 1)
    {
        if (is_array($product)) {
            $product = new Product($product['id_product'], false, (int)$this->id_lang);
        }
        if (is_array($combination)) {
            $combination = new Product($combination['id_combination']);
            $id_combination = $combination->id;
        } elseif (is_object($combination)) {
            $id_combination = $combination->id;
        } else {
            $id_combination = 0;
        }
        if ($id_quotation_product = QuotationProduct::getQuotationProduct(
            $this->id_roja45_quotation,
            $product->id,
            $id_combination
        )) {
            $quotation_product = new QuotationProduct($id_quotation_product);
            $quotation_product->qty = $quotation_product->qty + $qty;
        } else {
            $quotation_product = new QuotationProduct();
            $quotation_product->id_roja45_quotation = (int)$this->id;
            $quotation_product->id_shop = (int)$this->id_shop;
            $quotation_product->id_lang = (int)$this->id_lang;
            $quotation_product->id_product = (int)$product->id;
            $quotation_product->product_title = $product->name;
            $quotation_product->custom_price = false;
            $quotation_product->qty = $qty;
        }

        $null = null;
        $default_currency = Currency::getDefaultCurrency();
        $id_group = (int)Configuration::get('PS_CUSTOMER_GROUP');
        if ($combination) {
            $price_tax_excl = Product::priceCalculation(
                $this->id_shop,
                (int)$product->id,
                $combination->id,
                $this->id_country,
                $this->id_state,
                '0',
                $default_currency->id,
                $id_group,
                $qty,
                false, /* USE TAX*/
                6,
                false,
                true,
                false, /* WITH ECOTAX */
                $null,
                true,
                0,
                true,
                null,
                $qty
            );

            $price_tax_incl = Product::priceCalculation(
                $this->id_shop,
                (int)$product->id,
                $combination->id,
                $this->id_country,
                $this->id_state,
                '0',
                $default_currency->id,
                $id_group,
                $qty,
                true, /* USE TAX*/
                6,
                false,
                true,
                false, /* WITH ECOTAX */
                $null,
                true,
                0,
                true,
                null,
                $qty
            );
            //$price_tax_incl = Product::getPriceStatic((int)$product->id, true, $combination->id);
            $quotation_product->id_product_attribute = $combination->id;
        } else {
            //  $price_tax_incl = Product::getPriceStatic((int)$product->id, true, null);
            $price_tax_excl = Product::priceCalculation(
                $this->id_shop,
                (int)$product->id,
                null,
                $this->id_country,
                $this->id_state,
                '0',
                $default_currency->id,
                $id_group,
                $qty,
                false, /* USE TAX*/
                6,
                false,
                true,
                false, /* WITH ECOTAX */
                $null,
                true,
                0,
                true,
                null,
                $qty
            );

            $price_tax_incl = Product::priceCalculation(
                $this->id_shop,
                (int)$product->id,
                null,
                $this->id_country,
                $this->id_state,
                '0',
                $default_currency->id,
                $id_group,
                $qty,
                true, /* USE TAX*/
                6,
                false,
                true,
                false, /* WITH ECOTAX */
                $null,
                true,
                0,
                true,
                null,
                $qty
            );
        }

        $quotation_product->unit_price_tax_excl = (float)$price_tax_excl;
        $quotation_product->unit_price_tax_incl = (float)$price_tax_incl;

        $this->total_products += (float)$price_tax_excl;
        $this->total_products_wt += (float)$price_tax_incl;

        if ($quotation_product->save()) {
            $this->save();
            return $quotation_product->id;
        } else {
            return 0;
        }
    }

    /**
     * deleteProduct - Update a product line on a quotation.
     *
     * @return json
     *
     */
    public function deleteProduct($quotation_product)
    {
        $this->total_products -= (float)$quotation_product->unit_price_tax_excl;
        $this->total_products_wt -= (float)$quotation_product->unit_price_tax_incl;
        if (!$quotation_product->delete()) {
            return false;
        }

        if (!$this->save()) {
            return false;
        }

        return true;
    }

    public function resetPrice($id_roja45_quotation_product)
    {
        $this->updateProductPrice($id_roja45_quotation_product, true);
    }

    public function resetCartPrices()
    {
        $products = $this->getQuotationProductList();
        foreach ($products as $product) {
            if ($product['id_specific_price']) {
                $specific_price = new SpecificPrice($product['id_specific_price']);
                $specific_price->delete();
            }
        }

        $discounts = $this->getQuotationChargeList(QuotationCharge::$DISCOUNT);
        foreach ($discounts as $discount) {
            if ($discount['id_cart_rule']) {
                $cart_rule = new CartRule($discount['id_cart_rule']);
                $cart_rule->delete();
            }
        }
    }

    public function resetAllPrices()
    {
        $products = $this->getProducts();
        foreach ($products as $product) {
            $this->resetPrice($product['id_roja45_quotation_product']);
        }
    }

    public function updateProductPrice($id_roja45_quotation_product, $reset = false)
    {
        $product = new QuotationProduct($id_roja45_quotation_product);
        $price_excl = 0;
        $price_incl = 0;
        $with_taxes = false;

        $address = new Address();
        $address->id_country = $this->id_country;
        $address->id_state = $this->id_state;

        $id_group = (int)Configuration::get('PS_CUSTOMER_GROUP');

        $precision = Configuration::get('PS_PRICE_DISPLAY_PRECISION');
        if (!$precision) {
            $precision = 2;
        }

        if ($product->custom_price && !$reset) {
            $price = $product->unit_price_tax_excl;
        } else {
            $null = null;
            $product->custom_price = false;
            $price = Product::priceCalculation(
                $this->id_shop,
                (int)$product->id_product,
                (int)$product->id_product_attribute,
                $this->id_country,
                $this->id_state,
                '0',
                $this->id_currency,
                $id_group,
                $product->qty,
                false,
                6,
                false,
                true,
                false,
                $null,
                true,
                0,
                true,
                null,
                $product->qty
            );
        }

        if (Configuration::get('PS_USE_ECOTAX')) {
            $ecotax = $product->ecotax;
            if (isset($product->attribute_ecotax) && $product->attribute_ecotax > 0) {
                $ecotax = $product->attribute_ecotax;
            }
        } else {
            $ecotax = 0;

            $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct(
                (int)$product->id_product,
                Context::getContext()
            );
            $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();

            /*
            if ($ecotax) {
                $ecotax_tax_calculator = TaxManagerFactory::getManager(
                    $address,
                    (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID')
                )->getTaxCalculator();
            }
            */
            switch (Configuration::get('PS_ROUND_TYPE')) {
                case RojaQuotation::ROUND_TOTAL:
                    $price_incl = $price;
                    break;
                case RojaQuotation::ROUND_LINE:
                    $price_incl = Tools::ps_round(
                        $price + $tax_calculator->getTaxesTotalAmount(
                            $price
                        ),
                        (int)$precision
                    );
                    $price_excl = Tools::ps_round($price, (int)$precision);

                    if ($ecotax) {
                        if ($with_taxes) {
                            //$ecotax_incl = Tools::ps_round(
                            //    $ecotax + $ecotax_tax_calculator->getTaxesTotalAmount(
                            //        $ecotax
                            //    ),
                            //    (int)$precision
                            //);
                        } else {
                           // $ecotax_excl = Tools::ps_round($ecotax, (int)$precision);
                        }
                    }

                    break;
                case RojaQuotation::ROUND_ITEM:
                default:
                    $price_incl = $tax_calculator->addTaxes($price);
                    $price_excl = Tools::ps_round($price, (int)$precision);
                    if ($ecotax) {
                        if ($with_taxes) {
                            //$ecotax_incle_incl = $ecotax_tax_calculator->addTaxes($ecotax);
                        } else {
                            //$ecotax_excl = $ecotax;
                        }
                    }
                    break;
            }
            $product->unit_price_tax_excl = $price_excl;
            $product->unit_price_tax_incl = $price_incl;
            $product->update();
        }
    }

    public function updateAllPrices()
    {
        $products = $this->getProducts();

        foreach ($products as $product) {
            $this->updateProductPrice($product['id_roja45_quotation_product'], false);
        }
    }

    public function getTaxCalculator($id_tax_rules_group)
    {
        $address = new Address($this->id_address);
        $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
        return $tax_calculator;
    }

    public function getQuotationTotal($with_taxes = true, $type = self::BOTH)
    {
        $context = Context::getContext();
        // TODO - add dirty flag, if false return cached values.  set to true when changes to content made.
        $type = (int)$type;

        $this->quotation_total = 0;
        $this->quotation_total_charges = 0;
        $this->quotation_total_shipping = 0;
        $this->quotation_total_discount = 0;
        $this->quotation_total_handling = 0;

        $products_total = array();

        $ecotax_total = 0;
        $total_charges = 0;
        $total_charges_wt = 0;
        $total_shipping = 0;
        $total_shipping_wt = 0;
        $total_handling = 0;
        $total_handling_wt = 0;

        //$id_group = (int)Configuration::get('PS_CUSTOMER_GROUP');
        $products = $this->getProducts();
        $address = new Address();
        $address->id_country = $this->id_country;
        $address->id_state = $this->id_state;

        if ($type == self::ONLY_PRODUCTS_WITHOUT_SHIPPING) {
            $type = self::ONLY_PRODUCTS;
        }

        $precision = Configuration::get('PS_PRICE_DISPLAY_PRECISION');
        if (!$precision) {
            $precision = 2;
        }
        $precision = 6;
        foreach ($products as $product) {
            // products refer to the cart details
            if ($with_taxes) {
                $price = $product['unit_price_tax_incl'];
            } else {
                $price = $product['unit_price_tax_excl'];
            }
            // TODO -for each key 0 discount, apply it
            // for each id_product, appy it.

            if (Configuration::get('PS_USE_ECOTAX')) {
                $ecotax = $product['ecotax'];
                if (isset($product['attribute_ecotax']) && $product['attribute_ecotax'] > 0) {
                    $ecotax = $product['attribute_ecotax'];
                }
            } else {
                $ecotax = 0;
            }

            if ($with_taxes) {
                $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $context);
                if ($ecotax != 0) {
                    $ecotax_tax_calculator = TaxManagerFactory::getManager(
                        $address,
                        (int) Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID')
                    )->getTaxCalculator();
                }
            } else {
                $id_tax_rules_group = 0;
            }

            $id_address = 0;
            if (in_array(
                Configuration::get('PS_ROUND_TYPE'),
                array(
                    RojaQuotation::ROUND_ITEM,
                    RojaQuotation::ROUND_LINE
            ))) {
                if (!isset($products_total[$id_tax_rules_group])) {
                    $products_total[$id_tax_rules_group] = 0;
                }
            } elseif (!isset($products_total[$id_tax_rules_group . '_' . $id_address])) {
                $products_total[$id_tax_rules_group . '_' . $id_address] = 0;
            }

            switch (Configuration::get('PS_ROUND_TYPE')) {
                case RojaQuotation::ROUND_TOTAL:
                    $products_total[$id_tax_rules_group . '_' . $id_address] += $price * (int)$product['qty'];

                    if ($ecotax != 0) {
                        $ecotax_total += $ecotax * (int)$product['qty'];
                    }
                    break;
                case RojaQuotation::ROUND_LINE:
                    $product_price = $price * $product['qty'];
                    $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, (int)$precision);

                    if ($ecotax != 0) {
                        $ecotax_price = $ecotax * (int)$product['qty'];

                        if ($with_taxes) {
                            $ecotax_total += Tools::ps_round(
                                $ecotax_price + $ecotax_tax_calculator->getTaxesTotalAmount($ecotax_price),
                                (int)$precision
                            );
                        } else {
                            $ecotax_total += Tools::ps_round($ecotax_price, (int)$precision);
                        }
                    }
                    break;
                case RojaQuotation::ROUND_ITEM:
                default:
                    $product_price = $price * $product['qty'];
                    $products_total[$id_tax_rules_group . '_' . $id_address] += Tools::ps_round(
                        $product_price,
                        (int)$precision
                    ) * (int)$product['qty'];

                    if ($ecotax != 0) {
                        $ecotax_price = $with_taxes ? $ecotax_tax_calculator->addTaxes($ecotax) : $ecotax;
                        $ecotax_total += Tools::ps_round($ecotax_price, (int)$precision) * (int)$product['qty'];
                    }
                    break;
            }
        }

        foreach ($products_total as $price) {
            $this->quotation_total += $price;
        }

        if (!in_array($type, array(self::ONLY_PRODUCTS))) {
            // TODO - If apply discounts after charges and shipping, apply here.
            $discounts = $this->getQuotationChargeList(QuotationCharge::$DISCOUNT);
            $total_discounts = $this->calculateDiscount($this->quotation_total, $discounts);
            if ($type == self::ONLY_DISCOUNTS) {
                return $total_discounts;
            }

            if ($type == self::TOTAL_BEFORE_DISCOUNT) {
                return $this->quotation_total;
            }

            $this->quotation_total -= $total_discounts;
            $this->quotation_total_discount -= $total_discounts;

            if ($type == self::TOTAL_AFTER_DISCOUNT) {
                return $this->quotation_total;
            }

            if ($ecotax_total && $with_taxes && Configuration::get('PS_ROUND_TYPE') == RojaQuotation::ROUND_TOTAL) {
                $ecotax_total = Tools::ps_round(
                    $ecotax_total,
                    (int)$precision
                ) + Tools::ps_round($ecotax_tax_calculator->getTaxesTotalAmount($ecotax_total), (int)$precision);
            }
            $this->quotation_total += $ecotax_total;
            $this->quotation_total_products = $this->quotation_total;

            // calculate charges
            $charges = $this->getQuotationChargeList(QuotationCharge::$CHARGE);
            foreach ($charges as $charge) {
                $total_charges += $charge['charge_amount'];
                $total_charges_wt += $charge['charge_amount_wt'];
            }
            $charges = $this->getQuotationChargeList(QuotationCharge::$SHIPPING);
            foreach ($charges as $charge) {
                $total_shipping += $charge['charge_amount'];
                $total_shipping_wt += $charge['charge_amount_wt'];
            }

            $charges = $this->getQuotationChargeList(QuotationCharge::$HANDLING);
            foreach ($charges as $charge) {
                $total_handling += $charge['charge_amount'];
                $total_handling_wt += $charge['charge_amount_wt'];
            }
            // TODO - If apply discounts after charges and shipping, apply here.
            if ($with_taxes) {
                $this->quotation_total += $total_charges_wt;
                $this->quotation_total += $total_shipping_wt;
                $this->quotation_total += $total_handling_wt;
                $this->quotation_total_charges += $total_charges_wt;
                $this->quotation_total_shipping += $total_shipping_wt;
                $this->quotation_total_handling += $total_handling_wt;
            } else {
                $this->quotation_total += $total_charges;
                $this->quotation_total += $total_shipping;
                $this->quotation_total += $total_handling;
                $this->quotation_total_charges += $total_charges;
                $this->quotation_total_shipping += $total_shipping;
                $this->quotation_total_handling += $total_handling;
            }
        }

        if ($this->quotation_total < 0 && $type != self::ONLY_DISCOUNTS) {
            return 0;
        }

        if ($type == self::ONLY_SHIPPING) {
            return $this->quotation_total_shipping;
        }

        if ($type == self::ONLY_HANDLING) {
            return $this->quotation_total_handling;
        }

        if ($type == self::ONLY_CHARGES) {
            return $this->quotation_total_charges;
        }

        if ($type == self::ONLY_DISCOUNTS) {
            return $this->quotation_total_discount;
        }

        $this->is_dirty = false;
        return (float)$this->quotation_total;
    }

    private function calculateDiscount($quotation_total, $discounts)
    {
        $current_total = 0;
        foreach ($discounts as $discount) {
            // If the cart rule offers a reduction, the amount is prorated (with the products in the package)
            if ($discount['charge_method']==QuotationCharge::$PERCENTAGE) {
                $current_total += $quotation_total * ((int) $discount['charge_value']/100);
            } elseif ($discount['charge_method']==QuotationCharge::$VALUE) {
                $current_total += $quotation_total - (float) $discount['charge_value'];
            }
        }
        return $current_total;
    }

    public function getTotalShippingCost($use_tax = true)
    {
        // TODO - get shipping entries from charges.
        // TODO - Calculate with tax using tax details from country and state.
        if ($use_tax) {
            return $this->total_shipping_wt;
        } else {
            return $this->total_shipping;
        }
    }

    public function getRequestDetails()
    {
        $requestJSON = Tools::jsonDecode($this->form_data);
        $html = '';
        $text = '';
        foreach ($requestJSON->columns as $column) {
            $heading = '';
            if (isset($column->heading)) {
                $heading = $column->heading;
            }
            $html .= '<table style="background-color: #fff; width: 100%;" class="table table-bordered table-striped">';
            $html .= '<thead><tr><th colspan="2" style="text-align: left;padding: 8px;font-size: 17px;">' . $heading .
                '</th></tr></thead>';
            $html .= '<tbody>';
            $text .= $heading . "\r\n\r\n";
            foreach ($column->fields as $field) {
                $html .= '<tr style="background-color: #f9f9f9;">';
                $html .= '<th style="width: 50%; border: 1px solid #dddddd;text-align: left;padding: 8px;line-height: 1.42857143;vertical-align: top;border-top: 1px solid #dddddd;">';
                $html .= '<p style="font-family: Helvetica, \'Open Sans\', Arial, sans-serif;border-bottom:1px solid #D6D4D4;margin:3px 0 7px;font-weight:500;font-size:14px;padding-bottom:10px">' .
                    trim($field->label) . '</p></th>';
                $html .= '<td style="width: 50%; border: 1px solid #dddddd;text-align: left;padding: 8px;line-height: 1.42857143;vertical-align: top;border-top: 1px solid #dddddd;">';
                $html .= '<p style="font-family: Helvetica, \'Open Sans\', Arial, sans-serif;border-bottom:1px solid #D6D4D4;margin:3px 0 7px;font-weight:300;font-size:14px;padding-bottom:10px">' .
                    trim($field->value) . '</p></td>';
                $html .= '</tr>';
                $text .= trim($field->label) . ' : ' . trim($field->value) . "\r\n";
            }
            $html .= '</tbody>';
            $html .= '</table>';
        }

        return $html;
    }

    public function getSummaryDetails($id_lang = null, $id_currency = null)
    {
        if (!$this->quote_sent) {
            return array();
        }

        $context = Context::getContext();
        if (!$id_lang) {
            $id_lang = $context->language->id;
        }

        if (!$id_currency) {
            $id_currency = $this->id_currency;
        }
        $defaultCurrency = Currency::getDefaultCurrency();
        $currency = new Currency($id_currency);
        $base_total_tax_inc = $this->getQuotationTotal(true);
        $base_total_tax_exc = $this->getQuotationTotal(false);
        $total_tax = $base_total_tax_inc - $base_total_tax_exc;
        if ($total_tax < 0) {
            $total_tax = 0;
        }
        $status = new QuotationStatus($this->id_roja45_quotation_status);
        $products = $this->getProducts();

        if (!$products) {
            $products = array();
        }
        $totals = array(
            'products' => array_values($products),
            'total_charges' => $this->getQuotationTotal(false, RojaQuotation::ONLY_CHARGES),
            'total_charges_wt' => $this->getQuotationTotal(true, RojaQuotation::ONLY_CHARGES),
            'total_discounts' => $this->getQuotationTotal($this->calculate_taxes, RojaQuotation::ONLY_DISCOUNTS),
            'total_shipping' => $this->getQuotationTotal(false, RojaQuotation::ONLY_SHIPPING),
            'total_shipping_wt' => $this->getQuotationTotal(true, RojaQuotation::ONLY_SHIPPING),
            'total_handling' => $this->getQuotationTotal(false, RojaQuotation::ONLY_HANDLING),
            'total_handling_wt' => $this->getQuotationTotal(true, RojaQuotation::ONLY_HANDLING),
            'total_products' => $this->getQuotationTotal(false, RojaQuotation::ONLY_PRODUCTS),
            'total_products_wt' => $this->getQuotationTotal(true, RojaQuotation::ONLY_PRODUCTS),
            'total_price_before_discount' => $this->getQuotationTotal(
                false,
                RojaQuotation::TOTAL_BEFORE_DISCOUNT
            ),
            'total_price_before_discount_wt' => $this->getQuotationTotal(
                true,
                RojaQuotation::TOTAL_BEFORE_DISCOUNT
            ),
            'total_products_after_discount' => $this->getQuotationTotal(
                false,
                RojaQuotation::TOTAL_AFTER_DISCOUNT
            ),
            'total_products_after_discount_wt' => $this->getQuotationTotal(
                true,
                RojaQuotation::TOTAL_AFTER_DISCOUNT
            ),
            'total_price' => $base_total_tax_inc,
            'total_tax' => $total_tax,
            'tax_average_rate' => $this->getTaxesAverage(),
            'total_price_without_tax' => $base_total_tax_exc,
            'default_currency_symbol' => $defaultCurrency->sign,
            //'use_taxes' => $this->calculate_taxes,
            'use_taxes' => (bool) Configuration::get('PS_TAX'),
            'currency' => $currency,
            'deleted' => ($status->code == QuotationStatus::$DLTD),
            'show_exchange_rate' => ((float)$currency->conversion_rate == (float)1.0) ? 0 : 1,
            'exchange_rate' => $currency->conversion_rate
        );

        $totals_formatted = array(
            'total_charges_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_charges'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_charges_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_charges_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_discounts_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_discounts'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_shipping_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_shipping'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_shipping_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_shipping_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_handling_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_handling'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_handling_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_handling_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_products_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_products'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_products_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_products_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_price_before_discount_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_price_before_discount'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_price_before_discount_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_price_before_discount_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_products_after_discount_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_products_after_discount'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_products_after_discount_wt_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_products_after_discount_wt'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_price_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_price'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_tax_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_tax'],
                    $currency,
                    true
                ),
                $currency
            ),
            'total_price_without_tax_formatted' => Tools::displayPrice(
                Tools::convertPrice(
                    $totals['total_price_without_tax'],
                    $currency,
                    true
                ),
                $currency
            ),
        );

        return array_merge(
            $totals,
            $totals_formatted
        );
    }

    public function setStatus($status)
    {
        $id_quotation_status = QuotationStatus::getQuotationStatusByType($status);
        $status = new QuotationStatus($id_quotation_status[0]['id_roja45_quotation_status']);
        $this->id_roja45_quotation_status = $status->id;
        $this->save();
        return true;
    }

    /**
     * getPriceWithoutTax - Calculate the price without tax added.
     *
     * @param Product $id_product Product ID of the price to be converted
     * @param float $price Price to be converted
     * @param Context $context The current user context
     *
     * @return json
     *
     */
    public function getPriceWithoutTax($id_product, $price, $context)
    {
        $address = new Address();
        $address->id_country = $this->id_country;
        $address->id_state = $this->id_state;

        $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$id_product, $context);
        $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
        $rate = (float)$tax_calculator->getTotalRate();

        return $price / (1 + ($rate / 100));
    }

    public function getPriceWithTax($id_product, $price, $context)
    {
        $address = new Address();
        $address->id_country = $this->id_country;
        $address->id_state = $this->id_state;

        $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$id_product, $context);
        $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
        $rate = (float)$tax_calculator->getTotalRate();

        return $price * (1 + ($rate / 100));
    }

    public function getTemplateVars()
    {
        $context = Context::getContext();
        $customer = new Customer((int)$this->id_customer);
        $status = new QuotationStatus($this->id_roja45_quotation_status, (int)$context->language->id);
        $default_tax_display = $this->getTaxCalculationMethod();

        $language = new Language($this->id_lang);
        $languages = Language::getLanguages();
        $tmp_vars = array(
            'languages' => $languages,
            'language' => $language,
            'defaultFormLanguage' => (int)$context->language->id,
            'quotation' => $this,
            'discounts' => array(),
            'charges' => array(),
            'email' => true,
            'default_tax_method' => $default_tax_display,
        );

        $summary = $this->getSummaryDetails($context->language->id, $this->id_currency);
        $vars = array_merge($tmp_vars, $summary);

        $quote_txt = '';
        $quote_html = '';
        if ($this->quote_sent) {
            $tpl = $context->smarty->createTemplate(_PS_MODULE_DIR_.'roja45quotationsprofree/views/templates/admin/' . 'quote_template_txt.tpl');
            $tpl->assign($vars);
            $tpl->assign(
                array(
                    'languages' => $languages,
                    'link' => $context->link,
                )
            );
            $quote_txt = $tpl->fetch();
            $tpl = $context->smarty->createTemplate(_PS_MODULE_DIR_.'roja45quotationsprofree/views/templates/admin/' . 'quote_template.tpl');
            $tpl->assign($vars);
            $tpl->assign(
                array(
                    'languages' => $languages,
                    'link' => $context->link,
                )
            );
            $quote_html = $tpl->fetch();
        }

        $products = $this->getProducts();
        $product_list_html = '';
        $product_list_txt = '';
        $product = null;
        if (count($products)) {
            $product = reset($products);
        }

        $requestJSON = Tools::jsonDecode($this->form_data);
        $tpl = $context->smarty->createTemplate(
            _PS_MODULE_DIR_.'roja45quotationsprofree/views/templates/front/email-request-content.tpl'
        );
        $tpl->assign(
            array(
                'columns' => $requestJSON->columns,
                'product' => $product,
                'request_qty' => $product['request_qty'],
            )
        );
        $quotation_request = $tpl->fetch();
        $quotation_request_text = new Html2Text($quotation_request);
        $quotation_request_text = $quotation_request_text->getText();

        // create a product list template in html and txt
        $template_vars = array(
            '{shop_logo}' => $context->link->getMediaLink(_PS_IMG_ . Configuration::get('PS_LOGO')),
            '{shop_name}' => Configuration::get('PS_SHOP_NAME'),
            '{shop_email}' => Configuration::get('PS_SHOP_EMAIL'),
            '{shop_url}' => $context->link->getPageLink(
                'index',
                true,
                $context->language->id,
                null,
                false,
                $context->shop->id
            ),
            '{my_account_url}' => $context->link->getPageLink(
                'my-account',
                true,
                $context->language->id,
                null,
                false,
                $context->shop->id
            ),
            '{guest_tracking_url}' => $context->link->getPageLink(
                'guest-tracking',
                true,
                $context->language->id,
                null,
                false,
                $context->shop->id
            ),
            '{history_url}' => $context->link->getPageLink(
                'history',
                true,
                $context->language->id,
                null,
                false,
                $context->shop->id
            ),
            '{customer_email}' => $customer->email,
            '{customer_firstname}' => $customer->firstname,
            '{customer_lastname}' => $customer->lastname,
            '{customer_company}' => $customer->company,
            '{quotation_reference}' => $this->reference,
            '{quotation_received}' => $this->received,
            '{quotation_status_code}' => $status->code,
            '{quotation_status}' => $status->status,
            '{quotation_lastupdate}' => $this->last_update,
            '{quotation_total}' => $this->total_to_pay,
            '{quotation_total_wt}' => $this->total_to_pay_wt,
            '{quotation_summary_html}' => $quote_html,
            '{quotation_summary_txt}' => $quote_txt,
            '{quotation_request}' => $quotation_request,
            '{quotation_request_txt}' => $quotation_request_text
        );

        $requestJSON = Tools::jsonDecode($this->form_data);
        if (isset($requestJSON->columns)) {
            foreach ($requestJSON->columns as $column) {
                foreach ($column->fields as $field) {
                    if (($field->name != 'FIRSTNAME') &&
                        ($field->name != 'LASTNAME') &&
                        ($field->name != 'CONTACT_EMAIL')) {
                        $template_vars['{' . $field->name . '_LABEL}'] = $field->label;
                        $template_vars['{' . $field->name . '_VALUE}'] = $field->value;
                    }
                }
            }
        }
        return $template_vars;
    }

    public function delete()
    {
        // get all products, delete them
        $quotation_products = $this->getQuotationProductList();
        foreach ($quotation_products as $quotation_product) {
            $quotation_product = new QuotationProduct($quotation_product['id_roja45_quotation_product']);
            $quotation_product->delete();
        }
        QuotationMessage::deleteQuotationMessages($this->id_roja45_quotation);
        // get all discounts, delete them
        return parent::delete();
    }

    public function save($null_values = false, $autodate = true)
    {
        $mysql_date_now = date('Y-m-d H:i:s');
        $this->last_update = $mysql_date_now;
        $return = parent::save($null_values, $autodate);
        $this->is_dirty = true;
        return $return;
    }

    public function getEmailTemplateContent($template_name, $mail_type, $vars, $context, $iso_code = null)
    {
        $email_configuration = Configuration::get('PS_MAIL_TYPE');
        if ($email_configuration != $mail_type && $email_configuration != Mail::TYPE_BOTH) {
            return '';
        }

        if (!$iso_code) {
            $iso_code=$context->language->iso_code;
        }
        $theme_template_path = _PS_THEME_DIR_.'modules/roja45quotationsprofree/mails'.DIRECTORY_SEPARATOR.$iso_code.DIRECTORY_SEPARATOR.$template_name;
        $default_mail_template_path = _PS_MODULE_DIR_.'roja45quotationsprofree/mails'.DIRECTORY_SEPARATOR.$iso_code.DIRECTORY_SEPARATOR.$template_name;

        if (Tools::file_exists_cache($theme_template_path)) {
            $default_mail_template_path = $theme_template_path;
        }

        if (Tools::file_exists_cache($default_mail_template_path)) {
            $context->smarty->assign($vars);
            return $context->smarty->fetch($default_mail_template_path);
        }
        return '';
    }

    public function populateCart()
    {
        $context = Context::getContext();
        $cart_products = $context->cart->getProducts(true);
        foreach ($cart_products as $cart_product) {
            $context->cart->deleteProduct($cart_product['id_product']);
        }
        $mysql_date_now = date('Y-m-d H:i:s');
        $mysql_date_plus_one = date('Y-m-d H:i:s', strtotime('+1 day'));

        $products = $this->getQuotationProductList();
        foreach ($products as $product) {
            if ($product['id_specific_price']) {
                $specific_price = new SpecificPrice($product['id_specific_price']);
                $specific_price->delete();
            }
            $productObj = new Product($product['id_product']);
            $quotationProduct = new QuotationProduct($product['id_roja45_quotation_product']);

            $price = Product::getPriceStatic(
                $product['id_product'],
                false,
                $product['id_product_attribute'],
                Roja45QuotationsProFree::DEFAULT_PRECISION
            );
            //if ($this->calculate_taxes) {
            //    $reduction = $price - $quotationProduct->unit_price_tax_incl;
            //} else {
                $reduction = $price - $quotationProduct->unit_price_tax_excl;
            //}

            if ($reduction < 0.0) {
                $reduction = 0.0;
            }
            $specific_price = new SpecificPrice();
            $specific_price->id_cart = (int)$context->cart->id;
            $specific_price->id_shop = (int)$context->shop->id;
            $specific_price->id_shop_group = (int)$context->shop->id_shop_group;
            $specific_price->id_currency = (int)($this->id_currency);
            $specific_price->id_country = (int)($this->id_country);
            $specific_price->id_group = 0;
            $specific_price->id_customer = (int)($this->id_customer);
            $specific_price->id_product = (int)$product['id_product'];
            $specific_price->id_product_attribute = (int)$product['id_product_attribute'];
            $specific_price->price = (float)$productObj->price;
            $specific_price->from_quantity = 1;
            $specific_price->reduction = $reduction;
            $specific_price->reduction_type = 'amount';
            $specific_price->from = $mysql_date_now;
            $specific_price->to = $mysql_date_plus_one;  // TODO - Today + days

            if (!$specific_price->save()) {
                $this->errors[] = Tools::displayError(
                    'Unable to create cart price for product [' . $product['id_product'] . ']',
                    !Tools::getValue('ajax')
                );
            }
            $quotationProduct->id_specific_price = $specific_price->id;
            if (!$quotationProduct->save()) {
                $this->errors[] = $this->l('Unable to save quotation product, please try again. If the problem persists, please contact your system administrator.');
            }

            $update_quantity = $context->cart->updateQty(
                $product['qty'],
                $product['id_product'],
                $product['id_product_attribute'],
                null,
                Tools::getValue('op', 'up'),
                null
            );
            if ($product['qty'] < 0) {
                // If product has attribute, minimal quantity is set with minimal quantity of attribute
                $minimal_quantity = ($product['id_product_attribute']) ? Attribute::getAttributeMinimalQty($product['id_product_attribute']) : $product->minimal_quantity;
                $this->errors[] = sprintf(Tools::displayError(
                    'You must add %d minimum quantity',
                    !Tools::getValue('ajax')
                ), $minimal_quantity);
            } elseif (!$update_quantity) {
                $this->errors[] = Tools::displayError(
                    'You already have the maximum quantity available for this product.',
                    !Tools::getValue('ajax')
                );
            }
        }

        $discounts = $this->getQuotationChargeList(QuotationCharge::$DISCOUNT);
        foreach ($discounts as $discount) {
            if ($discount['id_cart_rule']) {
                $cart_rule = new CartRule($discount['id_cart_rule']);
                $cart_rule->delete();
            }
            $discountObj = new QuotationCharge($discount['id_roja45_quotation_charge']);
            $cart_discount = new CartRule();
            $cart_discount->quantity = 1;
            $cart_discount->quantity_per_user = 1;

            switch ($discount['charge_method']) {
                case QuotationCharge::$PERCENTAGE:
                    $cart_discount->id_discount_type = Discount::PERCENT;
                    $cart_discount->reduction_percent = $discount['charge_value'];
                    break;
                case QuotationCharge::$AMOUNT:
                    $cart_discount->id_discount_type = Discount::AMOUNT;
                    $cart_discount->reduction_amount = $discount['charge_value'];
                    break;
            }
            $start_date = date('Y-m-d H:i:s');
            $cart_discount->date_from = $start_date;

            // CONFIGURATION option for quotation expiration
            $end_date = date('Y-m-d H:i:s', strtotime('+1 week'));
            $cart_discount->date_to = $end_date;
            $cart_discount->description = $discount['charge_name'];
            $gen_pass = Tools::strtoupper(Tools::passwdGen(8));
            $vouchercode = $this->reference;
            $name_v = $vouchercode . '-' . $gen_pass;

            $languages = Language::getLanguages(true);
            $namelang = array();
            foreach ($languages as $language) {
                $namelang[$language['id_lang']] = $name_v;
            }
            $cart_discount->name = $namelang;
            //$current_language = (int)$this->id_lang;
            $cart_discount->id_customer = $this->id_customer;
            $code_v = $vouchercode . '-' . $gen_pass;
            $cart_discount->code = $code_v;
            $cart_discount->active = 1;
            //$cart_discount->cart_display = 1;
            $cart_discount->cart_rule_restriction = 0;
            $cart_discount->highlight = 1;

            if (!$cart_discount->save()) {
                $this->errors[] = $this->l('Unable to save cart rule. If the problem persists, please contact your system administrator.');

                foreach ($products as $product) {
                    //SpecificPrice::deleteByIdCart((int)$cart->id, (int)$product['id_product'], (int)$product['id_product_attribute']);
                }
                $context->cart->delete();
            }
            $discountObj->id_cart_rule = $cart_discount->id;
            if (!$discountObj->save()) {
                $this->errors[] = $this->l('Unable to save quotation discount, please try again.  If the problem persists, please contact your system administrator.');
                foreach ($products as $product) {
                    //SpecificPrice::deleteByIdCart((int)$cart->id, (int)$product['id_product'], (int)$product['id_product_attribute']);
                }
                $context->cart->delete();
            }
            $context->cart->addCartRule($cart_discount->id);
        }
        $this->id_cart = $context->cart->id;
        $this->setStatus(QuotationStatus::$CART);
        $this->modified = 0;
        if (!$this->save()) {
            return false;
        }
        return true;
    }
}