Fix: Incorrect tax calculation after room reallocation

This commit is contained in:
Aman deep sharma
2025-06-30 16:37:32 +05:30
parent 569c093b00
commit f70c8a99d2
6 changed files with 130 additions and 6 deletions

View File

@@ -2598,8 +2598,53 @@ class OrderCore extends ObjectModel
Product::PRICE_ADDITION_TYPE_WITH_ROOM
)
) {
$additionalTaxAmounts = $tax_calculator->getTaxesAmount($autoAddedPriceExcl);
$totalTaxBase += $autoAddedPriceExcl;
$autoAddedServiceData = $objServiceProductOrderDetail->getRoomTypeServiceProducts(
$order_detail['id_order'],
0, 0,
$order_detail['product_id'],
0, 0, 0,
false, false, true,
Product::PRICE_ADDITION_TYPE_WITH_ROOM
);
// We are getting auto added service for specific room.There will be only on htl_booking_detail but can have multiple auto added service with room.
// Note: All the auto added service with room have same id_tax_rule group
$autoAddedServiceData = array_shift($autoAddedServiceData);
$autoAddedServices = $autoAddedServiceData['additional_services'];
// Calculate total quantity of auto-added services
$totalAutoAddedQty = array_reduce($autoAddedServices, function ($quantity, $service) {
$qty = isset($service['quantity']) ? $service['quantity'] : 0;
return $quantity + $qty;
}, 0);
$firstAutoAddedService = array_shift($autoAddedServices);
$id_tax_rule_group = $firstAutoAddedService['id_tax_rules_group'];
// If tax group is different from order detail, add tax info separately
if ($order_detail['id_tax_rules_group'] != $id_tax_rule_group) {
$objAddress = new Address((int)$this->id_address_tax);
$autoAddedServiceTaxManager = TaxManagerFactory::getManager($objAddress, (int)$id_tax_rule_group);
$autoAddedServiceTaxCalculator = $autoAddedServiceTaxManager->getTaxCalculator();
// Calculate tax for the total price
$additionalTaxAmounts = $autoAddedServiceTaxCalculator->getTaxesAmount($autoAddedPriceExcl);
foreach ($additionalTaxAmounts as $taxId => $amount) {
$objTax = new Tax((int)$taxId);
$groupedTaxDetails[$taxId] = array(
'id_order_detail' => $firstAutoAddedService['id_order_detail'],
'id_tax' => $taxId,
'tax_rate' => $objTax->rate,
'unit_tax_base' => $autoAddedPriceExcl / $totalAutoAddedQty,
'total_tax_base' => $autoAddedPriceExcl,
'unit_amount' => $amount,
'total_amount' => Tools::processPriceRounding($amount, $totalAutoAddedQty),
);
}
} else {
// Calculate tax for the total price
$additionalTaxAmounts = $tax_calculator->getTaxesAmount($autoAddedPriceExcl);
$totalTaxBase += $autoAddedPriceExcl;
}
}
$taxBaseShare = $totalTaxBase;

View File

@@ -650,7 +650,7 @@ class OrderInvoiceCore extends ObjectModel
'total_price_tax_excl' => 0,
'total_amount' => 0,
'id_tax' => $row['id_tax'],
'rate' => $key,
'rate' => sprintf('%.3f', $row['tax_rate']),
);
}

View File

