fe 0.0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +16 -36
  3. data/app/assets/javascripts/fe/admin.js +0 -1
  4. data/app/assets/javascripts/fe/fe.admin.js +40 -16
  5. data/app/assets/javascripts/fe/fe.common.js +48 -14
  6. data/app/assets/javascripts/fe/fe.public.js +1 -414
  7. data/app/assets/javascripts/fe/fe.public.nojquery.js +450 -0
  8. data/app/assets/javascripts/fe/jquery.validate.pack.js +3 -15
  9. data/app/assets/stylesheets/360front.css +0 -0
  10. data/app/assets/stylesheets/fe/fe.screen.css.scss.erb +69 -10
  11. data/app/controllers/fe/admin/elements_controller.rb +64 -48
  12. data/app/controllers/fe/admin/email_templates_controller.rb +2 -2
  13. data/app/controllers/fe/admin/question_pages_controller.rb +1 -1
  14. data/app/controllers/fe/admin/question_sheets_controller.rb +2 -103
  15. data/app/controllers/fe/concerns/admin/question_sheets_controller_concern.rb +112 -0
  16. data/app/controllers/fe/concerns/answer_pages_controller_concern.rb +2 -1
  17. data/app/controllers/fe/concerns/answer_sheets_controller_concern.rb +1 -1
  18. data/app/controllers/fe/concerns/application_controller_concern.rb +13 -0
  19. data/app/controllers/fe/reference_sheets_controller.rb +2 -0
  20. data/app/controllers/fe/references_controller.rb +1 -0
  21. data/app/helpers/fe/application_helper.rb +5 -0
  22. data/app/mailers/fe/notifier.rb +11 -4
  23. data/app/models/answer_sheet.rb +2 -0
  24. data/app/models/fe/application.rb +2 -1
  25. data/app/models/fe/concerns/answer_pages_presenter_concern.rb +10 -1
  26. data/app/models/fe/concerns/answer_sheet_concern.rb +38 -8
  27. data/app/models/fe/concerns/choice_field_concern.rb +17 -10
  28. data/app/models/fe/date_field.rb +1 -1
  29. data/app/models/fe/element.rb +105 -31
  30. data/app/models/fe/page.rb +52 -20
  31. data/app/models/fe/page_element.rb +6 -1
  32. data/app/models/fe/page_link.rb +6 -3
  33. data/app/models/fe/person.rb +11 -8
  34. data/app/models/fe/question.rb +2 -6
  35. data/app/models/fe/question_grid.rb +1 -1
  36. data/app/models/fe/question_grid_with_total.rb +15 -0
  37. data/app/models/fe/question_set.rb +1 -1
  38. data/app/models/fe/question_sheet.rb +15 -13
  39. data/app/models/fe/reference_question.rb +0 -10
  40. data/app/models/fe/reference_sheet.rb +17 -13
  41. data/app/models/staff.rb +2 -0
  42. data/app/validators/email_validator.rb +11 -0
  43. data/app/views/fe/admin/elements/create.js.erb +1 -0
  44. data/app/views/fe/admin/elements/drop.js.erb +1 -0
  45. data/app/views/fe/admin/elements/duplicate.js.erb +1 -0
  46. data/app/views/fe/admin/panels/_advanced_options.html.erb +9 -3
  47. data/app/views/fe/admin/panels/_common_fields.html.erb +19 -5
  48. data/app/views/fe/admin/panels/_page.html.erb +1 -1
  49. data/app/views/fe/admin/panels/_prop_choice_field.html.erb +20 -11
  50. data/app/views/fe/admin/panels/_prop_element.html.erb +2 -9
  51. data/app/views/fe/admin/panels/_prop_page.html.erb +8 -3
  52. data/app/views/fe/admin/panels/_prop_paragraph.html.erb +38 -24
  53. data/app/views/fe/admin/panels/_prop_section.html.erb +8 -2
  54. data/app/views/fe/admin/panels/_prop_sheet.html.erb +4 -1
  55. data/app/views/fe/admin/question_pages/_element.html.erb +11 -1
  56. data/app/views/fe/answer_pages/_answer_page.html.erb +9 -8
  57. data/app/views/fe/answer_pages/_element.html.erb +6 -7
  58. data/app/views/fe/answer_pages/_page_name.html.erb +1 -0
  59. data/app/views/fe/answer_pages/update.js.erb +3 -3
  60. data/app/views/fe/answer_sheets/_answer_sheet.html.erb +3 -3
  61. data/app/views/fe/answer_sheets/_element.html.erb +52 -34
  62. data/app/views/fe/answer_sheets/_incomplete.html.erb +1 -1
  63. data/app/views/fe/answer_sheets/_page_link.html.erb +2 -2
  64. data/app/views/fe/answer_sheets/_pages_list.html.erb +3 -3
  65. data/app/views/fe/answer_sheets/_submit_to.html.erb +1 -0
  66. data/app/views/fe/answer_sheets/edit.html.erb +14 -14
  67. data/app/views/fe/answer_sheets/incomplete.js.erb +3 -0
  68. data/app/views/fe/answer_sheets/index.html.erb +3 -3
  69. data/app/views/fe/answer_sheets/show.html.erb +1 -1
  70. data/app/views/fe/applications/_logout.html.erb +1 -0
  71. data/app/views/fe/applications/show.html.erb +1 -0
  72. data/app/views/fe/questions/fe/_acceptance.html.erb +3 -3
  73. data/app/views/fe/questions/fe/_attachment_field.html.erb +7 -3
  74. data/app/views/fe/questions/fe/_checkbox_field.html.erb +26 -24
  75. data/app/views/fe/questions/fe/_date_field.html.erb +1 -2
  76. data/app/views/fe/questions/fe/_date_field_mmyy.html.erb +2 -2
  77. data/app/views/fe/questions/fe/_drop_down_field.html.erb +3 -2
  78. data/app/views/fe/questions/fe/_paragraph.html.erb +1 -1
  79. data/app/views/fe/questions/fe/_question_grid.html.erb +14 -9
  80. data/app/views/fe/questions/fe/_question_grid_with_total.html.erb +21 -14
  81. data/app/views/fe/questions/fe/_questions.html.erb +2 -2
  82. data/app/views/fe/questions/fe/_radio_button_field.html.erb +12 -11
  83. data/app/views/fe/questions/fe/_rating.html.erb +9 -8
  84. data/app/views/fe/questions/fe/_reference_discipler.html.erb +1 -1
  85. data/app/views/fe/questions/fe/_reference_friend.html.erb +1 -1
  86. data/app/views/fe/questions/fe/_reference_parent.html.erb +1 -1
  87. data/app/views/fe/questions/fe/_reference_peer.html.erb +1 -1
  88. data/app/views/fe/questions/fe/_reference_question.html.erb +22 -15
  89. data/app/views/fe/questions/fe/_reference_roommate.html.erb +1 -1
  90. data/app/views/fe/questions/fe/_reference_spiritual.html.erb +1 -1
  91. data/app/views/fe/questions/fe/_reference_staff.html.erb +1 -1
  92. data/app/views/fe/questions/fe/_section.html.erb +1 -1
  93. data/app/views/fe/questions/fe/_text_area_field.html.erb +10 -3
  94. data/app/views/fe/questions/fe/_text_field.html.erb +1 -1
  95. data/app/views/fe/questions/fe/_yes_no_field.erb +3 -3
  96. data/app/views/fe/reference_pages/_reference.html.erb +11 -11
  97. data/app/views/fe/reference_pages/edit.html.erb +7 -7
  98. data/app/views/fe/reference_sheets/done.html.erb +2 -2
  99. data/app/views/fe/reference_sheets/not_found.html.erb +4 -4
  100. data/app/views/fe/references/edit.html.erb +6 -6
  101. data/app/views/fe/references/show.html.erb +7 -7
  102. data/app/views/fe/references/submit.js.erb +1 -1
  103. data/app/views/fe/submit_pages/_thankyou.html.erb +1 -1
  104. data/app/views/fe/submit_pages/edit.html.erb +9 -9
  105. data/app/views/layouts/fe/_error_messages_for.html.erb +7 -0
  106. data/app/views/layouts/fe/application.html.erb +1 -1
  107. data/config/routes.rb +0 -36
  108. data/db/migrate/20131003044250_create_reference_sheets.rb +1 -0
  109. data/db/migrate/20140623153424_create_fe_people.rb +1 -1
  110. data/db/migrate/20140624180246_create_fe_addresses.rb +1 -1
  111. data/db/migrate/20140624182216_create_fe_phone_numbers.rb +16 -0
  112. data/db/migrate/20140625160545_create_fe_users.rb +1 -1
  113. data/db/migrate/20150504221439_add_all_element_ids_to_pages.rb +5 -0
  114. data/db/migrate/20150713022326_add_locale_columns.rb +9 -0
  115. data/db/migrate/20150714220730_add_locale_to_answer_sheet.rb +5 -0
  116. data/db/migrate/20150928085325_change_pages_all_element_ids_to_text.rb +5 -0
  117. data/db/migrate/20150930191538_add_locale_to_reference_sheets.rb +5 -0
  118. data/lib/access_key_generator.rb +12 -0
  119. data/lib/distinct_distinct_patch.rb +20 -0
  120. data/lib/fe.rb +4 -0
  121. data/lib/fe/engine.rb +16 -4
  122. data/lib/fe/version.rb +1 -1
  123. data/spec/controllers/fe/admin/elements_controller_spec.rb +201 -1
  124. data/spec/controllers/fe/admin/email_templates_controller_spec.rb +26 -1
  125. data/spec/controllers/fe/admin/question_pages_controller_spec.rb +8 -1
  126. data/spec/controllers/fe/admin/question_sheets_controller_spec.rb +48 -1
  127. data/spec/controllers/fe/answer_pages_controller_spec.rb +73 -1
  128. data/spec/controllers/fe/answer_sheets_controller_spec.rb +80 -1
  129. data/spec/controllers/fe/reference_pages_controller.rb +4 -0
  130. data/spec/controllers/fe/references_controller_spec.rb +4 -0
  131. data/spec/controllers/fe/submit_pages_controller_spec.rb +4 -0
  132. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  133. data/spec/dummy/app/helpers/application_helper.rb +9 -0
  134. data/spec/dummy/app/models/application.rb +3 -0
  135. data/spec/dummy/app/models/person.rb +11 -0
  136. data/spec/dummy/app/models/user.rb +3 -0
  137. data/spec/dummy/config/application.rb +2 -1
  138. data/spec/dummy/config/database.yml +20 -17
  139. data/spec/dummy/config/environments/production.rb +1 -5
  140. data/spec/dummy/config/environments/test.rb +3 -1
  141. data/spec/dummy/config/initializers/fast_gettext.rb +5 -0
  142. data/spec/dummy/config/secrets.yml +2 -2
  143. data/spec/dummy/db/migrate/20141203214017_core.fe_engine.rb +92 -0
  144. data/spec/dummy/db/migrate/20141203214018_create_reference_sheets.fe_engine.rb +25 -0
  145. data/spec/dummy/db/migrate/20141203214019_add_element_and_answer_fields.fe_engine.rb +11 -0
  146. data/spec/dummy/db/migrate/20141203214020_create_email_templates.fe_engine.rb +18 -0
  147. data/spec/dummy/db/migrate/20141203214021_add_max_lengths.fe_engine.rb +9 -0
  148. data/spec/dummy/db/migrate/20141203214022_create_join_table.fe_engine.rb +12 -0
  149. data/spec/dummy/db/migrate/20141203214023_remove_question_id_from_element.fe_engine.rb +10 -0
  150. data/spec/dummy/db/migrate/20141203214024_create_fe_people.fe_engine.rb +13 -0
  151. data/spec/dummy/db/migrate/20141203214025_create_fe_addresses.fe_engine.rb +21 -0
  152. data/{db/migrate/20140624182216_create_create_fe_phone_numbers.rb → spec/dummy/db/migrate/20141203214026_create_create_fe_phone_numbers.fe_engine.rb} +1 -0
  153. data/spec/dummy/db/migrate/20141203214027_create_fe_users.fe_engine.rb +13 -0
  154. data/spec/dummy/db/migrate/20141203214028_add_conditional_type_to_elements.fe_engine.rb +6 -0
  155. data/spec/dummy/db/migrate/20141203214029_add_conditional_answer_to_elements.fe_engine.rb +6 -0
  156. data/spec/dummy/db/migrate/20141203214030_remove_short_value_column.fe_engine.rb +6 -0
  157. data/spec/dummy/db/migrate/20141203214031_move_conditional_ids_used_for_choice_field_to_their_own_column.fe_engine.rb +8 -0
  158. data/spec/dummy/db/migrate/20150123215803_create_users.rb +9 -0
  159. data/spec/dummy/db/migrate/20150504222619_add_all_element_ids_to_pages.fe_engine.rb +6 -0
  160. data/spec/dummy/db/migrate/20150930190001_create_fe_phone_numbers.fe_engine.rb +20 -0
  161. data/spec/dummy/db/migrate/20150930190002_add_locale_columns.fe_engine.rb +10 -0
  162. data/spec/dummy/db/migrate/20150930190003_add_locale_to_answer_sheet.fe_engine.rb +6 -0
  163. data/spec/dummy/db/migrate/20150930190004_change_pages_all_element_ids_to_text.fe_engine.rb +6 -0
  164. data/spec/dummy/db/migrate/20150930191756_add_locale_to_reference_sheets.fe_engine.rb +6 -0
  165. data/spec/dummy/db/schema.rb +50 -20
  166. data/spec/dummy/log/development.log +5 -0
  167. data/spec/factories/applications.rb +0 -1
  168. data/spec/factories/dummy_applications.rb +6 -0
  169. data/spec/factories/dummy_people.rb +6 -0
  170. data/spec/factories/dummy_users.rb +6 -0
  171. data/spec/factories/elements.rb +28 -3
  172. data/spec/factories/email_templates.rb +5 -0
  173. data/spec/factories/fe_email_templates.rb +9 -0
  174. data/spec/factories/fe_people.rb +0 -2
  175. data/spec/factories/fe_user.rb +6 -0
  176. data/spec/factories/question_sheet.rb +1 -1
  177. data/spec/factories/reference_sheets.rb +9 -0
  178. data/spec/mailers/fe/notifier_spec.rb +39 -0
  179. data/spec/models/fe/choice_field_spec.rb +20 -0
  180. data/spec/models/fe/element_spec.rb +185 -0
  181. data/spec/models/fe/page_spec.rb +112 -0
  182. data/spec/models/fe/question_sheet_spec.rb +106 -0
  183. data/spec/models/fe/reference_sheet_spec.rb +20 -0
  184. data/spec/rails_helper.rb +41 -13
  185. data/spec/support/choices.xml +6 -0
  186. metadata +136 -48
  187. data/app/assets/javascripts/fe/rails.extra.js +0 -6
  188. data/app/controllers/fe/applications_controller.rb +0 -183
  189. data/app/controllers/fe/payments_controller.rb +0 -184
  190. data/app/models/fe/payment.rb +0 -77
  191. data/app/models/fe/payment_question.rb +0 -22
  192. data/app/views/fe/admin/panels/_prop_payment_question.html.erb +0 -1
  193. data/app/views/fe/application/_logout.html.erb +0 -1
  194. data/app/views/fe/payment_pages/_credit.html.erb +0 -47
  195. data/app/views/fe/payment_pages/_mail.html.erb +0 -27
  196. data/app/views/fe/payment_pages/_payment.html.erb +0 -6
  197. data/app/views/fe/payment_pages/_staff.html.erb +0 -25
  198. data/app/views/fe/payment_pages/_staff_results.html.erb +0 -17
  199. data/app/views/fe/payment_pages/edit.html.erb +0 -75
  200. data/app/views/fe/payment_pages/staff_search.js.erb +0 -2
  201. data/app/views/fe/payments/_credit.html.erb +0 -47
  202. data/app/views/fe/payments/_errors.html.erb +0 -1
  203. data/app/views/fe/payments/_payment.html.erb +0 -13
  204. data/app/views/fe/payments/_staff.html.erb +0 -21
  205. data/app/views/fe/payments/_staff_results.html.erb +0 -18
  206. data/app/views/fe/payments/approve.js.erb +0 -3
  207. data/app/views/fe/payments/create.js.erb +0 -19
  208. data/app/views/fe/payments/destroy.js.erb +0 -7
  209. data/app/views/fe/payments/edit.html.erb +0 -56
  210. data/app/views/fe/payments/error.js.erb +0 -3
  211. data/app/views/fe/payments/no_access.html.erb +0 -7
  212. data/app/views/fe/payments/staff_search.js.erb +0 -1
  213. data/app/views/fe/payments/update.html.erb +0 -24
  214. data/app/views/fe/questions/fe/_payment_question.html.erb +0 -70
  215. data/db/migrate/20140828045339_create_payments.rb +0 -13
  216. data/spec/dummy/db/test.sqlite3 +0 -0
  217. data/spec/factories/payments.rb +0 -7
  218. data/spec/models/fe/payment_question_spec.rb +0 -65
