gera 0.3.4

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.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +67 -0
  4. data/Rakefile +43 -0
  5. data/app/assets/config/gera_manifest.js +2 -0
  6. data/app/assets/javascripts/gera/application.js +14 -0
  7. data/app/assets/stylesheets/gera/application.css +15 -0
  8. data/app/authorizers/gera/application_authorizer.rb +6 -0
  9. data/app/authorizers/gera/currency_rate_authorizer.rb +9 -0
  10. data/app/authorizers/gera/currency_rate_mode_authorizer.rb +7 -0
  11. data/app/authorizers/gera/direction_rate_authorizer.rb +8 -0
  12. data/app/authorizers/gera/exchange_rate_authorizer.rb +8 -0
  13. data/app/authorizers/gera/payment_system_authorizer.rb +13 -0
  14. data/app/authorizers/gera/rate_source_authorizer.rb +7 -0
  15. data/app/controllers/gera/application_controller.rb +30 -0
  16. data/app/controllers/gera/currencies_controller.rb +8 -0
  17. data/app/controllers/gera/currency_rate_history_intervals_controller.rb +53 -0
  18. data/app/controllers/gera/currency_rate_mode_snapshots_controller.rb +83 -0
  19. data/app/controllers/gera/currency_rate_modes_controller.rb +60 -0
  20. data/app/controllers/gera/currency_rates_controller.rb +70 -0
  21. data/app/controllers/gera/direction_rate_history_intervals_controller.rb +62 -0
  22. data/app/controllers/gera/direction_rates_controller.rb +28 -0
  23. data/app/controllers/gera/exchange_rates_controller.rb +25 -0
  24. data/app/controllers/gera/external_rate_snapshots_controller.rb +35 -0
  25. data/app/controllers/gera/external_rates_controller.rb +28 -0
  26. data/app/controllers/gera/payment_systems_controller.rb +78 -0
  27. data/app/controllers/gera/rate_sources_controller.rb +8 -0
  28. data/app/decorators/gera/currency_rate_decorator.rb +148 -0
  29. data/app/decorators/gera/direction_rate_decorator.rb +47 -0
  30. data/app/decorators/gera/payment_system_decorator.rb +19 -0
  31. data/app/helpers/gera/application_helper.rb +110 -0
  32. data/app/helpers/gera/currency_rate_helper.rb +19 -0
  33. data/app/helpers/gera/currency_rate_modes_helper.rb +73 -0
  34. data/app/helpers/gera/direction_rate_helper.rb +36 -0
  35. data/app/helpers/gera/exchange_rates_helper.rb +21 -0
  36. data/app/jobs/gera/application_job.rb +6 -0
  37. data/app/models/concerns/gera/currency_pair_generator.rb +14 -0
  38. data/app/models/concerns/gera/currency_pair_support.rb +42 -0
  39. data/app/models/concerns/gera/currency_rate_mode_builder_support.rb +35 -0
  40. data/app/models/concerns/gera/direction_support.rb +14 -0
  41. data/app/models/concerns/gera/history_interval_concern.rb +46 -0
  42. data/app/models/gera/application_record.rb +8 -0
  43. data/app/models/gera/cbr_external_rate.rb +13 -0
  44. data/app/models/gera/cross_rate_mode.rb +13 -0
  45. data/app/models/gera/currency_rate.rb +78 -0
  46. data/app/models/gera/currency_rate_history_interval.rb +25 -0
  47. data/app/models/gera/currency_rate_history_interval_filter.rb +30 -0
  48. data/app/models/gera/currency_rate_mode.rb +20 -0
  49. data/app/models/gera/currency_rate_mode_snapshot.rb +26 -0
  50. data/app/models/gera/currency_rate_snapshot.rb +12 -0
  51. data/app/models/gera/direction.rb +44 -0
  52. data/app/models/gera/direction_rate.rb +136 -0
  53. data/app/models/gera/direction_rate_history_interval.rb +33 -0
  54. data/app/models/gera/direction_rate_history_interval_filter.rb +30 -0
  55. data/app/models/gera/direction_rate_snapshot.rb +7 -0
  56. data/app/models/gera/exchange_rate.rb +130 -0
  57. data/app/models/gera/external_rate.rb +38 -0
  58. data/app/models/gera/external_rate_snapshot.rb +20 -0
  59. data/app/models/gera/payment_system.rb +98 -0
  60. data/app/models/gera/rate_source.rb +77 -0
  61. data/app/models/gera/rate_source_auto.rb +25 -0
  62. data/app/models/gera/rate_source_bitfinex.rb +9 -0
  63. data/app/models/gera/rate_source_cbr.rb +13 -0
  64. data/app/models/gera/rate_source_cbr_avg.rb +6 -0
  65. data/app/models/gera/rate_source_exmo.rb +9 -0
  66. data/app/models/gera/rate_source_manual.rb +13 -0
  67. data/app/views/application/_exchange_rate_monitor.slim +1 -0
  68. data/app/views/gera/application/_attributes_table.slim +5 -0
  69. data/app/views/gera/application/_currencies_table.slim +18 -0
  70. data/app/views/gera/application/_currency_rate_mode_snapshots.slim +6 -0
  71. data/app/views/gera/application/_direction_rate.slim +6 -0
  72. data/app/views/gera/application/_directions_submenu.slim +11 -0
  73. data/app/views/gera/application/_directions_table.slim +15 -0
  74. data/app/views/gera/application/_exchange_rate.slim +6 -0
  75. data/app/views/gera/application/_external_rate.slim +6 -0
  76. data/app/views/gera/application/_header.slim +12 -0
  77. data/app/views/gera/application/_table.slim +28 -0
  78. data/app/views/gera/application/_topnav.slim +21 -0
  79. data/app/views/gera/application/direction_details.slim +75 -0
  80. data/app/views/gera/application/page.html.slim +1 -0
  81. data/app/views/gera/currencies/index.html.slim +20 -0
  82. data/app/views/gera/currency_rate_history_intervals/_filter.slim +11 -0
  83. data/app/views/gera/currency_rate_history_intervals/index.slim +39 -0
  84. data/app/views/gera/currency_rate_mode_snapshots/_snapshot.slim +20 -0
  85. data/app/views/gera/currency_rate_mode_snapshots/edit.html.slim +30 -0
  86. data/app/views/gera/currency_rate_modes/_cross_rate_mode_fields.slim +21 -0
  87. data/app/views/gera/currency_rate_modes/_currency_rate_mode.slim +7 -0
  88. data/app/views/gera/currency_rate_modes/_form.slim +29 -0
  89. data/app/views/gera/currency_rate_modes/edit.slim +11 -0
  90. data/app/views/gera/currency_rate_modes/index.html.slim +12 -0
  91. data/app/views/gera/currency_rates/_currency_rate.slim +22 -0
  92. data/app/views/gera/currency_rates/_currency_rate_humanized.slim +35 -0
  93. data/app/views/gera/currency_rates/diff.slim +12 -0
  94. data/app/views/gera/currency_rates/index.slim +27 -0
  95. data/app/views/gera/currency_rates/modes.slim +14 -0
  96. data/app/views/gera/currency_rates/show.slim +4 -0
  97. data/app/views/gera/direction_rate_history_intervals/_filter.slim +11 -0
  98. data/app/views/gera/direction_rate_history_intervals/index.slim +41 -0
  99. data/app/views/gera/direction_rates/_direction_rate_example_calculator.slim +28 -0
  100. data/app/views/gera/direction_rates/diff.slim +19 -0
  101. data/app/views/gera/direction_rates/index.slim +26 -0
  102. data/app/views/gera/direction_rates/legacy.html.slim +5 -0
  103. data/app/views/gera/direction_rates/minimals.slim +5 -0
  104. data/app/views/gera/direction_rates/show.slim +14 -0
  105. data/app/views/gera/external_rate_snapshots/index.slim +25 -0
  106. data/app/views/gera/external_rate_snapshots/show.slim +22 -0
  107. data/app/views/gera/external_rates/_flat_list.slim +22 -0
  108. data/app/views/gera/external_rates/index.html.slim +28 -0
  109. data/app/views/gera/external_rates/show.slim +1 -0
  110. data/app/views/gera/payment_systems/_fields.slim +4 -0
  111. data/app/views/gera/payment_systems/_fields_table.slim +18 -0
  112. data/app/views/gera/payment_systems/_form.slim +9 -0
  113. data/app/views/gera/payment_systems/edit.slim +7 -0
  114. data/app/views/gera/payment_systems/index.slim +3 -0
  115. data/app/views/gera/payment_systems/new.slim +9 -0
  116. data/app/views/gera/payment_systems/show.slim +1 -0
  117. data/app/views/gera/rate_sources/_list.slim +13 -0
  118. data/app/views/gera/rate_sources/_rate_source.slim +23 -0
  119. data/app/views/gera/rate_sources/index.html.slim +6 -0
  120. data/app/views/layouts/application.html.slim +15 -0
  121. data/app/views/layouts/gera/blank.html.slim +10 -0
  122. data/app/workers/concerns/gera/rates_worker.rb +87 -0
  123. data/app/workers/gera/bitfinex_rates_worker.rb +65 -0
  124. data/app/workers/gera/cbr_avg_rates_worker.rb +42 -0
  125. data/app/workers/gera/cbr_rates_worker.rb +192 -0
  126. data/app/workers/gera/create_history_intervals_worker.rb +38 -0
  127. data/app/workers/gera/currency_rates_worker.rb +64 -0
  128. data/app/workers/gera/directions_rates_worker.rb +51 -0
  129. data/app/workers/gera/exmo_rates_worker.rb +62 -0
  130. data/app/workers/gera/purge_currency_rates_worker.rb +21 -0
  131. data/app/workers/gera/purge_direction_rates_worker.rb +30 -0
  132. data/config/currencies.yml +559 -0
  133. data/config/routes.rb +30 -0
  134. data/db/migrate/20180912130000_setup.rb +228 -0
  135. data/db/migrate/20190314114844_add_is_available_to_payment_systems.rb +7 -0
  136. data/db/migrate/20190315113046_add_icon_url_to_payment_systems.rb +7 -0
  137. data/db/migrate/20190315132137_add_commission_to_payment_systems.rb +7 -0
  138. data/lib/banks/currency_exchange.rb +12 -0
  139. data/lib/builders/currency_rate_auto_builder.rb +38 -0
  140. data/lib/builders/currency_rate_builder.rb +60 -0
  141. data/lib/builders/currency_rate_cross_builder.rb +70 -0
  142. data/lib/builders/currency_rate_direct_builder.rb +26 -0
  143. data/lib/gera.rb +32 -0
  144. data/lib/gera/bitfinex_fetcher.rb +36 -0
  145. data/lib/gera/configuration.rb +47 -0
  146. data/lib/gera/currencies_purger.rb +28 -0
  147. data/lib/gera/currency_pair.rb +93 -0
  148. data/lib/gera/engine.rb +14 -0
  149. data/lib/gera/mathematic.rb +156 -0
  150. data/lib/gera/money_support.rb +89 -0
  151. data/lib/gera/numeric.rb +25 -0
  152. data/lib/gera/railtie.rb +8 -0
  153. data/lib/gera/rate.rb +22 -0
  154. data/lib/gera/rate_from_multiplicator.rb +54 -0
  155. data/lib/gera/repositories/currency_rate_modes_repository.rb +37 -0
  156. data/lib/gera/repositories/currency_rates_repository.rb +25 -0
  157. data/lib/gera/repositories/direction_rates_repository.rb +46 -0
  158. data/lib/gera/repositories/exchange_rates_repository.rb +23 -0
  159. data/lib/gera/repositories/payment_systems_repository.rb +21 -0
  160. data/lib/gera/repositories/universe.rb +47 -0
  161. data/lib/gera/version.rb +3 -0
  162. data/lib/tasks/auto_generate_diagram.rake +6 -0
  163. data/lib/tasks/gera_tasks.rake +4 -0
  164. metadata +765 -0
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+
5
+ module Gera
6
+ class CurrencyRatesController < Gera::ApplicationController
7
+ authorize_actions_for CurrencyRate
8
+ authority_actions modes: :read
9
+
10
+ helper_method :source
11
+
12
+ def index
13
+ if snapshot.present?
14
+ render locals: {
15
+ rates: snapshot.rates,
16
+ created_at: snapshot.created_at
17
+ }
18
+ else
19
+ render :page, locals: { message: 'No current currency rate snapshot found' }
20
+ end
21
+ end
22
+
23
+ def show
24
+ render locals: {
25
+ currency_rate: currency_rate,
26
+ currency_pair: currency_rate.currency_pair
27
+ }
28
+ end
29
+
30
+ def modes
31
+ body = CSV.generate do |csv|
32
+ line = ['income\outcome']
33
+ line += Money::Currency.all.map(&:to_s)
34
+ csv << line
35
+ Money::Currency.all.each do |cur_from|
36
+ line = [cur_from]
37
+ Money::Currency.all.each do |cur_to|
38
+ rate = snapshot.rates.find_by(cur_from: cur_from.iso_code, cur_to: cur_to.iso_code)
39
+ d = CurrencyRateDecorator.decorate rate
40
+ line << d.mode
41
+ end
42
+ csv << line
43
+ end
44
+ end
45
+
46
+ respond_to do |format|
47
+ format.html { raise 'CSV only supported' }
48
+ format.csv { send_data body, filename: "exchange_rates-modes-#{Date.today}.csv" }
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def source
55
+ params[:source]
56
+ end
57
+
58
+ def currency_rate
59
+ @currency_rate ||= CurrencyRate.find params[:id]
60
+ end
61
+
62
+ def currency_pair
63
+ @currency_pair ||= CurrencyPair.new cur_from: params[:cur_from], cur_to: params[:cur_to]
64
+ end
65
+
66
+ def snapshot
67
+ Universe.currency_rates_repository.snapshot
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+ module Gera
5
+ class DirectionRateHistoryIntervalsController < ApplicationController
6
+ authorize_actions_for DirectionRate
7
+ helper_method :payment_system_from, :payment_system_to
8
+ helper_method :filter
9
+
10
+ def index
11
+ respond_to do |format|
12
+ format.html { render locals: { title: title, value_decimals: value_decimals } }
13
+ format.json { render json: intervals }
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def value_decimals
20
+ if filter.value_type == 'comission'
21
+ 3
22
+ else
23
+ 4
24
+ end
25
+ end
26
+
27
+ def title
28
+ "График конечного курса для направление #{filter.payment_system_from}->#{filter.payment_system_to}"
29
+ end
30
+
31
+ def filter
32
+ @filter ||= DirectionRateHistoryIntervalFilter.new params.fetch(:direction_rate_history_interval_filter, {}).permit!
33
+ end
34
+
35
+ def prepare_rate_value(value)
36
+ inverse? ? 1.0 / value : value
37
+ end
38
+
39
+ def inverse?
40
+ @inverse ||= Money.from_amount(1, filter.payment_system_from.currency).exchange_to(filter.payment_system_to.currency).to_f < 1
41
+ end
42
+
43
+ def intervals
44
+ scope = DirectionRateHistoryInterval
45
+ .where(payment_system_to_id: filter.payment_system_to_id, payment_system_from_id: filter.payment_system_from_id)
46
+ .order(:interval_from)
47
+
48
+ case filter.value_type
49
+ when 'rate'
50
+ scope
51
+ .pluck(:interval_from, :min_rate, :max_rate)
52
+ .map { |time, min, max| [time.to_f * 1000, prepare_rate_value(min), prepare_rate_value(max), prepare_rate_value(min), prepare_rate_value(max)] }
53
+ when 'comission'
54
+ scope
55
+ .pluck(:interval_from, :min_comission, :max_comission)
56
+ .map { |time, min, max| [time.to_f * 1000, min, max, min, max] }
57
+ else
58
+ raise "Unknown value_type #{filter.value_type}"
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gera
4
+ class DirectionRatesController < Gera::ApplicationController
5
+ authorize_actions_for DirectionRate
6
+ authority_actions last: :read
7
+
8
+ # TODO: use params from show
9
+ def last
10
+ exchange_rate = direction_rate.exchange_rate
11
+ dr = Universe.direction_rates_repository.find_direction_rate_by_exchange_rate_id exchange_rate.id
12
+
13
+ redirect_to direction_rate_path(dr), flash: { success: "Перекинули на страницу курса от #{I18n.l dr.created_at, format: :long}" }
14
+ end
15
+
16
+ def show
17
+ render locals: {
18
+ direction_rate: direction_rate
19
+ }
20
+ end
21
+
22
+ private
23
+
24
+ def direction_rate
25
+ @direction_rate ||= DirectionRate.find params[:id]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+
5
+ module Gera
6
+ class ExchangeRatesController < ApplicationController
7
+ authorize_actions_for ExchangeRate
8
+
9
+ def show
10
+ render locals: {
11
+ exchange_rate: exchange_rate
12
+ }
13
+ end
14
+
15
+ def details
16
+ render 'direction_details', locals: { direction: exchange_rate.direction }, layout: nil
17
+ end
18
+
19
+ private
20
+
21
+ def exchange_rate
22
+ @exchange_rate ||= ExchangeRate.find params[:id]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+ module Gera
5
+ class ExternalRateSnapshotsController < ApplicationController
6
+ authorize_actions_for ExchangeRate
7
+
8
+ PER_PAGE = 200
9
+ helper_method :rate_source
10
+
11
+ def index
12
+ render locals: {
13
+ snapshots: snapshots
14
+ }
15
+ end
16
+
17
+ def show
18
+ snapshot = ExternalRateSnapshot.find params[:id]
19
+
20
+ render locals: {
21
+ snapshot: snapshot
22
+ }
23
+ end
24
+
25
+ private
26
+
27
+ def rate_source
28
+ RateSource.find params[:rate_source_id]
29
+ end
30
+
31
+ def snapshots
32
+ rate_source.snapshots.ordered.page(params[:page]).per(params[:per] || PER_PAGE)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+ module Gera
5
+ class ExternalRatesController < ApplicationController
6
+ authorize_actions_for ExchangeRate
7
+
8
+ def index
9
+ if params[:rate_source_id].present?
10
+ redirect_to external_rate_snapshots_path(rate_source_id: params[:rate_source_id])
11
+ else
12
+ redirect_to rate_sources_path
13
+ end
14
+ end
15
+
16
+ def show
17
+ render locals: {
18
+ external_rate: external_rate
19
+ }
20
+ end
21
+
22
+ private
23
+
24
+ def external_rate
25
+ ExternalRate.find params[:id]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+ module Gera
5
+ class PaymentSystemsController < ApplicationController
6
+ authorize_actions_for PaymentSystem
7
+
8
+ EDIT_COLUMNS = %i[
9
+ name icon_url currency
10
+ income_enabled outcome_enabled
11
+ ].freeze
12
+
13
+ SHOW_COLUMNS = %i[
14
+ id icon_url name currency
15
+ income_enabled outcome_enabled
16
+ actions
17
+ ].freeze
18
+
19
+ def index
20
+ render locals: {
21
+ payment_systems: PaymentSystem.order(:id),
22
+ columns: SHOW_COLUMNS
23
+ }
24
+ end
25
+
26
+ def show
27
+ render locals: {
28
+ payment_system: PaymentSystem.find(params[:id]),
29
+ columns: SHOW_COLUMNS
30
+ }
31
+ end
32
+
33
+ def new
34
+ render locals: {
35
+ payment_system: PaymentSystem.new,
36
+ columns: EDIT_COLUMNS
37
+ }
38
+ end
39
+
40
+ def create
41
+ PaymentSystem.create! permitter_params
42
+ rescue ActiveRecord::RecordInvalid => e
43
+ render :new, locals: {
44
+ payment_system: e.record,
45
+ columns: EDIT_COLUMNS
46
+ }
47
+ end
48
+
49
+ def edit
50
+ render locals: {
51
+ payment_system: PaymentSystem.find(params[:id]),
52
+ columns: EDIT_COLUMNS
53
+ }
54
+ end
55
+
56
+ def update
57
+ respond_to do |format|
58
+ if payment_system.update_attributes permitter_params
59
+ format.html { redirect_to(payment_systems_path, notice: 'Status was successfully updated.') }
60
+ format.json { respond_with_bip(payment_system) }
61
+ else
62
+ format.html { render action: 'edit', locals: { payment_system: payment_system, columns: EDIT_COLUMNS } }
63
+ format.json { respond_with_bip(payment_system) }
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def payment_system
71
+ @payment_system ||= PaymentSystem.find params[:id]
72
+ end
73
+
74
+ def permitter_params
75
+ params[:payment_system].permit!
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'application_controller'
4
+ module Gera
5
+ class RateSourcesController < ApplicationController
6
+ authorize_actions_for RateSource
7
+ end
8
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gera
4
+ class CurrencyRateDecorator < ApplicationDecorator
5
+ delegate :mode, :id, :external_rate_id, :meta, :rate_value
6
+
7
+ def detailed
8
+ buffer = []
9
+ buffer << if object.mode_cross?
10
+ 'cross'
11
+ else
12
+ object.rate_source.to_s # if object.rate_source.present?
13
+ end
14
+
15
+ buffer.join(' × ').html_safe
16
+ end
17
+
18
+ def external_rate
19
+ return unless object.external_rate_id.present?
20
+
21
+ er = object.external_rate
22
+ buffer = if [:exmo_sell].include? mode.to_sym
23
+ "#{h.humanized_rate_detailed er.sell_price} (из колонки 'продажа')"
24
+ elsif [:exmo_buy].include? mode.to_sym
25
+ "#{h.humanized_rate_detailed er.buy_price} (из колонки 'покупка')"
26
+ elsif [:cbr_min].include? mode.to_sym
27
+ "#{h.humanized_rate_detailed er.rate}<br/>(минимальный из пары #{object.meta.rates})"
28
+ elsif [:cbr_max].include? mode.to_sym
29
+ "#{h.humanized_rate_detailed er.rate}<br/>(максимальный из пары #{object.meta.rates})"
30
+ else
31
+ 'WTF?'
32
+ end
33
+
34
+ buffer = buffer + ' от ' + I18n.l(er.created_at, format: :long)
35
+
36
+ h.link_to buffer.html_safe, h.external_rate_path(er)
37
+ end
38
+
39
+ def tooltip
40
+ buffer = []
41
+ buffer << "Покупаем 1 #{object.cur_from} за #{object.rate_value} #{object.cur_to}"
42
+ buffer << "Покупаем 1 #{object.currency_pair.first} за #{h.humanized_rate object.rate_value} #{object.currency_pair.second}".html_safe
43
+ buffer << "Продаем 1 #{object.cur_to} за #{1.0 / object.rate_value} #{object.cur_from}"
44
+ buffer = buffer.join "\n"
45
+ h.simple_format(buffer).html_safe
46
+ end
47
+
48
+ def created_at
49
+ h.link_to h.currency_rate_path(object) do
50
+ if object.created_at.present?
51
+ I18n.l object.created_at, format: :long
52
+ else
53
+ 'время создания не известно'
54
+ end
55
+ end
56
+ end
57
+
58
+ def source_external_rate
59
+ return '-' unless object.source_external_rate_id.present?
60
+
61
+ er = Gera::ExternalRate.find object.source_external_rate_id
62
+ h.link_to h.external_rate_path(er) do
63
+ "Источник EXMO\n#{I18n.l er.created_at, format: :long}\n#{er.buy_price}/#{er.sell_price}"
64
+ end
65
+ end
66
+
67
+ def reverse_currency_rate
68
+ return '-' unless object.reverse_currency_rate_id
69
+
70
+ cer = Gera::CurrencyRate.find object.reverse_currency_rate_id
71
+ cerd = CurrencyRateDecorator.decorate(cer)
72
+ h.link_to cerd.short_description, h.currency_rate_path(cer)
73
+ end
74
+
75
+ def short_description
76
+ "#{title} (#{object.buy_rate}) #{comment}".html_safe
77
+ end
78
+
79
+ def title
80
+ to_s
81
+ end
82
+
83
+ def rate_value
84
+ h.humanized_rate_detailed object.rate_value
85
+ end
86
+
87
+ def metadata
88
+ h.content_tag :code, object.metadata.to_json
89
+ end
90
+
91
+ def comment(inverse = false)
92
+ return object.mode
93
+ send "comment_#{object.source}", inverse
94
+ rescue ActiveRecord::RecordNotFound
95
+ raise "Не найдена одна из зависимых записей для #{object.id}"
96
+ end
97
+
98
+ def comment_equal(_inverse)
99
+ 'Одинаковый тип валюты'
100
+ end
101
+
102
+ def comment_inderect(_inverse)
103
+ r1 = CurrencyRateDecorator.decorate object.rate1_currency_rate
104
+ r2 = CurrencyRateDecorator.decorate object.rate2_currency_rate
105
+ "Через #{object.meta.inter_cur}\n" \
106
+ "Продажа:\n" \
107
+ "#{object.rate1_currency_rate.rate_money.format} за #{object.rate1_currency_rate.cur_from}\n(#{r1.comment})\n" \
108
+ "#{object.rate2_currency_rate.rate_money.format} за #{object.rate2_currency_rate.cur_from}\n(#{r2.comment})"
109
+ end
110
+
111
+ def comment_exmo(inverse)
112
+ er = Gera::ExternalRate.find object.meta.external_rate_id
113
+ ExternalRateDecorator.decorate(er).comment inverse
114
+ end
115
+
116
+ def comment_cbr(inverse)
117
+ # min_rate = Gera::ExternalRate.find object.meta.min_external_rate_id
118
+ max_rate = Gera::ExternalRate.find object.meta.max_external_rate_id
119
+ # min_rate_d = ExternalRateDecorator.decorate min_rate
120
+ max_rate_d = ExternalRateDecorator.decorate max_rate
121
+
122
+ max_rate_d.comment inverse
123
+ end
124
+
125
+ def comment_reverse(_inverse)
126
+ [
127
+ "Инверсия (#{object.reverse_currency_rate.pair})",
128
+ object.reverse_currency_rate.buy_rate,
129
+ CurrencyRateDecorator.decorate(object.reverse_currency_rate).comment(true)
130
+ ].join "\n"
131
+ end
132
+
133
+ private
134
+
135
+ def muted(content)
136
+ h.content_tag :span, content, class: 'text-muted'
137
+ end
138
+
139
+ def source(currency_rate)
140
+ buffer = if currency_rate.mode_cross?
141
+ CurrencyRateDecorator.decorate(currency_rate).detailed
142
+ else
143
+ currency_rate.rate_source.presence || currency_rate.mode
144
+ end
145
+ "(#{buffer})".html_safe
146
+ end
147
+ end
148
+ end