Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate by weekday #291

Merged
merged 12 commits into from
Aug 17, 2023
24 changes: 22 additions & 2 deletions app/controllers/assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
class AssignmentsController < ApplicationController
before_action :find_assignment, only: %i[destroy edit update]
before_action :set_roster_users, only: %i[edit new rotation_generator]
before_action :require_admin_in_roster, only: %i[generate_rotation
rotation_generator]
before_action :require_admin_in_roster, only: %i[generate_rotation rotation_generator
generate_by_weekday generate_by_weekday_submit]
skip_before_action :set_current_user, :set_roster, only: :feed

def index
Expand Down Expand Up @@ -43,6 +43,22 @@ def generate_rotation
redirect_to roster_assignments_path(@roster, date: start_date)
end

def generate_by_weekday
@generator = Assignment::WeekdayGenerator.new roster_id: @roster.id
end

def generate_by_weekday_submit
@generator = Assignment::WeekdayGenerator.new(roster_id: @roster.id,
**generate_by_weekday_params)
if @generator.generate
flash[:message] = t('.success')
redirect_to roster_assignments_path(@roster, date: @generator.start_date)
else
flash.now[:errors] = @generator.errors.full_messages.to_sentence
render :generate_by_weekday
end
end

def create
ass_params = params.require(:assignment)
.permit :start_date, :end_date,
Expand Down Expand Up @@ -158,4 +174,8 @@ def taking_ownership?
new_user_id = params.require(:assignment).require(:user_id)
new_user_id == @current_user.id.to_s
end

def generate_by_weekday_params
params.fetch(:assignment_weekday_generator, {}).permit!
end
end
74 changes: 74 additions & 0 deletions app/models/assignment/weekday_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

class Assignment < ApplicationRecord
class WeekdayGenerator
include ActiveModel::Model
include ActiveModel::Attributes

attribute :roster_id, :integer
attribute :user_id, :integer
attribute :start_date, :date
attribute :end_date, :date
attribute :start_weekday, :integer
attribute :end_weekday, :integer

validates :roster, presence: true
validates :user, presence: true
validates :start_date, presence: true
validates :end_date, presence: true, comparison: { greater_than_or_equal_to: :start_date }
validates :start_weekday, presence: true, numericality: { in: 0...7 }
validates :end_weekday, presence: true, numericality: { in: 0...7 }
werebus marked this conversation as resolved.
Show resolved Hide resolved

def roster
@roster ||= Roster.find_by(id: roster_id)
end

def user
@user ||= User.find_by(id: user_id)
end

def generate
generate!
true
rescue ActiveModel::ValidationError, ActiveRecord::RecordInvalid
false
end

def generate!
validate!
ActiveRecord::Base.transaction do
date_ranges.each do |range|
roster.assignments.create! user: user, start_date: range.begin, end_date: range.end
end
end
rescue ActiveRecord::RecordInvalid => e
errors.merge! e.record.errors
raise e
end

private

def date_ranges
Enumerator.new do |enum|
weeks.each do |sunday|
end_weekday_adjusted = end_weekday < start_weekday ? end_weekday + 7 : end_weekday
range_start = [start_date, sunday + start_weekday].max
range_end = [end_date, sunday + end_weekday_adjusted].min
next unless range_start <= range_end

enum.yield range_start..range_end
end
end
end

def weeks
Enumerator.new do |enum|
week = start_date.beginning_of_week(:sunday)
while week <= end_date.beginning_of_week(:sunday)
enum.yield week
week += 7
end
end
end
werebus marked this conversation as resolved.
Show resolved Hide resolved
end
end
27 changes: 27 additions & 0 deletions app/views/assignments/generate_by_weekday.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
%section.container.my-3
%h1 Generate by Weekday
%hr
= form_with model: @generator,
url: generate_by_weekday_submit_roster_assignments_path(@roster),
local: true do |f|
.form-group
= f.label :user_id
= f.collection_select :user_id, @roster.users.active.order(:last_name), :id, :last_name,
{}, required: true, class: 'custom-select'
.form-row
.form-group.col-md
= f.label :start_date
= f.date_field :start_date, class: 'form-control'
.form-group.col-md
= f.label :end_date
= f.date_field :end_date, class: 'form-control'
.form-row
.form-group.col-md
= f.label :start_weekday
= f.collection_select :start_weekday, Date::DAYNAMES, ->(day) { Date::DAYNAMES.index(day) }, :itself,
{}, required: true, class: 'custom-select'
.form-group.col-md
= f.label :end_weekday
= f.collection_select :end_weekday, Date::DAYNAMES, ->(day) { Date::DAYNAMES.index(day) }, :itself,
{}, required: true, class: 'custom-select'
= f.submit 'Generate', class: 'btn btn-primary'
9 changes: 7 additions & 2 deletions app/views/layouts/_nav.haml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@
= nav_link_item 'Manage Rosters', rosters_path
- if @current_user&.admin_in? @roster
= nav_link_item 'Manage Users', roster_users_path(@roster)
= nav_link_item 'Generate Rotation',
rotation_generator_roster_assignments_path(@roster)
%li.nav-item.dropdown
= link_to 'Generate', '#', role: 'button',
id: 'navbar-generate-nav-link', class: 'nav-link dropdown-toggle',
'data-toggle': 'dropdown', 'aria-expanded': 'false'
.dropdown-menu{ 'aria-labelledby': 'navbar-generate-nav-link' }
= link_to 'Rotation', rotation_generator_roster_assignments_path(@roster), class: 'dropdown-item'
= link_to 'By Weekday', generate_by_weekday_roster_assignments_path(@roster), class: 'dropdown-item'
%ul.navbar-nav
- if @current_user.present?
%li.nav-item.navbar-text.mx-2
Expand Down
9 changes: 9 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ en:
attributes:
user:
is_fallback: Fallback
activemodel:
errors:
models:
assignment/weekday_generator:
attributes:
end_date:
greater_than_or_equal_to: "must be on or after start date"
assignments:
update:
not_an_admin: 'You may only edit assignments such that you become on call.
Expand All @@ -45,3 +52,5 @@ en:
Or, a roster administrator can perform this change for you.'
destroy:
not_an_admin: 'Only roster admins may delete assignments.'
generate_by_weekday_submit:
success: "Assignments have been generated."
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
collection do
post :generate_rotation
get :rotation_generator
get :generate_by_weekday
post :generate_by_weekday_submit
end
end

Expand Down
Loading