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; |