kuality-coeus 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +16 -18
  3. data/chromedriver.log +46 -0
  4. data/features/grants_gov/grants_gov_forms/code_and_form_mapping.feature +26 -0
  5. data/features/grants_gov/grants_gov_forms/forms_validation.feature +1 -0
  6. data/features/grants_gov/grants_gov_forms/s2s_questionnaire.feature +19 -0
  7. data/features/grants_gov/s2s_submission.feature +30 -0
  8. data/features/grants_gov/s2s_validation.feature +36 -0
  9. data/features/proposal_development/create_budget_versions.feature +31 -0
  10. data/features/proposal_development/create_proposal.feature +25 -0
  11. data/features/proposal_development/key_personnel_validations.feature +41 -0
  12. data/features/proposal_development/proposal_actions_validations.feature +46 -0
  13. data/features/proposal_development/proposal_permissions.feature +73 -0
  14. data/features/proposal_development/proposal_workflow.feature +105 -0
  15. data/features/proposal_development/special_review_validations.feature +12 -0
  16. data/features/step_definitions/action_list.rb +12 -0
  17. data/features/step_definitions/awards/create_award.rb +3 -0
  18. data/features/step_definitions/grants_gov/forms.rb +34 -0
  19. data/features/step_definitions/grants_gov/s2s_submission.rb +51 -0
  20. data/features/step_definitions/institutional_proposals/create_institutional_proposal.rb +3 -0
  21. data/features/step_definitions/proposal_development/budget_versions.rb +102 -0
  22. data/features/step_definitions/proposal_development/create_proposal.rb +157 -0
  23. data/features/step_definitions/proposal_development/edit_proposal.rb +79 -0
  24. data/features/step_definitions/proposal_development/institute_rates.rb +21 -0
  25. data/features/step_definitions/proposal_development/key_personnel_validations.rb +74 -0
  26. data/features/step_definitions/proposal_development/proposal_actions_validations.rb +73 -0
  27. data/features/step_definitions/proposal_development/proposal_permissions.rb +141 -0
  28. data/features/step_definitions/proposal_development/proposal_workflow.rb +81 -0
  29. data/features/step_definitions/proposal_development/s2s_validation.rb +30 -0
  30. data/features/step_definitions/proposal_development/special_review_validations.rb +7 -0
  31. data/features/step_definitions/test.rb +3 -0
  32. data/features/step_definitions/users.rb +65 -0
  33. data/features/support/env.rb +35 -0
  34. data/features/test.feature +13 -0
  35. data/kuality-coeus.gemspec +1 -1
  36. data/lib/chromedriver.log +4483 -0
  37. data/lib/kuality-coeus.rb +5 -2
  38. data/lib/kuality-coeus/core_extensions.rb +10 -0
  39. data/lib/kuality-coeus/data_objects/award/award.rb +126 -0
  40. data/lib/kuality-coeus/data_objects/award/award_transaction.rb +57 -0
  41. data/lib/kuality-coeus/data_objects/budget/budget_periods.rb +114 -0
  42. data/lib/kuality-coeus/data_objects/budget/budget_versions.rb +221 -0
  43. data/lib/kuality-coeus/data_objects/budget/subaward_budget.rb +65 -0
  44. data/lib/kuality-coeus/data_objects/committee_document/committee_document.rb +65 -0
  45. data/lib/kuality-coeus/data_objects/committee_document/committee_members.rb +30 -0
  46. data/lib/kuality-coeus/data_objects/committee_document/committee_schedule.rb +27 -0
  47. data/lib/kuality-coeus/data_objects/committee_document/member_roles.rb +28 -0
  48. data/lib/kuality-coeus/data_objects/conflict_of_interest/financial_entity.rb +48 -0
  49. data/lib/kuality-coeus/data_objects/grants_gov/phs_fellowship_questionnaire.rb +90 -0
  50. data/lib/kuality-coeus/data_objects/grants_gov/phs_training_budget_questionnaire.rb +5 -0
  51. data/lib/kuality-coeus/data_objects/institutional_proposal/institutional_proposal.rb +20 -0
  52. data/lib/kuality-coeus/data_objects/institutional_proposal/intellectual_property_review.rb +62 -0
  53. data/lib/kuality-coeus/data_objects/navigation.rb +64 -0
  54. data/lib/kuality-coeus/data_objects/proposal_development/compliance_questions.rb +47 -0
  55. data/lib/kuality-coeus/data_objects/proposal_development/custom_data.rb +41 -0
  56. data/lib/kuality-coeus/data_objects/proposal_development/degrees.rb +40 -0
  57. data/lib/kuality-coeus/data_objects/proposal_development/key_personnel.rb +299 -0
  58. data/lib/kuality-coeus/data_objects/proposal_development/kuali_university_questions.rb +58 -0
  59. data/lib/kuality-coeus/data_objects/proposal_development/permissions.rb +107 -0
  60. data/lib/kuality-coeus/data_objects/proposal_development/personnel_attachments.rb +46 -0
  61. data/lib/kuality-coeus/data_objects/proposal_development/proposal_attachments.rb +41 -0
  62. data/lib/kuality-coeus/data_objects/proposal_development/proposal_development.rb +301 -0
  63. data/lib/kuality-coeus/data_objects/proposal_development/proposal_questions.rb +52 -0
  64. data/lib/kuality-coeus/data_objects/proposal_development/s2s_questionnaire.rb +129 -0
  65. data/lib/kuality-coeus/data_objects/proposal_development/special_review.rb +79 -0
  66. data/lib/kuality-coeus/data_objects/rates/institute_rate.rb +209 -0
  67. data/lib/kuality-coeus/data_objects/user.rb +303 -33
  68. data/lib/kuality-coeus/gem_extensions.rb +26 -0
  69. data/lib/kuality-coeus/page_objects/000_base_page.rb +196 -14
  70. data/lib/kuality-coeus/page_objects/action_list.rb +32 -0
  71. data/lib/kuality-coeus/page_objects/award/award.rb +25 -0
  72. data/lib/kuality-coeus/page_objects/award/award_actions.rb +7 -0
  73. data/lib/kuality-coeus/page_objects/award/award_budget_versions.rb +9 -0
  74. data/lib/kuality-coeus/page_objects/award/commitments.rb +27 -0
  75. data/lib/kuality-coeus/page_objects/award/contacts.rb +19 -0
  76. data/lib/kuality-coeus/page_objects/award/custom_data.rb +6 -0
  77. data/lib/kuality-coeus/page_objects/award/payment_reports_terms.rb +26 -0
  78. data/lib/kuality-coeus/page_objects/award/special_review.rb +7 -0
  79. data/lib/kuality-coeus/page_objects/award/time_and_money.rb +36 -0
  80. data/lib/kuality-coeus/page_objects/budget/budget_actions.rb +31 -0
  81. data/lib/kuality-coeus/page_objects/budget/budget_versions.rb +13 -0
  82. data/lib/kuality-coeus/page_objects/budget/modular_budget.rb +16 -0
  83. data/lib/kuality-coeus/page_objects/budget/non-personnel.rb +11 -0
  84. data/lib/kuality-coeus/page_objects/budget/parameters.rb +65 -0
  85. data/lib/kuality-coeus/page_objects/budget/personnel.rb +56 -0
  86. data/lib/kuality-coeus/page_objects/budget/rates.rb +7 -0
  87. data/lib/kuality-coeus/page_objects/budget/summary.rb +5 -0
  88. data/lib/kuality-coeus/page_objects/budget_document.rb +19 -0
  89. data/lib/kuality-coeus/page_objects/central_admin.rb +4 -2
  90. data/lib/kuality-coeus/page_objects/committee/committee.rb +10 -10
  91. data/lib/kuality-coeus/page_objects/committee/members.rb +4 -4
  92. data/lib/kuality-coeus/page_objects/committee_document.rb +1 -6
  93. data/lib/kuality-coeus/page_objects/confirmation.rb +16 -0
  94. data/lib/kuality-coeus/page_objects/disclosure/disclosure.rb +56 -0
  95. data/lib/kuality-coeus/page_objects/disclosure/disclosure_actions.rb +9 -0
  96. data/lib/kuality-coeus/page_objects/document_header.rb +5 -0
  97. data/lib/kuality-coeus/page_objects/financial_entities.rb +1 -4
  98. data/lib/kuality-coeus/page_objects/financial_entities/my_financial_entities.rb +6 -0
  99. data/lib/kuality-coeus/page_objects/financial_entities/new_financial_entity.rb +11 -0
  100. data/lib/kuality-coeus/page_objects/financial_entities/reporter.rb +5 -3
  101. data/lib/kuality-coeus/page_objects/identity/person.rb +57 -0
  102. data/lib/kuality-coeus/page_objects/institute_rates_maintenance.rb +18 -0
  103. data/lib/kuality-coeus/page_objects/institutional_proposal.rb +18 -0
  104. data/lib/kuality-coeus/page_objects/institutional_proposal/contacts.rb +32 -0
  105. data/lib/kuality-coeus/page_objects/institutional_proposal/custom_data.rb +6 -0
  106. data/lib/kuality-coeus/page_objects/institutional_proposal/distribution.rb +20 -0
  107. data/lib/kuality-coeus/page_objects/institutional_proposal/institutional_proposal.rb +27 -0
  108. data/lib/kuality-coeus/page_objects/institutional_proposal/institutional_proposal_actions.rb +7 -0
  109. data/lib/kuality-coeus/page_objects/institutional_proposal/intellectual_property_review.rb +20 -0
  110. data/lib/kuality-coeus/page_objects/institutional_proposal/special_review.rb +6 -0
  111. data/lib/kuality-coeus/page_objects/kc_awards.rb +48 -0
  112. data/lib/kuality-coeus/page_objects/kc_protocol.rb +15 -0
  113. data/lib/kuality-coeus/page_objects/login.rb +4 -5
  114. data/lib/kuality-coeus/page_objects/lookup_pages/000_lookups.rb +10 -0
  115. data/lib/kuality-coeus/page_objects/lookup_pages/action_list_filter.rb +6 -0
  116. data/lib/kuality-coeus/page_objects/lookup_pages/address_book_lookup.rb +4 -0
  117. data/lib/kuality-coeus/page_objects/lookup_pages/development_proposal_lookup.rb +3 -0
  118. data/lib/kuality-coeus/page_objects/lookup_pages/document_search.rb +10 -0
  119. data/lib/kuality-coeus/page_objects/lookup_pages/group_lookup.rb +3 -0
  120. data/lib/kuality-coeus/page_objects/lookup_pages/institute_rates_lookup.rb +12 -0
  121. data/lib/kuality-coeus/page_objects/lookup_pages/opportunity_lookup.rb +6 -0
  122. data/lib/kuality-coeus/page_objects/lookup_pages/organization_lookup.rb +5 -0
  123. data/lib/kuality-coeus/page_objects/lookup_pages/person_extended_attributes.rb +5 -0
  124. data/lib/kuality-coeus/page_objects/lookup_pages/person_lookup.rb +10 -0
  125. data/lib/kuality-coeus/page_objects/lookup_pages/role_lookup.rb +6 -0
  126. data/lib/kuality-coeus/page_objects/lookup_pages/sponsor_lookup.rb +9 -0
  127. data/lib/kuality-coeus/page_objects/lookup_pages/unit_admin_lookup.rb +3 -0
  128. data/lib/kuality-coeus/page_objects/lookup_pages/unit_lookup.rb +3 -0
  129. data/lib/kuality-coeus/page_objects/maintenance.rb +7 -0
  130. data/lib/kuality-coeus/page_objects/notification_editor.rb +6 -0
  131. data/lib/kuality-coeus/page_objects/proposal_development.rb +7 -2
  132. data/lib/kuality-coeus/page_objects/proposal_development/abstracts_and_attachments.rb +54 -0
  133. data/lib/kuality-coeus/page_objects/proposal_development/key_personnel.rb +126 -0
  134. data/lib/kuality-coeus/page_objects/proposal_development/pd_custom_data.rb +6 -0
  135. data/lib/kuality-coeus/page_objects/proposal_development/permissions.rb +44 -0
  136. data/lib/kuality-coeus/page_objects/proposal_development/phs_fellowship_questionnaire.rb +44 -0
  137. data/lib/kuality-coeus/page_objects/proposal_development/phs_training_budget_questionnaire.rb +50 -0
  138. data/lib/kuality-coeus/page_objects/proposal_development/proposal.rb +47 -8
  139. data/lib/kuality-coeus/page_objects/proposal_development/proposal_actions.rb +62 -0
  140. data/lib/kuality-coeus/page_objects/proposal_development/proposal_summary.rb +9 -0
  141. data/lib/kuality-coeus/page_objects/proposal_development/questions.rb +111 -0
  142. data/lib/kuality-coeus/page_objects/proposal_development/s2s.rb +35 -0
  143. data/lib/kuality-coeus/page_objects/proposal_development/special_review.rb +6 -0
  144. data/lib/kuality-coeus/page_objects/protocol/custom_data.rb +6 -0
  145. data/lib/kuality-coeus/page_objects/protocol/permissions.rb +5 -0
  146. data/lib/kuality-coeus/page_objects/protocol/personnel.rb +5 -0
  147. data/lib/kuality-coeus/page_objects/protocol/protocol.rb +11 -0
  148. data/lib/kuality-coeus/page_objects/protocol/questionnaire.rb +5 -0
  149. data/lib/kuality-coeus/page_objects/protocol/special_review.rb +6 -0
  150. data/lib/kuality-coeus/page_objects/rejection_confirmation.rb +5 -0
  151. data/lib/kuality-coeus/page_objects/researcher.rb +4 -2
  152. data/lib/kuality-coeus/page_objects/shared/unit_administrator.rb +13 -0
  153. data/lib/kuality-coeus/page_objects/system/person_extended_attributes.rb +18 -0
  154. data/lib/kuality-coeus/page_objects/system_admin.rb +7 -0
  155. data/lib/kuality-coeus/page_objects/unit.rb +2 -4
  156. data/lib/kuality-coeus/utilities.rb +39 -0
  157. data/libpeerconnection.log +0 -0
  158. metadata +140 -5
  159. data/lib/kuality-coeus/data_objects/committee_document.rb +0 -65
  160. data/lib/kuality-coeus/data_objects/proposal_development.rb +0 -53
  161. data/lib/kuality-coeus/navigation.rb +0 -3