@@ -6,25 +6,25 @@ module Fe
6
6
  belongs_to :question_sheet
7
7
 
8
8
  has_many :page_elements, -> { order(:position) },
9
- :dependent => :destroy
9
+ dependent: :destroy
10
10
 
11
11
  has_many :elements, -> { order(Fe::PageElement.table_name + '.position') },
12
- :through => :page_elements
12
+ through: :page_elements
13
13
 
14
14
  has_many :question_grid_with_totals, -> { where("kind = 'Fe::QuestionGridWithTotal'") },
15
- :through => :page_elements,
16
- :source => :element
15
+ through: :page_elements,
16
+ source: :element
17
17
 
18
- has_many :questions, -> { where("kind NOT IN('Fe::Paragraph', 'Fe::Section', 'Fe::QuestionGrid', 'Fe::QuestionGridWithTotal')") },
19
- :through => :page_elements,
20
- :source => :element
18
+ has_many :questions, -> { questions.order(Fe::PageElement.table_name + '.position') },
19
+ through: :page_elements,
20
+ source: :element
21
21
 
22
22
  has_many :question_grids, -> { where("kind = 'Fe::QuestionGrid'") },
23
- :through => :page_elements,
24
- :source => :element
23
+ through: :page_elements,
24
+ source: :element
25
25
 
