1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27:
28: class Mage_Sales_Model_Quote_Address_Total_Tax extends Mage_Sales_Model_Quote_Address_Total_Abstract
29: {
30: protected $_appliedTaxes = array();
31:
32: public function __construct(){
33: $this->setCode('tax');
34: }
35:
36: public function collect(Mage_Sales_Model_Quote_Address $address)
37: {
38: $store = $address->getQuote()->getStore();
39:
40: $address->setTaxAmount(0);
41: $address->setBaseTaxAmount(0);
42:
43:
44: $address->setAppliedTaxes(array());
45:
46: $items = $address->getAllItems();
47: if (!count($items)) {
48: return $this;
49: }
50: $custTaxClassId = $address->getQuote()->getCustomerTaxClassId();
51:
52: $taxCalculationModel = Mage::getSingleton('tax/calculation');
53:
54: $request = $taxCalculationModel->getRateRequest(
55: $address,
56: $address->getQuote()->getBillingAddress(),
57: $custTaxClassId,
58: $store
59: );
60:
61: foreach ($items as $item) {
62: 63: 64:
65: if ($item->getParentItemId()) {
66: continue;
67: }
68: 69: 70:
71:
72: if ($item->getHasChildren() && $item->isChildrenCalculated()) {
73: foreach ($item->getChildren() as $child) {
74: $discountBefore = $item->getDiscountAmount();
75: $baseDiscountBefore = $item->getBaseDiscountAmount();
76:
77: $rate = $taxCalculationModel->getRate(
78: $request->setProductClassId($child->getProduct()->getTaxClassId())
79: );
80:
81: $child->setTaxPercent($rate);
82: $child->calcTaxAmount();
83:
84: if ($discountBefore != $item->getDiscountAmount()) {
85: $address->setDiscountAmount(
86: $address->getDiscountAmount() + ($item->getDiscountAmount() - $discountBefore)
87: );
88: $address->setBaseDiscountAmount(
89: $address->getBaseDiscountAmount() + ($item->getBaseDiscountAmount() - $baseDiscountBefore)
90: );
91:
92: $address->setGrandTotal(
93: $address->getGrandTotal() - ($item->getDiscountAmount() - $discountBefore)
94: );
95: $address->setBaseGrandTotal(
96: $address->getBaseGrandTotal() - ($item->getBaseDiscountAmount() - $baseDiscountBefore)
97: );
98: }
99:
100: $this->_saveAppliedTaxes(
101: $address,
102: $taxCalculationModel->getAppliedRates($request),
103: $child->getTaxAmount(),
104: $child->getBaseTaxAmount(),
105: $rate
106: );
107: }
108: $itemTaxAmount = $item->getTaxAmount() + $item->getDiscountTaxCompensation();
109: $address->setTaxAmount($address->getTaxAmount() + $itemTaxAmount);
110: $itemBaseTaxAmount = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation();
111: $address->setBaseTaxAmount($address->getBaseTaxAmount() + $itemBaseTaxAmount);
112: }
113: else {
114: $discountBefore = $item->getDiscountAmount();
115: $baseDiscountBefore = $item->getBaseDiscountAmount();
116:
117: $rate = $taxCalculationModel->getRate(
118: $request->setProductClassId($item->getProduct()->getTaxClassId())
119: );
120:
121: $item->setTaxPercent($rate);
122: $item->calcTaxAmount();
123:
124: if ($discountBefore != $item->getDiscountAmount()) {
125: $address->setDiscountAmount(
126: $address->getDiscountAmount() + ($item->getDiscountAmount() - $discountBefore)
127: );
128: $address->setBaseDiscountAmount(
129: $address->getBaseDiscountAmount() + ($item->getBaseDiscountAmount() - $baseDiscountBefore)
130: );
131:
132: $address->setGrandTotal(
133: $address->getGrandTotal() - ($item->getDiscountAmount() - $discountBefore)
134: );
135: $address->setBaseGrandTotal(
136: $address->getBaseGrandTotal() - ($item->getBaseDiscountAmount() - $baseDiscountBefore)
137: );
138: }
139:
140: $itemTaxAmount = $item->getTaxAmount() + $item->getDiscountTaxCompensation();
141: $address->setTaxAmount($address->getTaxAmount() + $itemTaxAmount);
142: $itemBaseTaxAmount = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation();
143: $address->setBaseTaxAmount($address->getBaseTaxAmount() + $itemBaseTaxAmount);
144:
145: $applied = $taxCalculationModel->getAppliedRates($request);
146: $this->_saveAppliedTaxes(
147: $address,
148: $applied,
149: $item->getTaxAmount(),
150: $item->getBaseTaxAmount(),
151: $rate
152: );
153: }
154: }
155:
156:
157: $shippingTaxClass = Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, $store);
158:
159: $shippingTax = 0;
160: $shippingBaseTax = 0;
161:
162: if ($shippingTaxClass) {
163: if ($rate = $taxCalculationModel->getRate($request->setProductClassId($shippingTaxClass))) {
164: if (!Mage::helper('tax')->shippingPriceIncludesTax()) {
165: $shippingTax = $address->getShippingAmount() * $rate/100;
166: $shippingBaseTax= $address->getBaseShippingAmount() * $rate/100;
167: } else {
168: $shippingTax = $address->getShippingTaxAmount();
169: $shippingBaseTax= $address->getBaseShippingTaxAmount();
170: }
171:
172: $shippingTax = $store->roundPrice($shippingTax);
173: $shippingBaseTax= $store->roundPrice($shippingBaseTax);
174:
175: $address->setTaxAmount($address->getTaxAmount() + $shippingTax);
176: $address->setBaseTaxAmount($address->getBaseTaxAmount() + $shippingBaseTax);
177:
178: $this->_saveAppliedTaxes(
179: $address,
180: $taxCalculationModel->getAppliedRates($request),
181: $shippingTax,
182: $shippingBaseTax,
183: $rate
184: );
185: }
186: }
187:
188: if (!Mage::helper('tax')->shippingPriceIncludesTax()) {
189: $address->setShippingTaxAmount($shippingTax);
190: $address->setBaseShippingTaxAmount($shippingBaseTax);
191: }
192:
193: $address->setGrandTotal($address->getGrandTotal() + $address->getTaxAmount());
194: $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getBaseTaxAmount());
195: return $this;
196: }
197:
198: protected function _saveAppliedTaxes(Mage_Sales_Model_Quote_Address $address, $applied, $amount, $baseAmount, $rate)
199: {
200: $previouslyAppliedTaxes = $address->getAppliedTaxes();
201: $process = count($previouslyAppliedTaxes);
202:
203: foreach ($applied as $row) {
204: if (!isset($previouslyAppliedTaxes[$row['id']])) {
205: $row['process'] = $process;
206: $row['amount'] = 0;
207: $row['base_amount'] = 0;
208: $previouslyAppliedTaxes[$row['id']] = $row;
209: }
210:
211: if (!is_null($row['percent'])) {
212: $row['percent'] = $row['percent'] ? $row['percent'] : 1;
213: $rate = $rate ? $rate : 1;
214:
215: $appliedAmount = $amount/$rate*$row['percent'];
216: $baseAppliedAmount = $baseAmount/$rate*$row['percent'];
217: } else {
218: $appliedAmount = 0;
219: $baseAppliedAmount = 0;
220: foreach ($row['rates'] as $rate) {
221: $appliedAmount += $rate['amount'];
222: $baseAppliedAmount += $rate['base_amount'];
223: }
224: }
225:
226:
227: if ($appliedAmount || $previouslyAppliedTaxes[$row['id']]['amount']) {
228: $previouslyAppliedTaxes[$row['id']]['amount'] += $appliedAmount;
229: $previouslyAppliedTaxes[$row['id']]['base_amount'] += $baseAppliedAmount;
230: } else {
231: unset($previouslyAppliedTaxes[$row['id']]);
232: }
233: }
234: $address->setAppliedTaxes($previouslyAppliedTaxes);
235: }
236:
237: public function fetch(Mage_Sales_Model_Quote_Address $address)
238: {
239: $applied = $address->getAppliedTaxes();
240: $store = $address->getQuote()->getStore();
241: $amount = $address->getTaxAmount();
242:
243: if (($amount!=0) || (Mage::helper('tax')->displayZeroTax($store))) {
244: $address->addTotal(array(
245: 'code'=>$this->getCode(),
246: 'title'=>Mage::helper('sales')->__('Tax'),
247: 'full_info'=>$applied ? $applied : array(),
248: 'value'=>$amount
249: ));
250: }
251: return $this;
252: }
253: }
254: