c80_shared 0.1.59 → 0.1.60

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/repositories/accounts/admin_account_repository.rb +35 -0
  3. data/app/repositories/accounts/central_agent_account_repository.rb +46 -0
  4. data/app/repositories/accounts/client_account_repository.rb +43 -0
  5. data/app/repositories/accounts/manager_account_repository.rb +35 -0
  6. data/app/repositories/accounts/manager_guest_account_repository.rb +35 -0
  7. data/app/repositories/accounts/moderator_account_repository.rb +35 -0
  8. data/app/schemas/base.rb +67 -0
  9. data/app/schemas/base_boat_schema.rb +235 -0
  10. data/app/schemas/central_agent/save_boat_schema.rb +57 -0
  11. data/app/services/abstract_prices_service.rb +70 -0
  12. data/app/services/boats/boat_prices_save_service.rb +81 -0
  13. data/app/services/boats/boat_sale_prices_save_service.rb +60 -0
  14. data/app/services/boats/dimension_service.rb +44 -0
  15. data/app/services/central_agent/save_boat_service.rb +111 -0
  16. data/app/services/lease/create_broadcast_inquiry_service.rb +62 -0
  17. data/app/services/lease/destroy_inquiry_service.rb +5 -0
  18. data/config/initializers/core_ext/active_record_log_subscriber.rb +60 -0
  19. data/config/initializers/core_ext/string.rb +62 -0
  20. data/lib/c80_shared/dry/errors.rb +77 -0
  21. data/lib/c80_shared/dry/rule.rb +69 -0
  22. data/lib/c80_shared/dry/rules/and.rb +11 -0
  23. data/lib/c80_shared/dry/rules/between.rb +20 -0
  24. data/lib/c80_shared/dry/rules/binary.rb +18 -0
  25. data/lib/c80_shared/dry/rules/collection.rb +16 -0
  26. data/lib/c80_shared/dry/rules/composite.rb +19 -0
  27. data/lib/c80_shared/dry/rules/equal.rb +18 -0
  28. data/lib/c80_shared/dry/rules/format.rb +18 -0
  29. data/lib/c80_shared/dry/rules/greater_than.rb +18 -0
  30. data/lib/c80_shared/dry/rules/greater_than_or_equal.rb +18 -0
  31. data/lib/c80_shared/dry/rules/included.rb +18 -0
  32. data/lib/c80_shared/dry/rules/length_between.rb +18 -0
  33. data/lib/c80_shared/dry/rules/length_equal.rb +18 -0
  34. data/lib/c80_shared/dry/rules/less_than.rb +18 -0
  35. data/lib/c80_shared/dry/rules/less_than_or_equal.rb +18 -0
  36. data/lib/c80_shared/dry/rules/max_length.rb +18 -0
  37. data/lib/c80_shared/dry/rules/min_length.rb +18 -0
  38. data/lib/c80_shared/dry/rules/not_equal.rb +18 -0
  39. data/lib/c80_shared/dry/rules/or.rb +15 -0
  40. data/lib/c80_shared/dry/rules/present.rb +21 -0
  41. data/lib/c80_shared/dry/rules/then.rb +13 -0
  42. data/lib/c80_shared/dry/rules_factory.rb +118 -0
  43. data/lib/c80_shared/dry/schema.rb +148 -0
  44. data/lib/c80_shared/version.rb +1 -1
  45. data/lib/c80_shared.rb +1 -1
  46. metadata +44 -3
  47. data/scratch_105___02.txt +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 993ce9456590de551437c7445c40261e3c33969538706dcfda35ff0cd432dae7
4
- data.tar.gz: 18ada8fe20f884a4c09754903e5d9fe7659ffa8f4331efbeaf6aa87e1628efc6
3
+ metadata.gz: 041f6a36b9dc94e33939939f808ffa80f7f6d69d34bcef15edc1eb49cbda7d81
4
+ data.tar.gz: 0c92d58789c52d96427c2b92911474f25d139e23f636faca8cb86ea59a9dbc00
5
5
  SHA512:
