erp_base_erp_svcs 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/GPL-3-LICENSE +674 -0
  2. data/README.rdoc +2 -0
  3. data/Rakefile +31 -0
  4. data/app/assets/javascripts/erp_base_erp_svcs/application.js +9 -0
  5. data/app/assets/stylesheets/erp_base_erp_svcs/application.css +7 -0
  6. data/app/controllers/erp_base_erp_svcs/application_controller.rb +4 -0
  7. data/app/helpers/erp_base_erp_svcs/application_helper.rb +4 -0
  8. data/app/models/category.rb +11 -0
  9. data/app/models/category_classification.rb +4 -0
  10. data/app/models/compass_ae_instance.rb +11 -0
  11. data/app/models/contact.rb +42 -0
  12. data/app/models/contact_purpose.rb +6 -0
  13. data/app/models/contact_type.rb +3 -0
  14. data/app/models/currency.rb +16 -0
  15. data/app/models/descriptive_asset.rb +4 -0
  16. data/app/models/email_address.rb +15 -0
  17. data/app/models/geo_country.rb +8 -0
  18. data/app/models/geo_zone.rb +8 -0
  19. data/app/models/individual.rb +76 -0
  20. data/app/models/iso_country_code.rb +10 -0
  21. data/app/models/money.rb +19 -0
  22. data/app/models/note.rb +14 -0
  23. data/app/models/note_type.rb +7 -0
  24. data/app/models/organization.rb +32 -0
  25. data/app/models/party.rb +191 -0
  26. data/app/models/party_relationship.rb +9 -0
  27. data/app/models/party_role.rb +8 -0
  28. data/app/models/phone_number.rb +16 -0
  29. data/app/models/postal_address.rb +19 -0
  30. data/app/models/relationship_type.rb +7 -0
  31. data/app/models/role_type.rb +7 -0
  32. data/app/models/valid_note_type.rb +4 -0
  33. data/app/models/view_type.rb +3 -0
  34. data/app/views/layouts/erp_base_erp_svcs/application.html.erb +14 -0
  35. data/config/initializers/erp_base_erp_svcs.rb +4 -0
  36. data/config/routes.rb +2 -0
  37. data/db/data_migrations/20110525001935_add_usd_currency.rb +11 -0
  38. data/db/data_migrations/20110609150135_add_iso_codes.rb +18 -0
  39. data/db/data_migrations/20110913145838_setup_compass_ae_instance.rb +11 -0
  40. data/db/data_sets/geo_countries.yml +2952 -0
  41. data/db/data_sets/geo_zones.yml +1233 -0
  42. data/db/migrate/20080805000020_base_erp_services.rb +461 -0
  43. data/db/migrate/20110913145329_create_compass_ae_instance.rb +15 -0
  44. data/db/migrate/upgrade/20110907171257_add_notes.rb +63 -0
  45. data/lib/erp_base_erp_svcs/ar_fixtures.rb +103 -0
  46. data/lib/erp_base_erp_svcs/command.rb +37 -0
  47. data/lib/erp_base_erp_svcs/config.rb +27 -0
  48. data/lib/erp_base_erp_svcs/engine.rb +27 -0
  49. data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_category.rb +50 -0
  50. data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_erp_type.rb +148 -0
  51. data/lib/erp_base_erp_svcs/extensions/active_record/acts_as_note_type.rb +47 -0
  52. data/lib/erp_base_erp_svcs/extensions/active_record/data_migrator.rb +46 -0
  53. data/lib/erp_base_erp_svcs/extensions/active_record/has_contact.rb +56 -0
  54. data/lib/erp_base_erp_svcs/extensions/active_record/has_notes.rb +32 -0
  55. data/lib/erp_base_erp_svcs/extensions/active_record/is_describable.rb +44 -0
  56. data/lib/erp_base_erp_svcs/extensions/active_record/migrator.rb +76 -0
  57. data/lib/erp_base_erp_svcs/extensions/active_record/sti_instantiation.rb +37 -0
  58. data/lib/erp_base_erp_svcs/extensions/core/array.rb +20 -0
  59. data/lib/erp_base_erp_svcs/extensions/core/hash.rb +19 -0
  60. data/lib/erp_base_erp_svcs/extensions/core/numbers.rb +27 -0
  61. data/lib/erp_base_erp_svcs/extensions/core/object.rb +6 -0
  62. data/lib/erp_base_erp_svcs/extensions/railties/engine.rb +85 -0
  63. data/lib/erp_base_erp_svcs/extensions.rb +19 -0
  64. data/lib/erp_base_erp_svcs/non_escape_json_string.rb +5 -0
  65. data/lib/erp_base_erp_svcs/rails_template.rb +93 -0
  66. data/lib/erp_base_erp_svcs/version.rb +3 -0
  67. data/lib/erp_base_erp_svcs.rb +17 -0
  68. data/lib/tasks/compass_backup.rake +87 -0
  69. data/lib/tasks/erp_base_erp_svcs_tasks.rake +59 -0
  70. data/lib/tasks/release_notes/NOTES +21 -0
  71. data/spec/dummy/Rakefile +7 -0
  72. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  73. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  74. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  75. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  76. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  77. data/spec/dummy/config/application.rb +42 -0
  78. data/spec/dummy/config/boot.rb +10 -0
  79. data/spec/dummy/config/database.yml +8 -0
  80. data/spec/dummy/config/environment.rb +5 -0
  81. data/spec/dummy/config/environments/spec.rb +27 -0
  82. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  83. data/spec/dummy/config/initializers/inflections.rb +10 -0
  84. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  85. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  86. data/spec/dummy/config/initializers/session_store.rb +8 -0
  87. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  88. data/spec/dummy/config/locales/en.yml +5 -0
  89. data/spec/dummy/config/routes.rb +4 -0
  90. data/spec/dummy/config.ru +4 -0
  91. data/spec/dummy/db/spec.sqlite3 +0 -0
  92. data/spec/dummy/log/spec.log +4820 -0
  93. data/spec/dummy/public/404.html +26 -0
  94. data/spec/dummy/public/422.html +26 -0
  95. data/spec/dummy/public/500.html +26 -0
  96. data/spec/dummy/public/favicon.ico +0 -0
  97. data/spec/dummy/script/rails +6 -0
  98. data/spec/factories/business_party.rb +21 -0
  99. data/spec/factories/contact_purpose.rb +8 -0
  100. data/spec/factories/party.rb +16 -0
  101. data/spec/factories/party_relationship.rb +10 -0
  102. data/spec/factories/party_role.rb +7 -0
  103. data/spec/factories/phone_number.rb +7 -0
  104. data/spec/factories/relationship_type.rb +8 -0
  105. data/spec/factories/role_type.rb +8 -0
  106. data/spec/models/category_classification_spec.rb +11 -0
  107. data/spec/models/category_spec.rb +18 -0
  108. data/spec/models/contact_purpose_spec.rb +12 -0
  109. data/spec/models/contact_spec.rb +12 -0
  110. data/spec/models/contact_type_spec.rb +12 -0
  111. data/spec/models/currency_spec.rb +12 -0
  112. data/spec/models/descriptive_asset_spec.rb +12 -0
  113. data/spec/models/email_address_spec.rb +12 -0
  114. data/spec/models/geo_country_spec.rb +13 -0
  115. data/spec/models/geo_zone_spec.rb +12 -0
  116. data/spec/models/individual_spec.rb +40 -0
  117. data/spec/models/money_spec.rb +12 -0
  118. data/spec/models/note_spec.rb +26 -0
  119. data/spec/models/note_type_spec.rb +12 -0
  120. data/spec/models/organization_spec.rb +33 -0
  121. data/spec/models/party_relationship_spec.rb +12 -0
  122. data/spec/models/party_role_spec.rb +12 -0
  123. data/spec/models/party_spec.rb +98 -0
  124. data/spec/models/phone_number_spec.rb +12 -0
  125. data/spec/models/postal_address_spec.rb +12 -0
  126. data/spec/models/relationship_type_spec.rb +11 -0
  127. data/spec/models/role_type_spec.rb +12 -0
  128. data/spec/models/view_type_spec.rb +12 -0
  129. data/spec/spec_helper.rb +57 -0
  130. 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,4 @@