26
26
  # has_many :conditions, :class_name => "Condition", :foreign_key => "toggle_page_id", # conditions associated with page as a whole
27
- # :conditions => 'toggle_id is NULL', :dependent => :nullify
27
+ # conditions: 'toggle_id is NULL', :dependent => :nullify
28
28
 
29
29
  acts_as_list :column => :number, :scope => :question_sheet_id
30
30
 
@@ -41,6 +41,8 @@ module Fe
41
41
 
42
42
  validates_numericality_of :number, :only_integer => true
43
43
 
44
+ serialize :label_translations, Hash
45
+
44
46
  # a page is disabled if there is a condition, and that condition evaluates to false
45
47
  # could set multiple conditions to influence this question, in which case all must be met
46
48
  # def active?
@@ -52,8 +54,17 @@ module Fe
52
54
  # false
53
55
  # end
54
56
 
57
+ def label(locale = nil)
58
+ label_translations[locale] || self[:label]
59
+ end
60
+
61
+ # returns true if there is a question element on the page, including one inside a grid
55
62
  def has_questions?
56
- questions.present? || question_grids.present? || question_grid_with_totals.present?
63
+ all_questions.any?
64
+ end
65
+
66
+ def all_questions
67
+ all_elements.questions
57
68
  end
58
69
 
