# 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 include CsvExportable include Approvable include Amendmenable NUMBER_OF_CUSTOM_FIELDS = 15 class << self def custom_csv_exportable_headers %i[name contact_info] end end 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