tax_cloud 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.travis.yml +9 -0
  2. data/CHANGELOG.rdoc +28 -0
  3. data/CONTRIBUTORS.txt +20 -0
  4. data/Gemfile +1 -1
  5. data/LICENSE.rdoc +22 -0
  6. data/README.rdoc +112 -28
  7. data/Rakefile +10 -2
  8. data/lib/config/locales/en.yml +34 -0
  9. data/lib/hash.rb +8 -6
  10. data/lib/savon_soap_xml.rb +33 -0
  11. data/lib/tasks/tax_cloud.rake +20 -0
  12. data/lib/tasks/tax_code_groups.rake +39 -0
  13. data/lib/tasks/tax_codes.rake +45 -0
  14. data/lib/tax_cloud.rb +43 -16
  15. data/lib/tax_cloud/address.rb +30 -17
  16. data/lib/tax_cloud/cart_item.rb +13 -19
  17. data/lib/tax_cloud/client.rb +48 -0
  18. data/lib/tax_cloud/configuration.rb +17 -2
  19. data/lib/tax_cloud/errors.rb +6 -0
  20. data/lib/tax_cloud/errors/api_error.rb +18 -0
  21. data/lib/tax_cloud/errors/missing_config_error.rb +13 -0
  22. data/lib/tax_cloud/errors/missing_config_option_error.rb +19 -0
  23. data/lib/tax_cloud/errors/soap_error.rb +33 -0
  24. data/lib/tax_cloud/errors/tax_cloud_error.rb +86 -0
  25. data/lib/tax_cloud/errors/unexpected_soap_response_error.rb +23 -0
  26. data/lib/tax_cloud/record.rb +14 -0
  27. data/lib/tax_cloud/responses.rb +13 -0
  28. data/lib/tax_cloud/responses/authorized.rb +10 -0
  29. data/lib/tax_cloud/responses/authorized_with_capture.rb +10 -0
  30. data/lib/tax_cloud/responses/base.rb +88 -0
  31. data/lib/tax_cloud/responses/captured.rb +11 -0
  32. data/lib/tax_cloud/responses/cart_item.rb +24 -0
  33. data/lib/tax_cloud/responses/generic.rb +35 -0
  34. data/lib/tax_cloud/responses/lookup.rb +41 -0
  35. data/lib/tax_cloud/responses/ping.rb +10 -0
  36. data/lib/tax_cloud/responses/returned.rb +10 -0
  37. data/lib/tax_cloud/responses/tax_code_groups.rb +33 -0
  38. data/lib/tax_cloud/responses/tax_codes.rb +33 -0
  39. data/lib/tax_cloud/responses/tax_codes_by_group.rb +33 -0
  40. data/lib/tax_cloud/responses/verify_address.rb +29 -0
  41. data/lib/tax_cloud/tax_code.rb +11 -0
  42. data/lib/tax_cloud/tax_code_constants.rb +562 -0
  43. data/lib/tax_cloud/tax_code_group.rb +30 -0
  44. data/lib/tax_cloud/tax_code_group_constants.rb +31 -0
  45. data/lib/tax_cloud/tax_code_groups.rb +28 -0
  46. data/lib/tax_cloud/tax_codes.rb +24 -47
  47. data/lib/tax_cloud/transaction.rb +39 -34
  48. data/lib/tax_cloud/version.rb +3 -3
  49. data/tax_cloud.gemspec +7 -5
  50. data/test/cassettes/authorized.yml +70 -45
  51. data/test/cassettes/authorized_with_capture.yml +70 -45
  52. data/test/cassettes/captured.yml +101 -67
  53. data/test/cassettes/get_tic_groups.yml +656 -0
  54. data/test/cassettes/get_tics.yml +952 -0
  55. data/test/cassettes/get_tics_by_group.yml +49 -0
  56. data/test/cassettes/invalid_soap_call.yml +651 -0
  57. data/test/cassettes/lookup.yml +644 -25
  58. data/test/cassettes/lookup_ny.yml +651 -0
  59. data/test/cassettes/ping.yml +647 -0
  60. data/test/cassettes/ping_with_invalid_credentials.yml +647 -0
  61. data/test/cassettes/ping_with_invalid_response.yml +647 -0
  62. data/test/cassettes/returned.yml +101 -67
  63. data/test/cassettes/verify_bad_address.yml +578 -976
  64. data/test/cassettes/verify_good_address.yml +36 -23
  65. data/test/helper.rb +4 -19
  66. data/test/test_address.rb +25 -7
  67. data/test/test_client.rb +29 -0
  68. data/test/test_configuration.rb +33 -0
  69. data/test/test_setup.rb +18 -0
  70. data/test/test_soap.rb +13 -0
  71. data/test/test_tax_code_groups.rb +31 -0
  72. data/test/test_tax_codes.rb +19 -0
  73. data/test/test_transaction.rb +22 -11
  74. data/test/test_transaction_ny.rb +27 -0
  75. data/test/vcr_setup.rb +9 -0
  76. metadata +134 -24
  77. data/lib/savon_xml_override.rb +0 -30
