Skip to content

Instantly share code, notes, and snippets.

@martink-io
Last active September 19, 2018 13:15
Show Gist options
  • Save martink-io/7a594b89c4fa4348b84bb4e4fec7983b to your computer and use it in GitHub Desktop.
Save martink-io/7a594b89c4fa4348b84bb4e4fec7983b to your computer and use it in GitHub Desktop.
module AdminCommand
module Jobs
class Assign < BaseCommand
include Concerns::Common::Collection
include Concerns::Common::WithUser
include Concerns::Jobs::GuardFilters
GUARD_ERROR = "Error: Job Is Already Filled"
LICENCE_ERROR ="Error: Guard Has Unmet Licence Requirements"
# TODO: Revisit guard_job creation and relations.
# TODO: Handle errors.
def call
guard_ids = params[:guard_ids].split(',')
params[:job] = job
params[:guard] = guard
ActiveRecord::Base.transaction do
if job.unfilled? && are_guard_licences_active?
job.assign! do
job.guard_jobs.each do |guard_job|
guard_id = guard_ids.pop
raise ActiveRecord::Rollback unless guard_id && guard_job.guard_id.blank?
guard_job.update!(guard_id: guard_id)
JobMailer.job_assigned_email(job, guard_job.user).deliver_later
end
end
else
job.assign_error = job.unfilled? ? LICENCE_ERROR : GUARD_ERROR
end
end
job
end
def job
@job ||= Job.find(params[:job_id])
end
def guard
@guard ||= User.find(params[:guard_ids].split(',')).first
end
end
end
end
module Concerns
module Jobs
module GuardFilters
extend ActiveSupport::Concern
included do
def apply_filters(jobs)
jobs = licence_ids_query(jobs)
if jobs.present?
jobs = order_query(jobs)
jobs = within_distance_query(jobs)
jobs = state_query(jobs)
jobs = specific_date_query(jobs)
jobs = date_range_query(jobs)
jobs = free_text_query(jobs)
jobs.page(page)
.per_page(per_page)
.includes(:job_licences, :client, :guard_jobs, job_licences: :licence)
end
end
def apply_stats_filters(jobs)
jobs = state_query(jobs)
jobs = specific_date_query(jobs)
jobs = date_range_query(jobs)
end
def order_query(jobs)
return jobs unless params[:order]
jobs.order(params[:order])
end
def within_distance_query(jobs)
return jobs if place.blank? || !is_uk_postcode?
jobs_in_range = Job.within(guard_profile.distance_to_travel, origin: place).select([:id])
jobs.where(id: jobs_in_range).order(Job.distance_sql(place))
end
def licence_ids_query(jobs)
licence_ids_param = params[:licence_ids]
return [] if params[:job_state] == 'unfilled' && licence_ids_param.blank?
return jobs unless licence_ids_param.present?
licence_ids = licence_ids_param.is_a?(Array) ? licence_ids_param : licence_ids_param.split(',')
job_ids_by_licence = licence_ids.map do |licence_id|
JobLicence.where(licence_id: licence_id).pluck(:job_id)
end
# matching_job_ids = job_ids_by_licence.each_with_object(job_ids_by_licence.first) do |job_ids, matched_ids|
# matched_ids &= job_ids
# end
uniq_job_ids = job_ids_by_licence.flatten.uniq
jobs.where(id: uniq_job_ids)
end
def state_query(jobs)
return jobs unless params[:job_state].present?
return jobs.by_state(Job::CANCELLED_STATES) if params[:job_state] == 'cancelled'
return jobs.by_state(params[:job_state].split(',')) unless params[:job_state] == 'cancelled'
end
def free_text_query(jobs)
return jobs unless params[:query].present?
jobs.by_client(params[:query])
end
def specific_date_query(jobs)
return jobs unless params[:specific_date].present?
specific_date = Time.parse(params[:specific_date])
jobs = jobs.starting_after(specific_date.beginning_of_day)
.starting_before(specific_date.end_of_day)
end
def date_range_query(jobs)
return jobs unless params[:from_date].present? && params[:to_date].present?
from_date = Time.parse(params[:from_date])
to_date = Time.parse(params[:to_date])
jobs = jobs.starting_after(from_date.beginning_of_day)
.ending_before(to_date.end_of_day)
end
def matching_guard_licence_ids(job)
return [] unless job.guards.any?
job_licence_ids = job.job_licences.pluck(:licence_id)
# TODO: Change to take into consideration multiple guards
job.guards.first.guard_licences.where(licence_id: job_licence_ids).pluck(:id)
end
private
def place
@place ||= params[:place] if params[:place].present?
end
def guard_profile
@guard_profile ||= params[:guard_profile]
end
def is_uk_postcode?
return false unless guard_profile.present?
UKPostcode.parse(guard_profile.postcode).full_valid?
end
def are_guard_licences_active?
guard_licences_ids.each do |guard_licence_id|
return false if licence_check(guard_licence_id).status != 'active'
end
guard_licences_ids.blank? ? false : true
end
# GuardLicences IDs for all selected guards to be assigned (admin actor)
# GuardLicences IDs for current guard to accept the job (guard actor)
def guard_licences_ids
return [] unless params[:guard].present? && params[:job].present?
job_licence_ids = params[:job].job_licences.pluck(:licence_id)
guard_licences = params[:guard].guard_licences.where('status_changed_at > ?', 24.hours.ago)
guard_licences.where(licence_id: job_licence_ids).pluck(:id)
end
def licence_check(guard_licence_id)
LicenceCommand::VerifyGuardLicence.call(guard_licence_id: guard_licence_id)
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment