* TaxModifier::set_for_country('NZ', 0.125, 'GST', 'inclusive'); * TaxModifier::set_for_country('UK', 0.175, 'VAT', 'exclusive'); * * * @package shop * @subpackage modifiers */ class StateTaxModifier extends OrderModifier { public static $db = array( 'State' => 'Text', 'Rate' => 'Double', 'Name' => 'Text', 'TaxType' => "Enum('Exclusive,Inclusive')" ); public static $has_one = array(); public static $has_many = array(); public static $many_many = array(); public static $belongs_many_many = array(); public static $defaults = array(); public static $casting = array(); protected static $names_by_state; protected static $rates_by_state; protected static $excl_by_state; /** * Set the tax information for a particular State. * By default, no tax is charged. * * @param $state string The two-letter state code * @param $rate float The tax rate, eg, 0.125 = 12.5% * @param $name string The name to give to the tax, eg, "GST" * @param $inclexcl string "inclusive" if the prices are tax-inclusive. * "exclusive" if tax should be added to the order total. */ static function set_for_state($state, $rate, $name, $inclexcl) { self::$names_by_state[$state] = $name; self::$rates_by_state[$state] = $rate; switch($inclexcl) { case 'inclusive' : self::$excl_by_state[$state] = false; break; case 'exclusive' : self::$excl_by_state[$state] = true; break; default: user_error("TaxModifier::set_for_state - bad argument '$inclexcl' for \$inclexl. Must be 'inclusive' or 'exclusive'.", E_USER_ERROR); } } function State() { return $this->ID ? $this->State : $this->LiveState(); } function Rate() { return $this->ID ? $this->Rate : $this->LiveRate(); } function Name() { return $this->ID ? $this->Name : $this->LiveName(); } function IsExclusive() { return $this->ID ? $this->TaxType == 'Exclusive' : $this->LiveIsExclusive(); } protected function LiveState() { //If State has been entered return current state else return default. } protected function LiveCountry() { return EcommerceRole::find_country(); } protected function LiveRate() { if($this->LiveState() && isset(self::$rates_by_state[$this->LiveState()])) { return self::$rates_by_state[$this->LiveState()]; } } protected function LiveName() { if($this->LiveState() && isset(self::$names_by_state[$this->LiveState()])) { return self::$names_by_state[$this->LiveState()]; } } protected function LiveIsExclusive() { if($this->LiveState() && isset(self::$excl_by_state[$this->LiveState()])) { return self::$excl_by_state[$this->LiveState()]; } } function Amount() { return $this->AddedCharge(); } /** * Get the tax amount that needs to be added to the given order. * If tax is setup to be inclusive, then this will be 0. */ function AddedCharge() { return $this->IsExclusive() ? $this->Charge() : 0; } /** * Get the tax amount to charge on the order. * * Exclusive is easy, however, inclusive is harder. * For example, with GST the tax amount is 1/9 of the * inclusive price not 1/8. */ function Charge() { $rate = ($this->IsExclusive() ? $this->Rate() : (1 - (1 / (1 + $this->Rate())))); return $this->TaxableAmount() * $rate; } /** * The total amount from the {@link Order} that * is taxable. */ function TaxableAmount() { $order = $this->Order(); return $order->SubTotal() + $order->ModifiersSubTotal($this->class); } function ShowInTable() { return $this->Rate(); } /** * The title of what appears on the OrderInformation * template table on the checkout page. * * PRECONDITION: There is a rate set. * * @return string */ function TableTitle() { return number_format($this->Rate() * 100, 1) . '% ' . $this->Name() . ($this->IsExclusive() ? '' : ' (included in the above price)'); } /** * PRECONDITION: The order item is not saved in the database yet. */ public function onBeforeWrite() { parent::onBeforeWrite(); $this->State = $this->LiveState(); $this->Rate = $this->LiveRate(); $this->Name = $this->LiveName(); $this->TaxType = $this->LiveIsExclusive() ? 'Exclusive' : 'Inclusive'; } }