corgibytes-tax_cloud 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +17 -0
- data/.circleci/config.yml +81 -0
- data/.circleci/setup-rubygems.sh +9 -0
- data/.gitignore +67 -0
- data/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +66 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.rdoc +48 -0
- data/CONTRIBUTORS.txt +23 -0
- data/Dockerfile +9 -0
- data/Gemfile +22 -0
- data/LICENSE +23 -0
- data/README.md +190 -0
- data/Rakefile +29 -0
- data/docker-compose.yml +10 -0
- data/examples/.env.example +2 -0
- data/examples/lookup_example.rb +139 -0
- data/lib/config/locales/en.yml +34 -0
- data/lib/hash.rb +8 -0
- data/lib/savon_soap_xml.rb +32 -0
- data/lib/tasks/tax_cloud.rake +18 -0
- data/lib/tasks/tax_code_groups.rake +37 -0
- data/lib/tasks/tax_codes.rake +43 -0
- data/lib/tax_cloud.rb +70 -0
- data/lib/tax_cloud/address.rb +50 -0
- data/lib/tax_cloud/cart_item.rb +26 -0
- data/lib/tax_cloud/client.rb +60 -0
- data/lib/tax_cloud/configuration.rb +28 -0
- data/lib/tax_cloud/errors.rb +6 -0
- data/lib/tax_cloud/errors/api_error.rb +17 -0
- data/lib/tax_cloud/errors/missing_config_error.rb +13 -0
- data/lib/tax_cloud/errors/missing_config_option_error.rb +19 -0
- data/lib/tax_cloud/errors/soap_error.rb +30 -0
- data/lib/tax_cloud/errors/tax_cloud_error.rb +83 -0
- data/lib/tax_cloud/errors/unexpected_soap_response_error.rb +19 -0
- data/lib/tax_cloud/record.rb +14 -0
- data/lib/tax_cloud/responses.rb +13 -0
- data/lib/tax_cloud/responses/authorized.rb +10 -0
- data/lib/tax_cloud/responses/authorized_with_capture.rb +10 -0
- data/lib/tax_cloud/responses/base.rb +82 -0
- data/lib/tax_cloud/responses/captured.rb +10 -0
- data/lib/tax_cloud/responses/cart_item.rb +23 -0
- data/lib/tax_cloud/responses/generic.rb +31 -0
- data/lib/tax_cloud/responses/lookup.rb +38 -0
- data/lib/tax_cloud/responses/ping.rb +10 -0
- data/lib/tax_cloud/responses/returned.rb +10 -0
- data/lib/tax_cloud/responses/tax_code_groups.rb +30 -0
- data/lib/tax_cloud/responses/tax_codes.rb +30 -0
- data/lib/tax_cloud/responses/tax_codes_by_group.rb +30 -0
- data/lib/tax_cloud/responses/verify_address.rb +26 -0
- data/lib/tax_cloud/tax_code.rb +11 -0
- data/lib/tax_cloud/tax_code_constants.rb +560 -0
- data/lib/tax_cloud/tax_code_group.rb +28 -0
- data/lib/tax_cloud/tax_code_group_constants.rb +31 -0
- data/lib/tax_cloud/tax_code_groups.rb +25 -0
- data/lib/tax_cloud/tax_codes.rb +25 -0
- data/lib/tax_cloud/transaction.rb +118 -0
- data/lib/tax_cloud/version.rb +4 -0
- data/tax_cloud.gemspec +23 -0
- data/test/cassettes/authorized.yml +826 -0
- data/test/cassettes/authorized_with_capture.yml +826 -0
- data/test/cassettes/authorized_with_localized_time.yml +826 -0
- data/test/cassettes/captured.yml +872 -0
- data/test/cassettes/get_tic_groups.yml +783 -0
- data/test/cassettes/get_tics.yml +1079 -0
- data/test/cassettes/get_tics_by_group.yml +776 -0
- data/test/cassettes/invalid_soap_call.yml +778 -0
- data/test/cassettes/lookup.yml +780 -0
- data/test/cassettes/lookup_ny.yml +780 -0
- data/test/cassettes/ping.yml +776 -0
- data/test/cassettes/ping_with_invalid_credentials.yml +774 -0
- data/test/cassettes/ping_with_invalid_response.yml +774 -0
- data/test/cassettes/returned.yml +872 -0
- data/test/cassettes/verify_bad_address.yml +772 -0
- data/test/cassettes/verify_good_address.yml +772 -0
- data/test/helper.rb +17 -0
- data/test/test_address.rb +54 -0
- data/test/test_cart_item.rb +15 -0
- data/test/test_client.rb +27 -0
- data/test/test_configuration_optional_keys.rb +42 -0
- data/test/test_configuration_required_keys.rb +31 -0
- data/test/test_lookup_response.rb +20 -0
- data/test/test_setup.rb +17 -0
- data/test/test_soap.rb +11 -0
- data/test/test_tax_code_groups.rb +29 -0
- data/test/test_tax_codes.rb +17 -0
- data/test/test_transaction.rb +78 -0
- data/test/test_transaction_ny.rb +25 -0
- data/test/vcr_setup.rb +9 -0
- metadata +174 -0
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |test|
|
7
|
+
test.libs << 'lib' << 'test'
|
8
|
+
test.pattern = 'test/test_*.rb'
|
9
|
+
# REM
|
10
|
+
#test.verbose = false
|
11
|
+
end
|
12
|
+
|
13
|
+
RDoc::Task.new do |rd|
|
14
|
+
README = 'README.rdoc'.freeze
|
15
|
+
rd.main = README
|
16
|
+
rd.rdoc_files.include(README, 'CHANGELOG.rdoc', 'LICENSE.rdoc', 'lib/**/*.rb')
|
17
|
+
rd.rdoc_dir = 'doc'
|
18
|
+
rd.title = 'tax_cloud'
|
19
|
+
end
|
20
|
+
|
21
|
+
load 'lib/tasks/tax_cloud.rake'
|
22
|
+
load 'lib/tasks/tax_codes.rake'
|
23
|
+
load 'lib/tasks/tax_code_groups.rake'
|
24
|
+
load 'vcr/tasks/vcr.rake'
|
25
|
+
|
26
|
+
require 'rubocop/rake_task'
|
27
|
+
RuboCop::RakeTask.new(:rubocop)
|
28
|
+
|
29
|
+
task default: [:rubocop, :test]
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
##
|
2
|
+
# An example of doing a tax lookup that hits TaxCloud. To run:
|
3
|
+
#
|
4
|
+
# bundle exec ruby lookup_example.rb
|
5
|
+
#
|
6
|
+
# Make sure you copy the .env.example to .env an update the
|
7
|
+
# values in it before running. I also recommend no running
|
8
|
+
# this script against a live TaxCloud site. Run it only against
|
9
|
+
# test sites.
|
10
|
+
##
|
11
|
+
|
12
|
+
require 'dotenv/load'
|
13
|
+
require 'securerandom'
|
14
|
+
|
15
|
+
require_relative '../lib/tax_cloud'
|
16
|
+
|
17
|
+
##
|
18
|
+
# Load the TaxCloud settings from the environment file.\
|
19
|
+
#
|
20
|
+
def load_config
|
21
|
+
TaxCloud.configure do |config|
|
22
|
+
config.api_login_id = ENV['TAX_CLOUD_LOGIN_ID']
|
23
|
+
config.api_key = ENV['TAX_CLOUD_API_KEY']
|
24
|
+
config.open_timeout = 10
|
25
|
+
config.read_timeout = 10
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Display the current TaxCloud settings.
|
31
|
+
#
|
32
|
+
def display_config
|
33
|
+
TaxCloud.configure do |config|
|
34
|
+
puts "API Login ID: #{config.api_login_id}"
|
35
|
+
puts "API Key: #{config.api_key}"
|
36
|
+
puts "Open timeout: #{config.open_timeout}"
|
37
|
+
puts "Read timeout: #{config.read_timeout}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Create a test transaction with one cart item.
|
43
|
+
#
|
44
|
+
# Will create a new customer and cart each time using GUIDs for
|
45
|
+
# the customer and cart IDs. This prevents collisions with
|
46
|
+
# existing customer/carts when running the script multiple times.
|
47
|
+
#
|
48
|
+
def create_test_transaction
|
49
|
+
origin = TaxCloud::Address.new(
|
50
|
+
:address1 => '162 East Avenue',
|
51
|
+
:address2 => 'Third Floor',
|
52
|
+
:city => 'Norwalk',
|
53
|
+
:state => 'CT',
|
54
|
+
:zip5 => '06851')
|
55
|
+
|
56
|
+
destination = TaxCloud::Address.new(
|
57
|
+
:address1 => '3121 West Government Way',
|
58
|
+
:address2 => 'Suite 2B',
|
59
|
+
:city => 'Seattle',
|
60
|
+
:state => 'WA',
|
61
|
+
:zip5 => '98199')
|
62
|
+
|
63
|
+
transaction = TaxCloud::Transaction.new(
|
64
|
+
:customer_id => SecureRandom.uuid,
|
65
|
+
:cart_id => SecureRandom.uuid,
|
66
|
+
:origin => origin,
|
67
|
+
:destination => destination)
|
68
|
+
|
69
|
+
transaction.cart_items << TaxCloud::CartItem.new(
|
70
|
+
:index => 0,
|
71
|
+
:item_id => 'SKU-100',
|
72
|
+
:tic => TaxCloud::TaxCodes::GENERAL,
|
73
|
+
:price => 10.00,
|
74
|
+
:quantity => 1)
|
75
|
+
|
76
|
+
transaction
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Displays information about the transaction:
|
81
|
+
#
|
82
|
+
# - Customer ID
|
83
|
+
# - Cart ID
|
84
|
+
# - Origin Address
|
85
|
+
# - Destination Address
|
86
|
+
# - Cart Items
|
87
|
+
#
|
88
|
+
# @param [TaxCloud::Transaction] transaction
|
89
|
+
#
|
90
|
+
def display_transaction(transaction)
|
91
|
+
puts "Customer ID: #{transaction.customer_id}"
|
92
|
+
puts "Cart ID: #{transaction.cart_id}"
|
93
|
+
puts "Origin: #{transaction.origin.to_hash}"
|
94
|
+
puts "Destination: #{transaction.destination.to_hash}"
|
95
|
+
puts "Cart Items: #{transaction.cart_items.map(&:to_hash)}"
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Display the total tax and tax for each cart item.
|
100
|
+
#
|
101
|
+
# @param [TaxCloud::Responses::Lookup] lookup
|
102
|
+
def display_tax(lookup)
|
103
|
+
puts "Total tax amount: #{lookup.tax_amount}"
|
104
|
+
|
105
|
+
lookup.cart_items.each do |cart_item|
|
106
|
+
puts "Tax cart index #{cart_item.cart_item_index}: #{cart_item.tax_amount}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
##
|
112
|
+
# Run an example lookup
|
113
|
+
##
|
114
|
+
puts 'Loading config information from .env file...'
|
115
|
+
load_config
|
116
|
+
puts 'Config loaded'
|
117
|
+
puts
|
118
|
+
|
119
|
+
puts 'The TaxCloud config is:'
|
120
|
+
display_config
|
121
|
+
puts
|
122
|
+
|
123
|
+
puts 'Checking config...'
|
124
|
+
TaxCloud.configuration.check!
|
125
|
+
puts 'Check passed.'
|
126
|
+
puts
|
127
|
+
|
128
|
+
puts 'Pinging TaxCloud server...'
|
129
|
+
puts TaxCloud.client.ping
|
130
|
+
|
131
|
+
puts 'Cart values:'
|
132
|
+
transaction = create_test_transaction
|
133
|
+
display_transaction(transaction)
|
134
|
+
puts
|
135
|
+
|
136
|
+
puts 'Tax lookup:'
|
137
|
+
lookup = transaction.lookup
|
138
|
+
display_tax(lookup)
|
139
|
+
puts
|
@@ -0,0 +1,34 @@
|
|
1
|
+
en:
|
2
|
+
taxcloud:
|
3
|
+
errors:
|
4
|
+
messages:
|
5
|
+
missing_config:
|
6
|
+
message: "Missing configuration."
|
7
|
+
summary: "TaxCloud requires an API login ID and key."
|
8
|
+
resolution: "Create a TaxCloud merchant account at http://www.taxcloud.net.
|
9
|
+
Add a website to your TaxCloud account. This will generate an API ID and
|
10
|
+
API Key that you will need to use the service. Configure the TaxCloud
|
11
|
+
gem. For example, add the following to `config/initializers/tax_cloud.rb`.\n
|
12
|
+
\_\_TaxCloud.configure do |config|\n
|
13
|
+
\_\_\_config.api_login_id = 'your_tax_cloud_api_login_id'\n
|
14
|
+
\_\_\_config.api_key = 'your_tax_cloud_api_key'\n
|
15
|
+
\_\_\_config.usps_username = 'your_usps_username' # optional\n
|
16
|
+
\_\_end\n"
|
17
|
+
missing_config_option:
|
18
|
+
message: "Missing configuration option: %{name}."
|
19
|
+
summary: "A configuration option was not provided when configuring TaxCloud."
|
20
|
+
resolution: "Review your `TaxCloud.configure` code. Are you using an environment
|
21
|
+
variable that has not been set?"
|
22
|
+
soap_error:
|
23
|
+
message: "%{message}"
|
24
|
+
summary: "The server returned a %{code} error."
|
25
|
+
resolution: "Review the parameters passed to the request."
|
26
|
+
unexpected_soap_response:
|
27
|
+
message: "Expected a value for `%{key}` in `%{chain}` in the TaxCloud response."
|
28
|
+
summary: "TaxCloud returned an unexpected response: `%{raw}`."
|
29
|
+
resolution: "This is possibly a bug in the tax_cloud gem.\n
|
30
|
+
Please report it in https://github.com/drewtempelmeyer/tax_cloud/issues."
|
31
|
+
api_error:
|
32
|
+
message: "%{message}"
|
33
|
+
summary: "The TaxCloud server returned an error in the response: `%{raw}`"
|
34
|
+
resolution: "Check the request parameters."
|
data/lib/hash.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Hack Savon to work properly with arrays
|
2
|
+
module Savon #:nodoc:
|
3
|
+
module SOAP #:nodoc:
|
4
|
+
class XML #:nodoc:
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
old_add_namespaces_to_body = self.instance_method(:add_namespaces_to_body)
|
9
|
+
|
10
|
+
def add_namespaces_to_body(hash, path = [input[1].to_s])
|
11
|
+
return unless hash
|
12
|
+
return hash if hash.kind_of? Array
|
13
|
+
return hash.to_s unless hash.kind_of? Hash
|
14
|
+
|
15
|
+
hash.inject({}) do |newhash, (key, value)|
|
16
|
+
camelcased_key = Gyoku::XMLKey.create(key)
|
17
|
+
newpath = path + [camelcased_key]
|
18
|
+
|
19
|
+
if used_namespaces[newpath]
|
20
|
+
newhash.merge(
|
21
|
+
"#{used_namespaces[newpath]}:#{camelcased_key}" =>
|
22
|
+
add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath)
|
23
|
+
)
|
24
|
+
else
|
25
|
+
newhash.merge(key => value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'tax_cloud'
|
2
|
+
|
3
|
+
namespace :tax_cloud do
|
4
|
+
desc 'Configure TaxCloud.'
|
5
|
+
task :configure do
|
6
|
+
unless TaxCloud.configured?
|
7
|
+
TaxCloud.configure do |config|
|
8
|
+
config.api_login_id = ENV['TAXCLOUD_API_LOGIN_ID']
|
9
|
+
config.api_key = ENV['TAXCLOUD_API_KEY']
|
10
|
+
config.usps_username = ENV['TAXCLOUD_USPS_USERNAME']
|
11
|
+
end
|
12
|
+
Savon.configure do |config|
|
13
|
+
config.log = false
|
14
|
+
end
|
15
|
+
HTTPI.log = false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
namespace :tax_cloud do
|
2
|
+
desc 'Generate tax code groups.'
|
3
|
+
task tax_code_groups: :configure do
|
4
|
+
filename = 'lib/tax_cloud/tax_code_group_constants.rb'
|
5
|
+
|
6
|
+
begin
|
7
|
+
groups = TaxCloud::TaxCode::Groups.all.values
|
8
|
+
|
9
|
+
File.open filename, 'wt' do |f|
|
10
|
+
f.write "module TaxCloud\n"
|
11
|
+
f.write " class TaxCode\n"
|
12
|
+
f.write " # Tax Code Groups.\n"
|
13
|
+
f.write " class Groups\n"
|
14
|
+
|
15
|
+
groups.each do |group|
|
16
|
+
puts " #{group.description}"
|
17
|
+
code = group.description.upcase
|
18
|
+
code.gsub! /[^A-Z0-9]/, '_'
|
19
|
+
code.gsub! /_$/, ''
|
20
|
+
code.gsub! /\_+/, '_'
|
21
|
+
f.write " \# #{group.description}\n"
|
22
|
+
f.write " #{code} = #{group.group_id}\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
f.write " end\n"
|
26
|
+
f.write " end\n"
|
27
|
+
f.write "end\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "Done, #{filename}."
|
31
|
+
rescue => e
|
32
|
+
puts 'ERROR: Unable to generate a new list of tax codes.'
|
33
|
+
puts e.message
|
34
|
+
raise e
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
namespace :tax_cloud do
|
2
|
+
desc 'Generate tax codes.'
|
3
|
+
task tax_codes: :configure do
|
4
|
+
filename = 'lib/tax_cloud/tax_code_constants.rb'
|
5
|
+
|
6
|
+
begin
|
7
|
+
groups = TaxCloud::TaxCode::Groups.all.values
|
8
|
+
groups_and_tax_codes = Hash[groups.map do |group|
|
9
|
+
[group, group.tax_codes.values]
|
10
|
+
end]
|
11
|
+
File.open filename, 'wt' do |f|
|
12
|
+
f.write "module TaxCloud\n"
|
13
|
+
f.write " # Tax Codes.\n"
|
14
|
+
f.write " class TaxCodes\n"
|
15
|
+
f.write "\n"
|
16
|
+
codes = {}
|
17
|
+
groups_and_tax_codes.each_pair do |group, tax_codes|
|
18
|
+
puts " #{group.description}"
|
19
|
+
f.write " \# #{group.description}\n\n"
|
20
|
+
tax_codes.each do |tax_code|
|
21
|
+
code = tax_code.description.upcase
|
22
|
+
code.gsub! /[^A-Z0-9]/, '_'
|
23
|
+
code.gsub! /\_+$/, ''
|
24
|
+
code.gsub! /\_+/, '_'
|
25
|
+
# avoid duplicates
|
26
|
+
code_id = codes[code] ? "#{code}_#{codes[code]}" : code
|
27
|
+
codes[code] = (codes[code] || 0) + 1
|
28
|
+
f.write " \# #{group.description}: #{tax_code.description}\n"
|
29
|
+
f.write " #{code_id} = #{tax_code.ticid}\n"
|
30
|
+
end
|
31
|
+
f.write "\n"
|
32
|
+
end
|
33
|
+
f.write " end\n"
|
34
|
+
f.write "end\n"
|
35
|
+
end
|
36
|
+
puts "Done, #{filename}."
|
37
|
+
rescue => e
|
38
|
+
puts 'ERROR: Unable to generate a new list of tax codes.'
|
39
|
+
puts e.message
|
40
|
+
raise e
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/tax_cloud.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'i18n'
|
3
|
+
require 'hash'
|
4
|
+
require 'savon_soap_xml'
|
5
|
+
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/core_ext'
|
8
|
+
|
9
|
+
require 'tax_cloud/version'
|
10
|
+
require 'tax_cloud/errors'
|
11
|
+
require 'tax_cloud/responses'
|
12
|
+
require 'tax_cloud/record'
|
13
|
+
require 'tax_cloud/transaction'
|
14
|
+
require 'tax_cloud/address'
|
15
|
+
require 'tax_cloud/cart_item'
|
16
|
+
require 'tax_cloud/tax_code'
|
17
|
+
require 'tax_cloud/tax_code_group'
|
18
|
+
require 'tax_cloud/tax_codes'
|
19
|
+
require 'tax_cloud/tax_code_constants'
|
20
|
+
require 'tax_cloud/tax_code_groups'
|
21
|
+
require 'tax_cloud/tax_code_group_constants'
|
22
|
+
require 'tax_cloud/configuration'
|
23
|
+
require 'tax_cloud/client'
|
24
|
+
|
25
|
+
I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
|
26
|
+
|
27
|
+
# TaxCloud is a web service to calculate and track sales tax for your ecommerce platform. Integration is easy to use.
|
28
|
+
# For information on configuring and using the TaxCloud API, look at the <tt>README</tt> file.
|
29
|
+
module TaxCloud
|
30
|
+
# WSDL location for TaxCloud API.
|
31
|
+
WSDL_URL = 'https://api.taxcloud.net/1.0/?wsdl'.freeze
|
32
|
+
|
33
|
+
# TaxCloud API version.
|
34
|
+
API_VERSION = '1.0'.freeze
|
35
|
+
|
36
|
+
class << self
|
37
|
+
# TaxCloud gem configuration.
|
38
|
+
attr_accessor :configuration
|
39
|
+
|
40
|
+
# Returns true if the gem has been configured.
|
41
|
+
def configured?
|
42
|
+
configuration.present?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Configure the gem.
|
46
|
+
def configure
|
47
|
+
self.configuration ||= Configuration.new
|
48
|
+
yield configuration
|
49
|
+
end
|
50
|
+
|
51
|
+
# Reset the current configuration.
|
52
|
+
def reset!
|
53
|
+
self.configuration = nil
|
54
|
+
@client = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# The configured SOAP client to the TaxCloud service.
|
58
|
+
def client
|
59
|
+
check_configuration!
|
60
|
+
@client ||= TaxCloud::Client.new
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def check_configuration!
|
66
|
+
raise TaxCloud::Errors::MissingConfig.new unless self.configuration
|
67
|
+
self.configuration.check!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module TaxCloud #:nodoc:
|
2
|
+
# An <tt>Address</tt> defines an address in the United States.
|
3
|
+
class Address < Record
|
4
|
+
# First line of address.
|
5
|
+
attr_accessor :address1
|
6
|
+
# Second line of adress.
|
7
|
+
attr_accessor :address2
|
8
|
+
# City.
|
9
|
+
attr_accessor :city
|
10
|
+
# State.
|
11
|
+
attr_accessor :state
|
12
|
+
# 5-digit Zip Code.
|
13
|
+
attr_accessor :zip5
|
14
|
+
# 4-digit Zip Code.
|
15
|
+
attr_accessor :zip4
|
16
|
+
|
17
|
+
# Verify this address.
|
18
|
+
#
|
19
|
+
# Returns a verified TaxCloud::Address.
|
20
|
+
def verify
|
21
|
+
params = to_hash.downcase_keys
|
22
|
+
if TaxCloud.configuration.usps_username
|
23
|
+
params = params.merge(
|
24
|
+
'uspsUserID' => TaxCloud.configuration.usps_username
|
25
|
+
)
|
26
|
+
end
|
27
|
+
response = TaxCloud.client.request(:verify_address, params)
|
28
|
+
TaxCloud::Responses::VerifyAddress.parse(response)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Complete zip code.
|
32
|
+
# Returns a 9-digit Zip Code, when available.
|
33
|
+
def zip
|
34
|
+
return nil unless zip5 && !zip5.empty?
|
35
|
+
[zip5, zip4].select { |z| z && !z.empty? }.join('-')
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convert the object to a usable hash for SOAP requests
|
39
|
+
def to_hash
|
40
|
+
{
|
41
|
+
'Address1' => address1,
|
42
|
+
'Address2' => address2,
|
43
|
+
'City' => city,
|
44
|
+
'State' => state,
|
45
|
+
'Zip5' => zip5,
|
46
|
+
'Zip4' => zip4
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|