# frozen_string_literal: true class AppearanceRelease < ApplicationRecord include Confirmable include Contractable include Exploitable include Notable include Releasable include Searchable include Signable include Syncable include Taggable include PersonName include GuardianPhotoable include SecondGuardianPhotoable include GuardianName include SecondGuardianName has_one_attached :person_photo composed_of :person_address, class_name: 'Address', mapping: [ %w[person_address_street1 street1], %w[person_address_street2 street2], %w[person_address_city city], %w[person_address_state state], %w[person_address_zip zip], %w[person_address_country country] ] composed_of :guardian_address, class_name: 'Address', mapping: [ %w[guardian_address_street1 street1], %w[guardian_address_street2 street2], %w[guardian_address_city city], %w[guardian_address_state state], %w[guardian_address_zip zip], %w[guardian_address_country country] ] composed_of :guardian_2_address, class_name: 'Address', mapping: [ %w[guardian_2_address_street1 street1], %w[guardian_2_address_street2 street2], %w[guardian_2_address_city city], %w[guardian_2_address_state state], %w[guardian_2_address_zip zip], %w[guardian_2_address_country country] ] # These validations apply to all releases validates :person_email, email: true, allow_blank: true validates :person_first_name, :person_last_name, presence: true scope :order_by_name, -> { order(:person_last_name) } def self.random_contract_number rand(1_000_000..9_999_998) # random 7 digit number end # We don't care for the argument but method WILL receive option name # when called from inside with_option block, hence * argument def self.face_photo_acceptable_content_types(*) ['image/png', 'image/jpeg'] end def self.acceptable_import_file_extensions ['.png', '.jpeg', '.jpg', '.pdf'] end # These validations apply to releases being signed by a minor with_options if: :minor? do validates :guardian_first_name, :guardian_last_name, presence: true validates :guardian_email, email: true, allow_blank: true end validates :person_photo, content_type: face_photo_acceptable_content_types # These validations apply to releases created natively by the system (i.e. not imported from elsewhere) with_options on: :native do validates :signature, attached: true validates :person_photo, attached: true, content_type: face_photo_acceptable_content_types validate :person_photo_is_acceptable, if: :new_record? # Only validate photos on new releases end def contract_or_photo_is_attached return if person_photo.attached? || contract.attached? errors[:base] << I18n.t('appearance_releases.index.imported_appearance_release_missing_attachment') end # These validations apply to releases imported to the system from an outside source with_options on: :non_native do validate :contract_or_photo_is_attached validates :person_photo, content_type: face_photo_acceptable_content_types end scope :with_person_photo, -> { joins(:person_photo_attachment) } scope :with_person_photo_and_contract, -> { joins(:person_photo_attachment, :contract_attachment) } scope :without_person_photo_or_contract, -> { where.not(id: with_person_photo_and_contract) } scope :complete, -> { with_person_photo_and_contract } scope :incomplete, -> { without_person_photo_or_contract } scope :having_no_person_photo, -> { left_joins(:person_photo_attachment).group(:id).having('COUNT(active_storage_attachments) = 0') } scope :with_person_name, ->(name) { where('person_first_name ILIKE ? OR person_last_name ILIKE ?', "%#{name}%") } searchable_on %i[ person_first_name person_last_name person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country person_email person_phone ] # All releases must respond to the following messages def name person_name end def filename_suffix "#{person_last_name} #{person_first_name}" end def photo person_photo end def photos photo.attached? ? [photo] : [] end def contact_person @contact_person ||= Contact.new(name, person_address, person_email, person_phone) end def uses_edl? true end def second_guardian_present? self.guardian_2_first_name.present? end def contract_file_name "#{project.name.parameterize}_#{contract_template.release_type}_#{(signed_at || created_at).strftime('%Y.%m.%d')}_#{release_number}_#{filename_suffix.parameterize}" end private # Validates the quality of the person photo def person_photo_is_acceptable return unless person_photo.attached? # Call a remote API to perform the validation image_validation = BrayniacAI::Validation.create(bucket_name: ENV['AWS_BUCKET'], object_name: person_photo.key) unless image_validation.valid errors.add(:person_photo, image_validation.error) end rescue ActiveResource::ConnectionError => e # TODO Rails.logger.error(e) end end