gera 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +67 -0
- data/Rakefile +43 -0
- data/app/assets/config/gera_manifest.js +2 -0
- data/app/assets/javascripts/gera/application.js +14 -0
- data/app/assets/stylesheets/gera/application.css +15 -0
- data/app/authorizers/gera/application_authorizer.rb +6 -0
- data/app/authorizers/gera/currency_rate_authorizer.rb +9 -0
- data/app/authorizers/gera/currency_rate_mode_authorizer.rb +7 -0
- data/app/authorizers/gera/direction_rate_authorizer.rb +8 -0
- data/app/authorizers/gera/exchange_rate_authorizer.rb +8 -0
- data/app/authorizers/gera/payment_system_authorizer.rb +13 -0
- data/app/authorizers/gera/rate_source_authorizer.rb +7 -0
- data/app/controllers/gera/application_controller.rb +30 -0
- data/app/controllers/gera/currencies_controller.rb +8 -0
- data/app/controllers/gera/currency_rate_history_intervals_controller.rb +53 -0
- data/app/controllers/gera/currency_rate_mode_snapshots_controller.rb +83 -0
- data/app/controllers/gera/currency_rate_modes_controller.rb +60 -0
- data/app/controllers/gera/currency_rates_controller.rb +70 -0
- data/app/controllers/gera/direction_rate_history_intervals_controller.rb +62 -0
- data/app/controllers/gera/direction_rates_controller.rb +28 -0
- data/app/controllers/gera/exchange_rates_controller.rb +25 -0
- data/app/controllers/gera/external_rate_snapshots_controller.rb +35 -0
- data/app/controllers/gera/external_rates_controller.rb +28 -0
- data/app/controllers/gera/payment_systems_controller.rb +78 -0
- data/app/controllers/gera/rate_sources_controller.rb +8 -0
- data/app/decorators/gera/currency_rate_decorator.rb +148 -0
- data/app/decorators/gera/direction_rate_decorator.rb +47 -0
- data/app/decorators/gera/payment_system_decorator.rb +19 -0
- data/app/helpers/gera/application_helper.rb +110 -0
- data/app/helpers/gera/currency_rate_helper.rb +19 -0
- data/app/helpers/gera/currency_rate_modes_helper.rb +73 -0
- data/app/helpers/gera/direction_rate_helper.rb +36 -0
- data/app/helpers/gera/exchange_rates_helper.rb +21 -0
- data/app/jobs/gera/application_job.rb +6 -0
- data/app/models/concerns/gera/currency_pair_generator.rb +14 -0
- data/app/models/concerns/gera/currency_pair_support.rb +42 -0
- data/app/models/concerns/gera/currency_rate_mode_builder_support.rb +35 -0
- data/app/models/concerns/gera/direction_support.rb +14 -0
- data/app/models/concerns/gera/history_interval_concern.rb +46 -0
- data/app/models/gera/application_record.rb +8 -0
- data/app/models/gera/cbr_external_rate.rb +13 -0
- data/app/models/gera/cross_rate_mode.rb +13 -0
- data/app/models/gera/currency_rate.rb +78 -0
- data/app/models/gera/currency_rate_history_interval.rb +25 -0
- data/app/models/gera/currency_rate_history_interval_filter.rb +30 -0
- data/app/models/gera/currency_rate_mode.rb +20 -0
- data/app/models/gera/currency_rate_mode_snapshot.rb +26 -0
- data/app/models/gera/currency_rate_snapshot.rb +12 -0
- data/app/models/gera/direction.rb +44 -0
- data/app/models/gera/direction_rate.rb +136 -0
- data/app/models/gera/direction_rate_history_interval.rb +33 -0
- data/app/models/gera/direction_rate_history_interval_filter.rb +30 -0
- data/app/models/gera/direction_rate_snapshot.rb +7 -0
- data/app/models/gera/exchange_rate.rb +130 -0
- data/app/models/gera/external_rate.rb +38 -0
- data/app/models/gera/external_rate_snapshot.rb +20 -0
- data/app/models/gera/payment_system.rb +98 -0
- data/app/models/gera/rate_source.rb +77 -0
- data/app/models/gera/rate_source_auto.rb +25 -0
- data/app/models/gera/rate_source_bitfinex.rb +9 -0
- data/app/models/gera/rate_source_cbr.rb +13 -0
- data/app/models/gera/rate_source_cbr_avg.rb +6 -0
- data/app/models/gera/rate_source_exmo.rb +9 -0
- data/app/models/gera/rate_source_manual.rb +13 -0
- data/app/views/application/_exchange_rate_monitor.slim +1 -0
- data/app/views/gera/application/_attributes_table.slim +5 -0
- data/app/views/gera/application/_currencies_table.slim +18 -0
- data/app/views/gera/application/_currency_rate_mode_snapshots.slim +6 -0
- data/app/views/gera/application/_direction_rate.slim +6 -0
- data/app/views/gera/application/_directions_submenu.slim +11 -0
- data/app/views/gera/application/_directions_table.slim +15 -0
- data/app/views/gera/application/_exchange_rate.slim +6 -0
- data/app/views/gera/application/_external_rate.slim +6 -0
- data/app/views/gera/application/_header.slim +12 -0
- data/app/views/gera/application/_table.slim +28 -0
- data/app/views/gera/application/_topnav.slim +21 -0
- data/app/views/gera/application/direction_details.slim +75 -0
- data/app/views/gera/application/page.html.slim +1 -0
- data/app/views/gera/currencies/index.html.slim +20 -0
- data/app/views/gera/currency_rate_history_intervals/_filter.slim +11 -0
- data/app/views/gera/currency_rate_history_intervals/index.slim +39 -0
- data/app/views/gera/currency_rate_mode_snapshots/_snapshot.slim +20 -0
- data/app/views/gera/currency_rate_mode_snapshots/edit.html.slim +30 -0
- data/app/views/gera/currency_rate_modes/_cross_rate_mode_fields.slim +21 -0
- data/app/views/gera/currency_rate_modes/_currency_rate_mode.slim +7 -0
- data/app/views/gera/currency_rate_modes/_form.slim +29 -0
- data/app/views/gera/currency_rate_modes/edit.slim +11 -0
- data/app/views/gera/currency_rate_modes/index.html.slim +12 -0
- data/app/views/gera/currency_rates/_currency_rate.slim +22 -0
- data/app/views/gera/currency_rates/_currency_rate_humanized.slim +35 -0
- data/app/views/gera/currency_rates/diff.slim +12 -0
- data/app/views/gera/currency_rates/index.slim +27 -0
- data/app/views/gera/currency_rates/modes.slim +14 -0
- data/app/views/gera/currency_rates/show.slim +4 -0
- data/app/views/gera/direction_rate_history_intervals/_filter.slim +11 -0
- data/app/views/gera/direction_rate_history_intervals/index.slim +41 -0
- data/app/views/gera/direction_rates/_direction_rate_example_calculator.slim +28 -0
- data/app/views/gera/direction_rates/diff.slim +19 -0
- data/app/views/gera/direction_rates/index.slim +26 -0
- data/app/views/gera/direction_rates/legacy.html.slim +5 -0
- data/app/views/gera/direction_rates/minimals.slim +5 -0
- data/app/views/gera/direction_rates/show.slim +14 -0
- data/app/views/gera/external_rate_snapshots/index.slim +25 -0
- data/app/views/gera/external_rate_snapshots/show.slim +22 -0
- data/app/views/gera/external_rates/_flat_list.slim +22 -0
- data/app/views/gera/external_rates/index.html.slim +28 -0
- data/app/views/gera/external_rates/show.slim +1 -0
- data/app/views/gera/payment_systems/_fields.slim +4 -0
- data/app/views/gera/payment_systems/_fields_table.slim +18 -0
- data/app/views/gera/payment_systems/_form.slim +9 -0
- data/app/views/gera/payment_systems/edit.slim +7 -0
- data/app/views/gera/payment_systems/index.slim +3 -0
- data/app/views/gera/payment_systems/new.slim +9 -0
- data/app/views/gera/payment_systems/show.slim +1 -0
- data/app/views/gera/rate_sources/_list.slim +13 -0
- data/app/views/gera/rate_sources/_rate_source.slim +23 -0
- data/app/views/gera/rate_sources/index.html.slim +6 -0
- data/app/views/layouts/application.html.slim +15 -0
- data/app/views/layouts/gera/blank.html.slim +10 -0
- data/app/workers/concerns/gera/rates_worker.rb +87 -0
- data/app/workers/gera/bitfinex_rates_worker.rb +65 -0
- data/app/workers/gera/cbr_avg_rates_worker.rb +42 -0
- data/app/workers/gera/cbr_rates_worker.rb +192 -0
- data/app/workers/gera/create_history_intervals_worker.rb +38 -0
- data/app/workers/gera/currency_rates_worker.rb +64 -0
- data/app/workers/gera/directions_rates_worker.rb +51 -0
- data/app/workers/gera/exmo_rates_worker.rb +62 -0
- data/app/workers/gera/purge_currency_rates_worker.rb +21 -0
- data/app/workers/gera/purge_direction_rates_worker.rb +30 -0
- data/config/currencies.yml +559 -0
- data/config/routes.rb +30 -0
- data/db/migrate/20180912130000_setup.rb +228 -0
- data/db/migrate/20190314114844_add_is_available_to_payment_systems.rb +7 -0
- data/db/migrate/20190315113046_add_icon_url_to_payment_systems.rb +7 -0
- data/db/migrate/20190315132137_add_commission_to_payment_systems.rb +7 -0
- data/lib/banks/currency_exchange.rb +12 -0
- data/lib/builders/currency_rate_auto_builder.rb +38 -0
- data/lib/builders/currency_rate_builder.rb +60 -0
- data/lib/builders/currency_rate_cross_builder.rb +70 -0
- data/lib/builders/currency_rate_direct_builder.rb +26 -0
- data/lib/gera.rb +32 -0
- data/lib/gera/bitfinex_fetcher.rb +36 -0
- data/lib/gera/configuration.rb +47 -0
- data/lib/gera/currencies_purger.rb +28 -0
- data/lib/gera/currency_pair.rb +93 -0
- data/lib/gera/engine.rb +14 -0
- data/lib/gera/mathematic.rb +156 -0
- data/lib/gera/money_support.rb +89 -0
- data/lib/gera/numeric.rb +25 -0
- data/lib/gera/railtie.rb +8 -0
- data/lib/gera/rate.rb +22 -0
- data/lib/gera/rate_from_multiplicator.rb +54 -0
- data/lib/gera/repositories/currency_rate_modes_repository.rb +37 -0
- data/lib/gera/repositories/currency_rates_repository.rb +25 -0
- data/lib/gera/repositories/direction_rates_repository.rb +46 -0
- data/lib/gera/repositories/exchange_rates_repository.rb +23 -0
- data/lib/gera/repositories/payment_systems_repository.rb +21 -0
- data/lib/gera/repositories/universe.rb +47 -0
- data/lib/gera/version.rb +3 -0
- data/lib/tasks/auto_generate_diagram.rake +6 -0
- data/lib/tasks/gera_tasks.rake +4 -0
- metadata +765 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
class DirectionRateDecorator < ApplicationDecorator
|
5
|
+
include Mathematic
|
6
|
+
delegate :id
|
7
|
+
|
8
|
+
def inverse_direction
|
9
|
+
h.link_to h.direction_rate_path(object.inverse_direction_rate), class: 'text-muted' do
|
10
|
+
dd = DirectionRateDecorator.new(object.inverse_direction_rate)
|
11
|
+
buffer = dd.direction
|
12
|
+
buffer << ' '
|
13
|
+
buffer << dd.rate_value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def direction
|
18
|
+
"#{h.ps_icon object.ps_from}(#{object.ps_from.currency}) → #{h.ps_icon object.ps_to}(#{object.ps_to.currency})".html_safe
|
19
|
+
end
|
20
|
+
|
21
|
+
def title
|
22
|
+
[object.ps_from, object.ps_to].join('->')
|
23
|
+
end
|
24
|
+
|
25
|
+
def ps_comission
|
26
|
+
object.ps_comission.to_percent
|
27
|
+
end
|
28
|
+
|
29
|
+
def created_at
|
30
|
+
h.link_to h.direction_rate_path(object) do
|
31
|
+
I18n.l object.created_at, format: :long
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def base_rate_value
|
36
|
+
h.currency_rate_mode_detailed object.currency_rate
|
37
|
+
end
|
38
|
+
|
39
|
+
def rate_percent
|
40
|
+
object.rate_percent.to_percent
|
41
|
+
end
|
42
|
+
|
43
|
+
def rate_value
|
44
|
+
h.rate_humanized_description(object.rate_value, object.ps_from.currency, object.ps_to.currency)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
class PaymentSystemDecorator < ApplicationDecorator
|
5
|
+
delegate_all
|
6
|
+
|
7
|
+
def icon
|
8
|
+
h.ps_icon object, size: 32
|
9
|
+
end
|
10
|
+
|
11
|
+
def actions
|
12
|
+
h.link_to t('.edit'), h.edit_payment_system_path(object), class: 'btn btn-outline btn-default btn-sm' if object.updatable_by? current_user
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.decorated_class
|
16
|
+
PaymentSystem
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module ApplicationHelper
|
5
|
+
MINIMAL_EPSILON = 0.001
|
6
|
+
|
7
|
+
def humanized_currency_rate(rate_value, pair, currency)
|
8
|
+
rate = if rate_value < 1
|
9
|
+
format('%.9f', rate_value.to_f)
|
10
|
+
else
|
11
|
+
format('%.3f', rate_value.to_f)
|
12
|
+
end
|
13
|
+
|
14
|
+
if pair.first == currency
|
15
|
+
"#{rate} #{currency}" # покупка
|
16
|
+
elsif pair.second == currency
|
17
|
+
"#{rate} #{currency}" # продажа
|
18
|
+
else
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def rate_source(currency_rate, level = 0)
|
24
|
+
if currency_rate.mode_cross?
|
25
|
+
buffer = currency_rate_mode_detailed currency_rate, level
|
26
|
+
"⟮ <span class='text-muted'>#{buffer}</span> ⟯".html_safe
|
27
|
+
else
|
28
|
+
buffer = currency_rate.rate_source.presence || currency_rate.mode
|
29
|
+
"(#{buffer})".html_safe
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def currency_rate_cell_data_attr(rate)
|
34
|
+
{
|
35
|
+
toggle: :popover,
|
36
|
+
container: :body,
|
37
|
+
content: "Calculation method: #{currency_rate_mode_detailed rate}",
|
38
|
+
trigger: :hover,
|
39
|
+
html: 'true',
|
40
|
+
placement: :bottom,
|
41
|
+
animation: false,
|
42
|
+
delay: 0,
|
43
|
+
href: currency_rate_path(rate)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def rate_diff(rv1, rv2, _reverse = false)
|
48
|
+
return rate_diff(1.0 / rv1, 1.0 / rv2, true) if rv1 < 1
|
49
|
+
|
50
|
+
diff = rv2 - rv1
|
51
|
+
return 0 if diff.abs.round(3) == 0
|
52
|
+
|
53
|
+
p = 100 * diff / rv2
|
54
|
+
|
55
|
+
buffer = "#{format('%.2f', p.round(3))}%"
|
56
|
+
content_tag :span, buffer, data: { toggle: :tooltip, title: "#{rv2} - #{rv1}" }
|
57
|
+
end
|
58
|
+
|
59
|
+
def rate_with_currency(rate, currency)
|
60
|
+
rate = format('%.12f', rate) if rate.is_a?(Float) && rate < MINIMAL_EPSILON
|
61
|
+
"#{rate} <span class=text-muted>#{currency}</span>".html_safe
|
62
|
+
end
|
63
|
+
|
64
|
+
def rate_cell_with_currency(rate, currency)
|
65
|
+
buffer = [rate_with_currency(rate, currency)]
|
66
|
+
buffer << rate_with_currency(rate_inversed(rate), currency) if rate < 1
|
67
|
+
[buffer].join('<br/>').html_safe
|
68
|
+
end
|
69
|
+
|
70
|
+
# = '%.12f' % humanized_money rate.buy_money
|
71
|
+
def humanized_rate(rate, _currency = nil)
|
72
|
+
rate = rate.to_f if rate.is_a? Gera::Rate
|
73
|
+
if rate.is_a? Money
|
74
|
+
raise 'Dont use Money, it has bad round'
|
75
|
+
currency = rate.currency
|
76
|
+
rate = rate.to_f
|
77
|
+
end
|
78
|
+
if rate < 1
|
79
|
+
rate1 = format('%.3f', (1.0 / rate))
|
80
|
+
"<span class=text-muted>1/</span>#{rate1}".html_safe
|
81
|
+
else
|
82
|
+
format('%.3f', rate)
|
83
|
+
# = '%.12f' % humanized_money rate.buy_money
|
84
|
+
# humanized_money Money.from_amount(rate, currency)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def humanized_rate_text(rate, _currency = nil)
|
89
|
+
if rate < 1
|
90
|
+
rate1 = format('%.3f', (1.0 / rate))
|
91
|
+
"1/#{rate1}".html_safe
|
92
|
+
else
|
93
|
+
format('%.3f', rate)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def rate_inversed(rate)
|
98
|
+
"<span class='text-muted'>(1/#{1.0 / rate.to_f})</span>".html_safe
|
99
|
+
end
|
100
|
+
|
101
|
+
def humanized_rate_detailed(rate, separator = ' ')
|
102
|
+
buffer = if rate < 1
|
103
|
+
"#{rate}#{separator}#{rate_inversed(rate)}".html_safe
|
104
|
+
else
|
105
|
+
rate
|
106
|
+
end
|
107
|
+
content_tag :span, buffer.to_s, class: 'text-nowrap'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera::CurrencyRateHelper
|
4
|
+
def currency_rate_mode_autoshow_style(crm)
|
5
|
+
'display: none' unless crm.mode_cross?
|
6
|
+
end
|
7
|
+
|
8
|
+
def currency_rate_columns(cer)
|
9
|
+
if cer.external_rate_id.present?
|
10
|
+
%i[id created_at rate_value mode external_rate tooltip metadata]
|
11
|
+
else
|
12
|
+
%i[id created_at rate_value mode tooltip metadata]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def currency_rate_class(cer)
|
17
|
+
"cer-mode-#{cer.mode}"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera::CurrencyRateModesHelper
|
4
|
+
ICON_CLASS = {
|
5
|
+
'draft' => 'battery-half',
|
6
|
+
'active' => 'battery-charging',
|
7
|
+
'deactive' => 'battery-empty'
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
STATUS_CLASS = {
|
11
|
+
'draft' => 'label-info',
|
12
|
+
'active' => 'label-success',
|
13
|
+
'deactive' => 'label-default'
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
def currency_rate_mode_detailed(currency_rate, level = 0)
|
17
|
+
buffer = []
|
18
|
+
if currency_rate.mode_cross?
|
19
|
+
currency_rate.external_rates.each do |er|
|
20
|
+
buffer << "#{er.currency_pair}(#{er.source})<sup>#{humanized_rate er.rate_value}</sup>"
|
21
|
+
end
|
22
|
+
elsif currency_rate.mode_same?
|
23
|
+
buffer << t('.same_currency')
|
24
|
+
else
|
25
|
+
buffer << "#{currency_rate.currency_pair}(#{currency_rate.rate_source})"
|
26
|
+
end
|
27
|
+
|
28
|
+
buffer = buffer.join(' × ')
|
29
|
+
buffer << " = #{humanized_rate currency_rate.rate_value} #{currency_rate.currency_pair.last}" if level == 0
|
30
|
+
buffer.html_safe
|
31
|
+
end
|
32
|
+
|
33
|
+
def currency_rate_mode_build_result_details(build_result)
|
34
|
+
return build_result.error.message if build_result.error?
|
35
|
+
|
36
|
+
raw t('.calculation_method', rate: currency_rate_mode_detailed(build_result.currency_rate))
|
37
|
+
end
|
38
|
+
|
39
|
+
def crms_cell_data_attr(crm)
|
40
|
+
url = crm.persisted? ? edit_currency_rate_mode_path(crm, back: request.url) :
|
41
|
+
new_currency_rate_mode_path(
|
42
|
+
currency_rate_mode: crm.attributes.slice('currency_rate_mode_snapshot_id', 'cur_from', 'cur_to'),
|
43
|
+
back: request.url
|
44
|
+
)
|
45
|
+
{
|
46
|
+
toggle: :popover,
|
47
|
+
container: :body,
|
48
|
+
content: currency_rate_mode_build_result_details(crm.build_result),
|
49
|
+
trigger: :hover,
|
50
|
+
html: 'true',
|
51
|
+
placement: :bottom,
|
52
|
+
animation: false,
|
53
|
+
delay: 0,
|
54
|
+
href: url
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def crms_status_label(status)
|
59
|
+
content_tag :span, status, class: "label #{STATUS_CLASS[status]}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def currency_rate_mode_snapshot_icon(crms)
|
63
|
+
ion_icon ICON_CLASS[crms.status]
|
64
|
+
end
|
65
|
+
|
66
|
+
def currency_rate_modes_enum
|
67
|
+
Gera::CurrencyRateMode.modes.keys
|
68
|
+
end
|
69
|
+
|
70
|
+
def currencies_enum
|
71
|
+
Money::Currency.all.map(&:to_s)
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module DirectionRateHelper
|
5
|
+
def exchange_rate_cell_data_attr(direction)
|
6
|
+
rate_cell_data_attr(direction).merge href: operator_exchange_rate_path(direction.exchange_rate)
|
7
|
+
end
|
8
|
+
|
9
|
+
def direction_rate_cell_data_attr(direction)
|
10
|
+
rate_cell_data_attr(direction).merge href: direction_rate_path(direction.direction_rate.try(:id) || 0)
|
11
|
+
end
|
12
|
+
|
13
|
+
def rate_cell_data_attr(direction)
|
14
|
+
return {} unless show_direction_popover?
|
15
|
+
|
16
|
+
{
|
17
|
+
toggle: 'ajax-popover',
|
18
|
+
container: :body,
|
19
|
+
popover_content_url: details_exchange_rate_path(direction.exchange_rate),
|
20
|
+
trigger: :hover,
|
21
|
+
html: 'true',
|
22
|
+
placement: :bottom,
|
23
|
+
animation: false,
|
24
|
+
delay: 0
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def rate_humanized_description(rate_value, cur_from, cur_to)
|
29
|
+
if rate_value < 1
|
30
|
+
t '.sell_for', cur_to: cur_to, value: (1.0 / rate_value).round(3), cur_from: cur_from
|
31
|
+
else
|
32
|
+
t '.buy_for', cur_to: cur_to, value: rate_value.round(3), cur_from: cur_from
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module ExchangeRatesHelper
|
5
|
+
def exchange_rate_cell_class(er)
|
6
|
+
return unless er
|
7
|
+
|
8
|
+
classes = []
|
9
|
+
|
10
|
+
classes << 'rate-popover' if show_direction_popover?
|
11
|
+
|
12
|
+
classes << if er.comission_percents <= 0
|
13
|
+
'text-danger'
|
14
|
+
else
|
15
|
+
'text-success'
|
16
|
+
end
|
17
|
+
|
18
|
+
classes.join ' '
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module CurrencyPairGenerator
|
5
|
+
def generate_pairs_from_currencies(currencies)
|
6
|
+
currencies = currencies.map { |c| Money::Currency.find c }
|
7
|
+
|
8
|
+
currencies
|
9
|
+
.map { |c1| currencies.reject { |c2| c2 == c1 }.map { |c2| [c1, c2].join('/') } }
|
10
|
+
.flatten.compact
|
11
|
+
.map { |cp| Gera::CurrencyPair.new cp }.uniq
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module CurrencyPairSupport
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
if ancestors.include? ActiveRecord::Base
|
9
|
+
scope :by_currency_pair, ->(pair) { where cur_from: pair.cur_from.to_s, cur_to: pair.cur_to.to_s }
|
10
|
+
|
11
|
+
def self.find_by_currency_pair(pair)
|
12
|
+
by_currency_pair(pair).take
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_or_build_by_currency_pair(pair)
|
16
|
+
by_currency_pair(pair).take || new(currency_pair: pair)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def currency_pair=(value)
|
22
|
+
self.cur_from = value.cur_from
|
23
|
+
self.cur_to = value.cur_to
|
24
|
+
@currency_pair = nil
|
25
|
+
@currency_from = nil
|
26
|
+
@currency_to = nil
|
27
|
+
value
|
28
|
+
end
|
29
|
+
|
30
|
+
def currency_pair
|
31
|
+
@currency_pair ||= Gera::CurrencyPair.new currency_from, currency_to
|
32
|
+
end
|
33
|
+
|
34
|
+
def currency_from
|
35
|
+
@currency_from ||= cur_from.is_a?(Money::Currency) ? cur_from : Money::Currency.find!(cur_from)
|
36
|
+
end
|
37
|
+
|
38
|
+
def currency_to
|
39
|
+
@currency_to ||= cur_to.is_a?(Money::Currency) ? cur_to : Money::Currency.find!(cur_to)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module CurrencyRateModeBuilderSupport
|
5
|
+
def build_currency_rate
|
6
|
+
@currency_rate ||= build_currency_rate!
|
7
|
+
rescue CurrencyRateBuilder::Error
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_result
|
12
|
+
@result ||= builder.build_currency_rate
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_currency_rate!
|
16
|
+
raise build_result.error if build_result.error?
|
17
|
+
|
18
|
+
build_result.currency_rate
|
19
|
+
end
|
20
|
+
|
21
|
+
def builder
|
22
|
+
case mode
|
23
|
+
when 'auto'
|
24
|
+
CurrencyRateAutoBuilder.new currency_pair: currency_pair
|
25
|
+
when 'cross'
|
26
|
+
CurrencyRateCrossBuilder.new currency_pair: currency_pair, cross_rate_modes: cross_rate_modes
|
27
|
+
else
|
28
|
+
source = RateSource.find_by_key(mode)
|
29
|
+
raise "not supported mode #{mode} for #{currency_pair}" unless source.present?
|
30
|
+
|
31
|
+
CurrencyRateDirectBuilder.new currency_pair: currency_pair, source: source
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gera
|
4
|
+
module DirectionSupport
|
5
|
+
def direction=(value)
|
6
|
+
self.payment_system_from = value.payment_system_from
|
7
|
+
self.payment_system_to = value.payment_system_to
|
8
|
+
end
|
9
|
+
|
10
|
+
def direction
|
11
|
+
::Gera::Direction.new(ps_from: payment_system_from, ps_to: payment_system_to).freeze
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|