vat-gst-calculator 0.4.9 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 366cf261abb53b08f2be204058b98e37fba5cd53bd33b3fd45833e5b98160d37
4
- data.tar.gz: 3b621d0a89a6d0500b8e3cb84170e39bf88dc5c19e75e27ac741a328c83b5989
3
+ metadata.gz: f39992ff401d87c4d256cbbe7da9ef39e03e134b9e21ca5f4ba258d9ad613497
4
+ data.tar.gz: 118ee1b247f9536cdaf16aad6246ba8d61d48ee817a02ba7510c1245ccf4d52d
5
5
  SHA512:
6
- metadata.gz: 9668b14728ba8a15d4fe0ab473533c61aa8657747ec52e49e33328e1d8d8b088d8eac7acc7b039a39c940d4896dd72bb6cda02147d68c89a3f0114653653b96b
7
- data.tar.gz: 9ed1cf89d9b2aa91de544f340cb9f0d20e860d434ae303e9a69e756107a37206a2b2392c447c0c98a58dfd83937be99244ab6eab35148f3e0faa70ab7b0d8088
6
+ metadata.gz: 8ba20e1380d4264138c446a675d5e1a6b5147e39713dcf7d441b706d09295214a0661f75e47411136f459dbf38843a38443d400d98cfc29e3d748e39ef426199
7
+ data.tar.gz: 490338962e3e8146c6a851aaa4c027a491cc6bb9f276206a00d8687af5b80ab2e7891565d3308086cbd099e5cd71913441124e5590e851519622f211824f531b
data/.gitignore CHANGED
@@ -1,3 +1,6 @@
1
1
  .byebug_history
2
2
  .rspec_status
3
3
  Gemfile.lock
