Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4033 product drives filter by category #4094

Merged

Conversation

PhantomSean
Copy link
Contributor

Resolves #4033

Description

Added new filter to the product drive page. This allows for filtration by item category. Made adjustments to the functions that display donation quantities and distinct item counts to return correct figures for when item category is chosen.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Visual Test:

  1. Login as organization admin.
  2. Go to the product drive page.
  3. Select an item category from the drop down menu.
  4. Apply the filter.
  5. Confirm product drive are filtered correctly and that donation quantities and distinct item counts are correct.

Rspec Tests:
Added testing to spec/models/product_drive_spec.rb to confirm that

  1. All donated organization item quantities by category and date are correctly calculated and returned.
  2. All distinct donated organization items belonging to a given category are correctly counted and returned.
  3. Filter by_item_category_id works as expected.

Screenshots

Before:
image

After:
image

@@ -6,10 +6,13 @@ def index
setup_date_range_picker
@product_drives = current_organization
.product_drives
.includes(donations: [line_items: [:item]])
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a weird syntax... I'd assume it should look like donations: {line_items: :item}. Not even sure how this parses 😮

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Functionally they create the same SQL query but describe the associations using arrays vs using a hash as you have.

I've changed it as you suggested as it probably is better to have it described as a hash and it a bit more readable.

@@ -18,6 +18,7 @@ class ProductDrive < ApplicationRecord
include Filterable

scope :by_name, ->(name_filter) { where(name: name_filter) }
scope :by_item_category_id, ->(item_category_id) { joins(donations: [line_items: [:item]]).where(item: { item_category_id: item_category_id }) }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this line be split? Kinda long.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure

.during(date_range)
.sum('line_items.quantity')
def donation_quantity_by_date(date_range, item_category_id = nil)
if [nil, ''].include? item_category_id
Copy link
Collaborator

Choose a reason for hiding this comment

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

More Rails-y: if item_category_id.blank? Better yet, use present? and switch the conditional so the positive condition comes first.

.where(item: {item_category_id: item_category_id})
.during(date_range)
.sum('line_items.quantity')
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

I usually try to build the query rather than copy the lines. So I'd write this thusly:

query = donations.during(date_range)
if item_category_id.present?
  query = query.joins(line_items: :item).where(item: {item_category_id: item_category_id})
else
  query = query.joins(:line_items)
end
query.sum('line_items.quantity') 

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, that's a lot cleaner

donations.joins(line_items: [:item])
.where(item: {item_category_id: item_category_id})
.during(date_range)
.select('line_items.item_id').distinct.count
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above.

Copy link
Collaborator

Choose a reason for hiding this comment

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

See above comment, can this be built reusing the parts that are common to both conditions?

it "calculates and returns all donated organization item quantities by category and date" do
create(:donation, :with_items, item_quantity: 2, product_drive: product_drive, issued_at: '26-01-2023')
result = product_drive.donation_quantity_by_date(Time.zone.parse('23/01/2023')..Time.zone.parse('26/01/2023'), 1)
expect(result).to eq product_drive.organization.items.where(item_category_id: 1).count
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a bit too finicky IMO. I'd actually create an item with the desired item category and verify that it comes back in the query. Otherwise we could just not have any data in there and it comes back empty... but we wouldn't know if it was empty because there was no data, or because there's an error in our query. In general for things like this you'll want at least one result that should be included and one that shouldn't, and verify that only the one you want comes back.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good feedback, I've created two items with unique category ids and have the test verifying the one we want comes back

Copy link
Collaborator

@dorner dorner left a comment

Choose a reason for hiding this comment

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

One last nitpick and then I think this is good to go!

donations.joins(line_items: [:item])
.where(item: {item_category_id: item_category_id})
.during(date_range)
.select('line_items.item_id').distinct.count
Copy link
Collaborator

Choose a reason for hiding this comment

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

See above comment, can this be built reusing the parts that are common to both conditions?

@PhantomSean
Copy link
Contributor Author

One last nitpick and then I think this is good to go!

Sorry missed that one! Should be sorted now 😄

@PhantomSean
Copy link
Contributor Author

Seems as though there appears to be a flaky test case in spec/system/manufacturer_system_spec.rb:51 that caused the following timeout failure

Failures:

  1) Manufacturer allows a user to update a manufacturer with empty attributes
     Failure/Error: raise TimeoutError unless data

     Ferrum::TimeoutError:
       Timed out waiting for response. It's possible that this happened because something took a very long time (for example a page load was slow). If so, setting the :timeout option to a higher value might help.

Not sure if this a known issue.
see https://github.com/rubyforgood/human-essentials/actions/runs/8059102112/job/22012957655 for full log

And another flaky test in ./spec/system/distribution_system_spec.rb:111 but I believe this was confirmed to be a known issue based on the conversation here and that there is a fix on another branch

@dorner
Copy link
Collaborator

dorner commented Feb 27, 2024

Yep, does look flaky. Re-ran it and it passed. The other one should be fixed on the main branch.

Copy link
Collaborator

@dorner dorner left a comment

Choose a reason for hiding this comment

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

Looks good - thank you!

@dorner dorner merged commit 03dc9cc into rubyforgood:main Feb 27, 2024
19 checks passed
@PhantomSean
Copy link
Contributor Author

Looks good - thank you!

No problem, thanks for all the good feedback!

Copy link
Contributor

github-actions bot commented Mar 3, 2024

@PhantomSean: Your PR 4033 product drives filter by category is part of today's Human Essentials production release: 2024.03.03.
Thank you very much for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Product Drives -- allow filtration by category
2 participants