Users (Basic) Time Sheets (Advanced) Issues (API)

Developer Project Company Report hours
Eleonore Wisozk doloribus hic corporis
Microsoft
96.0
Wiley Wuckert animi aperiam tenetur
Google
96.0
Myrtle O'Conner perspiciatis totam perferendis
Apple
97.0
Nelson Leannon perspiciatis totam perferendis
Apple
98.0
Kaye Greenfelder perspiciatis totam perferendis
Apple
98.0
Felisa Jaskolski vitae eum pariatur
Google
98.0
Rossana Schneider quibusdam sed sit
Apple
99.0
Wiley Wuckert suscipit consectetur beatae
Google
99.0
Desmond Murray eum amet quia
Google
99.0
Treena Wolf saepe hic temporibus
Microsoft
100.0
Gwendolyn Satterfield suscipit consectetur beatae
Google
100.0
Micheal Jenkins saepe hic temporibus
Microsoft
100.0
Milagros Lemke odio velit repudiandae
Apple
100.0
Terisa Ruecker perspiciatis totam perferendis
Apple
100.0
Sixta Bashirian vitae eum pariatur
Google
100.0
Pearlie McGlynn suscipit consectetur beatae
Google
101.0
Elise Waelchi animi aperiam tenetur
Google
102.0
Desmond Murray quibusdam sed sit
Apple
102.0
Alex Legros saepe hic temporibus
Microsoft
102.0
Lesia Hyatt saepe hic temporibus
Microsoft
103.0
Johnny Spinka suscipit consectetur beatae
Google
103.0
Kaye Greenfelder suscipit consectetur beatae
Google
104.0
Shane Glover eum amet quia
Google
104.0
Myriam Von suscipit consectetur beatae
Google
104.0
Johnny Spinka vitae eum pariatur
Google
105.0

Grid:

class TimeEntriesGrid < ApplicationGrid

  #
  # Scope
  #

  scope do
    User.select(
      "users.name",
      "projects.name as project_name",
      "accounts.name as account_name",
      "sum(time_entries.hours) as report_hours"
    ).joins(
      time_entries: {project: :account}
    ).group("projects.name", "users.name", "accounts.name").
    order("users.name")
  end


  #
  # Filters
  #

  filter(
    :project_id, :enum,
    :select => :project_id_select,
    :multiple => true,
    :include_blank => false
  ) do |value|
    self.where(:time_entries => {:project_id => value})
  end


  filter(
    :year, :enum,
    :select => :year_select,
    :include_blank => false,
    :default => lambda {Date.today.year}
  ) do |value|
    self.where([
      "extract(year from time_entries.date) = ?",
      value.to_i
    ])
  end

  filter(
    :month, :enum,
    :select => :month_select,
    :include_blank => false,
    :default => lambda {Date.today.month}
  ) do |value|

    self.where([
      "extract(month from time_entries.date) = ?",
      value.to_i
    ])
  end


  #
  # Columns
  #

  column(:user_name, :header => "Developer", :order => "users.name") do
    self.name
  end
  column(:project_name, :header => "Project", :order => "projects.name")
  column(
    :account_name,
    :header => "Company",
    :order => "accounts.name",
  ) do |model|
    format(model.account_name) do
      render :partial => "time_entries/company", :locals => {:model => model}
    end
  end

  column(:report_hours, order: "sum(time_entries.hours)")

  protected

  def year_select
    TimeEntry.all.any? ? (TimeEntry.minimum(:date).year..TimeEntry.maximum(:date).year) : []
  end
  def month_select
    Date::MONTHNAMES[1..12].enum_for(:each_with_index).collect {|name, index| [name, index + 1]}
  end

  def project_id_select
    Project.all.map {|p| [p.name, p.id]}
  end
end

Controller:

class TimeEntriesController < ApplicationController

  def index
    @time_entries_grid = TimeEntriesGrid.new(params[:g]) do |scope|
      scope.page(params[:page] )
    end
  end
end

View:

.grid-index-grid
  %div{class: 'overflow-x-auto p-4'}
    = datagrid_form_with model: @time_entries_grid, url: time_entries_path
    %br/
    = datagrid_table(@time_entries_grid)
    = paginate @time_entries_grid.assets, window: 2
  %div
    = render :partial => "shared/source", :object => @time_entries_grid