Skip to content

Instantly share code, notes, and snippets.

@selvait90
Last active January 8, 2017 10:48
Show Gist options
  • Save selvait90/11e9e84a9bd26e56c47d to your computer and use it in GitHub Desktop.
Save selvait90/11e9e84a9bd26e56c47d to your computer and use it in GitHub Desktop.
# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 The Collaborative Software Foundation
#
# This file is part of TriSano.
#
# TriSano is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the
# Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# TriSano is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with TriSano. If not, see http://www.gnu.org/licenses/agpl-3.0.txt.
class Place < ActiveRecord::Base
belongs_to :entity
has_and_belongs_to_many :place_types,
:foreign_key => 'place_id',
:class_name => 'Code',
:join_table => 'places_types',
:association_foreign_key => 'type_id',
:order => 'code_description'
validates_presence_of :name
validates_each :name, :if => :is_unassigned_jurisdiction? do |record, attr, value|
if unassigned = self.unassigned_jurisdiction
record.errors.add(attr, :unassigned_is_special) unless unassigned == record
end
end
validates_presence_of :short_name, :if => :is_a_jurisdiction?
before_update :set_jurisdiction_place_type, :if => :is_a_jurisdiction?
validate :not_modifying_special_jurisdiction_names, :if => :is_a_jurisdiction?, :on => :update
named_scope :active, {
:include => :entity,
:conditions => {:entities => {:deleted_at => nil}}
}
named_scope :types, lambda { |types|
{ :include => :place_types,
:conditions => { :codes => {:code_name => 'placetype', :the_code => types} },
}
}
named_scope :diagnostic_facilities, lambda { |name|
{ :conditions => ["places.name ILIKE ? AND codes.code_name = 'placetype' AND codes.the_code IN (?) AND entities.deleted_at IS NULL", name + '%', Place.diagnostic_type_codes],
:joins => [:place_types, :entity],
:order => 'LOWER(TRIM(places.name)) ASC'
}
}
named_scope :starts_with, lambda { |name|
{ :conditions => [ "name ~* ?", "^#{name}" ] }
}
named_scope :reporting_agencies_by_name, lambda { |name|
{ :conditions => ["places.name ILIKE ? AND codes.code_name = 'placetype' AND codes.the_code IN (?) AND entities.deleted_at IS NULL", name + '%', Place.agency_type_codes],
:joins => [:place_types, :entity],
:order => 'LOWER(TRIM(places.name)) ASC'
}
}
class << self
# TODO: Does not yet take into account multiple edits of a single hospital. Can probably be optimized.
def hospitals(unique=false)
if unique
select = "DISTINCT ON (name) places.*"
self.all_by_place_code('H', select)
else
self.all_by_place_code('H')
end
end
def name=(value); super; logger.debug value; logger.info "*****************"; end;
def jurisdictions
jurisdictions = self.all_by_place_code('J')
pull_unassigned_and_put_it_on_top(jurisdictions)
end
def jurisdiction_by_name(name)
all_by_name_and_types(name, 'J').first
end
def labs_by_name(name)
all_by_name_and_types(name, 'L')
end
def all_by_name_and_types(name, type_codes, short_name=false)
type_codes = [ type_codes ] unless type_codes.is_a?(Array)
self.all(
:joins => [:place_types, :entity],
:conditions => [ "LOWER(places.#{short_name ? 'short_name' : 'name'}) = ? AND codes.the_code IN (?) AND codes.code_name = 'placetype' AND entities.deleted_at IS NULL", name.downcase, type_codes ],
:order => "LOWER(TRIM(name))")
end
def jurisdictions_for_privilege_by_user_id(user_id, privilege)
query = "
SELECT
places.id, places.entity_id, places.name, places.short_name
FROM
users,
role_memberships,
privileges_roles,
privileges,
entities,
places
WHERE
users.id = role_memberships.user_id
AND
privileges.id = privileges_roles.privilege_id
AND
role_memberships.role_id = privileges_roles.role_id
AND
role_memberships.jurisdiction_id = entities.id
AND
places.entity_id = entities.id
AND
users.id = '#{user_id}'
AND
privileges.priv_name = '#{privilege.to_s}'
ORDER BY
places.name"
jurisdictions = find_by_sql(query)
pull_unassigned_and_put_it_on_top(jurisdictions)
end
def hospitalization_type_codes
%w(H)
end
def lab_type_codes
%w(L)
end
def agency_type_codes
%w(H L C O S DC CF LCF PUB OOS)
end
def diagnostic_type_codes
#%w(H L C O S CF PUB OOS)
#Lei Comments Add place type for std program
%w(H L C O S CF PUB OOS 01 02 03 04 06 07 10 13 14 15 16 18 66 77 99)
end
def epi_type_codes
%w(S P FE DC RA E CF LCF GLE)
end
# Includes a unique array of all of the above, which should not include
# jurisdictions.
def exposed_type_codes
(agency_type_codes + diagnostic_type_codes + epi_type_codes).uniq
end
def agency_types
place_types(agency_type_codes)
end
def diagnostic_types
place_types(diagnostic_type_codes)
end
def epi_types
place_types(epi_type_codes)
end
def exposed_types
place_types(exposed_type_codes)
end
def place_types(type_codes)
Code.active.find(:all,
:conditions => ['code_name = ? AND the_code IN (?)', 'placetype', type_codes])
end
def all_by_place_code(code, select=nil)
if select
self.all(
:select => select,
:joins => [:place_types, :entity],
:conditions => "codes.the_code = '#{code}' AND codes.code_name = 'placetype' AND entities.deleted_at IS NULL",
:order => 'name, places.id'
)
else
self.all(
:joins => [:place_types, :entity],
:conditions => "codes.the_code = '#{code}' AND codes.code_name = 'placetype' AND entities.deleted_at IS NULL",
:order => 'name, places.id'
)
end
end
def unassigned_jurisdiction
self.first({
:joins => [:place_types, :entity],
:conditions => ["name = ? AND codes.the_code = ? AND codes.code_name = ?",
"Unassigned",
Code.jurisdiction_place_type.the_code,
"placetype"]
})
end
def unassigned_jurisdiction_entity_id
unassigned_jurisdiction.try(:entity_id)
end
def pull_unassigned_and_put_it_on_top(jurisdictions)
unassigned = jurisdictions.find { |jurisdiction| jurisdiction.read_attribute(:name) == "Unassigned" }
jurisdictions.unshift( jurisdictions.delete( unassigned ) ) unless unassigned.nil?
jurisdictions
end
end
def xml_fields
[:name, [:place_type_ids, {:rel => :place_type}]]
end
def place_descriptions
place_types.sort_by(&:sort_order).collect { |pt| pt.code_description }
end
def formatted_place_descriptions
place_descriptions.to_sentence
end
# The unassigned jurisdiction is the only place with a translated name, so
# we have overriden the name getter to go to the locale configs for the
# correct translation to display.
def name
if read_attribute(:name) == 'Unassigned'
I18n.translate('unassigned_jurisdiction_name')
else
read_attribute(:name)
end
end
def short_name
if is_unassigned_jurisdiction?
I18n.translate('unassigned_jurisdiction_name')
else
read_attribute(:short_name)
end
end
def is_unassigned_jurisdiction?
is_a_jurisdiction? && self.read_attribute(:name) == "Unassigned"
end
alias unassigned_jurisdiction? is_unassigned_jurisdiction?
def is_a_jurisdiction?
self.place_type_ids.include?(Code.jurisdiction_place_type_id)
end
def set_jurisdiction_place_type
# Once a Place is created as a Jurisdiction
# it's place type will always be set to Jurisdiction
self.place_types = [Code.find(Code.jurisdiction_place_type_id)]
end
def not_modifying_special_jurisdiction_names
special_jurisdiction_names = ["Out of State", "Unassigned"]
# Uses the ActiveRecord::Dirty to determine if user is modifying the name of a special jurisdiction
self.errors.add(:base, "Cannot modify the name of this Jurisdiction.") if self.name_changed? && special_jurisdiction_names.include?(self.name_was)
end
end
# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 The Collaborative Software Foundation
#
# This file is part of TriSano.
#
# TriSano is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the
# Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# TriSano is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with TriSano. If not, see http://www.gnu.org/licenses/agpl-3.0.txt.
class PlaceEntity < Entity
has_one :place, :foreign_key => "entity_id", :class_name => "Place", :dependent => :destroy
has_one :entity, :through => :place
accepts_nested_attributes_for :place
=begin
, :reject_if => proc { |attrs| attrs.all? { |k, v|
puts k; v.blank?
v.blank?
} }, :allow_destroy => true
=end
named_scope :jurisdictions,
:joins => "INNER JOIN places p on entities.id = p.entity_id INNER JOIN places_types on p.id = places_types.place_id INNER JOIN codes on places_types.type_id = codes.id",
:conditions => "codes.the_code = 'J' AND codes.code_name = 'placetype'",
:order => 'p.name',
:readonly => false
named_scope :labs,
:joins => "INNER JOIN places p on entities.id = p.entity_id INNER JOIN places_types on p.id = places_types.place_id INNER JOIN codes on places_types.type_id = codes.id",
:conditions => "codes.the_code = 'L' AND codes.code_name = 'placetype'",
:order => 'p.name',
:include => :place,
:readonly => false
named_scope :active,
:conditions => "entities.deleted_at IS NULL"
# Intended to be chained to one of the other jurisdiction named scopes
named_scope :excluding_unassigned,
:conditions => "p.name != 'Unassigned'"
named_scope :by_place_name, lambda { |place_name|
{ :joins => "INNER JOIN places p on entities.id = p.entity_id",
:conditions => ["p.name = ? and entities.deleted_at IS NULL", place_name]
}
}
named_scope :with_short_name, lambda { |short_name|
{ :conditions => ["p.short_name = ?", short_name] } }
named_scope :with_place_names_like, lambda { |place_name|
{ :joins => ["INNER JOIN places p on entities.id = p.entity_id"],
:conditions => ["p.name ILIKE ? AND entities.deleted_at IS NULL", '%' + place_name + '%']
}
}
named_scope :limit_by_place_types, lambda { |types|
{ :conditions => ["codes.the_code IN (?)", types] }
}
# Used to decrease number of queries executed when diplaying a place
# listing. Should be combined with other place scopes.
named_scope :optimize_for_index, {
:joins => [{:place => :place_types}],
:select => "DISTINCT(entities.id), p.name",
:order => "p.name ASC"
}
# builds a scoped object, like what is returned from named_scopes
def self.by_name_and_place_type(search_data)
scope = optimize_for_index
if search_data.includes_place_type?
scope = scope.limit_by_place_types(search_data.place_types)
end
scope = scope.with_place_names_like(search_data.name)
scope
end
# Convenience method to allow a place entity's place name to be accessible through
# the place entity directly, enabling things like collection_select to work easily.
def name
place.name unless place.nil?
end
def merge(entity_ids)
entity_ids = [entity_ids].flatten.compact
if entity_ids.empty?
errors.add(:base, :no_entities_for_merging)
return
end
begin
::PlaceEntity.transaction do
returning [] do |effected_participations|
self.class.exclude_deleted.exclude_entity(self).find(entity_ids).each do |entity|
effected_events_for_entity = []
pids = []
Participation.find(:all, :conditions => ["primary_entity_id = ? OR secondary_entity_id = ?", entity.id, entity.id]).each do |participation|
change_entity_reference(entity, participation)
update_addresses(participation)
participation.save!
effected_participations << participation
effected_events_for_entity << participation.event_id
end
pids = self.place.place_types.map { |p| p.id }
entity.place.place_types.each do |pt|
unless pids.include? pt.id
self.place.place_types << pt
end
end
entity.deleted_at = Time.now
entity.merged_into_entity_id = self.id
entity.merge_effected_events = effected_events_for_entity.uniq.join(",")
entity.save!
end
end
end
rescue Exception => ex
logger.error ex
errors.add(:base, :failed_merge, :msg => ex.message)
return nil
end
end
private
def change_entity_reference(entity, participation)
if participation.primary_entity_id == entity.id
participation.primary_entity_id = self.id
else
participation.secondary_entity_id = self.id
end
end
def update_addresses(participation)
if (participation.type == "InterestedPlace")
clone_canonical_address(participation)
elsif (participation.type == "InterestedParty")
change_address_entity_reference(participation)
end
end
# For certain participation types, the event's address should receive the canonical address of the entity
# at which the merge is directed.
def clone_canonical_address(participation)
if clone_canonical_address?(participation)
cloned_canonical_address = self.canonical_address.clone
cloned_canonical_address.save
delete_existing_address(participation)
participation.event.address = cloned_canonical_address
end
end
# Returns true if this participation's event requires a cloning of a canonical address, along with a merge operation.
def clone_canonical_address?(participation)
(self.canonical_address && (participation.type == "InterestedPlace"))
end
def change_address_entity_reference(participation)
existing_address = participation.event.address
unless existing_address.nil?
existing_address.entity = self
existing_address.save
end
end
def delete_existing_address(participation)
existing_address = participation.event.address
existing_address.destroy unless existing_address.nil?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment