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_Tax_Model_Sales_Total_Quote_Shipping extends Mage_Sales_Model_Quote_Address_Total_Abstract
29: {
30: 31: 32: 33: 34:
35: protected $_calculator = null;
36:
37: 38: 39: 40: 41:
42: protected $_config = null;
43:
44: 45: 46: 47: 48: 49:
50: protected $_areTaxRequestsSimilar = false;
51:
52: 53: 54: 55: 56:
57: protected $_storeTaxRequest = null;
58:
59: 60: 61:
62: public function __construct()
63: {
64: $this->setCode('shipping');
65: $this->_calculator = Mage::getSingleton('tax/calculation');
66: $this->_config = Mage::getSingleton('tax/config');
67: }
68:
69: 70: 71: 72: 73: 74:
75: public function collect(Mage_Sales_Model_Quote_Address $address)
76: {
77: parent::collect($address);
78: $calc = $this->_calculator;
79: $store = $address->getQuote()->getStore();
80: $storeTaxRequest = $calc->getRateOriginRequest($store);
81: $addressTaxRequest = $calc->getRateRequest(
82: $address,
83: $address->getQuote()->getBillingAddress(),
84: $address->getQuote()->getCustomerTaxClassId(),
85: $store
86: );
87:
88: $shippingTaxClass = $this->_config->getShippingTaxClass($store);
89: $storeTaxRequest->setProductClassId($shippingTaxClass);
90: $addressTaxRequest->setProductClassId($shippingTaxClass);
91:
92: $priceIncludesTax = $this->_config->shippingPriceIncludesTax($store);
93: if ($priceIncludesTax) {
94: $this->_areTaxRequestsSimilar = $calc->compareRequests($addressTaxRequest, $storeTaxRequest);
95: }
96:
97: $shipping = $taxShipping = $address->getShippingAmount();
98: $baseShipping = $baseTaxShipping = $address->getBaseShippingAmount();
99: $rate = $calc->getRate($addressTaxRequest);
100: if ($priceIncludesTax) {
101: if ($this->_areTaxRequestsSimilar) {
102: $tax = $this->_round($calc->calcTaxAmount($shipping, $rate, true, false), $rate, true);
103: $baseTax = $this->_round($calc->calcTaxAmount($baseShipping, $rate, true, false), $rate, true, 'base');
104: $taxShipping = $shipping;
105: $baseTaxShipping= $baseShipping;
106: $shipping = $shipping - $tax;
107: $baseShipping = $baseShipping - $baseTax;
108: $taxable = $taxShipping;
109: $baseTaxable = $baseTaxShipping;
110: $isPriceInclTax = true;
111: } else {
112: $storeRate = $calc->getStoreRate($addressTaxRequest, $store);
113: $storeTax = $calc->calcTaxAmount($shipping, $storeRate, true, false);
114: $baseStoreTax = $calc->calcTaxAmount($baseShipping, $storeRate, true, false);
115: $shipping = $calc->round($shipping - $storeTax);
116: $baseShipping = $calc->round($baseShipping - $baseStoreTax);
117: $tax = $this->_round($calc->calcTaxAmount($shipping, $rate, false, false), $rate, false);
118: $baseTax = $this->_round($calc->calcTaxAmount($baseShipping, $rate, false, false), $rate, false, 'base');
119: $taxShipping = $shipping + $tax;
120: $baseTaxShipping= $baseShipping + $baseTax;
121: $taxable = $shipping;
122: $baseTaxable = $baseShipping;
123: $isPriceInclTax = false;
124: }
125: } else {
126: $tax = $this->_round($calc->calcTaxAmount($shipping, $rate, false, false), $rate, false);
127: $baseTax = $this->_round($calc->calcTaxAmount($baseShipping, $rate, false, false), $rate, false, 'base');
128: $taxShipping = $shipping + $tax;
129: $baseTaxShipping= $baseShipping + $baseTax;
130: $taxable = $shipping;
131: $baseTaxable = $baseShipping;
132: $isPriceInclTax = false;
133: }
134: $address->setTotalAmount('shipping', $shipping);
135: $address->setBaseTotalAmount('shipping', $baseShipping);
136: $address->setShippingInclTax($taxShipping);
137: $address->setBaseShippingInclTax($baseTaxShipping);
138: $address->setShippingTaxable($taxable);
139: $address->setBaseShippingTaxable($baseTaxable);
140: $address->setIsShippingInclTax($isPriceInclTax);
141: if ($this->_config->discountTax($store)) {
142: $address->setShippingAmountForDiscount($taxShipping);
143: $address->setBaseShippingAmountForDiscount($baseTaxShipping);
144: }
145: return $this;
146: }
147:
148: 149: 150: 151: 152: 153: 154: 155: 156:
157: protected function _round($price, $rate, $direction, $type = 'regular')
158: {
159: if (!$price) {
160: return $this->_calculator->round($price);
161: }
162:
163: $deltas = $this->_address->getRoundingDeltas();
164: $key = $type.$direction;
165: $rate = (string) $rate;
166: $delta = isset($deltas[$key][$rate]) ? $deltas[$key][$rate] : 0;
167: return $this->_calculator->round($price+$delta);
168: }
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182: 183: 184: 185: 186: 187: 188:
189: protected function _getStoreTaxRequest($address)
190: {
191: if (is_null($this->_storeTaxRequest)) {
192: $this->_storeTaxRequest = $this->_calculator->getRateOriginRequest($address->getQuote()->getStore());
193: }
194: return $this->_storeTaxRequest;
195: }
196:
197: 198: 199: 200: 201: 202: 203:
204: protected function _getAddressTaxRequest($address)
205: {
206: $addressTaxRequest = $this->_calculator->getRateRequest(
207: $address,
208: $address->getQuote()->getBillingAddress(),
209: $address->getQuote()->getCustomerTaxClassId(),
210: $address->getQuote()->getStore()
211: );
212: return $addressTaxRequest;
213: }
214:
215: 216: 217: 218: 219: 220: 221:
222: protected function _needSubtractShippingTax($address)
223: {
224: $store = $address->getQuote()->getStore();
225: if ($this->_config->shippingPriceIncludesTax($store) || $this->_config->getNeedUseShippingExcludeTax()) {
226: return true;
227: }
228: return false;
229: }
230:
231: 232: 233: 234: 235: 236: 237:
238: protected function _processShippingAmount($address)
239: {
240: }
241: }
242: