tax_cloud 0.1.4 → 0.2.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.
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