suretax 0.1.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 (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