Last active
January 16, 2018 20:24
-
-
Save eighty20results/c42d30526662c67129f8ca39a8f21b5b to your computer and use it in GitHub Desktop.
Canadian Tax calculation for PMPro (HST, PST, TPS and TVQ rates)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: PMPro: Canadian Tax calculation | |
Plugin URI: https://eighty20resultsc.com/wordpress-plugins/ | |
Description: PMPro Tax Calculation for (some of) the Canadian province(s) | |
Version: 1.4 | |
Author: Thomas Sjolshagen @ Paid Memberships Pro <[email protected]> | |
Author URI: https://eighty20results.com/thomas-sjolshagen/ | |
License: GPL2 | |
* Copyright (c) 2017-2018 - Eighty / 20 Results by Wicked Strong Chicks. | |
* ALL RIGHTS RESERVED | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
namespace E20R\Customizations; | |
/** | |
* Attempt at a tax solution for Canada | |
* | |
* This solution assume the tax rate specified in the private class variables. | |
* | |
* NOTE: Ask your accountant how much tax you must charge! | |
* | |
* More info: http://sbinfocanada.about.com/od/pst/a/BC-PST.htm | |
* | |
* Edit as needed, then save this file in your plugins folder and activate it through the plugins page in the WP dashboard. | |
* | |
* @credit: https://github.com/ideadude | |
*/ | |
class Canadian_Taxes { | |
/** | |
* This class (instance) | |
* | |
* @var null|Canadian_Taxes | |
*/ | |
private static $instance = null; | |
/** | |
* The TPS tax rate. Set to null if not applicable | |
* | |
* TODO: Update for your province! | |
* | |
* @var float|null | |
*/ | |
private $tps_rate = null; | |
/** | |
* The TVQ tax rate. Set to null if not applicable | |
* | |
* TODO: Update for your province! | |
* | |
* @var float|null | |
*/ | |
private $tvq_rate = null; | |
/** | |
* The PST rate to use (set other rates to 'null' if not needed.) | |
* | |
* TODO: Update when needed for your province! | |
* | |
* @var float|null | |
*/ | |
private $pst_rate = null; | |
/** | |
* The HST rate to use (set other rates to 'null' if not needed.) | |
* | |
* TODO: Update when needed | |
* | |
* @var float|null | |
*/ | |
private $hst_rate = 13.0; | |
/** | |
* Province name | |
* | |
* TODO: Update for your province! | |
* | |
* @var string|null - Null means we're assuming the calculation is for all of Canada | |
*/ | |
private $province = null; | |
/** | |
* Province Abbreviation | |
* | |
* TODO: Update for your province! | |
* | |
* @var string|null - Null means we're assuming the calculation is for all of Canada | |
*/ | |
private $province_code = null; | |
/** | |
* Canadian_Taxes constructor. | |
*/ | |
public function __construct() { | |
} | |
/** | |
* Load WordPress action/filters for plugin/functionality | |
*/ | |
public function loadHooks() { | |
add_filter( 'pmpro_level_cost_text', array( $this, 'levelCostText' ), 10, 2 ); | |
add_action( 'pmpro_checkout_boxes', array( $this, 'addToCheckoutPage' ), 10 ); | |
add_action( 'pmpro_checkout_preheader', array( $this, 'saveToSession' ), 10 ); | |
add_action( 'pmpro_after_checkout', array( $this, 'removeFromSession' ), 10 ); | |
// Add custom tax calculation if user indicated they're from "our" province in Canada | |
if ( !empty( $_REQUEST['taxregion'] ) || !empty( $_SESSION['taxregion'] ) ) { | |
add_filter( "pmpro_tax", array( $this, 'calculateCustomTax' ), 10, 3 ); | |
} else { | |
// They didn't indicate, but we're checking anyway (only if billing info is enabled for gateway!) | |
if ( !empty( $_REQUEST['bstate'] ) && !empty ( $_REQUEST['bcountry'] ) ) { | |
$province = trim( strtolower( $_REQUEST['bstate'] ) ); | |
$country = trim( strtolower( $_REQUEST['bcountry'] ) ); | |
if ( ( in_array( $province, array( strtolower( $this->province_code ), strtolower( $this->province ) ) ) && 'ca' === $country ) || 'ca' == $country ) { | |
add_filter( "pmpro_tax", array( $this, 'calculateCustomTax' ), 10, 3 ); | |
} | |
} | |
} | |
} | |
/** | |
* Clear the session object on our behalf | |
*/ | |
public function removeFromSession() { | |
if ( isset( $_SESSION['taxregion'] ) ) { | |
unset( $_SESSION['taxregion'] ); | |
} | |
} | |
/** | |
* Handle off-site gateways | |
*/ | |
public function saveToSession() { | |
if ( isset( $_REQUEST['tax_region'] ) ) { | |
$_SESSION['taxregion'] = $_REQUEST['taxregion']; | |
} | |
} | |
/** | |
* Generate HTML to include on checkout page for Residents of the specified province in Canada | |
*/ | |
public function addToCheckoutPage() { | |
$region_selected = ( ( ! empty( $_REQUEST['taxregion'] ) || ! empty( $_SESSION['taxregion'] ) || strtolower( $_REQUEST['bcountry'] ) == 'ca' ) ? 'checked="checked" ' : null ); ?> | |
<table id="pmpro_pricing_fields" class="pmpro_checkout" width="100%" cellpadding="0" cellspacing="0" border="0"> | |
<thead> | |
<tr> | |
<th> | |
<?php printf( __( 'Resident of %s', 'paid-memberships-pro' ), | |
( !empty( $this->province ) ? $this->province : __('Canada', 'paid-memberships-pro') ) | |
); | |
?> | |
</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr> | |
<td> | |
<div> | |
<input id="taxregion" name="taxregion" type="checkbox" | |
value="1" <?php echo $region_selected; ?>/><?php if ( !empty( $this->province ) ) { printf( __( 'Check this box if your billing address is in %s, Canada', 'paid-memberships-pro' ), $this->province ); } else { _e( 'Check this box if your billing address is in Canada', 'paid-memberships-pro' ); } ?> | |
</div> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<?php | |
} | |
/** | |
* Conditionally add text to indicate that TPS or TVQ tax will be added | |
* | |
* @param $text | |
* @param $level | |
* | |
* @return string | |
*/ | |
public function levelCostText( $text, $level ) { | |
if ( ! empty( $this->tvq_rate ) || ! empty( $this->tps_rate ) || !empty( $this->pst_rate ) || !empty( $this->hst_rate ) ) { | |
$text .= sprintf( | |
__( ' Members in %1$s will be charged a %2$s%3$s%4$s%5$s%6$s', 'paid-memberships-pro' ), | |
( !empty( $this->province ) ? $this->province : __('Canada', 'paid-memberships-pro' ) ), | |
( ! empty( $this->hst_rate ) ? sprintf( __( '%1$.3f%% HST tax rate', 'paid-memberships-pro' ), $this->hst_rate ) : null ), | |
( ! empty( $this->pst_rate ) ? sprintf( __( '%1$.3f%% PST tax rate', 'paid-memberships-pro' ), $this->pst_rate ) : null ), | |
( ! empty( $this->tps_rate ) ? sprintf( __( '%1$.3f%% TPS tax rate', 'paid-memberships-pro' ), $this->tps_rate ) : null ), | |
( ! empty( $this->tps_rate ) ? __( ' and a ', 'paid-memberships-pro' ) : null ), | |
( ! empty( $this->tvq_rate ) ? sprintf( __( '%1$.3f%% TVQ tax rate', 'paid-memberships-pro' ), $this->tvq_rate ) : null ) | |
); | |
} | |
return $text; | |
} | |
/** | |
* Calculate the tax(es) to add to the base price during checkout | |
* | |
* @param $tax_amount | |
* @param $settings | |
* @param $order | |
* | |
* @return float | |
* | |
* @filter pmpro_tax - Tax calculation for Paid Memberships Pro | |
*/ | |
public function calculateCustomTax( $tax_amount, $settings, $order ) { | |
$base_cost = (float) $settings['price']; | |
// Instantiate the variable w/a value we can do something about/with in a typed language | |
if ( empty( $tax_amount ) ) { | |
$tax_amount = 0; | |
} | |
// Apply TPS tax | |
if ( !empty( $this->tps_rate ) ) { | |
$tax_amount += (float) $this->calculateTax( $this->tps_rate, $base_cost ); | |
} | |
// Apply TVQ tax | |
if ( !empty( $this->tvq_rate ) ) { | |
$tax_amount += (float) $this->calculateTax( $this->tvq_rate, $base_cost ); | |
} | |
// Apply PST tax | |
if ( !empty( $this->pst_rate ) ) { | |
$tax_amount += (float) $this->calculateTax( $this->pst_rate, $base_cost ); | |
} | |
// Apply HST tax | |
if ( !empty( $this->hst_rate) ) { | |
$tax_amount += (float) $this->calculateTax( $this->hst_rate, $base_cost ); | |
} | |
return $tax_amount; | |
} | |
/** | |
* Standard tax calculation | |
* | |
* @param float $rate | |
* @param float $base_amount | |
* | |
* @return float The tax amount (to be added to the total) | |
* | |
* @access private | |
*/ | |
private function calculateTax( $rate, $base_amount ) { | |
// Basic percentage calculation | |
return round( ( (float) $base_amount * ( (float) $rate ) ) / 100, 2 ); | |
} | |
/** | |
* Return or instantiate the Canadian_Taxes object | |
* | |
* @return Canadian_Taxes|null | |
*/ | |
public static function getInstance() { | |
if ( is_null( self::$instance ) ) { | |
self::$instance = new self; | |
} | |
return self::$instance; | |
} | |
} | |
add_action( 'plugins_loaded', array( Canadian_Taxes::getInstance(), 'loadHooks'), 10 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment