Jump to content

Error en precios especificos


Rumoku

Recommended Posts

Buenos dias,

 

Prestashop me da un error en los precios especificos que jamas me habia pasado en otras tiendas que he montado.

 

Tengo un producto con estos precios:

Precio venta SIN IVA: 57.024793

Regla impuestos: 21%

Precio con IVA: 69

 

PRECIO ESPECIFICO (Aqui el error)

Regla --

Combinacion: Talla 30

...

IMPACTO: -17.44 (imp. excl.)

 

El calculo correcto que deberia hacer para saber el precio final es:

(57.024793 - 17.44) +21% = 47.90€

 

Pero en realidad me lo calcula como:

(69-17.44)+21%=51.56€ !!!!

 

Por que puede ser dado ese error??

Link to comment
Share on other sites

  • 1 month later...

Esto a mi me sucede en una tienda prestashop 1.5.6, creada hace años.

 

Lo que sucede en esa versión (y creo que tambien en ps1.6) es que los precios específicos se aplican directamente sobre el precio final del producto (con IVA), yo quisiera saber que archivo es el que controla esa conversión de precios, para decirle que lo aplique sobre el precio inicial sin impuestos, por que...

El problema grave, con los precios específicos, está al configurar los envíos a Canarias y paises Europeos, donde los productos se cobran sin iva.
 

En mi caso la tienda muestra siempre los precios de los productos sin IVA, ya sea para Europa, Canarias o resto de España.

El precio que muestra la ficha es el mismo antes de registrase como cliente o cuando te identificas como cliente de España (no canarias).

Pero... si me registro con una dirección de envío a Canarias o un pais europeo donde no hay que cobrar el iva, o incluso si me identifico con dirección de la Península, pero cambio el envío a Canarias,  el precio me cambia por esa forma de aplicarse el precio específico.

Por ejemplo: 

Producto que vale 15€ sin iva  es decir 18.15 con el 21% de iva.

Si lo pongo en rebajas con un precio específico para que reduzca un importe de 10.89€, prestashop hace el siguiente calculo (PS1.5.6 no tiene opción de indicar si el descuento es con o sin iva):

Toma el precio final 18.15 y le quita el precio específico: 18.15-10.89= 7.26€ como la tienda muestra el precio sin iva lo que vemos en la ficha del producto es 6.00€ (que es 7.26 sin iva 7.26/1.21=6)

Pero al registrarse o cambiar la dirección de envío a canarias o paises europeos, el precio final del producto ya no es 18.15 sino 15 por que esas zonas van sin iva por lo que el descuento que aplica es mayor porque precio específico lo calcula así: 

Toma el precio final 15 y le quita el precio específico: 15-10.89=4.11euros. como el precio que muestra la tienda es sin iva, pues muestra esos 4.11 que ya son sin iva.

 

Creo que el descuento por importe en los precios específicos, debería aplicarse siempre sobre el precio sin impuesto, en mi caso así se vería siempre el mismo precio y luego aplicar los impuestos que correspondan o no, según zona de envío.

 

He revisado ya varios archivos en controllers, tanto admin como front, classes/product.php, y tools que hacen el convert_price pero no consigo dar con el que gestiona esa reducción de precio, para hacer que el descuento (specific_price) lo aplique siempre sobre el precio sin iva (lo que solucionaría mi problema y todos los que he leido que hay con los precios espcíficos).

 

Por favor, alguna sugerencia?

Link to comment
Share on other sites

  • 2 years later...

Hola, despues de mucho tiempo parece que el problema persiste en PS 1.6.1.23, voy a explicar el problema otra vez, ya que parece que sea el mismo, y he conseguido implementar una solución.

La base del problema es cuando creamos precios específicos para un producto, ya que en el carrito no se refleja el IVA correctamente, sinó que calcula el IVA del precio original del producto, sin tener en cuenta la reducción del precio específico, un ejemplo:

añadimos un producto de coste original 9€ (imp. excl.)

el coste de transporte son 3€

total sin impuestos: 12€

IVA: 2,52€

Total: 14,52€

