fe 0.0.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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