@@ -0,0 +1,64 @@
1
+ module Navigation
2
+
3
+ include Utilities
4
+
5
+ def open_document doc_header
6
+ doc_search unless on_document?(doc_header)
7
+ end
8
+
9
+ def on_document?(doc_header)
10
+ begin
11
+ on(DocumentHeader).document_id==@document_id && @browser.frm.div(id: 'headerarea').h1.text==doc_header
12
+ rescue Watir::Exception::UnknownObjectException, Selenium::WebDriver::Error::StaleElementReferenceError
13
+ false
14
+ end
15
+ end
16
+
17
+ def doc_search
18
+ visit DocumentSearch do |search|
19
+ search.close_parents
20
+ search.document_id.set @document_id
21
+ search.search
22
+ search.open_doc @document_id
23
+ end
24
+ end
25
+
26
+ def on_page? element
27
+ begin
28
+ element.exist?
29
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
30
+ false
31
+ end
32
+ end
33
+
34
+ # Use in the #create method of your data objects for filling out
35
+ # fields. This method eliminates the need to write repetitive
36
+ # lines of code, with one line for every field needing to be
37
+ # filled in.
38
+ #
39
+ # Requirement: The field method name and the class instance variable
40
+ # must be the same!
41
+ #
42
+ def fill_out(page, *fields)
43
+ methods={
44
+ 'Watir::TextField' => lambda{|p, f| p.send(f).fit(get f)},
45
+ 'Watir::Select' => lambda{|p, f| p.send(f).pick!(get f)},
46
+ 'Watir::Radio' => lambda{|p, f| p.send(f, get(f)) unless get(f)==nil },
47
+ 'Watir::CheckBox' => lambda{|p, f| p.send(f).fit(get f) }
48
+ }
49
+ fields.shuffle.each do |field|
50
+ # TODO: Someday see if there's a way to fix things so this rescue isn't necessary...
51
+ # It's here because the radio button "element" definitions are *actions* that
52
+ # require a parameter, so just sending the method to the page
53
+ # is not going to work.
54
+ begin
55
+ key = page.send(field).class.to_s
56
+ rescue NoMethodError
57
+ key = 'Watir::Radio'
58
+ end
59
+ methods[key].call(page, field)
60
+ end
61
+ end
62
+ alias_method :fill_in, :fill_out
63
+
64
+ end
@@ -0,0 +1,47 @@
1
+ class ComplianceQuestionsObject
2
+
3
+ include Foundry
4
+ include DataFactory
5
+ include DateFactory
6
+ include Navigation
7
+
8
+ attr_accessor :document_id, :agree_to_ethical_conduct, :conduct_review_date
9
+
10
+ def initialize(browser, opts={})
11
+ @browser = browser
12
+ # PLEASE NOTE:
13
+ # This is an unusual data object class in that
14
+ # it breaks the typical model for radio button
15
+ # methods and their associated class instance variables
16
+ #
17
+ # In general, it's not workable to set up radio button elements
18
+ # to use "Y" and "N" as the instance variables associated with them.
19
+ defaults = {
20
+ agree_to_ethical_conduct: 'Y',
21
+ conduct_review_date: right_now[:date_w_slashes],
22
+ }
23
+ set_options(defaults.merge(opts))
24
+ requires :document_id
25
+ end
26
+
27
+ def create
28
+ navigate
29
+ on Questions do |cq|
30
+ cq.show_compliance_questions
31
+ fill_out cq, :agree_to_ethical_conduct, :conduct_review_date
32
+ cq.save
33
+ end
34
+ end
35
+
36
+ # =======
37
+ private
38
+ # =======
39
+
40
+ # Nav Aids...
41
+
42
+ def navigate
43
+ open_document @doc_type
44
+ on(Proposal).questions unless on_page?(on(Questions).questions_header)
45
+ end
46
+
47
+ end
@@ -0,0 +1,41 @@
1
+ class CustomDataObject
2
+
3
+ include Foundry
4
+ include DataFactory
5
+ include Navigation
6
+ include StringFactory
7
+
8
+ attr_accessor :document_id, :graduate_student_count, :billing_element, :doc_type
9
+
10
+ def initialize(browser, opts={})
11
+ @browser = browser
12
+
13
+ defaults = {
14
+ graduate_student_count: rand(50).to_s,
15
+ billing_element: random_alphanums(40)
16
+ }
17
+ set_options(defaults.merge(opts))
18
+ requires :document_id, :doc_type
19
+ end
20
+
21
+ def create
22
+ navigate
23
+ on PDCustomData do |create|
24
+ create.expand_all
25
+ fill_out create, :graduate_student_count, :billing_element
26
+ create.save
27
+ end
28
+ end
29
+
30
+ # =======
31
+ private
32
+ # =======
33
+
34
+ # Nav Aids...
35
+
36
+ def navigate
37
+ open_document @doc_type
38
+ on(Proposal).custom_data unless on_page?(on(PDCustomData).asdf_tab)
39
+ end
40
+
41
+ end
@@ -0,0 +1,40 @@
1
+ class DegreeObject
2
+
3
+ include Foundry
4
+ include DataFactory
5
+ include StringFactory
6
+
7
+ attr_accessor :type, :description, :graduation_year, :school,
8
+ :document_id, :person
9
+
10
+ def initialize(browser, opts={})
11
+ @browser = browser
12
+
13
+ defaults = {
14
+ type: '::random::',
15
+ description: random_alphanums_plus,
16
+ graduation_year: Time.random(year_range: 35).strftime('%Y')
17
+ }
18
+ set_options(defaults.merge(opts))
19
+ requires :document_id, :person
20
+ end
21
+
22
+ def create
23
+ # This method assumes navigation was performed by the parent object
24
+ on KeyPersonnel do |degrees|
25
+ degrees.expand_all
26
+ degrees.degree_type(@person).pick! @type
27
+ degrees.degree_description(@person).fit @description
28
+ degrees.graduation_year(@person).fit @graduation_year
29
+ degrees.school(@person).fit @school
30
+ degrees.add_degree(@person)
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ class DegreesCollection < Array
37
+
38
+
39
+
40
+ end
@@ -0,0 +1,299 @@
1
+ class KeyPersonObject
2
+
3
+ include Foundry
4
+ include DataFactory
5
+ include StringFactory
6
+ include Navigation
7
+
8
+ attr_accessor :first_name, :last_name, :role, :document_id, :key_person_role,
9
+ :full_name, :user_name, :home_unit, :units, :responsibility,
10
+ :financial, :recognition, :certified, :certify_info_true,
11
+ :potential_for_conflicts, :submitted_financial_disclosures,
12
+ :lobbying_activities, :excluded_from_transactions, :familiar_with_pla,
13
+ :space, :other_key_persons, :era_commons_name, :degrees
14
+
15
+ # Note that you must pass in both first and last names (or neither).
16
+ def initialize(browser, opts={})
17
+ @browser = browser
18
+
19
+ defaults = {
20
+ role: 'Principal Investigator',
21
+ units: [],
22
+ degrees: DegreesCollection.new,
23
+ certified: true, # Set this to false if you do not want any Proposal Person Certification Questions answered
24
+ certify_info_true: 'Y',
25
+ potential_for_conflict: 'Y',
26
+ submitted_financial_disclosures: 'Y',
27
+ lobbying_activities: 'Y',
28
+ excluded_from_transactions: 'Y',
29
+ familiar_with_pla: 'Y'
30
+ }
31
+
32
+ set_options(defaults.merge(opts))
33
+ requires :document_id
34
+ @full_name="#{@first_name} #{@last_name}"
35
+ end
36
+
37
+ def create
38
+ navigate
39
+ on(KeyPersonnel).employee_search
40
+ if @last_name==nil
41
+ on PersonLookup do |look|
42
+ look.search
43
+ look.return_random
44
+ end
45
+ on KeyPersonnel do |person|
46
+ @full_name=person.person_name
47
+ @first_name=@full_name[/^\w+/]
48
+ @last_name=@full_name[/\w+$/]
49
+ end
50
+ else
51
+ on PersonLookup do |look|
52
+ look.last_name.set @last_name
53
+ look.search
54
+ look.return_value @full_name
55
+ end
56
+ end
57
+ on KeyPersonnel do |person|
58
+ # This conditional exists to deal with the fact that
59
+ # a Principal Investigator can also be called a "PI/Contact",
60
+ # in cases where it's an NIH proposal.
61
+ if person.proposal_role.include? @role
62
+ person.proposal_role.select @role
63
+ else
64
+ person.proposal_role.select_value role_value[@role]
65
+ @role = person.proposal_role.selected_options[0].text
66
+ end
67
+ person.key_person_role.fit @key_person_role
68
+ person.add_person
69
+ break unless person.add_person_errors.empty? # ..we've thrown an error, so no need to continue this method...
70
+ person.expand_all
71
+ @user_name=person.user_name @full_name
72
+ @home_unit=person.home_unit @full_name
73
+ if @units.empty? # No units in @units, so we're not setting units
74
+ # ...so, get the units from the UI:
75
+ @units=person.units @full_name if @key_person_role==nil
76
+
77
+ else # We have Units to add and update...
78
+ # Temporarily store any existing units...
79
+ person.add_unit_details(@full_name) unless @key_person_role==nil
80
+
81
+ units=person.units @full_name
82
+ # Note that this assumes we're adding
83
+ # Unit(s) that aren't already present
84
+ # in the list, so be careful!
85
+ @units.each do |unit|
86
+ person.unit_number(@full_name).set unit[:number]
87
+ person.add_unit @full_name
88
+ end
89
+ break if person.unit_details_errors_div(@full_name).present?
90
+ # Now add the previously existing units to
91
+ # @units
92
+ units.each { |unit| @units << unit }
93
+ end
94
+
95
+ # Now we groom the Unit Hashes, to include
96
+ # the Combined Credit Split numbers...
97
+ #
98
+ # NOTE: Commenting out this code until we
99
+ # determine either we need it or else we come up with
100
+ # a better way to do this...
101
+ #@units.each do |unit|
102
+ # [:space, :responsibility, :financial, :recognition].each do |item|
103
+ # unit[item] ||= unit.store(item, rand_num)
104
+ # # Then we update the UI with the values...
105
+ # person.send("unit_#{item.to_s}".to_sym, @full_name, unit[:number]).set unit[item]
106
+ # end
107
+ #end
108
+
109
+ # If it's a key person without units then they won't have credit splits,
110
+ # otherwise, the person will, so fill them out...
111
+ if @key_person_role==nil || !@units.empty?
112
+ person.space(@full_name).fit @space
113
+ person.responsibility(@full_name).fit @responsibility
114
+ person.financial(@full_name).fit @financial
115
+ person.recognition(@full_name).fit @recognition
116
+ end
117
+
118
+ # Proposal Person Certification
119
+ if @certified
120
+ person.include_certification_questions(@full_name) unless @key_person_role==nil
121
+ cert_questions.each { |q| person.send(q, full_name, get(q)) }
122
+ else
123
+ cert_questions.each { |q| set(q, nil) }
124
+ end
125
+
126
+ # Add gathering/setting of more attributes here as needed
127
+ person.era_commons_name(@full_name).fit @era_commons_name
128
+ person.save
129
+ end
130
+ end
131
+
132
+ # IMPORTANT NOTE:
133
+ # Add edit options to this method as needed.
134
+ #
135
+ # HOWEVER:
136
+ # Do NOT add updating of Unit Credit Splits here.
137
+ # Those require special handling and
138
+ # thus have their own method: #update_unit_credit_splits
139
+ def edit opts={}
140
+ navigate
141
+ on KeyPersonnel do |update|
142
+ update.expand_all
143
+ # Note: This is a dangerous short cut, as it may not
144
+ # apply to every field that could be edited with this
145
+ # method...
146
+ opts.each do |field, value|
147
+ update.send(field, @full_name).fit value
148
+ end
149
+ update.save
150
+ end
151
+ update_options(opts)
152
+ end
153
+
154
+ # This method requires a parameter that is an Array
155
+ # of Hashes. Though it defaults to the person object's
156
+ # @units variable.
157
+ #
158
+ # Example:
159
+ # [{:number=>"UNIT NUMBER", :responsibility=>"33.33"}]
160
+ def update_unit_credit_splits(units=@units)
161
+ splits=[:responsibility, :financial, :recognition, :space]
162
+ units.each do |unit|
163
+ on KeyPersonnel do |update|
164
+ update.unit_space(@full_name, unit[:number]).fit unit[:space]
165
+ update.unit_responsibility(@full_name, unit[:number]).fit unit[:responsibility]
166
+ update.unit_financial(@full_name, unit[:number]).fit unit[:financial]
167
+ update.unit_recognition(@full_name, unit[:number]).fit unit[:recognition]
168
+ update.save
169
+ end
170
+ splits.each do |split|
171
+ unless unit[split]==nil
172
+ @units[@units.find_index{|u| u[:number]==unit[:number]}][split]=unit[split]
173
+ end
174
+ end
175
+
176
+ end
177
+ end
178
+
179
+ def add_degree_info opts={}
180
+ defaults = { document_id: @document_id,
181
+ person: @full_name }
182
+ degree = make DegreeObject, defaults.merge(opts)
183
+ degree.create
184
+ @degrees << degree
185
+ end
186
+
187
+ def delete
188
+ navigate
189
+ on KeyPersonnel do |person|
190
+ person.check_person @full_name
191
+ person.delete_selected
192
+ end
193
+ end
194
+
195
+ def delete_units
196
+ @units.each do |unit|
197
+ on KeyPersonnel do |units|
198
+ units.delete_unit(@full_name, unit[:number])
199
+ end
200
+ end
201
+ @units=[]
202
+ end
203
+
204
+ # =======
205
+ private
206
+ # =======
207
+
208
+ # Nav Aids...
209
+
210
+ def navigate
211
+ open_document @doc_type
212
+ on(Proposal).key_personnel unless on_page?
213
+ end
214
+
215
+ def on_page?
216
+ # Note, the rescue clause should be
217
+ # removed when the Selenium bug with
218
+ # firefox elements gets fixed. This is
219
+ # still broken in selenium-webdriver 2.29
220
+ begin
221
+ on(KeyPersonnel).proposal_role.exist?
222
+ rescue
223
+ false
224
+ end
225
+ end
226
+
227
+ def cert_questions
228
+ [:certify_info_true,
229
+ :potential_for_conflict,
230
+ :submitted_financial_disclosures,
231
+ :lobbying_activities,
232
+ :excluded_from_transactions,
233
+ :familiar_with_pla]
234
+ end
235
+
236
+ def role_value
237
+ {
238
+ 'Principal Investigator' => 'PI',
239
+ 'PI/Contact' => 'PI',
240
+ 'Co-Investigator' => 'COI',
241
+ 'Key Person' => 'KP'
242
+ }
243
+ end
244
+
245
+ end # KeyPersonObject
246
+
247
+ class KeyPersonnelCollection < Array
248
+
249
+ def names
250
+ self.collect { |person| person.full_name }
251
+ end
252
+
253
+ def roles
254
+ self.collect{ |person| person.role }.uniq
255
+ end
256
+
257
+ def unit_names
258
+ units.collect{ |unit| unit[:name] }.uniq
259
+ end
260
+
261
+ def unit_numbers
262
+ units.collect{ |unit| unit[:number] }.uniq
263
+ end
264
+
265
+ def units
266
+ self.collect{ |person| person.units }.flatten
267
+ end
268
+
269
+ def person(full_name)
270
+ self.find { |person| person.full_name==full_name }
271
+ end
272
+
273
+ # returns an array of KeyPersonObjects who have associated
274
+ # units
275
+ def with_units
276
+ self.find_all { |person| person.units.size > 0 }
277
+ end
278
+
279
+ def principal_investigator
280
+ self.find { |person| person.role=='Principal Investigator' || person.role=='PI/Contact' }
281
+ end
282
+
283
+ def co_investigator
284
+ self.find { |person| person.role=='Co-Investigator' }
285
+ end
286
+
287
+ def key_person(role)
288
+ self.find { |person| person.key_person_role==role }
289
+ end
290
+
291
+ # IMPORTANT: This method returns a KeyPersonObject--meaning that if there
292
+ # are multiple key persons in the collection that match this search only
293
+ # the first one will be returned. If you need a collection of multiple persons
294
+ # write the method for that.
295
+ def uncertified_person(role)
296
+ self.find { |person| person.certified==false && person.role==role }
297
+ end
298
+
299
+ end # KeyPersonnelCollection