taxjar-ruby 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.
@@ -0,0 +1,16 @@
1
+ require 'taxjar/base'
2
+ require 'taxjar/shipping'
3
+
4
+ module Taxjar
5
+ class Breakdown < Taxjar::Base
6
+ attr_reader :state_taxable_amount, :state_tax_collectable, :county_taxable_amount,
7
+ :county_tax_collectable, :city_tax_collectable,
8
+ :special_district_taxable_amount, :special_district_tax_collectable
9
+
10
+ object_attr_reader Taxjar::Shipping, :shipping
11
+
12
+ def line_items
13
+ @line_items ||= map_collection(Taxjar::BreakdownLineItem, :line_items)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class BreakdownLineItem < Taxjar::Base
5
+ attr_reader :id, :state_taxable_amount, :state_sales_tax_rate, :county_taxable_amount,
6
+ :county_tax_rate, :city_taxable_amount, :city_tax_rate, :special_district_taxable_amount
7
+ :special_tax_rate
8
+
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Category < Taxjar::Base
5
+ attr_reader :name, :product_tax_code, :description
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'taxjar/api/api'
2
+ require 'taxjar/error'
3
+ require 'taxjar/api/request'
4
+ require 'taxjar/api/utils'
5
+ module Taxjar
6
+ class Client
7
+ include Taxjar::API
8
+ attr_accessor :api_key
9
+
10
+ def initialize(options = {})
11
+ options.each do |key, value|
12
+ instance_variable_set("@#{key}", value)
13
+ end
14
+ yield(self) if block_given?
15
+ end
16
+
17
+ def api_key?
18
+ !!@api_key
19
+ end
20
+
21
+ def user_agent
22
+ "TaxjarRubyGem/#{Taxjar::Version}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,74 @@
1
+ module Taxjar
2
+ class Error < StandardError
3
+ attr_reader :code
4
+
5
+ ClientError = Class.new(self)
6
+
7
+ ServerError = Class.new(self)
8
+
9
+ # Raised when Taxjar endpoint returns the HTTP status code 400
10
+ BadRequest = Class.new(ClientError)
11
+
12
+ # Raised when Taxjar endpoint returns the HTTP status code 401
13
+ Unauthorized = Class.new(ClientError)
14
+
15
+ # Raised when Taxjar endpoint returns the HTTP status code 403
16
+ Forbidden = Class.new(ClientError)
17
+
18
+ # Raised when Taxjar endpoint returns the HTTP status code 404
19
+ NotFound = Class.new(ClientError)
20
+
21
+ # Raised when Taxjar endpoint returns the HTTP status code 405
22
+ MethodNotAllowed = Class.new(ClientError)
23
+
24
+ # Raised when Taxjar endpoint returns the HTTP status code 406
25
+ NotAcceptable = Class.new(ClientError)
26
+
27
+ # Raised when Taxjar endpoint returns the HTTP status code 410
28
+ Gone = Class.new(ClientError)
29
+
30
+ # Raised when Taxjar endpoint returns the HTTP status code 422
31
+ UnprocessableEntity = Class.new(ClientError)
32
+
33
+ # Raised when Taxjar endpoint returns the HTTP status code 429
34
+ TooManyRequests = Class.new(ClientError)
35
+
36
+ # Raised when Taxjar endpoint returns the HTTP status code 500
37
+ InternalServerError = Class.new(ServerError)
38
+
39
+ # Raised when Taxjar endpoint returns the HTTP status code 503
40
+ ServiceUnavailable = Class.new(ServerError)
41
+
42
+ ERRORS = {
43
+ 400 => Taxjar::Error::BadRequest,
44
+ 401 => Taxjar::Error::Unauthorized,
45
+ 403 => Taxjar::Error::Forbidden,
46
+ 404 => Taxjar::Error::NotFound,
47
+ 405 => Taxjar::Error::MethodNotAllowed,
48
+ 406 => Taxjar::Error::NotAcceptable,
49
+ 410 => Taxjar::Error::Gone,
50
+ 422 => Taxjar::Error::UnprocessableEntity,
51
+ 429 => Taxjar::Error::TooManyRequests,
52
+ 500 => Taxjar::Error::InternalServerError,
53
+ 503 => Taxjar::Error::ServiceUnavailable
54
+ }
55
+
56
+ class << self
57
+
58
+ def from_response(body)
59
+ code = body[:status]
60
+ message = body[:detail]
61
+ new(message, code)
62
+ end
63
+
64
+ end
65
+
66
+ def initialize(message = '', code = nil)
67
+ super(message)
68
+ @code = code
69
+ end
70
+
71
+ ConfigurationError = Class.new(::ArgumentError)
72
+
73
+ end
74
+ end
@@ -0,0 +1,9 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class LineItem < Taxjar::Base
5
+ attr_reader :quantity, :product_identifier, :description, :unit_price, :discount,
6
+ :sales_tax
7
+
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Order < Taxjar::Base
5
+ attr_reader :transaction_id, :user_id, :transaction_date, :to_country, :to_zip,
6
+ :to_state, :to_city, :to_street, :amount, :shipping, :sales_tax
7
+
8
+ def line_items
9
+ @line_items ||= map_collection(Taxjar::LineItem, :line_items)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Rate < Taxjar::Base
5
+ attr_reader :zip, :state, :state_rate, :county, :city, :city_rate,
6
+ :combined_distric_rate, :combined_rate
7
+
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Refund < Taxjar::Base
5
+
6
+ attr_reader :transaction_id, :user_id, :transaction_date, :transaction_reference_id, :to_country, :to_zip,
7
+ :to_state, :to_city, :to_street, :amount, :shipping, :sales_tax
8
+
9
+ def line_items
10
+ @line_items ||= map_collection(Taxjar::LineItem, :line_items)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Shipping < Taxjar::Base
5
+ attr_reader :state_amount, :state_sales_tax_rate, :county_amount, :county_tax_rate,
6
+ :city_amount, :city_tax_rate, :special_district_amount, :special_tax_rate
7
+
8
+ end
9
+ end
data/lib/taxjar/tax.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'taxjar/base'
2
+
3
+ module Taxjar
4
+ class Tax < Taxjar::Base
5
+ attr_reader :order_total_amount, :amount_to_collect, :has_nexus,
6
+ :freight_taxable, :tax_source
7
+
8
+ object_attr_reader Taxjar::Breakdown, :brekdown
9
+
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ module Taxjar
2
+ module Version
3
+ module_function
4
+
5
+ def major
6
+ 1
7
+ end
8
+
9
+ def minor
10
+ 0
11
+ end
12
+
13
+ def patch
14
+ 0
15
+ end
16
+
17
+ def pre
18
+ nil
19
+ end
20
+
21
+ def to_h
22
+ {
23
+ major: major,
24
+ minor: minor,
25
+ patch: patch,
26
+ pre: pre,
27
+ }
28
+ end
29
+
30
+ def to_a
31
+ to_h.values.compact
32
+ end
33
+
34
+ def to_s
35
+ to_a.join('.')
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ {
2
+ "categories": [
3
+ {
4
+ "name": "Digital Goods",
5
+ "product_tax_code": "31000",
6
+ "description": "Digital products transferred electronically, meaning obtained by the purchaser by means other than tangible storage media."
7
+ },
8
+ {
9
+ "name": "Clothing",
10
+ "product_tax_code": "20010",
11
+ "description": " All human wearing apparel suitable for general use"
12
+ },
13
+ {
14
+ "name": "Non-Prescription",
15
+ "product_tax_code": "51010",
16
+ "description": "Drugs for human use without a prescription"
17
+ },
18
+ {
19
+ "name": "Prescription",
20
+ "product_tax_code": "51020",
21
+ "description": "Drugs for human use with a prescription"
22
+ },
23
+ {
24
+ "name": "Food & Groceries",
25
+ "product_tax_code": "40030",
26
+ "description": "Food for humans consumption, unprepared"
27
+ },
28
+ {
29
+ "name": "Other Exempt",
30
+ "product_tax_code": "99999",
31
+ "description": "Item is exempt"
32
+ },
33
+ {
34
+ "name": "Software as a Service",
35
+ "product_tax_code": "30070",
36
+ "description": "Pre-written software, delivered electronically, but access remotely."
37
+ }
38
+ ]
39
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "order": {
3
+ "transaction_id": "123",
4
+ "user_id": 10649,
5
+ "transaction_date": "2015-05-14T00:00:00Z",
6
+ "to_country": "US",
7
+ "to_zip": "90002",
8
+ "to_state": "CA",
9
+ "to_city": "LOS ANGELES",
10
+ "to_street": "123 Palm Grove Ln",
11
+ "amount": "17.45",
12
+ "shipping": "1.5",
13
+ "sales_tax": "0.95",
14
+ "line_items": [
15
+ {
16
+ "id": 1,
17
+ "quantity": 1,
18
+ "product_identifier": "12-34243-9",
19
+ "description": "Fuzzy Widget",
20
+ "unit_price": "15.0",
21
+ "discount": "0.0",
22
+ "sales_tax": "0.95"
23
+ }
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "rate": {
3
+ "zip": "90002",
4
+ "state": "CA",
5
+ "state_rate": "0.065",
6
+ "county": "LOS ANGELES",
7
+ "county_rate": "0.01",
8
+ "city": "WATTS",
9
+ "city_rate": "0.0",
10
+ "combined_district_rate": "0.015",
11
+ "combined_rate": "0.09"
12
+ }
13
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "refund": {
3
+ "transaction_id": "321",
4
+ "user_id": 10649,
5
+ "transaction_date": "2015-05-14T00:00:00Z",
6
+ "transaction_reference_id": "123",
7
+ "to_country": "US",
8
+ "to_zip": "90002",
9
+ "to_state": "CA",
10
+ "to_city": "LOS ANGELES",
11
+ "to_street": "123 Palm Grove Ln",
12
+ "amount": "17.45",
13
+ "shipping": "1.5",
14
+ "sales_tax": "0.95",
15
+ "line_items": [
16
+ {
17
+ "id": 1,
18
+ "quantity": 1,
19
+ "product_identifier": "12-34243-9",
20
+ "description": "Fuzzy Widget",
21
+ "unit_price": "15.0",
22
+ "discount": "0.0",
23
+ "sales_tax": "0.95"
24
+ }
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "tax": {
3
+ "order_total_amount": 16.5,
4
+ "amount_to_collect": 1.16,
5
+ "has_nexus": true,
6
+ "freight_taxable": true,
7
+ "tax_source": "destination",
8
+ "breakdown": {
9
+ "shipping": {
10
+ "state_amount": 0.11,
11
+ "state_sales_tax_rate": 0.07,
12
+ "county_amount": 0,
13
+ "county_tax_rate": 0,
14
+ "city_amount": 0,
15
+ "city_tax_rate": 0,
16
+ "special_district_amount": 0,
17
+ "special_tax_rate": 0
18
+ },
19
+ "state_taxable_amount": 16.5,
20
+ "state_tax_collectable": 1.16,
21
+ "county_taxable_amount": 0,
22
+ "county_tax_collectable": 0,
23
+ "city_taxable_amount": 0,
24
+ "city_tax_collectable": 0,
25
+ "special_district_taxable_amount": 0,
26
+ "special_district_tax_collectable": 0,
27
+ "line_items": [
28
+ {
29
+ "id": "1",
30
+ "state_taxable_amount": 15,
31
+ "state_sales_tax_rate": 0.07,
32
+ "county_taxable_amount": 0,
33
+ "county_tax_rate": 0,
34
+ "city_taxable_amount": 0,
35
+ "city_tax_rate": 0,
36
+ "special_district_taxable_amount": 0,
37
+ "special_tax_rate": 0
38
+ }
39
+ ]
40
+ }
41
+ }
42
+ }
data/spec/helper.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'taxjar'
2
+ require 'rspec'
3
+ require 'webmock/rspec'
4
+
5
+ WebMock.disable_net_connect!(allow: 'coveralls.io')
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec do |c|
9
+ c.syntax = :expect
10
+ end
11
+ end
12
+
13
+
14
+ def a_get(path)
15
+ a_request(:get, Taxjar::API::Request::BASE_URL + path)
16
+ end
17
+
18
+ def a_post(path)
19
+ a_request(:post, Taxjar::API::Request::BASE_URL + path)
20
+ end
21
+
22
+ def a_put(path)
23
+ a_request(:put, Taxjar::API::Request::BASE_URL + path)
24
+ end
25
+
26
+ def stub_get(path)
27
+ stub_request(:get, Taxjar::API::Request::BASE_URL + path)
28
+ end
29
+
30
+ def stub_post(path)
31
+ stub_request(:post, Taxjar::API::Request::BASE_URL + path)
32
+ end
33
+
34
+ def stub_put(path)
35
+ stub_request(:put, Taxjar::API::Request::BASE_URL + path)
36
+ end
37
+
38
+ def fixture_path
39
+ File.expand_path('../fixtures', __FILE__)
40
+ end
41
+
42
+ def fixture(file)
43
+ File.new(fixture_path + '/' + file)
44
+ end
45
+