@@ -231,10 +231,11 @@ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice
{
$breakdowns = array(
'room_tax' => $this->getRoomTypeTaxesBreakdown(),
'service_products_tax' => $this->getServiceProductsTaxesBreakdown($this->order),
'shipping_tax' => $this->getShippingTaxesBreakdown(),
'ecotax_tax' => $this->order_slip->getEcoTaxTaxesBreakdown(),
);
foreach ($breakdowns as $type => $bd) {
if (empty($bd)) {
unset($breakdowns[$type]);
@@ -339,6 +340,68 @@ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice
return $breakdown;
}
public function getServiceProductsTaxesBreakdown()
{
$sum_composite_taxes = !$this->useOneAfterAnotherTaxComputationMethod();
// $breakdown will be an array with tax rates as keys and at least the columns:
// - 'total_price_tax_excl'
// - 'total_amount'
$breakdown = array();
$order_detail = array_filter($this->order->products, function($v) {
return (!$v['is_booking_product'] && (
$v['selling_preference_type'] == Product::SELLING_PREFERENCE_STANDALONE
|| $v['selling_preference_type'] == Product::SELLING_PREFERENCE_HOTEL_STANDALONE
));
});
$details = $this->order->getProductTaxesDetails($order_detail, false);
if ($sum_composite_taxes) {
$grouped_details = array();
foreach ($details as $row) {
if (!isset($grouped_details[$row['id_order_detail']])) {
$grouped_details[$row['id_order_detail']] = array(
'tax_rate' => 0,
'total_tax_base' => $row['total_tax_base'],
'total_amount' => 0,
'id_tax' => $row['id_tax'],
);
}
$grouped_details[$row['id_order_detail']]['tax_rate'] += $row['tax_rate'];
$grouped_details[$row['id_order_detail']]['total_amount'] += $row['total_amount'];
}
$details = $grouped_details;
}
foreach ($details as $row) {
if (!$sum_composite_taxes) {
$key = $row['id_tax'];
} else {
$key = sprintf('%.3f', $row['tax_rate']);
}
if (!isset($breakdown[$key])) {
$breakdown[$key] = array(
'total_price_tax_excl' => 0,
'total_amount' => 0,
'id_tax' => $row['id_tax'],
'rate' => sprintf('%.3f', $row['tax_rate']),
);
}
$breakdown[$key]['total_price_tax_excl'] += $row['total_tax_base'];
$breakdown[$key]['total_amount'] += $row['total_amount'];
}
foreach ($breakdown as $key => $data) {
$breakdown[$key]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode);
$breakdown[$key]['total_amount'] = Tools::ps_round($data['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode);
}
ksort($breakdown);
return $breakdown;
}
/**
* Returns Shipping tax breakdown elements
*

View File

@@ -140,11 +140,14 @@ class TaxCalculatorCore
$taxes_amounts = array();
foreach ($this->taxes as $tax) {
if (!isset($taxes_amounts[$tax->id])) {
$taxes_amounts[$tax->id] = 0;
}
if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD) {
$taxes_amounts[$tax->id] = $price_te * (abs($tax->rate) / 100);
$taxes_amounts[$tax->id] += $price_te * (abs($tax->rate) / 100);
$price_te = $price_te + $taxes_amounts[$tax->id];
} else {
$taxes_amounts[$tax->id] = ($price_te * (abs($tax->rate) / 100));
$taxes_amounts[$tax->id] += ($price_te * (abs($tax->rate) / 100));
}
}

View File

@@ -71,6 +71,8 @@ class RoomTypeServiceProductPrice extends ObjectModel
{
$cache_key = 'RoomTypeServiceProductPrice::getProductRoomTypePriceAndTax'.$idProduct.'_'.$idElement.'_'.$elementType;
if (!Cache::isStored($cache_key)) {
$objServiceProductCartDetail = new ServiceProductCartDetail();
$objServiceProduct = new Product((int)$idProduct);
if ($result = Db::getInstance()->getRow('
SELECT spp.`price`, spp.`id_tax_rules_group`, p.`auto_add_to_cart`, p.`price_addition_type`
FROM `'._DB_PREFIX_.'product` p
@@ -88,6 +90,15 @@ class RoomTypeServiceProductPrice extends ObjectModel
$result['id_tax_rules_group'] = Product::getIdTaxRulesGroupByIdProduct((int)$idElement);
}
}
} elseif ($objServiceProduct->auto_add_to_cart
&& $elementType == RoomTypeServiceProduct::WK_ELEMENT_TYPE_ROOM_TYPE
&& $objServiceProduct->price_addition_type == Product::PRICE_ADDITION_TYPE_WITH_ROOM
&& $objServiceProductCartDetail->alreadyExists(Context::getContext()->cart->id, $idProduct)
) {
$result = array();
$result['auto_add_to_cart'] = 1;
$result['price_addition_type'] = Product::PRICE_ADDITION_TYPE_WITH_ROOM;
$result['id_tax_rules_group'] = Product::getIdTaxRulesGroupByIdProduct((int)$idElement);
}
Cache::store($cache_key, $result);

View File

@@ -304,6 +304,8 @@ class ServiceProductOrderDetail extends ObjectModel
'name' => $product['name'],
'quantity' => $product['quantity'],
'allow_multiple_quantity' => $product['product_allow_multiple_quantity'],
'tax_computation_method' => $product['tax_computation_method'],
'id_tax_rules_group' => $product['id_tax_rules_group'],
'price_calculation_method' => $product['product_price_calculation_method'],
'product_tax' => $product_tax,
'product_tax_label' => $product_tax_label,