commissioner-guy 0.1.2 → 0.2.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +61 -0
- data/.travis.yml +1 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +33 -2
- data/README.md +72 -1
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/commissioner.gemspec +9 -5
- data/lib/commissioner.rb +3 -1
- data/lib/commissioner/calculator.rb +120 -59
- data/lib/commissioner/mixin.rb +9 -8
- data/lib/commissioner/version.rb +3 -1
- metadata +37 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '09145e647b6a57e336c094804b5cae11c6aa1346a3bacda852f6119a0e79a322'
|
|
4
|
+
data.tar.gz: 20a9ced63f0ecab83195834d36b710a9bf1a0e9d6cf3aea557347cd976c98f22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '006658ff7ea4801acf352c15c8fb192970fbecab106e548596b69910332612bd62a78daf935db3583c03efbb699ef6f04eb7de3412512e7f6a387d6b04d1499d'
|
|
7
|
+
data.tar.gz: 749dfe3e31731ddde638be7d7e84bf2a1e9d28d77352183ad97c4a10dcb84bbdfcf75e5cff8035aca3f298c387b639f13891c2be21d4edd4c1631041e01263bc
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2020-12-12 19:03:34 UTC using RuboCop version 1.6.1.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: Include.
|
|
11
|
+
# Include: **/*.gemspec
|
|
12
|
+
Gemspec/RequiredRubyVersion:
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'commissioner.gemspec'
|
|
15
|
+
|
|
16
|
+
# Offense count: 2
|
|
17
|
+
# Configuration parameters: AllowedMethods.
|
|
18
|
+
# AllowedMethods: enums
|
|
19
|
+
Lint/ConstantDefinitionInBlock:
|
|
20
|
+
Exclude:
|
|
21
|
+
- 'spec/commissioner/mixin_spec.rb'
|
|
22
|
+
|
|
23
|
+
# Offense count: 2
|
|
24
|
+
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
|
25
|
+
Metrics/AbcSize:
|
|
26
|
+
Max: 19
|
|
27
|
+
|
|
28
|
+
# Offense count: 5
|
|
29
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
30
|
+
# IgnoredMethods: refine
|
|
31
|
+
Metrics/BlockLength:
|
|
32
|
+
Max: 98
|
|
33
|
+
|
|
34
|
+
# Offense count: 1
|
|
35
|
+
# Configuration parameters: CountComments, CountAsOne.
|
|
36
|
+
Metrics/ClassLength:
|
|
37
|
+
Max: 101
|
|
38
|
+
|
|
39
|
+
# Offense count: 1
|
|
40
|
+
# Configuration parameters: IgnoredMethods.
|
|
41
|
+
Metrics/CyclomaticComplexity:
|
|
42
|
+
Max: 8
|
|
43
|
+
|
|
44
|
+
# Offense count: 5
|
|
45
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
46
|
+
Metrics/MethodLength:
|
|
47
|
+
Max: 20
|
|
48
|
+
|
|
49
|
+
# Offense count: 2
|
|
50
|
+
Style/ClassVars:
|
|
51
|
+
Exclude:
|
|
52
|
+
- 'lib/commissioner/mixin.rb'
|
|
53
|
+
|
|
54
|
+
# Offense count: 4
|
|
55
|
+
Style/Documentation:
|
|
56
|
+
Exclude:
|
|
57
|
+
- 'spec/**/*'
|
|
58
|
+
- 'test/**/*'
|
|
59
|
+
- 'lib/commissioner.rb'
|
|
60
|
+
- 'lib/commissioner/calculator.rb'
|
|
61
|
+
- 'lib/commissioner/mixin.rb'
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
|
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
4
6
|
|
|
5
7
|
# Specify your gem's dependencies in exchanger.gemspec
|
|
6
8
|
gemspec
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
commissioner-guy (0.
|
|
4
|
+
commissioner-guy (0.2.0)
|
|
5
5
|
dry-auto_inject (~> 0.6)
|
|
6
6
|
dry-configurable (~> 0.11)
|
|
7
7
|
money (~> 6.13.8)
|
|
@@ -9,6 +9,9 @@ PATH
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
+
ast (2.4.1)
|
|
13
|
+
byebug (11.1.3)
|
|
14
|
+
coderay (1.1.3)
|
|
12
15
|
concurrent-ruby (1.1.7)
|
|
13
16
|
diff-lcs (1.4.4)
|
|
14
17
|
dry-auto_inject (0.7.0)
|
|
@@ -20,14 +23,27 @@ GEM
|
|
|
20
23
|
dry-container (0.7.2)
|
|
21
24
|
concurrent-ruby (~> 1.0)
|
|
22
25
|
dry-configurable (~> 0.1, >= 0.1.3)
|
|
23
|
-
dry-core (0.
|
|
26
|
+
dry-core (0.5.0)
|
|
24
27
|
concurrent-ruby (~> 1.0)
|
|
25
28
|
dry-equalizer (0.3.0)
|
|
26
29
|
i18n (1.8.5)
|
|
27
30
|
concurrent-ruby (~> 1.0)
|
|
31
|
+
method_source (1.0.0)
|
|
28
32
|
money (6.13.8)
|
|
29
33
|
i18n (>= 0.6.4, <= 2)
|
|
34
|
+
parallel (1.20.1)
|
|
35
|
+
parser (2.7.2.0)
|
|
36
|
+
ast (~> 2.4.1)
|
|
37
|
+
pry (0.13.1)
|
|
38
|
+
coderay (~> 1.1)
|
|
39
|
+
method_source (~> 1.0)
|
|
40
|
+
pry-byebug (3.9.0)
|
|
41
|
+
byebug (~> 11.0)
|
|
42
|
+
pry (~> 0.13.0)
|
|
43
|
+
rainbow (3.0.0)
|
|
30
44
|
rake (10.5.0)
|
|
45
|
+
regexp_parser (2.0.0)
|
|
46
|
+
rexml (3.2.4)
|
|
31
47
|
rspec (3.10.0)
|
|
32
48
|
rspec-core (~> 3.10.0)
|
|
33
49
|
rspec-expectations (~> 3.10.0)
|
|
@@ -41,6 +57,19 @@ GEM
|
|
|
41
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
42
58
|
rspec-support (~> 3.10.0)
|
|
43
59
|
rspec-support (3.10.0)
|
|
60
|
+
rubocop (1.6.1)
|
|
61
|
+
parallel (~> 1.10)
|
|
62
|
+
parser (>= 2.7.1.5)
|
|
63
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
64
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
65
|
+
rexml
|
|
66
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
|
67
|
+
ruby-progressbar (~> 1.7)
|
|
68
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
|
69
|
+
rubocop-ast (1.3.0)
|
|
70
|
+
parser (>= 2.7.1.5)
|
|
71
|
+
ruby-progressbar (1.10.1)
|
|
72
|
+
unicode-display_width (1.7.0)
|
|
44
73
|
|
|
45
74
|
PLATFORMS
|
|
46
75
|
ruby
|
|
@@ -48,8 +77,10 @@ PLATFORMS
|
|
|
48
77
|
DEPENDENCIES
|
|
49
78
|
bundler (~> 1.17)
|
|
50
79
|
commissioner-guy!
|
|
80
|
+
pry-byebug (~> 3.9.0)
|
|
51
81
|
rake (~> 10.0)
|
|
52
82
|
rspec (~> 3.0)
|
|
83
|
+
rubocop (~> 1.6.1)
|
|
53
84
|
|
|
54
85
|
BUNDLED WITH
|
|
55
86
|
1.17.3
|
data/README.md
CHANGED
|
@@ -77,6 +77,76 @@ class MyCalculator
|
|
|
77
77
|
end
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
#### Specify order
|
|
81
|
+
|
|
82
|
+
You can specify in which order calculation will be applied. The steps are:
|
|
83
|
+
|
|
84
|
+
- exchange
|
|
85
|
+
- commission
|
|
86
|
+
- exchange_commission
|
|
87
|
+
|
|
88
|
+
`exchange` - calls exchanger if currencies of received and charged amounts differ
|
|
89
|
+
`commission` - applies typical commission operation
|
|
90
|
+
`exchange_commission` - applies commission for exchange (in charged currency if ordered before `exchange` or in received currency if ordered after `exchange`)
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
class MyCalculator
|
|
94
|
+
include Commissioner::Mixin
|
|
95
|
+
|
|
96
|
+
# Default order is:
|
|
97
|
+
# - :commission
|
|
98
|
+
# - :exchange
|
|
99
|
+
# - :exchange_commission
|
|
100
|
+
|
|
101
|
+
Order[
|
|
102
|
+
:commission,
|
|
103
|
+
:exchange_commission,
|
|
104
|
+
:exchange
|
|
105
|
+
]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
MyCalculator.new.calculate(
|
|
109
|
+
received_amount: 100,
|
|
110
|
+
received_currency: 'EUR',
|
|
111
|
+
charged_currency: 'USD',
|
|
112
|
+
commission: 10,
|
|
113
|
+
exchange_commission: 15
|
|
114
|
+
).to_h
|
|
115
|
+
# =>
|
|
116
|
+
# {
|
|
117
|
+
# :received_amount => #<Money fractional:10000 currency:EUR>,
|
|
118
|
+
# :charged_amount => #<Money fractional:13072 currency:USD>,
|
|
119
|
+
# :fee => #<Money fractional:1307 currency:USD>,
|
|
120
|
+
# :exchange_fee => #<Money fractional:1765 currency:USD>,
|
|
121
|
+
# :exchange_rate => 1
|
|
122
|
+
# }
|
|
123
|
+
|
|
124
|
+
# Changing the order
|
|
125
|
+
class MyCalculator
|
|
126
|
+
Order[
|
|
127
|
+
:exchange_commission,
|
|
128
|
+
:exchange,
|
|
129
|
+
:commission
|
|
130
|
+
]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
MyCalculator.new.calculate(
|
|
134
|
+
received_amount: 100,
|
|
135
|
+
received_currency: 'EUR',
|
|
136
|
+
charged_currency: 'USD',
|
|
137
|
+
commission: 10,
|
|
138
|
+
exchange_commission: 15
|
|
139
|
+
).to_h
|
|
140
|
+
# =>
|
|
141
|
+
# {
|
|
142
|
+
# :received_amount => #<Money fractional:10000 currency:EUR>,
|
|
143
|
+
# :charged_amount => #<Money fractional:13072 currency:USD>,
|
|
144
|
+
# :fee => #<Money fractional:1111 currency:EUR>,
|
|
145
|
+
# :exchange_fee => #<Money fractional:1961 currency:USD>,
|
|
146
|
+
# :exchange_rate => 1
|
|
147
|
+
# }
|
|
148
|
+
```
|
|
149
|
+
|
|
80
150
|
## Development
|
|
81
151
|
|
|
82
152
|
- [x] Custom exchanger
|
|
@@ -84,7 +154,8 @@ end
|
|
|
84
154
|
- [x] Commission for operation
|
|
85
155
|
- [x] Commission for exchange
|
|
86
156
|
- [x] No matter whether received or charged amount is provided, the calculation result is the same
|
|
87
|
-
- [
|
|
157
|
+
- [x] User-defined order of commissions aplying and exchanging
|
|
158
|
+
- [ ] Custom commissions and exchanges in order
|
|
88
159
|
|
|
89
160
|
## Contributing
|
|
90
161
|
|
data/Rakefile
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
3
5
|
|
|
4
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
5
7
|
|
|
6
|
-
task :
|
|
8
|
+
task default: :spec
|
|
7
9
|
|
|
8
10
|
task :build do
|
|
9
11
|
sh 'gem build commissioner.gemspec'
|
data/bin/console
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'exchanger'
|
|
5
6
|
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
|
@@ -10,5 +11,5 @@ require "exchanger"
|
|
|
10
11
|
# require "pry"
|
|
11
12
|
# Pry.start
|
|
12
13
|
|
|
13
|
-
require
|
|
14
|
+
require 'irb'
|
|
14
15
|
IRB.start(__FILE__)
|
data/commissioner.gemspec
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
5
|
require 'commissioner/version'
|
|
4
6
|
|
|
@@ -8,8 +10,8 @@ Gem::Specification.new do |spec|
|
|
|
8
10
|
spec.authors = ['Valentine Kiselev']
|
|
9
11
|
spec.email = ['mrexox@outlook.com']
|
|
10
12
|
|
|
11
|
-
spec.summary =
|
|
12
|
-
spec.description =
|
|
13
|
+
spec.summary = 'A simple gem to calculate money based on provided amounts.'
|
|
14
|
+
spec.description = 'A simple gem to calculate money based on provided amounts.'
|
|
13
15
|
spec.homepage = 'https://github.com/mrexox/commissioner'
|
|
14
16
|
spec.license = 'MIT'
|
|
15
17
|
|
|
@@ -25,17 +27,19 @@ Gem::Specification.new do |spec|
|
|
|
25
27
|
|
|
26
28
|
# Specify which files should be added to the gem when it is released.
|
|
27
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
28
|
-
spec.files = Dir.chdir(File.expand_path(
|
|
30
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
29
31
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
spec.require_paths = ['lib']
|
|
33
35
|
|
|
34
|
-
spec.add_runtime_dependency 'dry-configurable', '~> 0.11'
|
|
35
36
|
spec.add_runtime_dependency 'dry-auto_inject', '~> 0.6'
|
|
37
|
+
spec.add_runtime_dependency 'dry-configurable', '~> 0.11'
|
|
36
38
|
spec.add_runtime_dependency 'money', '~> 6.13.8'
|
|
37
39
|
|
|
38
40
|
spec.add_development_dependency 'bundler', '~> 1.17'
|
|
41
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.9.0'
|
|
39
42
|
spec.add_development_dependency 'rake', '~> 10.0'
|
|
40
43
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
44
|
+
spec.add_development_dependency 'rubocop', '~> 1.6.1'
|
|
41
45
|
end
|
data/lib/commissioner.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'commissioner/version'
|
|
2
4
|
require 'commissioner/calculator'
|
|
3
5
|
require 'commissioner/mixin'
|
|
@@ -11,6 +13,6 @@ module Commissioner
|
|
|
11
13
|
setting :rounding_mode, :half_up # possible values: :up, :down, :half_up, :half_even
|
|
12
14
|
|
|
13
15
|
def self.calculate(params)
|
|
14
|
-
Calculator.new(params, config:
|
|
16
|
+
Calculator.new(params, config: config).calculate
|
|
15
17
|
end
|
|
16
18
|
end
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ostruct'
|
|
1
4
|
require 'money'
|
|
2
5
|
|
|
3
6
|
module Commissioner
|
|
@@ -5,10 +8,77 @@ module Commissioner
|
|
|
5
8
|
AmountUnknown = Class.new(StandardError)
|
|
6
9
|
CommissionerArityInvalid = Class.new(StandardError)
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
class Operator
|
|
12
|
+
OPERATIONS = {
|
|
13
|
+
exchange: ->(op) { op.exchange },
|
|
14
|
+
commission: ->(op) { op.apply_commission(op.commission, :operation) },
|
|
15
|
+
exchange_commission: ->(op) { op.apply_commission(op.exchange_commission, :exchange) if op.to != op.from }
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
attr_reader :commission, :exchange_commission, :exchanger, :to, :from, :exchange_fee, :fee, :exchange_rate,
|
|
19
|
+
:amount
|
|
20
|
+
|
|
21
|
+
def initialize(params)
|
|
22
|
+
@amount = params[:amount]
|
|
23
|
+
@commission = params[:commission]
|
|
24
|
+
@exchange_commission = params[:exchange_commission]
|
|
25
|
+
@exchanger = params[:exchanger]
|
|
26
|
+
@rounding_mode = params[:rounding_mode]
|
|
27
|
+
@commission_action = params[:commission_action]
|
|
28
|
+
@from = params[:from_currency]
|
|
29
|
+
@to = params[:to_currency]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def apply_order(order)
|
|
33
|
+
order.each do |operation|
|
|
34
|
+
OPERATIONS[operation]&.call(self)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def apply_commission(commission, type)
|
|
39
|
+
return 0 unless commission
|
|
40
|
+
|
|
41
|
+
if @commission_action == :reduce
|
|
42
|
+
fee = round(@amount.to_f * commission / 100, @amount.currency.to_s)
|
|
43
|
+
@amount -= fee
|
|
44
|
+
else
|
|
45
|
+
fee = round(@amount.to_f * commission / (100 - commission), @amount.currency.to_s)
|
|
46
|
+
@amount += fee
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
case type
|
|
50
|
+
when :exchange
|
|
51
|
+
@exchange_fee = fee
|
|
52
|
+
else
|
|
53
|
+
@fee = fee
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def round(decimal, currency)
|
|
58
|
+
Money.with_rounding_mode(@rounding_mode) do
|
|
59
|
+
Money.from_amount(decimal, currency)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def exchange
|
|
64
|
+
@amount, @exchange_rate = exchanger.call(from, to, @amount)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
HELP_MESSAGE = 'You must provider either charged_amount (with charged_currency) '\
|
|
69
|
+
'or received_amount (with received_currency). If none or both are '\
|
|
70
|
+
'non-zero, the service cannot know how to handle this.'
|
|
71
|
+
DEFAULT_ORDER = %i[
|
|
72
|
+
commission
|
|
73
|
+
exchange
|
|
74
|
+
exchange_commission
|
|
75
|
+
].freeze
|
|
76
|
+
|
|
9
77
|
private_constant :HELP_MESSAGE
|
|
78
|
+
private_constant :DEFAULT_ORDER
|
|
79
|
+
private_constant :Operator
|
|
10
80
|
|
|
11
|
-
def initialize(params, config:)
|
|
81
|
+
def initialize(params, config:, order: DEFAULT_ORDER)
|
|
12
82
|
@charged_amount = guess_amount(params[:charged_amount], params[:charged_currency])
|
|
13
83
|
@received_amount = guess_amount(params[:received_amount], params[:received_currency])
|
|
14
84
|
|
|
@@ -16,10 +86,11 @@ module Commissioner
|
|
|
16
86
|
@commission = params[:commission] || 0
|
|
17
87
|
|
|
18
88
|
unless config.exchanger.is_a?(Proc) && config.exchanger.arity == 3
|
|
19
|
-
raise CommissionerArityInvalid
|
|
89
|
+
raise CommissionerArityInvalid, "'exchanger' setting must be a lambda with arity of 3"
|
|
20
90
|
end
|
|
21
91
|
|
|
22
92
|
@exchanger = config.exchanger
|
|
93
|
+
@order = order
|
|
23
94
|
@rounding_mode =
|
|
24
95
|
case config.rounding_mode
|
|
25
96
|
when :up
|
|
@@ -34,53 +105,69 @@ module Commissioner
|
|
|
34
105
|
end
|
|
35
106
|
|
|
36
107
|
def calculate
|
|
37
|
-
|
|
38
|
-
@charged_amount = calculate_for_received
|
|
39
|
-
elsif !empty?(@charged_amount) && empty?(@received_amount)
|
|
40
|
-
@received_amount = calculate_for_charged
|
|
41
|
-
else
|
|
42
|
-
raise AmountUnknown.new(HELP_MESSAGE)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
OpenStruct.new(
|
|
108
|
+
@result = OpenStruct.new(
|
|
46
109
|
received_amount: @received_amount,
|
|
47
110
|
charged_amount: @charged_amount,
|
|
48
|
-
fee:
|
|
49
|
-
exchange_fee:
|
|
50
|
-
exchange_rate:
|
|
111
|
+
fee: 0,
|
|
112
|
+
exchange_fee: 0,
|
|
113
|
+
exchange_rate: 0
|
|
51
114
|
)
|
|
115
|
+
|
|
116
|
+
if !empty?(@charged_amount) && @received_amount.zero?
|
|
117
|
+
calculate_for_charged
|
|
118
|
+
elsif !empty?(@received_amount) && @charged_amount.zero?
|
|
119
|
+
calculate_for_received
|
|
120
|
+
else
|
|
121
|
+
raise AmountUnknown, HELP_MESSAGE
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
@result
|
|
52
125
|
end
|
|
53
126
|
|
|
54
127
|
private
|
|
55
128
|
|
|
56
|
-
attr_reader :exchange_commission, :commission, :exchanger
|
|
57
|
-
|
|
58
129
|
def empty?(amount)
|
|
59
130
|
amount.nil? || amount.zero?
|
|
60
131
|
end
|
|
61
132
|
|
|
62
|
-
def
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
133
|
+
def calculate_for_charged
|
|
134
|
+
operator = Operator.new(
|
|
135
|
+
from_currency: @charged_amount.currency.to_s,
|
|
136
|
+
to_currency: @received_amount.currency.to_s,
|
|
137
|
+
amount: @charged_amount,
|
|
138
|
+
commission: @commission,
|
|
139
|
+
exchange_commission: @exchange_commission,
|
|
140
|
+
exchanger: @exchanger,
|
|
141
|
+
rounding_mode: @rounding_mode,
|
|
142
|
+
commission_action: :reduce
|
|
143
|
+
)
|
|
68
144
|
|
|
69
|
-
|
|
145
|
+
operator.apply_order(@order)
|
|
70
146
|
|
|
71
|
-
amount
|
|
147
|
+
@result.received_amount = operator.amount
|
|
148
|
+
@result.fee = operator.fee if operator.fee
|
|
149
|
+
@result.exchange_fee = operator.exchange_fee if operator.exchange_fee
|
|
150
|
+
@result.exchange_rate = operator.exchange_rate
|
|
72
151
|
end
|
|
73
152
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
153
|
+
def calculate_for_received
|
|
154
|
+
operator = Operator.new(
|
|
155
|
+
from_currency: @charged_amount.currency.to_s,
|
|
156
|
+
to_currency: @received_amount.currency.to_s,
|
|
157
|
+
amount: @received_amount,
|
|
158
|
+
commission: @commission,
|
|
159
|
+
exchange_commission: @exchange_commission,
|
|
160
|
+
exchanger: @exchanger,
|
|
161
|
+
rounding_mode: @rounding_mode,
|
|
162
|
+
commission_action: :add
|
|
163
|
+
)
|
|
80
164
|
|
|
81
|
-
|
|
165
|
+
operator.apply_order(@order.reverse)
|
|
82
166
|
|
|
83
|
-
amount
|
|
167
|
+
@result.charged_amount = operator.amount
|
|
168
|
+
@result.fee = operator.fee if operator.fee
|
|
169
|
+
@result.exchange_fee = operator.exchange_fee if operator.exchange_fee
|
|
170
|
+
@result.exchange_rate = operator.exchange_rate
|
|
84
171
|
end
|
|
85
172
|
|
|
86
173
|
def guess_amount(amount, currency)
|
|
@@ -93,31 +180,5 @@ module Commissioner
|
|
|
93
180
|
Money.new(0, currency) if currency.is_a?(String)
|
|
94
181
|
end
|
|
95
182
|
end
|
|
96
|
-
|
|
97
|
-
def reduce_commission(amount, commission)
|
|
98
|
-
return 0 unless commission
|
|
99
|
-
fee = round(amount.to_f * commission / 100, amount.currency.to_s)
|
|
100
|
-
amount -= fee
|
|
101
|
-
|
|
102
|
-
[amount, fee]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def add_commission(amount, commission)
|
|
106
|
-
return 0 unless commission
|
|
107
|
-
fee = round(amount.to_f * commission / (100 - commission), amount.currency.to_s)
|
|
108
|
-
amount += fee
|
|
109
|
-
|
|
110
|
-
[amount, fee]
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def round(decimal, currency)
|
|
114
|
-
Money.with_rounding_mode(@rounding_mode) do
|
|
115
|
-
Money.from_amount(decimal, currency)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def exchange(amount)
|
|
120
|
-
exchanger.call(@charged_amount.currency.to_s, @received_amount.currency.to_s, amount)
|
|
121
|
-
end
|
|
122
183
|
end
|
|
123
184
|
end
|
data/lib/commissioner/mixin.rb
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Commissioner
|
|
2
4
|
module Mixin
|
|
3
|
-
|
|
4
|
-
# Order = ->(*order) { @@order = order }
|
|
5
|
+
Order = ->(*order) { @@order = order }
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
@@order = %i[
|
|
8
|
+
commission
|
|
9
|
+
exchange
|
|
10
|
+
exchange_commission
|
|
11
|
+
]
|
|
11
12
|
|
|
12
13
|
def calculate(params)
|
|
13
|
-
Calculator.new(params, config: Commissioner.config).calculate
|
|
14
|
+
Calculator.new(params, config: Commissioner.config, order: @@order).calculate
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
data/lib/commissioner/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: commissioner-guy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Valentine Kiselev
|
|
@@ -11,33 +11,33 @@ cert_chain: []
|
|
|
11
11
|
date: 2020-12-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: dry-
|
|
14
|
+
name: dry-auto_inject
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.6'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
26
|
+
version: '0.6'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: dry-
|
|
28
|
+
name: dry-configurable
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0.
|
|
33
|
+
version: '0.11'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0.
|
|
40
|
+
version: '0.11'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: money
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,6 +66,20 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '1.17'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: pry-byebug
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 3.9.0
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 3.9.0
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
84
|
name: rake
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,6 +108,20 @@ dependencies:
|
|
|
94
108
|
- - "~>"
|
|
95
109
|
- !ruby/object:Gem::Version
|
|
96
110
|
version: '3.0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rubocop
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 1.6.1
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 1.6.1
|
|
97
125
|
description: A simple gem to calculate money based on provided amounts.
|
|
98
126
|
email:
|
|
99
127
|
- mrexox@outlook.com
|
|
@@ -103,6 +131,8 @@ extra_rdoc_files: []
|
|
|
103
131
|
files:
|
|
104
132
|
- ".gitignore"
|
|
105
133
|
- ".rspec"
|
|
134
|
+
- ".rubocop.yml"
|
|
135
|
+
- ".rubocop_todo.yml"
|
|
106
136
|
- ".ruby-version"
|
|
107
137
|
- ".travis.yml"
|
|
108
138
|
- Gemfile
|