/** * Compounds rates of this compounder added with addRate() method * * @param cbpaidPaymentBasket $paymentBasket * @param cbpaidPaymentTotalizerCompoundable[] $taxableTotalizers * @param string $totalizerType * @return void */ public function computeAllTaxes($paymentBasket, &$taxableTotalizers, $totalizerType) { $currency = $paymentBasket->mc_currency; $anyAutoRecurringInBasket = $paymentBasket->isAnyAutoRecurringPossibleWithThisBasket(); foreach ($this->ratesToCompound as $ratesOfPriorityItem) { // handle first taxes-inclusive items: //TODO $this->_getItemsTaxesInclusiveToExclusive( $ratesOfPriorityItem, $currency ); $itemsTaxesToAdd = array(); foreach ($ratesOfPriorityItem as $ratesOfItem) { $item = $ratesOfItem['item']; // item can have first_rate and first_period SOMETIMES, but only of $anyAutoRecurringInBasket // totalizer is same rules as basket: if basket has first_period then totalizer follows basket. // So: // Now $first.... below is refering to the $item : $extraAmountBefore = 0; $extraPercents = 0; $extraAmountAfter = 0; $firstExtraAmountBefore = 0; $firstExtraPercents = 0; $firstExtraAmountAfter = 0; $itemHasReallyFirstRate = isset($item->first_validity) && $item->first_validity || $item->first_rate; // when $item is cbpaidPaymentTotalizer then it doesn't have first_validity $itemHasFirstRate = $itemHasReallyFirstRate || $item->first_discount_amount || $item->first_tax_amount; $amountTaxExcl = $this->_getItemAmount_first_incl($item, false, false); $amount = $this->_getItemAmount_first_incl($item, true, false); if ($itemHasFirstRate) { $firstAmountTaxExcl = $this->_getItemAmount_first_incl($item, false, true, $itemHasReallyFirstRate); $firstAmount = $this->_getItemAmount_first_incl($item, true, true, $itemHasReallyFirstRate); } else { $firstAmountTaxExcl = null; $firstAmount = null; } // first handles the item: $totalizerRatesOfItem = array(); // first period first, as some totalizers differ after use (e.g. wallet use), then the normal period: foreach ($ratesOfItem['ratestots'] as $k => $rateTotalizer) { /** @var $rate cbpaidTotalizertypeCompoundable */ list($rate, $totalizer) = $rateTotalizer; $rate->setBasket($paymentBasket); $rate->setPaymentItem($item); /* NOT NOW, MAYBE LATER DIFFERENTLY: if ( $item->getPlanParam( 'tax_taxing_date', 1 ) == 2 ) { $tax_taxing_date_ratio = $item->getPlanParam( 'tax_taxing_date_ratio', 0.0 ); // we have a non-linear taxation on this item: $item = NEW cbpaidPaymentItem(); // Does this taxRate start after the start (or stops before the stop) of the initiating time of the basket ? : $itemStartDay = cbpaidTimes::getInstance()->localDate( 'Y-m-d', cbpaidTimes::getInstance()->strToTime( $item->start_date ) ); $taxRate_stop_date = ( $rate->stop_date == '0000-00-00' ? '9999-99-99' : $rate->stop_date ); if ( ( $rate->start_date <= $itemStartDay ) && ( $taxRate_stop_date >= $itemStartDay ) ) { // The item starts during the validity period of this tax rate: we need to fix the ratios: } else { $proraterFactor = ( 100.0 - (float) $tax_taxing_date_ratio ) / 100; } } else { $proraterFactor = 1; } */ // if ( $totalizer->first_rate !== null ) { /** @var $totalizer cbpaidPaymentTotalizerCompoundable */ $firstPeriodProrater = $totalizer->proRatePeriod($item, true); $totalizerRatesOfItem[$k]['fr'] = $firstPeriodProrater; if ($itemHasFirstRate) { $firstExtraAmountBefore += $totalizerRatesOfItem[$k]['fb'] = $rate->getAmountBeforePercents($firstAmount, $firstAmountTaxExcl, $firstPeriodProrater, true, $currency); $firstExtraPercents += $totalizerRatesOfItem[$k]['fp'] = $rate->getPercents($firstAmount, $firstAmountTaxExcl, $firstPeriodProrater, true); $firstExtraAmountAfter += $totalizerRatesOfItem[$k]['fa'] = $rate->getAmountAfterPercents($firstAmount, $firstAmountTaxExcl, $firstPeriodProrater, true, $currency); } else { $firstExtraAmountBefore += $totalizerRatesOfItem[$k]['fb'] = $rate->getAmountBeforePercents($amount, $amountTaxExcl, $firstPeriodProrater, true, $currency); $firstExtraPercents += $totalizerRatesOfItem[$k]['fp'] = $rate->getPercents($amount, $amountTaxExcl, $firstPeriodProrater, true); $firstExtraAmountAfter += $totalizerRatesOfItem[$k]['fa'] = $rate->getAmountAfterPercents($amount, $amountTaxExcl, $firstPeriodProrater, true, $currency); } // } } // Now the normal recurring period: if ($anyAutoRecurringInBasket && $item->autorecurring > 0) { foreach ($ratesOfItem['ratestots'] as $k => $rateTotalizer) { list($rate, $totalizer) = $rateTotalizer; if ($totalizer->rate !== null) { $periodProrater = $totalizer->proRatePeriod($item, false); $totalizerRatesOfItem[$k]['r'] = $periodProrater; $extraAmountBefore += $totalizerRatesOfItem[$k]['b'] = $rate->getAmountBeforePercents($amount, $amountTaxExcl, $periodProrater, false, $currency); $extraPercents += $totalizerRatesOfItem[$k]['p'] = $rate->getPercents($amount, $amountTaxExcl, $periodProrater, false); $extraAmountAfter += $totalizerRatesOfItem[$k]['a'] = $rate->getAmountAfterPercents($amount, $amountTaxExcl, $periodProrater, false, $currency); } } } // Now adds to the item: if ($itemHasFirstRate) { $first_tax_amount = ($firstAmount + $firstExtraAmountBefore) * (1 + $firstExtraPercents) + $firstExtraAmountAfter - $firstAmount; } else { $first_tax_amount = ($amount + $firstExtraAmountBefore) * (1 + $firstExtraPercents) + $firstExtraAmountAfter - $amount; } $second_tax_amount = ($amount + $extraAmountBefore) * (1 + $extraPercents) + $extraAmountAfter - $amount; if ($anyAutoRecurringInBasket && $item->autorecurring > 0) { // We cannot do this now, otherwise same-priority taxes will be compounded: // $item->first_tax_amount += $first_tax_amount; // So store that for after all rates totalizers of this priority have been handled: if ($first_tax_amount != 0 && ($itemHasFirstRate || $first_tax_amount != $second_tax_amount)) { if (!$itemHasFirstRate) { // As the following step will create the first rate for the item, we need to copy current discount from regular discount amount: $item->first_discount_amount = $item->discount_amount; $item->first_tax_amount = $item->tax_amount; } // Now prepare following statement but deferred: // $item->first_discount_amount (or ->first_tax_amount) += $first_tax_amount; $itemsTaxesToAdd[] = array($item, $this->_getItemTotalizerColumnName(true), $first_tax_amount); } else { $second_tax_amount = ($amount + $firstExtraAmountBefore) * (1 + $firstExtraPercents) + $firstExtraAmountAfter - $amount; } if ($second_tax_amount != 0) { // Now prepare following statement but deferred: // $item->discount_amount (or ->tax_amount) += $tax_amount; $itemsTaxesToAdd[] = array($item, $this->_getItemTotalizerColumnName(false), $second_tax_amount); } } else { $itemsTaxesToAdd[] = array($item, $this->_getItemTotalizerColumnName(false), $first_tax_amount); } // then, now that totals for this item in this tax priority are known, handles the totalizers (of that priority, for that item): foreach ($ratesOfItem['ratestots'] as $k => $rateTotalizer) { list(, $totalizer) = $rateTotalizer; if ($totalizer->first_rate !== null) { if ($itemHasFirstRate) { $totalizer->first_original_rate += $firstAmount * $totalizerRatesOfItem[$k]['fr']; $totalizer->first_rate += $totalizerRatesOfItem[$k]['fb'] + (($firstAmount + $firstExtraAmountBefore) * (0 + $totalizerRatesOfItem[$k]['fp']) + $totalizerRatesOfItem[$k]['fa']); } else { // Basket and totalizer have first rate but the item doesn't have one: still add item's non-first tax to totalizer's first tax: $totalizer->first_original_rate += $amount * $totalizerRatesOfItem[$k]['fr']; $totalizer->first_rate += $totalizerRatesOfItem[$k]['fb'] + (($amount + $firstExtraAmountBefore) * (0 + $totalizerRatesOfItem[$k]['fp']) + $totalizerRatesOfItem[$k]['fa']); } $totalizer->first_original_rate = round($totalizer->first_original_rate, 2); $totalizer->first_rate = round($totalizer->first_rate, 2); } if ($totalizer->rate !== null && (!$anyAutoRecurringInBasket || $anyAutoRecurringInBasket && $item->autorecurring > 0)) { if ($anyAutoRecurringInBasket) { $totalizer->original_rate += $amount * $totalizerRatesOfItem[$k]['r']; $totalizer->rate += $totalizerRatesOfItem[$k]['b'] + (($amount + $extraAmountBefore) * (0 + $totalizerRatesOfItem[$k]['p']) + $totalizerRatesOfItem[$k]['a']); } else { $totalizer->original_rate += $amount * $totalizerRatesOfItem[$k]['fr']; $totalizer->rate += $totalizerRatesOfItem[$k]['fb'] + (($amount + $extraAmountBefore) * (0 + $totalizerRatesOfItem[$k]['fp']) + $totalizerRatesOfItem[$k]['fa']); } $totalizer->original_rate = round($totalizer->original_rate, 2); $totalizer->rate = round($totalizer->rate, 2); if ($totalizer->first_rate == null && $anyAutoRecurringInBasket) { $totalizer->first_rate = '0.0'; $totalizer->first_item_days = $totalizer->item_days; $totalizer->first_totalizer_days = $totalizer->totalizer_days; $totalizer->first_original_rate = '0.0'; } } } } unset($totalizerRatesOfItem); // Now can add to items the taxes, before we look at next tax rates priorities: foreach ($itemsTaxesToAdd as $taxToAdd) { $taxToAdd[0]->{$taxToAdd[1]} += $taxToAdd[2]; } } // Now that all items and totalizers have been computed, adjust basket: foreach ($taxableTotalizers as $k => $totalizer) { if ($totalizer->totalizer_type == $totalizerType && $totalizer->hasItems()) { if (!$totalizer->applyThisTotalizerToBasket($paymentBasket, $anyAutoRecurringInBasket)) { unset($taxableTotalizers[$k]); } } } }