183 lines
5.9 KiB
Ruby
183 lines
5.9 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
# Profile model
|
||
# in original version user has only one drafted or submitted at time but can has many verified and rejected
|
||
# but in my version user can only one verified profile too
|
||
# only drafted profile editable, so dont send confirm param in creation or update time
|
||
class Profile < ApplicationRecord
|
||
include Encryptable
|
||
|
||
# acts_as_eventable prefix: 'profile', on: %i[create update]
|
||
|
||
belongs_to :user
|
||
belongs_to :city, required: false
|
||
|
||
enum state: { drafted: 0, submitted: 1, verified: 3, rejected: 4 }
|
||
|
||
EDITABLE_PARAMS = { drafted: %w[first_name last_name dob address postcode city country metadata national_code] }.freeze
|
||
OPTIONAL_PARAMS = %w[first_name last_name dob address postcode city country national_code].freeze
|
||
|
||
attr_encrypted :first_name
|
||
attr_encrypted :last_name
|
||
attr_encrypted :dob
|
||
attr_encrypted :address
|
||
attr_encrypted :national_code
|
||
|
||
validates :first_name, presence: true,
|
||
length: 1..255,
|
||
format: {
|
||
with: /\A[[:word:]\s\-']+\z/,
|
||
message: 'only allows letters, digits "-", "\'", and space'
|
||
},
|
||
if: proc { |a| a.first_name.present? }
|
||
validates :last_name, presence: true,
|
||
length: 1..255,
|
||
format: {
|
||
with: /\A[[:word:]\s\-']+\z/,
|
||
message: 'only allows letters, digits "-", "\'", and space'
|
||
},
|
||
if: proc { |a| a.last_name.present? }
|
||
|
||
validates :city, presence: false
|
||
|
||
validate :validate_country_format, if: ->(p) { p.country.present? }
|
||
validates :postcode, length: 2..255,
|
||
format: {
|
||
with: /\A[[:word:]\s\-]+\z/,
|
||
message: 'only allows letters, digits, "-" and space'
|
||
},
|
||
if: proc { |a| a.postcode.present? }
|
||
|
||
validates :address, length: 1..255,
|
||
format: {
|
||
with: /\A[[:word:]\s\-\–\,\.~;\/:\#"\\&\')\(]+\z/,
|
||
message: 'only allows letters, digits "-", "–", "\'", ".", ",", "#", ":", ";", "&" and space'
|
||
},
|
||
if: proc { |a| a.address.present? }
|
||
|
||
validates :national_code, length: { is: 10 },
|
||
format: { with: /\A\d+\z/, message: 'Ten Integer only. No sign allowed.' }
|
||
|
||
validates :metadata, data_is_json: true
|
||
validate :profile_state!, on: :create
|
||
# validate :profile_update!, on: :update
|
||
validate :dob_not_in_the_future
|
||
|
||
after_commit :start_profile_kyc_verification
|
||
|
||
scope :kept, -> { joins(:user).where(users: { discarded_at: nil }) }
|
||
|
||
before_validation do
|
||
squish_spaces
|
||
end
|
||
|
||
def full_name
|
||
"#{first_name} #{last_name}"
|
||
end
|
||
|
||
def reverse_full_name
|
||
"#{last_name} #{first_name}"
|
||
end
|
||
|
||
def sub_masked_last_name
|
||
last_name.sub(/(?<=\A.{1})(.*)/) { |match| '*' * match.length } if last_name
|
||
end
|
||
|
||
def sub_masked_national_code
|
||
national_code.sub(/(?<=\A.{5})(.*)/) { |match| '*' * match.length } if national_code
|
||
end
|
||
|
||
def sub_masked_dob
|
||
dob.to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length } if dob
|
||
end
|
||
|
||
def as_json_for_event_api
|
||
{
|
||
user: user.as_json_for_event_api,
|
||
first_name: first_name,
|
||
last_name: last_name,
|
||
dob: format_iso8601_time(dob),
|
||
address: address,
|
||
postcode: postcode,
|
||
city: city,
|
||
country: country,
|
||
metadata: metadata,
|
||
created_at: format_iso8601_time(created_at),
|
||
updated_at: format_iso8601_time(updated_at)
|
||
}
|
||
end
|
||
|
||
|
||
private
|
||
|
||
def validate_country_format
|
||
return if ISO3166::Country.find_country_by_alpha2(country) ||
|
||
ISO3166::Country.find_country_by_alpha3(country)
|
||
|
||
errors.add(:country, 'must have alpha2 or alpha3 format')
|
||
end
|
||
|
||
def squish_spaces
|
||
self.first_name = first_name&.squish
|
||
self.last_name = last_name&.squish
|
||
self.postcode = postcode&.squish
|
||
end
|
||
|
||
def profile_state!
|
||
# No limits for storing drafted and rejected profiles
|
||
# return if state.in?(%w[drafted rejected])
|
||
return if state.in?(%w[drafted rejected])
|
||
|
||
# This check is actual for profile states [drafted submitted]
|
||
# User cant create submitted or verified profile, when already had one of them
|
||
user_profiles_states = user.profiles.pluck(:state)
|
||
errors.add(:state, :exists, message: 'already exists') unless (user_profiles_states & %w[submitted verified]).empty?
|
||
end
|
||
|
||
def profile_update!
|
||
# we cant update rejected or verified profile
|
||
errors.add(:state, :exists, message: 'just edit submitted') if %w[rejected verified].include?(state_was)
|
||
end
|
||
|
||
def start_profile_kyc_verification
|
||
KycService.profile_step(self)
|
||
end
|
||
|
||
def dob_not_in_the_future
|
||
return if dob.nil?
|
||
|
||
self.dob = dob.to_date
|
||
return errors.add(:dob, :invalid_format, message: 'invalid date format') unless dob.is_a?(Date)
|
||
return errors.add(:dob, :invalid, message: 'cant be in future') if dob > Date.current
|
||
end
|
||
end
|
||
|
||
# == Schema Information
|
||
# Schema version: 20210425062048
|
||
#
|
||
# Table name: profiles
|
||
#
|
||
# id :bigint not null, primary key
|
||
# user_id :bigint
|
||
# author :string(255)
|
||
# applicant_id :string(255)
|
||
# first_name_encrypted :string(1024)
|
||
# last_name_encrypted :string(1024)
|
||
# dob_encrypted :string(255)
|
||
# address_encrypted :string(1024)
|
||
# postcode :string(255)
|
||
# city :string(255)
|
||
# country :string(255)
|
||
# state :integer default("drafted"), unsigned
|
||
# metadata :text(65535)
|
||
# created_at :datetime not null
|
||
# updated_at :datetime not null
|
||
# national_code_encrypted :string(255)
|
||
# city_id :bigint
|
||
#
|
||
# Indexes
|
||
#
|
||
# index_profiles_on_city_id (city_id)
|
||
# index_profiles_on_user_id (user_id)
|
||
#
|