Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SECRET_KEY_BASE=
SENTRY_KEY=
SENDGRID_API_KEY=
HTTP_HOST=localhost:3000
RAILS_FORCE_SSL=false
RAILS_LOG_LEVEL=
WEB_PORT=3000
REDIS_PORT=6379
Expand Down
31 changes: 25 additions & 6 deletions app/controllers/api/v1/reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ module V1
class ReportsController < BaseController
def index
authorize!
scope = authorized_scope(TimeReg, type: :relation)
scope = scope.between_dates(params[:start_date], params[:end_date]) if params[:start_date] && params[:end_date]
scope = scope.by_clients(params[:client_ids]) if params[:client_ids]
scope = scope.by_projects(params[:project_ids]) if params[:project_ids]
scope = scope.by_users(params[:user_ids]) if params[:user_ids]
scope = scope.by_tasks(params[:task_ids]) if params[:task_ids]
scope = filtered_scope

@total_minutes = scope.sum(:minutes)
@total_entries = scope.count
Expand All @@ -23,6 +18,30 @@ def index
.group("users.id", "users.first_name", "users.last_name")
.select("users.id AS user_id, users.first_name, users.last_name, SUM(time_regs.minutes) AS total_minutes, COUNT(time_regs.id) AS total_entries")
end

def detailed
authorize!
entries = filtered_scope
.includes(:user, assigned_task: [ :task, { project: :client } ])
.order(date_worked: :desc, created_at: :desc)
.to_a

@total_minutes = entries.sum(&:minutes)
@total_billable_minutes = entries.select { |tr| tr.assigned_task.project&.billable }.sum(&:minutes)
@entries_by_date = entries.group_by(&:date_worked)
end

private

def filtered_scope
scope = authorized_scope(TimeReg, type: :relation)
scope = scope.between_dates(params[:start_date], params[:end_date]) if params[:start_date] && params[:end_date]
scope = scope.by_clients(params[:client_ids]) if params[:client_ids]
scope = scope.by_projects(params[:project_ids]) if params[:project_ids]
scope = scope.by_users(params[:user_ids]) if params[:user_ids]
scope = scope.by_tasks(params[:task_ids]) if params[:task_ids]
scope
end
end
end
end
24 changes: 24 additions & 0 deletions app/views/api/v1/reports/detailed.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
json.total_minutes @total_minutes
json.total_billable_minutes @total_billable_minutes

json.dates @entries_by_date do |date, time_regs|
json.date date
json.time_regs time_regs do |time_reg|
assigned_task = time_reg.assigned_task
project = assigned_task.project

json.id time_reg.id
json.date_worked time_reg.date_worked
json.minutes time_reg.minutes
json.notes time_reg.notes
json.user_id time_reg.user_id
json.user_name time_reg.user.name
json.client_name project.client&.name
json.project_id project&.id
json.project_name project&.name
json.project_billable project&.billable
json.task_name assigned_task.task&.name
json.rate assigned_task.rate.positive? ? assigned_task.rate : project.rate
json.billed_amount time_reg.billed_amount
end
end
2 changes: 1 addition & 1 deletion config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
# config.assume_ssl = true

# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
config.force_ssl = ENV.fetch("RAILS_FORCE_SSL", "true") == "true"

# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new(STDOUT)
Expand Down
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
get :me, on: :collection
end
resource :api_token, only: :update
resources :reports, only: %i[index]
resources :reports, only: %i[index] do
get :detailed, on: :collection
end
end
end

Expand Down
8 changes: 8 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ services:
condition: service_healthy
redis:
condition: service_started
env_file:
- path: .env
required: false
environment:
RAILS_ENV: production
DATABASE_URL: postgres://postgres:postgres@db:5432/stemplin_development
REDIS_URL: redis://redis:6379/0
SECRET_KEY_BASE: ${SECRET_KEY_BASE:-change_this_to_a_secure_secret_key}
HTTP_HOST: ${HTTP_HOST:-localhost:3000}
stdin_open: true
tty: true

Expand All @@ -52,11 +56,15 @@ services:
condition: service_healthy
redis:
condition: service_started
env_file:
- path: .env
required: false
environment:
RAILS_ENV: production
DATABASE_URL: postgres://postgres:postgres@db:5432/stemplin_development
REDIS_URL: redis://redis:6379/0
SECRET_KEY_BASE: ${SECRET_KEY_BASE:-change_this_to_a_secure_secret_key}
HTTP_HOST: ${HTTP_HOST:-localhost:3000}

volumes:
postgres_data:
Expand Down
31 changes: 31 additions & 0 deletions test/controllers/api/v1/reports_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,35 @@ class Api::V1::ReportsControllerTest < Api::V1::BaseTest
), headers: api_headers(@user)
assert_response :success
end

test "detailed returns entries grouped by date" do
get detailed_api_v1_reports_path, headers: api_headers(@user)
assert_response :success

assert json_response.key?("total_minutes")
assert json_response.key?("total_billable_minutes")
assert json_response.key?("dates")

first_date_group = json_response["dates"].first
assert first_date_group.key?("date")
assert first_date_group.key?("time_regs")

entry = first_date_group["time_regs"].first
assert entry.key?("id")
assert entry.key?("minutes")
assert entry.key?("user_name")
assert entry.key?("client_name")
assert entry.key?("project_name")
assert entry.key?("task_name")
assert entry.key?("rate")
assert entry.key?("billed_amount")
end

test "detailed filters by date range" do
get detailed_api_v1_reports_path(
start_date: 1.week.ago.to_date.to_s,
end_date: Date.today.to_s
), headers: api_headers(@user)
assert_response :success
end
end
Loading