death_and_taxes 0.0.1 → 0.0.2
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.
- data/config/ca.yml +33 -0
- data/lib/death_and_taxes/country.rb +37 -0
- data/lib/death_and_taxes/state.rb +37 -0
- data/lib/death_and_taxes/tax.rb +7 -0
- data/lib/death_and_taxes/tax_info.rb +27 -0
- data/lib/death_and_taxes/tax_version.rb +17 -0
- data/lib/death_and_taxes/taxable.rb +6 -1
- data/lib/death_and_taxes/version.rb +1 -1
- data/lib/death_and_taxes.rb +18 -4
- metadata +67 -38
data/config/ca.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
taxes:
|
2
|
+
GST:
|
3
|
+
versions:
|
4
|
+
- starts: 2011-01-01
|
5
|
+
ends: 2011-12-31
|
6
|
+
percentage: 5
|
7
|
+
|
8
|
+
states:
|
9
|
+
qc:
|
10
|
+
rules:
|
11
|
+
same_state: [GST, QST]
|
12
|
+
same_country: GST
|
13
|
+
taxes:
|
14
|
+
QST:
|
15
|
+
apply_on: GST
|
16
|
+
versions:
|
17
|
+
- starts: 2011-01-01
|
18
|
+
ends: 2011-12-31
|
19
|
+
percentage: 8.5
|
20
|
+
|
21
|
+
- starts: 2012-01-01
|
22
|
+
ends: 2012-12-31
|
23
|
+
percentage: 9.5
|
24
|
+
|
25
|
+
on:
|
26
|
+
rules:
|
27
|
+
same_country: HST
|
28
|
+
taxes:
|
29
|
+
HST:
|
30
|
+
versions:
|
31
|
+
- starts: 2011-01-01
|
32
|
+
ends: 2012-12-31
|
33
|
+
percentage: 5
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DeathAndTaxes
|
2
|
+
class Country
|
3
|
+
|
4
|
+
def initialize code, yml = nil
|
5
|
+
@taxes = {}
|
6
|
+
@states = {}
|
7
|
+
@code = code
|
8
|
+
parse yml if yml
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse yml
|
12
|
+
yml['taxes'].each do |tax_name, infos|
|
13
|
+
@taxes[tax_name] = TaxInfo.new(tax_name, infos)
|
14
|
+
end
|
15
|
+
|
16
|
+
yml['states'].each do |state_code, state_yml|
|
17
|
+
@states[state_code] = State.new(state_code, state_yml)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def applicable_taxes from, to, date
|
22
|
+
if from[:country] == to[:country] && to[:country] == @code
|
23
|
+
@states[from[:state]].applicable_taxes to[:state], date
|
24
|
+
else
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def applies_taxes? from, to, date
|
30
|
+
applicable_taxes(from, to, date).any?
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_tax tax, date
|
34
|
+
@taxes[tax].try(:build, date) || @states.map{|t, s| s.build_tax(tax, date)}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DeathAndTaxes
|
2
|
+
class State
|
3
|
+
|
4
|
+
def initialize code, yml = nil
|
5
|
+
@taxes = {}
|
6
|
+
@code = code
|
7
|
+
parse yml if yml
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse yml
|
11
|
+
##
|
12
|
+
# Builds a tax list for each taxes defined in this state
|
13
|
+
yml['taxes'].each do |tax_name, infos|
|
14
|
+
@taxes[tax_name] = TaxInfo.new(tax_name, infos)
|
15
|
+
end
|
16
|
+
|
17
|
+
@rules = yml['rules']
|
18
|
+
end
|
19
|
+
|
20
|
+
def applicable_taxes to_state, date
|
21
|
+
taxes = if to_state == @code && @rules['same_state']
|
22
|
+
@rules['same_state']
|
23
|
+
elsif @rules['same_country']
|
24
|
+
@rules['same_country']
|
25
|
+
else
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
[taxes].flatten
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_tax tax, date
|
32
|
+
if i = @taxes[tax] && i.cover?(date)
|
33
|
+
i.build(date)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/death_and_taxes/tax.rb
CHANGED
@@ -3,6 +3,9 @@ module DeathAndTaxes
|
|
3
3
|
belongs_to :taxer, :polymorphic => true
|
4
4
|
belongs_to :tax, :foreign_key => :apply_on_tax
|
5
5
|
|
6
|
+
validates :percentage, :numericality => {:greater_than => 0.01, :less_than => 100}, :format => /^\d+??(?:\.\d*)?$/, :presence => true
|
7
|
+
validates_presence_of :name
|
8
|
+
|
6
9
|
def apply amount
|
7
10
|
amount * multiplier
|
8
11
|
end
|
@@ -10,5 +13,9 @@ module DeathAndTaxes
|
|
10
13
|
def multiplier
|
11
14
|
(percentage / 100) * (1 + tax.try(:multiplier).to_f)
|
12
15
|
end
|
16
|
+
|
17
|
+
def blank?
|
18
|
+
percentage.blank? && name.blank? && account_number.blank?
|
19
|
+
end
|
13
20
|
end
|
14
21
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module DeathAndTaxes
|
2
|
+
class TaxInfo
|
3
|
+
def initialize name, yml = nil
|
4
|
+
@name = name
|
5
|
+
parse yml if yml
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse yml
|
9
|
+
@apply_on = yml['apply_on']
|
10
|
+
@versions = yml['versions'].collect do |version|
|
11
|
+
TaxVersion.new(version)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cover? date
|
16
|
+
@versions.any?{ |version| v.cover? date }
|
17
|
+
end
|
18
|
+
|
19
|
+
def build date
|
20
|
+
if v = @versions.detect{ |v| v.cover?(date) }
|
21
|
+
t = Tax.new :name => @name, :percentage => v['percentage']
|
22
|
+
t.tax = DeathAndTaxes.build_tax(@apply_on, date) if @apply_on
|
23
|
+
t
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -22,6 +22,11 @@ module DeathAndTaxes
|
|
22
22
|
|
23
23
|
include DeathAndTaxes::Taxable::InstanceMethods
|
24
24
|
end
|
25
|
+
|
26
|
+
def calculate_rate taxes
|
27
|
+
taxes.reduce(1) { |rate, tax| rate + tax.apply(1) }
|
28
|
+
end
|
29
|
+
|
25
30
|
end
|
26
31
|
|
27
32
|
module InstanceMethods
|
@@ -29,7 +34,7 @@ module DeathAndTaxes
|
|
29
34
|
taxes = [taxes] unless taxes.is_a? Array
|
30
35
|
|
31
36
|
self.taxations = taxes.collect do |tax|
|
32
|
-
Taxation.new :amount => tax.apply(amount), :percentage => tax.
|
37
|
+
Taxation.new :amount => tax.apply(amount), :percentage => tax.percentage, :name => tax.name, :account_number => tax.account_number
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
data/lib/death_and_taxes.rb
CHANGED
@@ -3,11 +3,25 @@ require 'active_record/version'
|
|
3
3
|
|
4
4
|
require 'active_support/core_ext'
|
5
5
|
|
6
|
-
|
7
|
-
require File.join(File.dirname(__FILE__), 'death_and_taxes/railtie')
|
6
|
+
require File.join(File.dirname(__FILE__), 'death_and_taxes', 'railtie')
|
8
7
|
|
9
8
|
module DeathAndTaxes
|
10
|
-
%w( Tax Taxable Taxation Taxer ).each do |class_name|
|
11
|
-
autoload class_name.to_sym, File.join(File.dirname(__FILE__), "death_and_taxes/#{class_name.
|
9
|
+
%w( Country State Tax Taxable Taxation Taxer TaxInfo TaxVersion ).each do |class_name|
|
10
|
+
autoload class_name.to_sym, File.join(File.dirname(__FILE__), "death_and_taxes/#{class_name.underscore}")
|
11
|
+
end
|
12
|
+
|
13
|
+
Dir[File.join(File.dirname(__FILE__), '..', 'config', '*.yml')].each do |filename|
|
14
|
+
country_code = filename.match(/\W(?<country_code>[a-z]+)\.yml/)[:country_code]
|
15
|
+
@countries = {}
|
16
|
+
@countries[country_code] = Country.new( country_code, YAML::load_file(filename) )
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.applicable_taxes from, to, date = nil
|
20
|
+
date ||= Date.today
|
21
|
+
@countries.map{ |code, country| country.applicable_taxes(from, to, date)}.flatten.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.build tax, date
|
25
|
+
@countries.detect {|code, country| country.build_tax(tax, date)}
|
12
26
|
end
|
13
27
|
end
|
metadata
CHANGED
@@ -1,45 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: death_and_taxes
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Guillaume Malette
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
17
|
+
|
18
|
+
date: 2011-08-09 00:00:00 -04:00
|
13
19
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
16
22
|
name: rails
|
17
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
25
|
none: false
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
23
33
|
type: :runtime
|
24
|
-
|
25
|
-
|
26
|
-
- !ruby/object:Gem::Dependency
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
27
36
|
name: sqlite3
|
28
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
39
|
none: false
|
30
|
-
requirements:
|
31
|
-
- -
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
34
47
|
type: :development
|
35
|
-
|
36
|
-
version_requirements: *2152141280
|
48
|
+
version_requirements: *id002
|
37
49
|
description: Death and Taxes allows to 'easily' calculate taxes on a model
|
38
50
|
email: gmalette@gmail.com
|
39
51
|
executables: []
|
52
|
+
|
40
53
|
extensions: []
|
54
|
+
|
41
55
|
extra_rdoc_files: []
|
42
|
-
|
56
|
+
|
57
|
+
files:
|
43
58
|
- .document
|
44
59
|
- .gitignore
|
45
60
|
- Gemfile
|
@@ -47,10 +62,15 @@ files:
|
|
47
62
|
- LICENSE.txt
|
48
63
|
- README.rdoc
|
49
64
|
- Rakefile
|
65
|
+
- config/ca.yml
|
50
66
|
- death_and_taxes.gemspec
|
51
67
|
- lib/death_and_taxes.rb
|
68
|
+
- lib/death_and_taxes/country.rb
|
52
69
|
- lib/death_and_taxes/railtie.rb
|
70
|
+
- lib/death_and_taxes/state.rb
|
53
71
|
- lib/death_and_taxes/tax.rb
|
72
|
+
- lib/death_and_taxes/tax_info.rb
|
73
|
+
- lib/death_and_taxes/tax_version.rb
|
54
74
|
- lib/death_and_taxes/taxable.rb
|
55
75
|
- lib/death_and_taxes/taxation.rb
|
56
76
|
- lib/death_and_taxes/taxer.rb
|
@@ -60,30 +80,39 @@ files:
|
|
60
80
|
- test/helper.rb
|
61
81
|
- test/test_death_and_taxes.rb
|
62
82
|
has_rdoc: true
|
63
|
-
homepage:
|
83
|
+
homepage: ""
|
64
84
|
licenses: []
|
85
|
+
|
65
86
|
post_install_message:
|
66
87
|
rdoc_options: []
|
67
|
-
|
88
|
+
|
89
|
+
require_paths:
|
68
90
|
- lib
|
69
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
92
|
none: false
|
71
|
-
requirements:
|
72
|
-
- -
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
101
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
81
109
|
requirements: []
|
110
|
+
|
82
111
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.
|
112
|
+
rubygems_version: 1.3.7
|
84
113
|
signing_key:
|
85
114
|
specification_version: 3
|
86
115
|
summary: Tax calculations
|
87
|
-
test_files:
|
116
|
+
test_files:
|
88
117
|
- test/helper.rb
|
89
118
|
- test/test_death_and_taxes.rb
|