Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Group reports#429

Merged
supriya3105 merged 14 commits intodevelopfrom
group-reports
Jun 7, 2022
Merged

Group reports#429
supriya3105 merged 14 commits intodevelopfrom
group-reports

Conversation

@shalapatil
Copy link
Contributor

@shalapatil shalapatil commented Jun 1, 2022

Notion card

Summary

https://www.notion.so/saeloun/Back-end-Groupby-on-Reports-Filter-150697fe97e14036aec0400e20be8e17

Preview

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to
    not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Checklist:

  • I have manually tested all workflows
  • I have performed a self-review of my own code
  • I have added automated tests for my code

Copy link
Contributor

@keshavbiswa keshavbiswa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! added minor comments.

end

def process
return {} if group_by_field.blank? || !POSSIBLE_GROUP_BY_INPUTS.include?(group_by_field)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return {} if group_by_field.blank? || !POSSIBLE_GROUP_BY_INPUTS.include?(group_by_field)
return {} if group_by_field.blank? || POSSIBLE_GROUP_BY_INPUTS.exclude?(group_by_field)

Comment on lines 23 to 27
# When we query ES, we get all matching timesheet entries as response even when we pass aggregation query.
# Those timesheet entries contains all required association but not the ones in aggregated data.
# So, in order to avoid queries for associated records,
# creating map of id -> timesheet entries from the general ES response and
# then using it for building final data by merging that with ids found in aggregation query.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add these comments outside the method?

Copy link
Contributor

@rohitjoshixyz rohitjoshixyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM
I liked how you have split the code into services, making it very clean and easy to grasp.

I understand the PR was complex and needed a lot of research but we would also want to have specs for each service you added and a request spec for the controller action to make the code foolproof.

Could you please also attach a loom video demonstrating the functionality?

Overall good job Shalaka. Well done 👏


scope :in_workspace, -> (company) { where(project_id: company&.project_ids) }

searchkick
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For aggregations to work you have to have filterable is searchkick

  searchable = %i[name]
  filterable = %[created_at]

  searchkick searchable: searchable, filterable: filterable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. With aggregation query which I am passing, aggregations are working fine


searchkick

def search_data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we individually list all the attributes we want to index?

For example

  def search_data
    {
      id: id.to_i,
      name: name,
      created_at: created_at.to_datetime
}
      

Reason for this is ES works on RAM, and unnecessary fields will clutter up the ES instance which becomes exponential over time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I was thinking of doing this but thought that fields are not that much so indexed everything. I will update code to index only required ones

filters_where_clause = Report::Filters.process(params)
where_clause = current_company_project_ids_filter.merge(filters_where_clause)
TimesheetEntry.search(where: where_clause, includes: [:user, :project])
group_by_clause = Report::GroupBy.process(params["group_by"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how GroupBy works, for grouping you can use aggregations, as in the SearchKick documentation:

Product.search("wingtips", where: {color: "brandy"}, aggs: [:size])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using aggregation only which is defined in the service class

Copy link
Contributor Author

@shalapatil shalapatil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rohitjoshixyz I can't add loom video as UI is broken and FE integration is required.

I am working on all the review comments now

Copy link
Contributor

@rohitjoshixyz rohitjoshixyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added few comments


require "rails_helper"

RSpec.describe "service::reports#group_by", type: :model do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type should be service

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

expect(reports["label"]).to eq("")
timesheet_ids_in_response = reports["entries"].pluck("id")
expect(reports["entries"].size).to eq(2)
# Timsheets should be in desceding order of work_date
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert in separate it block instead of a comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +49 to +53
@this_week_start_date = 0.weeks.ago.beginning_of_week
@this_week_end_date = 0.weeks.ago.end_of_week
@timesheet_entry1 = create(:timesheet_entry, project:, work_date: last_month_start_date)
@timesheet_entry2 = create(:timesheet_entry, project:, work_date: this_week_start_date)
@timesheet_entry3 = create(:timesheet_entry, project:, work_date: this_week_start_date)
@timesheet_entry2 = create(:timesheet_entry, project:, work_date: @this_week_start_date)
@timesheet_entry3 = create(:timesheet_entry, project:, work_date: @this_week_end_date)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use @ variables, use let instead

timesheet_ids_in_response = json_response["entries"].pluck("id")
expect(json_response["entries"].size).to eq(1)
reports = json_response["reports"].first
expect(reports["label"]).to eq("")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are we asserting here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want label empty when we grouping is not selected

Copy link
Contributor

@keshavbiswa keshavbiswa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments.

class GroupBy < ApplicationService
attr_reader :group_by_field

POSSIBLE_GROUP_BY_INPUTS = ["team_member", "client", "project", "week"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
POSSIBLE_GROUP_BY_INPUTS = ["team_member", "client", "project", "week"]
POSSIBLE_GROUP_BY_INPUTS = ["team_member", "client", "project", "week"].freeze

cc: @keshavbiswa @rohitjoshixyz

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@github-actions
Copy link

github-actions bot commented Jun 6, 2022

Current Code Coverage Percent of this PR:

84.72 %

Files having coverage below 100%

Impacted Files Coverage
/app/controllers/subscriptions_controller.rb 66.67 %
/app/controllers/invoices_controller.rb 57.14 %
/app/models/invoice.rb 96.3 %
/app/policies/client_policy.rb 95.45 %
/app/policies/invoice_policy.rb 94.12 %
/app/policies/subscriptions_policy.rb 66.67 %
/app/policies/timezone_policy.rb 66.67 %
/app/controllers/invoices/payments_controller.rb 61.11 %
/app/services/invoice_payment/checkout.rb 44.0 %
/app/services/invoice_payment/pdf_generation.rb 70.97 %
/app/services/report/filters.rb 87.1 %
/app/controllers/internal_api/v1/timezones_controller.rb 37.5 %
/app/controllers/internal_api/v1/clients_controller.rb 94.44 %
/app/controllers/internal_api/v1/invoices_controller.rb 94.87 %
/lib/benchmarking/benchmarker.rb 0.0 %
/lib/countries_info.rb 0.0 %

Copy link
Contributor

@rohitjoshixyz rohitjoshixyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shalapatil please add specs for filters and results service in a follow up PR so that our code coverage doesn't drop, other than that code LGTM. I am fine with keeping the @ variables for that one spec. cc @akhilgkrishnan @keshavbiswa .

Let's push this to production 🔥 if others do not object.

@supriya3105 supriya3105 merged commit d0b8845 into develop Jun 7, 2022
@supriya3105 supriya3105 deleted the group-reports branch June 7, 2022 08:11
vipulnsward pushed a commit that referenced this pull request Feb 15, 2026
* Index client_id to elasticsearch

* Use client id directly for filtering

* Add service class for creating group-by es query

* Add service class for processing aggregated ES data

* Consider group-by while showing reports

* Return formatted date labels for grouping by week

* Add sorting as desc order by work_date

* Add default filter of this_month duration

* Fix reports request tests

* Add specs for group_by service class

* Add request specs for group by but without any filters

* Add specs for group by and filter combinations

* Fix clients specs

* Fix suggested changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants