class Project < ActiveRecord::Base
include GlobalHelpers
extend FriendlyId
#associations between tables
belongs_to :dmptemplate
belongs_to :organisation
has_many :plans
has_many :project_groups, :dependent => :destroy
has_and_belongs_to_many :guidance_groups, join_table: "project_guidance"
friendly_id :title, use: [:slugged, :history, :finders]
# Set the is_public flag to false if we are making this a test plan
# -----------------------------------------------------------------
def is_test=(val)
self[:is_public] = false if val && is_public?
self[:is_test] = val
end
# Set the is_test flag to false if we are making this plan public
# -----------------------------------------------------------------
def is_public=(val)
self[:is_test] = false if val && is_test?
self[:is_public] = val
end
##
# returns the title of the project
#
# @return [String] the project's title
def to_s
"#{title}"
end
after_create :create_plans
##
# sets a new funder for the project
# defaults to the first dmptemplate if the current template is nill and the funder has more than one dmptemplate
#
# @param new_funder_id [Integer] the id for a new funder
# @return [Organisation] the new funder
def funder_id=(new_funder_id)
if new_funder_id != "" then
new_funder = Organisation.find(new_funder_id);
if new_funder.dmptemplates.count >= 1 && self.dmptemplate.nil? then
self.dmptemplate = new_funder.dmptemplates.first
end
end
end
##
# returns the funder id for the project
#
# @return [Integer, nil] the id for the funder
def funder_id
if self.dmptemplate.nil? then
return nil
end
template_org = self.dmptemplate.organisation
if template_org.organisation_type.name == constant("organisation_types.funder").downcase
return template_org.id
else
return nil
end
end
##
# returns the funder organisation for the project or nil if none is specified
#
# @return [Organisation, nil] the funder for project, or nil if none exists
def funder
if self.dmptemplate.nil? then
return nil
end
template_org = self.dmptemplate.organisation
if template_org.organisation_type.name == constant("organisation_types.funder").downcase
return template_org
else
return nil
end
end
##
# returns the name of the funder for the project
#
# @return [String] the name fo the funder for the project
def funder_name
if self.funder.nil?
return read_attribute(:funder_name)
else
return self.funder.name
end
end
##
# defines a new funder_name for the project.
#
# @param new_funder_name [String] the string name of the new funder
# @return [Integer, nil] the org_id of the new funder
def funder_name=(new_funder_name)
write_attribute(:funder_name, new_funder_name)
org_table = Organisation.arel_table
existing_org = Organisation.where(org_table[:name].matches(new_funder_name))
if existing_org.nil?
existing_org = Organisation.where(org_table[:abbreviation].matches(new_funder_name))
end
unless existing_org.empty?
self.funder_id=existing_org.id
end
end
##
# sets a new institution_id if there is no current organisation
#
# @param new_institution_id [Integer] the id for the new institution
# @return [Integer, Bool] false if an organisation exists, or the id of the set org if a new organisation is set
def institution_id=(new_institution_id)
if organisation.nil? then
self.organisation_id = new_institution_id
end
end
##
# returns the organisation which is root over the owning organisation
#
# @return [Integer, nil] the organisation_id or nil
def institution_id
if organisation.nil?
return nil
else
return organisation.root.id
end
end
##
# defines a new organisation_id for the project
# but is confusingly labled unit_id
#
# @param new_unit_id [Integer]
# @return [Integer, Boolean] the new organisation ID or false if no unit_id was passed
def unit_id=(new_unit_id)
unless new_unit_id.nil? ||new_unit_id == ""
self.organisation_id = new_unit_id
end
end
##
# returns the organisation_id or nil
# again seems redundant
#
# @return [nil, Integer] nil if no organisation, or the id if there is an organisation specified
def unit_id
if organisation.nil? || organisation.parent_id.nil?
return nil
else
return organisation_id
end
end
##
# assigns the passed user_id to the creater_role for the project
# gives the user rights to read, edit, administrate, and defines them as creator
#
# @param user_id [Integer] the user to be given priveleges' id
def assign_creator(user_id)
add_user(user_id, true, true, true)
end
##
# assigns the passed user_id as an editor for the project
# gives the user rights to read and edit
#
# @param user_id [Integer] the user to be given priveleges' id
def assign_editor(user_id)
add_user(user_id, true)
end
##
# assigns the passed user_id as a reader for the project
# gives the user rights to read
#
# @param user_id [Integer] the user to be given priveleges' id
def assign_reader(user_id)
add_user(user_id)
end
##
# assigns the passed user_id as an administrator for the project
# gives the user rights to read, adit, and administrate the project
#
# @param user_id [Integer] the user to be given priveleges' id
def assign_administrator(user_id)
add_user(user_id, true, true)
end
##
# whether or not the current plan is administrable by the user
#
# @param user_id [Integer] the user to check if has privleges
# @return [Boolean] true if user can administer project, false otherwise
def administerable_by(user_id)
user = project_groups.find_by_user_id(user_id)
if (! user.nil?) && user.project_administrator then
return true
else
return false
end
end
##
# whether or not the current plan is editable by the user
#
# @param user_id [Integer] the user to check if has privleges
# @return [Boolean] true if user can edit project, false otherwise
def editable_by(user_id)
user = project_groups.find_by_user_id(user_id)
if (! user.nil?) && user.project_editor then
return true
else
return false
end
end
##
# whether or not the current plan is readable by the user
# should be renamed to readable_by?
#
# @param user_id [Integer] the user to check if has privleges
# @return [Boolean] true if user can read project, false otherwise
def readable_by(user_id)
user = project_groups.find_by_user_id(user_id)
if (! user.nil?) then
return true
else
return false
end
end
##
# returns the projects which the user can atleast read
#
# @param user_id [Integer] the user to lookup projects for
# @return [Array<Project>] list of all projects the user can atleast read
def self.projects_for_user(user_id)
projects = Array.new
groups = ProjectGroup.where("user_id = ?", user_id)
unless groups.nil? then
groups.each do |group|
unless group.project.nil? then
projects << group.project
end
end
end
return projects
end
##
# whether or not the specified user_id created this project
# should be renamed to created_by?
#
# @param user_id [Integer] the user to check the priveleges of
# @return [Boolean] true if the user created the project
def created_by(user_id)
user = project_groups.find_by_user_id(user_id)
if (! user.nil?) && user.project_creator then
return true
else
return false
end
end
##
# the datetime for the latest update of this project, or any plan it owns
#
# @return [DateTime] the time of latest update
def latest_update
latest_update = updated_at
plans.each do |plan|
if plan.latest_update > latest_update then
latest_update = plan.latest_update
end
end
return latest_update
end
# Getters to match 'My plans' columns
##
# the title of the project
#
# @return [String] the title of the project
def name
self.title
end
##
# the owner of the project
#
# @return [User] the creater of the project
def owner
self.project_groups.find_by_project_creator(true).try(:user)
end
##
# the time the project was last updated, formatted as a date
#
# @return [Date] last update as a date
def last_edited
self.latest_update.to_date
end
##
# whether or not the plan is shared with anybody
#
# @return [Boolean] true if the project has been shared
def shared?
self.project_groups.count > 1
end
alias_method :shared, :shared?
##
# the organisation who owns the project
#
# @return [Dmptemplate,Organisation,String] the template, it's owner, or it's owner's abreviation
def template_owner
self.dmptemplate.try(:organisation).try(:abbreviation)
end
private
##
# adds a user to the project
# if no flags are specified, the user is given read privleges
#
# @param user_id [Integer] the user to be given privleges
# @param is_editor [Boolean] whether or not the user can edit the project
# @param is_administrator [Boolean] whether or not the user can administrate the project
# @param is_creator [Boolean] wheter or not the user created the project
# @return [Array<ProjectGroup>]
def add_user(user_id, is_editor = false, is_administrator = false, is_creator = false)
group = ProjectGroup.new
group.user_id = user_id
group.project_creator = is_creator
group.project_editor = is_editor
group.project_administrator = is_administrator
project_groups << group
end
##
# creates a plan for each phase in the dmptemplate associated with this project
# unless the phase is unpublished, it creates a new plan, and a new version of the plan and adds them to the project's plans
#
# @return [Array<Plan>]
def create_plans
dmptemplate.phases.each do |phase|
latest_published_version = phase.latest_published_version
unless latest_published_version.nil?
new_plan = Plan.new
new_plan.version = latest_published_version
plans << new_plan
end
end
end
end