suretax 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +74 -0
  6. data/Gemfile.travis +12 -0
  7. data/LICENSE.txt +22 -0
  8. data/NOTES.md +3 -0
  9. data/README.md +58 -0
  10. data/Rakefile +1 -0
  11. data/circle.yml +7 -0
  12. data/lib/suretax.rb +24 -0
  13. data/lib/suretax/api.rb +7 -0
  14. data/lib/suretax/api/cancel_request.rb +64 -0
  15. data/lib/suretax/api/group.rb +16 -0
  16. data/lib/suretax/api/item_message.rb +13 -0
  17. data/lib/suretax/api/request.rb +133 -0
  18. data/lib/suretax/api/request_item.rb +84 -0
  19. data/lib/suretax/api/response.rb +53 -0
  20. data/lib/suretax/api/tax.rb +25 -0
  21. data/lib/suretax/api/tax_amount.rb +46 -0
  22. data/lib/suretax/concerns.rb +7 -0
  23. data/lib/suretax/concerns/validatable.rb +208 -0
  24. data/lib/suretax/configuration.rb +84 -0
  25. data/lib/suretax/connection.rb +48 -0
  26. data/lib/suretax/constants.rb +7 -0
  27. data/lib/suretax/constants/regulatory_codes.rb +11 -0
  28. data/lib/suretax/constants/response_groups.rb +8 -0
  29. data/lib/suretax/constants/sales_type_codes.rb +8 -0
  30. data/lib/suretax/constants/tax_situs_codes.rb +12 -0
  31. data/lib/suretax/constants/transaction_type_codes.rb +505 -0
  32. data/lib/suretax/response.rb +70 -0
  33. data/lib/suretax/version.rb +3 -0
  34. data/spec/lib/suretax/api/group_spec.rb +50 -0
  35. data/spec/lib/suretax/api/request_item_spec.rb +54 -0
  36. data/spec/lib/suretax/api/request_item_validations_spec.rb +237 -0
  37. data/spec/lib/suretax/api/request_spec.rb +197 -0
  38. data/spec/lib/suretax/api/request_validations_spec.rb +384 -0
  39. data/spec/lib/suretax/api/response_spec.rb +165 -0
  40. data/spec/lib/suretax/api/tax_amount_spec.rb +37 -0
  41. data/spec/lib/suretax/api/tax_spec.rb +59 -0
  42. data/spec/lib/suretax/configuration_spec.rb +97 -0
  43. data/spec/lib/suretax/connection_spec.rb +77 -0
  44. data/spec/lib/suretax/response_spec.rb +136 -0
  45. data/spec/spec_helper.rb +45 -0
  46. data/spec/support/cancellation_helper.rb +31 -0
  47. data/spec/support/connection_shared_examples.rb +37 -0
  48. data/spec/support/request_helper.rb +309 -0
  49. data/spec/support/suretax_helper.rb +27 -0
  50. data/spec/support/validations_shared_examples.rb +28 -0
  51. data/suretax.gemspec +33 -0
  52. metadata +281 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 090d466426a8ed2734e208ca3e310afa0fca041c