59
70
  def questions_before_position(position)
@@ -62,7 +73,22 @@ module Fe
62
73
 
63
74
  # Include nested elements
64
75
  def all_elements
65
- (elements + elements.collect(&:all_elements)).flatten
76
+ ids = all_element_ids_arr
77
+ order = ids.collect{ |id| "id=#{id} DESC" }.join(', ')
78
+ ids.present? ? Element.where(id: ids).order(order) : Element.where("1 = 0")
79
+ end
80
+
81
+ def all_element_ids
82
+ rebuild_all_element_ids if self[:all_element_ids].nil?
83
+ self[:all_element_ids]
84
+ end
85
+
86
+ def all_element_ids_arr
87
+ @all_element_ids_arr ||= all_element_ids.split(',').collect(&:to_i)
88
+ end
89
+
90
+ def rebuild_all_element_ids
91
+ self.update_column :all_element_ids, elements.collect{ |e| [e] + e.all_elements }.flatten.collect(&:id).join(',')
66
92
  end
67
93
 
68
94
  def copy_to(question_sheet)
@@ -76,24 +102,30 @@ module Fe
76
102
  element.duplicate(new_page)
77
103
  end
78
104
  end
105
+ new_page.rebuild_all_element_ids
106
+ end
107
+
108
+ def hidden?(answer_sheet)
109
+ return false unless question_sheet.all_elements.where(conditional_type: 'Fe::Page', conditional_id: self).any?
110
+
111
+ # if any of the conditional questions matches, it's visible
112
+ !question_sheet.all_elements.where(conditional_type: 'Fe::Page', conditional_id: self).any?{ |e|
113
+ e.conditional_match(answer_sheet)
114
+ }
79
115
  end
