erp_base_erp_svcs 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GPL-3-LICENSE +674 -0
- data/README.rdoc +2 -0
- data/Rakefile +31 -0
- data/app/assets/javascripts/erp_base_erp_svcs/application.js +9 -0
- data/app/assets/stylesheets/erp_base_erp_svcs/application.css +7 -0
- data/app/controllers/erp_base_erp_svcs/application_controller.rb +4 -0
- data/app/helpers/erp_base_erp_svcs/application_helper.rb +4 -0
- data/app/models/category.rb +11 -0
- data/app/models/category_classification.rb +4 -0
- data/app/models/compass_ae_instance.rb +11 -0
- data/app/models/contact.rb +42 -0
- data/app/models/contact_purpose.rb +6 -0
- data/app/models/contact_type.rb +3 -0
- data/app/models/currency.rb +16 -0
- data/app/models/descriptive_asset.rb +4 -0
- data/app/models/email_address.rb +15 -0
- data/app/models/geo_country.rb +8 -0
- data/app/models/geo_zone.rb +8 -0
- data/app/models/individual.rb +76 -0
- data/app/models/iso_country_code.rb +10 -0
- data/app/models/money.rb +19 -0
- data/app/models/note.rb +14 -0
- data/app/models/note_type.rb +7 -0
- data/app/models/organization.rb +32 -0
- data/app/models/party.rb +191 -0
- data/app/models/party_relationship.rb +9 -0
- data/app/models/party_role.rb +8 -0
- data/app/models/phone_number.rb +16 -0
- data/app/models/postal_address.rb +19 -0
- data/app/models/relationship_type.rb +7 -0
- data/app/models/role_type.rb +7 -0
- data/app/models/valid_note_type.rb +4 -0
- data/app/models/view_type.rb +3 -0
- data/app/views/layouts/erp_base_erp_svcs/application.html.erb +14 -0
- data/config/initializers/erp_base_erp_svcs.rb +4 -0
- data/config/routes.rb +2 -0
- data/db/data_migrations/20110525001935_add_usd_currency.rb +11 -0
- data/db/data_migrations/20110609150135_add_iso_codes.rb +18 -0
- data/db/data_migrations/20110913145838_setup_compass_ae_instance.rb +11 -0
- data/db/data_sets/geo_countries.yml +2952 -0
- data/db/data_sets/geo_zones.yml +1233 -0
- data/db/migrate/20080805000020_base_erp_services.rb +461 -0
- data/db/migrate/20110913145329_create_compass_ae_instance.rb +15 -0
- data/db/migrate/upgrade/20110907171257_add_notes.rb +63 -0
- data/lib/erp_base_erp_svcs/ar_fixtures.rb +103 -0
- data/lib/erp_base_erp_svcs/command.rb +37 -0
- data/lib/erp_base_erp_svcs/config.rb +27 -0
- data/lib/erp_base_erp_svcs/engine.rb +27 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_category.rb +50 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_erp_type.rb +148 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_note_type.rb +47 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/data_migrator.rb +46 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/has_contact.rb +56 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/has_notes.rb +32 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/is_describable.rb +44 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/migrator.rb +76 -0
- data/lib/erp_base_erp_svcs/extensions/active_record/sti_instantiation.rb +37 -0
- data/lib/erp_base_erp_svcs/extensions/core/array.rb +20 -0
- data/lib/erp_base_erp_svcs/extensions/core/hash.rb +19 -0
- data/lib/erp_base_erp_svcs/extensions/core/numbers.rb +27 -0
- data/lib/erp_base_erp_svcs/extensions/core/object.rb +6 -0
- data/lib/erp_base_erp_svcs/extensions/railties/engine.rb +85 -0
- data/lib/erp_base_erp_svcs/extensions.rb +19 -0
- data/lib/erp_base_erp_svcs/non_escape_json_string.rb +5 -0
- data/lib/erp_base_erp_svcs/rails_template.rb +93 -0
- data/lib/erp_base_erp_svcs/version.rb +3 -0
- data/lib/erp_base_erp_svcs.rb +17 -0
- data/lib/tasks/compass_backup.rake +87 -0
- data/lib/tasks/erp_base_erp_svcs_tasks.rake +59 -0
- data/lib/tasks/release_notes/NOTES +21 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +42 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +8 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/spec.rb +27 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/spec.sqlite3 +0 -0
- data/spec/dummy/log/spec.log +4820 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/business_party.rb +21 -0
- data/spec/factories/contact_purpose.rb +8 -0
- data/spec/factories/party.rb +16 -0
- data/spec/factories/party_relationship.rb +10 -0
- data/spec/factories/party_role.rb +7 -0
- data/spec/factories/phone_number.rb +7 -0
- data/spec/factories/relationship_type.rb +8 -0
- data/spec/factories/role_type.rb +8 -0
- data/spec/models/category_classification_spec.rb +11 -0
- data/spec/models/category_spec.rb +18 -0
- data/spec/models/contact_purpose_spec.rb +12 -0
- data/spec/models/contact_spec.rb +12 -0
- data/spec/models/contact_type_spec.rb +12 -0
- data/spec/models/currency_spec.rb +12 -0
- data/spec/models/descriptive_asset_spec.rb +12 -0
- data/spec/models/email_address_spec.rb +12 -0
- data/spec/models/geo_country_spec.rb +13 -0
- data/spec/models/geo_zone_spec.rb +12 -0
- data/spec/models/individual_spec.rb +40 -0
- data/spec/models/money_spec.rb +12 -0
- data/spec/models/note_spec.rb +26 -0
- data/spec/models/note_type_spec.rb +12 -0
- data/spec/models/organization_spec.rb +33 -0
- data/spec/models/party_relationship_spec.rb +12 -0
- data/spec/models/party_role_spec.rb +12 -0
- data/spec/models/party_spec.rb +98 -0
- data/spec/models/phone_number_spec.rb +12 -0
- data/spec/models/postal_address_spec.rb +12 -0
- data/spec/models/relationship_type_spec.rb +11 -0
- data/spec/models/role_type_spec.rb +12 -0
- data/spec/models/view_type_spec.rb +12 -0
- data/spec/spec_helper.rb +57 -0
- metadata +391 -0
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ErpBaseErpSvcs'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require "rspec/core/rake_task"
|
29
|
+
RSpec::Core::RakeTask.new(:spec)
|
30
|
+
task :default => :spec
|
31
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
5
|
+
// the compiled file.
|
6
|
+
//
|
7
|
+
//= require jquery
|
8
|
+
//= require jquery_ujs
|
9
|
+
//= require_tree .
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require_tree .
|
7
|
+
*/
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Category < ActiveRecord::Base
|
2
|
+
acts_as_nested_set
|
3
|
+
|
4
|
+
belongs_to :category_record, :polymorphic => true
|
5
|
+
has_many :category_classifications, :dependent => :destroy
|
6
|
+
|
7
|
+
def self.iid( internal_identifier_string )
|
8
|
+
where("internal_identifier = ?",internal_identifier_string.to_s).first
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CompassAeInstance < ActiveRecord::Base
|
2
|
+
has_file_assets
|
3
|
+
|
4
|
+
def installed_engines
|
5
|
+
Rails::Application::Railties.engines.map{|e|
|
6
|
+
name = e.railtie_name.camelize
|
7
|
+
ErpBaseErpSvcs::ENGINES.include?(name) ? {:name => name, :version => ("#{name}::VERSION".constantize rescue 'N/A')} : nil
|
8
|
+
}.delete_if {|x| x == nil}
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Contact < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many :contact_purposes
|
3
|
+
belongs_to :party
|
4
|
+
belongs_to :contact_mechanism, :polymorphic => true, :dependent => :destroy
|
5
|
+
|
6
|
+
#rather than carry our own description for the abstract -contact-, we'll
|
7
|
+
#delegate that call to the implementor of the -contact_mechanism- interface
|
8
|
+
|
9
|
+
def description
|
10
|
+
@description = contact_mechanism.description
|
11
|
+
end
|
12
|
+
|
13
|
+
def description=(d)
|
14
|
+
@description=d
|
15
|
+
end
|
16
|
+
|
17
|
+
#delegate our need to provide a label to scaffolds to the implementor of
|
18
|
+
#the -contact_mechanism- interface.
|
19
|
+
|
20
|
+
def to_label
|
21
|
+
"#{contact_mechanism.description}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def summary_line
|
25
|
+
"#{contact_mechanism.summary_line}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# return first contact purpose
|
29
|
+
def purpose
|
30
|
+
contact_purposes.first.description
|
31
|
+
end
|
32
|
+
|
33
|
+
# return all contact purposes as an array
|
34
|
+
def purposes
|
35
|
+
p = []
|
36
|
+
contact_purposes.each do |cp|
|
37
|
+
p << cp.description
|
38
|
+
end
|
39
|
+
|
40
|
+
return p
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class EmailAddress < ActiveRecord::Base
|
2
|
+
has_contact
|
3
|
+
|
4
|
+
validates_format_of :email_address, :with => /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/, :message => "Must be a valid email address"
|
5
|
+
|
6
|
+
def summary_line
|
7
|
+
"#{description} : #{email_address}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_label
|
11
|
+
"#{description} : #{email_address}"
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Individual < ActiveRecord::Base
|
2
|
+
require 'attr_encrypted'
|
3
|
+
|
4
|
+
after_create :create_party
|
5
|
+
after_save :save_party
|
6
|
+
after_destroy :destroy_party
|
7
|
+
|
8
|
+
has_one :party, :as => :business_party
|
9
|
+
|
10
|
+
attr_encrypted :encrypted_ssn, :key => 'a secret key', :marshall => true
|
11
|
+
alias_attribute :unencypted_ssn, :social_security_number
|
12
|
+
|
13
|
+
def after_initialize
|
14
|
+
self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
def social_security_number=(ssn)
|
18
|
+
self.ssn_last_four = ssn[-4..-1]
|
19
|
+
self.encrypted_ssn = Individual.encrypt_encrypted_ssn(ssn)
|
20
|
+
self.save
|
21
|
+
end
|
22
|
+
|
23
|
+
def social_security_number
|
24
|
+
Individual.decrypt_encrypted_ssn(self.encrypted_ssn)
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :ssn, :social_security_number
|
28
|
+
|
29
|
+
def formatted_ssn_label
|
30
|
+
(self.ssn_last_four.blank?) ? "" : "XXX-XX-#{self.ssn_last_four}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.from_registered_user( a_user )
|
34
|
+
ind = Individual.new
|
35
|
+
ind.current_first_name = a_user.first_name
|
36
|
+
ind.current_last_name = a_user.last_name
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.from_registered_user( a_user )
|
40
|
+
ind = Individual.new
|
41
|
+
ind.current_first_name = a_user.first_name
|
42
|
+
ind.current_last_name = a_user.last_name
|
43
|
+
|
44
|
+
#this is necessary because this is where the callback creates the party instance.
|
45
|
+
ind.save
|
46
|
+
|
47
|
+
a_user.party = ind.party
|
48
|
+
a_user.save
|
49
|
+
ind.save
|
50
|
+
#this is necessary because save returns a boolean, not the saved object
|
51
|
+
return ind
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_party
|
55
|
+
pty = Party.new
|
56
|
+
pty.description = [current_personal_title,current_first_name,current_last_name].join(' ').strip
|
57
|
+
pty.business_party = self
|
58
|
+
pty.save
|
59
|
+
self.save
|
60
|
+
end
|
61
|
+
|
62
|
+
def save_party
|
63
|
+
self.party.description = [current_personal_title,current_first_name,current_last_name].join(' ').strip
|
64
|
+
self.party.save
|
65
|
+
end
|
66
|
+
|
67
|
+
def destroy_party
|
68
|
+
if self.party
|
69
|
+
self.party.destroy
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_label
|
74
|
+
"#{current_first_name} #{current_last_name}"
|
75
|
+
end
|
76
|
+
end
|
data/app/models/money.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Money < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :currency
|
4
|
+
before_save :parse_currency_code
|
5
|
+
|
6
|
+
attr_accessor :currency_code
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def parse_currency_code
|
11
|
+
unless currency_code.blank?
|
12
|
+
case currency_code.downcase
|
13
|
+
# Check for all iso currency types we support
|
14
|
+
when "usd" then self.currency = Currency.usd
|
15
|
+
# add additional currency types
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/app/models/note.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Note < ActiveRecord::Base
|
2
|
+
belongs_to :note_type
|
3
|
+
belongs_to :noted_record, :polymorphic => true
|
4
|
+
belongs_to :created_by, :class_name => 'Party', :foreign_key => 'created_by_id'
|
5
|
+
|
6
|
+
def note_type_desc
|
7
|
+
self.note_type.description
|
8
|
+
end
|
9
|
+
|
10
|
+
def summary
|
11
|
+
(content.length > 20) ? "#{content[0..20]}..." : content
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Organization < ActiveRecord::Base
|
2
|
+
after_create :create_party
|
3
|
+
after_save :save_party
|
4
|
+
after_destroy :destroy_party
|
5
|
+
|
6
|
+
has_one :party, :as => :business_party
|
7
|
+
|
8
|
+
def create_party
|
9
|
+
pty = Party.new
|
10
|
+
pty.description = self.description
|
11
|
+
pty.business_party = self
|
12
|
+
|
13
|
+
pty.save
|
14
|
+
self.save
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_party
|
18
|
+
self.party.description = self.description
|
19
|
+
self.party.save
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy_party
|
23
|
+
if self.party
|
24
|
+
self.party.destroy
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_label
|
29
|
+
"#{description}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/app/models/party.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
class Party < ActiveRecord::Base
|
2
|
+
has_notes
|
3
|
+
|
4
|
+
has_many :contacts, :dependent => :destroy
|
5
|
+
has_many :created_notes, :class_name => 'Note', :foreign_key => 'created_by_id'
|
6
|
+
belongs_to :business_party, :polymorphic => true
|
7
|
+
has_many :party_roles, :dependent => :destroy
|
8
|
+
has_many :role_types, :through => :party_roles
|
9
|
+
|
10
|
+
attr_reader :relationships
|
11
|
+
attr_writer :create_relationship
|
12
|
+
|
13
|
+
# Gathers all party relationships that contain this particular party id
|
14
|
+
# in either the from or to side of the relationship.
|
15
|
+
def relationships
|
16
|
+
@relationships ||= PartyRelationship.where('party_id_from = ? OR party_id_to = ?', id, id)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Creates a new PartyRelationship for this particular
|
20
|
+
# party instance.
|
21
|
+
def create_relationship(description, to_party_id)
|
22
|
+
PartyRelationship.create(:description => description, :party_id_from => id, :party_id_to => to_party_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Callback
|
26
|
+
def after_destroy
|
27
|
+
if self.business_party
|
28
|
+
self.business_party.destroy
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_phone_number?(phone_number)
|
33
|
+
result = nil
|
34
|
+
self.contacts.each do |c|
|
35
|
+
if c.contact_mechanism_type == 'PhoneNumber'
|
36
|
+
if c.contact_mechanism.phone_number == phone_number
|
37
|
+
result = true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_zip_code?(zip)
|
45
|
+
result = nil
|
46
|
+
self.contacts.each do |c|
|
47
|
+
if c.contact_mechanism_type == 'PostalAddress'
|
48
|
+
if c.contact_mechanism.zip == zip
|
49
|
+
result = true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
# Alias for to_s
|
57
|
+
def to_label
|
58
|
+
to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
"#{description}"
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
#************************************************************************************************
|
67
|
+
#** Contact Methods
|
68
|
+
#************************************************************************************************
|
69
|
+
|
70
|
+
def find_contact_mechanism_with_purpose(contact_mechanism_class, contact_purpose)
|
71
|
+
contact_mechanism = nil
|
72
|
+
|
73
|
+
contact = self.find_contact_with_purpose(contact_mechanism_class, contact_purpose)
|
74
|
+
contact_mechanism = contact.contact_mechanism unless contact.nil?
|
75
|
+
|
76
|
+
contact_mechanism
|
77
|
+
end
|
78
|
+
|
79
|
+
def find_contact_with_purpose(contact_mechanism_class, contact_purpose)
|
80
|
+
contact = nil
|
81
|
+
|
82
|
+
#if a symbol or string was passed get the model
|
83
|
+
unless contact_purpose.is_a? ContactPurpose
|
84
|
+
contact_purpose = ContactPurpose.find_by_internal_identifier(contact_purpose.to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
contact = self.find_contact(contact_mechanism_class, nil, [contact_purpose])
|
88
|
+
|
89
|
+
contact
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_all_contacts_by_contact_mechanism(contact_mechanism_class)
|
93
|
+
table_name = contact_mechanism_class.name.tableize
|
94
|
+
|
95
|
+
contacts = self.contacts.joins("inner join #{table_name} on #{table_name}.id = contact_mechanism_id and contact_mechanism_type = '#{contact_mechanism_class.name}'")
|
96
|
+
|
97
|
+
contacts.collect(&:contact_mechanism)
|
98
|
+
end
|
99
|
+
|
100
|
+
def find_contact(contact_mechanism_class, contact_mechanism_args={}, contact_purposes=[])
|
101
|
+
conditions = ''
|
102
|
+
|
103
|
+
table_name = contact_mechanism_class.name.tableize
|
104
|
+
|
105
|
+
contact_mechanism_args.each do |key, value|
|
106
|
+
next if key == 'updated_at' or key == 'created_at' or key == 'id'
|
107
|
+
conditions += " #{table_name}.#{key} = '#{value}' and" unless value.nil?
|
108
|
+
end unless contact_mechanism_args.nil?
|
109
|
+
|
110
|
+
conditions = conditions[0..conditions.length - 5] unless conditions == ''
|
111
|
+
|
112
|
+
self.contacts.joins("inner join #{table_name} on #{table_name}.id = contact_mechanism_id and contact_mechanism_type = '#{contact_mechanism_class.name}'
|
113
|
+
inner join contact_purposes_contacts on contact_purposes_contacts.contact_id = contacts.id
|
114
|
+
and contact_purposes_contacts.contact_purpose_id in (#{contact_purposes.collect{|item| item.attributes["id"]}.join(',')})").where(conditions).first
|
115
|
+
end
|
116
|
+
|
117
|
+
# looks for contacts matching on value and purpose
|
118
|
+
# if a contact exists, it updates, if not, it adds it
|
119
|
+
def add_contact(contact_mechanism_class, contact_mechanism_args={}, contact_purposes=[])
|
120
|
+
contact_purposes = [contact_purposes] if !contact_purposes.kind_of?(Array) # gracefully handle a single purpose not in an array
|
121
|
+
contact = find_contact(contact_mechanism_class, contact_mechanism_args, contact_purposes)
|
122
|
+
if contact.nil?
|
123
|
+
contact_mechanism = contact_mechanism_class.new(contact_mechanism_args)
|
124
|
+
contact_mechanism.contact.party = self
|
125
|
+
contact_mechanism.contact.contact_purposes = contact_purposes
|
126
|
+
contact_mechanism.contact.save
|
127
|
+
contact_mechanism.save
|
128
|
+
|
129
|
+
self.contacts << contact_mechanism.contact
|
130
|
+
else
|
131
|
+
contact_mechanism = update_contact(contact_mechanism_class, contact, contact_mechanism_args)
|
132
|
+
end
|
133
|
+
|
134
|
+
contact_mechanism
|
135
|
+
end
|
136
|
+
|
137
|
+
# tries to update contact by purpose
|
138
|
+
# if contact doesn't exist, it adds it
|
139
|
+
def update_or_add_contact_with_purpose(contact_mechanism_class, contact_purpose, contact_mechanism_args)
|
140
|
+
if return_value = update_contact_with_purpose(contact_mechanism_class, contact_purpose, contact_mechanism_args)
|
141
|
+
return_value
|
142
|
+
else
|
143
|
+
add_contact(contact_mechanism_class, contact_mechanism_args, [contact_purpose])
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# looks for a contact matching on purpose
|
148
|
+
# if it exists, it updates it, if not returns false
|
149
|
+
def update_contact_with_purpose(contact_mechanism_class, contact_purpose, contact_mechanism_args)
|
150
|
+
contact = find_contact_with_purpose(contact_mechanism_class, contact_purpose)
|
151
|
+
contact.nil? ? false : update_contact(contact_mechanism_class, contact, contact_mechanism_args)
|
152
|
+
end
|
153
|
+
|
154
|
+
def update_contact(contact_mechanism_class, contact, contact_mechanism_args)
|
155
|
+
contact_mechanism_class.update(contact.contact_mechanism, contact_mechanism_args)
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_contact_by_method(m)
|
159
|
+
method_name = m.split('_')
|
160
|
+
return nil if method_name.size < 3 or method_name.size > 4
|
161
|
+
# handles 1 or 2 segment contact purposes (i.e. home or employment_offer)
|
162
|
+
# contact mechanism must be 2 segments, (i.e. email_address, postal_address, phone_number)
|
163
|
+
if method_name.size == 4
|
164
|
+
purpose = method_name[0] + '_' + method_name[1]
|
165
|
+
klass = method_name[2] + '_' + method_name[3]
|
166
|
+
else
|
167
|
+
purpose = method_name[0]
|
168
|
+
klass = method_name[1] + '_' + method_name[2]
|
169
|
+
end
|
170
|
+
|
171
|
+
contact_purpose = ContactPurpose.find_by_internal_identifier(purpose)
|
172
|
+
if contact_purpose.nil? or !Object.const_defined?(klass.camelize)
|
173
|
+
return nil
|
174
|
+
else
|
175
|
+
find_contact_mechanism_with_purpose(klass.camelize.constantize, contact_purpose)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def respond_to?(m)
|
180
|
+
((get_contact_by_method(m.to_s).nil? ? super : true)) rescue super
|
181
|
+
end
|
182
|
+
|
183
|
+
def method_missing(m, *args, &block)
|
184
|
+
value = get_contact_by_method(m.to_s)
|
185
|
+
(value.nil?) ? super : (return value)
|
186
|
+
end
|
187
|
+
|
188
|
+
#************************************************************************************************
|
189
|
+
#** End
|
190
|
+
#************************************************************************************************
|
191
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class PartyRelationship < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :from_party, :class_name => "Party", :foreign_key => "party_id_from"
|
4
|
+
belongs_to :to_party, :class_name => "Party", :foreign_key => "party_id_to"
|
5
|
+
belongs_to :from_role, :class_name => "RoleType", :foreign_key => "role_type_id_from"
|
6
|
+
belongs_to :to_role, :class_name => "RoleType", :foreign_key => "role_type_id_to"
|
7
|
+
belongs_to :relationship_type, :class_name => "RelationshipType"
|
8
|
+
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class PhoneNumber < ActiveRecord::Base
|
2
|
+
has_contact
|
3
|
+
|
4
|
+
def summary_line
|
5
|
+
"#{description} : #{phone_number}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def eql_to?(phone)
|
9
|
+
self.phone_number.reverse.gsub(/[^0-9]/,"")[0..9] == phone.reverse.gsub(/[^0-9]/,"")[0..9]
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_label
|
13
|
+
"#{description} : #{phone_number}"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class PostalAddress < ActiveRecord::Base
|
2
|
+
has_contact
|
3
|
+
|
4
|
+
belongs_to :geo_country
|
5
|
+
belongs_to :geo_zone
|
6
|
+
|
7
|
+
def summary_line
|
8
|
+
"#{description} : #{address_line_1}, #{city}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_label
|
12
|
+
"#{description} : #{address_line_1}, #{city}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def zip_eql_to?(zip)
|
16
|
+
self.zip.downcase.gsub(/[^a-zA-Z0-9]/, "")[0..4] == zip.to_s.downcase.gsub(/[^a-zA-Z0-9]/,"")[0..4]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class RelationshipType < ActiveRecord::Base
|
2
|
+
acts_as_nested_set
|
3
|
+
acts_as_erp_type
|
4
|
+
|
5
|
+
belongs_to :valid_from_role, :class_name => "RoleType", :foreign_key => "valid_from_role_type_id"
|
6
|
+
belongs_to :valid_to_role, :class_name => "RoleType", :foreign_key => "valid_to_role_type_id"
|
7
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>ErpBaseErpSvcs</title>
|
5
|
+
<%= stylesheet_link_tag "erp_base_erp_svcs/application" %>
|
6
|
+
<%= javascript_include_tag "erp_base_erp_svcs/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|