super_good-solidus_taxjar 0.17.1 → 0.18.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -13
  3. data/.travis.yml +11 -5
  4. data/CHANGELOG.md +30 -0
  5. data/Gemfile +21 -5
  6. data/LICENSE +26 -0
  7. data/PULL_REQUEST_TEMPLATE.md +19 -0
  8. data/README.md +20 -11
  9. data/Rakefile +4 -17
  10. data/bin/rails +7 -0
  11. data/bin/rails-engine +13 -0
  12. data/bin/rails-sandbox +16 -0
  13. data/bin/rake +7 -0
  14. data/bin/sandbox +84 -0
  15. data/lib/super_good-solidus_taxjar.rb +4 -0
  16. data/lib/super_good/engine.rb +8 -0
  17. data/lib/super_good/solidus_taxjar.rb +11 -6
  18. data/lib/super_good/solidus_taxjar/addresses.rb +63 -0
  19. data/lib/super_good/solidus_taxjar/api.rb +20 -11
  20. data/lib/super_good/solidus_taxjar/api_params.rb +19 -9
  21. data/lib/super_good/solidus_taxjar/calculator_helper.rb +4 -10
  22. data/lib/super_good/solidus_taxjar/discount_calculator.rb +1 -1
  23. data/lib/super_good/solidus_taxjar/tax_calculator.rb +12 -12
  24. data/lib/super_good/solidus_taxjar/tax_rate_calculator.rb +6 -7
  25. data/lib/super_good/solidus_taxjar/version.rb +2 -2
  26. data/spec/spec_helper.rb +20 -0
  27. data/spec/super_good/solidus_taxjar/addresses_spec.rb +288 -0
  28. data/spec/super_good/solidus_taxjar/api_params_spec.rb +402 -0
  29. data/spec/super_good/solidus_taxjar/api_spec.rb +205 -0
  30. data/spec/super_good/solidus_taxjar/discount_calculator_spec.rb +13 -0
  31. data/spec/super_good/solidus_taxjar/tax_calculator_spec.rb +332 -0
  32. data/spec/super_good/solidus_taxjar/tax_rate_calculator_spec.rb +116 -0
  33. data/spec/super_good/solidus_taxjar_spec.rb +77 -0
  34. data/super_good-solidus_taxjar.gemspec +17 -14
  35. metadata +35 -10
  36. data/LICENSE.txt +0 -21
