Now, the time of schedules are configurable.

Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk@supinfo.com>
---
 app/models/product.rb                              |    1 +
 app/models/user_mailer.rb                          |   10 +++++
 .../user_mailer/sprints_products_status.html.erb   |    9 ++++
 config/initializers/schedules.rb                   |   34 ++++++++++++++++-
 config/schedules.yml                               |    7 +++
 db/schema.rb                                       |   40 ++++++++++++-------
 6 files changed, 84 insertions(+), 17 deletions(-)
 create mode 100644 app/views/user_mailer/sprints_products_status.html.erb
 create mode 100644 config/schedules.yml

diff --git a/app/models/product.rb b/app/models/product.rb
index 1cd3035..78cff45 100644
--- a/app/models/product.rb
+++ b/app/models/product.rb
@@ -30,6 +30,7 @@ class Product < ActiveRecord::Base
   has_many   :backlog, :class_name => 'UserStory', :order => 'priority ASC'
   has_many :product_roles
   has_many :users, :through => :product_roles
+  has_many :sprints
 
   # Returns whether the user can create sprints for this product.
   #
diff --git a/app/models/user_mailer.rb b/app/models/user_mailer.rb
index 896a688..9c70473 100644
--- a/app/models/user_mailer.rb
+++ b/app/models/user_mailer.rb
@@ -36,4 +36,14 @@ class UserMailer < ActionMailer::Base
     subject     "No task has been detected"
     body        :user => user, :backlog_items => backlog_items
   end
+
+  # Send an email to a user to notify him the status of each sprint of his
+  # products.
+  #
+  def sprints_products_status(user, products)
+    recipients  user.email
+    from        MAIL_CONFIG[:from]
+    subject     "Status of sprints"
+    body        :user => user, :products => products
+  end
 end
diff --git a/app/views/user_mailer/sprints_products_status.html.erb b/app/views/user_mailer/sprints_products_status.html.erb
new file mode 100644
index 0000000..9ae07c9
--- /dev/null
+++ b/app/views/user_mailer/sprints_products_status.html.erb
@@ -0,0 +1,9 @@
+Dear <%= @user.display_name %>,
+
+Here the sprint's status of every product.
+<% @products.each do |product| %>
+- <%= product.name %>
+<% product.sprints.each do |sprint| %>
+     - <%= sprint.title %> => <%= Sprint::STATUS_TEXT.collect { |s| s.first if (s.last == sprint.status) }.compact %>
+<% end %>
+<% end %>
diff --git a/config/initializers/schedules.rb b/config/initializers/schedules.rb
index fb58101..aa8a515 100644
--- a/config/initializers/schedules.rb
+++ b/config/initializers/schedules.rb
@@ -2,6 +2,10 @@ require 'fastthread'
 require 'openwfe/util/scheduler'
 include OpenWFE
 
+# Load the schedules configuration
+schedules_file_path = "#{RAILS_ROOT}/config/schedules.yml"
+SCHEDULES_CONFIG = YAML.load(File.open(schedules_file_path))
+
 # Initialize a threads array
 threads = []
 
@@ -9,8 +13,10 @@ threads << Thread.new do
   scheduler = Scheduler.new
   scheduler.start
 
-  # Do this everyday at 05:00 am
-  scheduler.schedule('0 5 * * *') do # TODO Time must be configurable
+  hours = SCHEDULES_CONFIG[:no_activity_or_no_task_recorded_time][:hours]
+  minutes = SCHEDULES_CONFIG[:no_activity_or_no_task_recorded_time][:minutes]
+
+  scheduler.schedule("#{minutes} #{hours} * * *") do
 
     user_no_activity_on_backlog_items = {}
     user_no_tasks_on_backlog_items = {}
@@ -50,5 +56,29 @@ threads << Thread.new do
   scheduler.join
 end
 
+threads << Thread.new do
+  scheduler = Scheduler.new
+  scheduler.start
+
+  hours = SCHEDULES_CONFIG[:sprints_products_status_time][:hours]
+  minutes = SCHEDULES_CONFIG[:sprints_products_status_time][:minutes]
+
+  scheduler.schedule("#{minutes} #{hours} * * *") do
+    user_with_products = {}
+
+    Product.find(:all).each do |product|
+      product_owner = product.owner
+      user_with_products[product_owner] ||= []
+      user_with_products[product_owner] << product
+    end
+
+    user_with_products.each do |owner, products|
+      UserMailer.deliver_sprints_products_status(owner, products)
+    end
+  end
+
+  scheduler.join
+end
+
 # Run all threads
 threads.each { |thread| thread.run }
