Cypher-key Posted December 9 Share Posted December 9 Bonjour, Je vous contacte pour comprendre un peu mieux le fonctionnement des bons de réductions sur Prestashop (version 1.7.8.9). Actuellement, l'ERP d'un de nos client renvoie des erreurs liés à la TVA suite à l'utilisation des réductions sur son site. Lors de l'utilisation de réductions, le montant est déduit du total hors taxe des produits. Or, cette réduction est en TTC, et est appliquée sur les produits Hors Taxe du panier; Une telle réduction ne devrait-elle pas être appliquée sur le montant total du panier, et non pas les produits ? Par ailleurs, nous avons aussi l'ajout d'un produit sous forme de cadeau, et son prix est bel et bien retiré du total du panier de la même manière. Mais son prix ne devrais-il pas être déduit du montant du produit en lui-même ? Ces réductions posent problème lors du détail du clacul de la TVA, puisque les montants sont retirés des prix des produits individuellement, créant des valeurs ne correspodnant à rien dans l'ERP. Ne serait-il pas plsu logique que le montant d'un produit offert soit déduit à lui-même indépendament du reste des produits, et la réduction TTC appliquée au panier total ? En vous remerciant pour vos retours, Link to comment Share on other sites More sharing options...
Eolia Posted December 9 Share Posted December 9 Tout dépend comment sont configurés ces bons de réduction et sur quoi ils s'appliquent Link to comment Share on other sites More sharing options...
Cypher-key Posted December 9 Author Share Posted December 9 Les bons de réductions sont configurés en montant TTC, et s'appliquent suir le total du panier, d'où ma question. Et concernant les cadeaux... Il s'agit d'un produit ajouté en cadeau lorsqu'un montant est dépassé, donc aucun autre réglagé n'est appliqué dans le bon de réduction. Link to comment Share on other sites More sharing options...
Cypher-key Posted December 11 Author Share Posted December 11 Je suis en train de remonter tout le fil de où se situe tout les calculs dans Prestashop, et je trouve des résultats lunaires. Par exemple : pourquoi est-ce que le montant de taxe correct lors d'un achat n'est pas renseigné dans la base de données ? APrès export vers l'ERP, le montant réduit ets utilisé, mais les montants HT et TTC du produit ne sont pas modifiés et sont ceux remplis dans le site, ce qui créé des problèmes dans la comptabilité ! (Et je ne parle pas des sempiternels problèmes d'arrondis qui ne sont toujours pas réglés à ce jour, deux versions majeures plus tard). Est-ce que quelqu'un pourrait éclairer ma lanterne sur le fonctionnement exact des calculs des totaux, et comment sont calculées les réductions ? Rien ne semble avoir de sens. Link to comment Share on other sites More sharing options...
Eolia Posted December 11 Share Posted December 11 le montant HT et TTC des réductions (Règles paniers) est dans la table ps_orders et ps_order_cart_rule La table ps_order_detail enregistre les prix produits avec uniquement l'impact des prix spécifiques s'il y en a Link to comment Share on other sites More sharing options...
Cypher-key Posted December 11 Author Share Posted December 11 (edited) Le problème vient du fait que le montant de TVA remonté sur l'ERP, et utililsé dans le détail des taxes de la facture provient de la table ps_order_detail_tax, dont le montant est calculé après déduction des réductions dans la commande. Ce qui n'a aucun sens. Cela fait, par exemple, qu'un produit à 19.90€ avec une TVA à 5.5% et a donc un prix à 18.85€ se retrouve avec un total de TVA de 0.65€ au lieu de 1.04€. Or, le détails des taxes n'a aucun sens, puisque recalculé je ne sais comment, et nous offre des résultats incompréhensibles, qui n'offrent pas un montant de taxe correct même en calculant à la main (cf exemple ci-joint). Edited December 11 by Cypher-key (see edit history) Link to comment Share on other sites More sharing options...
Eolia Posted December 11 Share Posted December 11 Ah oui mais Prestashop a inventé une super fonction de prorata des taxes quand il y a plusieurs taxes différentes dans un même panier. C'est une hérésie que j'ai dénoncé maintes fois mais ils persistent. public function getShippingTaxesBreakdown($order) { // No shipping breakdown if no shipping! if ($this->total_shipping_tax_excl == 0) { return []; } // No shipping breakdown if it's free! foreach ($order->getCartRules() as $cart_rule) { if ($cart_rule['free_shipping']) { return []; } } $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; if (Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') || Configuration::get('PS_ATCP_SHIPWRAP')) { $shipping_breakdown = Db::getInstance()->executeS( 'SELECT t.id_tax, t.rate, oit.amount as total_amount FROM `' . _DB_PREFIX_ . 'tax` t INNER JOIN `' . _DB_PREFIX_ . 'order_invoice_tax` oit ON oit.id_tax = t.id_tax WHERE oit.type = "shipping" AND oit.id_order_invoice = ' . (int) $this->id ); $sum_of_split_taxes = 0; $sum_of_tax_bases = 0; /** @var array{id_tax: int, rate: float, total_amount: float} $row */ foreach ($shipping_breakdown as &$row) { if (Configuration::get('PS_ATCP_SHIPWRAP')) { $row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode); $sum_of_tax_bases += $row['total_tax_excl']; } else { $row['total_tax_excl'] = $this->total_shipping_tax_excl; } $row['total_amount'] = Tools::ps_round($row['total_amount'], Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode); $sum_of_split_taxes += $row['total_amount']; } unset($row); $delta_amount = $shipping_tax_amount - $sum_of_split_taxes; if ($delta_amount != 0) { Tools::spreadAmount($delta_amount, Context::getContext()->getComputingPrecision(), $shipping_breakdown, 'total_amount'); } $delta_base = $this->total_shipping_tax_excl - $sum_of_tax_bases; if ($delta_base != 0) { Tools::spreadAmount($delta_base, Context::getContext()->getComputingPrecision(), $shipping_breakdown, 'total_tax_excl'); } } else { $shipping_breakdown = [ [ 'total_tax_excl' => $this->total_shipping_tax_excl, 'rate' => $order->carrier_tax_rate, 'total_amount' => $shipping_tax_amount, 'id_tax' => null, ], ]; } return $shipping_breakdown; } La fameuse fonction : /** * Spread an amount on lines, adjusting the $column field, * with the biggest adjustments going to the rows having the * highest $sort_column. * * E.g.: * $rows = [['a' => 5.1], ['a' => 8.2]]; * spreadAmount(0.3, 1, $rows, 'a'); * => $rows is [['a' => 8.4], ['a' => 5.2]] * * @param float $amount The amount to spread across the rows * @param int $precision Rounding precision * e.g. if $amount is 1, $precision is 0 and $rows = [['a' => 2], ['a' => 1]] * then the resulting $rows will be [['a' => 3], ['a' => 1]] * But if $precision were 1, then the resulting $rows would be [['a' => 2.5], ['a' => 1.5]] * @param array $rows An array, associative or not, containing arrays that have at least $column and $sort_column fields * @param string $column The column on which to perform adjustments */ public static function spreadAmount($amount, $precision, &$rows, $column) { if (!is_array($rows) || empty($rows)) { return; } $sort_function = function ($a, $b) use ($column) { return $b[$column] > $a[$column] ? 1 : -1; }; uasort($rows, $sort_function); $unit = 10 ** $precision; $int_amount = (int) round($unit * $amount); $remainder = $int_amount % count($rows); $amount_to_spread = ($int_amount - $remainder) / count($rows) / $unit; $sign = ($amount >= 0 ? 1 : -1); $position = 0; foreach ($rows as &$row) { $adjustment_factor = $amount_to_spread; if ($position < abs($remainder)) { $adjustment_factor += $sign * 1 / $unit; } $row[$column] += $adjustment_factor; ++$position; } unset($row); } Perso j'ai viré tout ça dans PhenixSuite^^ Link to comment Share on other sites More sharing options...
Cypher-key Posted December 12 Author Share Posted December 12 ... Qu'est-ce que c'est que cette horreur '-' ? Sans vouloir trop en, demander, pourriez-vous me dire comment vous avez pu passer outre dans PhenixSuite ? Link to comment Share on other sites More sharing options...
Eolia Posted December 12 Share Posted December 12 Le raisonnement a été fait dans l'autre sens et tous les round() ont été supprimés. L'arrondi ne doit être effectué qu'en final/display, pas pendant les calculs surtout que Prestashop n'a jamais compris que la somme des arrondis n'est pas égale à l'arrondi de la somme. Ils font la même erreur dans la génération des avoirs. Et dans Phenix on limite les calculs vu que les valeurs des règles paniers (getContextualValue()) sont stockées dans la table ps_cart_cart_rule Et si, comme dans votre cas, une réduction est appliquée en montant TTC sur une commande, il faut se baser sur le TTC. Exemple simple, le panier comporte 3 produits avec 3 taux de taxe: 1 produit à 10€ à 5% 1 produit à 10€ à 10% 1 produit à 10€ à 20% Dans cette exemple le prorata de chaque produit représente 33.33% du total. Total TTC = 30€ - Remise TTC 5€ Total remisé : 25€ Le prorata des produits reste le même après remise globale: 33.33% Après remise (25 €/3): Produit 1 TTC = 8.333€ Produit 1 TTC = 8.333€ Produit 1 TTC = 8.333€ On peut à présent récupérer les HT et taxes: Produit 1 HT = 8.333/1.05 = 7.94 HT (0.39 de TVA) Produit 2 HT = 8.333/1.1 = 7.57 HT (0.76 de TVA) Produit 3HT = 8.333/1.2 = 6.94 HT (1.39 de TVA) Ensuite pour l'affichage, soit on conserve les prix et taxes avant remise et on détaille les taxes de la remise, soit on affiche dans le récap les taxes finales payées sur cette commande. Soit: - Un total avant remise TTC de 30€, 26.94 HT (9.52 + 9.09 + 8.33) + TVA 3.06€ - Un total remisé TTC de 25€, 22.45 € HT + total TVA 2.54 € - Une remise de 5€ TTC, 4.48 HT + TVA 0.52 € Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now