@@ -0,0 +1,9 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
6
+ - jruby
7
+ - rbx
8
+ - ree
9
+
@@ -0,0 +1,28 @@
1
+ === 0.2.0 (11/26/2012)
2
+
3
+ * The gem is now licensed under the MIT license - @dblock.
4
+ * Raise specialized configuration and SOAP errors - @dblock.
5
+ * Added <tt>TaxCloud::Client.ping</tt> - @dblock.
6
+ * Returning a verified <tt>TaxCloud::Address</tt> from <tt>TaxCloud::Address.verify</tt> - @dblock.
7
+ * Added <tt>TaxCloud::Address.zip</tt> that returns a 9-digit address zip code, when available - @dblock.
8
+ * Returning a <tt>TaxCloud::Responses::Lookup</tt> from <tt>TaxCloud::Transaction.lookup</tt> - @dblock.
9
+ * Returning transaction state, ie. <tt>"OK"</tt> from all other TaxCloud transactions. Exceptions are raised on error - @dblock.
10
+ * Added support for tax codes and tax code groups lookup with <tt>TaxCloud::TaxCodes</tt> and <tt>TaxCloud::TaxCode::Groups</tt> - @dblock.
11
+
12
+ === 0.1.5 (5/9/2012)
13
+
14
+ * Fixed compatibility with Ruby 1.8.7 and 1.9.3, removed super from constructors for classes which inherit from <tt>Object</tt> - @gfmurphy.
15
+
16
+ === 0.1.4 (10/20/2011)
17
+
18
+ * Upgraded rdoc - @drewtempelmeyer.
19
+ * Fixed <tt>.gemspec</tt> dependency declaration for savon - @drewtempelmeyer.
20
+
21
+ === 0.1.3 (9/19/2011)
22
+
23
+ * Added support for the "returned" request - @danielmorrison.
24
+ * Refactoreted tests to use vcr and webmock - @danielmorrison.
25
+
26
+ === 0.1.0 (8/23/2011)
27
+
28
+ * Initial public release - @drewtempelmeyer.
@@ -0,0 +1,20 @@
1
+ tax_cloud Contributors
2
+
3
+ Lead Developers
4
+ =======================
5
+ * Drew Tempelmeyer
6
+ * Twitter: @tempelmeyer
7
+ * App.net: @tempelmeyer
8
+ * GitHub: drewtempelmeyer
9
+
10
+ * Daniel Doubrovkine
11
+ * Twitter: @dblockdotorg
12
+ * GitHub: dblock
13
+
14
+ Contributors
15
+ =======================
16
+ * Daniel Morrison
17
+ * GitHub: danielmorrison
18
+
19
+ * George F Murphy
20
+ * GitHub: gfmurphy
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in taxcloud.gemspec
3
+ # Specify your gem's dependencies in tax_cloud.gemspec
4
4
  gemspec
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2011-2012 Drew Tempelmeyer & Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,47 +1,126 @@
1
1
  = TaxCloud
2
2
 