@@ -0,0 +1,288 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe SuperGood::SolidusTaxjar::Addresses do
4
+ describe "#normalize" do
5
+ subject { described_class.new(api: dummy_api).normalize(spree_address) }
6
+
7
+ let(:spree_address) {
8
+ create(
9
+ :address,
10
+ address1: "475 North Beverly Drive",
11
+ city: "Los Angeles",
12
+ country: country_us,
13
+ first_name: "Chuck",
14
+ last_name: "Schuldiner",
15
+ phone: "1-250-555-4444",
16
+ state: state_california,
17
+ zipcode: "90210"
18
+ )
19
+ }
20
+
21
+ let(:country_us) {
22
+ Spree::Country.create!(
23
+ iso3: "USA",
24
+ iso: "US",
25
+ iso_name: "UNITED STATES",
26
+ name: "United States",
27
+ numcode: 840,
28
+ states_required: true
29
+ )
30
+ }
31
+
32
+ let(:state_california) {
33
+ Spree::State.create!(
34
+ abbr: "CA",
35
+ country: country_us,
36
+ name: "California"
37
+ )
38
+ }
39
+
40
+ let(:dummy_api) {
41
+ instance_double ::SuperGood::SolidusTaxjar::Api
42
+ }
43
+
44
+ context "when there are no possibilities for the address" do
45
+ before do
46
+ allow(dummy_api)
47
+ .to receive(:validate_spree_address)
48
+ .with(spree_address)
49
+ .and_raise(Taxjar::Error::NotFound)
50
+ end
51
+
52
+ it { is_expected.to be_nil }
53
+ end
54
+
55
+ context "when there is one possibility for the address" do
56
+ before do
57
+ allow(dummy_api)
58
+ .to receive(:validate_spree_address)
59
+ .with(spree_address)
60
+ .and_return(results)
61
+ end
62
+
63
+ let(:results) {
64
+ [
65
+ Taxjar::Address.new(
66
+ country: "US",
67
+ state: "CA",
68
+ zip: "90210-4606",
69
+ city: "Beverly Hills",
70
+ street: "475 N Beverly Dr"
71
+ )
72
+ ]
73
+ }
74
+
75
+ it "returns a sanitized address" do
76
+ expect(subject).to eq(
77
+ build(
78
+ :address,
79
+ address1: "475 N Beverly Dr",
80
+ city: "Beverly Hills",
81
+ country: country_us,
82
+ first_name: "Chuck",
83
+ last_name: "Schuldiner",
84
+ phone: "1-250-555-4444",
85
+ state: state_california,
86
+ zipcode: "90210-4606"
87
+ )
88
+ )
89
+ end
90
+ end
91
+
92
+ context "when there are multiple possibilities for the address" do
93
+ before do
94
+ allow(dummy_api)
95
+ .to receive(:validate_spree_address)
96
+ .with(spree_address)
97
+ .and_return(results)
98
+ end
99
+
100
+ let(:results) {
101
+ [
102
+ Taxjar::Address.new(
103
+ country: "US",
104
+ state: "CA",
105
+ zip: "90210-4606",
106
+ city: "Beverly Hills",
107
+ street: "475 N Beverly Dr"
108
+ ),
109
+ Taxjar::Address.new(
110
+ country: "US",
111
+ state: "AZ",
112
+ zip: "90213-4606",
113
+ city: "Beverly Hills",
114
+ street: "475 N Beverly Dr"
115
+ )
116
+ ]
117
+ }
118
+
119
+ it "uses the first result to sanitize the addresses" do
120
+ expect(subject).to eq(
121
+ build(
122
+ :address,
123
+ address1: "475 N Beverly Dr",
124
+ city: "Beverly Hills",
125
+ country: country_us,
126
+ first_name: "Chuck",
127
+ last_name: "Schuldiner",
128
+ phone: "1-250-555-4444",
129
+ state: state_california,
130
+ zipcode: "90210-4606"
131
+ )
132
+ )
133
+ end
134
+ end
135
+ end
136
+
137
+ describe "#normalize" do
138
+ subject { described_class.new(api: dummy_api).possibilities(spree_address) }
139
+
140
+ let(:spree_address) {
141
+ create(
142
+ :address,
143
+ address1: "475 North Beverly Drive",
144
+ city: "Los Angeles",
145
+ country: country_us,
146
+ first_name: "Chuck",
147
+ last_name: "Schuldiner",
148
+ phone: "1-250-555-4444",
149
+ state: state_california,
150
+ zipcode: "90210"
151
+ )
152
+ }
153
+
154
+ let(:country_us) {
155
+ Spree::Country.create!(
156
+ iso3: "USA",
157
+ iso: "US",
158
+ iso_name: "UNITED STATES",
159
+ name: "United States",
160
+ numcode: 840,
161
+ states_required: true
162
+ )
163
+ }
164
+
165
+ let(:state_california) {
166
+ Spree::State.create!(
167
+ abbr: "CA",
168
+ country: country_us,
169
+ name: "California"
170
+ )
171
+ }
172
+
173
+ let(:dummy_api) {
174
+ instance_double ::SuperGood::SolidusTaxjar::Api
175
+ }
176
+
177
+ context "when there are no possibilities for the address" do
178
+ before do
179
+ allow(dummy_api)
180
+ .to receive(:validate_spree_address)
181
+ .with(spree_address)
182
+ .and_raise(Taxjar::Error::NotFound)
183
+ end
184
+
185
+ it { is_expected.to be_empty }
186
+ end
187
+
188
+ context "when there is one possibility for the address" do
189
+ before do
190
+ allow(dummy_api)
191
+ .to receive(:validate_spree_address)
192
+ .with(spree_address)
193
+ .and_return(results)
194
+ end
195
+
196
+ let(:results) {
197
+ [
198
+ Taxjar::Address.new(
199
+ country: "US",
200
+ state: "CA",
201
+ zip: "90210-4606",
202
+ city: "Beverly Hills",
203
+ street: "475 N Beverly Dr"
204
+ )
205
+ ]
206
+ }
207
+
208
+ it "returns the possibilities" do
209
+ expect(subject).to eq([
210
+ build(
211
+ :address,
212
+ address1: "475 N Beverly Dr",
213
+ city: "Beverly Hills",
214
+ country: country_us,
215
+ first_name: "Chuck",
216
+ last_name: "Schuldiner",
217
+ phone: "1-250-555-4444",
218
+ state: state_california,
219
+ zipcode: "90210-4606"
220
+ )
221
+ ])
222
+ end
223
+ end
224
+
225
+ context "when there are multiple possibilities for the address" do
226
+ before do
227
+ allow(dummy_api)
228
+ .to receive(:validate_spree_address)
229
+ .with(spree_address)
230
+ .and_return(results)
231
+ end
232
+
233
+ let(:results) {
234
+ [
235
+ Taxjar::Address.new(
236
+ country: "US",
237
+ state: "CA",
238
+ zip: "90210-4606",
239
+ city: "Beverly Hills",
240
+ street: "475 N Beverly Dr"
241
+ ),
242
+ Taxjar::Address.new(
243
+ country: "US",
244
+ state: "AZ",
245
+ zip: "90213-1234",
246
+ city: "Phoenix",
247
+ street: "473 N Beverly Dr"
248
+ )
249
+ ]
250
+ }
251
+
252
+ let!(:state_arizona) {
253
+ Spree::State.create!(
254
+ abbr: "AZ",
255
+ country: country_us,
256
+ name: "Arizona"
257
+ )
258
+ }
259
+
260
+ it "returns all the possibilities" do
261
+ expect(subject).to eq([
262
+ build(
263
+ :address,
264
+ address1: "475 N Beverly Dr",
265
+ city: "Beverly Hills",
266
+ country: country_us,
267
+ first_name: "Chuck",
268
+ last_name: "Schuldiner",
269
+ phone: "1-250-555-4444",
270
+ state: state_california,
271
+ zipcode: "90210-4606"
272
+ ),
273
+ build(
274
+ :address,
275
+ address1: "473 N Beverly Dr",
276
+ city: "Phoenix",
277
+ country: country_us,
278
+ first_name: "Chuck",
279
+ last_name: "Schuldiner",
280
+ phone: "1-250-555-4444",
281
+ state: state_arizona,
282
+ zipcode: "90213-1234"
283
+ )
284
+ ])
285
+ end
286
+ end
287
+ end
288
+ end
@@ -0,0 +1,402 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe SuperGood::SolidusTaxjar::ApiParams do
4
+ let(:order) do
5
+ Spree::Order.create!(
6
+ additional_tax_total: BigDecimal("9.87"),
7
+ item_total: BigDecimal("28.00"),
8
+ line_items: [line_item],
9
+ number: "R111222333",
10
+ ship_address: ship_address,
11
+ shipment_total: BigDecimal("3.01"),
12
+ store: store,
13
+ total: order_total,
14
+ user_id: 12345
15
+ ).tap do |order|
16
+ order.update! completed_at: DateTime.new(2018, 3, 6, 12, 10, 33)
17
+ end
18
+ end
19
+ let(:order_total) { BigDecimal("123.45") }
20
+
21
+ let(:store) do
22
+ Spree::Store.create!(
23
+ cart_tax_country_iso: "US",
24
+ code: "store",
25
+ mail_from_address: "contact@example.com",
26
+ name: "Default Store",
27
+ url: "https://store.example.com"
28
+ )
29
+ end
30
+
31
+ let(:ship_address) do
32
+ Spree::Address.create!(
33
+ address1: "475 N Beverly Dr",
34
+ city: "Los Angeles",
35
+ country: country_us,
36
+ first_name: "Chuck",
37
+ last_name: "Schuldiner",
38
+ phone: "1-250-555-4444",
39
+ state: state_california,
40
+ zipcode: "90210"
41
+ )
42
+ end
43
+
44
+ let(:country_us) do
45
+ Spree::Country.create!(
46
+ iso3: "USA",
47
+ iso: "US",
48
+ iso_name: "UNITED STATES",
49
+ name: "United States",
50
+ numcode: 840,
51
+ states_required: true
52
+ )
53
+ end
54
+
55
+ let(:state_california) do
56
+ Spree::State.create!(
57
+ abbr: "CA",
58
+ country: country_us,
59
+ name: "California"
60
+ )
61
+ end
62
+
63
+ let(:line_item) do
64
+ Spree::LineItem.new(
65
+ additional_tax_total: 4,
66
+ price: 10,
67
+ promo_total: -2,
68
+ quantity: 3,
69
+ variant: variant
70
+ )
71
+ end
72
+
73
+ let(:variant) do
74
+ Spree::Variant.create!(
75
+ price: 10,
76
+ product: product,
77
+ sku: "G00D-PR0DUCT"
78
+ )
79
+ end
80
+
81
+ let(:product) do
82
+ Spree::Product.create!(
83
+ master: master_variant,
84
+ name: "Product Name",
85
+ shipping_category: shipping_category,
86
+ tax_category: tax_category,
87
+ variants: [master_variant]
88
+ )
89
+ end
90
+
91
+ let(:shipping_category) do
92
+ Spree::ShippingCategory.create!(name: "Default Category")
93
+ end
94
+
95
+ let(:tax_category) do
96
+ Spree::TaxCategory.create!(
97
+ is_default: true,
98
+ name: "Default",
99
+ tax_code: "A_GEN_TAX"
100
+ )
101
+ end
102
+
103
+ let(:master_variant) do
104
+ Spree::Variant.new(
105
+ is_master: true,
106
+ price: 10
107
+ )
108
+ end
109
+
110
+ let(:reimbursement) do
111
+ Spree::Reimbursement.new(
112
+ number: "RI123123123",
113
+ order: order,
114
+ return_items: [
115
+ Spree::ReturnItem.new(additional_tax_total: 0.33),
116
+ Spree::ReturnItem.new(additional_tax_total: 33.0)
117
+ ],
118
+ total: 333.33
119
+ )
120
+ end
121
+
122
+ describe "#order_params" do
123
+ subject { described_class.order_params(order) }
124
+
125
+ it "returns params for fetching the tax for the order" do
126
+ expect(subject).to eq(
127
+ customer_id: "12345",
128
+ line_items: [{
129
+ discount: 2.00,
130
+ id: order.line_items.first.id,
131
+ product_tax_code: "A_GEN_TAX",
132
+ quantity: 3,
133
+ unit_price: 10.00
134
+ }],
135
+ shipping: 3.01,
136
+ to_city: "Los Angeles",
137
+ to_country: "US",
138
+ to_state: "CA",
139
+ to_street: "475 N Beverly Dr",
140
+ to_zip: "90210"
141
+ )
142
+ end
143
+
144
+ context "when custom params are used" do
145
+ around do |example|
146
+ default = SuperGood::SolidusTaxjar.custom_order_params
147
+ SuperGood::SolidusTaxjar.custom_order_params = ->(order) {
148
+ {
149
+ nexus_addresses: [
150
+ {
151
+ id: "Main Location",
152
+ country: "AU",
153
+ zip: "NSW 2000",
154
+ city: "Sydney",
155
+ street: "483 George St"
156
+ }
157
+ ]
158
+ }
159
+ }
160
+ example.run
161
+ SuperGood::SolidusTaxjar.custom_order_params = default
162
+ end
163
+
164
+ it "returns params for fetching the tax for the order" do
165
+ expect(subject).to eq(
166
+ customer_id: "12345",
167
+ line_items: [{
168
+ discount: 2.00,
169
+ id: order.line_items.first.id,
170
+ product_tax_code: "A_GEN_TAX",
171
+ quantity: 3,
172
+ unit_price: 10.00
173
+ }],
174
+ nexus_addresses: [{
175
+ id: "Main Location",
176
+ country: "AU",
177
+ zip: "NSW 2000",
178
+ city: "Sydney",
179
+ street: "483 George St"
180
+ }],
181
+ shipping: 3.01,
182
+ to_city: "Los Angeles",
183
+ to_country: "US",
184
+ to_state: "CA",
185
+ to_street: "475 N Beverly Dr",
186
+ to_zip: "90210"
187
+ )
188
+ end
189
+ end
190
+
191
+ context "when the line item has zero quantity" do
192
+ let(:line_item) do
193
+ Spree::LineItem.new(
194
+ additional_tax_total: 4,
195
+ price: 10,
196
+ promo_total: -2,
197
+ quantity: 0,
198
+ variant: variant
199
+ )
200
+ end
201
+
202
+ it "excludes the line item" do
203
+ expect(subject).to eq(
204
+ customer_id: "12345",
205
+ line_items: [],
206
+ shipping: 3.01,
207
+ to_city: "Los Angeles",
208
+ to_country: "US",
209
+ to_state: "CA",
210
+ to_street: "475 N Beverly Dr",
211
+ to_zip: "90210"
212
+ )
213
+ end
214
+ end
215
+ end
216
+
217
+ describe "#address_params" do
218
+ subject { described_class.address_params(ship_address) }
219
+
220
+ it "returns params for fetching the tax info for that address" do
221
+ expect(subject).to eq([
222
+ "90210",
223
+ {
224
+ city: "Los Angeles",
225
+ country: "US",
226
+ state: "CA",
227
+ street: "475 N Beverly Dr"
228
+ }
229
+ ])
230
+ end
231
+ end
232
+
233
+ describe "#tax_rate_address_params" do
234
+ subject { described_class.tax_rate_address_params(ship_address) }
235
+
236
+ it "returns params for fetching the tax rate for that address" do
237
+ expect(subject).to eq(
238
+ {
239
+ amount: 100,
240
+ shipping: 0,
241
+ to_city: "Los Angeles",
242
+ to_country: "US",
243
+ to_state: "CA",
244
+ to_street: "475 N Beverly Dr",
245
+ to_zip: "90210"
246
+ }
247
+ )
248
+ end
249
+ end
250
+
251
+ describe "#transaction_params" do
252
+ subject { described_class.transaction_params(order) }
253
+
254
+ it "returns params for creating/updating an order transaction" do
255
+ expect(subject).to eq({
256
+ amount: BigDecimal("113.58"),
257
+ customer_id: "12345",
258
+ line_items: [{
259
+ discount: 2,
260
+ id: line_item.id,
261
+ product_identifier: "G00D-PR0DUCT",
262
+ product_tax_code: "A_GEN_TAX",
263
+ quantity: 3,
264
+ sales_tax: 4,
265
+ unit_price: 10
266
+ }],
267
+ sales_tax: BigDecimal("9.87"),
268
+ shipping: BigDecimal("3.01"),
269
+ to_city: "Los Angeles",
270
+ to_country: "US",
271
+ to_state: "CA",
272
+ to_street: "475 N Beverly Dr",
273
+ to_zip: "90210",
274
+ transaction_date: "2018-03-06T12:10:33Z",
275
+ transaction_id: "R111222333"
276
+ })
277
+ end
278
+
279
+ context "when the order is adjusted to 0" do
280
+ let(:order_total) { BigDecimal("0") }
281
+
282
+ it "sends the order total as zero" do
283
+ expect(subject[:amount]).to be_zero
284
+ end
285
+
286
+ it "sends the sales tax total as zero" do
287
+ expect(subject[:sales_tax]).to be_zero
288
+ end
289
+
290
+ it "sends the sales tax on the line items as zero" do
291
+ expect(subject[:line_items]).to contain_exactly({
292
+ discount: 2,
293
+ id: line_item.id,
294
+ product_identifier: "G00D-PR0DUCT",
295
+ product_tax_code: "A_GEN_TAX",
296
+ quantity: 3,
297
+ sales_tax: 0,
298
+ unit_price: 10
299
+ })
300
+ end
301
+ end
302
+
303
+ context "when the line item has 0 quantity" do
304
+ let(:line_item) do
305
+ Spree::LineItem.new(
306
+ additional_tax_total: 4,
307
+ price: 10,
308
+ promo_total: -2,
309
+ quantity: 0,
310
+ variant: variant
311
+ )
312
+ end
313
+
314
+ it "excludes the line item" do
315
+ expect(subject).to eq({
316
+ amount: BigDecimal("113.58"),
317
+ customer_id: "12345",
318
+ line_items: [],
319
+ sales_tax: BigDecimal("9.87"),
320
+ shipping: BigDecimal("3.01"),
321
+ to_city: "Los Angeles",
322
+ to_country: "US",
323
+ to_state: "CA",
324
+ to_street: "475 N Beverly Dr",
325
+ to_zip: "90210",
326
+ transaction_date: "2018-03-06T12:10:33Z",
327
+ transaction_id: "R111222333"
328
+ })
329
+ end
330
+ end
331
+ end
332
+
333
+ describe "#refund_params" do
334
+ subject { described_class.refund_params(reimbursement) }
335
+
336
+ it "returns params for creating/updating a refund" do
337
+ expect(subject).to eq({
338
+ amount: BigDecimal("300.00"),
339
+ sales_tax: BigDecimal("33.33"),
340
+ shipping: 0,
341
+ to_city: "Los Angeles",
342
+ to_country: "US",
343
+ to_state: "CA",
344
+ to_street: "475 N Beverly Dr",
345
+ to_zip: "90210",
346
+ transaction_date: "2018-03-06T12:10:33Z",
347
+ transaction_id: "RI123123123",
348
+ transaction_reference_id: "R111222333"
349
+ })
350
+ end
351
+ end
352
+
353
+ describe "#validate_address_params" do
354
+ subject { described_class.validate_address_params(ship_address) }
355
+
356
+ it "returns params for validating an address" do
357
+ expect(subject).to eq({
358
+ country: "US",
359
+ state: "CA",
360
+ zip: "90210",
361
+ city: "Los Angeles",
362
+ street: "475 N Beverly Dr"
363
+ })
364
+ end
365
+
366
+ context "with an address without a state" do
367
+ let(:ship_address) do
368
+ Spree::Address.create!(
369
+ address1: "72 High St",
370
+ city: "Birmingham",
371
+ country: country_uk,
372
+ first_name: "Chuck",
373
+ last_name: "Schuldiner",
374
+ phone: "1-250-555-4444",
375
+ state_name: "West Midlands",
376
+ zipcode: "B4 7TA"
377
+ )
378
+ end
379
+
380
+ let(:country_uk) do
381
+ Spree::Country.create!(
382
+ iso3: "GBR",
383
+ iso: "GB",
384
+ iso_name: "UNITED KINGDOM",
385
+ name: "United Kingdom",
386
+ numcode: 826,
387
+ states_required: false
388
+ )
389
+ end
390
+
391
+ it "uses the state_name to build address params" do
392
+ expect(subject).to eq({
393
+ country: "GB",
394
+ state: "West Midlands",
395
+ zip: "B4 7TA",
396
+ city: "Birmingham",
397
+ street: "72 High St"
398
+ })
399
+ end
400
+ end
401
+ end
402
+ end