6
- metadata.gz: 8cfcf130e1d432127c312f57562ec0c3b759869fa24def12c122e51860816a212532d3928bcf2bb86b33951ee67cc9a1a4ff19373394391f26cc76e80be1a58d
7
- data.tar.gz: caf966a932a7ab15322fdcce8803fc4e32c13e73ea463784098132852ac0c640ff29f9e906ff37e3b6fbeeb0339b76ccae003d5c8106bcc7b8c79aa879989c43
6
+ metadata.gz: 698924b53ce5b331eb76555154bad6fe1015ceb33f87170de0b5249acce6c702de9a2efc1bcd146080d34e779734b3b444a59b9c3035eafdb1894a317e6a5c0b
7
+ data.tar.gz: 96996cb21f8db1cae96f2ecaedbd7d42165e0a9879253e34e15796ec88ddd4437d8d356bc495a77a7677c782dbf2b98c5a267933a29ae7b505f1fe9e07e6064d
@@ -0,0 +1,35 @@
1
+ module Accounts
2
+ class AdminAccountRepository
3
+
4
+ def create_account(user)
5
+ return unless user
6
+ return if user.accounts.admins.any?
7
+
8
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::ADMIN)
9
+ admin = ::Accounts::Admin.new(account: account)
10
+
11
+ account.user = user
12
+ account.name = user.name.to_s
13
+ account.active = true
14
+
15
+ account.transaction do
16
+ account.save validate: false
17
+ admin.save validate: false
18
+ end
19
+ end
20
+
21
+ def destroy_account(user)
22
+ return unless user
23
+ return unless user.accounts.admins.any?
24
+
25
+ account = user.accounts.admins.first
26
+ admin = account.admin
27
+
28
+ ActiveRecord::Base.transaction do
29
+ admin.destroy
30
+ account.destroy
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ module Accounts
2
+ class CentralAgentAccountRepository
3
+
4
+ # todo-my: перевести в self.
5
+ def create_account(user)
6
+ return unless user
7
+ return if user.accounts.central_agents.any?
8
+
9
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::CENTRAL_AGENT)
10
+ central = ::Accounts::CentralAgent.new(account: account)
11
+
12
+ account.user = user
13
+ account.name = user.name.to_s
14
+ account.active = true
15
+ user.is_notify = true
16
+
17
+ ActiveRecord::Base.transaction do
18
+ account.save
19
+ central.save
20
+ user.save
21
+ end
22
+
23
+ central
24
+ end
25
+
26
+ # todo-my: перевести в self.
27
+ def destroy_account(user)
28
+ return unless user
29
+ return unless user.accounts.central_agents.any?
30
+
31
+ account = user.accounts.central_agents.first
32
+ central = account.central_agent
33
+
34
+ ActiveRecord::Base.transaction do
35
+ central.destroy
36
+ account.destroy
37
+ end
38
+ end
39
+
40
+ def self.fetch_or_create(user)
41
+ return unless user
42
+ return user.accounts.central_agents.first.central_agent if user.accounts.central_agents.any?
43
+ new.create_account(user)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ module Accounts
2
+ class ClientAccountRepository
3
+
4
+ def fetch_or_create(user)
5
+ return unless user
6
+ return user.accounts.clients.first.client if user.accounts.clients.any?
7
+ create_account(user)
8
+ end
9
+
10
+ def create_account(user)
11
+ return unless user
12
+ return if user.accounts.clients.any?
13
+
14
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::CLIENT)
15
+ client = ::Accounts::Client.new(account: account)
16
+
17
+ account.user = user
18
+ account.name = user.name.to_s
19
+ account.active = true
20
+
21
+ account.transaction do
22
+ account.save validate: false
23
+ client.save validate: false
24
+ end
25
+
26
+ client
27
+ end
28
+
29
+ def destroy_account(user)
30
+ return unless user
31
+ return unless user.accounts.clients.any?
32
+
33
+ account = user.accounts.clients.first
34
+ client = account.client
35
+
36
+ ActiveRecord::Base.transaction do
37
+ client.destroy
38
+ account.destroy
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ module Accounts
2
+ class ManagerAccountRepository
3
+
4
+ def create_account(user)
5
+ return unless user
6
+ return if user.accounts.managers.any?
7
+
8
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::MANAGER)
9
+ manager = ::Accounts::Manager.new(account: account)
10
+
11
+ account.user = user
12
+ account.name = user.name.to_s
13
+ account.active = true
14
+
15
+ account.transaction do
16
+ account.save validate: false
17
+ manager.save validate: false
18
+ end
19
+ end
20
+
21
+ def destroy_account(user)
22
+ return unless user
23
+ return unless user.accounts.managers.any?
24
+
25
+ account = user.accounts.managers.first
26
+ manager = account.manager
27
+
28
+ ActiveRecord::Base.transaction do
29
+ manager.destroy
30
+ account.destroy
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Accounts
2
+ class ManagerGuestAccountRepository
3
+
4
+ def create_account(user)
5
+ return unless user
6
+ return if user.accounts.managers_guests.any?
7
+
8
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::MANAGER_GUEST)
9
+ manager = ::Accounts::ManagerGuest.new(account: account)
10
+
11
+ account.user = user
12
+ account.name = user.name.to_s
13
+ account.active = true
14
+
15
+ account.transaction do
16
+ account.save validate: false
17
+ manager.save validate: false
18
+ end
19
+ end
20
+
21
+ def destroy_account(user)
22
+ return unless user
23
+ return unless user.accounts.managers_guests.any?
24
+
25
+ account = user.accounts.managers_guests.first
26
+ manager = account.manager_guest
27
+
28
+ ActiveRecord::Base.transaction do
29
+ manager.destroy
30
+ account.destroy
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Accounts
2
+ class ModeratorAccountRepository
3
+
4
+ def create_account(user)
5
+ return unless user
6
+ return if user.accounts.moderators.any?
7
+
8
+ account = ::Account.new(type_id: ::Dictionaries::AccountType::MODERATOR)
9
+ moderator = ::Accounts::Moderator.new(account: account)
10
+
11
+ account.user = user
12
+ account.name = user.name.to_s
13
+ account.active = true
14
+
15
+ account.transaction do
16
+ account.save validate: false
17
+ moderator.save validate: false
18
+ end
19
+ end
20
+
21
+ def destroy_account(user)
22
+ return unless user
23
+ return unless user.accounts.moderators.any?
24
+
25
+ account = user.accounts.moderators.first
26
+ moderator = account.moderator
27
+
28
+ ActiveRecord::Base.transaction do
29
+ moderator.destroy
30
+ account.destroy
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,67 @@
1
+ module Schemas
2
+ class Base
3
+
4
+ include Dry::Schema
5
+
6
+ def normalize_integer(value)
7
+ return nil if value.blank?
8
+ Integer(value.to_s.gsub(/\s/, '')) rescue value
9
+ end
10
+
11
+
12
+ def strip_string(value, empty_to_nil = true)
13
+ value = value.to_s.strip
14
+ value = nil if empty_to_nil && value.blank?
15
+ value
16
+ end
17
+
18
+
19
+ def to_date(value)
20
+ value.to_date rescue value
21
+ end
22
+
23
+
24
+ def clear_html(value)
25
+ Rails::Html::WhiteListSanitizer.new.sanitize(value)
26
+ end
27
+
28
+
29
+ def normalize_url(value)
30
+ return if value.blank?
31
+ value.to_s.strip.scan(/^https?:\/\//).present? ? value : sprintf('https://%s', value.to_s.strip)
32
+ end
33
+
34
+
35
+ def to_bool(value)
36
+ value.to_s.to_bool
37
+ end
38
+
39
+
40
+ def to_float(value)
41
+ return unless value.present?
42
+ BigDecimal.new(value.to_s.gsub(/\s/, '')) rescue value
43
+ end
44
+
45
+
46
+ def to_big_decimal(value)
47
+ return unless value.present?
48
+ BigDecimal.new(value.to_s.gsub(/\s/, '')) rescue value
49
+ end
50
+
51
+
52
+ def forced_array(value)
53
+ [value.present? ? value : nil].flatten.compact
54
+ end
55
+
56
+
57
+ def forced_hash(value)
58
+ value.blank? ? {} : value
59
+ end
60
+
61
+
62
+ def nullify_empty(value)
63
+ value.present? ? value : nil
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,235 @@
1
+ require_relative 'base'
2
+
3
+ module Schemas
4
+ class BaseBoatSchema < ::Schemas::Base
5
+ def schema
6
+ result = {
7
+ properties: {
8
+ id: {
9
+ type: %i[null number],
10
+ cast: ->(value) { normalize_integer(value) }
11
+ },
12
+ name: {
13
+ type: [:null, :string],
14
+ cast: ->(value) { clear_html(strip_string(value)) },
15
+ rule: ->(parents) { rule_name(parents) }
16
+ },
17
+ boat_type_id: {
18
+ enum: [nil, -1] + Dicts::BoatType::ALL.collect(&:id),
19
+ cast: ->(value) { normalize_integer(value) },
20
+ rule: ->(parents) { rule_boat_type_id(parents) }
21
+ },
22
+ boat_model: {
23
+ type: %i[null string],
24
+ cast: ->(value) { clear_html(strip_string(value)) }
25
+ },
26
+ builder: {
27
+ type: %i[null string],
28
+ cast: ->(value) { clear_html(strip_string(value)) }
29
+ },
30
+ length: {
31
+ type: :hash,
32
+ required: %i[value length_id],
33
+ properties: {
34
+ value: {
35
+ type: %i[null number string],
36
+ cast: ->(value) { to_float(value) }
37
+ },
38
+ length_id: {
39
+ enum: Dicts::Length.all.collect(&:id),
40
+ cast: ->(value) { normalize_integer(value) }
41
+ }
42
+ }
43
+ },
44
+ crew_total: {
45
+ type: %i[null number],
46
+ cast: ->(value) { normalize_integer(value) }
47
+ },
48
+ guest_cabins: {
49
+ type: %i[null number],
50
+ cast: ->(value) { normalize_integer(value) }
51
+ },
52
+ guests_total: {
53
+ type: %i[null number],
54
+ cast: ->(value) { normalize_integer(value) }
55
+ },
56
+ maximum_guests_during_cruise: {
57
+ type: %i[null number],
58
+ cast: ->(value) { normalize_integer(value) },
59
+ rule: ->(parents) { rule_maximum_guests_during_cruise(parents) }
60
+ },
61
+ boat_locations_attributes: {
62
+ type: %i[null array],
63
+ items: {
64
+ type: :hash,
65
+ required: %i[latitude longitude address is_main _destroy],
66
+ cast: ->(value) do
67
+ value[:latitude] = to_big_decimal value[:latitude]
68
+ value[:longitude] = to_big_decimal value[:longitude]
69
+ value[:address] = strip_string value[:address]
70
+ value[:is_main] = to_bool value[:is_main]
71
+ value[:_destroy] = to_bool value[:_destroy]
72
+
73
+ value[:latitude].nil? || value[:longitude].nil? || !value[:address].present? ? nil : value
74
+ end
75
+ },
76
+ cast: ->(value) { forced_array(value) }
77
+ }
78
+ }
79
+ }
80
+
81
+ result[:properties][:rent_prices] = {
82
+ type: [:null, :array], # это первая версия, где я пробую разобраться с массивом объектов (версия покруче тут - app/getboat/schemas/base_boat_schema.rb - с помощью :items)
83
+ cast: ->(value) do
84
+ value.inject([]) do |res, el|
85
+ el[:_delete] = to_bool el[:_delete]
86
+ el[:currency] = normalize_integer el[:currency]
87
+ el[:discount] = to_float el[:discount]
88
+ el[:duration] = to_float el[:duration]
89
+ el[:season] = normalize_integer el[:season]
90
+ el[:uom] = normalize_integer el[:uom]
91
+ el[:value] = normalize_integer(el[:value].is_a?(String) ? el[:value].split(/[, ]/).join : el[:value])
92
+ res << el
93
+ res
94
+ end
95
+ end
96
+ }
97
+
98
+ result[:properties][:sale_price] = {
99
+ type: [:null, :hash],
100
+ properties: {
101
+ currency_id: {
102
+ enum: Dicts::Currency.all.collect(&:id),
103
+ cast: ->(value) { normalize_integer(value) }
104
+ },
105
+ value: {
106
+ type: %i[number null string],
107
+ cast: ->(value) do
108
+ val = value.is_a?(String) ? value.split(/[, ]/).join : value
109
+ normalize_integer val
110
+ end
111
+ },
112
+ discount: {
113
+ type: %i[number null string],
114
+ cast: ->(value) { to_float(value) }
115
+ },
116
+ }
117
+ }
118
+
119
+ result[:properties][:boat_photos_attributes] = {
120
+ type: [:null, :hash],
121
+ cast: ->(value) { nullify_empty(value) },
122
+ rule: ->(parents) { rule_boat_photos_attributes(parents)}
123
+ }
124
+
125
+ result
126
+ end
127
+
128
+
129
+ def rule_name(parents)
130
+ messages = {
131
+ present: I18n.t('errors.boat.name.blank'),
132
+ length_between: I18n.t('errors.boat.name.length_invalid', min: 2, max: 255)
133
+ }
134
+ rule(:name, parents, messages) { present? & length_between?(2..255) }
135
+ end
136
+
137
+
138
+ def rule_boat_type_id(parents)
139
+ messages = {
140
+ present: I18n.t('errors.boat.boat_type_id.blank'),
141
+ gt: I18n.t('errors.boat.boat_type_id.blank')
142
+ }
143
+ rule(:boat_type_id, parents, messages) { present? & gt?(0) }
144
+ end
145
+
146
+
147
+ def rule_maximum_guests_during_cruise(parents)
148
+ messages = {
149
+ present: I18n.t('errors.boat.maximum_guests_during_cruise.blank'),
150
+ gt: I18n.t('errors.boat.maximum_guests_during_cruise.blank')
151
+ }
152
+ rule(:maximum_guests_during_cruise, parents, messages) { present? & gt?(0) }
153
+ end
154
+
155
+
156
+ def rule_boat_photos_attributes(parents)
157
+ messages = { present: I18n.t('errors.boat.boat_photos_attributes.blank') }
158
+ rule(:boat_photos_attributes, parents, messages) { present? }
159
+ end
160
+
161
+
162
+ def validate_location
163
+ unless boat_locations_attributes
164
+ errors.add :boat_locations, I18n.t('errors.boat.boat_locations.blank')
165
+ return
166
+ end
167
+
168
+ bls = boat_locations_attributes.compact.select { |loc| !loc[:_destroy] }
169
+ mbls = bls.select { |loc| loc[:is_main] }
170
+
171
+ if bls.size.zero?
172
+ errors.add :boat_locations, I18n.t('errors.boat.boat_locations.blank')
173
+ return
174
+ end
175
+
176
+ if bls.size > 5
177
+ errors.add :boat_locations, I18n.t('errors.boat.boat_locations.limit', max: 5)
178
+ return
179
+ end
180
+
181
+ if mbls.size == 0
182
+ errors.add :boat_locations, I18n.t('errors.boat.boat_locations.is_main')
183
+ return
184
+ end
185
+ end
186
+
187
+
188
+ def validate_length
189
+ errors.add(:length_value, I18n.t('errors.boat.length.blank')) unless length[:value]&.nonzero?
190
+ end
191
+
192
+
193
+ def validate_crew_total
194
+ errors.add(:crew_total, I18n.t('errors.boat.crew_total.blank')) unless crew_total.present?
195
+ end
196
+
197
+
198
+ def validate_guests_total
199
+ errors.add(:guests_total, I18n.t('errors.boat.guests_total.blank')) unless guests_total.present?
200
+ end
201
+
202
+
203
+ def validate_guest_cabins
204
+ errors.add(:guest_cabins, I18n.t('errors.boat.guest_cabins.blank')) unless guest_cabins.present?
205
+ end
206
+
207
+
208
+ def validate_prices_and_rent_prices
209
+ rent_prices_present = rent_prices.present? && rent_prices.count { |price| price[:_delete] } < rent_prices.count
210
+ sale_price_present = sale_price.present? && sale_price[:value]&.>(0)
211
+ return if rent_prices_present && sale_price_present
212
+
213
+ if !(rent_prices_present || sale_price_present)
214
+ errors.add :rent_prices, I18n.t('errors.boat.prices.any')
215
+ errors.add :sale_price, I18n.t('errors.boat.prices.any')
216
+ end
217
+ end
218
+
219
+
220
+ def validate_rent_prices
221
+ return unless rent_prices.present?
222
+
223
+ rent_prices.each do |price|
224
+ if price[:value].nil? || price[:value].zero?
225
+ errors.add :rent_prices, I18n.t('errors.boat.rent_prices.invalid')
226
+ break
227
+ end
228
+ if price[:duration].nil? || price[:duration].zero?
229
+ errors.add :rent_prices, I18n.t('errors.boat.rent_prices.invalid_duration')
230
+ break
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,57 @@
1
+ require_relative '../base_boat_schema'
2
+
3
+ module Schemas
4
+ module CentralAgent
5
+ class SaveBoatSchema < Schemas::BaseBoatSchema
6
+ def schema
7
+ boat_schema = super
8
+ boat_schema[:required] = %i[
9
+ name
10
+ boat_type_id
11
+ ]
12
+
13
+ boat_schema[:properties][:boat_photos_attributes] = {
14
+ type: [:null, :hash],
15
+ cast: ->(value) { nullify_empty(value) }
16
+ }
17
+
18
+ # второй вариант реализации property boat_length, который присутствует в базовой схеме
19
+ %i[boat_length_metrics boat_beam_metrics boat_draft_metrics].product([:meters, :ft]).map { |f,d| '%s_%s' % [f,d] }.each do |prop|
20
+ boat_schema[:properties][prop.to_sym] = {
21
+ type: %i[null string number],
22
+ cast: ->(value) do
23
+ val = value.is_a?(String) ? value.split(/[, ]/).join : value
24
+ to_float val
25
+ end
26
+ }
27
+ end
28
+
29
+ boat_schema
30
+ end
31
+
32
+
33
+ def validate_additional
34
+ validate_boat_photos
35
+ validate_prices_and_rent_prices
36
+ validate_rent_prices
37
+ validate_length
38
+ validate_location
39
+ validate_guests_total
40
+ # validate_guest_cabins
41
+ validate_crew_total
42
+ end
43
+
44
+ def validate_boat_photos
45
+ errors.add :boat_photos, I18n.t('errors.boat.boat_photos_attributes.blank') unless boat_photos_attributes.present?
46
+ end
47
+
48
+
49
+ def validate_length
50
+ val = boat_length_metrics_meters || boat_length_metrics_ft
51
+ unless val.present? && val > 0 && val < 1000
52
+ errors.add(:boat_length_metrics, I18n.t('errors.messages.invalid'))
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,70 @@
1
+ class AbstractPricesService
2
+
3
+ attr_reader :built_prices
4
+
5
+ def initialize(all_currencies = ::Dicts::Currency::ALL2) # all_currencies - список валют, в которых надо сохранить цены
6
+ @all_currencies = all_currencies
7
+ _reset_ivars
8
+ end
9
+
10
+ private
11
+
12
+ def _model
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def _fields_for_create
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def _save(prices) # помещаем в базу всё одним запросом
21
+ filtered = prices.select { |el| !el[:_delete] && el[:value].to_i != 0 } # игнорируя цены, которые были помечены "к удалению" или те, у которых значение 0 (0 можно подавать, если хотим "удалить" цену продажи)
22
+ return if filtered.size.zero?
23
+
24
+ values = filtered.map do |p|
25
+ _fields_for_create.map do |field|
26
+ p[field.to_sym]
27
+ end.compact * ','
28
+ end * '),('
29
+ values = '(%s)' % values
30
+ sql = 'INSERT INTO %s(%s) VALUES %s' % [_model.table_name, _fields_for_create * ',', values]
31
+ ActiveRecord::Base.connection.execute sql
32
+
33
+ filtered
34
+ end
35
+
36
+ # из базы удаляем все записи, принадлежащие данной лодке
37
+ # т.к. считаем, что с формы приходит полная картина по ценам
38
+ # кроме того, юзер может просто изменить, например, период в уже
39
+ # существующей строке с ценами, которую он видит на экране
40
+ def _delete_existing_records(boat_id)
41
+ sql = 'DELETE FROM %s WHERE boat_id = %s' % [_model.table_name, boat_id]
42
+ ActiveRecord::Base.connection.execute sql
43
+ end
44
+
45
+ def _build_other(price) # отталкиваясь от валюты входных данных, рассчитываем "те же" цены в других валютах
46
+ return if price[:_delete] || price[:value].to_i == 0 # игнорируя цены, которые были помечены "к удалению" или те, у которых значение 0 (0 можно подавать, если хотим "удалить" цену продажи)
47
+
48
+ incoming_curr = ::Dicts::Currency.find(price[:currency_id])
49
+ currs_to_build = @all_currencies - [incoming_curr]
50
+ rates = Currency.fresh(incoming_curr.index).rates
51
+ rates = JSON.parse(rates)['rates']
52
+
53
+ currs_to_build.each do |curr|
54
+ rate = rates[curr.index]
55
+ res = price.clone
56
+ res[:currency_id] = curr.id
57
+ res[:value] = res[:value].to_f * rate
58
+ res[:is_orig] = false
59
+ @built_prices << res
60
+ end
61
+ end
62
+
63
+ def _delete_bad_values(prices)
64
+ prices.delete_if { |price| price[:value].nil? || price[:value].to_f.zero? }
65
+ end
66
+
67
+ def _reset_ivars
68
+ @built_prices = []
69
+ end
70
+ end