c80_shared 0.1.69 → 0.1.70

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a51c1503139e06e27c0a6734a20c44bff15f5ba150c776ff4ad5be6739206004
4
- data.tar.gz: 39343ca14d3ccb8817c2be53812529b7e00041e89f19d435bf2df6cd002139b8
3
+ metadata.gz: 2c3214907b93916e8e43bf0d80847168d6e8ae568bc62e22fff7e34637221b35
4
+ data.tar.gz: 2bc2128ec79443d16fe8f7b67c0cd0c1131067b6c1807bc3e96041ce5af0d493
5
5
  SHA512:
6
- metadata.gz: 8a9eaf0707a2282394a2511fb25676b3c06708e0c0b4ae27039c7e7ae03ef486ade82b403647c42a7e5d22bf2a165f294cd650d5a403bbd867e99203f49cd858
7
- data.tar.gz: 42287fcb2ab7e5d759951199508cd8ab564cecb1697dd19a482ae02d3c7aa4ddc04f056f80bc14b0e48c2606a439428c2400a0c8af8f7e6150ac9b482996d257
6
+ metadata.gz: 824d6dae5f5b4619d94a7408276e62afacae379e5100268d5af691531e805a99464c523b5f98004127741e70009c50937350b05df6c4ac3a30c483f919e3bacd
7
+ data.tar.gz: 9a2cae54b524a337834a98f2a3b78194d9eb9b11b4d3db0db19dfec6b2f3c9a5481e54dc2260914be63877169ba90476a1f3d6ba6ae767a113c5a68275639a62
@@ -2,5 +2,6 @@ module Dicts
2
2
  class EventType < ::Dict
3
3
  MANAGER_LEASE_BID_MAKE = new 1, 'manager_lease_bid_make'
4
4
  AGENT_LEASE_BID_MAKE = new 2, 'agent_lease_bid_make'
5
+ REJECT = new 3, 'reject'
5
6
  end
6
7
  end