4
+ .idea/*
5
+ *.swp
6
+ tags
@@ -1,7 +1,18 @@
1
+ require "time"
2
+
1
3
  module Easyship
2
4
  module SalesTax
3
5
  module Formula
4
6
  class Error < StandardError; end
7
+
8
+ NO_TAX = {
9
+ shipment_charge_total: 0,
10
+ insurance_fee: 0,
11
+ pickup_fee: 0,
12
+ residential_surcharge: 0
13
+ }.freeze
14
+ DEFAULT_EFFECTIVE_TIMESTAMP = Time.at(0).utc.freeze
15
+
5
16
  class << self
6
17
  def build_fee_struct(shipment_charge_total, insurance_fee, pickup_fee, residential_surcharge)
7
18
  {
@@ -12,23 +23,41 @@ module Easyship
12
23
  }
13
24
  end
14
25
 
15
- def no_taxes
16
- build_fee_struct(0, 0, 0, 0)
26
+ def effective_data(country_alpha2, effective_timestamp = nil)
27
+ data = DOMESTIC.fetch(country_alpha2, [])
28
+
29
+ data.find { |rates| rates[:effective_timestamp] <= effective_time(effective_timestamp) }
30
+ end
31
+
32
+ private
33
+
34
+ def effective_time(effective_timestamp)
35
+ case effective_timestamp
36
+ when String
37
+ Time.parse(effective_timestamp).utc
38
+ when Time
39
+ effective_timestamp
40
+ else
41
+ Time.now.utc
42
+ end
17
43
  end
18
44
  end
19
45
 
20
46
  DOMESTIC = {
21
- 'AU' => {
47
+ 'AU' => [{
48
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
22
49
  sales_tax_website_name: 'GST',
23
- sales_tax: { '_ALL': build_fee_struct(0.1, 0, 0.1, 0) },
24
- provincial_sales_taxes: { '_ALL': no_taxes }
25
- },
26
- 'GB' => {
50
+ sales_tax: {'_ALL': build_fee_struct(0.1, 0, 0.1, 0)},
51
+ provincial_sales_taxes: {'_ALL': NO_TAX}
52
+ }],
53
+ 'GB' => [{
54
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
27
55
  sales_tax_website_name: 'VAT',
28
- sales_tax: { '_ALL': build_fee_struct(0.2, 0, 0.2, 0.2) }, # TBC
29
- provincial_sales_taxes: { '_ALL': no_taxes }
30
- },
31
- 'CA' => {
56
+ sales_tax: {'_ALL': build_fee_struct(0.2, 0, 0.2, 0.2)}, # TBC
57
+ provincial_sales_taxes: {'_ALL': NO_TAX}
58
+ }],
59
+ 'CA' => [{
60
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
32
61
  sales_tax_website_name: 'Taxes',
33
62
  sales_tax: {
34
63
  'AB' => build_fee_struct(0.05, 0, 0.05, 0.05), # Alberta
@@ -46,41 +75,52 @@ module Easyship
46
75
  'YT' => build_fee_struct(0.05, 0, 0.05, 0.05), # Yukon
47
76
  },
48
77
  provincial_sales_taxes: {
49
- 'AB' => no_taxes, # Alberta
50
- 'BC' => no_taxes, # British Columbia
51
- 'MB' => no_taxes, # Manitoba
52
- 'NB' => no_taxes, # New Brunswick
53
- 'NL' => no_taxes, # Newfoundland and Labrador
54
- 'NT' => no_taxes, # Northwest Territories
55
- 'NS' => no_taxes, # Nova Scotia
56
- 'NU' => no_taxes, # Nunavut
57
- 'ON' => no_taxes, # Ontario
58
- 'PE' => no_taxes, # Prince Edward Island
78
+ 'AB' => NO_TAX, # Alberta
79
+ 'BC' => NO_TAX, # British Columbia
80
+ 'MB' => NO_TAX, # Manitoba
81
+ 'NB' => NO_TAX, # New Brunswick
82
+ 'NL' => NO_TAX, # Newfoundland and Labrador
83
+ 'NT' => NO_TAX, # Northwest Territories
84
+ 'NS' => NO_TAX, # Nova Scotia
85
+ 'NU' => NO_TAX, # Nunavut
86
+ 'ON' => NO_TAX, # Ontario
87
+ 'PE' => NO_TAX, # Prince Edward Island
59
88
  'QC' => build_fee_struct(0.09975, 0, 0.09975, 0.09975), # Quebec
60
- 'SK' => no_taxes, # Saskatchewan
61
- 'YT' => no_taxes, # Yukon
89
+ 'SK' => NO_TAX, # Saskatchewan
90
+ 'YT' => NO_TAX, # Yukon
62
91
  }
63
- },
64
- 'SG' => {
65
- sales_tax_website_name: 'GST',
66
- sales_tax: { '_ALL': build_fee_struct(0.07, 0.07, 0.07, 0.07) },
67
- provincial_sales_taxes: { '_ALL': no_taxes }
68
- },
69
- 'HK' => {
92
+ }],
93
+ 'SG' => [
94
+ {
95
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
96
+ sales_tax_website_name: 'GST',
97
+ sales_tax: {'_ALL': build_fee_struct(0.07, 0.07, 0.07, 0.07)},
98
+ provincial_sales_taxes: {'_ALL': NO_TAX}
99
+ },
100
+ {
101
+ effective_timestamp: Time.utc(2023, 1, 1, 8),
102
+ sales_tax_website_name: 'GST',
103
+ sales_tax: {'_ALL': build_fee_struct(0.08, 0.08, 0.08, 0.08)},
104
+ provincial_sales_taxes: {'_ALL': NO_TAX}
105
+ }
106
+ ],
107
+ 'HK' => [{
108
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
70
109
  sales_tax_website_name: nil,
71
- sales_tax: { '_ALL': no_taxes },
72
- provincial_sales_taxes: { '_ALL': no_taxes }
73
- },
110
+ sales_tax: {'_ALL': NO_TAX},
111
+ provincial_sales_taxes: {'_ALL': NO_TAX}
112
+ }],
74
113
  # 'NL' => {
75
114
  # sales_tax_website_name: 'VAT',
76
115
  # sales_tax: { '_ALL': build_fee_struct(0.21, 0, 0.21, 0.21) },
77
116
  # provincial_sales_taxes: { '_ALL': no_taxes }
78
117
  # },
79
- 'US' => {
118
+ 'US' => [{
119
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
80
120
  sales_tax_website_name: nil,
81
- sales_tax: { '_ALL': no_taxes },
82
- provincial_sales_taxes: { '_ALL': no_taxes }
83
- },
121
+ sales_tax: {'_ALL': NO_TAX},
122
+ provincial_sales_taxes: {'_ALL': NO_TAX}
123
+ }],
84
124
  # 'DE' => {
85
125
  # sales_tax_website_name: 'VAT',
86
126
  # sales_tax: { '_ALL': build_fee_struct(0.19, 0, 0, 0) },
@@ -126,11 +166,12 @@ module Easyship
126
166
  # sales_tax: { '_ALL': build_fee_struct(0.2, 0, 0, 0) },
127
167
  # provincial_sales_taxes: { '_ALL': no_taxes }
128
168
  # },
129
- 'AE' => {
169
+ 'AE' => [{
170
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
130
171
  sales_tax_website_name: 'VAT',
131
- sales_tax: { '_ALL': build_fee_struct(0.05, 0, 0, 0) },
132
- provincial_sales_taxes: { '_ALL': no_taxes }
133
- },
172
+ sales_tax: {'_ALL': build_fee_struct(0.05, 0, 0, 0)},
173
+ provincial_sales_taxes: {'_ALL': NO_TAX}
174
+ }],
134
175
  # 'IE' => {
135
176
  # sales_tax_website_name: 'VAT',
136
177
  # sales_tax: { '_ALL': build_fee_struct(0.23, 0, 0, 0) },
@@ -176,11 +217,12 @@ module Easyship
176
217
  # sales_tax: { '_ALL': build_fee_struct(0.1, 0, 0, 0) },
177
218
  # provincial_sales_taxes: { '_ALL': no_taxes }
178
219
  # },
179
- # 'NZ' => {
180
- # sales_tax_website_name: 'VAT',
181
- # sales_tax: { '_ALL': build_fee_struct(0.15, 0, 0, 0) },
182
- # provincial_sales_taxes: { '_ALL': no_taxes }
183
- # },
220
+ 'NZ' => [{
221
+ effective_timestamp: DEFAULT_EFFECTIVE_TIMESTAMP,
222
+ sales_tax_website_name: 'VAT',
223
+ sales_tax: {'_ALL': build_fee_struct(0.15, 0.15, 0.15, 0.15)},
224
+ provincial_sales_taxes: {'_ALL': NO_TAX}
225
+ }],
184
226
  # 'IN' => {
185
227
  # sales_tax_website_name: 'VAT',
186
228
  # sales_tax: { '_ALL': build_fee_struct(0.15, 0, 0, 0) },
@@ -196,7 +238,7 @@ module Easyship
196
238
  # sales_tax: { '_ALL': build_fee_struct(0.16, 0, 0, 0) },
197
239
  # provincial_sales_taxes: { '_ALL': no_taxes }
198
240
  # }
199
- }.freeze
241
+ }.transform_values { |value| value.sort_by { |rates| -rates[:effective_timestamp].to_i } }.freeze
200
242
  end
201
243
  end
202
244
  end
@@ -1,7 +1,7 @@
1
1
  module Easyship
2
2
  module SalesTax
3
3
  module Calculator
4
- VERSION = "0.4.9"
4
+ VERSION = "0.6.0"
5
5
  end
6
6
  end
7
7
  end
@@ -6,33 +6,38 @@ module Easyship
6
6
  module Calculator
7
7
  class Error < StandardError; end
8
8
 
9
- def self.calculate(origin_country_alpha2: nil, destination_country_alpha2: nil, origin_state: nil, destination_state: nil, fees: nil)
10
- return fallback_value if origin_country_alpha2.nil? || origin_country_alpha2.empty? || destination_country_alpha2.nil? || destination_country_alpha2.empty?
11
- return fallback_value unless fees.is_a?(Fee)
9
+ FALLBACK_VALUE = {sales_tax: 0, provincial_sales_tax: 0}.freeze
10
+
11
+ def self.calculate(origin_country_alpha2: nil, destination_country_alpha2: nil, origin_state: nil, destination_state: nil, fees: nil, effective_timestamp: nil)
12
+ return FALLBACK_VALUE if origin_country_alpha2.nil? || origin_country_alpha2.empty? || destination_country_alpha2.nil? || destination_country_alpha2.empty?
13
+ return FALLBACK_VALUE unless fees.is_a?(Fee)
12
14
 
13
15
  if domestic?(origin_country_alpha2, destination_country_alpha2) || within_eu?(origin_country_alpha2, destination_country_alpha2)
14
- domestic_value(origin_country_alpha2: origin_country_alpha2, origin_state: origin_state, destination_state: destination_state, fees: fees)
16
+ domestic_value(origin_country_alpha2: origin_country_alpha2, origin_state: origin_state, destination_state: destination_state, fees: fees, effective_timestamp: effective_timestamp)
15
17
  else
16
- fallback_value
18
+ FALLBACK_VALUE
17
19
  end
18
20
  rescue
19
- fallback_value
21
+ FALLBACK_VALUE
22
+ end
23
+
24
+ def self.sales_tax_website_name(country_alpha2, effective_timestamp = nil)
25
+ rates = Formula.effective_data(country_alpha2, effective_timestamp)
26
+ (rates || {}).dig(:sales_tax_website_name)
20
27
  end
21
28
 
22
- def self.domestic_value(origin_country_alpha2: nil, origin_state: nil, destination_state: nil, fees: nil)
23
- domestic_rates = Formula::DOMESTIC[origin_country_alpha2.to_s]
24
- return fallback_value if domestic_rates.nil? || domestic_rates.empty?
29
+ private
30
+
31
+ def self.domestic_value(origin_country_alpha2: nil, origin_state: nil, destination_state: nil, fees: nil, effective_timestamp: nil)
32
+ rates = Formula.effective_data(origin_country_alpha2, effective_timestamp)
33
+ return FALLBACK_VALUE if rates.nil?
25
34
 
26
35
  {
27
- sales_tax: tax_calculate(domestic_rates[:sales_tax], nil, destination_state, fees, false),
28
- provincial_sales_tax: tax_calculate(domestic_rates[:provincial_sales_taxes], origin_state, destination_state, fees, true)
36
+ sales_tax: tax_calculate(rates[:sales_tax], nil, destination_state, fees, false),
37
+ provincial_sales_tax: tax_calculate(rates[:provincial_sales_taxes], origin_state, destination_state, fees, true)
29
38
  }
30
39
  end
31
40
 
32
- def self.fallback_value
33
- { sales_tax: 0, provincial_sales_tax: 0 }
34
- end
35
-
36
41
  def self.tax_calculate(formula, origin_state, destination_state, fees, is_provincial_sales_taxes)
37
42
  if (tax_destination_formula = formula[destination_state.to_s.upcase])
38
43
  # ONLY CA has provincial_sales_taxes(QST/PST) and it only apply when ship within same state
@@ -46,11 +51,6 @@ module Easyship
46
51
  end
47
52
  end
48
53
 
49
- def self.sales_tax_website_name(country_alpha2)
50
- return if Formula::DOMESTIC[country_alpha2.to_s].nil? || Formula::DOMESTIC[country_alpha2.to_s].empty?
51
- Formula::DOMESTIC[country_alpha2][:sales_tax_website_name]
52
- end
53
-
54
54
  def self.in_eu?(country_alpha2)
55
55
  %w(NL LU EE LT HU BE PT SK HR CZ IT FI PL MT DE SI RO BG AT SE CY DK FR IE ES GR LV).include?(country_alpha2)
56
56
  end
@@ -23,8 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.17"
27
- spec.add_development_dependency "rake", "~> 10.0"
28
26
  spec.add_development_dependency "rspec", "~> 3.0"
29
27
  spec.add_development_dependency "byebug"
30
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vat-gst-calculator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aloha Chen
@@ -9,36 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-01-14 00:00:00.000000000 Z
12
+ date: 2022-12-14 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.17'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: '1.17'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - "~>"
33
- - !ruby/object:Gem::Version
34
- version: '10.0'
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: '10.0'
42
14
  - !ruby/object:Gem::Dependency
43
15
  name: rspec
44
16
  requirement: !ruby/object:Gem::Requirement