-
-
Notifications
You must be signed in to change notification settings - Fork 573
Expand file tree
/
Copy pathadult_incontinence_report_service.rb
More file actions
165 lines (136 loc) · 5.71 KB
/
adult_incontinence_report_service.rb
File metadata and controls
165 lines (136 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
module Reports
class AdultIncontinenceReportService
include ActionView::Helpers::NumberHelper
attr_reader :year, :organization
# @param year [Integer]
# @param organization [Organization]
def initialize(year:, organization:)
@year = year
@organization = organization
end
# @return [Hash]
def report
@report ||= { name: 'Adult Incontinence',
entries: {
'Adult incontinence supplies distributed' => number_with_delimiter(total_supplies_distributed),
'Adults Assisted Per Month' => adults_served_per_month.round(2),
'Adult incontinence supplies per adult per month' => supplies_per_adult_per_month.round(2),
'Adult incontinence supplies' => types_of_supplies,
'% adult incontinence supplies donated' => "#{percent_donated.round}%",
'% adult incontinence bought' => "#{percent_bought.round}%",
'Money spent purchasing adult incontinence supplies' => number_to_currency(money_spent_on_supplies)
} }
end
# @return [Integer]
def distributed_loose_supplies
@distributed_supplies ||= organization
.distributions
.for_year(year)
.joins(line_items: :item)
.merge(Item.adult_incontinence)
.sum('line_items.quantity')
end
# @return [Integer]
def total_supplies_distributed
(distributed_loose_supplies + distributed_adult_incontinence_items_from_kits).to_i
end
def monthly_supplies
total_supplies_distributed.to_f / 12.0
end
def supplies_per_adult_per_month
monthly_supplies.to_f / (adults_served_per_month.nonzero? || 1)
end
def types_of_supplies
organization.items.adult_incontinence.map(&:name).uniq.sort.join(', ')
end
# @return [Float]
def percent_donated
return 0.0 if total_supplies.zero?
(donated_supplies.to_f / total_supplies.to_f) * 100.0
end
# @return [Float]
def percent_bought
return 0.0 if total_supplies.zero?
(purchased_supplies.to_f / total_supplies.to_f) * 100.0
end
# @return [String]
def money_spent_on_supplies
organization.purchases.for_year(year).sum(:amount_spent_on_adult_incontinence_cents) / 100.0
end
###### HELPER METHODS ######
# @return [Integer]
def purchased_supplies
@purchased_supplies ||= LineItem.joins(:item)
.merge(Item.adult_incontinence)
.where(itemizable: organization.purchases.for_year(year))
.sum(:quantity)
end
# @return [Integer]
def total_supplies
@total_supplies ||= purchased_supplies.to_f + donated_supplies.to_f
end
# @return [Integer]
def donated_supplies
@donated_supplies ||= LineItem.joins(:item)
.merge(Item.adult_incontinence)
.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 line_items AS kit_line_items ON items.id = kit_line_items.itemizable_id
INNER JOIN items AS kit_items ON kit_items.id = kit_line_items.item_id
WHERE distributions.organization_id = ?
AND EXTRACT(year FROM issued_at) = ?
AND kit_items.reporting_category = 'adult_incontinence'
AND items.kit_id IS NOT NULL
AND kit_line_items.itemizable_type = 'Item';
SQL
sanitized_sql = ActiveRecord::Base.send(:sanitize_sql_array, [sql_query, organization_id, year])
result = ActiveRecord::Base.connection.execute(sanitized_sql)
result.first['sum'].to_f
end
def adults_served_per_month
total_people_served_with_loose_supplies_per_month + total_distributed_kits_containing_adult_incontinence_items_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.where(kit_id: nil)) # exclude kits
.sum('line_items.quantity / COALESCE(items.distribution_quantity, 50.0)')
total_quantity.to_f / 12.0
end
def distributed_kits_for_year
organization
.distributions
.for_year(year)
.joins(line_items: { item: :kit })
.distinct
.pluck('kits.id')
end
def total_distributed_kits_containing_adult_incontinence_items_per_month
kits = Kit.where(id: distributed_kits_for_year).select do |kit|
kit.kit_item.items.adult_incontinence.exists?
end
total_assisted_adults = kits.sum do |kit|
kit_item = Item.where(kit_id: kit.id).first
next 0 unless kit_item
organization
.distributions
.for_year(year)
.joins(line_items: :item)
.where(line_items: { item_id: kit_item.id })
.sum('line_items.quantity / COALESCE(items.distribution_quantity, 1.0)')
end
total_assisted_adults.to_i / 12.0
end
end
end