| 
				
			 | 
			
			
				@@ -38,6 +38,14 @@ class Activity < ApplicationRecord 
			 | 
		
	
		
			
			| 
				38
			 | 
			
				38
			 | 
			
			
				   # @!attribute reminder_done 
			 | 
		
	
		
			
			| 
				39
			 | 
			
				39
			 | 
			
			
				   #   @return [Boolean] 
			 | 
		
	
		
			
			| 
				40
			 | 
			
				40
			 | 
			
			
				   #     whether or not sending the reminder has finished. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				41
			 | 
			
			
				+  # 
			 | 
		
	
		
			
			| 
				
			 | 
			
				42
			 | 
			
			
				+  # @!attribute subgroup_division_enabled 
			 | 
		
	
		
			
			| 
				
			 | 
			
				43
			 | 
			
			
				+  #   @return [Boolean] 
			 | 
		
	
		
			
			| 
				
			 | 
			
				44
			 | 
			
			
				+  #     whether automatic subgroup division on the deadline is enabled. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				45
			 | 
			
			
				+  # 
			 | 
		
	
		
			
			| 
				
			 | 
			
				46
			 | 
			
			
				+  # @!attribute subgroup_division_done 
			 | 
		
	
		
			
			| 
				
			 | 
			
				47
			 | 
			
			
				+  #   @return [Boolean] 
			 | 
		
	
		
			
			| 
				
			 | 
			
				48
			 | 
			
			
				+  #     whether subgroup division has been performed. 
			 | 
		
	
		
			
			| 
				41
			 | 
			
				49
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				42
			 | 
			
				50
			 | 
			
			
				   belongs_to :group 
			 | 
		
	
		
			
			| 
				43
			 | 
			
				51
			 | 
			
			
				  
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -53,10 +61,17 @@ class Activity < ApplicationRecord 
			 | 
		
	
		
			
			| 
				53
			 | 
			
				61
			 | 
			
			
				   validate  :deadline_before_start, unless: "self.deadline.blank?" 
			 | 
		
	
		
			
			| 
				54
			 | 
			
				62
			 | 
			
			
				   validate  :end_after_start,       unless: "self.end.blank?" 
			 | 
		
	
		
			
			| 
				55
			 | 
			
				63
			 | 
			
			
				   validate  :reminder_before_deadline, unless: "self.reminder_at.blank?" 
			 | 
		
	
		
			
			| 
				
			 | 
			
				64
			 | 
			
			
				+  validate  :subgroups_for_division_present, on: :update 
			 | 
		
	
		
			
			| 
				56
			 | 
			
				65
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				57
			 | 
			
				66
			 | 
			
			
				   after_create :create_missing_participants! 
			 | 
		
	
		
			
			| 
				58
			 | 
			
				67
			 | 
			
			
				   after_create :copy_default_subgroups! 
			 | 
		
	
		
			
			| 
				59
			 | 
			
				
			 | 
			
			
				-  after_commit :schedule_reminder, if: Proc.new {|a| a.previous_changes["reminder_at"] } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				68
			 | 
			
			
				+  after_commit :schedule_reminder, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				69
			 | 
			
			
				+               if: Proc.new { |a| a.previous_changes["reminder_at"] } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				70
			 | 
			
			
				+  after_commit :schedule_subgroup_division, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				71
			 | 
			
			
				+               if: Proc.new { |a| (a.previous_changes['deadline'] || 
			 | 
		
	
		
			
			| 
				
			 | 
			
				72
			 | 
			
			
				+                                   a.previous_changes['subgroup_division_enabled']) && 
			 | 
		
	
		
			
			| 
				
			 | 
			
				73
			 | 
			
			
				+                                  !a.subgroup_division_done && 
			 | 
		
	
		
			
			| 
				
			 | 
			
				74
			 | 
			
			
				+                                  a.subgroup_division_enabled } 
			 | 
		
	
		
			
			| 
				60
			 | 
			
				75
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				61
			 | 
			
				76
			 | 
			
			
				   # Get all people (not participants) that are organizers. Does not include 
			 | 
		
	
		
			
			| 
				62
			 | 
			
				77
			 | 
			
			
				   # group leaders, although they may modify the activity as well. 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -123,12 +138,16 @@ class Activity < ApplicationRecord 
			 | 
		
	
		
			
			| 
				123
			 | 
			
				138
			 | 
			
			
				   def copy_default_subgroups! 
			 | 
		
	
		
			
			| 
				124
			 | 
			
				139
			 | 
			
			
				     defaults = self.group.default_subgroups 
			 | 
		
	
		
			
			| 
				125
			 | 
			
				140
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				141
			 | 
			
			
				+    # If there are no subgroups, there cannot be subgroup division. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				142
			 | 
			
			
				+    self.update_attribute(:subgroup_division_enabled, false) if defaults.none? 
			 | 
		
	
		
			
			| 
				
			 | 
			
				143
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				126
			 | 
			
				144
			 | 
			
			
				     defaults.each do |dsg| 
			 | 
		
	
		
			
			| 
				127
			 | 
			
				145
			 | 
			
			
				       sg = Subgroup.new(activity: self) 
			 | 
		
	
		
			
			| 
				128
			 | 
			
				146
			 | 
			
			
				       sg.name = dsg.name 
			 | 
		
	
		
			
			| 
				129
			 | 
			
				147
			 | 
			
			
				       sg.is_assignable = dsg.is_assignable 
			 | 
		
	
		
			
			| 
				130
			 | 
			
				148
			 | 
			
			
				       sg.save! # Should never fail, as DSG and SG have identical validation, and names cannot clash. 
			 | 
		
	
		
			
			| 
				131
			 | 
			
				149
			 | 
			
			
				     end 
			 | 
		
	
		
			
			| 
				
			 | 
			
				150
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				132
			 | 
			
				151
			 | 
			
			
				   end 
			 | 
		
	
		
			
			| 
				133
			 | 
			
				152
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				134
			 | 
			
				153
			 | 
			
			
				   # Create multiple Activities from data in a CSV file, assign to a group, return. 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -183,6 +202,12 @@ class Activity < ApplicationRecord 
			 | 
		
	
		
			
			| 
				183
			 | 
			
				202
			 | 
			
			
				     self.delay(run_at: self.reminder_at).send_reminder 
			 | 
		
	
		
			
			| 
				184
			 | 
			
				203
			 | 
			
			
				   end 
			 | 
		
	
		
			
			| 
				185
			 | 
			
				204
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				205
			 | 
			
			
				+  def schedule_subgroup_division 
			 | 
		
	
		
			
			| 
				
			 | 
			
				206
			 | 
			
			
				+    return if self.deadline.nil? || self.subgroup_division_done 
			 | 
		
	
		
			
			| 
				
			 | 
			
				207
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				208
			 | 
			
			
				+    self.delay(run_at: self.deadline).assign_subgroups! 
			 | 
		
	
		
			
			| 
				
			 | 
			
				209
			 | 
			
			
				+  end 
			 | 
		
	
		
			
			| 
				
			 | 
			
				210
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				186
			 | 
			
				211
			 | 
			
			
				   # Assign a subgroup to all attending participants without one. 
			 | 
		
	
		
			
			| 
				187
			 | 
			
				212
			 | 
			
			
				   def assign_subgroups! 
			 | 
		
	
		
			
			| 
				188
			 | 
			
				213
			 | 
			
			
				     # Sanity check: we need subgroups to divide into. 
			 |