Skip to content

Commit a061873

Browse files
4946 partner profile export (#5142)
* First pass at adding the profile fields to the seed * Added the unused fields application_data and distributor_type to ignored_columns and added comments recording the relationship betwween Partners::Profile fields and partials * First pass at expanding the fields exported to the csv * Removed contact_person as it was only used in the exprt_partners_csv_service and it makes sense to have all the logic for the csv in one place, removed accidental duplicate contact columns * Removed agency_info as it was only used in the exprt_partners_csv_service and it makes sense to have all the logic for the csv in one place * Cleaned and DRYed up definition of population and poverty served percentages * First pass at modifying the specs to check for all of the new fields in the export * Seperated expected headers and values by associated partial, added spec to verify that only columns for enabled partials are exported * Effects of adding application_data and distributor_type to unused fields * Changes made by linter * Added test to specify how a partner with an empty profile should be exported * Added partials_to_show function to the Organization model, reworked the Partner model to refer to Organization model for the partials_to_show and ALL_PARTIALS * Added organization argument to ExportPartnersCSVService so which partials to show can be determined even when no partials are present * Added tests to verify the export service works when there are no partners * Expanded partners request tests to account for new exported fields * Changes made by linter * Updated user documentation about exporting partners * Added comment explaining addition of partner_form_fields * Updated the order of columns in the partners export to match the order of fields in the partner profile form * Updated the order to columns to more closely match the order of fields in the partner profile form, renamed column headers to match fields in the form * Updated partner profile view to have same field names as edit form and export * Updated user documentation about exporting partners to reflect new column order * Removed duplicate hash key * Hardcoded expected values for tests on partner export * Split up massive base_table function * Fixed creating adding non priod supply item
1 parent d8fa236 commit a061873

12 files changed

Lines changed: 912 additions & 291 deletions

File tree

app/controllers/partners_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def index
1515

1616
respond_to do |format|
1717
format.html
18-
format.csv { send_data Exports::ExportPartnersCSVService.new(@partners.unscope(:includes)).generate_csv, filename: "Partners-#{Time.zone.today}.csv" }
18+
format.csv { send_data Exports::ExportPartnersCSVService.new(@partners.unscope(:includes), current_organization).generate_csv, filename: "Partners-#{Time.zone.today}.csv" }
1919
end
2020
end
2121

app/models/organization.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ def address_changed?
168168
street_changed? || city_changed? || state_changed? || zipcode_changed?
169169
end
170170

171+
def partials_to_show
172+
partner_form_fields.presence || ALL_PARTIALS.map { |partial| partial[1] }
173+
end
174+
171175
def self.seed_items(organization = Organization.all)
172176
base_items = BaseItem.without_kit.map(&:to_h)
173177

app/models/partner.rb

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,7 @@ class Partner < ApplicationRecord
6666
where(status: status.to_sym)
6767
}
6868

69-
ALL_PARTIALS = %w[
70-
media_information
71-
agency_stability
72-
organizational_capacity
73-
sources_of_funding
74-
area_served
75-
population_served
76-
executive_director
77-
pick_up_person
78-
agency_distribution_information
79-
attached_documents
80-
].freeze
69+
ALL_PARTIALS = Organization::ALL_PARTIALS.map { |partial| partial[1] }.freeze
8170

8271
# @return [String]
8372
def display_status
@@ -126,33 +115,8 @@ def self.import_csv(csv, organization_id)
126115
errors
127116
end
128117

129-
def contact_person
130-
return @contact_person if @contact_person
131-
132-
@contact_person = {
133-
name: profile.primary_contact_name,
134-
email: profile.primary_contact_email,
135-
phone: profile.primary_contact_phone ||
136-
profile.primary_contact_mobile
137-
}
138-
end
139-
140-
def agency_info
141-
return @agency_info if @agency_info
142-
143-
symbolic_agency_type = profile.agency_type&.to_sym
144-
@agency_info = {
145-
address: [profile.address1, profile.address2].select(&:present?).join(', '),
146-
city: profile.city,
147-
state: profile.state,
148-
zip_code: profile.zip_code,
149-
website: profile.website,
150-
agency_type: (symbolic_agency_type == :other) ? "#{I18n.t symbolic_agency_type, scope: :partners_profile}: #{profile.other_agency_type}" : (I18n.t symbolic_agency_type, scope: :partners_profile)
151-
}
152-
end
153-
154118
def partials_to_show
155-
organization.partner_form_fields.presence || ALL_PARTIALS
119+
organization.partials_to_show
156120
end
157121

158122
def quantity_year_to_date