4
+ data.tar.gz: 890130d8629a6ff1ca5d959202a6d640753397b6
5
+ SHA512:
6
+ metadata.gz: 0509fea19ea7ce6a32f96a2888b8c1b170f028a9c0cdf5be786f221c9cf7f177498675795c27517c07ecd1cb6157203fb4e3b78d1f929eeddbf234446d342db5
7
+ data.tar.gz: 0daa94af83c1320f63869a7607528a45de24d8da108d7ff2e86718e4bff66f55061331d6b7317f262f804a0fe4f9cdfe5d0740095a8833ffdd36709042825c7a
data/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ ._*
2
+ .bundle
3
+ .DS_Store
4
+ .rvmrc
5
+ .ruby-version
6
+ .ruby-gemset
7
+ .pow*
8
+
9
+ *.gem
10
+ *.swp
11
+ database.yml
12
+ application.yml
13
+
14
+ tmp/*
15
+ log/*
16
+ coverage/*
17
+ vendor/bundle
18
+
19
+ spec/dummy/log/*
20
+ spec/dummy/tmp/*
21
+ spec/dummy/vendor/bundle/*
22
+ spec/dummy/coverage
23
+
24
+ !spec/dummy/config/database.yml
25
+
26
+ .env
27
+ dump.rdb
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ env:
2
+ - SURETAX_VALIDATION_KEY="xxxxxxxxxx" SURETAX_CLIENT_NUMBER="000000000"
3
+ gemfile:
4
+ - Gemfile.travis
5
+ language: ruby
6
+ script:
7
+ - bundle exec rspec
8
+ rvm:
9
+ - 1.9.3
10
+ - 2.1.0
11
+ - jruby-19mode
12
+ - rbx-2.2
13
+ notifications:
14
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in suretax.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,74 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ suretax (0.1.0)
5
+ faraday
6
+ monetize
7
+ money
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.3.5)
13
+ awesome_print (1.2.0)
14
+ coderay (1.1.0)
15
+ crack (0.4.2)
16
+ safe_yaml (~> 1.0.0)
17
+ diff-lcs (1.2.5)
18
+ docile (1.1.3)
19
+ dotenv (0.9.0)
20
+ faraday (0.9.0)
21
+ multipart-post (>= 1.2, < 3)
22
+ i18n (0.7.0.beta1)
23
+ method_source (0.8.2)
24
+ monetize (0.4.1)
25
+ money (~> 6.2.1)
26
+ money (6.2.1)
27
+ i18n (>= 0.6.4, <= 0.7.0.dev)
28
+ multi_json (1.8.4)
29
+ multipart-post (2.0.0)
30
+ pry (0.9.12.6)
31
+ coderay (~> 1.0)
32
+ method_source (~> 0.8)
33
+ slop (~> 3.4)
34
+ rake (10.1.1)
35
+ rspec (3.0.0)
36
+ rspec-core (~> 3.0.0)
37
+ rspec-expectations (~> 3.0.0)
38
+ rspec-mocks (~> 3.0.0)
39
+ rspec-core (3.0.2)
40
+ rspec-support (~> 3.0.0)
41
+ rspec-expectations (3.0.2)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.0.0)
44
+ rspec-its (1.0.1)
45
+ rspec-core (>= 2.99.0.beta1)
46
+ rspec-expectations (>= 2.99.0.beta1)
47
+ rspec-mocks (3.0.2)
48
+ rspec-support (~> 3.0.0)
49
+ rspec-support (3.0.2)
50
+ safe_yaml (1.0.1)
51
+ simplecov (0.8.2)
52
+ docile (~> 1.1.0)
53
+ multi_json
54
+ simplecov-html (~> 0.8.0)
55
+ simplecov-html (0.8.0)
56
+ slop (3.4.7)
57
+ webmock (1.17.3)
58
+ addressable (>= 2.2.7)
59
+ crack (>= 0.3.2)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ awesome_print
66
+ bundler (~> 1.3)
67
+ dotenv
68
+ pry
69
+ rake
70
+ rspec (~> 3.0.0)
71
+ rspec-its (~> 1.0)
72
+ simplecov
73
+ suretax!
74
+ webmock
data/Gemfile.travis ADDED
@@ -0,0 +1,12 @@
1
+ # Special Travis Gemfile for Rubinius
2
+ source 'https://rubygems.org'
3
+
4
+ platforms :rbx do
5
+ gem 'rubysl', '~> 2.0'
6
+ gem 'rubysl-openssl', '~> 2.1.0'
7
+ gem 'psych'
8
+ gem 'rubinius-coverage'
9
+ gem 'json', '~> 1.8'
10
+ end
11
+
12
+ eval_gemfile File.expand_path('../Gemfile', __FILE__)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Damon Davison
2
+
3
+ MIT License
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.
data/NOTES.md ADDED
@@ -0,0 +1,3 @@
1
+ # Suretax gem notes
2
+
3
+ - Deal with post failures and parse errors in Response.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ [![Code Climate](https://codeclimate.com/github/bqsoft/suretax.png)](https://codeclimate.com/github/bqsoft/suretax)
2
+ [![TravisCI](https://api.travis-ci.org/bqsoft/suretax.png)](https://travis-ci.org/bqsoft/suretax)
3
+ # Suretax
4
+
5
+
6
+ ## Synopsis
7
+
8
+ ```ruby
9
+ Suretax.configure do |c|
10
+ c.validation_key = ENV['SURETAX_VALIDATION_KEY']
11
+ c.base_url = ENV['SURETAX_BASE_URL']
12
+ c.client_number = ENV['SURETAX_CLIENT_NUMBER']
13
+ c.request_version = ENV['SURETAX_REQUEST_VERSION']
14
+ c.cancel_version = ENV['SURETAX_CANCEL_VERSION']
15
+ end
16
+
17
+ request = Suretax::Api::Request.new({ initial: data })
18
+ request.items = [ Suretax::Api::RequestItem.new({ initial: data }) ]
19
+ connection = Suretax::Connection.new
20
+
21
+ if request.valid?
22
+ response = connection.post(body: request.params)
23
+ response.params
24
+ end
25
+ ```
26
+
27
+ The configuration object is used to provide default values for
28
+ Suretax transactions. The validation_key, client_number, and
29
+ base_url may be overridden by supplying the key when instantiating
30
+ a Suretax::Api::Request object.
31
+
32
+
33
+ If not supplied, the base_url will default to the Suretax test
34
+ host (https://testapi.taxrating.net) and the request version
35
+ and cancel version will default to the latest versions available
36
+ (currently V03 and V01 respectively).
37
+
38
+
39
+ You can peek inside the tests for more examples and to see what data
40
+ methods are available.
41
+
42
+
43
+ ## Development Environment
44
+
45
+ Suretax uses [dotenv] to easily switch between development/test environments
46
+ and production.
47
+
48
+ You will need to set the following environment variables for the gem to work:
49
+
50
+ - `SURETAX_VALIDATION_KEY` (You can get this from [SureTax][suretax].)
51
+ - `SURETAX_BASE_URL` (This is usually `https://testapi.taxrating.net` for testing.)
52
+
53
+ You can do this by creating a .env file in the root of the Suretax gem
54
+ repository (gitignored by default). For more information, please see
55
+ the [dotenv documentation][dotenv]
56
+
57
+ [dotenv]: https://github.com/bkeepers/dotenv
58
+ [suretax]: http://suretax.com
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/circle.yml ADDED
@@ -0,0 +1,7 @@
1
+ machine:
2
+ environment:
3
+ SURETAX_BASE_URL: "https://testapi.taxrating.net"
4
+ SURETAX_VALIDATION_KEY: "xxxxxxxxxx"
5
+ SURETAX_CLIENT_NUMBER: "000000000"
6
+ SURETAX_POST_PATH: "/Services/V01/SureTax.asmx/PostRequest"
7
+ SURETAX_CANCEL_PATH: "/Services/V01/SureTax.asmx/CancelPostRequest"
data/lib/suretax.rb ADDED
@@ -0,0 +1,24 @@
1
+ require "suretax/version"
2
+
3
+ require "suretax/concerns"
4
+
5
+ require "suretax/configuration"
6
+ require "suretax/connection"
7
+ require "suretax/response"
8
+ require "suretax/constants"
9
+ require "suretax/api"
10
+
11
+ require "money"
12
+
13
+ module Suretax
14
+
15
+ class << self
16
+ attr_accessor :configuration
17
+
18
+ def configure
19
+ yield(configuration)
20
+ end
21
+ end
22
+
23
+ self.configuration ||= Configuration.instance
24
+ end
@@ -0,0 +1,7 @@
1
+ require 'suretax/api/response'
2
+ require 'suretax/api/request'
3
+ require 'suretax/api/request_item'
4
+ require 'suretax/api/cancel_request'
5
+ require 'suretax/api/group'
6
+ require 'suretax/api/tax'
7
+ require 'suretax/api/tax_amount'
@@ -0,0 +1,64 @@
1
+ module Suretax
2
+ module Api
3
+ #
4
+ # Given a transaction ID, sends a request to cancel
5
+ # that transaction to Suretax.
6
+ #
7
+ class CancelRequest
8
+ attr_accessor :client_number, :validation_key, :transaction,
9
+ :client_tracking
10
+
11
+ attr_reader :response
12
+
13
+ def initialize(options = {})
14
+ self.client_number = options.fetch(:client_number,
15
+ configuration.client_number)
16
+ self.validation_key = options.fetch(:validation_key,
17
+ configuration.validation_key)
18
+
19
+ options.each_pair do |key, value|
20
+ send("#{key.to_s}=", value.to_s)
21
+ end
22
+ end
23
+
24
+ def submit
25
+ log_request
26
+ suretax_response = connection.cancel(params)
27
+
28
+ log_response(suretax_response)
29
+ @response = Suretax::Api::Response.new(suretax_response.body)
30
+ end
31
+
32
+ def params
33
+ {
34
+ 'ClientNumber' => client_number,
35
+ 'ClientTracking' => client_tracking,
36
+ 'TransId' => transaction,
37
+ 'ValidationKey' => validation_key
38
+ }
39
+ end
40
+
41
+ private
42
+
43
+ def log_request
44
+ logger.info "\nSureTax Cancellation sent:\n#{params.inspect}" if logger
45
+ end
46
+
47
+ def log_response(response)
48
+ logger.info("\nSureTax Cancellation resp:\n#{response.inspect}") if logger
49
+ end
50
+
51
+ def logger
52
+ configuration.logger
53
+ end
54
+
55
+ def configuration
56
+ Suretax.configuration
57
+ end
58
+
59
+ def connection
60
+ @connection ||= Connection.new
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,16 @@
1
+ module Suretax
2
+ module Api
3
+ class Group
4
+ attr_reader :state, :customer, :invoice, :taxes, :line
5
+
6
+ def initialize(response_params)
7
+ @state = response_params.fetch('StateCode')
8
+ @invoice = response_params.fetch('InvoiceNumber')
9
+ @line = response_params['LineNumber']
10
+ @customer = response_params.fetch('CustomerNumber')
11
+ @taxes = response_params.fetch('TaxList').map { |tax| Tax.new(tax) }
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Suretax
2
+ module Api
3
+ class ItemMessage
4
+ attr_reader :line_number, :response_code, :message
5
+
6
+ def initialize(response_params)
7
+ @line_number = response_params.fetch('LineNumber')
8
+ @response_code = response_params.fetch('ResponseCode')
9
+ @message = response_params.fetch('Message')
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,133 @@
1
+ module Suretax
2
+ module Api
3
+ class ValidationError < StandardError; end
4
+
5
+ class Request
6
+ include Suretax::Concerns::Validatable
7
+
8
+ attr_accessor :business_unit,
9
+ :client_number,
10
+ :client_tracking,
11
+ :data_month,
12
+ :data_year,
13
+ :industry_exemption,
14
+ :response_group,
15
+ :response_type,
16
+ :return_file_code,
17
+ :total_revenue,
18
+ :validation_key,
19
+ :items
20
+
21
+ attr_reader :response
22
+
23
+ validate :client_number,
24
+ :business_unit,
25
+ :validation_key,
26
+ :data_year,
27
+ :data_month,
28
+ :total_revenue,
29
+ :return_file_code,
30
+ :client_tracking,
31
+ :response_group,
32
+ :response_type,
33
+ :items
34
+
35
+ def initialize(options = {})
36
+ self.return_file_code = '0'
37
+ self.client_number = options.delete(:client_number) || configuration.client_number
38
+ self.validation_key = options.delete(:validation_key) || configuration.validation_key
39
+
40
+ default_data_date(options)
41
+
42
+ options.each_pair do |key,value|
43
+ self.send("#{key.to_s}=", value.to_s)
44
+ end
45
+
46
+ initialize_items(options)
47
+
48
+ validate!
49
+ end
50
+
51
+ def submit
52
+ if valid?
53
+ log_request
54
+ suretax_response = connection.post(params)
55
+ @response = Suretax::Api::Response.new(suretax_response.body)
56
+ else
57
+ raise(ValidationError, errors.messages.join(", "))
58
+ end
59
+ end
60
+
61
+ def valid?
62
+ !errors.any?
63
+ end
64
+
65
+ def rollback
66
+ if response
67
+ CancelRequest.new(transaction: response.transaction,
68
+ client_number: client_number, validation_key: validation_key,
69
+ client_tracking: client_tracking).submit
70
+ end
71
+ end
72
+
73
+ def params
74
+ {
75
+ "ClientNumber" => client_number,
76
+ "BusinessUnit" => business_unit || '',
77
+ "ValidationKey" => validation_key,
78
+ "DataYear" => data_year,
79
+ "DataMonth" => data_month,
80
+ "TotalRevenue" => total_revenue.to_f,
81
+ "ReturnFileCode" => return_file_code,
82
+ "ClientTracking" => client_tracking || '',
83
+ "IndustryExemption" => industry_exemption,
84
+ "ResponseType" => response_type,
85
+ "ResponseGroup" => response_group,
86
+ "ItemList" => items.map { |item| item.params }
87
+ }
88
+ end
89
+
90
+ private
91
+
92
+ def default_data_date(options)
93
+ max_date = configuration.test? ? Date.today.prev_month : Date.today
94
+
95
+ requested_date = begin
96
+ Date.new(options[:data_year].to_i, options[:data_month].to_i, 1)
97
+ rescue
98
+ max_date
99
+ end
100
+
101
+ data_date = [requested_date, max_date].min
102
+
103
+ self.data_month = data_date.strftime('%m')
104
+ self.data_year = data_date.strftime('%Y')
105
+ end
106
+
107
+ def initialize_items(options)
108
+ self.items = []
109
+ if options[:items].respond_to?(:each)
110
+ options[:items].each do |item_args|
111
+ self.items << RequestItem.new(item_args)
112
+ end
113
+ end
114
+ end
115
+
116
+ def log_request
117
+ logger.info "\nSureTax Request sent:\n#{params.inspect}" if logger
118
+ end
119
+
120
+ def logger
121
+ configuration.logger
122
+ end
123
+
124
+ def configuration
125
+ Suretax.configuration
126
+ end
127
+
128
+ def connection
129
+ @connection ||= Connection.new
130
+ end
131
+ end
132
+ end
133
+ end