File Coverage

blib/lib/Business/Tax/Canada.pm
Criterion Covered Total %
statement 43 44 97.7
branch 11 20 55.0
condition 4 7 57.1
subroutine 14 14 100.0
pod 0 2 0.0
total 72 87 82.7


line stmt bran cond sub pod time code
1             package Business::Tax::Canada;
2              
3 1     1   32745 use strict;
  1         2  
  1         41  
4 1     1   4 use warnings;
  1         2  
  1         25  
5 1     1   4 use Carp;
  1         5  
  1         82  
6              
7 1     1   4 use vars qw/$VERSION @provinces/;
  1         1  
  1         334  
8             $VERSION = '0.04';
9             @provinces = qw/ab bc mb nb nf nt ns nu on pe qc sk yt/;
10              
11             =head1 NAME
12              
13             Business::Tax::Canada - perform Canadian GST/HST/PST calculations
14              
15             =head1 SYNOPSIS
16              
17             use Business::Tax::Canada;
18              
19             my $tax = Business::Tax::Canada->new;
20              
21             my $price = $tax->item(
22             from => 'ab',
23             to => 'ab'
24             price => 120);
25             my $price_to_customer = $price->full; # 126.00
26             my $gst_charged = $price->gst; # 6.00
27             my $pst_charged = $price->pst; # 0
28             my $net_charged = $price->net; # 120
29            
30             =cut
31              
32             sub new {
33 1     1 0 11 my $class = shift;
34 1         3 my %provinces = map { $_ => 1 } @provinces;
  13         28  
35 1         7 bless {
36             default => $_[0],
37             provinces => \%provinces,
38             }, $class;
39             }
40              
41 3     3 0 686 sub item { my $self = shift; $self->_item(@_) }
  3         9  
42              
43             sub _item {
44 3     3   4 my $self = shift;
45 3         10 my %params = @_;
46 3 50       12 my $province_from = $params{from} or croak "No 'from' province specified";
47 3 50       7 my $province_to = $params{to} or croak "No 'to' province specified";
48 3 50       7 my $price = $params{price} or croak "No price specified";
49 3         20 return Business::Tax::Canada::Price->new($self, $price, $province_from, $province_to);
50             }
51              
52             package Business::Tax::Canada::Price;
53              
54 1     1   6 use vars qw/%GST_RATE %PST_RATE/;
  1         2  
  1         483  
55             %GST_RATE = (
56             ab => 5, bc => 12, mb => 5, nb => 13,
57             nf => 13, nt => 5, ns => 15, nu => 5,
58             on => 13, pe => 5, qc => 5, sk => 5,
59             yt => 5,
60             );
61              
62             %PST_RATE = (
63             ab => 0, bc => 0, mb => 7, nb => 0,
64             nf => 0, nt => 0, ns => 0, nu => 0,
65             on => 0, pe => 10, qc => 9.975, sk => 5,
66             yt => 0,
67             );
68              
69             sub new {
70 3     3   5 my ($class, $tax_obj, $price, $province_from, $province_to) = @_;
71 3         7 my $self = {};
72            
73 3   50     12 my $gst_rate = ($GST_RATE{lc $province_to} || 0) / 100;
74 3   100     19 my $pst_rate = ($PST_RATE{lc $province_to} || 0) / 100;
75              
76 3         8 $self->{net} = $price;
77 3         20 $self->{gst} = $self->{net} * $gst_rate;
78 3         7 $self->{pst} = 0;
79 3 100       11 $self->{pst} = $self->{net} * $pst_rate if (lc $province_from eq lc $province_to);
80 3 50 33     21 if (lc $province_from =~ /pe/ || $province_to =~ /pe/) {
81             # PEI charges PST tax on the GST tax amount
82 0 0       0 $self->{pst} = ($self->{net} + $self->{gst}) * $pst_rate if (lc $province_from eq lc $province_to);
83             }
84 3         12 $self->{full} = $self->{net} + $self->{gst} + $self->{pst};
85              
86 3         17 bless $self, $class;
87             }
88              
89 3 50   3   34 sub full { $_[0]->{full} || 0 }
90 3 50   3   20 sub gst { $_[0]->{gst} || 0 }
91 3 100   3   24 sub pst { $_[0]->{pst} || 0 }
92 1     1   5 sub tvq { $_[0]->pst }
93 3 50   3   18 sub net { $_[0]->{net} || 0 }
94              
95             =head1 DESCRIPTION
96              
97             This module will allow you to calculate the Canadian GST and PST
98             charges on items.
99              
100             There are several key processes:
101              
102             =head1 CONSTRUCTING A TAX OBJECT
103              
104             my $tax = Business::Tax::Canada->new;
105              
106             First, construct a tax object. There is no need to specify a list of
107             provinces as all are supported.
108              
109             =head1 PRICING AN ITEM
110              
111             my $price = $tax->item(
112             from => $province_code,
113             to => $province_code,
114             $unit_price => $province_code);
115              
116             You create a Price object by calling the 'item' constructor, with the
117             seller's location (from), the buyer's location (to), and the unit price.
118             From and to locations are used to determine if PST tax should be charged.
119              
120             You must supply all values or you will receive an error.
121              
122             =head1 CALCULATING THE COMPONENT PRICES
123              
124             my $price_to_customer = $price->full;
125             my $gst_charged = $price->gst;
126             my $pst_charged = $price->pst;
127             my $tvq_charged = $price->tvq;
128             my $net_price_to_me = $price->net;
129              
130             Once you have the price, you can query it for either the 'full' price
131             that will be charged (GST + PST if applicable), the 'gst' amount, the 'pst'
132             amount, or the 'net' amount, which will be the same number you entered
133             in the item method. tvq (Quebec's PST) is simply an alias to the pst
134             method.
135              
136             =head1 PROVINCES AND RATES
137              
138             This module uses the following rates and codes:
139              
140             Code Province GST/HST PST
141             ab Alberta 5% N/A
142             bc British Columbia 12% N/A
143             mb Manitoba 5% 7%
144             nb New Brunswick 13% N/A
145             nf Newfoundland & Labrador 13% N/A
146             nt Northwest Territories 5% N/A
147             ns Nova Scotia 15% N/A
148             nu Nunavut 5% N/A
149             on Ontario 13% N/A
150             pe Prince Edward Island 5% 10% *
151             qc Quebec 5% 9.975%
152             sk Saskatchewan 5% 5%
153             yt Yukon Territory 5% N/A
154            
155             * In Prince Edward Island only, the GST is included in the
156             provincial sales tax base. You are also charged PST on GST.
157              
158             =head1 FEEDBACK
159              
160             If you find this module useful, or have any comments, suggestions or
161             improvements, please let me know. Patches are welcome!
162              
163             =head1 AUTHOR
164              
165             Created by Andy Grundman. Updated and maintained by Steve Simms.
166              
167             =head1 THANKS
168              
169             This module was heavily inspired by Tony Bowden's Business::Tax::VAT.
170              
171             =head1 COPYRIGHT
172              
173             This module is free software; you can redistribute it and/or modify it
174             under the same terms as Perl itself.
175              
176             =head1 WARRANTY
177              
178             This program is distributed in the hope that it will be useful,
179             but WITHOUT ANY WARRANTY; without even the implied warranty of
180             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
181              
182             =cut
183              
184             1;