Skip to content

Instantly share code, notes, and snippets.

@anjanaraveendra
Last active January 17, 2017 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anjanaraveendra/c8e7110a574ddb5e33d87a2c027b1a92 to your computer and use it in GitHub Desktop.
Save anjanaraveendra/c8e7110a574ddb5e33d87a2c027b1a92 to your computer and use it in GitHub Desktop.
#SurveyController Class
class Api::V1::SurveysController < Api::V1::BaseController
before_action :set_survey, only: [:show, :questions]
def index
# Api to get all current user schedules for the current time
@schedules = @account.schedules.includes(:survey, survey_version: :departments).joins(:survey)
.where(surveys: { status: 1 }, completed_at: nil).where(ignore: false)
.where('schedules.start_time <= :time AND schedules.buffer_time >= :time', time: Time.current)
.order('schedules.start_time asc')
end
def reminder
# Api to Remind for Survey Completion
@schedules = @account.schedules.includes(:survey, :survey_version).joins(:survey)
.where(surveys: { status: 1 }, completed_at: nil).where(ignore: false).where.not(survey_versions: { notify_time: 0 })
.where(schedules: { notify_time: Time.current.beginning_of_day..Time.current.end_of_day })
.order('schedules.notify_time asc')
end
def history
# Survey listing for a day and status
@schedules = @account.schedules.includes(:survey, :survey_version).where(ignore: false)
.where(completed_at: Time.current.beginning_of_day..Time.current.end_of_day)
end
def history_show
# Pick a survey from history to get survey details
schedule = Schedule.find(params[:id])
@survey = schedule.survey
if !schedule.completed_at.nil?
@answers = schedule.answers.group_by(&:question_id)
else
render json: { code: 404, status: 'not_found', payload: {}, errors: ['Survey not found'] }
end
end
def survey_details
# Details and Listing of all schedules for the user
@schedule = Schedule.includes(:survey_version).find(params[:id])
@questions = (@schedule.survey_version.questions.order('created_at ASC') + Incident.default_questions) unless @schedule.survey_version.disable_default_questions
@questions = @schedule.survey_version.questions.order('created_at ASC') if @schedule.survey_version.disable_default_questions
@staffs = @account.organization.accounts
@departments = @account.organization.departments
end
def departments
# Api to retrieve departments
render json: { departments: @account.organization.departments.pluck(:id, :name) }
end
private
def set_survey
@survey = Survey.find(params[:id])
end
end
# == Schema Information
#
# Table name: surveys
#
# id :integer not null, primary key
# status :integer
# account_id :integer
# drafted_at :datetime
# published_on :datetime
# unpublished_on :datetime
# suspended_on :datetime
# archived_on :datetime
# marked_as :integer
# version_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# questions_count :integer default(0)
# organization_id :integer
#
# Indexes
#
# index_surveys_on_organization_id (organization_id)
#
# Foreign Keys
#
# fk_rails_2c8e32429d (organization_id => organizations.id)
#
class Survey < ActiveRecord::Base
has_many :email_notifications, as: :item
belongs_to :version, class_name: 'SurveyVersion', foreign_key: 'version_id'
belongs_to :department
belongs_to :account
belongs_to :organization
has_many :survey_versions, dependent: :destroy
has_many :completed_surveys, dependent: :destroy
has_many :schedules, dependent: :destroy
enum status: %w(draft published suspended archived)
accepts_nested_attributes_for :survey_versions
def publish!
update_attributes(status: 1, published_on: Time.current, suspended_on: nil, archived_on: nil)
version.update_attribute(:unpublished_at, nil)
version.schedule!
end
def suspend!
update_attributes(status: 2, suspended_on: Time.current)
version.update_attribute(:unpublished_at, Time.current)
version.remove_future_schedules!
end
end
# == Schema Information
#
# Table name: survey_versions
#
# id :integer not null, primary key
# name :string
# start_time :datetime
# end_time :datetime
# is_recurring :boolean
# every :integer
# interval :integer
# recurs_on :text default([]), is an Array
# end_after :integer
# recurring_end_date :datetime
# survey_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# questions_count :integer default(0)
# unpublished_at :datetime
# disabled_at :datetime
# notify_time :integer default(0)
# buffer_time :integer default(0)
# timezone :string
# disable_default_questions :boolean default(FALSE)
#
class SurveyVersion < ActiveRecord::Base
after_save :update_current_version_id
belongs_to :survey
belongs_to :account
has_many :survey_version_accounts, dependent: :destroy
has_many :questions, dependent: :destroy
has_many :accounts, -> { distinct }, through: :survey_version_accounts
has_many :department_survey_versions, dependent: :destroy
has_many :departments, -> { distinct }, through: :department_survey_versions
has_many :questions
has_many :sections, dependent: :destroy
has_many :schedules, dependent: :destroy
enum every: %w(day week month year hour minute)
def self.notify
[['Do not notify', 0], ['15 minutes', 15], ['30 minutes', 30], ['45 minutes', 45], ['1 hour', 60]]
end
def self.buffer
[
['No buffer', 0], ['15 minutes', 15], ['30 minutes', 30], ['45 minutes', 45],
['1 hour', 60], ['1 hour and 15 minutes', 75], ['1 hour and 30 minutes', 90],
['1 hour and 45 minutes', 105], ['2 hours', 120]
]
end
# validate :start_date_cant_be_today
validate :start_time_cant_be_past
validate :end_must_be_greater_than_start
validate :end_should_be_same_date_as_start
validates :end_after, numericality: true, allow_nil: true
# validate :validate_department_presence
validates_presence_of :name, :start_time, :end_time, message: 'required'
validate :validate_weekly
validate :recurring_end_date_than_end
validate :occurance_should_be_greater_than_one
def schedule!
survey.reload
ScheduleService.new(self).this_week.each do |schedule|
next if survey.published_on.nil?
accounts.each do |account|
Schedule.find_or_create_by(schedule.merge(survey_id: survey_id, survey_version_id: id, account_id: account.id))
end
end
end
def remove_future_schedules!
schedules.where('start_time >= ?', Time.current.beginning_of_day)
.where(completed_at: nil).where(ignore: false)
.destroy_all
end
private
def validate_weekly
if week? && recurs_on.empty?
errors.add(:recurs, 'select atleast one weekday')
end
end
def start_time_cant_be_past
if !start_time.blank? && start_time.in_time_zone(timezone) < Time.current.in_time_zone(timezone)
errors[:start_time] = 'can\'t be past'
end
end
def start_date_cant_be_today
return if start_time.blank?
if start_time.in_time_zone(timezone).to_date <= Date.today
errors[:start_time] = 'should be greater than today'
end
end
def end_must_be_greater_than_start
return if start_time.blank? && end_time.blank?
if start_time.in_time_zone(timezone) >= end_time.in_time_zone(timezone)
errors[:end_time] = 'should be greater than start time'
end
end
def end_should_be_same_date_as_start
return if start_time.blank? || end_time.blank? || start_time.in_time_zone(timezone) >= end_time.in_time_zone(timezone)
unless start_time.in_time_zone(timezone).to_date == end_time.in_time_zone(timezone).to_date
errors[:end_time] = 'should be same day as start day'
end
end
def occurance_should_be_greater_than_one
if end_after.present? && end_after < 1
errors.add(:end_after, 'should be greater than 0')
end
end
def recurring_end_date_than_end
return if start_time.blank? || end_time.blank? || recurring_end_date.blank?
if recurring_end_date.in_time_zone(timezone) <= end_time.in_time_zone(timezone)
errors.add(:recurring_end_date, 'should be greater than end time')
end
end
def update_current_version_id
survey.update_attribute(:version_id, id)
end
def validate_department_presence
errors.add(:department_ids, 'required') if departments.blank?
end
extend ActiveSupport::Concern
included do
amoeba do
include_association :questions
include_association :accounts
include_association :survey_version_accounts
end
end
end
#TaskController Class
class Api::V1::TasksController < Api::V1::BaseController
def create
@task = @account.tasks.new(task_params)
authorize @task
#If there is a safety_issue, send out an email
if @task.save
if @task.task_type == 'safety_issue'
@leads = @task.department.department_leads + @organization.executives
@leads.each do |lead|
ApplicationMailer.safety_issue_email(lead).deliver_now
end
end
render json: { status: 200, message: 'Task was successfully created' }
else
# Task validation errors response if task object fails to create.
render json: { messages: @task.errors.full_messages, status: :unprocessable_entity }
end
end
def show
if params[:task_status_id].present?
# Task Status response
@task_status = @account.task_statuses.find(params[:task_status_id])
else
# Task Object response
@task = @account.tasks.find(params[:id]) if params[:task_status_id].nil?
end
end
def created_tasks
# Listing of Tasks created by current user
@tasks = @account.tasks.includes(:task_statuses).order(updated_at: :desc)
.paginate(page: (params[:page] || 1), per_page: (params[:per_page] || 10))
end
def assigned_tasks
# Listing of tasks assigned to current user
@tasks = @account.task_statuses.where(status: [0, 1]).order(updated_at: :desc)
.paginate(page: (params[:page] || 1), per_page: (params[:per_page] || 10))
end
def open
# Api to change Task status to open
@task_status = @account.task_statuses.find(params[:task_status_id])
authorize @task_status
if @task_status.open!
render json: { status: 200, message: 'Successfully opened' }
else
render json: { messages: @task_status.task.errors.full_messages, status: :unprocessable_entity }
end
end
def accept
# Api to change Task status to accept
@task_status = @account.task_statuses.find(params[:task_status_id])
authorize @task_status
# Send emails to Department Leads & Executive after task accept
if @task_status.accept!
department_leads = @task_status.task.department.department_leads
department_leads.each do |department_lead|
ApplicationMailer.accept_task(department_lead, @task_status, @account).deliver_now
end
render json: { status: 200, message: 'Successfully acccepted' }
else
render json: { messages: @task_status.task.errors.full_messages, status: :unprocessable_entity }
end
end
def reassign
# Api to handle task re-assignment
@task_status = @account.task_statuses.find(params[:task_status_id])
authorize @task_status # Check current user role, allow only if role is Department-Lead/ Executive
if @task_status.task.reassign!(params[:assigned_to])
render json: { status: 200, message: 'Successfully reassigned the task status' }
else
render json: { messages: @task_status.task.errors.full_messages, status: :unprocessable_entity }
end
end
def complete
# Api to change task status to complete
@task_status = @account.task_statuses.find(params[:task_status_id])
authorize @task_status # Check current user role, allow only if role is Department-Lead/ Executive
if @task_status.close!
render json: { status: 200, message: 'Successfully completed' }
else
render json: { messages: @task_status.task.errors.full_messages, status: :unprocessable_entity }
end
end
def departments
# Listing all departments from current user's organization
@departments = @account.organization.departments
render json: { departments: @departments }
end
def department_users
# Get all users from selected departments(params[:ids])
ids = JSON.parse(params[:ids]) # ids parsing handled from backend
@accounts = Account.includes(:departments).where(departments: { id: ids }).to_a
@accounts.delete(@account)
render json: { accounts: @accounts }
end
def user_departments
# Listing all departments where current user is part of
@user_departments = @account.departments
render json: { user_departments: @user_departments }
end
def update
# Task PATCH Api
@task = Task.find(params[:id])
authorize @task
if @task.update(task_update_params)
render json: { status: 201, message: 'Your task was successfully updated' }
else
render json: { messages: @task.error.full_messages, status: 'unprocessable_entity' }
end
end
def destroy
# Deleting of a task
@task = Task.find(params[:id])
authorize @task
if @task.destroy
render json: { status: 204, message: 'Task was deleted successfully' }
else
render json: { messages: @task.error.full_messages, status: 'Task could not be deleted' }
end
end
private
def pundit_user
# Setting @account with role checks
@account
end
def task_params
task_statuses = []
if @account.type == 'User::User'
department_leads = Department.find(params[:task][:department_id]).department_leads
department_leads.each { |ac| task_statuses << { account_id: ac.id, created_by: @account.id } }
else
params[:task][:assigned_to].each { |ac| task_statuses << { account_id: ac, created_by: @account.id } }
end
# Params beautify
params[:task][:task_statuses_attributes] = task_statuses
params[:task][:organization_id] = @account.organization_id
params[:task][:task_type] = params[:task][:type] if params[:task][:type].present?
params.require(:task).permit(:name, :description, :department_id, :question_id, :organization_id, :end_time, :category, :task_type, task_list: [], task_statuses_attributes: [:account_id, :created_by])
end
def task_update_params
# Update Task Beautify params
params[:task][:task_statuses_attributes].each { |ts| ts[:created_by] = @account.id }
params.require(:task).permit(:id, :name, :description, :department_id, :question_id, :category, :end_time, :task_type, task_list: [], task_statuses_attributes: [:id, :account_id, :created_by, :_destroy])
end
end
# == Schema Information
#
# Table name: tasks
#
# id :integer not null, primary key
# name :string
# description :text
# department_id :integer
# account_id :integer
# question_id :integer
# organization_id :integer
# task_list :text default([]), is an Array
# created_at :datetime not null
# updated_at :datetime not null
# task_type :integer default(0)
# end_time :datetime
# category :integer
#
# Indices
#
# index_tasks_on_account_id (account_id)
# index_tasks_on_department_id (department_id)
# index_tasks_on_organization_id (organization_id)
# index_tasks_on_question_id (question_id)
#
# Foreign Keys
#
# fk_rails_9d303107ad (question_id => questions.id)
# fk_rails_a0db1d9e05 (department_id => departments.id)
# fk_rails_c8d7e9affa (account_id => accounts.id)
#
# fk_rails_46f8d59d15 (question_id => questions.id)
# fk_rails_64f216c611 (account_id => accounts.id)
# fk_rails_792c09d6bc (department_id => departments.id)
#
class Task < ActiveRecord::Base
belongs_to :question
belongs_to :account
belongs_to :department
belongs_to :organization
has_many :task_statuses, dependent: :destroy
accepts_nested_attributes_for :task_statuses, allow_destroy: true
enum task_type: %w(normal process_improvement safety_issue)
# enum category: %w(accident surgery emergency po mm rm infec_control enviro_serv med_rec lab imaging adm med_surg ob icu o)
enum category: %w(financial_and_growth quality_and_safety people_and_service)
validates :name, :description, presence: true
# validates :task_list, presence: true, unless: Proc.new { |task| task.process_improvement? }
def reassign!(assign_to)
existing_ids = task_statuses.pluck(:account_id)
# Add new users
(assign_to - existing_ids).each do |u|
task_statuses.create(account_id: u)
end
# Remove old users
(existing_ids - assign_to).each do |u|
task_statuses.find_by_account_id(u).destroy
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment