<commit_before>class Agreement < ActiveRecord::Base

  # STEP 1 Fields:
  #   :data_user
  #   :data_user_type => 'individual', 'organization'
  #   :individual_institution_name
  #   # :individual_name => Not in schema, this is data_user
  #   :individual_title
  #   :individual_telephone
  #   :individual_fax
  #   # :individual_email => Not in schema, this is agreement.user.email
  #   :individual_address

  #   :organization_business_name
  #   :organization_contact_name
  #   :organization_contact_title
  #   :organization_contact_telephone
  #   :organization_contact_fax
  #   :organization_contact_email
  #   :organization_address

  # STEP 2 Fields:
  #   :specific_purpose

  # STEP 3 Fields:
  #   :has_read_step3

  # Step 4 Fields:
  #   :posting_permission 'all', 'name_only', 'none'

  # STEP 5 Fields
  #   :has_read_step5

  serialize :history, Array

  mount_uploader :dua, PDFUploader
  mount_uploader :executed_dua, PDFUploader
  mount_uploader :irb, PDFUploader
  mount_uploader :printed_file, PDFUploader

  STATUS = ["submitted", "approved", "resubmit", "expired"].collect{|i| [i,i]}

  attr_accessor :draft_mode, :full_mode

  # Concerns
  include Deletable, Latexable

  # Named Scopes
  scope :search, lambda { |arg| where( 'agreements.user_id in (select users.id from users where LOWER(users.first_name) LIKE ? or LOWER(users.last_name) LIKE ? or LOWER(users.email) LIKE ? )', arg.to_s.downcase.gsub(/^| |$/, '%'), arg.to_s.downcase.gsub(/^| |$/, '%'), arg.to_s.downcase.gsub(/^| |$/, '%') ).references(:users) }
  scope :expired, -> { where("agreements.expiration_date IS NOT NULL and agreements.expiration_date < ?", Date.today) }
  scope :not_expired, -> { where("agreements.expiration_date IS NULL or agreements.expiration_date >= ?", Date.today) }

  # Model Validation
  validates_presence_of :user_id
  # validates_presence_of :dua
  # validates_presence_of :executed_dua, if: :approved?

  validates_presence_of :reviewer_signature, :approval_date, :expiration_date, if: :approved?
  validates :reviewer_signature, length: { minimum: 20, tokenizer: lambda { |str| (JSON.parse(str) rescue []) }, too_short: "can't be blank" }, if: :approved?

  validates_presence_of :comments, if: :resubmission_required?

  validates_presence_of :data_user, if: :step1?
  validates_presence_of :data_user_type, if: :step1?
  validates :data_user_type, inclusion: { in: %w(individual organization), message: "\"%{value}\" is not a valid data user type" }, if: :step1?
  validates_presence_of :individual_institution_name, :individual_title, :individual_telephone, :individual_fax, :individual_address, if: :step1_and_individual?
  validates_presence_of :organization_business_name, :organization_contact_name, :organization_contact_title, :organization_contact_telephone, :organization_contact_fax, :organization_contact_email, :organization_address, if: :step1_and_organization?

  validates_presence_of :specific_purpose, if: :step2?
  validates_presence_of :datasets, if: :step2?

  validates_presence_of :has_read_step3, if: :step3?

  validates_presence_of :posting_permission, if: :step4?
  validates :posting_permission, inclusion: { in: %w(all name_only none), message: "\"%{value}\" is not a valid posting permission" }, if: :step4?

  validates_presence_of :has_read_step5, if: :step5?

  validates_presence_of :signature, :signature_print, :signature_date, if: :step6?
  validates :signature, length: { minimum: 20, tokenizer: lambda { |str| (JSON.parse(str) rescue []) }, too_short: "can't be blank" }, if: :step6?

  validates_presence_of :irb_evidence_type, if: :step7?
  validates :irb_evidence_type, inclusion: { in: %w(has_evidence no_evidence), message: "\"%{value}\" is not a valid evidence type" }, if: :step7?

  validates_presence_of :irb, if: :step7_and_has_evidence?

  validates_presence_of :title_of_project, :intended_use_of_data, :data_secured_location, :secured_device, if: :step8?

  # Model Relationships
  belongs_to :user
  has_many :requests
  has_many :datasets, -> { where deleted: false }, through: :requests
  has_many :reviews, -> { joins(:user).order('left(users.first_name,1), left(users.last_name,1)') }
  has_many :agreement_events, -> { order( :event_at ) }

  # Agreement Methods

  def copyable_attributes
    self.attributes.reject{|key, val| ['id', 'deleted', 'created_at', 'updated_at', 'reviewer_signature', 'approval_date', 'expiration_date', 'comments', 'has_read_step3', 'has_read_step5', 'current_step', 'dua', 'executed_dua'].include?(key.to_s)}
  end

  def dataset_ids=(ids)
    self.datasets = Dataset.release_scheduled.where( id: ids )
  end

  def name
    self.user ? self.user.name : "##{self.id}"
  end

  def to_param
    "#{id}" + (self.user ? "-#{self.user.name.parameterize}" : '')
  end

  def agreement_number
    Agreement.where(user_id: self.user_id).order(:id).pluck(:id).index(self.id) + 1
  end

  def approved?
    self.status == 'approved'
  end

  def under_review?
    ['submitted'].include?(self.status)<commit_msg>Use substring to work with PostgreSQL 9.0+<commit_after>class Agreement < ActiveRecord::Base

  # STEP 1 Fields:
  #   :data_user
  #   :data_user_type => 'individual', 'organization'
  #   :individual_institution_name
  #   # :individual_name => Not in schema, this is data_user
  #   :individual_title
  #   :individual_telephone
  #   :individual_fax
  #   # :individual_email => Not in schema, this is agreement.user.email
  #   :individual_address

  #   :organization_business_name
  #   :organization_contact_name
  #   :organization_contact_title
  #   :organization_contact_telephone
  #   :organization_contact_fax
  #   :organization_contact_email
  #   :organization_address

  # STEP 2 Fields:
  #   :specific_purpose

  # STEP 3 Fields:
  #   :has_read_step3

  # Step 4 Fields:
  #   :posting_permission 'all', 'name_only', 'none'

  # STEP 5 Fields
  #   :has_read_step5

  serialize :history, Array

  mount_uploader :dua, PDFUploader
  mount_uploader :executed_dua, PDFUploader
  mount_uploader :irb, PDFUploader
  mount_uploader :printed_file, PDFUploader

  STATUS = ["submitted", "approved", "resubmit", "expired"].collect{|i| [i,i]}

  attr_accessor :draft_mode, :full_mode

  # Concerns
  include Deletable, Latexable

  # Named Scopes
  scope :search, lambda { |arg| where( 'agreements.user_id in (select users.id from users where LOWER(users.first_name) LIKE ? or LOWER(users.last_name) LIKE ? or LOWER(users.email) LIKE ? )', arg.to_s.downcase.gsub(/^| |$/, '%'), arg.to_s.downcase.gsub(/^| |$/, '%'), arg.to_s.downcase.gsub(/^| |$/, '%') ).references(:users) }
  scope :expired, -> { where("agreements.expiration_date IS NOT NULL and agreements.expiration_date < ?", Date.today) }
  scope :not_expired, -> { where("agreements.expiration_date IS NULL or agreements.expiration_date >= ?", Date.today) }

  # Model Validation
  validates_presence_of :user_id
  # validates_presence_of :dua
  # validates_presence_of :executed_dua, if: :approved?

  validates_presence_of :reviewer_signature, :approval_date, :expiration_date, if: :approved?
  validates :reviewer_signature, length: { minimum: 20, tokenizer: lambda { |str| (JSON.parse(str) rescue []) }, too_short: "can't be blank" }, if: :approved?

  validates_presence_of :comments, if: :resubmission_required?

  validates_presence_of :data_user, if: :step1?
  validates_presence_of :data_user_type, if: :step1?
  validates :data_user_type, inclusion: { in: %w(individual organization), message: "\"%{value}\" is not a valid data user type" }, if: :step1?
  validates_presence_of :individual_institution_name, :individual_title, :individual_telephone, :individual_fax, :individual_address, if: :step1_and_individual?
  validates_presence_of :organization_business_name, :organization_contact_name, :organization_contact_title, :organization_contact_telephone, :organization_contact_fax, :organization_contact_email, :organization_address, if: :step1_and_organization?

  validates_presence_of :specific_purpose, if: :step2?
  validates_presence_of :datasets, if: :step2?

  validates_presence_of :has_read_step3, if: :step3?

  validates_presence_of :posting_permission, if: :step4?
  validates :posting_permission, inclusion: { in: %w(all name_only none), message: "\"%{value}\" is not a valid posting permission" }, if: :step4?

  validates_presence_of :has_read_step5, if: :step5?

  validates_presence_of :signature, :signature_print, :signature_date, if: :step6?
  validates :signature, length: { minimum: 20, tokenizer: lambda { |str| (JSON.parse(str) rescue []) }, too_short: "can't be blank" }, if: :step6?

  validates_presence_of :irb_evidence_type, if: :step7?
  validates :irb_evidence_type, inclusion: { in: %w(has_evidence no_evidence), message: "\"%{value}\" is not a valid evidence type" }, if: :step7?

  validates_presence_of :irb, if: :step7_and_has_evidence?

  validates_presence_of :title_of_project, :intended_use_of_data, :data_secured_location, :secured_device, if: :step8?

  # Model Relationships
  belongs_to :user
  has_many :requests
  has_many :datasets, -> { where deleted: false }, through: :requests
  has_many :reviews, -> { joins(:user).order('substring(users.first_name from 0 for 1), substring(users.last_name from 0 for 1)') }
  has_many :agreement_events, -> { order( :event_at ) }

  # Agreement Methods

  def copyable_attributes
    self.attributes.reject{|key, val| ['id', 'deleted', 'created_at', 'updated_at', 'reviewer_signature', 'approval_date', 'expiration_date', 'comments', 'has_read_step3', 'has_read_step5', 'current_step', 'dua', 'executed_dua'].include?(key.to_s)}
  end

  def dataset_ids=(ids)
    self.datasets = Dataset.release_scheduled.where( id: ids )
  end

  def name
    self.user ? self.user.name : "##{self.id}"
  end

  def to_param
    "#{id}" + (self.user ? "-#{self.user.name.parameterize}" : '')
  end

  def agreement_number
    Agreement.where(user_id: self.user_id).order(:id).pluck(:id).index(self.id) + 1
  end

  def approved?
    self.status == 'approved'
  end

  def under_review?
    ['submitted'].include?(self.status)
{'fraction_non_alphanumeric': 0.12912169521734826, 'fraction_numerical': 0.007327458164174671, 'mean_word_length': 5.242274412855377, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2450465', 'n_tokens_mistral': 3729, 'n_tokens_neox': 3470, 'n_words': 751}