1
+ module ErpBaseErpSvcs
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ErpBaseErpSvcs
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -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,4 @@
1
+ class CategoryClassification < ActiveRecord::Base
2
+ belongs_to :classification, :polymorphic => true
3
+ belongs_to :category
4
+ 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,6 @@
1
+ class ContactPurpose < ActiveRecord::Base
2
+ acts_as_nested_set
3
+ acts_as_erp_type
4
+
5
+ has_and_belongs_to_many :contacts
6
+ end
@@ -0,0 +1,3 @@
1
+ class ContactType < ActiveRecord::Base
2
+ acts_as_nested_set
3
+ end
@@ -0,0 +1,16 @@
1
+ class Currency < ActiveRecord::Base
2
+ has_many :money
3
+
4
+ def symbol
5
+ major_unit_symbol
6
+ end
7
+
8
+ def self.usd
9
+ # Pull the usd currency from GeoCountry
10
+ find_by_internal_identifier("USD")
11
+ end
12
+
13
+ def self.blank
14
+ new
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ class DescriptiveAsset < ActiveRecord::Base
2
+ belongs_to :view_type
3
+ belongs_to :described_record, :polymorphic => true
4
+ 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,8 @@
1
+ class GeoCountry < ActiveRecord::Base
2
+ has_many :postal_addresses
3
+ has_many :geo_zones
4
+
5
+ validates_presence_of :name
6
+ validates_presence_of :iso_code_2
7
+ validates_presence_of :iso_code_3
8
+ end
@@ -0,0 +1,8 @@
1
+ class GeoZone < ActiveRecord::Base
2
+ belongs_to :geo_country
3
+ has_many :postal_addresses
4
+
5
+ validates_presence_of :geo_country_id
6
+ validates_presence_of :zone_code
7
+ validates_presence_of :zone_name
8
+ 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
@@ -0,0 +1,10 @@
1
+ class IsoCountryCode < GeoCountry
2
+
3
+ has_many :currencies, :through => :locales
4
+ # TODO validate identifier is iso alphabetic two digit code
5
+
6
+ def short_name
7
+ name
8
+ end
9
+
10
+ end
@@ -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
@@ -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,7 @@
1
+ class NoteType < ActiveRecord::Base
2
+ acts_as_nested_set
3
+ acts_as_erp_type
4
+
5
+ belongs_to :note_type_record, :polymorphic => true
6
+ has_many :notes
7
+ 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
@@ -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,8 @@
1
+ class PartyRole < ActiveRecord::Base
2
+ belongs_to :party, :class_name => "Party", :foreign_key => "party_id"
3
+ belongs_to :role_type, :class_name => "RoleType", :foreign_key => "role_type_id"
4
+
5
+ def to_label
6
+ self.role_type.description
7
+ end
8
+ 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,7 @@
1
+ class RoleType < ActiveRecord::Base
2
+ acts_as_nested_set
3
+ acts_as_erp_type
4
+
5
+ has_many :party_roles
6
+ has_many :parties, :through => :party_roles
7
+ end
@@ -0,0 +1,4 @@
1
+ class ValidNoteType < ActiveRecord::Base
2
+ belongs_to :note_type
3
+ belongs_to :valid_note_record, :polymorphic => true
4
+ end
@@ -0,0 +1,3 @@
1
+ class ViewType < ActiveRecord::Base
2
+ has_many :descriptive_assets
3
+ 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>
@@ -0,0 +1,4 @@
1
+ Rails.application.config.erp_base_erp_svcs.configure do |config|
2
+ config.compass_ae_extensions_directory = 'compass_ae_extensions'
3
+ end
4
+ Rails.application.config.erp_base_erp_svcs.configure!