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

4513 incontinence supplies #4794

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1d93dcd
Begin working calculations for new feild addtions for report and upda…
jadekstewart3 Oct 29, 2024
7ec4f2d
Created kits in spec to ensure report values update with kit creation…
jadekstewart3 Nov 20, 2024
607bec6
Update total_people_served_with_supplies_from_kits_per_month as descr…
jadekstewart3 Nov 27, 2024
ffa5b51
Remove commented text
jadekstewart3 Nov 27, 2024
fb68000
Modify calculation for adults served to ensure accurate values
jadekstewart3 Dec 11, 2024
28aa472
Evaluate how monthly supplies is calculated and modify to produce mor…
jadekstewart3 Dec 11, 2024
062d5a6
Merge branch 'main' of github.com:jadekstewart3/human-essentials into…
jadekstewart3 Dec 12, 2024
203730e
Update spec to passing, still working on identifying where service is…
jadekstewart3 Dec 12, 2024
a8816a0
rubocop
jadekstewart3 Dec 12, 2024
ac49fe5
Modify total_people_served_with_supplies_from_kits_per_month and tota…
jadekstewart3 Dec 16, 2024
fca526d
Modify kit item test set up, and add kits to endure calculations are …
jadekstewart3 Dec 16, 2024
a3b1155
Re-work kit test set up
jadekstewart3 Dec 16, 2024
ac542f8
Remove trailing whitespace
jadekstewart3 Dec 16, 2024
8a61604
rubocop
jadekstewart3 Dec 16, 2024
a0270f9
Fix oversight in distributed_adult_incontinence_items_from_kits, and …
jadekstewart3 Dec 19, 2024
c2f90ad
Modify how we calculate total_people_served_with_supplies_from_kits_p…
jadekstewart3 Dec 20, 2024
1fac9db
rubocop
jadekstewart3 Dec 20, 2024
b55672e
Create additional test to confirm functionality of distributed_adult_…
jadekstewart3 Jan 2, 2025
e2c41a6
Fixed test set up including kit containing wipes, correct amount of d…
jadekstewart3 Jan 2, 2025
15c7c84
Fix spacing per rubocop
jadekstewart3 Jan 2, 2025
91b7f16
Adjust methods to calculate monthly values, and correct test expectat…
jadekstewart3 Jan 2, 2025
2b17110
Fix test set up to manually create objects and bypass factory creatio…
jadekstewart3 Jan 29, 2025
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
77 changes: 65 additions & 12 deletions app/services/reports/adult_incontinence_report_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ def initialize(year:, organization:)
def report
@report ||= { name: 'Adult Incontinence',
entries: {
'Adult incontinence supplies distributed' => number_with_delimiter(distributed_supplies),
'Adult incontinence supplies per adult per month' => monthly_supplies&.round || 0,
'Adult incontinence supplies distributed' => number_with_delimiter(distributed_loose_supplies + distributed_adult_incontinence_items_from_kits),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this not total_supplies_distributed?

'Adults Assisted Per Month' => adults_served_per_month.round,
'Adult incontinence supplies per adult per month' => supplies_per_adult_per_month.round,
'Adult incontinence supplies' => types_of_supplies,
'% adult incontinence supplies donated' => "#{percent_donated.round}%",
'% adult incontinence bought' => "#{percent_bought.round}%",
Expand All @@ -24,7 +25,7 @@ def report
end

# @return [Integer]
def distributed_supplies
def distributed_loose_supplies
@distributed_supplies ||= organization
.distributions
.for_year(year)
Expand All @@ -34,16 +35,16 @@ def distributed_supplies
end

# @return [Integer]
def total_supplies_distributed
distributed_loose_supplies + distributed_adult_incontinence_items_from_kits
end

def monthly_supplies
# NOTE: This is asking "per adult per month" but there doesn't seem to be much difference
# in calculating per month or per any other time frame, since all it's really asking
# is the value of the `distribution_quantity` field for the items we're giving out.
organization
.distributions
.for_year(year)
.joins(line_items: :item)
.merge(Item.adult_incontinence)
.average('COALESCE(items.distribution_quantity, 50)')
total_supplies_distributed / 12.0
end

def supplies_per_adult_per_month
monthly_supplies / (adults_served_per_month.nonzero? || 1)
end

def types_of_supplies
Expand Down Expand Up @@ -91,5 +92,57 @@ def donated_supplies
.where(itemizable: organization.donations.for_year(year))
.sum(:quantity)
end

def distributed_adult_incontinence_items_from_kits
organization_id = @organization.id
year = @year

sql_query = <<-SQL
SELECT SUM(line_items.quantity * kit_line_items.quantity)
FROM distributions
INNER JOIN line_items ON line_items.itemizable_type = 'Distribution' AND line_items.itemizable_id = distributions.id
INNER JOIN items ON items.id = line_items.item_id
INNER JOIN kits ON kits.id = items.kit_id
INNER JOIN line_items AS kit_line_items ON kits.id = kit_line_items.itemizable_id
INNER JOIN items AS kit_items ON kit_items.id = kit_line_items.item_id
INNER JOIN base_items ON base_items.partner_key = kit_items.partner_key
WHERE distributions.organization_id = ?
AND EXTRACT(year FROM issued_at) = ?
AND LOWER(base_items.category) LIKE '%adult%'
AND NOT (LOWER(base_items.category) LIKE '%cloth%' OR LOWER(base_items.name) LIKE '%cloth%')
AND kit_line_items.itemizable_type = 'Kit';
SQL
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should not be excluding cloth (Adult Cloth Diapers count as AI) and should be excluding wipes. See Item.adult_incontinence.


sanitized_sql = ActiveRecord::Base.send(:sanitize_sql_array, [sql_query, organization_id, year])

result = ActiveRecord::Base.connection.execute(sanitized_sql)

result.first['sum'].to_i
end

def adults_served_per_month
total_people_served_with_loose_supplies_per_month + total_people_served_with_supplies_from_kits_per_month
end

def total_people_served_with_loose_supplies_per_month
total_quantity = organization
.distributions
.for_year(year)
.joins(line_items: :item)
.merge(Item.adult_incontinence)
.sum('line_items.quantity / COALESCE(items.distribution_quantity, 50)')
total_quantity / 12.0
end

def total_people_served_with_supplies_from_kits_per_month
total_quantity = organization
.distributions
.for_year(year)
.joins(line_items: {item: :kit})
.where.not(items: {kit_id: nil})
.merge(Item.adult_incontinence)
.sum('line_items.quantity / COALESCE(items.distribution_quantity, 1)')
total_quantity / 12.0
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

Per the issue, "
The number of adults assisted with kit items is the number of kits that contain adult incontinence supplies distributed divided by the "quantity per individual" on the kit item. if there is no quantity per individual provided, assume that quantity is 1."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Quick question, also I apologize for missing that bit! Is it a safe assumption that the distribution_quantity is equal to the "quantity per individual"?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. Sorry for the terminology ambiguity -- they are the same.

Copy link
Collaborator

@cielf cielf Dec 12, 2024

Choose a reason for hiding this comment

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

I suspect this is giving you kits that are identified as adult_incontinence, rather than kits that have adult incontinence items in them? Though you used the same pattern as for the disposables... Huh.

end
end
50 changes: 40 additions & 10 deletions spec/services/reports/adult_incontinence_report_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
it 'should report zero values' do
expect(report.report[:name]).to eq("Adult Incontinence")
expect(report.report[:entries]).to match(hash_including({
"Adult incontinence supplies distributed" => "0",
"Adults Assisted Per Month" => 0,
"% adult incontinence bought" => "0%",
"% adult incontinence supplies donated" => "0%",
"Adult incontinence supplies distributed" => "0",
"Adult incontinence supplies per adult per month" => 0,
"Money spent purchasing adult incontinence supplies" => "$0.00"
}))
Expand All @@ -39,6 +40,25 @@
adult_incontinence_item = organization.items.adult_incontinence.first
non_adult_incontinence_item = organization.items.where.not(id: organization.items.adult_incontinence).first

# kits
create(:base_item, name: "Adult Briefs (Medium)", partner_key: "adult_briefs_medium", category: "adult incontinence")
create(:base_item, name: "Adult Briefs (Large)", partner_key: "adult_briefs_large", category: "adult incontinence")

adult_incontinence_kit_item_1 = create(:item, name: "Adult Briefs (Medium)", partner_key: "adult_briefs_medium")
adult_incontinence_kit_item_2 = create(:item, name: "Adult Briefs (Large)", partner_key: "adult_briefs_large")

adult_line_item_1 = create(:line_item, item: adult_incontinence_kit_item_1, quantity: 5)
adult_line_item_2 = create(:line_item, item: adult_incontinence_kit_item_2, quantity: 10)

kit_1 = create(:kit, :with_item, organization: organization, line_items: [adult_line_item_1])
kit_2 = create(:kit, :with_item, organization: organization, line_items: [adult_line_item_2])

# kit distributions
kit_distribution_1 = create(:distribution, organization: organization, issued_at: within_time)
kit_distribution_2 = create(:distribution, organization: organization, issued_at: within_time)

create(:line_item, :distribution, quantity: 10, item: kit_1.item, itemizable: kit_distribution_1)
create(:line_item, :distribution, quantity: 10, item: kit_2.item, itemizable: kit_distribution_2)
# We will create data both within and outside our date range, and both adult_incontinence and non adult_incontinence.
# Spec will ensure that only the required data is included.

Expand Down Expand Up @@ -101,8 +121,9 @@
expect(report.report[:entries]).to match(hash_including({
"% adult incontinence bought" => "60%",
"% adult incontinence supplies donated" => "40%",
"Adult incontinence supplies distributed" => "2,000",
"Adult incontinence supplies per adult per month" => 20,
"Adults Assisted Per Month" => 10,
"Adult incontinence supplies distributed" => "2,170",
"Adult incontinence supplies per adult per month" => 18,
"Money spent purchasing adult incontinence supplies" => "$30.00"
}))
expect(report.report[:entries]['Adult incontinence supplies'].split(', '))
Expand All @@ -115,18 +136,23 @@
"Adult Briefs (XXS)",
"Adult Incontinence Pads",
"Underpads (Pack)",
"1T Diapers",
"2T Diapers",
"Adult Cloth Diapers (Large/XL/XXL)",
"Adult Cloth Diapers (Small/Medium)",
"Liners (Incontinence)",
"Adult Cloth Diapers (Large/XL/XXL)",
"Adult Cloth Diapers (Small/Medium)")
"Adult Briefs (Large)",
"Adult Briefs (Medium)")
end

it 'should handle null distribution quantity' do
expect(report.report[:name]).to eq("Adult Incontinence")
expect(report.report[:entries]).to match(hash_including({
"% adult incontinence bought" => "60%",
"% adult incontinence supplies donated" => "40%",
"Adult incontinence supplies distributed" => "2,000",
"Adult incontinence supplies per adult per month" => 50,
"Adult incontinence supplies distributed" => "2,170",
"Adults Assisted Per Month" => 5,
"Adult incontinence supplies per adult per month" => 36,
"Money spent purchasing adult incontinence supplies" => "$30.00"
}))
expect(report.report[:entries]['Adult incontinence supplies'].split(', '))
Expand All @@ -139,9 +165,13 @@
"Adult Briefs (XXS)",
"Adult Incontinence Pads",
"Underpads (Pack)",
"Liners (Incontinence)",
"Adult Cloth Diapers (Large/XL/XXL)",
"Adult Cloth Diapers (Small/Medium)")
"3T Diapers",
"4T Diapers",
"Adult Cloth Diapers (Large/XL/XXL)",
"Adult Cloth Diapers (Small/Medium)",
"Liners (Incontinence)",
"Adult Briefs (Large)",
"Adult Briefs (Medium)")
end
end
end
Expand Down
Loading