suretax 0.2.3 → 1.0.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 +4 -4
- data/.env.example +4 -0
- data/.rubocop.yml +111 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +9 -9
- data/lib/suretax.rb +0 -1
- data/lib/suretax/api.rb +7 -7
- data/lib/suretax/api/cancel_request.rb +7 -7
- data/lib/suretax/api/group.rb +5 -6
- data/lib/suretax/api/item_message.rb +3 -3
- data/lib/suretax/api/request.rb +37 -37
- data/lib/suretax/api/request_item.rb +13 -17
- data/lib/suretax/api/response.rb +18 -19
- data/lib/suretax/api/tax.rb +11 -12
- data/lib/suretax/api/tax_amount.rb +3 -4
- data/lib/suretax/concerns.rb +1 -3
- data/lib/suretax/concerns/validatable.rb +21 -27
- data/lib/suretax/configuration.rb +17 -20
- data/lib/suretax/connection.rb +3 -5
- data/lib/suretax/constants/regulatory_codes.rb +8 -8
- data/lib/suretax/constants/response_groups.rb +6 -6
- data/lib/suretax/constants/sales_type_codes.rb +5 -5
- data/lib/suretax/constants/tax_situs_codes.rb +10 -10
- data/lib/suretax/constants/transaction_type_codes.rb +2 -2
- data/lib/suretax/response.rb +7 -10
- data/lib/suretax/version.rb +1 -1
- data/spec/lib/suretax/api/group_spec.rb +21 -22
- data/spec/lib/suretax/api/request_item_spec.rb +10 -12
- data/spec/lib/suretax/api/request_item_validations_spec.rb +73 -76
- data/spec/lib/suretax/api/request_spec.rb +62 -66
- data/spec/lib/suretax/api/request_validations_spec.rb +141 -143
- data/spec/lib/suretax/api/response_spec.rb +48 -52
- data/spec/lib/suretax/api/tax_amount_spec.rb +12 -12
- data/spec/lib/suretax/api/tax_spec.rb +26 -28
- data/spec/lib/suretax/configuration_spec.rb +21 -24
- data/spec/lib/suretax/connection_spec.rb +11 -15
- data/spec/lib/suretax/response_spec.rb +27 -31
- data/spec/spec_helper.rb +16 -17
- data/spec/support/cancellation_helper.rb +0 -1
- data/spec/support/connection_shared_examples.rb +8 -10
- data/spec/support/request_helper.rb +13 -14
- data/spec/support/suretax_helper.rb +2 -4
- data/spec/support/validations_shared_examples.rb +12 -12
- data/suretax.gemspec +10 -8
- metadata +7 -7
- data/.travis.yml +0 -13
data/lib/suretax/api/response.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(
|
1
|
+
require File.join(File.dirname(__FILE__), "item_message.rb")
|
2
2
|
|
3
3
|
module Suretax
|
4
4
|
module Api
|
@@ -8,12 +8,12 @@ module Suretax
|
|
8
8
|
|
9
9
|
def initialize(response_body)
|
10
10
|
@body = JSON.generate(response_body)
|
11
|
-
@status = response_body.fetch(
|
12
|
-
@transaction = response_body.fetch(
|
13
|
-
@message = response_body.fetch(
|
14
|
-
@success = response_body.fetch(
|
15
|
-
@client_tracking = response_body[
|
16
|
-
@total_tax = Amount.new(response_body[
|
11
|
+
@status = response_body.fetch("ResponseCode")
|
12
|
+
@transaction = response_body.fetch("TransId").to_s
|
13
|
+
@message = response_body.fetch("HeaderMessage")
|
14
|
+
@success = response_body.fetch("Successful") == "Y"
|
15
|
+
@client_tracking = response_body["ClientTracking"] || nil
|
16
|
+
@total_tax = Amount.new(response_body["TotalTax"])
|
17
17
|
|
18
18
|
build_groups(response_body)
|
19
19
|
build_item_messages(response_body)
|
@@ -24,26 +24,25 @@ module Suretax
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def item_errors?
|
27
|
-
@status ==
|
27
|
+
@status == "9001"
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
32
|
+
def build_groups(response_body)
|
33
|
+
@groups = []
|
34
|
+
if response_body["GroupList"].respond_to?(:map)
|
35
|
+
@groups = response_body.fetch("GroupList").map do |group|
|
36
|
+
Group.new(group)
|
38
37
|
end
|
39
38
|
end
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
41
|
+
def build_item_messages(response_body)
|
42
|
+
@item_messages = Array(response_body.fetch("ItemMessages", [])).map do |item_message|
|
43
|
+
ItemMessage.new(item_message)
|
45
44
|
end
|
45
|
+
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
data/lib/suretax/api/tax.rb
CHANGED
@@ -4,17 +4,17 @@ module Suretax
|
|
4
4
|
attr_reader :code, :description, :amount, :revenue, :county, :city, :rate, :taxable, :fee_rate, :tax_on_tax, :revenue_base
|
5
5
|
|
6
6
|
def initialize(response_params)
|
7
|
-
@code = response_params.fetch(
|
8
|
-
@description = response_params.fetch(
|
9
|
-
@amount = set_amount(response_params.fetch(
|
10
|
-
@revenue = response_params[
|
11
|
-
@county = response_params[
|
12
|
-
@city = response_params[
|
13
|
-
@rate = set_amount(response_params[
|
14
|
-
@taxable = set_amount(response_params[
|
15
|
-
@fee_rate = set_amount(response_params[
|
16
|
-
@tax_on_tax = set_amount(response_params[
|
17
|
-
@revenue_base = set_amount(response_params[
|
7
|
+
@code = response_params.fetch("TaxTypeCode")
|
8
|
+
@description = response_params.fetch("TaxTypeDesc")
|
9
|
+
@amount = set_amount(response_params.fetch("TaxAmount").to_f)
|
10
|
+
@revenue = response_params["Revenue"]
|
11
|
+
@county = response_params["CountyName"]
|
12
|
+
@city = response_params["CityName"]
|
13
|
+
@rate = set_amount(response_params["TaxRate"])
|
14
|
+
@taxable = set_amount(response_params["PercentTaxable"])
|
15
|
+
@fee_rate = set_amount(response_params["FeeRate"])
|
16
|
+
@tax_on_tax = set_amount(response_params["TaxOnTax"])
|
17
|
+
@revenue_base = set_amount(response_params["RevenueBase"])
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
@@ -22,7 +22,6 @@ module Suretax
|
|
22
22
|
def set_amount(value)
|
23
23
|
Amount.new(value) unless value.nil?
|
24
24
|
end
|
25
|
-
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require "monetize"
|
2
2
|
|
3
3
|
module Suretax
|
4
4
|
module Api
|
5
5
|
class Amount
|
6
6
|
attr_reader :precision, :divisor
|
7
7
|
|
8
|
-
def initialize(amount, currency =
|
8
|
+
def initialize(amount, currency = "US6")
|
9
9
|
@amount = Monetize.parse(amount, currency)
|
10
10
|
@precision = count_significant_decimal_places
|
11
11
|
@divisor = @amount.currency.subunit_to_unit
|
@@ -24,7 +24,7 @@ module Suretax
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def cents
|
27
|
-
(("%.2f" % to_f).to_f * 100
|
27
|
+
(("%.2f" % to_f).to_f * 100).to_i
|
28
28
|
end
|
29
29
|
|
30
30
|
def params
|
@@ -40,7 +40,6 @@ module Suretax
|
|
40
40
|
def count_significant_decimal_places
|
41
41
|
@amount.currency.subunit_to_unit.to_s.scan(/0/).count
|
42
42
|
end
|
43
|
-
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
data/lib/suretax/concerns.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Suretax::Concerns
|
2
|
-
|
3
2
|
module Validatable
|
4
|
-
|
5
3
|
def self.included(base)
|
6
4
|
base.extend ClassMethods
|
7
5
|
base.send(:include, Validations)
|
@@ -11,18 +9,17 @@ module Suretax::Concerns
|
|
11
9
|
@errors = Errors.new
|
12
10
|
|
13
11
|
self.class.validatable_attributes.each do |attribute_name|
|
14
|
-
value =
|
15
|
-
assertion =
|
12
|
+
value = send(attribute_name)
|
13
|
+
assertion = send("valid_#{attribute_name}?", value)
|
16
14
|
|
17
15
|
@errors[attribute_name] = Error.new(attribute_name, value) unless assertion
|
18
16
|
end
|
19
17
|
|
20
18
|
@errors
|
21
19
|
end
|
22
|
-
|
20
|
+
alias validate! errors
|
23
21
|
|
24
22
|
class Error
|
25
|
-
|
26
23
|
attr_accessor :message, :value, :attribute
|
27
24
|
|
28
25
|
def initialize(attribute, value)
|
@@ -38,14 +35,14 @@ module Suretax::Concerns
|
|
38
35
|
end
|
39
36
|
|
40
37
|
def format_nested_errors(value)
|
41
|
-
value.map { |obj| obj.errors.messages.join(
|
38
|
+
value.map { |obj| obj.errors.messages.join(", ") }
|
42
39
|
end
|
43
40
|
|
44
41
|
def format_error(value)
|
45
42
|
if value.nil?
|
46
43
|
"nil"
|
47
44
|
elsif value.is_a?(String) && value.empty?
|
48
|
-
%
|
45
|
+
%('')
|
49
46
|
else
|
50
47
|
value
|
51
48
|
end
|
@@ -56,15 +53,13 @@ module Suretax::Concerns
|
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
59
|
-
class Errors < Hash
|
60
|
-
|
56
|
+
class Errors < Hash
|
61
57
|
def messages
|
62
|
-
|
58
|
+
map { |_key, value| value.message }
|
63
59
|
end
|
64
60
|
end
|
65
61
|
|
66
62
|
module ClassMethods
|
67
|
-
|
68
63
|
attr_writer :validatable_attributes
|
69
64
|
|
70
65
|
def validate(*attribute_names)
|
@@ -77,7 +72,6 @@ module Suretax::Concerns
|
|
77
72
|
end
|
78
73
|
|
79
74
|
module Validations
|
80
|
-
|
81
75
|
def valid_data_year?(value)
|
82
76
|
return false if blank?(value)
|
83
77
|
value.length == 4 &&
|
@@ -85,11 +79,11 @@ module Suretax::Concerns
|
|
85
79
|
end
|
86
80
|
|
87
81
|
def valid_data_month?(value)
|
88
|
-
matches?(value,month_list_subexpression)
|
82
|
+
matches?(value, month_list_subexpression)
|
89
83
|
end
|
90
84
|
|
91
85
|
def valid_items?(items)
|
92
|
-
|
86
|
+
items.none? { |item| item.errors.any? }
|
93
87
|
end
|
94
88
|
|
95
89
|
def valid_list?(value)
|
@@ -100,7 +94,7 @@ module Suretax::Concerns
|
|
100
94
|
return false if blank?(value)
|
101
95
|
numeric?(value) && value.length <= 10
|
102
96
|
end
|
103
|
-
|
97
|
+
alias valid_customer_number? valid_client_number?
|
104
98
|
|
105
99
|
def valid_business_unit?(value)
|
106
100
|
blank?(value) || (value.length <= 20 && alphanumeric?(value))
|
@@ -117,7 +111,7 @@ module Suretax::Concerns
|
|
117
111
|
end
|
118
112
|
|
119
113
|
def valid_return_file_code?(value)
|
120
|
-
matches?(value.to_s,
|
114
|
+
matches?(value.to_s, "[Q0]")
|
121
115
|
end
|
122
116
|
|
123
117
|
def valid_client_tracking?(value)
|
@@ -129,7 +123,7 @@ module Suretax::Concerns
|
|
129
123
|
end
|
130
124
|
|
131
125
|
def valid_response_type?(value)
|
132
|
-
matches?(value,
|
126
|
+
matches?(value, "[DS][1-9]")
|
133
127
|
end
|
134
128
|
|
135
129
|
def valid_line_number?(value)
|
@@ -160,14 +154,14 @@ module Suretax::Concerns
|
|
160
154
|
def valid_tax_exemption_code_list?(value)
|
161
155
|
valid_list?(value) && !blank?(value.first)
|
162
156
|
end
|
163
|
-
|
157
|
+
alias valid_tax_exemption_codes? valid_tax_exemption_code_list?
|
164
158
|
|
165
159
|
def optional_north_american_phone_number?(value)
|
166
160
|
blank?(value) || north_american_phone_number?(value)
|
167
161
|
end
|
168
|
-
|
169
|
-
|
170
|
-
|
162
|
+
alias valid_bill_to_number? optional_north_american_phone_number?
|
163
|
+
alias valid_orig_number? optional_north_american_phone_number?
|
164
|
+
alias valid_term_number? optional_north_american_phone_number?
|
171
165
|
|
172
166
|
private
|
173
167
|
|
@@ -184,24 +178,24 @@ module Suretax::Concerns
|
|
184
178
|
end
|
185
179
|
|
186
180
|
def numeric?(value)
|
187
|
-
matches?(value,'\d+')
|
181
|
+
matches?(value, '\d+')
|
188
182
|
end
|
189
183
|
|
190
184
|
def alphanumeric?(value)
|
191
|
-
matches?(value,
|
185
|
+
matches?(value, "[a-z0-9]+")
|
192
186
|
end
|
193
187
|
|
194
188
|
def blank?(value)
|
195
|
-
value.nil? || matches?(value,'\s*')
|
189
|
+
value.nil? || matches?(value, '\s*')
|
196
190
|
end
|
197
191
|
|
198
|
-
def matches?(value,subexpression)
|
192
|
+
def matches?(value, subexpression)
|
199
193
|
/\A#{subexpression}\z/i === value
|
200
194
|
end
|
201
195
|
|
202
196
|
# Month numbers 1-12 with optional leading zero
|
203
197
|
def month_list_subexpression
|
204
|
-
"0?(?:" + (1..12).to_a.join(
|
198
|
+
"0?(?:" + (1..12).to_a.join("|") + ")"
|
205
199
|
end
|
206
200
|
end
|
207
201
|
end
|
@@ -4,8 +4,8 @@ module Suretax
|
|
4
4
|
class Configuration
|
5
5
|
include Singleton
|
6
6
|
|
7
|
-
REQUEST_VERSIONS = [1, 2, 3, 4]
|
8
|
-
CANCEL_VERSIONS = [1]
|
7
|
+
REQUEST_VERSIONS = [1, 2, 3, 4].freeze
|
8
|
+
CANCEL_VERSIONS = [1].freeze
|
9
9
|
|
10
10
|
attr_accessor :validation_key, :base_url, :client_number,
|
11
11
|
:request_version, :cancel_version, :logger
|
@@ -43,18 +43,18 @@ module Suretax
|
|
43
43
|
|
44
44
|
def request_path
|
45
45
|
@request_path ||=
|
46
|
-
|
46
|
+
"/Services/V%02d/SureTax.asmx/PostRequest" % request_version
|
47
47
|
end
|
48
48
|
|
49
49
|
def cancel_path
|
50
50
|
@cancel_path ||=
|
51
|
-
|
51
|
+
"/Services/V%02d/SureTax.asmx/CancelPostRequest" % cancel_version
|
52
52
|
end
|
53
53
|
|
54
54
|
private
|
55
55
|
|
56
56
|
def test_host
|
57
|
-
|
57
|
+
"https://testapi.taxrating.net"
|
58
58
|
end
|
59
59
|
|
60
60
|
def register_currencies
|
@@ -63,22 +63,19 @@ module Suretax
|
|
63
63
|
|
64
64
|
def register_dollar_with_six_decimal_places
|
65
65
|
Money::Currency.register(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
symbolize_names: true
|
79
|
-
}
|
66
|
+
priority: 1,
|
67
|
+
iso_code: "US6",
|
68
|
+
iso_numeric: "840",
|
69
|
+
name: "Dollar with six decimal places",
|
70
|
+
symbol: "$",
|
71
|
+
subunit: "Cent",
|
72
|
+
subunit_to_unit: 1_000_000,
|
73
|
+
symbol_first: true,
|
74
|
+
html_entity: "$",
|
75
|
+
decimal_mark: ".",
|
76
|
+
thousands_separator: ",",
|
77
|
+
symbolize_names: true
|
80
78
|
)
|
81
79
|
end
|
82
|
-
|
83
80
|
end
|
84
81
|
end
|
data/lib/suretax/connection.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "uri"
|
2
|
+
require "json"
|
3
3
|
|
4
4
|
module Suretax
|
5
|
-
|
6
5
|
class Connection
|
7
6
|
attr_accessor :headers
|
8
7
|
|
9
8
|
def initialize(args = {})
|
10
9
|
@link = Excon.new(args[:base_url] || api_host)
|
11
|
-
@headers = {
|
10
|
+
@headers = { "Content-Type" => "application/x-www-form-urlencoded" }
|
12
11
|
end
|
13
12
|
|
14
13
|
def post(body = {})
|
@@ -46,5 +45,4 @@ module Suretax
|
|
46
45
|
Suretax.configuration
|
47
46
|
end
|
48
47
|
end
|
49
|
-
|
50
48
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Suretax
|
2
2
|
REGULATORY_CODES = {
|
3
|
-
ilec:
|
4
|
-
ixc:
|
5
|
-
clec:
|
6
|
-
voip:
|
7
|
-
isp:
|
8
|
-
wireless:
|
9
|
-
default:
|
10
|
-
}
|
3
|
+
ilec: "00",
|
4
|
+
ixc: "01",
|
5
|
+
clec: "02",
|
6
|
+
voip: "03",
|
7
|
+
isp: "04",
|
8
|
+
wireless: "05",
|
9
|
+
default: "99"
|
10
|
+
}.freeze
|
11
11
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Suretax
|
2
|
-
RESPONSE_GROUPS = {
|
3
|
-
by_state:
|
4
|
-
by_state_and_invoice:
|
5
|
-
by_state_and_customer:
|
6
|
-
by_state_and_customer_and_invoice:
|
7
|
-
}
|
2
|
+
RESPONSE_GROUPS = {
|
3
|
+
by_state: "00",
|
4
|
+
by_state_and_invoice: "01",
|
5
|
+
by_state_and_customer: "02",
|
6
|
+
by_state_and_customer_and_invoice: "03"
|
7
|
+
}.freeze
|
8
8
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Suretax
|
2
|
-
TAX_SITUS_RULES =
|
3
|
-
two_of_three:
|
4
|
-
billed_to_number:
|
5
|
-
origination_number:
|
6
|
-
billing_zip:
|
7
|
-
billing_zip_plus_4:
|
8
|
-
private_lines:
|
9
|
-
point_to_point:
|
10
|
-
vat:
|
11
|
-
}
|
2
|
+
TAX_SITUS_RULES = {
|
3
|
+
two_of_three: "01",
|
4
|
+
billed_to_number: "02",
|
5
|
+
origination_number: "03",
|
6
|
+
billing_zip: "04",
|
7
|
+
billing_zip_plus_4: "05",
|
8
|
+
private_lines: "06",
|
9
|
+
point_to_point: "07",
|
10
|
+
vat: "14"
|
11
|
+
}.freeze
|
12
12
|
end
|