--------------------------------- Hasta aquí todo normal, sin embargo, si a ese mismo producto, le creamos un precio específico con una reducción de 6€ (imp. excl), queda del siguiente modo:

añadimos un producto con precio específico (-6€ imp. excl.): 3€

el coste de transporte son 3€

total sin impuestos: 6€

IVA: 2,52€ (MAL, deberia ser 1,26€)

Total: 8,52€ (MAL, debería ser 7,26€)

------------------------ El total es incorrecto, y por lo tanto el IVA también lo es, ya que prestashop calcula el IVA del carrito a partir de Total con IVA restando el Total sin IVA. En otras palabras, después de depurar y printar valores en la pantlla como si no hubiera un mañana, descubrí lo que ocurre exactamente: Al tener un descuento de -6€ sin impuestos, ese el el valor que utiliza el sistema como reducción y se lo aplica al total con IVA, por lo tanto, un producto de 9€ sin IVA 21%, sería con IVA 10.89€. El sistema le resta a 10,89€ - 6€ =  4,89€ (product con IVA -> MAL) deberái restar 10,89 - 7,26 = 3,63€ (es decir debería restar 6€ + 21% = 7,26€). En conclusión, aplica el descuento sin IVA al total con IVA, cuando debería aplicar el descuento con IVA al total con IVA.

Pues bien, he aquí la solución:

Se trata de modificar la clase Cart.php, (/classes/cart.php), aunque por supuesto recomiendo crear su correspondiente override (override/classes/Cart.php), el ejemplo continua sobre el override, modificando concretamente la función getSummaryDetails(). A continuación dejo la clase en override con esa función modificada, la cual soluciona el problema mencionado, comentando en negrita las líneas añadidas/modificadas.

en override/classes/Cart.php

class Cart extends CartCore
{

    public function getSummaryDetails($id_lang = null, $refresh = false)
    {
        $context = Context::getContext();
        if (!$id_lang) {
            $id_lang = $context->language->id;
        }
        
        $delivery = new Address((int)$this->id_address_delivery);
        $invoice = new Address((int)$this->id_address_invoice);
        
        // New layout system with personalization fields
        $formatted_addresses = array(
            'delivery' => AddressFormat::getFormattedLayoutData($delivery),
            'invoice' => AddressFormat::getFormattedLayoutData($invoice)
        );
        $products = $this->getProducts($refresh);
        
        
        
        $currency = new Currency($this->id_currency);
        
        
        
        $price_reduc = false; //CeSpues -> añadimos variable para controlar si algún producto del carrito tiene precio específico (reducción)
        $total_reduction = 0;//CeSpues -> variable para sumar las reducciones de todos los productos del carrito (en caso de que haya más de uno)

        foreach ($products as $key => &$product) {
            $product['price_without_quantity_discount'] = Product::getPriceStatic(
                $product['id_product'],
                !Product::getTaxCalculationMethod(),
                $product['id_product_attribute'],
                6,
                null,
                false,
                false
                );
            /* CeSpues -> modificamos la lógica, en caso de que haya reduccion */
             if ($product['reduction_type'] == 'amount') {
                 $reduction = (!Product::getTaxCalculationMethod() ? (float)$product['price_wt'] : (float)$product['price']) - (float)$product['price_without_quantity_discount'];
                 
                 $tax_amount = $product['rate']/100; // Cespues -> (guardamos el IVA de ese producto, ya que cada producto puede tener diferente IVA)
                 $reduction_wt = $reduction + $reduction*$tax_amount; // calculamos la reducción incluyendo  el IVA
                 $reduction_extra = (int)$product["cart_quantity"]*($reduction_wt - $reduction); //Calculamos la diferencia de redducion con IVA - reduccion sin IVA y multiplicamos por cantidad de productos en carrito (esto es el IVA que faltaba añadir al descuento)
                 $product['reduction_formatted'] = Tools::displayPrice($reduction);
                 $price_reduc = true; // cambiamos valor a "true", para notificar posteriormente que hay algún producto con descuento
                 $total_reduction = $total_reduction + $reduction_extra; // acumulamos todo los IVA faltantes de cada reduccion aplicada
             }
             /**/

        }
        $base_total_tax_inc = $this->getOrderTotal(true); // Cespues -> calculamos ahora el total con impuestos incluídos
        
        $gift_products = array();
        $cart_rules = $this->getCartRules();
        $total_shipping = $this->getTotalShippingCost();
        $total_shipping_tax_exc = $this->getTotalShippingCost(null, false);
        $total_products_wt = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS);
        