3
- TaxCloud is a service to calculate sales tax and generate tax reports.
4
- tax\_cloud allows you to easily integrate with TaxCloud's API.
3
+ {<img src="https://travis-ci.org/drewtempelmeyer/tax_cloud.png" />}[https://travis-ci.org/drewtempelmeyer/tax_cloud]
4
+
5
+ TaxCloud[http://www.taxcloud.com] is a free service to calculate sales tax and generate tax reports. The <tt>tax_cloud</tt> gem allows you to easily integrate with TaxCloud's API.
6
+
7
+ === Getting Started
8
+ A TaxCloud[http://www.taxcloud.com] API ID and API key are required, along with an optional USPS address API username.
9
+
10
+ 1. Create a TaxCloud[http://www.taxcloud.com] merchant account at http://www.taxcloud.net.
11
+ 2. Add a website to your TaxCloud[http://www.taxcloud.com] account. This will generate an API ID and API Key that you will need to use the service.
12
+ 3. Get access to the USPS Address API at https://www.usps.com/business/webtools.htm. The API will provide a 9-digit zip code, which allows TaxCloud[http://www.taxcloud.com] to determine the most accurate rate.
5
13
 
6
14
  === Setup
7
- Add the gem to your Gemfile
8
- gem 'tax_cloud', '~> 0.1.0'
15
+ Add the gem to your Gemfile.
16
+
17
+ gem 'tax_cloud', '~> 0.1.5'
9
18
 
10
- Configure your environment. For example, create an initializer in Rails in *config/initializers/tax_cloud.rb*
11
- TaxCloud.configure do |config|
12
- config.api_login_id = 'your_tax_cloud_api_login_id'
13
- config.api_key = 'your_tax_cloud_api_key'
14
- config.usps_username = 'your_usps_username'
15
- end
19
+ Configure your environment. For example, create an initializer in Rails in <tt>config/initializers/tax_cloud.rb</tt>.
20
+
21
+ TaxCloud.configure do |config|
22
+ config.api_login_id = 'your_tax_cloud_api_login_id'
23
+ config.api_key = 'your_tax_cloud_api_key'
24
+ config.usps_username = 'your_usps_username'
25
+ end
16
26
 
17
27
  === Using TaxCloud
18
28
  Define the destination and origin addresses using <tt>TaxCloud::Address</tt>.
19
- origin = TaxCloud::Address.new(:address1 => '123 Fake Street', :city => 'New York', :state => 'NY', :zip5 => '10001')
20
- destination = TaxCloud::Address.new(:address1 => '239 Hollywood Drive', :city => 'Beverly Hills', :state => 'CA', :zip5 => '90210')
29
+
30
+ origin = TaxCloud::Address.new(
31
+ :address1 => '162 East Avenue',
32
+ :address2 => 'Third Floor',
33
+ :city => 'Norwalk',
34
+ :state => 'CT',
35
+ :zip5 => '06851')
36
+ destination = TaxCloud::Address.new(
37
+ :address1 => '3121 West Government Way',
38
+ :address2 => 'Suite 2B',
39
+ :city => 'Seattle',
40
+ :state => 'WA',
41
+ :zip5 => '98199')
21
42
 
22
43
  Create your Transaction and set up your cart items
23
- transaction = TaxCloud::Transaction.new(:customer_id => '1', :cart_id => '1', :origin => origin, :destination => destination)
24
- transaction.cart_items << TaxCloud::CartItem.new(:index => 0, :item_id => 'SKU-100', :tic => TaxCloud::TaxCodes::GENERAL, :price => 10.00, :quantity => 1)
25
- lookup = transaction.lookup # this will return a Savon response object
44
+
45
+ transaction = TaxCloud::Transaction.new(
46
+ :customer_id => '1',
47
+ :cart_id => '1',
48
+ :origin => origin,
49
+ :destination => destination)
50
+ transaction.cart_items << TaxCloud::CartItem.new(
51
+ :index => 0,
52
+ :item_id => 'SKU-100',
53
+ :tic => TaxCloud::TaxCodes::GENERAL,
54
+ :price => 10.00,
55
+ :quantity => 1)
56
+ lookup = transaction.lookup # this will return a TaxCloud::Responses::Lookup instance
57
+ lookup.tax_amount # total tax amount
58
+ lookup.cart_items.each do |cart_item|
59
+ cart_item.tax_amount # tax for a single item
60
+ end
26
61
 
27
62
  After you've authorized and captured the transaction via your merchant account, you should do the same with TaxCloud for maintaining accurate tax information.
28
- transaction.order_id = 100
29
- transaction.authorized_with_capture # return Savon response object
30
63
 
31
- Later, you may need to mark some cart items as returned. TaxCloud will ignore any cart items that you don't include
32
64
  transaction.order_id = 100
33
- transaction.cart_items << TaxCloud::CartItem.new(:index => 0, :item_id => 'SKU-100', :tic => TaxCloud::TaxCodes::GENERAL, :price => 10.00, :quantity => 1)
34
- transaction.returned # return Savon response object
65
+ transaction.authorized_with_capture # returns "OK" or raises an error
35
66
 
36
- === Running Tests
37
- * Add your config details to *test/helper*
38
- * VCR and WebMock are used to replay requests and avoid hitting the API each time. To refresh the mocks, simply delete the *test/cassettes* directory.
39
- * The mocks will filter out your config details, but remember not to commit them!
40
- * run <tt>rake test</tt>
67
+ Later, you may need to mark some cart items as returned. TaxCloud will ignore any cart items that you don't include.
68
+
69
+ transaction.order_id = 100
70
+ transaction.cart_items << TaxCloud::CartItem.new(
71
+ :index => 0,
72
+ :item_id => 'SKU-100',
73
+ :tic => TaxCloud::TaxCodes::GENERAL,
74
+ :price => 10.00,
75
+ :quantity => 1)
76
+ transaction.returned # returns "OK" or raises an error
77
+
78
+ === Verifying Addresses
79
+
80
+ TaxCloud[http://www.taxcloud.com] optionally integrates with the USPS Address API. An address can be verified, which can also yield a 9-digit zip code that helps determine a more accurate tax rate.
81
+
82
+ address = TaxCloud::Address.new({
83
+ :address1 => '888 6th Ave',
84
+ :city => 'New York',
85
+ :state => 'New York',
86
+ :zip5 => '10001'
87
+ })
41
88
 
42
- === Todo
43
- * Instead of returning Savon response objects, it should return TransactionLookupResponse, TransactionAuthorizedResponse, TransactionCapturedResponse, etc.
44
- * Add all tax codes to TaxCloud::TaxCodes
89
+ verified_address = address.verify
90
+ verified_address.zip5 # 10001
91
+ verified_address.zip4 # 3502
92
+ verified_address.zip # 10001-3502
93
+
94
+ === Tax Codes
95
+ TaxCloud[http://www.taxcloud.com] maintains a list of all Taxability Information Codes or TICs, which can be found at https://taxcloud.net/tic.
96
+
97
+ You can obtain all tax codes as well as lookup a tax code by ID.
98
+
99
+ TaxCloud::TaxCodes.all # a hash of all codes
100
+ tax_code = TaxCloud::TaxCodes[TaxCloud::TaxCodes::DIRECT_MAIL_RELATED]
101
+ tax_code.ticid # 11000 or TaxCloud::TaxCodes::DIRECT_MAIL_RELATED
102
+ tax_code.description # "Direct-mail related"
103
+
104
+ Tax codes are organized in groups.
105
+
106
+ TaxCloud::TaxCode::Groups.all # a hash of all groups
107
+ tax_code_group = TaxCloud::TaxCode::Groups[TaxCloud::TaxCode::Groups::SCHOOL_RELATED_PRODUCTS]
108
+ tax_code_group.group_id # 3 or TaxCloud::TaxCode::Groups::SCHOOL_RELATED_PRODUCTS
109
+ tax_code_group.description # School Related Products
110
+ tax_code_group.tax_codes # a hash of all codes in this group
111
+
112
+ Tax code constants are defined in <tt>tax_code_constants.rb</tt> and tax code group constants in <tt>tax_code_group_constants.rb</tt>. These files can be generated by running the following rake tasks.
113
+
114
+ TAXCLOUD_API_LOGIN_ID=... TAXCLOUD_API_KEY=... TAXCLOUD_USPS_USERNAME=... tax_cloud:tax_codes
115
+ TAXCLOUD_API_LOGIN_ID=... TAXCLOUD_API_KEY=... TAXCLOUD_USPS_USERNAME=... tax_cloud:tax_code_groups
116
+
117
+ === Running Tests
118
+ * VCR and WebMock are used to replay requests and avoid hitting the API each time. To refresh the mocks, simply delete the <tt>test/cassettes</tt> directory.
119
+ * Run tests.
120
+ rake test
121
+ * If you need to record new requests against TaxCloud, set your keys first.
122
+ TAXCLOUD_API_LOGIN_ID=... TAXCLOUD_API_KEY=... TAXCLOUD_USPS_USERNAME=... rake test
123
+ The mocks will filter out your configuration details.
45
124
 
46
125
  === Bugs, fixes, etc
47
126
  * Fork.
@@ -49,3 +128,8 @@ Later, you may need to mark some cart items as returned. TaxCloud will ignore an
49
128
  * Fix.
50
129
  * Commit.
51
130
  * Submit pull request.
131
+
132
+ === License
133
+
134
+ This gem is licened under the MIT license.
135
+
data/Rakefile CHANGED
@@ -13,12 +13,20 @@ end
13
13
  RDoc::Task.new do |rd|
14
14
  README = 'README.rdoc'
15
15
  rd.main = README
16
- rd.rdoc_files.include(README, "lib/**/*.rb")
16
+ rd.rdoc_files.include(README, 'CHANGELOG.rdoc', 'LICENSE.rdoc', "lib/**/*.rb")
17
17
  rd.rdoc_dir = 'doc'
18
18
  rd.title = 'tax_cloud'
19
19
  end
20
20
 
21
- desc "Validate the gemspec"
21
+ desc "Validate the gemspec."
22
22
  task :gemspec do
23
23
  puts gemspec.validate
24
24
  end
25
+
26
+ load 'lib/tasks/tax_cloud.rake'
27
+ load 'lib/tasks/tax_codes.rake'
28
+ load 'lib/tasks/tax_code_groups.rake'
29
+
30
+ load 'vcr/tasks/vcr.rake'
31
+
32
+ task :default => :test
@@ -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 configuration 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."
@@ -1,9 +1,11 @@
1
- class Hash
1
+ class Hash #:nodoc: all
2
+
2
3
  # Downcase the keys. Use this because <tt>TaxCloud::Address.verify</tt> requires downcased keys
3
- def downcase_keys!
4
- keys.each do |key|
5
- self[key.to_s.downcase] = delete(key)
4
+ def downcase_keys
5
+ inject({}) do |h, (k, v)|
6
+ h[k.downcase] = v
7
+ h
6
8
  end
7
- self
8
9
  end
9
- end
10
+
11
+ end
@@ -0,0 +1,33 @@
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
33
+
@@ -0,0 +1,20 @@
1
+ require 'tax_cloud'
2
+
3
+ namespace :tax_cloud do
4
+
5
+ desc "Configure TaxCloud."
6
+ task :configure do
7
+ unless TaxCloud.configured?
8
+ TaxCloud.configure do |config|
9
+ config.api_login_id = ENV['TAXCLOUD_API_LOGIN_ID']
10
+ config.api_key = ENV['TAXCLOUD_API_KEY']
11
+ config.usps_username = ENV['TAXCLOUD_USPS_USERNAME']
12
+ end
13
+ Savon.configure do |config|
14
+ config.log = false
15
+ end
16
+ HTTPI.log = false
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,39 @@
1
+ namespace :tax_cloud do
2
+
3
+ desc "Generate tax code groups."
4
+ task :tax_code_groups => :configure do
5
+ filename = "lib/tax_cloud/tax_code_group_constants.rb"
6
+
7
+ begin
8
+ groups = TaxCloud::TaxCode::Groups.all.values
9
+
10
+ File.open filename, "wt" do |f|
11
+ f.write "module TaxCloud\n"
12
+ f.write " class TaxCode\n"
13
+ f.write " # Tax Code Groups.\n"
14
+ f.write " class Groups\n"
15
+
16
+ groups.each do |group|
17
+ puts " #{group.description}"
18
+ code = group.description.upcase
19
+ code.gsub! /[^A-Z0-9]/, '_'
20
+ code.gsub! /_$/, ''
21
+ code.gsub! /\_+/, '_'
22
+ f.write " \# #{group.description}\n"
23
+ f.write " #{code} = #{group.group_id}\n"
24
+ end
25
+
26
+ f.write " end\n"
27
+ f.write " end\n"
28
+ f.write "end\n"
29
+ end
30
+
31
+ puts "Done, #{filename}."
32
+ rescue => e
33
+ puts "ERROR: Unable to generate a new list of tax codes."
34
+ puts e.message
35
+ raise e
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,45 @@
1
+ namespace :tax_cloud do
2
+
3
+ desc "Generate tax codes."
4
+ task :tax_codes => :configure do
5
+ filename = "lib/tax_cloud/tax_code_constants.rb"
6
+
7
+ begin
8
+ groups = TaxCloud::TaxCode::Groups.all.values
9
+ groups_and_tax_codes = Hash[groups.map do |group|
10
+ [ group, group.tax_codes.values ]
11
+ end]
12
+ File.open filename, "wt" do |f|
13
+ f.write "module TaxCloud\n"
14
+ f.write " # Tax Codes.\n"
15
+ f.write " class TaxCodes\n"
16
+ f.write "\n"
17
+ codes = {}
18
+ groups_and_tax_codes.each_pair do |group, tax_codes|
19
+ puts " #{group.description}"
20
+ f.write " \# #{group.description}\n\n"
21
+ tax_codes.each do |tax_code|
22
+ code = tax_code.description.upcase
23
+ code.gsub! /[^A-Z0-9]/, '_'
24
+ code.gsub! /\_+$/, ''
25
+ code.gsub! /\_+/, '_'
26
+ # avoid duplicates
27
+ code_id = codes[code] ? "#{code}_#{codes[code]}" : code
28
+ codes[code] = (codes[code] || 0) + 1
29
+ f.write " \# #{group.description}: #{tax_code.description}\n"
30
+ f.write " #{code_id} = #{tax_code.ticid}\n"
31
+ end
32
+ f.write "\n"
33
+ end
34
+ f.write " end\n"
35
+ f.write "end\n"
36
+ end
37
+ puts "Done, #{filename}."
38
+ rescue => e
39
+ puts "ERROR: Unable to generate a new list of tax codes."
40
+ puts e.message
41
+ raise e
42
+ end
43
+
44
+ end
45
+ end