c80_shared 0.1.69 → 0.1.70

Sign up to get free protection for your applications and to get access to all the features.
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