app/models/client.rb
# frozen_string_literal: true
class Client < ApplicationRecord
SUBJECTS_JSON_SCHEMA = Rails.root.join("app", "models", "schemas", "client", "subjects.json")
audited except: %i[
system_email
service_contact
globus_uuid
salesforce_id
password
updated
comments
experiments
version
doi_quota_allowed
doi_quota_used
]
# include helper module for caching infrequently changing resources
include Cacheable
# include helper module for managing associated users
include Userable
# include helper module for setting password
include Passwordable
# include helper module for authentication
include Authenticable
# include helper module for Elasticsearch
include Indexable
# include helper module for sending emails
include Mailable
include Elasticsearch::Model
# define table and attribute names
# uid is used as unique identifier, mapped to id in serializer
self.table_name = "datacentre"
alias_attribute :flipper_id, :symbol
alias_attribute :created_at, :created
alias_attribute :updated_at, :updated
alias_attribute :contact_email, :system_email
attr_readonly :symbol
delegate :symbol, to: :provider, prefix: true
delegate :consortium_id, to: :provider, allow_nil: true
delegate :salesforce_id, to: :provider, prefix: true, allow_nil: true
attr_accessor :password_input, :target_id
attr_reader :from_salesforce
validate :subjects_only_for_disciplinary_repos
validates :subjects, if: :subjects?,
json: {
message: ->(errors) { errors },
schema: SUBJECTS_JSON_SCHEMA
}
validates_presence_of :symbol, :name, :system_email
validates_uniqueness_of :symbol,
message: "This Client ID has already been taken"
validates_format_of :symbol,
with: /\A([A-Z]+\.[A-Z0-9]+(-[A-Z0-9]+)?)\Z/,
message:
"should only contain capital letters, numbers, and at most one hyphen"
validates_length_of :symbol, minimum: 5, maximum: 18
validates_format_of :system_email,
with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
validates_format_of :salesforce_id,
with: /[a-zA-Z0-9]{18}/,
message: "wrong format for salesforce id",
if: :salesforce_id?
validates_inclusion_of :role_name,
in: %w[ROLE_DATACENTRE],
message: "Role %s is not included in the list"
validates_inclusion_of :client_type,
in: %w[repository periodical igsnCatalog],
message: "Client type %s is not included in the list"
validates_associated :provider
validate :check_id, on: :create
validate :check_prefix, on: :create
validate :freeze_symbol, on: :update
validate :check_issn, if: :issn?
validate :check_certificate, if: :certificate?
validate :check_repository_type, if: :repository_type?
validate :uuid_format, if: :globus_uuid?
strip_attributes
belongs_to :provider, foreign_key: :allocator, touch: true
has_many :dois, foreign_key: :datacentre
has_many :client_prefixes, dependent: :destroy
has_many :prefixes, through: :client_prefixes
has_many :provider_prefixes, through: :client_prefixes
has_many :activities, as: :auditable, dependent: :destroy
before_validation :set_defaults
before_validation :convert_subject_hashes_to_camelcase
before_create { self.created = Time.zone.now.utc.iso8601 }
before_save { self.updated = Time.zone.now.utc.iso8601 }
after_create_commit :assign_prefix
after_create_commit :create_reference_repository
after_update_commit :update_reference_repository
after_destroy_commit :destroy_reference_repository
after_commit on: %i[update] do
::Client.import_dois(self.id)
end
# use different index for testing
if Rails.env.test?
index_name "clients-test#{ENV['TEST_ENV_NUMBER']}"
elsif ENV["ES_PREFIX"].present?
index_name "clients-#{ENV['ES_PREFIX']}"
else
index_name "clients"
end
settings index: {
analysis: {
analyzer: {
string_lowercase: {
tokenizer: "keyword", filter: %w[lowercase ascii_folding]
},
},
normalizer: {
keyword_lowercase: { type: "custom", filter: %w[lowercase] },
},
filter: {
ascii_folding: {
type: "asciifolding", preserve_original: true
},
},
},
} do
mapping dynamic: "false" do
indexes :id, type: :keyword
indexes :uid, type: :keyword, normalizer: "keyword_lowercase"
indexes :symbol, type: :keyword
indexes :provider_id, type: :keyword
indexes :provider_id_and_name, type: :keyword
indexes :consortium_id, type: :keyword
indexes :re3data_id, type: :keyword
indexes :opendoar_id, type: :integer
indexes :salesforce_id, type: :keyword
indexes :globus_uuid, type: :keyword
indexes :issn,
type: :object,
properties: {
issnl: { type: :keyword },
electronic: { type: :keyword },
print: { type: :keyword },
}
indexes :prefix_ids, type: :keyword
indexes :name,
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text", analyzer: "string_lowercase", "fielddata": true
},
}
indexes :alternate_name,
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text", analyzer: "string_lowercase", "fielddata": true
},
}
indexes :description, type: :text
indexes :system_email,
type: :text, fields: { keyword: { type: "keyword" } }
indexes :service_contact,
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
}
indexes :certificate, type: :keyword
indexes :language, type: :keyword
indexes :repository_type, type: :keyword
indexes :version, type: :integer
indexes :is_active, type: :keyword
indexes :domains, type: :text
indexes :year, type: :integer
indexes :url, type: :text, fields: { keyword: { type: "keyword" } }
indexes :software,
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text", analyzer: "string_lowercase", "fielddata": true
},
}
indexes :cache_key, type: :keyword
indexes :client_type, type: :keyword
indexes :created, type: :date
indexes :updated, type: :date
indexes :deleted_at, type: :date
indexes :analytics_dashboard_url, type: :text
indexes :analytics_tracking_id, type: :text
indexes :cumulative_years, type: :integer, index: "false"
indexes :subjects, type: :object, properties: {
subjectScheme: { type: :keyword },
subject: { type: :keyword },
schemeUri: { type: :keyword },
valueUri: { type: :keyword },
lang: { type: :keyword },
classificationCode: { type: :keyword },
}
# include parent objects
indexes :provider,
type: :object,
properties: {
id: { type: :keyword },
uid: { type: :keyword },
symbol: { type: :keyword },
globus_uuid: { type: :keyword },
client_ids: { type: :keyword },
prefix_ids: { type: :keyword },
name: {
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text",
"analyzer": "string_lowercase",
"fielddata": true,
},
},
},
display_name: {
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text",
"analyzer": "string_lowercase",
"fielddata": true,
},
},
},
system_email: {
type: :text, fields: { keyword: { type: "keyword" } }
},
group_email: {
type: :text, fields: { keyword: { type: "keyword" } }
},
version: { type: :integer },
is_active: { type: :keyword },
year: { type: :integer },
description: { type: :text },
website: {
type: :text, fields: { keyword: { type: "keyword" } }
},
logo_url: { type: :text },
region: { type: :keyword },
focus_area: { type: :keyword },
organization_type: { type: :keyword },
member_type: { type: :keyword },
consortium_id: {
type: :text,
fields: {
keyword: { type: "keyword" },
raw: {
type: "text",
"analyzer": "string_lowercase",
"fielddata": true,
},
},
},
consortium_organization_ids: { type: :keyword },
country_code: { type: :keyword },
role_name: { type: :keyword },
cache_key: { type: :keyword },
joined: { type: :date },
twitter_handle: { type: :keyword },
ror_id: { type: :keyword },
salesforce_id: { type: :keyword },
billing_information: {
type: :object,
properties: {
postCode: { type: :keyword },
state: { type: :text },
organization: { type: :text },
department: { type: :text },
city: { type: :text },
country: { type: :text },
address: { type: :text },
},
},
technical_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
secondary_technical_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
billing_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
secondary_billing_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
service_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
secondary_service_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
voting_contact: {
type: :object,
properties: {
email: { type: :text },
given_name: { type: :text },
family_name: { type: :text },
},
},
created: { type: :date },
updated: { type: :date },
deleted_at: { type: :date },
cumulative_years: { type: :integer, index: "false" },
consortium: { type: :object },
consortium_organizations: { type: :object },
}
end
end
def as_indexed_json(options = {})
{
"id" => uid,
"uid" => uid,
"provider_id" => provider_id,
"provider_id_and_name" => provider_id_and_name,
"consortium_id" => consortium_id,
"re3data_id" => re3data_id,
"opendoar_id" => opendoar_id,
"salesforce_id" => salesforce_id,
"globus_uuid" => globus_uuid,
"issn" => issn,
"prefix_ids" => options[:exclude_associations] ? nil : prefix_ids,
"name" => name,
"alternate_name" => alternate_name,
"description" => description,
"certificate" => Array.wrap(certificate),
"symbol" => symbol,
"year" => year,
"language" => Array.wrap(language),
"repository_type" => Array.wrap(repository_type),
"service_contact" => service_contact,
"system_email" => system_email,
"domains" => domains,
"url" => url,
"software" => software,
"is_active" => is_active,
"password" => password,
"cache_key" => cache_key,
"client_type" => client_type,
"created" => created.try(:iso8601),
"updated" => updated.try(:iso8601),
"deleted_at" => deleted_at.try(:iso8601),
"cumulative_years" => cumulative_years,
"provider" =>
if options[:exclude_associations]
nil
else
provider.as_indexed_json(exclude_associations: true)
end,
"analytics_dashboard_url" => analytics_dashboard_url,
"analytics_tracking_id" => analytics_tracking_id,
"subjects" => Array.wrap(subjects),
}
end
def self.query_fields
%w[
uid^10
symbol^10
name^5
description^5
system_email^5
url
software^3
repository.subjects.text^3
repository.certificates.text^3
_all
]
end
def self.query_aggregations
{
years: {
date_histogram: {
field: "created",
interval: "year",
format: "year",
order: { _key: "desc" },
min_doc_count: 1,
},
aggs: { bucket_truncate: { bucket_sort: { size: 10 } } },
},
cumulative_years: {
terms: {
field: "cumulative_years",
size: 20,
min_doc_count: 1,
order: { _count: "asc" },
},
},
providers: {
terms: { field: "provider_id_and_name", size: 10, min_doc_count: 1 },
},
software: {
terms: { field: "software.keyword", size: 10, min_doc_count: 1 },
},
client_types: {
terms: { field: "client_type", size: 10, min_doc_count: 1 },
},
repository_types: {
terms: { field: "repository_type", size: 10, min_doc_count: 1 },
},
certificates: {
terms: { field: "certificate", size: 10, min_doc_count: 1 },
},
}
end
def csv
client = {
name: name,
client_id: symbol,
provider_id: provider.present? ? provider.symbol : "",
salesforce_id: salesforce_id,
consortium_salesforce_id: provider.present? ? provider.salesforce_id : "",
is_active: is_active == "\x01",
created: created,
updated: updated,
re3data_id: re3data_id,
client_type: client_type,
alternate_name: alternate_name,
description: description,
url: url,
software: software,
system_email: system_email,
}.values
CSV.generate { |csv| csv << client }
end
def uid
symbol.downcase
end
def from_salesforce=(value)
@from_salesforce = (value.to_s == "true")
end
# workaround for non-standard database column names and association
def provider_id
provider_symbol.downcase
end
def provider_id_and_name
"#{provider_id}:#{provider.name}"
end
def provider_id=(value)
r = Provider.where(symbol: value).first
return nil if r.blank?
write_attribute(:allocator, r.id)
end
def re3data=(value)
attr = value.present? ? value[16..-1] : nil
write_attribute(:re3data_id, attr)
end
def subjects=(value)
write_attribute(:subjects, Array.wrap(value).uniq)
end
def opendoar=(value)
attr = value.present? ? value[38..-1] : nil
write_attribute(:opendoar_id, attr)
end
def prefix_ids
prefixes.pluck(:uid)
end
def target_id=(value)
c = self.class.find_by_id(value)
return nil if c.blank?
client_target = c.records.first
Rails.logger.info "[Transfer] with target client #{client_target.symbol}"
Doi.transfer(client_id: symbol.downcase, client_target_id: client_target.id)
end
# use keyword arguments consistently
def transfer(provider_target_id: nil)
if provider_target_id.blank?
Rails.logger.error "[Transfer] No target provider provided."
return nil
end
target_provider =
Provider.where(
"role_name IN (?)",
%w[ROLE_ALLOCATOR ROLE_CONSORTIUM_ORGANIZATION],
).
where(symbol: provider_target_id).
first
if target_provider.blank?
Rails.logger.error "[Transfer] Provider doesn't exist."
return nil
end
Rails.logger.info "[Transfer] Client transfer starting from #{provider_id} to #{target_provider.id}"
# Transfer client
update_attribute(:allocator, target_provider.id)
# transfer prefixes
transfer_prefixes(provider_target_id: target_provider.symbol)
# Update DOIs
TransferClientJob.perform_later(
self,
provider_target_id: provider_target_id,
)
end
# use keyword arguments consistently
def transfer_prefixes(provider_target_id: nil)
# These prefixes are used by multiple clients
prefixes_to_keep = %w[10.4124 10.4225 10.4226 10.4227]
# delete all associated prefixes
associated_prefixes =
prefixes.reject { |prefix| prefixes_to_keep.include?(prefix.uid) }
prefix_ids = associated_prefixes.pluck(:id)
prefixes_names = associated_prefixes.pluck(:uid)
if prefix_ids.present?
response = ProviderPrefix.where("prefix_id IN (?)", prefix_ids).destroy_all
Rails.logger.info "[Transfer][Prefix] #{response.count} provider prefixes deleted. #{prefix_ids}"
response = ClientPrefix.where("prefix_id IN (?)", prefix_ids).destroy_all
Rails.logger.info "[Transfer][Prefix] #{response.count} client prefixes deleted. #{prefix_ids}"
end
# Assign prefix(es) to provider and client
prefixes_names.each do |prefix|
provider_prefix =
ProviderPrefix.create(
provider_id: provider_target_id, prefix_id: prefix,
)
Rails.logger.info "[Transfer][Prefix] Provider prefix for provider #{
provider_target_id
} and prefix #{prefix} created."
ClientPrefix.create(
client_id: symbol,
provider_prefix_id: provider_prefix.uid,
prefix_id: prefix,
)
Rails.logger.info "[Transfer][Prefix] Client prefix for client #{symbol} and prefix #{
prefix
} created."
end
end
def service_contact_email
service_contact.fetch("email", nil) if service_contact.present?
end
def service_contact_given_name
service_contact.fetch("given_name", nil) if service_contact.present?
end
def service_contact_family_name
service_contact.fetch("family_name", nil) if service_contact.present?
end
# def index_all_dois
# Doi.index(from_date: "2011-01-01", client_id: id)
# end
def cache_key
"clients/#{uid}-#{updated.iso8601}"
end
def password_input=(value)
write_attribute(:password, encrypt_password_sha256(value)) if value.present?
end
# backwards compatibility
def member
Provider.where(symbol: provider_id).first if provider_id.present?
end
def year
created_at.year if created_at.present?
end
# count years account has been active. Ignore if deleted the same year as created
def cumulative_years
if deleted_at && deleted_at.year > created_at.year
(created_at.year...deleted_at.year).to_a
elsif deleted_at
[]
else
(created_at.year..Date.today.year).to_a
end
end
def to_jsonapi
response =
DataciteDoi.query(
nil,
client_id: uid, state: "findable,registered", page: { size: 0, number: 1 }, totals_agg: "client_export",
)
doi_counts = response.aggregations.clients_totals.buckets.first
dois_total = doi_counts ? doi_counts.doc_count : 0
dois_current_year = doi_counts ? doi_counts.this_year.buckets.dig(0, "doc_count") : 0
dois_last_year = doi_counts ? doi_counts.last_year.buckets.dig(0, "doc_count") : 0
attributes = {
"symbol" => symbol,
"name" => name,
"description" => description,
"system_email" => system_email,
"url" => url,
"re3data_id" => re3data_id,
"provider_id" => provider_id,
"provider_salesforce_id" => provider_salesforce_id,
"is_active" => is_active.getbyte(0) == 1,
"dois_total" => dois_total,
"dois_current_year" => dois_current_year,
"dois_last_year" => dois_last_year,
"created" => created.iso8601,
"updated" => updated.iso8601,
"deleted_at" => deleted_at ? deleted_at.iso8601 : nil,
}
{ "id" => symbol.downcase, "type" => "clients", "attributes" => attributes }
end
def self.export(query: nil)
# Loop through all clients
i = 0
page = { size: 1_000, number: 1 }
response = self.query(query, include_deleted: true, page: page)
response.records.each do |client|
client.send_client_export_message(client.to_jsonapi)
i += 1
end
total = response.results.total
total_pages = page[:size] > 0 ? (total.to_f / page[:size]).ceil : 0
# keep going for all pages
page_num = 2
while page_num <= total_pages
page = { size: 1_000, number: page_num }
response = self.query(query, include_deleted: true, page: page)
response.records.each do |client|
client.send_client_export_message(client.to_jsonapi)
i += 1
end
page_num += 1
end
"#{i} clients exported."
end
def self.export_doi_counts(query: nil)
# Loop through all clients
page = { size: 1_000, number: 1 }
response = self.query(query, page: page)
clients = response.results.to_a
total = response.results.total
total_pages = page[:size] > 0 ? (total.to_f / page[:size]).ceil : 0
# keep going for all pages
page_num = 2
while page_num <= total_pages
page = { size: 1_000, number: page_num }
response = self.query(query, page: page)
clients = clients + response.results.to_a
page_num += 1
end
# Get doi counts via DOIs query and combine next to clients.
response =
DataciteDoi.query(
nil,
page: { size: 0, number: 1 }, totals_agg: "client_export",
)
client_totals = {}
totals_buckets = response.aggregations.clients_totals.buckets
totals_buckets.each do |totals|
client_totals[totals["key"]] = { "count" => totals["doc_count"] }
end
headers = [
"Repository Name",
"Repository ID",
"Organization",
"DOIs in Index",
"DOIs in Database",
"DOIs missing",
]
dois_by_client = DataciteDoi.group(:datacentre).count
rows =
clients.reduce([]) do |sum, client|
db_total = dois_by_client[client.id.to_i].to_i
es_total =
client_totals[client.uid] ? client_totals[client.uid]["count"] : 0
if (db_total - es_total) > 0
# Limit for salesforce default of max 80 chars
name = +client.name.truncate(80)
# Clean the name to remove quotes, which can break csv parsers
name.gsub!(/["']/, "")
row = {
accountName: name,
fabricaAccountId: client.symbol,
parentFabricaAccountId:
client.provider.present? ? client.provider.symbol : nil,
doisCountTotal: es_total,
doisDbTotal: db_total,
doisMissing: db_total - es_total,
}.values
sum << CSV.generate_line(row)
end
sum
end
title = if Rails.env.stage?
if ENV["ES_PREFIX"].present?
"DataCite Fabrica Stage"
else
"DataCite Fabrica Test"
end
else
"DataCite Fabrica"
end
if rows.blank?
message = "Found 0 repositories with DOIs not indexed."
Rails.logger.warn message
self.send_notification_to_slack(message, title: title + ": DOIs in Elasticsearch", level: "good")
return nil
end
csv = [CSV.generate_line(headers)] + rows
total_missing = rows.reduce(0) do |sum, row|
sum = sum + row.split(",").last.to_i
sum
end
message = "Found #{csv.size - 1} repositories with #{total_missing} DOIs not indexed."
Rails.logger.warn message
self.send_notification_to_slack(message, title: title + ": DOIs in Elasticsearch", level: "warning")
csv.join("")
end
def self.import_dois(client_id, options = {})
if client_id.blank?
Rails.logger.error "Missing client ID."
exit
end
DoiImportByClientJob.perform_later(client_id)
end
# import all DOIs not indexed in Elasticsearch
def self.import_dois_not_indexed(query: nil)
table = CSV.parse(export_doi_counts(query: query), headers: true)
# loop through repositories that have DOIs not indexed in Elasticsearch
table.each do |row|
Rails.logger.info "Started import of #{row["DOIs in Database"]} DOIs (#{row["DOIs missing"]} missing) for repository #{row["Repository ID"]}."
DoiImportByClientJob.perform_later(row["Repository ID"])
end
end
protected
def check_issn
Array.wrap(issn).each do |i|
if !i.is_a?(Hash)
errors.add(:issn, "ISSN should be an object and not a string.")
elsif i["issnl"].present?
unless /\A\d{4}(-)?\d{3}[0-9X]+\z/.match?(i["issnl"])
errors.add(:issn, "ISSN-L #{i['issnl']} is in the wrong format.")
end
end
if i["electronic"].present?
unless /\A\d{4}(-)?\d{3}[0-9X]+\z/.match?(i["electronic"])
errors.add(
:issn,
"ISSN (electronic) #{i['electronic']} is in the wrong format.",
)
end
end
if i["print"].present?
unless /\A\d{4}(-)?\d{3}[0-9X]+\z/.match?(i["print"])
errors.add(
:issn,
"ISSN (print) #{i['print']} is in the wrong format.",
)
end
end
end
end
def check_language
Array.wrap(language).each do |l|
errors.add(:issn, "Language can't be empty.") if l.blank?
end
end
def check_certificate
Array.wrap(certificate).each do |c|
unless [
"CoreTrustSeal",
"DIN 31644",
"DINI",
"DSA",
"RatSWD",
"WDS",
"CLARIN",
].include?(c)
errors.add(
:certificate,
"Certificate #{
c
} is not included in the list of supported certificates.",
)
end
end
end
def check_repository_type
Array.wrap(repository_type).each do |r|
unless %w[
disciplinary
governmental
institutional
multidisciplinary
project-related
other
].include?(r)
errors.add(
:repository_type,
"Repository type #{
r
} is not included in the list of supported repository types.",
)
end
end
end
def uuid_format
unless UUID.validate(globus_uuid)
errors.add(:globus_uuid, "#{globus_uuid} is not a valid UUID")
end
end
def freeze_symbol
errors.add(:symbol, "cannot be changed") if symbol_changed?
end
def subjects_only_for_disciplinary_repos
if Array.wrap(subjects).any? && Array.wrap(repository_type).exclude?("disciplinary")
errors.add(
:subjects,
"Subjects are only allowed for disciplinary repositories. This repository_type is: #{repository_type}",
)
end
end
def check_id
if symbol && symbol.split(".").first != provider.symbol
errors.add(
:symbol,
", Your Client ID must include the name of your provider. Separated by a dot '.' ",
)
end
end
def get_prefix
provider_prefix = (provider.present? && provider.provider_prefixes.present?) ? provider.provider_prefixes.select { |_provider_prefix| (_provider_prefix.state == "without-repository") }.first : nil
prefix = Prefix.all.count > 0 ? Prefix.where.missing(:client_prefixes).merge(Prefix.where.missing(:provider_prefixes)).first : nil
provider_prefix || prefix || nil
end
def check_prefix
if !get_prefix
errors.add(
:base,
"No prefixes available. Unable to create repository.",
)
end
end
def assign_prefix
available_prefix = get_prefix
if !available_prefix
errors.add(
:base,
"No prefixes available. Created repository, but a prefix was not assigned. Contact support to get a prefix.",
)
else
prefix, provider_prefix = nil
available_prefix.class.name == "Prefix" ? prefix = available_prefix : provider_prefix = available_prefix
if !provider_prefix.present?
provider_prefix = ProviderPrefix.create(
provider_id: provider.symbol, prefix_id: prefix.uid
)
end
ClientPrefix.create(
client_id: symbol,
provider_prefix_id: provider_prefix.uid,
prefix_id: provider_prefix.prefix.uid
)
end
end
def user_url
ENV["VOLPINO_URL"] + "/users?client-id=" + symbol.downcase
end
private
def set_defaults
self.domains = "*" if domains.blank?
self.client_type = "repository" if client_type.blank?
self.issn = {} if issn.blank? || client_type == "repository"
self.certificate = [] if certificate.blank? || client_type == "periodical"
if repository_type.blank? || client_type == "periodical"
self.repository_type = []
end
self.is_active = is_active ? "\x01" : "\x00"
self.version = version.present? ? version + 1 : 0
self.role_name = "ROLE_DATACENTRE" if role_name.blank?
self.doi_quota_used = 0 unless doi_quota_used.to_i > 0
self.doi_quota_allowed = -1 unless doi_quota_allowed.to_i > 0
end
def convert_subject_hashes_to_camelcase
if self.subjects?
self.subjects = Array.wrap(self.subjects).map { |subject|
subject.transform_keys! do |key|
key.to_s.camelcase(:lower)
end
}
else
[]
end
end
def create_reference_repository
ReferenceRepository.create_from_client(self)
end
def update_reference_repository
ReferenceRepository.update_from_client(self)
end
def destroy_reference_repository
ReferenceRepository.destroy_from_client(self)
end
end