diff --git a/.gitignore b/.gitignore index 705d2bf..1dbd321 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,6 @@ # Ignore user profile files /.rvmrc -.DS_Store \ No newline at end of file +.DS_Store + +/config/smtp_config.yml diff --git a/Gemfile b/Gemfile index f608d48..74482b9 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,7 @@ gem 'devise', '~> 3.0.0.rc' gem 'jbuilder' gem 'gravatar_image_tag', '~> 1.1.3' gem 'simple_form', '~> 3.0.0.beta1' +gem 'whenever' # Heroku gems diff --git a/Gemfile.lock b/Gemfile.lock index 37dfd8c..75fa960 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -34,6 +34,7 @@ GEM bootswatch-rails (0.4.0) railties (>= 3.1) builder (3.1.4) + chronic (0.10.2) coffee-rails (4.0.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) @@ -138,6 +139,9 @@ GEM json (>= 1.8.0) warden (1.2.3) rack (>= 1.0) + whenever (0.9.0) + activesupport (>= 2.3.4) + chronic (>= 0.6.3) wirble (0.1.3) PLATFORMS @@ -163,4 +167,5 @@ DEPENDENCIES simple_form (~> 3.0.0.beta1) thin (~> 1.4.1) uglifier (>= 1.0.3) + whenever wirble (~> 0.1.3) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 85478ef..eaf820c 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -22,4 +22,5 @@ //= require partials/mask //= require partials/timer //= require partials/timesheet -//= require partials/reports \ No newline at end of file +//= require partials/reports +//= require partials/users diff --git a/app/assets/javascripts/partials/users.js.coffee b/app/assets/javascripts/partials/users.js.coffee new file mode 100644 index 0000000..0d07fde --- /dev/null +++ b/app/assets/javascripts/partials/users.js.coffee @@ -0,0 +1,7 @@ +jQuery -> + if $("#user_is_admin").is ":checked" + $("#subscription_to_admin").show() + else + $("#subscription_to_admin").hide() + + $("#user_is_admin").change -> $("#subscription_to_admin").toggle() diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 38c6dae..4ee1724 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -64,8 +64,14 @@ def set_user # Never trust parameters from the scary internet, only allow the white list through. def user_params - user_attributes = [:name, :email, :password, :password_confirmation, :time_zone] - user_attributes += [:is_admin, :is_active] if current_user.is_admin + user_attributes = [:name, :email, :password, :password_confirmation, :time_zone, + :subscriber_to_user_summary_email] + if current_user.is_admin + user_attributes += [:is_admin, :is_active] + if params[:user][:is_admin].to_i == 1 + user_attributes.push(:subscriber_to_admin_summary_email) + end + end params.require(:user).permit(*user_attributes) end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb new file mode 100644 index 0000000..b31b72d --- /dev/null +++ b/app/mailers/user_mailer.rb @@ -0,0 +1,83 @@ +class UserMailer < ActionMailer::Base + include TimesheetHelper + helper_method :hours_and_minutes + + before_action :set_date + + default from: "Cuckoo <#{SMTP_CONFIG[:from_email]}>" + + def send_day_summary_to_all_subscribers + + users = User.where(subscriber_to_user_summary_email: true) + + users.each do |user| + user_day_summary_email(user).deliver + end + + admins = User.where(subscriber_to_admin_summary_email: true) + + admin_day_summary_email(admins).deliver + + end + + def send_week_summary_to_all_subscribers + + users = User.where(subscriber_to_user_summary_email: true) + + users.each do |user| + user_week_summary_email(user).deliver + end + + admins = User.where(subscriber_to_admin_summary_email: true) + + admin_week_summary_email(admins).deliver + + end + + def user_day_summary_email(user) + @user = user + subject = (@date.strftime('%b/%d')) + ' summary' + mail to: user.email, subject: subject, + content: 'html', template_name: 'user_day_summary_email' + end + + def admin_day_summary_email(recipients) + @users = User.all + subject = 'All users ' + @date.strftime('%b/%d') + ' summary' + emails = get_emails_from(recipients) + mail to: emails, subject: subject, + content: 'html', template_name: 'admin_day_summary_email' + end + + def user_week_summary_email(user) + @user = user + subject = @date.at_beginning_of_week.strftime('%b/%d') \ + + ' to ' + @date.at_end_of_week.strftime('%b/%d') + ' summary' + mail to: user.email, subject: subject, + content: 'html', template_name: 'user_week_summary_email' + end + + def admin_week_summary_email(recipients) + @users = User.all + subject = 'All users ' + @date.at_beginning_of_week.strftime('%b/%d') \ + + ' to ' + @date.at_end_of_week.strftime('%b/%d') + ' summary' + emails = get_emails_from(recipients) + mail to: emails, subject: subject, + content: 'html', template_name: 'admin_week_summary_email' + end + + private + + def set_date + @date = Time.current.to_date + end + + def get_emails_from(recipients) + if (recipients.class == User) + recipients.email + else + recipients.collect(&:email) + end + end + +end diff --git a/app/models/report.rb b/app/models/report.rb new file mode 100644 index 0000000..0e81aa7 --- /dev/null +++ b/app/models/report.rb @@ -0,0 +1,68 @@ +class Report + + def initialize(user) + @user = user + end + + def week_summary(date = Time.current.to_date) + + week_begin = date.at_beginning_of_week.at_midnight.gmtime + week_end = date.at_end_of_week.at_midnight.gmtime + entries = TimeEntry.where(user_id: @user.id) + .where('started_at >= ? AND started_at < ?', week_begin, week_end) + .includes(:project, :task) + + time_summary = {} + entries.each do |time_entry| + project = time_entry.project.name + task = time_entry.task.name + + if (time_summary[project].nil?) + time_summary[project] = {} + time_summary[project][:total] = 0 + time_summary[project][:tasks] = {} + end + + if (time_summary[project][:tasks][task].nil?) + time_summary[project][:tasks][task] = 0 + end + + if (!time_entry.total_time.nil?) + time_summary[project][:total] += time_entry.total_time + time_summary[project][:tasks][task] += time_entry.total_time + end + + end + + { + date: date, + weekdays: week_days(date), + week_hours: week_hours(date), + time_summary: time_summary + } + + end + + def day_summary(date = Time.current.to_date) + { + date: date, + weekdays: week_days(date), + week_hours: week_hours(date), + day_entries: day_entries(date) + } + end + + def week_hours(date = Time.current.to_date) + Timesheet.new(@user).week_hours(date) + end + + def week_days(date = Time.current.to_date) + (date.at_beginning_of_week..date.at_end_of_week) + end + + def day_entries(date = Time.current.to_date) + Timesheet.new(@user).day_entries(date) + end + + +end \ No newline at end of file diff --git a/app/views/user_mailer/_day_summary.html.erb b/app/views/user_mailer/_day_summary.html.erb new file mode 100644 index 0000000..101005f --- /dev/null +++ b/app/views/user_mailer/_day_summary.html.erb @@ -0,0 +1,92 @@ +<% if !summary[:day_entries].find_by(ended_at: nil).nil? %> +
| " >
+ <%= weekday.strftime('%A') %> + (<%= hours_and_minutes(summary[:week_hours][weekday.day]) %>) + |
+ <% end %>
+
+ Total + (<%= hours_and_minutes(summary[:week_hours].values.sum) %>) + |
+
| Activity | +Time | +Duration | +
|---|---|---|
+
|
+
+
+
+
+
+ <%= time_entry.started_at.strftime("%H:%M") %>
+
+ + <%= time_entry.ended_at.strftime("%H:%M") unless time_entry.ended_at.nil? %> + |
+
+
+
+
+
+ <% if !time_entry.ended_at.nil? %>
+ <%= hours_and_minutes(time_entry.ended_at - time_entry.started_at) %>
+ <% else %>
+ Running
+ <% end %>
+
+ |
+
+
|
+ <%= weekday.strftime('%A') %> + (<%= hours_and_minutes(summary[:week_hours][weekday.day]) %>) + |
+ <% end %>
+
+ Total + (<%= hours_and_minutes(summary[:week_hours].values.sum) %>) + |
+
+
|
+
+
+
+
+ <%= hours_and_minutes(info[:total]) %>
+
+
+ |
+
+
|
+ <% info[:tasks].each do |task, duration| %>
+
+ <%= task %> (<%= hours_and_minutes(duration) %>)
+ + <% end %> + |
+