Skip to content

Commit

Permalink
Select contact address from postcode lookup results (#120)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WC-112

Once users have entered a postcode to search with, we should let them choose the address they want from the results and save that as their contact address.

This should work the same way as the registered address earlier in the form.

We should go with the same inheritance model we've used for the people forms, postcode forms and manual address forms. CompanyAddressForm and ContactAddressForm are very similar, so any shared methods should be inherited from the AddressForm instead.
  • Loading branch information
irisfaraway committed Apr 12, 2018
1 parent 311632d commit a9b2600
Show file tree
Hide file tree
Showing 17 changed files with 333 additions and 108 deletions.
8 changes: 8 additions & 0 deletions app/controllers/address_forms_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class AddressFormsController < FormsController
def skip_to_manual_address
set_transient_registration(params[:reg_identifier])

@transient_registration.skip_to_manual_address! if form_matches_state?
redirect_to_correct_form
end
end
9 changes: 1 addition & 8 deletions app/controllers/company_address_forms_controller.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
class CompanyAddressFormsController < FormsController
class CompanyAddressFormsController < AddressFormsController
def new
super(CompanyAddressForm, "company_address_form")
end

def create
super(CompanyAddressForm, "company_address_form")
end

def skip_to_manual_address
set_transient_registration(params[:reg_identifier])

@transient_registration.skip_to_manual_address! if form_matches_state?
redirect_to_correct_form
end
end
2 changes: 1 addition & 1 deletion app/controllers/contact_address_forms_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class ContactAddressFormsController < FormsController
class ContactAddressFormsController < AddressFormsController
def new
super(ContactAddressForm, "contact_address_form")
end
Expand Down
68 changes: 68 additions & 0 deletions app/forms/address_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
class AddressForm < BaseForm
attr_accessor :temp_addresses
attr_accessor :temp_address
attr_accessor :addresses

def submit(params)
# Assign the params for validation and pass them to the BaseForm method for updating
self.addresses = add_or_replace_address(params[:temp_address])
attributes = { addresses: addresses }

super(attributes, params[:reg_identifier])
end

validates :addresses, presence: true

private

# Look up addresses based on the temp_postcode
def look_up_addresses
if temp_postcode.present?
address_finder = AddressFinderService.new(temp_postcode)
self.temp_addresses = address_finder.search_by_postcode
else
self.temp_addresses = []
end
end

# If an address has already been assigned to the transient registration, pre-select it
def preselect_existing_address
return unless @transient_registration.addresses.present?
return unless saved_address.uprn.present?
selected_address = temp_addresses.detect { |address| address["uprn"] == saved_address.uprn.to_s }
self.temp_address = selected_address["uprn"] if selected_address.present?
end

def add_or_replace_address(selected_address_uprn)
return if selected_address_uprn.blank?

data = temp_addresses.detect { |address| address["uprn"] == selected_address_uprn }
address = Address.create_from_os_places_data(data)
address.assign_attributes(address_type: address_type)

# Update the transient object's nested addresses, replacing any existing address of the same type
updated_addresses = @transient_registration.addresses
updated_addresses.delete(saved_address) if saved_address
updated_addresses << address
updated_addresses
end

# Methods which are called in this class but defined in subclasses
# We should throw descriptive errors in case an additional subclass of ManualAddressForm is ever added

def temp_postcode
implemented_in_subclass
end

def saved_address
implemented_in_subclass
end

def address_type
implemented_in_subclass
end

def implemented_in_subclass
raise NotImplementedError, "This #{self.class} cannot respond to:"
end
end
48 changes: 7 additions & 41 deletions app/forms/company_address_form.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
class CompanyAddressForm < BaseForm
class CompanyAddressForm < AddressForm
attr_accessor :business_type
attr_accessor :temp_company_postcode
attr_accessor :temp_addresses
attr_accessor :temp_address
attr_accessor :addresses

def initialize(transient_registration)
super
Expand All @@ -15,48 +12,17 @@ def initialize(transient_registration)
preselect_existing_address
end

def submit(params)
# Assign the params for validation and pass them to the BaseForm method for updating
self.addresses = add_or_replace_address(params[:temp_address])
attributes = { addresses: addresses }

super(attributes, params[:reg_identifier])
end

validates :addresses, presence: true

private

# Look up addresses based on the temp_company_postcode
def look_up_addresses
if temp_company_postcode.present?
address_finder = AddressFinderService.new(temp_company_postcode)
self.temp_addresses = address_finder.search_by_postcode
else
self.temp_addresses = []
end
def temp_postcode
temp_company_postcode
end

# If an address has already been assigned to the transient registration, pre-select it
def preselect_existing_address
return unless @transient_registration.addresses.present?
current_address = @transient_registration.registered_address
return unless current_address.uprn.present?
selected_address = temp_addresses.detect { |address| address["uprn"] == current_address.uprn.to_s }
self.temp_address = selected_address["uprn"] if selected_address.present?
def saved_address
@transient_registration.contact_address
end

def add_or_replace_address(selected_address_uprn)
return if selected_address_uprn.blank?

data = temp_addresses.detect { |address| address["uprn"] == selected_address_uprn }
address = Address.create_from_os_places_data(data)
address.assign_attributes(address_type: "REGISTERED")

# Update the transient object's nested addresses, replacing any existing registered address
updated_addresses = @transient_registration.addresses
updated_addresses.delete(@transient_registration.registered_address) if @transient_registration.registered_address
updated_addresses << address
updated_addresses
def address_type
"REGISTERED"
end
end
26 changes: 17 additions & 9 deletions app/forms/contact_address_form.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
class ContactAddressForm < BaseForm
# TODO: Define accessible attributes, eg attr_accessor :field
class ContactAddressForm < AddressForm
attr_accessor :temp_contact_postcode

def initialize(transient_registration)
super
# TODO: Define params to get from transient_registration, eg self.field = @transient_registration.field
self.temp_contact_postcode = @transient_registration.temp_contact_postcode

look_up_addresses
preselect_existing_address
end

def submit(params)
# Assign the params for validation and pass them to the BaseForm method for updating
# TODO: Define allowed params, eg self.field = params[:field]
# TODO: Include attributes to update in the attributes hash, eg { field: field }
attributes = {}
private

def temp_postcode
temp_contact_postcode
end

def saved_address
@transient_registration.contact_address
end

super(attributes, params[:reg_identifier])
def address_type
"CONTACT"
end
end
14 changes: 1 addition & 13 deletions app/views/company_address_forms/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,7 @@
<%= link_to(t(".postcode_change_link"), back_company_address_forms_path(@company_address_form.reg_identifier)) %>
</div>

<% if @company_address_form.errors[:addresses].any? %>
<div class="form-group form-group-error">
<% else %>
<div class="form-group">
<% end %>
<fieldset id="addresses">
<%= f.label :temp_address, t(".address_label"), class: "form-label" %>
<%= f.select(:temp_address,
options_for_select(@company_address_form.temp_addresses.map { |a| [a["partial"], a["uprn"]] }, @company_address_form.temp_address),
{ include_blank: t(".address_blank_option", count: @company_address_form.temp_addresses.length ) },
{ class: "form-control" }) %>
</fieldset>
</div>
<%= render("shared/select_address", form: @company_address_form, f: f) %>

<div class="form-group">
<%= link_to(t(".manual_address_link"), skip_to_manual_address_company_address_forms_path(@company_address_form.reg_identifier)) %>
Expand Down
26 changes: 15 additions & 11 deletions app/views/contact_address_forms/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
<%= render("shared/back", back_path: back_contact_address_forms_path(@contact_address_form.reg_identifier)) %>

<% if @contact_address_form.errors.any? %>

<h1 class="heading-large"><%= t(".error_heading") %></h1>

<% @contact_address_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
<% else %>
<div class="text">
<%= form_for(@contact_address_form) do |f| %>
<%= render("shared/errors", object: @contact_address_form) %>

<h1 class="heading-large"><%= t(".heading") %></h1>

<div class="form-group">
<label class="form-label"><%= t(".postcode_label") %></label>
<span class="postcode"><%= @contact_address_form.temp_contact_postcode %></span>
<%= link_to(t(".postcode_change_link"), back_contact_address_forms_path(@contact_address_form.reg_identifier)) %>
</div>

<%= render("shared/select_address", form: @contact_address_form, f: f) %>

<div class="form-group">
<%= link_to(t(".manual_address_link"), skip_to_manual_address_contact_address_forms_path(@contact_address_form.reg_identifier)) %>
</div>

<%= f.hidden_field :reg_identifier, value: @contact_address_form.reg_identifier %>
<div class="form-group">
<%= f.submit t(".next_button"), class: "button" %>
</div>
<% end %>
<% end %>
<%= render("shared/os_terms_footer") %>
</div>
13 changes: 13 additions & 0 deletions app/views/shared/_select_address.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<% if form.errors[:addresses].any? %>
<div class="form-group form-group-error">
<% else %>
<div class="form-group">
<% end %>
<fieldset id="addresses">
<%= f.label :temp_address, t(".address_label"), class: "form-label" %>
<%= f.select(:temp_address,
options_for_select(form.temp_addresses.map { |a| [a["partial"], a["uprn"]] }, form.temp_address),
{ include_blank: t(".address_blank_option", count: form.temp_addresses.length ) },
{ class: "form-control" }) %>
</fieldset>
</div>
6 changes: 6 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ en:
person_name:
first_name: First name
last_name: Last name
select_address:
address_label: Address
address_blank_option:
zero: No addresses found
one: 1 address found
other: "%{count} addresses found"

# Custom error pages
invalid_reg_identifier_heading: The registration number you entered is not valid
Expand Down
5 changes: 0 additions & 5 deletions config/locales/forms/company_address_forms/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ en:
heading_soleTrader: What's the address of the business?
postcode_label: Postcode
postcode_change_link: Change
address_label: Address
address_blank_option:
zero: No addresses found
one: 1 address found
other: "%{count} addresses found"
manual_address_link: "I can't find the address in the list"
error_heading: Something is wrong
next_button: Continue
Expand Down
5 changes: 5 additions & 0 deletions config/locales/forms/contact_address_forms/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ en:
contact_address_forms:
new:
heading: What's the address of the person we should contact?
postcode_label: Postcode
postcode_change_link: Change
manual_address_link: "I can't find the address in the list"
error_heading: Something is wrong
next_button: Continue
activemodel:
errors:
models:
contact_address_form:
attributes:
addresses:
blank: "You must select an address"
reg_identifier:
invalid_format: "The registration ID is not in a valid format"
no_registration: "There is no registration matching this ID"
Expand Down
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@
to: "contact_address_forms#go_back",
as: "back",
on: :collection

get "skip_to_manual_address/:reg_identifier",
to: "contact_address_forms#skip_to_manual_address",
as: "skip_to_manual_address",
on: :collection
end

resources :contact_address_manual_forms,
Expand Down
28 changes: 28 additions & 0 deletions spec/factories/forms/contact_address_form.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
FactoryBot.define do
factory :contact_address_form do
trait :has_required_data do
temp_address "340116"
temp_addresses [{
"moniker" => "340116",
"uprn" => "340116",
"lines" => ["NATURAL ENGLAND", "DEANERY ROAD"],
"town" => "BRISTOL",
"postcode" => "BS1 5AH",
"easting" => "358205",
"northing" => "172708",
"country" => "",
"dependentLocality" => "",
"dependentThroughfare" => "",
"administrativeArea" => "BRISTOL",
"localAuthorityUpdateDate" => "",
"royalMailUpdateDate" => "",
"partial" => "NATURAL ENGLAND, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH",
"subBuildingName" => "",
"buildingName" => "HORIZON HOUSE",
"thoroughfareName" => "DEANERY ROAD",
"organisationName" => "NATURAL ENGLAND",
"buildingNumber" => "",
"postOfficeBoxNumber" => "",
"departmentName" => "",
"doubleDependentLocality" => ""
}]

addresses { [build(:address, :has_required_data, :contact)] }

initialize_with { new(create(:transient_registration, :has_required_data, workflow_state: "contact_address_form")) }
end
end
Expand Down
Loading

0 comments on commit a9b2600

Please sign in to comment.