        /* CeSpues -> si ha habido reducción en algún producto */
         if($price_reduc){
         $total_products_wt = $total_products_wt + $total_reduction; // modificamos el total (sólo de productos) con impuestos sumando la reduccion, que será negativa
         $base_total_tax_inc = $base_total_tax_inc + $total_reduction; // modificamos el total absoluto (productos + transporte), aplicando el descuento correctamente
         }
         /**/

        
        $total_products = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS);
        $total_discounts = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS);
        $total_discounts_tax_exc = $this->getOrderTotal(false, Cart::ONLY_DISCOUNTS);
        
        $base_total_tax_exc = $this->getOrderTotal(false);
        $total_tax = $base_total_tax_inc - $base_total_tax_exc; // Cespues -> aqui se calcula el IVA final, usando el valor correcto del total con impuestos, a partir de aquí, el resto de la función ya no cambia.
        
        if ($total_tax < 0) {
            $total_tax = 0;
        }
        
        // The cart content is altered for display
        foreach ($cart_rules as &$cart_rule) {
            // If the cart rule is automatic (wihtout any code) and include free shipping, it should not be displayed as a cart rule but only set the shipping cost to 0
            if ($cart_rule['free_shipping'] && (empty($cart_rule['code']) || preg_match('/^'.CartRule::BO_ORDER_CODE_PREFIX.'[0-9]+/', $cart_rule['code']))) {
                
                $cart_rule['value_real'] -= $total_shipping;
                $cart_rule['value_tax_exc'] -= $total_shipping_tax_exc;
                $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                if ($total_discounts > $cart_rule['value_real']) {
                    $total_discounts -= $total_shipping;
                }
                if ($total_discounts_tax_exc > $cart_rule['value_tax_exc']) {
                    $total_discounts_tax_exc -= $total_shipping_tax_exc;
                }
                
                // Update total shipping
                $total_shipping = 0;
                $total_shipping_tax_exc = 0;
            }
            
            if ($cart_rule['gift_product']) {
                foreach ($products as $key => &$product) {
                    if (empty($product['gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) {
                        // Update total products
                        $total_products_wt = Tools::ps_round($total_products_wt - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        $total_products = Tools::ps_round($total_products - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        
                        // Update total discounts
                        $total_discounts = Tools::ps_round($total_discounts - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        $total_discounts_tax_exc = Tools::ps_round($total_discounts_tax_exc - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        
                        // Update cart rule value
                        $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        
                        // Update product quantity
                        $product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        $product['total'] = Tools::ps_round($product['total'] - $product['price'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_);
                        $product['cart_quantity']--;
                        
                        if (!$product['cart_quantity']) {
                            unset($products[$key]);
                        }
                        
                        // Add a new product line
                        $gift_product = $product;
                        $gift_product['cart_quantity'] = 1;
                        $gift_product['price'] = 0;
                        $gift_product['price_wt'] = 0;
                        $gift_product['total_wt'] = 0;
                        $gift_product['total'] = 0;
                        $gift_product['gift'] = true;
                        $gift_products[] = $gift_product;
                        
                        break; // One gift product per cart rule
                    }
                }
            }
        }
        
        foreach ($cart_rules as $key => &$cart_rule) {
            if (((float)$cart_rule['value_real'] == 0 && (int)$cart_rule['free_shipping'] == 0)) {
                unset($cart_rules[$key]);
            }
        }
        
        $summary = array(
            'delivery' => $delivery,
            'delivery_state' => State::getNameById($delivery->id_state),
            'invoice' => $invoice,
            'invoice_state' => State::getNameById($invoice->id_state),
            'formattedAddresses' => $formatted_addresses,
            'products' => array_values($products),
            'gift_products' => $gift_products,
            'discounts' => array_values($cart_rules),
            'is_virtual_cart' => (int)$this->isVirtualCart(),
            'total_discounts' => $total_discounts,
            'total_discounts_tax_exc' => $total_discounts_tax_exc,
            'total_wrapping' => $this->getOrderTotal(true, Cart::ONLY_WRAPPING),
            'total_wrapping_tax_exc' => $this->getOrderTotal(false, Cart::ONLY_WRAPPING),
            'total_shipping' => $total_shipping,
            'total_shipping_tax_exc' => $total_shipping_tax_exc,
            'total_products_wt' => $total_products_wt,
            'total_products' => $total_products,
            'total_price' => $base_total_tax_inc,
            'total_tax' => $total_tax,
            'total_price_without_tax' => $base_total_tax_exc,
            'is_multi_address_delivery' => $this->isMultiAddressDelivery() || ((int)Tools::getValue('multi-shipping') == 1),
            'free_ship' =>!$total_shipping && !count($this->getDeliveryAddressesWithoutCarriers(true, $errors)),
            'carrier' => new Carrier($this->id_carrier, $id_lang),
        );
        
        $hook = Hook::exec('actionCartSummary', $summary, null, true);
        if (is_array($hook)) {
            $summary = array_merge($summary, array_shift($hook));
        }
        
        return $summary;
    }

}

-------------------

Testeado y funcionando en PS 1.6.1.23, usando las opciones siguientes:

- Mostrar productos sin IVA

- Aplicando precios específicos con impuestos excluídos

Espero que os sea de ayuda, nunca es tarde si la dicha es buena.

 

Link to comment
Share on other sites

Corrección:

Con las anteriores modificaciones los valores en el carrito se ven bien, pero no es correcto, porque no se logra modificar el total del pedido que se envía a las formas de pago. Por lo tanto, haremos una modificación, sobre lo anterior:

- no se crea modificación de la funcion getSummaryDetails() , podéis eliminarla

- se crea una modificación sobre la función getOrderTotal(), llamada por la anterior, y es la que se encarga de calcula el verdadero total que se es utilizado por todas las funciones de todos los módulos., por lo tanto, el overide quedaría del siguiente modo (mucho más sencillo), el cual soluciona el problema en todos los casos (con y cin precios específicos y con y sin tasas):

marco en negrita las modificaciones de la función, con comentarios. Se trata de una copia de getOrderTotal() con 4 líneas añadidas.

en override/classes/Cart.php

class Cart extends CartCore
{

    public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true)
    {
        // Dependencies
        $address_factory    = Adapter_ServiceLocator::get('Adapter_AddressFactory');
        $price_calculator    = Adapter_ServiceLocator::get('Adapter_ProductPriceCalculator');
        $configuration        = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface');
        
        $ps_tax_address_type = $configuration->get('PS_TAX_ADDRESS_TYPE');
        $ps_use_ecotax = $configuration->get('PS_USE_ECOTAX');
        $ps_round_type = $configuration->get('PS_ROUND_TYPE');
        $ps_ecotax_tax_rules_group_id = $configuration->get('PS_ECOTAX_TAX_RULES_GROUP_ID');
        $compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_');
        
        if (!$this->id) {
            return 0;
        }
        
        $type = (int)$type;
        $array_type = array(
            Cart::ONLY_PRODUCTS,
            Cart::ONLY_DISCOUNTS,
            Cart::BOTH,
            Cart::BOTH_WITHOUT_SHIPPING,
            Cart::ONLY_SHIPPING,
            Cart::ONLY_WRAPPING,
            Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING,
            Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING,
        );
        
        // Define virtual context to prevent case where the cart is not the in the global context
        $virtual_context = Context::getContext()->cloneContext();
        $virtual_context->cart = $this;
        
        if (!in_array($type, $array_type)) {
            die(Tools::displayError());
        }
        
        $with_shipping = in_array($type, array(Cart::BOTH, Cart::ONLY_SHIPPING));
        
        // if cart rules are not used
        if ($type == Cart::ONLY_DISCOUNTS && !CartRule::isFeatureActive()) {
            return 0;
        }
        
        // no shipping cost if is a cart with only virtuals products
        $virtual = $this->isVirtualCart();
        if ($virtual && $type == Cart::ONLY_SHIPPING) {
            return 0;
        }
        
        if ($virtual && $type == Cart::BOTH) {
            $type = Cart::BOTH_WITHOUT_SHIPPING;
        }
        
        if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) {
            if (is_null($products) && is_null($id_carrier)) {
                $shipping_fees = $this->getTotalShippingCost(null, (bool)$with_taxes);
            } else {
                $shipping_fees = $this->getPackageShippingCost((int)$id_carrier, (bool)$with_taxes, null, $products);
            }
        } else {
            $shipping_fees = 0;
        }
        
        if ($type == Cart::ONLY_SHIPPING) {
            return $shipping_fees;
        }
        
        if ($type == Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) {
            $type = Cart::ONLY_PRODUCTS;
        }
        
        $param_product = true;
        if (is_null($products)) {
            $param_product = false;
            $products = $this->getProducts();
        }
        
        if ($type == Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING) {
            foreach ($products as $key => $product) {
                if ($product['is_virtual']) {
                    unset($products[$key]);
                }
            }
            $type = Cart::ONLY_PRODUCTS;
        }
        
        $order_total = 0;
        if (Tax::excludeTaxeOption()) {
            $with_taxes = false;
        }
        
        $products_total = array();
        $ecotax_total = 0;
        
        foreach ($products as $product) {
            // products refer to the cart details
            
            if ($virtual_context->shop->id != $product['id_shop']) {
                $virtual_context->shop = new Shop((int)$product['id_shop']);
            }
            
            if ($ps_tax_address_type == 'id_address_invoice') {
                $id_address = (int)$this->id_address_invoice;
            } else {
                $id_address = (int)$product['id_address_delivery'];
            } // Get delivery address of the product from the cart
            if (!$address_factory->addressExists($id_address)) {
                $id_address = null;
            }
            
            // The $null variable below is not used,
            // but it is necessary to pass it to getProductPrice because
            // it expects a reference.
            $null = null;
            $price = $price_calculator->getProductPrice(
                (int)$product['id_product'],
                $with_taxes,
                (int)$product['id_product_attribute'],
                6,
                null,
                false,
                true,
                $product['cart_quantity'],
                false,
                (int)$this->id_customer ? (int)$this->id_customer : null,
                (int)$this->id,
                $id_address,
                $null,
                $ps_use_ecotax,
                true,
                $virtual_context
                );
            /*CeSpues -> modificar el precio del producto si usa precio específico*/
            if ($product['reduction_type'] == 'amount' && $with_taxes == true) {     //en caso de que el producto tenga descuento específico y se trata del total con tasas se ejecuta este código
                $tax_amount = $product['rate']/100; // recuperamos el impuesto a añadir
                $price = $product['price_with_reduction_without_tax']+$product['price_with_reduction_without_tax']*$tax_amount;    //nuevo precio: obligamos a usar la variable del precio con descuento sin tasas y le sumamos las tasas
            }elseif($product['reduction_type'] == 'amount' && $with_taxes == false) $price = $product['price_with_reduction_without_tax'];     //en caso de no usar tasas para precio total, solamente obligamos a usar el precio del producto con descuento específico

            
            //$price = $product['price_with_reduction_without_tax'];
            $address = $address_factory->findOrCreate($id_address, true);
            
            if ($with_taxes) {
                $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $virtual_context);
                $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
            } else {
                $id_tax_rules_group = 0;
            }
            
            if (in_array($ps_round_type, array(Order::ROUND_ITEM, Order::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 ($ps_round_type) {
                case Order::ROUND_TOTAL:
                    $products_total[$id_tax_rules_group.'_'.$id_address] += $price * (int)$product['cart_quantity'];
                    break;
                    
                case Order::ROUND_LINE:
                    $product_price = $price * $product['cart_quantity'];
                    $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision);
                    break;
                    
                case Order::ROUND_ITEM:
                default:
                    $product_price = /*$with_taxes ? $tax_calculator->addTaxes($price) : */$price;
                    $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision) * (int)$product['cart_quantity'];
                    break;
            }
        }
        foreach ($products_total as $key => $price) {
            $order_total += $price;
        }
        $order_total_products = $order_total;
        
        if ($type == Cart::ONLY_DISCOUNTS) {
            $order_total = 0;
        }
        
        // Wrapping Fees
        $wrapping_fees = 0;
        
        // With PS_ATCP_SHIPWRAP on the gift wrapping cost computation calls getOrderTotal with $type === Cart::ONLY_PRODUCTS, so the flag below prevents an infinite recursion.
        $include_gift_wrapping = (!$configuration->get('PS_ATCP_SHIPWRAP') || $type !== Cart::ONLY_PRODUCTS);
        
        if ($this->gift && $include_gift_wrapping) {
            $wrapping_fees = Tools::convertPrice(Tools::ps_round($this->getGiftWrappingPrice($with_taxes), $compute_precision), Currency::getCurrencyInstance((int)$this->id_currency));
        }
        if ($type == Cart::ONLY_WRAPPING) {
            return $wrapping_fees;
        }
        
        $order_total_discount = 0;
        $order_shipping_discount = 0;
        if (!in_array($type, array(Cart::ONLY_SHIPPING, Cart::ONLY_PRODUCTS)) && CartRule::isFeatureActive()) {
            // First, retrieve the cart rules associated to this "getOrderTotal"
            if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) {
                $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_ALL);
            } else {
                $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_REDUCTION);
                // Cart Rules array are merged manually in order to avoid doubles
                foreach ($this->getCartRules(CartRule::FILTER_ACTION_GIFT) as $tmp_cart_rule) {
                    $flag = false;
                    foreach ($cart_rules as $cart_rule) {
                        if ($tmp_cart_rule['id_cart_rule'] == $cart_rule['id_cart_rule']) {
                            $flag = true;
                        }
                    }
                    if (!$flag) {
                        $cart_rules[] = $tmp_cart_rule;
                    }
                }
            }
            
            $id_address_delivery = 0;
            if (isset($products[0])) {
                $id_address_delivery = (is_null($products) ? $this->id_address_delivery : $products[0]['id_address_delivery']);
            }
            $package = array('id_carrier' => $id_carrier, 'id_address' => $id_address_delivery, 'products' => $products);
            
            // Then, calculate the contextual value for each one
            $flag = false;
            foreach ($cart_rules as $cart_rule) {
                // If the cart rule offers free shipping, add the shipping cost
                if (($with_shipping || $type == Cart::ONLY_DISCOUNTS) && $cart_rule['obj']->free_shipping && !$flag) {
                    $order_shipping_discount = (float)Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, ($param_product ? $package : null), $use_cache), $compute_precision);
                    $flag = true;
                }
                
                // If the cart rule is a free gift, then add the free gift value only if the gift is in this package
                if ((int)$cart_rule['obj']->gift_product) {
                    $in_order = false;
                    if (is_null($products)) {
                        $in_order = true;
                    } else {
                        foreach ($products as $product) {
                            if ($cart_rule['obj']->gift_product == $product['id_product'] && $cart_rule['obj']->gift_product_attribute == $product['id_product_attribute']) {
                                $in_order = true;
                            }
                        }
                    }
                    
                    if ($in_order) {
                        $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_GIFT, $package, $use_cache);
                    }
                }
                
                // If the cart rule offers a reduction, the amount is prorated (with the products in the package)
                if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0) {
                    $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), $compute_precision);
                }
            }
            $order_total_discount = min(Tools::ps_round($order_total_discount, 2), (float)$order_total_products) + (float)$order_shipping_discount;
            $order_total -= $order_total_discount;
        }
        
        if ($type == Cart::BOTH) {
            $order_total += $shipping_fees + $wrapping_fees;
        }
        
        if ($order_total < 0 && $type != Cart::ONLY_DISCOUNTS) {
            return 0;
        }
        
        if ($type == Cart::ONLY_DISCOUNTS) {
            return $order_total_discount;
        }
        return Tools::ps_round((float)$order_total, $compute_precision);
    }

}

De este modo, a parte de calcular bien los costes en el carrito, se envían los valores correctos a las formas de pago.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...