@@ -0,0 +1,17 @@
1
+ module Dicts
2
+ class RejectType < ::Dict
3
+
4
+ attr_reader :type
5
+
6
+ def initialize(id, index, type)
7
+ @type = type
8
+ super id, index
9
+ end
10
+
11
+ LEASE_INQUIRY = new 1, 'user_lease_inquiry', '::Lease::Inquiry' # какой-то юзер оставляет заявку на аренду
12
+ LIST_YOR_BOAT = new 2, 'user_list_your_boat', '::Boat' # какой-то юзер пытается добавить лодку с помощью фичи LIST YOUR BOAT
13
+ CREATE_BOAT = new 3, 'agent_create_boat', '::Boat' # агент пытается добавить лодку
14
+ UPDATE_BOAT = new 4, 'agent_update_boat', '::Boat' # агент пытается обновить лодку
15
+
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ class ApplicationForm
2
+ include ActiveModel::Model
3
+ include ActiveModel::Validations
4
+
5
+ def self.all_fields
6
+ @all_fields ||= {}
7
+ end
8
+
9
+ def self.fields(model, *names)
10
+ unless all_fields.key? model
11
+ attr_reader model
12
+
13
+ define_method :"validate_#{model}!" do
14
+ own = send model
15
+
16
+ unless own.valid?
17
+ errors.messages.merge!(own.errors.messages) { |_, ary1, ary2| ary1 + ary2 }
18
+ errors.details.merge!(own.errors.details) { |_, ary1, ary2| ary1 + ary2 }
19
+ end
20
+ end
21
+
22
+ validate :"validate_#{model}!"
23
+
24
+ all_fields[model] = []
25
+ end
26
+
27
+ delegate *names, to: model
28
+
29
+ all_fields[model] = all_fields[model] + names
30
+ all_fields[model].uniq!
31
+ all_fields
32
+ end
33
+
34
+ def persisted?
35
+ false
36
+ end
37
+
38
+ def to_h
39
+ self.class.all_fields.map { |a| [a, self.send(a)] if self.respond_to?(a) }.compact.to_h
40
+ end
41
+ end
@@ -0,0 +1,111 @@
1
+ class RentForm < ApplicationForm
2
+ include DatesNowValidator
3
+
4
+ FIELDS = %i[
5
+ address
6
+ latitude
7
+ longitude
8
+ location_address
9
+ name
10
+ from
11
+ to
12
+ guests
13
+ kids
14
+ boat_types
15
+ is_skippered
16
+ is_my_price
17
+ my_price_currency
18
+ my_price
19
+ watersports
20
+ need_transfer
21
+ comments
22
+ email
23
+ name
24
+ phone_number
25
+ password
26
+ sms_code
27
+ staying_overnight
28
+ uploaded_license_file
29
+ hours_per_day
30
+ ].freeze
31
+
32
+ attr_accessor *FIELDS
33
+
34
+ validates :address,
35
+ :latitude,
36
+ :longitude,
37
+ :from,
38
+ :to,
39
+ :email,
40
+ :name,
41
+ :phone_number, presence: true
42
+
43
+ validates :phone_number, phony_plausible: true
44
+ validates :email, email: { strict_mode: true }
45
+
46
+ validates :kids, numericality: { greater_than_or_equal_to: 0 }, if: -> { kids.present? }
47
+ validates :guests, numericality: { greater_than_or_equal_to: 0 }
48
+
49
+ validates :my_price, numericality: { greater_than_or_equal_to: 0 }, if: -> { !my_price.to_i.zero? }
50
+ validates :my_price_currency, presence: true, length: { minimum: 3, maximum: 3 }, allow_blank: false, if: -> { !my_price.to_i.zero? }
51
+
52
+ # validates :uploaded_license_file, presence: true, allow_blank: false, if: -> { is_skippered == 'false' }
53
+ validate :validate_license
54
+
55
+ validate :validate_dates
56
+ validate :validate_boat_types
57
+ validate :validate_address
58
+
59
+ attr_reader :is_need_bareboat_license
60
+
61
+ def initialize(params = nil, is_need_bareboat_license = true)
62
+ self.send(:is_my_price=, !params[:my_price].to_i.zero?) unless params.nil?
63
+ @is_need_bareboat_license = is_need_bareboat_license
64
+
65
+ super params
66
+ end
67
+
68
+ def validate_license
69
+ return unless @is_need_bareboat_license
70
+ return unless is_skippered.eql?('false')
71
+
72
+ unless uploaded_license_file.present?
73
+ errors.add(:uploaded_license_file, :presence)
74
+ end
75
+ end
76
+
77
+ def button_name
78
+ I18n.t(:new_rent_order)
79
+ end
80
+
81
+ def validate_dates
82
+ check_dates errors, from, to
83
+ end
84
+
85
+ def validate_boat_types
86
+ if boat_types.nil? || boat_types.empty?
87
+ errors.add(:boat_types, :absent)
88
+ else
89
+ unless BoatType.where(id: boat_types.map(&:to_i)).exists?
90
+ errors.add(:boat_types, :absent)
91
+ end
92
+ end
93
+ end
94
+
95
+ def validate_address
96
+ conditions = [
97
+ address.empty?,
98
+ latitude.to_f.zero?,
99
+ longitude.to_f.zero?,
100
+ latitude.to_i < -90,
101
+ latitude.to_i > 90,
102
+ longitude.to_i < -180,
103
+ longitude.to_i > 180,
104
+ ]
105
+
106
+ if conditions.any?
107
+ errors.add(:address, :invalid_address)
108
+ end
109
+ end
110
+
111
+ end
@@ -79,7 +79,7 @@ module Schemas
79
79
  result[:properties][:rent_prices] = {
80
80
  type: [:null, :array], # это первая версия, где я пробую разобраться с массивом объектов (версия покруче тут - app/getboat/schemas/base_boat_schema.rb - с помощью :items)
81
81
  cast: ->(value) do
82
- value.inject([]) do |res, el|
82
+ value&.inject([]) do |res, el|
83
83
  el[:_delete] = to_bool el[:_delete]
84
84
  el[:currency] = normalize_integer el[:currency]
85
85
  el[:discount] = to_float el[:discount]
@@ -0,0 +1,85 @@
1
+ module Schemas
2
+ module Site
3
+ class RegisterBoatSchema < Schemas::BaseBoatSchema
4
+
5
+ def schema
6
+ super_schema = super
7
+
8
+ super_schema[:required] = %i[
9
+ name
10
+ boat_type_id
11
+ boat_model
12
+ builder
13
+ length
14
+ crew_total
15
+ guest_cabins
16
+ guests_total
17
+ maximum_guests_during_cruise
18
+ boat_price
19
+ boat_sale_price
20
+ ]
21
+
22
+ super_schema[:properties][:boat_price] = {
23
+ type: :hash,
24
+ required: %i[duration uom_id season_id currency_id value],
25
+ properties: {
26
+ duration: {
27
+ type: :number,
28
+ cast: ->(value) { normalize_integer(value) }
29
+ },
30
+ uom_id: {
31
+ enum: Dicts::CharterUom.all.collect(&:id),
32
+ cast: ->(value) { normalize_integer(value) }
33
+ },
34
+ season_id: {
35
+ enum: Dicts::CharterSeason.all.collect(&:id),
36
+ cast: ->(value) { normalize_integer(value) }
37
+ },
38
+ currency_id: {
39
+ enum: Dicts::Currency.all.collect(&:id),
40
+ cast: ->(value) { normalize_integer(value) }
41
+ },
42
+ value: {
43
+ type: %i[number nil],
44
+ cast: ->(value) { normalize_integer(value) }
45
+ }
46
+ }
47
+ }
48
+
49
+ super_schema[:properties][:boat_sale_price] = {
50
+ type: :hash,
51
+ required: %i[value currency_id],
52
+ properties: {
53
+ currency_id: {
54
+ enum: Dicts::Currency.all.collect(&:id),
55
+ cast: ->(value) { normalize_integer(value) }
56
+ },
57
+ value: {
58
+ type: %i[number nil],
59
+ cast: ->(value) { normalize_integer(value) }
60
+ }
61
+ }
62
+ }
63
+
64
+ super_schema
65
+ end
66
+
67
+ def validate_additional
68
+ validate_prices
69
+ validate_location
70
+ validate_length
71
+ # validate_crew_total
72
+ # validate_guest_cabins
73
+ validate_guests_total
74
+ end
75
+
76
+ # noinspection RubyResolve
77
+ def validate_prices
78
+ unless boat_price[:value]&.nonzero? || boat_sale_price[:value]&.nonzero?
79
+ errors.add :prices, I18n.t('errors.boat.prices.any')
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,40 @@
1
+ module Events
2
+ class RejectsRepository
3
+
4
+ def self.create(reject_type_id, language_id, params, error_messages, current_user = nil)
5
+ raise ArgumentError, '`error_messages` must be String' unless error_messages.class.eql? String
6
+ raise ArgumentError, '`params` must be Hash' unless params.class.eql? Hash
7
+ raise ArgumentError, '`current_user` должен быть подан, когда создаётся лодка в кабинете' if current_user.nil? && reject_type_id == ::Dicts::RejectType::CREATE_BOAT.id
8
+ raise ArgumentError, '`current_user` должен быть подан, когда обновляется лодка в кабинете' if current_user.nil? && reject_type_id == ::Dicts::RejectType::UPDATE_BOAT.id
9
+
10
+ event = ::Event.new type_id: ::Dicts::EventType::REJECT.id
11
+ r_event = ::Events::Reject.new event: event
12
+
13
+ r_event.reject_type_id = reject_type_id
14
+ r_event.language_id = language_id
15
+ r_event.params = params.to_json
16
+ r_event.error_messages = error_messages
17
+
18
+ case reject_type_id
19
+ when ::Dicts::RejectType::LEASE_INQUIRY.id
20
+ r_event.email = params['email']
21
+ when ::Dicts::RejectType::LIST_YOR_BOAT.id
22
+ r_event.email = params['users_attributes']['0']['email']
23
+ when ::Dicts::RejectType::CREATE_BOAT.id
24
+ r_event.email = current_user.email
25
+ when ::Dicts::RejectType::UPDATE_BOAT.id
26
+ r_event.email = current_user.email
27
+ else
28
+ r_event.email = ''
29
+ end
30
+
31
+ event.transaction do
32
+ event.save
33
+ r_event.save
34
+ end
35
+
36
+ r_event
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,120 @@
1
+ class BoatRegisterService
2
+
3
+ attr_reader :boat,
4
+ :errors,
5
+ :user
6
+
7
+ def initialize
8
+ _reset_instance_variables
9
+ end
10
+
11
+ # @param boat_params - параметры лодки, пришедшие с формы регистрации лодки
12
+ # @param request - нужен только для того, чтобы установить ip юзеру
13
+ # @param user - это current_user (в номинальном режиме)
14
+ #
15
+ def perform(boat_params, request, user = nil)
16
+ _reset_instance_variables
17
+
18
+ schema = ::Schemas::Site::RegisterBoatSchema.new boat_params # проверяем параметры, пришедшие с формы
19
+ unless schema.valid?
20
+ @errors = schema.errors.messages
21
+ return false
22
+ end
23
+
24
+ _create_user(boat_params.dig(:users_attributes, '0'), user) # # затем создаём и проверяем юзера == NOTE: такой странный хэш приходит 100%, если в модели Boat есть accept_nested_attributes :users
25
+ return false if @user.new_record? && !@user.valid?
26
+ _new_boat boat_params # создаём лодку (но в базу пока не кладём)
27
+
28
+ ActiveRecord::Base.transaction do # если дошли до этого этапа - значит всё ровно и с юзером и с лодкой - связываем их и пишем в базу
29
+ @boat.users << @user
30
+ @user.save validate: false
31
+
32
+ @boat.send :set_slug
33
+ @boat.save validate: false
34
+
35
+ # Делаем первую фотку главной и пишем в базу IP
36
+ MediaService.new(@boat).set_main_picture(:boat_photo)
37
+ UserService.new(@user).set_ip(request.remote_ip.to_s)
38
+
39
+ # в конце концов рассчитываем цены во всех валютах
40
+ ::Boats::BoatPricesSaveService.perform(@boat, [schema.attributes[:boat_price]]) unless @boat.for_rent.zero?
41
+ ::Boats::BoatSalePricesSaveService.perform(@boat.id, schema.attributes[:boat_sale_price]) unless @boat.for_sale.zero?
42
+
43
+ # TODO:: во-первых, заменить условия в двух строках выше на анализ boat_params[:boat_price] и boat_params[:boat_sale_price] соответственно
44
+ # TODO:: во-вторых, только после успешной отработки ценовых сервисов определять for_sale и for_rent и обновлять атрибуты
45
+
46
+ end
47
+
48
+ true
49
+ end
50
+
51
+ private
52
+
53
+ # noinspection RubySimplifyBooleanInspection,RubyResolve
54
+ def _new_boat(boat_params)
55
+ boat_locs2 = boat_params[:boat_locations_attributes].compact.each_with_index.map { |attr, index| [index.to_s, attr] }.to_h
56
+ boat_new_params = boat_params.except(:users_attributes, :prices, :boat_sale_price, :boat_price, :length, :boat_locations_attributes) # это собираемся подать в Boat.new, но сначала допишем длину
57
+ lk = Dicts::Length.find(boat_params[:length][:length_id]).index # "meters", "ft"
58
+ lk = 'boat_length_metrics_%s' % lk
59
+ boat_new_params[lk] = boat_params[:length][:value]
60
+
61
+ boat_new_params[:boat_locations_attributes] = boat_locs2
62
+
63
+ # fuckin' active record
64
+ @boat = Boat.new
65
+ @boat.assign_attributes boat_new_params.permit(
66
+ :boat_type_id, :boat_model, :name,
67
+ :builder, :crew_total, :guest_cabins, :guests_total,
68
+ :maximum_guests_during_cruise,
69
+ # :longitude, :latitude, :location_address,
70
+ lk.to_sym,
71
+ boat_photos_attributes: %i[id boat_id name picture _destroy],
72
+ boat_locations_attributes: %i[latitude longitude address is_main radius _destroy id]
73
+ )
74
+ @boat.premoderate
75
+
76
+ length_index = ::Dicts::Length.find(boat_params[:length][:length_id]).index # вместо cookies[:dimension]
77
+ DimensionService.new(@boat).calculate_boat_attributes length_index
78
+
79
+ @boat.for_sale = !!boat_params[:boat_sale_price][:value]&.to_i&.nonzero?
80
+ @boat.for_rent = !!boat_params[:boat_price][:value]&.to_i&.nonzero?
81
+
82
+ true
83
+ end
84
+
85
+ def _create_user(user_params, user = nil)
86
+ @user = user || User.new(user_params.permit(:email, :password))
87
+ return unless @user.new_record? # 2. если пользователь авторизован
88
+
89
+ email = user_params[:email]
90
+ password = user_params[:password]
91
+
92
+ # 1. если пользователь не авторизован
93
+ if email.present? && password.present? # 1.1 если указаны email и password - поищем юзера в базе
94
+ may_be_user = User.find_by_email email
95
+ if may_be_user # 1.1.1 если есть такой юзер в базе - проверим правильность пароля
96
+ if may_be_user.valid_password? password # 1.1.1.1 если пароль правильный
97
+ @user = may_be_user
98
+ return
99
+ else # 1.1.1.2 если пароль неправильный -- сообщаем об этом
100
+ errors[:users_attributes_0_email] = # note : такой странный ключ хэша обусловлен Boat.accept_nested_attributes :user
101
+ [I18n.t('devise.failure.invalid', authentication_keys: 'email')]
102
+ return
103
+ end
104
+ else # 1.1.2 если такого юзера нет в базе - СОЗДАЁМ
105
+ @user.role_id = 11 # todo-my:: 2018-08-06: потом это будет заменено на создание аккаунта Central Agent (просто сейчас находимся в контексте разработки list your boat)
106
+ @user.name = @user.email.split('@')[0]
107
+ return
108
+ end
109
+ else # 1.2 если не указан или пароль или емайл - сообщаем об этом
110
+ errors[:users_attributes_0_email] = # note : такой странный ключ хэша обусловлен Boat.accept_nested_attributes :user
111
+ [I18n.t('devise.failure.invalid', authentication_keys: 'email')]
112
+ end
113
+
114
+ end
115
+
116
+ def _reset_instance_variables
117
+ @errors = { }
118
+ end
119
+
120
+ end
@@ -0,0 +1,5 @@
1
+ en:
2
+ dicts:
3
+ business:
4
+ rent: Rent
5
+ sale: Sale
@@ -0,0 +1,5 @@
1
+ en:
2
+ dicts:
3
+ business:
4
+ rent: Аренда
5
+ sale: Продажа
@@ -0,0 +1,41 @@
1
+ module DatesNowValidator
2
+
3
+ # Сверит даты между собой.
4
+ # Сверит даты с текущей датой.
5
+ #
6
+ # @param errors
7
+ # @param from [nil || String || ::ActiveSupport::TimeWithZone || Time]
8
+ # @param to [аналогично]
9
+ #
10
+ def check_dates(errors, from, to)
11
+ errors.add(:from, :invalid_date) unless is_date?(from)
12
+ errors.add(:to, :invalid_date) unless is_date?(to)
13
+
14
+ # если введена хотя бы одна некорректная дата - дальше не проверяем
15
+ return if errors[:from].any? || errors[:to].any?
16
+
17
+ from = Time.parse(from) rescue from
18
+ to = Time.parse(to) rescue to
19
+ now = Time.zone.now.beginning_of_day
20
+
21
+ conditions = [
22
+ from.beginning_of_day < now,
23
+ to.beginning_of_day < now,
24
+ from > to
25
+ ]
26
+
27
+ if conditions.any?
28
+ errors.add(:from, :invalid_date)
29
+ errors.add(:to, :invalid_date)
30
+ end
31
+
32
+ end
33
+
34
+ private
35
+
36
+ def is_date?(date)
37
+ return true if date.is_a? ::ActiveSupport::TimeWithZone
38
+ !!Time.parse(date) rescue false
39
+ end
40
+
41
+ end
@@ -1,3 +1,3 @@
1
1
  module C80Shared
2
- VERSION = "0.1.69"
2
+ VERSION = "0.1.70"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: c80_shared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.69
4
+ version: 0.1.70
5
5
  platform: ruby
6
6
  authors:
7
7
  - C80609A
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-31 00:00:00.000000000 Z
11
+ date: 2019-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,12 +64,16 @@ files:
64
64
  - app/dicts/length.rb
65
65
  - app/dicts/locale.rb
66
66
  - app/dicts/motor.rb
67
+ - app/dicts/reject_type.rb
67
68
  - app/dicts/rent_skip_type.rb
68
69
  - app/dicts/role.rb
70
+ - app/forms/application_form.rb
71
+ - app/forms/rent_form.rb
69
72
  - app/getboat/schemas/base.rb
70
73
  - app/getboat/schemas/base_boat_schema.rb
71
74
  - app/getboat/schemas/central_agent/save_boat_schema.rb
72
75
  - app/getboat/schemas/site/lease/create_personal_inquiry_schema.rb
76
+ - app/getboat/schemas/site/register_boat_schema.rb
73
77
  - app/helpers/custom/currency_helper.rb
74
78
  - app/helpers/custom/dimension_helper.rb
75
79
  - app/helpers/custom/price_helper.rb
@@ -77,6 +81,7 @@ files:
77
81
  - app/helpers/site/time_helper.rb
78
82
  - app/repositories/accounts/central_agent_account_repository.rb
79
83
  - app/repositories/accounts/client_account_repository.rb
84
+ - app/repositories/events/rejects_repository.rb
80
85
  - app/serializers/account_serializer.rb
81
86
  - app/serializers/boat_location_serializer.rb
82
87
  - app/serializers/boat_price_serializer.rb
@@ -95,6 +100,7 @@ files:
95
100
  - app/serializers/lib/boats/rent_price_per_season.rb
96
101
  - app/serializers/lib/boats/sale_price.rb
97
102
  - app/services/abstract_prices_service.rb
103
+ - app/services/boat_register_service.rb
98
104
  - app/services/boats/boat_prices_save_service.rb
99
105
  - app/services/boats/boat_sale_prices_save_service.rb
100
106
  - app/services/central_agent/save_boat_service.rb
@@ -112,6 +118,8 @@ files:
112
118
  - config/locales/boat/ru.yml
113
119
  - config/locales/dicts/account_type/en.yml
114
120
  - config/locales/dicts/account_type/ru.yml
121
+ - config/locales/dicts/business/en.yml
122
+ - config/locales/dicts/business/ru.yml
115
123
  - config/locales/dicts/charter_category/en.yml
116
124
  - config/locales/dicts/charter_category/ru.yml
117
125
  - config/locales/dicts/exterior_color/en.yml
@@ -133,6 +141,7 @@ files:
133
141
  - lib/c80_shared.rb
134
142
  - lib/c80_shared/aasm/handle_event.rb
135
143
  - lib/c80_shared/abstract_serializer.rb
144
+ - lib/c80_shared/dates_now_validator.rb
136
145
  - lib/c80_shared/dict.rb
137
146
  - lib/c80_shared/engine.rb
138
147
  - lib/c80_shared/geo/distance.rb