If you would like to make your own tax calculator, create a subclass of this and enable it by using {@link Order::set_modifiers()} in your project _config.php file. Sample configuration in your _config.php: TaxModifier::set_for_country('NZ', 0.125, 'GST', 'inclusive'); TaxModifier::set_for_country('UK', 0.175, 'VAT', 'exclusive');
Inheritance: extends OrderModifier
 function setUp()
 {
     parent::setUp();
     /* Set the modifiers to test */
     Order::set_modifiers(array('SimpleShippingModifier', 'TaxModifier'));
     /* Set the tax configuration on a per-country basis to test */
     TaxModifier::set_for_country('NZ', 0.125, 'GST', 'inclusive');
     TaxModifier::set_for_country('UK', 0.175, 'VAT', 'exclusive');
     /* Let's check that we have the Payment module installed properly */
     $this->assertTrue(class_exists('Payment'), 'Payment module is installed.');
     /* Set the site currency to NZD - this updates all the pricing labels from USD to NZD */
     Payment::set_site_currency('NZD');
     /* Set up the simple shipping calculator to test */
     SimpleShippingModifier::set_default_charge(10);
     SimpleShippingModifier::set_charges_for_countries(array('NZ' => 5, 'UK' => 20));
 }
 function testTaxModifier()
 {
     /* Add 2 of the product-1b to the shopping cart */
     $this->get('product-1b/add');
     $this->get('product-1b/add');
     /* Log our NZ member in so we can assert they see the GST component */
     $this->session()->inst_set('loggedInAs', $this->idFromFixture('Member', 'member'));
     /* 12.5% GST appears to our NZ user logged in */
     $this->get('checkout/');
     $this->assertPartialMatchBySelector('tr.taxmodifier td', array('12.5% GST (included in the above price)'));
     /* Let's check the totals to make sure GST wasn't being added (which is important!) */
     /* NZD is shown as the label, since it was set as the site currency in setUp() */
     $this->assertExactMatchBySelector('#Table_Order_Total', '$1,205.00 NZD');
     /* Let's sneakily change the GST to be exclusive, altering the checkout total */
     TaxModifier::set_for_country('NZ', 0.125, 'GST', 'exclusive');
     /* See what the checkout page has got now */
     $this->get('checkout/');
     /* Check the total, it has changed since the GST is now exclusive */
     $this->assertExactMatchBySelector('#Table_Order_Total', '$1,355.63 NZD');
     /* Member logs out */
     $this->session()->inst_set('loggedInAs', null);
 }
 function old_testTaxModifier()
 {
     $product1b = $this->objFromFixture('Product', 'p1b');
     // Add 2 of the product-1b to the shopping cart
     $this->get($product1b->addLink());
     $this->get($product1b->addLink());
     // Log our NZ member in so we can assert they see the GST component
     $this->session()->inst_set('loggedInAs', $this->idFromFixture('Member', 'member'));
     // 12.5% GST appears to our NZ user logged in
     $response = $this->get('checkout/');
     $this->assertPartialMatchBySelector('tr.taxmodifier td', array('12.5% GST (included in the above price)'));
     // Let's check the totals to make sure GST wasn't being added (which is important!)
     // NZD is shown as the label, since it was set as the site currency in setUp()
     $this->assertExactMatchBySelector('#Table_Order_Total', '$1,205.00');
     // Let's sneakily change the GST to be exclusive, altering the checkout total
     TaxModifier::set_for_country('NZ', 0.125, 'GST', 'exclusive');
     // See what the checkout page has got now
     $this->get('checkout/');
     // Check the total, it has changed since the GST is now exclusive
     $this->assertExactMatchBySelector('#Table_Order_Total', '$1,355.63');
     // Member logs out
     $this->session()->inst_set('loggedInAs', null);
 }
 public function populateDefaults()
 {
     parent::populateDefaults();
     $this->Type = self::config()->exclusive ? 'Chargable' : 'Ignored';
 }
 public function TableTitle()
 {
     $country = $this->Country ? " for " . $this->Country . " " : "";
     return parent::TableTitle() . $country . ($this->Type == "Chargable" ? '' : _t("GlobalTaxModifier.Included", ' (included in the above price)'));
 }
 /**
  * Updates the database structure of the Order table
  */
 function requireDefaultRecords()
 {
     parent::requireDefaultRecords();
     if (!self::$do_migration) {
         return;
     }
     // 1) If some orders with the old structure exist (hasShippingCost, Shipping and AddedTax columns presents in Order table), create the Order Modifiers SimpleShippingModifier and TaxModifier and associate them to the order
     // we must check for individual database types here because each deals with schema in a none standard way
     $db = DB::getConn();
     if ($db instanceof PostgreSQLDatabase) {
         $exist = DB::query("SELECT column_name FROM information_schema.columns WHERE table_name ='Order' AND column_name = 'Shipping'")->numRecords();
     } else {
         // default is MySQL - broken for others, each database conn type supported must be checked for!
         $exist = DB::query("SHOW COLUMNS FROM \"Order\" LIKE 'Shipping'")->numRecords();
     }
     if ($exist > 0) {
         if ($orders = DataObject::get('Order')) {
             foreach ($orders as $order) {
                 $id = $order->ID;
                 $hasShippingCost = DB::query("SELECT \"hasShippingCost\" FROM \"Order\" WHERE \"ID\" = '{$id}'")->value();
                 $shipping = DB::query("SELECT \"Shipping\" FROM \"Order\" WHERE \"ID\" = '{$id}'")->value();
                 $addedTax = DB::query("SELECT \"AddedTax\" FROM \"Order\" WHERE \"ID\" = '{$id}'")->value();
                 $country = $order->findShippingCountry(true);
                 if ($hasShippingCost == '1' && $shipping != null) {
                     $modifier1 = new SimpleShippingModifier();
                     $modifier1->Amount = $shipping < 0 ? abs($shipping) : $shipping;
                     $modifier1->Type = 'Chargable';
                     $modifier1->OrderID = $id;
                     $modifier1->Country = $country;
                     $modifier1->ShippingChargeType = 'Default';
                     $modifier1->write();
                 }
                 if ($addedTax != null) {
                     $modifier2 = new TaxModifier();
                     $modifier2->Amount = $addedTax < 0 ? abs($addedTax) : $addedTax;
                     $modifier2->Type = 'Chargable';
                     $modifier2->OrderID = $id;
                     $modifier2->Country = $country;
                     $modifier2->Name = 'Undefined After Ecommerce Upgrade';
                     $modifier2->TaxType = 'Exclusive';
                     $modifier2->write();
                 }
             }
             DB::alteration_message('The \'SimpleShippingModifier\' and \'TaxModifier\' objects have been successfully created and linked to the appropriate orders present in the \'Order\' table', 'created');
         }
         DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"hasShippingCost\" \"_obsolete_hasShippingCost\" tinyint(1)");
         DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"Shipping\" \"_obsolete_Shipping\" decimal(9,2)");
         DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"AddedTax\" \"_obsolete_AddedTax\" decimal(9,2)");
         DB::alteration_message('The columns \'hasShippingCost\', \'Shipping\' and \'AddedTax\' of the table \'Order\' have been renamed successfully. Also, the columns have been renamed respectly to \'_obsolete_hasShippingCost\', \'_obsolete_Shipping\' and \'_obsolete_AddedTax\'', 'obsolete');
     }
     // 2) Cancel status update
     if ($orders = DataObject::get('Order', "\"Status\" = 'Cancelled'")) {
         foreach ($orders as $order) {
             $order->Status = 'AdminCancelled';
             $order->write();
         }
         DB::alteration_message('The orders which status was \'Cancelled\' have been successfully changed to the status \'AdminCancelled\'', 'changed');
     }
     //set starting order number ID
     $number = intval(Order::get_order_id_start_number());
     $currentMax = 0;
     //set order ID
     if ($number) {
         $count = DB::query("SELECT COUNT( \"ID\" ) FROM \"Order\" ")->value();
         if ($count > 0) {
             $currentMax = DB::Query("SELECT MAX( \"ID\" ) FROM \"Order\"")->value();
         }
         if ($number > $currentMax) {
             DB::query("ALTER TABLE \"Order\"  AUTO_INCREMENT = {$number} ROW_FORMAT = DYNAMIC ");
             DB::alteration_message("Change OrderID start number to " . $number, "edited");
         }
     }
     //fix bad status
     $list = self::get_order_status_options();
     $firstOption = current($list);
     $badOrders = DataObject::get("Order", "\"Status\" = ''");
     if ($badOrders) {
         foreach ($badOrders as $order) {
             $order->Status = $firstOption;
             $order->write();
             DB::alteration_message("No order status for order number #" . $order->ID . " reverting to: {$firstOption}.", "error");
         }
     }
     //import details from member
     $memberfields = array('FirstName', 'Surname', 'Email');
     foreach ($memberfields as $field) {
         $memberfields[$field] = "\"{$field}\" = '' OR \"{$field}\" IS NULL";
     }
     if (count($memberfields) > 0 && ($orders = DataObject::get('Order', implode(" OR ", $memberfields) . " AND \"MemberID\" > 0"))) {
         foreach ($orders as $order) {
             foreach ($memberfields as $field => $filter) {
                 $order->{$field} = $order->Member()->{$field};
             }
             $order->write();
         }
     }
 }
 /**
  * Convert shipping and tax columns into modifiers
  *
  * Applies to pre 0.6 sites
  */
 public function migrateShippingValues($order)
 {
     //TODO: see if this actually works..it probably needs to be writeen to a SQL query
     if ($order->hasShippingCost && abs($order->Shipping)) {
         $modifier1 = ShippingModifier::create();
         $modifier1->Amount = $order->Shipping < 0 ? abs($order->Shipping) : $order->Shipping;
         $modifier1->Type = 'Chargable';
         $modifier1->OrderID = $order->ID;
         $modifier1->ShippingChargeType = 'Default';
         $modifier1->write();
         $order->hasShippingCost = null;
         $order->Shipping = null;
     }
     if ($order->AddedTax) {
         $modifier2 = TaxModifier::create();
         $modifier2->Amount = $order->AddedTax < 0 ? abs($order->AddedTax) : $order->AddedTax;
         $modifier2->Type = 'Chargable';
         $modifier2->OrderID = $order->ID;
         //$modifier2->Name = 'Undefined After Ecommerce Upgrade';
         $modifier2->TaxType = 'Exclusive';
         $modifier2->write();
         $order->AddedTax = null;
     }
 }
