tax_girl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 087b91f189fe9d5686163b072844520170ee5b91
4
+ data.tar.gz: c7bb6ddf2965a90572b462619e55cd218f727ebc
5
+ SHA512:
6
+ metadata.gz: 3f61e9fba050d4ba6a97ae9ef95d25f8eeb4035f1d24b05cb8d54346b8771de1bcb7443d48df592bf281adb1a0967d0f01142209bdf4361b7bf1dab31fa5b740
7
+ data.tar.gz: f803151d0889d17e0033f7585a3436027cadf354bcdff53394616a264da6bf945fb4f4ea18e93c4ec731d762b328d3e4a75aa3e87e7e6537ebdd80d36e2b0fc1
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
35
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Oswaldo S Ferreira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ tax_girl
2
+ =======
3
+
4
+ ### Introduction
5
+
6
+ TaxGirl is a simple tool that help's keeping calculation logic explicit using a pretty
7
+ ruby DSL. It also avoids the hard work of seaching for layers and layers of calculation methods.
8
+
9
+ ### Composing price
10
+
11
+ #### Increase block
12
+
13
+ Block where you define which methods will be triggered to compose the main price amount.
14
+
15
+ #### Params
16
+
17
+ **currency** and **percentage** - Accepts a method or list of methods symbols that will be triggered
18
+ on the moment you call the method passed as param to taxgirl (*price* on the example below).
19
+
20
+ Obs: *percentage* methods amounts will be applied on typed order.
21
+
22
+ ```ruby
23
+ class Product
24
+ taxgirl :price do
25
+ increase do
26
+ currency :provider_price, :convenience_fee
27
+ percentage :commission_fee, :another_fee
28
+ end
29
+ end
30
+
31
+ def provider_price
32
+ 105.5
33
+ end
34
+
35
+ def convenience_fee
36
+ 5.0
37
+ end
38
+
39
+ def commission_fee
40
+ # It means 10% to tax girl
41
+ 10.0
42
+ end
43
+
44
+ def another_fee
45
+ # It means 5.5% to tax girl
46
+ 5.5
47
+ end
48
+ end
49
+
50
+ product = Product.new
51
+ product.price
52
+
53
+ => 128.23525
54
+
55
+ ```
56
+
57
+ Obs: *price* will be calculated every time it's called.
58
+
59
+ #### Discount block
60
+
61
+ Block where you define which methods will be triggered to discount the main price amount calculated on *increase block*.
62
+
63
+ ```ruby
64
+ class Product
65
+ taxgirl :price do
66
+ increase do
67
+ currency :provider_price, :convenience_fee
68
+ percentage :commission_fee, :another_fee
69
+ end
70
+
71
+ discount do
72
+ currency :special_coupon_discount
73
+ percentage :black_friday_discount
74
+ end
75
+ end
76
+
77
+ def provider_price
78
+ 105.5
79
+ end
80
+
81
+ def convenience_fee
82
+ 5.0
83
+ end
84
+
85
+ def commission_fee
86
+ # It means 10% to tax girl
87
+ 10.0
88
+ end
89
+
90
+ def another_fee
91
+ # It means 5.5% to tax girl
92
+ 5.5
93
+ end
94
+
95
+ def special_coupon_discount
96
+ 20.0
97
+ end
98
+
99
+ def black_friday_discount
100
+ # It means 15% to tax girl
101
+ 15.0
102
+ end
103
+ end
104
+
105
+ product = Product.new
106
+ product.price
107
+
108
+ => 91.99996250000001
109
+ ```
110
+
111
+ ### Contributing
112
+
113
+ - Create an issue
114
+ - Fork the project
115
+ - Send a pull request
116
+ - Have fun! :)
data/lib/tax_girl.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'tax_girl/composer'
2
+ require 'tax_girl/increaser'
3
+ require 'tax_girl/discounter'
4
+
5
+ def taxgirl(price_attr, &main_block)
6
+ composer = Composer.new(main_block)
7
+
8
+ define_method price_attr do
9
+ Increaser.new(composer, self)
10
+ Discounter.new(composer, self)
11
+
12
+ composer.total
13
+ end
14
+
15
+ composer.evaluate!
16
+ end
@@ -0,0 +1,36 @@
1
+ class Composer
2
+ attr_accessor :demand_methods,
3
+ :current_demand,
4
+ :total
5
+
6
+ def initialize(taxgirl_block)
7
+ @demand_methods = { discount: { currency: [], percentage: [] }, increase: { currency: [], percentage: [] } }
8
+ @current_demand = nil
9
+ @taxgirl_block = taxgirl_block
10
+ @total = 0
11
+ end
12
+
13
+ def evaluate!
14
+ instance_eval(&@taxgirl_block)
15
+ end
16
+
17
+ def increase
18
+ @current_demand = :increase
19
+
20
+ yield
21
+ end
22
+
23
+ def discount
24
+ @current_demand = :discount
25
+
26
+ yield
27
+ end
28
+
29
+ def currency(*args)
30
+ demand_methods[current_demand][:currency] = args
31
+ end
32
+
33
+ def percentage(*args)
34
+ demand_methods[current_demand][:percentage] = args
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ class Discounter
2
+ attr_accessor :composer, :scope
3
+
4
+ def initialize(composer, scope)
5
+ @composer = composer
6
+ @scope = scope
7
+ @currency_demand = composer.demand_methods[:discount][:currency]
8
+ @percentage_demand = composer.demand_methods[:discount][:percentage]
9
+
10
+ calculate_amount if @currency_demand.any?
11
+ end
12
+
13
+ def calculate_amount
14
+ calculate_currency
15
+ calculate_percentage
16
+ end
17
+
18
+ def calculate_currency
19
+ self.composer.total -= @currency_demand.map do |method|
20
+ scope.send(method) || 0
21
+ end.reduce(:+)
22
+ end
23
+
24
+ def calculate_percentage
25
+ @percentage_demand.each do |method|
26
+ value = scope.send(method) || 0
27
+ self.composer.total -= (value.to_f / 100) * composer.total
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ class Increaser
2
+ attr_accessor :composer, :scope, :amount
3
+
4
+ def initialize(composer, scope)
5
+ @composer = composer
6
+ @scope = scope
7
+ @amount = 0
8
+ @currency_demand = composer.demand_methods[:increase][:currency]
9
+ @percentage_demand = composer.demand_methods[:increase][:percentage]
10
+
11
+ calculate_amount if @currency_demand.any?
12
+ end
13
+
14
+ def calculate_amount
15
+ calculate_currency
16
+ calculate_percentage
17
+
18
+ composer.total = amount
19
+ end
20
+
21
+ def calculate_currency
22
+ self.amount += @currency_demand.map do |method|
23
+ scope.send(method) || 0
24
+ end.reduce(:+)
25
+ end
26
+
27
+ def calculate_percentage
28
+ @percentage_demand.each do |method|
29
+ value = scope.send(method) || 0
30
+ self.amount += (value.to_f / 100) * amount
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'tax_girl'
2
+
3
+ class BasicDummy
4
+ taxgirl :price do
5
+ increase do
6
+ currency :provider_price, :convenience_fee
7
+ percentage :commission_fee, :another_percentage_tax
8
+ end
9
+
10
+ discount do
11
+ currency :coupon_discount, :another_fix_discount
12
+ percentage :black_friday_discount, :another_percentage_discount
13
+ end
14
+ end
15
+
16
+ # Just to improve the spec initialization (it's not needed)
17
+ def initialize(opts)
18
+ self.provider_price = opts[:provider_price]
19
+ self.convenience_fee = opts[:convenience_fee]
20
+ self.commission_fee = opts[:commission_fee]
21
+ self.another_percentage_tax = opts[:another_percentage_tax]
22
+ self.coupon_discount = opts[:coupon_discount]
23
+ self.another_fix_discount = opts[:another_fix_discount]
24
+ self.black_friday_discount = opts[:black_friday_discount]
25
+ self.another_percentage_discount = opts[:another_percentage_discount]
26
+ end
27
+
28
+ attr_accessor :provider_price,
29
+ :convenience_fee,
30
+ :commission_fee,
31
+ :another_percentage_tax,
32
+ :coupon_discount,
33
+ :another_fix_discount,
34
+ :black_friday_discount,
35
+ :another_percentage_discount
36
+ end
@@ -0,0 +1,120 @@
1
+ require 'basic_dummy'
2
+ require 'tax_girl'
3
+
4
+ describe 'TaxGirl initial syntax' do
5
+ describe '#taxgirl' do
6
+ let!(:simple_dummy) {
7
+ BasicDummy.new provider_price: 10,
8
+ convenience_fee: 20,
9
+ commission_fee: 5,
10
+ another_percentage_tax: 2
11
+ }
12
+
13
+ let!(:complete_dummy) {
14
+ BasicDummy.new provider_price: 100,
15
+ convenience_fee: 0,
16
+ commission_fee: 0,
17
+ another_percentage_tax: 0,
18
+ coupon_discount: 10,
19
+ another_fix_discount: 20,
20
+ black_friday_discount: 50,
21
+ another_percentage_discount: 1
22
+ }
23
+
24
+ context 'when only increase methods (simple_dummy)' do
25
+ it 'main taxgirl attribute returns calculated tax' do
26
+ expect(simple_dummy.price).to eq 32.13
27
+ end
28
+
29
+ it 'multiple calls does not affect calculation result' do
30
+ simple_dummy.price
31
+ expect(simple_dummy.price).to eq 32.13
32
+ end
33
+
34
+ it 'changes on the fly are considered on calculation result' do
35
+ simple_dummy.provider_price = 100
36
+ expect(simple_dummy.price).to eq 128.52
37
+ end
38
+ end
39
+
40
+ context 'when increase and discount methods (complete_dummy)' do
41
+ it 'main taxgirl attribute returns calculated tax' do
42
+ expect(complete_dummy.price).to eq 34.65
43
+
44
+ complete_dummy.provider_price = 90
45
+ end
46
+
47
+ it 'multiple calls does not affect calculation result' do
48
+ complete_dummy.price
49
+ expect(complete_dummy.price).to eq 34.65
50
+ end
51
+
52
+ it 'changes on the fly are considered on calculation result' do
53
+ complete_dummy.provider_price = 90
54
+ expect(complete_dummy.price).to eq 29.7
55
+ end
56
+ end
57
+
58
+ context 'when no value from a currency method' do
59
+ it '0 is returned from it' do
60
+ simple_dummy.provider_price = nil
61
+ expect(simple_dummy.price).to eq 21.42
62
+ end
63
+ end
64
+
65
+ context 'when no value from a percentage method' do
66
+ it '0 is returned from it' do
67
+ simple_dummy.commission_fee = nil
68
+ expect(simple_dummy.price).to eq 30.6
69
+ end
70
+ end
71
+
72
+ context 'when theres no discount block' do
73
+ let!(:dummy) do
74
+ class Dummy
75
+ taxgirl :price do
76
+ increase do
77
+ currency :p1
78
+ end
79
+ end
80
+
81
+ def p1
82
+ 100
83
+ end
84
+ end
85
+
86
+ Dummy.new
87
+ end
88
+
89
+ it 'discounter does not calculate amount' do
90
+ expect_any_instance_of(Discounter).not_to receive(:calculate_amount)
91
+
92
+ dummy.price
93
+ end
94
+ end
95
+
96
+ context 'when theres no increase block' do
97
+ let!(:dummy) do
98
+ class Dummy
99
+ taxgirl :price do
100
+ discount do
101
+ currency :p1
102
+ end
103
+ end
104
+
105
+ def p1
106
+ 100
107
+ end
108
+ end
109
+
110
+ Dummy.new
111
+ end
112
+
113
+ it 'increaser does not calculate amount' do
114
+ expect_any_instance_of(Increaser).not_to receive(:calculate_amount)
115
+
116
+ dummy.price
117
+ end
118
+ end
119
+ end
120
+ end
data/tax_girl.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'tax_girl'
6
+ s.version = '0.0.1'
7
+ s.date = '2015-02-05'
8
+ s.summary = 'DSL for calculation methods organization.'
9
+ s.description = 'TaxGirl is a simple tool that helps keeping calculation logic explicit using a ruby DSL.'
10
+ s.authors = ['Oswaldo Ferreira']
11
+ s.email = 'oswluizf@gmail.com'
12
+ s.homepage = 'https://github.com/oswaldoferreira/tax_girl'
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files -z`.split("\x0")
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency 'bundler', '~> 1.7'
21
+ s.add_development_dependency 'rspec', '~> 3.1', '>= 3.1.0'
22
+ end
23
+
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tax_girl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Oswaldo Ferreira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 3.1.0
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.1'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.1.0
47
+ description: TaxGirl is a simple tool that helps keeping calculation logic explicit
48
+ using a ruby DSL.
49
+ email: oswluizf@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - ".gitignore"
55
+ - ".rspec"
56
+ - LICENSE
57
+ - README.md
58
+ - lib/tax_girl.rb
59
+ - lib/tax_girl/composer.rb
60
+ - lib/tax_girl/discounter.rb
61
+ - lib/tax_girl/increaser.rb
62
+ - spec/basic_dummy.rb
63
+ - spec/tax_girl_spec.rb
64
+ - tax_girl.gemspec
65
+ homepage: https://github.com/oswaldoferreira/tax_girl
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.4.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: DSL for calculation methods organization.
89
+ test_files:
90
+ - spec/basic_dummy.rb
91
+ - spec/tax_girl_spec.rb