80
116
 
81
117
  def complete?(answer_sheet)
82
- return true if question_sheet.hidden_pages(answer_sheet).include?(self)
118
+ return true if hidden?(answer_sheet)
83
119
  prev_el = nil
84
- all_elements.all? {|e|
85
- complete = !e.required? || (prev_el && prev_el.conditional == e && !prev_el.conditional_match(answer_sheet)) || e.has_response?(answer_sheet)
120
+ all_elements.all? {|e|
121
+ complete = !e.required?(answer_sheet, self, prev_el) || e.has_response?(answer_sheet)
86
122
  prev_el = e
87
123
  complete
88
124
  }
89
125
  end
90
126
 
91
127
  def started?(answer_sheet)
92
- all_elements.any? {|e| e.has_response?(answer_sheet)}
93
- end
94
-
95
- def has_questions?
96
- all_elements.any? {|e| e.is_a?(Question)}
128
+ all_questions.any? {|e| e.has_response?(answer_sheet)}
97
129
  end
98
130
 
99
131
  private
@@ -3,11 +3,12 @@ module Fe
3
3
  class PageElement < ActiveRecord::Base
4
4
  self.table_name = self.table_name.sub('fe_', Fe.table_name_prefix)
5
5
  acts_as_list :scope => :page_id
6
- belongs_to :page
6
+ belongs_to :page, touch: true
7
7
  belongs_to :element
8
8
 
9
9
  after_save :save_element
10
10
  before_create :set_position
11
+ after_destroy :rebuild_page_all_element_ids
11
12
 
12
13
  def set_position
13
14
  self.position ||= (page.page_elements.last.try(:position) + 1) || page.elements.last.try(:position) || 0
@@ -17,5 +18,9 @@ module Fe
17
18
  def save_element
18
19
  element.save!
19
20
  end
21
+
22
+ def rebuild_page_all_element_ids
23
+ page.rebuild_all_element_ids
24
+ end
20
25
  end
21
26
  end
@@ -1,15 +1,18 @@
1
1
  # represents a link to a page for the page_list sidebar or next page links
2
2
  module Fe
3
3
  class PageLink
4
- attr_accessor :dom_id, :label, :load_path, :page
4
+ attr_accessor :dom_id, :load_path, :page
5
5
  attr_accessor :save_path # to save current page
6
6
 
7
- def initialize(label, load_path, dom_id, page)
8
- @label = label
7
+ def initialize(load_path, dom_id, page)
9
8
  @load_path = load_path
10
9
  @dom_id = dom_id
11
10
  @page = page
12
11
  end
13
12
 
13
+ def label(locale = nil)
14
+ page.label(locale)
15
+ end
16
+
14
17
  end
15
18
  end
@@ -1,14 +1,13 @@
1
1
  module Fe
2
2
  class Person < ActiveRecord::Base
3
3
  belongs_to :user, :foreign_key => "fk_ssmUserId" # TODO need to migrate person columns to be more rails-like
4
- has_one :current_address, -> { where("address_type = 'current'") }, :class_name => "Fe::Address"
5
- has_many :email_addresses, :foreign_key => "person_id", :class_name => '::EmailAddress', dependent: :destroy
6
- has_many :phone_numbers, :foreign_key => "person_id", :class_name => '::PhoneNumber', dependent: :destroy
7
- has_one :current_address, -> { where("address_type = 'current'") }, :foreign_key => "person_id", :class_name => '::Fe::Address'
8
- has_one :permanent_address, -> { where("address_type = 'permanent'") }, :foreign_key => "person_id", :class_name => '::Fe::Address'
9
- has_one :emergency_address1, -> { where("address_type = 'emergency1'") }, :foreign_key => "person_id", :class_name => 'Fe::Address'
10
- has_many :addresses, :foreign_key => "person_id", dependent: :destroy
11
- has_one :application, :foreign_key => "applicant_id"
4
+ has_many :email_addresses, class_name: '::EmailAddress', dependent: :destroy
5
+ has_many :phone_numbers, class_name: '::PhoneNumber', dependent: :destroy
6
+ has_one :current_address, -> { where("address_type = 'current'") }, class_name: '::Fe::Address', dependent: :destroy
7
+ has_one :permanent_address, -> { where("address_type = 'permanent'") }, class_name: '::Fe::Address', dependent: :destroy
8
+ has_one :emergency_address1, -> { where("address_type = 'emergency1'") }, class_name: 'Fe::Address', dependent: :destroy
9
+ has_many :addresses, dependent: :destroy
10
+ has_many :applications, class_name: Fe.answer_sheet_class
12
11
 
13
12
  def emergency_address
14
13
  emergency_address1
@@ -28,6 +27,10 @@ module Fe
28
27
  def create_permanent_address
29
28
  Address.create(:person_id => self.id, :address_type => 'permanent')
30
29
  end
30
+
31
+ def name
32
+ [ first_name, last_name ].join(' ')
33
+ end
31
34
  end
32
35
 
33
36
  end
@@ -79,7 +79,7 @@ module Fe
79
79
  end
80
80
 
81
81
  def locked?(params, answer_sheet, presenter)
82
- return true unless ['fe/answer_pages', 'fe/reference_sheets'].include?(params['controller']) && params['action'] == 'edit'
82
+ return true unless params['action'] == 'edit'
83
83
  if self.object_name == 'person.current_address' && ['address1','address2','city','zip','email','state','country'].include?(self.attribute_name)
84
84
  # Billing Address
85
85
  return false
@@ -169,7 +169,7 @@ module Fe
169
169
  value = values.first
170
170
  if self.is_a?(Fe::DateField) && value.present?
171
171
  begin
172
- value = Date.strptime(value, (I18n.t 'date.formats.default'))
172
+ value = Date.strptime(value, '%Y-%m-%d')
173
173
  rescue
174
174
  raise "invalid date - " + value.inspect
175
175
  end
@@ -248,9 +248,5 @@ module Fe
248
248
  false
249
249
  end
250
250
 
251
- def required?(answer_sheet = nil)
252
- super
253
- end
254
-
255
251
  end
256
252
  end
@@ -7,7 +7,7 @@
7
7
  module Fe
8
8
  class QuestionGrid < Element
9
9
 
10
- has_many :elements, -> { order('position') },
10
+ has_many :elements, -> { order('position asc, id asc') },
11
11
  :class_name => "Element",
12
12
  :foreign_key => "question_grid_id",
13
13
  :dependent => :nullify
@@ -7,5 +7,20 @@
7
7
 
8
8
  module Fe
9
9
  class QuestionGridWithTotal < QuestionGrid
10
+ def totals(app)
11
+ totals = []
12
+ col = 0
13
+ row = []
14
+ elements.each do |el|
15
+ value = el.display_response(app) if el.respond_to?(:display_response) && el.display_response(app).present?
16
+
17
+ if value && value.present? # keep totals nil until there actually is a value, so that we can only display a total only if at least one row had a value
18
+ value = value.tr("^0-9.", '').to_f
19
+ totals[col] = (totals[col].present? ? totals[col] + value : value)
20
+ end
21
+ col = (col + 1) % num_cols
22
+ end
23
+ totals
24
+ end
10
25
  end
11
26
  end
@@ -65,7 +65,7 @@ module Fe
65
65
  if month.blank? or year.blank?
66
66
  values = ''
67
67
  else
68
- values = [Date.new(year.to_i, month.to_i, 1).strftime('%m/%d/%Y')] # for mm/yy drop downs
68
+ values = [Date.new(year.to_i, month.to_i, 1).strftime('%Y-%m-%d')] # for mm/yy drop downs
69
69
  end
70
70
  elsif param.kind_of?(Hash)
71
71
  # from Hash with multiple answers per question
@@ -6,20 +6,19 @@ module Fe
6
6
  has_many :pages, -> { order('number') },
7
7
  :dependent => :destroy
8
8
 
9
- # has_many :elements
10
- # has_many :questions
11
-
12
9
  has_many :answer_sheet_question_sheets
13
10
 
14
11
  has_many :answer_sheets,
15
12
  :through => :answer_sheet_question_sheets
13
+ has_many :question_sheets,
14
+ :through => :answer_sheet_question_sheets
16
15
 
17
16
  scope :active, -> { where(:archived => false) }
18
17
  scope :archived, -> { where(:archived => true) }
19
18
 
20
19
  validates_presence_of :label
21
- # validates_length_of :label, :maximum => 60, :allow_nil => true
22
- validates_uniqueness_of :label
20
+
21
+ serialize :languages, Array
23
22
 
24
23
  before_destroy :check_for_answers
25
24
 
@@ -30,14 +29,24 @@ module Fe
30
29
  question_sheet
31
30
  end
32
31
 
32
+ # count all questions including ones inside a grid
33
+ def questions_count
34
+ all_elements.questions.count
35
+ end
36
+
33
37
  def questions
34
- pages.collect(&:questions).flatten
38
+ all_elements.questions
35
39
  end
36
40
 
37
41
  def elements
38
42
  pages.collect(&:elements).flatten
39
43
  end
40
44
 
45
+ def all_elements
46
+ element_ids = pages.pluck(:all_element_ids).compact.join(',').split(',')
47
+ element_ids.present? ? Element.where(id: element_ids).order(element_ids.collect{ |id| "id=#{id} DESC" }.join(', ')) : Element.where("1 = 0")
48
+ end
49
+
41
50
  # Pages get duplicated
42
51
  # Question elements get associated
43
52
  # non-question elements get cloned
@@ -51,13 +60,6 @@ module Fe
51
60
  new_sheet
52
61
  end
53
62
 
54
- # pages hidden by a conditional element
55
- def hidden_pages(answer_sheet)
56
- elements.find_all{ |e|
57
- e.conditional.is_a?(Fe::Page) && !e.conditional_match(answer_sheet)
58
- }.collect(&:conditional)
59
- end
60
-
61
63
  private
62
64
 
63
65
  # next unused label with "Untitled form" prefix
@@ -7,16 +7,6 @@ module Fe
7
7
  return unless app
8
8
  # A reference is the same if the related_question_sheet corresponding to the question is the same
9
9
  reference = Fe::ReferenceSheet.find_by_applicant_answer_sheet_id_and_question_id(app.id, id)
10
- # if references.present?
11
- # reference = references.detect {|r| r.question_id == id }
12
- # # If they have another reference that matches this question id, don't go fishing for another one
13
- # unless reference
14
- # # If the question_id doesn't match, but the reference question is based on the same reference template (question sheet)
15
- # # update the reference with the new question_id
16
- # reference = references.detect {|r| r.question.related_question_sheet_id == related_question_sheet_id}
17
- # reference.update_attribute(:question_id, id) if reference
18
- # end
19
- # end
20
10
  reference || Fe::ReferenceSheet.create(:applicant_answer_sheet_id => app.id, :question_id => id)
21
11
  end
22
12
 
@@ -5,19 +5,21 @@ module Fe
5
5
  include Fe::AnswerSheetConcern
6
6
  include Rails.application.routes.url_helpers
7
7
  include AASM
8
+ include AccessKeyGenerator
9
+
8
10
  self.table_name = "#{Fe.table_name_prefix}references"
9
11
  self.inheritance_column = 'fake'
10
12
 
11
13
  belongs_to :question,
12
- :class_name => 'Element',
14
+ :class_name => 'Fe::ReferenceQuestion',
13
15
  :foreign_key => 'question_id'
14
16
 
15
17
  belongs_to :applicant_answer_sheet,
16
- :class_name => Fe.answer_sheet_class,
18
+ :class_name => "::#{Fe.answer_sheet_class}",
17
19
  :foreign_key => "applicant_answer_sheet_id"
18
20
 
19
21
  validates_presence_of :first_name, :last_name, :phone, :email, :relationship, :on => :update, :message => "can't be blank"
20
- validates :email, :email_format => { :message => "doesn't look right." }
22
+ validates :email, :email_format => { :on => :update, :message => "doesn't look right." }
21
23
 
22
24
  delegate :style, :to => :question
23
25
 
@@ -74,10 +76,8 @@ module Fe
74
76
  end
75
77
  end
76
78
 
77
- alias_method :applicant, :applicant_answer_sheet
78
- def generate_access_key
79
- self.access_key = Digest::MD5.hexdigest(email + Time.now.to_s)
80
- end
79
+ alias_method :application, :applicant_answer_sheet
80
+ delegate :applicant, to: :application
81
81
 
82
82
  def frozen?
83
83
  !%w(started created).include?(self.status)
@@ -95,15 +95,15 @@ module Fe
95
95
  Fe.from_email,
96
96
  "Reference Invite",
97
97
  {'reference_full_name' => self.name,
98
- 'applicant_full_name' => application.name,
99
- 'applicant_email' => application.email,
100
- 'applicant_home_phone' => application.phone,
98
+ 'applicant_full_name' => application.applicant.name,
99
+ 'applicant_email' => application.applicant.email,
100
+ 'applicant_home_phone' => application.applicant.phone,
101
101
  'reference_url' => edit_fe_reference_sheet_url(self, :a => self.access_key, :host => ActionMailer::Base.default_url_options[:host])}).deliver
