Skip to content

Instantly share code, notes, and snippets.

@eighty20results
Last active January 16, 2018 20:24
Show Gist options
  • Save eighty20results/c42d30526662c67129f8ca39a8f21b5b to your computer and use it in GitHub Desktop.
Save eighty20results/c42d30526662c67129f8ca39a8f21b5b to your computer and use it in GitHub Desktop.
Canadian Tax calculation for PMPro (HST, PST, TPS and TVQ rates)
<?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 <thomas@eighy20results.com>
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