app/models/partners/profile.rb

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,13 @@
88
# address2 :string
99
# agency_mission :text
1010
# agency_type :string
11-
# application_data :text
1211
# at_fpl_or_below :integer
1312
# case_management :boolean
1413
# city :string
1514
# client_capacity :string
1615
# currently_provide_diapers :boolean
1716
# describe_storage_space :text
1817
# distribution_times :string
19-
# distributor_type :string
2018
# enable_child_based_requests :boolean default(TRUE), not null
2119
# enable_individual_requests :boolean default(TRUE), not null
2220
# enable_quantity_based_requests :boolean default(TRUE), not null
@@ -144,7 +142,44 @@ class Profile < Base
144142
validate :has_at_least_one_request_setting
145143
validate :pick_up_email_addresses
146144

145+
# For the sake of documentation, here are the partials each field belongs to. In the order those
146+
# partials appear in the actual form.
147+
# agency_information -- this partial is always shown, contains the agency information AND the Program / Delivery Address sections of the form
148+
# agency_type, other_agency_type, agency_mission, address1, address2, city, state, zip_code,
149+
# program_address1, program_address2, program_city, program_state, program_zip_code
150+
# media_information
151+
# website, facebook, twitter, instagram, no_social_media_presence
152+
# agency_stability
153+
# founded, form_990, program_name, program_description, program_age, evidence_based, case_management,
154+
# essentials_use, receives_essentials_from_other, currently_provide_diapers
155+
# organizational_capacity
156+
# client_capacity, storage_space, describe_storage_space
157+
# sources_of_funding
158+
# sources_of_funding, sources_of_diapers, essentials_budget, essentials_funding_source
159+
# area_served
160+
# has no associated Partners::Profile fields
161+
# population_served
162+
# income_requirement_desc, income_verification, population_black, population_white,
163+
# population_hispanic, population_asian, population_american_indian, population_island,
164+
# population_multi_racial, population_other, zips_served, at_fpl_or_below, above_1_2_times_fpl
165+
# greater_2_times_fpl, poverty_unknown
166+
# executive_director
167+
# executive_director_name, executive_director_phone, executive_director_email, primary_contact_name,
168+
# primary_contact_phone, primary_contact_mobile, primary_contact_email
169+
# pick_up_person
170+
# pick_up_name, pick_up_phone, pick_up_email
171+
# agency_distribution_information
172+
# distribution_times, new_client_times, more_docs_required
173+
# attached_documents
174+
# has no associated Partners::Profile fields
175+
# partner_settings -- this partial is always shown
176+
# enable_quantity_based_requests, enable_child_based_requests, enable_individual_requests
177+
178+
# These are columns which currently do not appear in any partial of the profile form.
179+
# It is possible these will be removed in the future.
147180
self.ignored_columns += %w[
181+
application_data
182+
distributor_type
148183
evidence_based_description
149184
program_client_improvement
150185
incorporate_plan

app/services/exports/export_partners_csv_service.rb

Lines changed: 142 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ class ExportPartnersCSVService
44
# to this service object; this is happening within the same request/response cycle, so it's already
55
# in memory, so we can pass that collection in directly. Should this be moved to a background / async
66
# job, we will need to pass in a collection of IDs instead.
7-
def initialize(partners)
7+
def initialize(partners, organization)
88
@partners = partners.includes(:profile)
9+
# Assumes that all of the partners belong to the same organization. This is true for the time being
10+
# and, were that to change, base_table would need to be reworked anyway to account for partners from
11+
# different orgs having different partials enabled, and thus different columns in the CSV.
12+
@partials_to_show = organization.partials_to_show
913
end
1014

1115
def generate_csv
@@ -19,28 +23,148 @@ def generate_csv
1923

2024
attr_reader :partners
2125

22-
def headers
23-
base_table.keys
24-
end
25-
2626
def base_table
27-
{
27+
table = {
2828
"Agency Name" => ->(partner) { partner.name },
2929
"Agency Email" => ->(partner) { partner.email },
30-
"Agency Address" => ->(partner) { partner.agency_info[:address] },
31-
"Agency City" => ->(partner) { partner.agency_info[:city] },
32-
"Agency State" => ->(partner) { partner.agency_info[:state] },
33-
"Agency Zip Code" => ->(partner) { partner.agency_info[:zip_code] },
34-
"Agency Website" => ->(partner) { partner.agency_info[:website] },
35-
"Agency Type" => ->(partner) { partner.agency_info[:agency_type] },
36-
"Contact Name" => ->(partner) { partner.contact_person[:name] },
37-
"Contact Phone" => ->(partner) { partner.contact_person[:phone] },
38-
"Contact Email" => ->(partner) { partner.contact_person[:email] },
3930
"Notes" => ->(partner) { partner.notes },
40-
"Counties Served" => ->(partner) { county_list_by_regions[partner.id] || "" },
41-
"Providing Diapers" => ->(partner) { diaper_statuses[partner.id] },
42-
"Providing Period Supplies" => ->(partner) { period_supplies_statuses[partner.id] }
31+
"Agency Type" => ->(partner) { I18n.t(partner.profile.agency_type, scope: :partners_profile) }, # Columns from the agency_information partial
32+
"Other Agency Type" => ->(partner) { partner.profile.other_agency_type },
33+
"Agency Mission" => ->(partner) { partner.profile.agency_mission },
34+
"Agency Address" => ->(partner) {
35+
(partner.profile.address1.blank? || partner.profile.address2.blank?) ?
36+
"" : "#{partner.profile.address1}, #{partner.profile.address2}"
37+
},
38+
"Agency City" => ->(partner) { partner.profile.city },
39+
"Agency State" => ->(partner) { partner.profile.state },
40+
"Agency Zip Code" => ->(partner) { partner.profile.zip_code },
41+
"Program/Delivery Address" => ->(partner) {
42+
(partner.profile.program_address1.blank? || partner.profile.program_address2.blank?) ?
43+
"" : "#{partner.profile.program_address1}, #{partner.profile.program_address2}"
44+
},
45+
"Program City" => ->(partner) { partner.profile.program_city },
46+
"Program State" => ->(partner) { partner.profile.program_state },
47+
"Program Zip Code" => ->(partner) { partner.profile.program_zip_code }
4348
}
49+
50+
media_information_col(table)
51+
agency_stability_col(table)
52+
organizational_capacity_col(table)
53+
sources_of_funding_col(table)
54+
area_served_col(table)
55+
population_served_col(table)
56+
executive_director_col(table)
57+
pick_up_person_col(table)
58+
agency_distribution_information_col(table)
59+
60+
table["Quantity-based Requests"] = ->(partner) { partner.profile.enable_quantity_based_requests } # Columns from the partner_settings partial
61+
table["Child-based Requests"] = ->(partner) { partner.profile.enable_child_based_requests }
62+
table["Individual Requests"] = ->(partner) { partner.profile.enable_individual_requests }
63+
64+
table["Providing Diapers"] = ->(partner) { diaper_statuses[partner.id] }
65+
table["Providing Period Supplies"] = ->(partner) { period_supplies_statuses[partner.id] }
66+
67+
table
68+
end
69+
70+
def media_information_col(table)
71+
if @partials_to_show.include? "media_information"
72+
table["Agency Website"] = ->(partner) { partner.profile.website }
73+
table["Facebook"] = ->(partner) { partner.profile.facebook }
74+
table["Twitter"] = ->(partner) { partner.profile.twitter }
75+
table["Instagram"] = ->(partner) { partner.profile.instagram }
76+
table["No Social Media Presence"] = ->(partner) { partner.profile.no_social_media_presence }
77+
end
78+
end
79+
80+
def agency_stability_col(table)
81+
if @partials_to_show.include? "agency_stability"
82+
table["Year Founded"] = ->(partner) { partner.profile.founded }
83+
table["Form 990 Filed"] = ->(partner) { partner.profile.form_990 }
84+
table["Program Name"] = ->(partner) { partner.profile.program_name }
85+
table["Program Description"] = ->(partner) { partner.profile.program_description }
86+
table["Agency Age"] = ->(partner) { partner.profile.program_age }
87+
table["Evidence Based"] = ->(partner) { partner.profile.evidence_based }
88+
table["Case Management"] = ->(partner) { partner.profile.case_management }
89+
table["How Are Essentials Used"] = ->(partner) { partner.profile.essentials_use }
90+
table["Receive Essentials From Other Sources"] = ->(partner) { partner.profile.receives_essentials_from_other }
91+
table["Currently Providing Diapers"] = ->(partner) { partner.profile.currently_provide_diapers }
92+
end
93+
end
94+
95+
def organizational_capacity_col(table)
96+
if @partials_to_show.include? "organizational_capacity"
97+
table["Client Capacity"] = ->(partner) { partner.profile.client_capacity }
98+
table["Storage Space"] = ->(partner) { partner.profile.storage_space }
99+
table["Storage Space Description"] = ->(partner) { partner.profile.describe_storage_space }
100+
end
101+
end
102+
103+
def sources_of_funding_col(table)
104+
if @partials_to_show.include? "sources_of_funding"
105+
table["Sources Of Funding"] = ->(partner) { partner.profile.sources_of_funding }
106+
table["How do you currently obtain diapers?"] = ->(partner) { partner.profile.sources_of_diapers }
107+
table["Essentials Budget"] = ->(partner) { partner.profile.essentials_budget }
108+
table["Essentials Funding Source"] = ->(partner) { partner.profile.essentials_funding_source }
109+
end
110+
end
111+
112+
def area_served_col(table)
113+
if @partials_to_show.include? "area_served"
114+
table["Area Served"] = ->(partner) { county_list_by_regions[partner.id] || "" }
115+
end
116+
end
117+
118+
def population_served_col(table)
119+
if @partials_to_show.include? "population_served"
120+
table["Income Requirement"] = ->(partner) { partner.profile.income_requirement_desc }
121+
table["Verify Income"] = ->(partner) { partner.profile.income_verification }
122+
table["% African American"] = ->(partner) { partner.profile.population_black }
123+
table["% Caucasian"] = ->(partner) { partner.profile.population_white }
124+
table["% Hispanic"] = ->(partner) { partner.profile.population_hispanic }
125+
table["% Asian"] = ->(partner) { partner.profile.population_asian }
126+
table["% American Indian"] = ->(partner) { partner.profile.population_american_indian }
127+
table["% Pacific Island"] = ->(partner) { partner.profile.population_island }
128+
table["% Multi-racial"] = ->(partner) { partner.profile.population_multi_racial }
129+
table["% Other"] = ->(partner) { partner.profile.population_other }
130+
table["Zip Codes Served"] = ->(partner) { partner.profile.zips_served }
131+
table["% At FPL or Below"] = ->(partner) { partner.profile.at_fpl_or_below }
132+
table["% Above 1-2 times FPL"] = ->(partner) { partner.profile.above_1_2_times_fpl }
133+
table["% Greater than 2 times FPL"] = ->(partner) { partner.profile.greater_2_times_fpl }
134+
table["% Poverty Unknown"] = ->(partner) { partner.profile.poverty_unknown }
135+
end
136+
end
137+
138+
def executive_director_col(table)
139+
if @partials_to_show.include? "executive_director"
140+
table["Executive Director Name"] = ->(partner) { partner.profile.executive_director_name }
141+
table["Executive Director Phone"] = ->(partner) { partner.profile.executive_director_phone }
142+
table["Executive Director Email"] = ->(partner) { partner.profile.executive_director_email }
143+
table["Primary Contact Name"] = ->(partner) { partner.profile.primary_contact_name }
144+
table["Primary Contact Phone"] = ->(partner) { partner.profile.primary_contact_phone }
145+
table["Primary Contact Cell"] = ->(partner) { partner.profile.primary_contact_mobile }
146+
table["Primary Contact Email"] = ->(partner) { partner.profile.primary_contact_email }
147+
end
148+
end
149+
150+
def pick_up_person_col(table)
151+
if @partials_to_show.include? "pick_up_person"
152+
table["Pick Up Person Name"] = ->(partner) { partner.profile.pick_up_name }
153+
table["Pick Up Person Phone"] = ->(partner) { partner.profile.pick_up_phone }
154+
table["Pick Up Person Email"] = ->(partner) { partner.profile.pick_up_email }
155+
end
156+
end
157+
158+
def agency_distribution_information_col(table)
159+
if @partials_to_show.include? "agency_distribution_information"
160+
table["Distribution Times"] = ->(partner) { partner.profile.distribution_times }
161+
table["New Client Times"] = ->(partner) { partner.profile.new_client_times }
162+
table["More Docs Required"] = ->(partner) { partner.profile.more_docs_required }
163+
end
164+
end
165+
166+
def headers
167+
base_table.keys
44168
end
45169

46170
def build_row_data(partner)

app/views/profiles/_show.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
</p>
5656
<p>Program Name(s): <%= partner_profile.program_name %></p>
5757
<p>Program Description(s): <%= partner_profile.program_description %></p>
58-
<p>Program Age: <%= partner_profile.program_age %></p>
58+
<p>Agency Age: <%= partner_profile.program_age %></p>
5959
<p>Case Management: <%= humanize_boolean_3state(partner_profile.case_management) %></p>
6060
<p>Evidence Based: <%= humanize_boolean_3state(partner_profile.evidence_based) %></p>
6161
<p>How Are Essentials (e.g. diapers, period supplies) Used In Your Program? <%= partner_profile.essentials_use %></p>
@@ -146,7 +146,7 @@
146146
<% if partner_profile_fields.include?('sources_of_funding') || partner_profile_fields.empty? %>
147147
<h4 class='text-2xl underline'>Sources of Funding</h4>
148148
<p>Sources of Funding: <%= partner_profile.sources_of_funding %></p>
149-
<p>Sources of Diapers: <%= partner_profile.sources_of_diapers %> </p>
149+
<p>How do you currently obtain diapers? <%= partner_profile.sources_of_diapers %> </p>
150150
<p>Essentials Budget:<%= partner_profile.essentials_budget %></p>
151151
<p>Essentials Funding Source: <%= partner_profile.essentials_funding_source %></p>
152152
<br>

0 commit comments

Comments
 (0)