102
102
  # Send notification to applicant
103
- Notifier.notification(applicant_answer_sheet.email, # RECIPIENTS
103
+ Notifier.notification(applicant_answer_sheet.applicant.email, # RECIPIENTS
104
104
  Fe.from_email, # FROM
105
105
  "Reference Notification to Applicant", # LIQUID TEMPLATE NAME
106
- {'applicant_full_name' => applicant_answer_sheet.name,
106
+ {'applicant_full_name' => applicant_answer_sheet.applicant.name,
107
107
  'reference_full_name' => self.name,
108
108
  'reference_email' => self.email,
109
109
  'application_url' => edit_fe_answer_sheet_url(applicant_answer_sheet, :host => ActionMailer::Base.default_url_options[:host])}).deliver
@@ -144,6 +144,10 @@ module Fe
144
144
  [question_sheet]
145
145
  end
146
146
 
147
+ def question_sheet_ids
148
+ [question_sheet.try(:id)].compact
149
+ end
150
+
147
151
  def display_type
148
152
  question.label.split(/:| \(/).first
149
153
  end
@@ -151,7 +155,7 @@ module Fe
151
155
  protected
152
156
  # if the email address has changed, we have to trash the old reference answers
153
157
  def check_email_change
154
- if changed.include?('email')
158
+ if !new_record? && changed.include?('email')
155
159
  answers.destroy_all
156
160
  # Every time the email address changes, generate a new access_key
157
161
  generate_access_key
@@ -5,6 +5,8 @@ class Staff < ActiveRecord::Base
5
5
  belongs_to :primary_address, :class_name => "StaffAddress", :foreign_key => :fk_primaryAddress
6
6
  belongs_to :secondary_address, :class_name => "StaffAddress", :foreign_key => :fk_secondaryAddress
7
7
 
8
+ alias_attribute :preferred_name, :preferredName
9
+
8
10
  def self.get_staff(ssm_id)
9
11
  if ssm_id.nil? then raise "nil ssm_id!" end
10
12
  ssm_user = User.find_by(userID: ssm_id)
@@ -0,0 +1,11 @@
1
+ require 'mail'
2
+
3
+ class EmailValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, value)
5
+ begin
6
+ parsed = Mail::Address.new(value)
7
+ rescue Mail::Field::ParseError => e
8
+ end
9
+ record.errors.add attribute, "is not valid" unless !parsed.nil? && parsed.address == value && parsed.local != value #cannot be a local address
10
+ end
11
+ end