\ No newline at end of file
diff --git a/config/schedules.yml b/config/schedules.yml
new file mode 100644
index 0000000..7883c15
--- /dev/null
+++ b/config/schedules.yml
@@ -0,0 +1,7 @@
+---
+  :no_activity_or_no_task_recorded_time:
+    :hours: 5
+    :minutes: 0
+  :sprints_products_status_time:
+    :hours: 5
+    :minutes: 0
\ No newline at end of file
diff --git a/db/schema.rb b/db/schema.rb
index 331a1e5..6802559 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -9,7 +9,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 15) do
+ActiveRecord::Schema.define(:version => 16) do
 
   create_table "backlog_items", :force => true do |t|
     t.integer  "sprint_id",                                                      :null => false
@@ -50,8 +50,8 @@ ActiveRecord::Schema.define(:version => 15) do
   add_index "products", ["project_id"], :name => "fk_products_project"
 
   create_table "projects", :force => true do |t|
-    t.integer  "owner_id",                  :null => false
-    t.string   "name",        :limit => 50, :null => false
+    t.integer  "owner_id",                                  :null => false
+    t.string   "name",        :limit => 50, :default => "", :null => false
     t.string   "url"
     t.text     "description"
     t.datetime "created_at"
@@ -74,7 +74,7 @@ ActiveRecord::Schema.define(:version => 15) do
   add_index "remaining_hours_estimates", ["user_id"], :name => "fk_remaining_hours_user"
 
   create_table "roles", :force => true do |t|
-    t.string   "name",                                        :null => false
+    t.string   "name",                     :default => "",    :null => false
     t.boolean  "can_manage_backlog_items", :default => false, :null => false
     t.boolean  "can_close_user_story",     :default => false, :null => false
     t.datetime "created_at"
@@ -84,7 +84,7 @@ ActiveRecord::Schema.define(:version => 15) do
   add_index "roles", ["name"], :name => "index_roles_on_name", :unique => true
 
   create_table "sessions", :force => true do |t|
-    t.string   "session_id", :null => false
+    t.string   "session_id", :default => "", :null => false
     t.text     "data"
     t.datetime "created_at"
     t.datetime "updated_at"
@@ -94,14 +94,14 @@ ActiveRecord::Schema.define(:version => 15) do
   add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
 
   create_table "sprints", :force => true do |t|
-    t.integer  "product_id",                                :null => false
-    t.string   "title",      :limit => 100,                 :null => false
-    t.date     "start",                                     :null => false
-    t.integer  "duration",                                  :null => false
-    t.string   "goals",      :limit => 1000,                :null => false
+    t.integer  "product_id",                                 :null => false
+    t.string   "title",      :limit => 100,  :default => "", :null => false
+    t.date     "start",                                      :null => false
+    t.integer  "duration",                                   :null => false
+    t.string   "goals",      :limit => 1000, :default => "", :null => false
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.integer  "status",                     :default => 0, :null => false
+    t.integer  "status",                     :default => 0,  :null => false
   end
 
   add_index "sprints", ["product_id"], :name => "fk_sprint_product"
@@ -143,11 +143,21 @@ ActiveRecord::Schema.define(:version => 15) do
 
   add_index "user_stories", ["product_id"], :name => "fk_user_story_product"
 
+  create_table "user_verifications", :force => true do |t|
+    t.integer  "user_id",                                  :null => false
+    t.string   "token",      :limit => 16, :default => "", :null => false
+    t.datetime "sent",                                     :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "user_verifications", ["user_id"], :name => "index_user_verifications_on_user_id", :unique => true
+
   create_table "users", :force => true do |t|
-    t.string   "email",           :limit => 128, :null => false
-    t.string   "display_name",    :limit => 128, :null => false
-    t.string   "hashed_password",                :null => false
-    t.string   "salt",                           :null => false
+    t.string   "email",           :limit => 128, :default => "", :null => false
+    t.string   "display_name",    :limit => 128, :default => "", :null => false
+    t.string   "hashed_password",                :default => "", :null => false
+    t.string   "salt",                           :default => "", :null => false
     t.text     "introduction"
     t.datetime "created_at"
     t.datetime "updated_at"
--
1.6.0.2