OrderManipulation::set_allow_paying();
//shows a payment form
// * * * PRODUCTS
ProductsAndGroupsModelAdmin::set_managed_models(array("Product", "ProductGroup", "ProductVariation"));
Product_Image::set_thumbnail_size(140, 100);
Product_Image::set_content_image_width(200);
Product_Image::set_large_image_width(200);
ProductGroup::set_include_child_groups(true);
ProductGroup::set_must_have_price(true);
ProductGroup::set_sort_options(array('Title' => 'Alphabetical', 'Price' => 'Lowest Price'));
// * * * CHECKOUT
ExpiryDateField::set_short_months(true);
//uses short months (e.g. Jan instead of january) for credit card expiry date.
OrderFormWithoutShippingAddress::set_fixed_country_code("NZ");
//country is fixed
OrderFormWithoutShippingAddress::set_postal_code_url("http://maps.google.com");
//link that can be used to check postal code
OrderFormWithoutShippingAddress::set_postal_code_label("click here to check your postal code");
//label for link that can be used to check postal code
OrderFormWithoutShippingAddress::set_login_invite_alternative_text('<a href="http://www.mysite.com/Security/login/?BackURL=">If you are a member then please log in.</a>');
//label for link that can be used to check postal code
// * * * MEMBER
EcommerceRole::set_group_name("Customers");
// * * * MODIFIERS
FlatTaxModifier::set_tax("0.15", "GST", $exclusive = false);
SimpleShippingModifier::set_default_charge(10);
SimpleShippingModifier::set_charges_for_countries(array('US' => 10, 'NZ' => 5));
TaxModifier::set_for_country($country = "NZ", $rate = 0.15, $name = "GST", $inclexcl = "inclusive");
// * * * HELP
Product::set_global_allow_purchase(false);
//stops the sale of all products
 /**
  * Updates the database structure of the Order table
  */
 function requireDefaultRecords()
 {
     parent::requireDefaultRecords();
     // 1) If some orders with the old structure exist (hasShippingCost, Shipping and AddedTax columns presents in Order table), create the Order Modifiers SimpleShippingModifier and TaxModifier and associate them to the order
     $exist = DB::query("SHOW COLUMNS FROM `Order` LIKE 'Shipping'")->numRecords();
     if ($exist > 0) {
         if ($orders = DataObject::get('Order')) {
             foreach ($orders as $order) {
                 $id = $order->ID;
                 $hasShippingCost = DB::query("SELECT `hasShippingCost` FROM `Order` WHERE `ID` = '{$id}'")->value();
                 $shipping = DB::query("SELECT `Shipping` FROM `Order` WHERE `ID` = '{$id}'")->value();
                 $addedTax = DB::query("SELECT `AddedTax` FROM `Order` WHERE `ID` = '{$id}'")->value();
                 $country = $order->findShippingCountry(true);
                 if ($hasShippingCost == '1' && $shipping != null) {
                     $modifier1 = new SimpleShippingModifier();
                     $modifier1->Amount = $shipping < 0 ? abs($shipping) : $shipping;
                     $modifier1->Type = 'Chargable';
                     $modifier1->OrderID = $id;
                     $modifier1->Country = $country;
                     $modifier1->ShippingChargeType = 'Default';
                     $modifier1->write();
                 }
                 if ($addedTax != null) {
                     $modifier2 = new TaxModifier();
                     $modifier2->Amount = $addedTax < 0 ? abs($addedTax) : $addedTax;
                     $modifier2->Type = 'Chargable';
                     $modifier2->OrderID = $id;
                     $modifier2->Country = $country;
                     $modifier2->Name = 'Undefined After Ecommerce Upgrade';
                     $modifier2->TaxType = 'Exclusive';
                     $modifier2->write();
                 }
             }
             Database::alteration_message('The \'SimpleShippingModifier\' and \'TaxModifier\' objects have been successfully created and linked to the appropriate orders present in the \'Order\' table', 'created');
         }
         DB::query("ALTER TABLE `Order` CHANGE COLUMN `hasShippingCost` `_obsolete_hasShippingCost` tinyint(1)");
         DB::query("ALTER TABLE `Order` CHANGE COLUMN `Shipping` `_obsolete_Shipping` decimal(9,2)");
         DB::query("ALTER TABLE `Order` CHANGE COLUMN `AddedTax` `_obsolete_AddedTax` decimal(9,2)");
         Database::alteration_message('The columns \'hasShippingCost\', \'Shipping\' and \'AddedTax\' of the table \'Order\' have been renamed successfully. Also, the columns have been renamed respectly to \'_obsolete_hasShippingCost\', \'_obsolete_Shipping\' and \'_obsolete_AddedTax\'', 'obsolete');
     }
     // 2) Cancel status update
     if ($orders = DataObject::get('Order', "`Status` = 'Cancelled'")) {
         foreach ($orders as $order) {
             $order->Status = 'AdminCancelled';
             $order->write();
         }
         Database::alteration_message('The orders which status was \'Cancelled\' have been successfully changed to the status \'AdminCancelled\'', 'changed');
     }
 }