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

Update error messages on user-facing forms #146

Merged
merged 7 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ services:
pelias:
networks:
- api
ports:
- 6800:3000
image: pelias/parser

meshdb:
Expand Down
18 changes: 11 additions & 7 deletions src/meshapi/tests/test_join_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ def test_bad_phone_join_form(self):
f"status code incorrect for Bad Phone Join Form. Should be {code}, but got {response.status_code}.\n Response is: {response.content.decode('utf-8')}",
)

self.assertEqual(
'"555-555-5555 is not a valid phone number"', response.content.decode("utf-8"), f"Content is wrong"
)
con = json.loads(response.content.decode("utf-8"))

self.assertEqual("555-555-5555 is not a valid phone number", con["detail"], f"Content is wrong")

def test_bad_email_join_form(self):
# Name, email, phone, location, apt, rooftop, referral
Expand All @@ -186,9 +186,11 @@ def test_bad_email_join_form(self):
f"status code incorrect for Bad Email Join Form. Should be {code}, but got {response.status_code}.\n Response is: {response.content.decode('utf-8')}",
)

con = json.loads(response.content.decode("utf-8"))

self.assertEqual(
'"[email protected] is not a valid email"',
response.content.decode("utf-8"),
"[email protected] is not a valid email",
con["detail"],
"Content is wrong",
)

Expand All @@ -205,9 +207,11 @@ def test_bad_address_join_form(self):
f"status code incorrect for Bad Address Join Form. Should be {code}, but got {response.status_code}.\n Response is: {response.content.decode('utf-8')}",
)

con = json.loads(response.content.decode("utf-8"))

self.assertEqual(
f"\"(NYC) Address '{form['street_address']}, {form['city']}, {form['state']} {form['zip']}' not found in geosearch.planninglabs.nyc.\"",
response.content.decode("utf-8"),
f"(NYC) Address '{form['street_address']}, {form['city']}, {form['state']} {form['zip']}' not found in geosearch.planninglabs.nyc.",
con["detail"],
f"Did not get correct response content for bad address join form: {response.content.decode('utf-8')}",
)

Expand Down
5 changes: 5 additions & 0 deletions src/meshapi/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ def __init__(self, street_address: str, city: str, state: str, zip: int):
# If we enter something not within NYC, the API will still give us
# the closest matching street address it can find, so check that
# the ZIP of what we entered matches what we got.

# FIXME (willnilges): Found an edge case where if you enter an address
# that's not in the Zip code, it will print the "not within city limits"
# error. Either the error message needs to be re-worked, or additional
# validation is required to figure out exactly what is wrong.
found_zip = int(nyc_planning_resp["features"][0]["properties"]["postalcode"])
if found_zip != zip:
raise AddressError(
Expand Down
48 changes: 34 additions & 14 deletions src/meshapi/views/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,26 @@ def join_form(request):
try:
r = JoinFormRequest(**request_json)
except TypeError as e:
return Response({"Got incomplete request"}, status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": "Got incomplete form request"}, status=status.HTTP_400_BAD_REQUEST)

if not r.ncl:
return Response("You must agree to the Network Commons License!", status=status.HTTP_400_BAD_REQUEST)
return Response(
{"detail": "You must agree to the Network Commons License!"}, status=status.HTTP_400_BAD_REQUEST
)

if not validate_email_address(r.email):
return Response(f"{r.email} is not a valid email", status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": f"{r.email} is not a valid email"}, status=status.HTTP_400_BAD_REQUEST)

# Expects country code!!!!
if not validate_phone_number(r.phone):
return Response(f"{r.phone} is not a valid phone number", status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": f"{r.phone} is not a valid phone number"}, status=status.HTTP_400_BAD_REQUEST)

# We only support the five boroughs of NYC at this time
if not NYCZipCodes.match_zip(r.zip):
return Response(
"Sorry, we don’t support non NYC registrations at this time, check back later or email [email protected]",
{
"detail": "Non-NYC registrations are not supported at this time. Check back later, or email [email protected]"
},
status=status.HTTP_400_BAD_REQUEST,
)

Expand All @@ -72,7 +76,7 @@ def join_form(request):
# off.
except AddressError as e:
print(e)
return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
# If we get any other error, then there was probably an issue
# using the API, and we should wait a bit and re-try
except (AddressAPIError, Exception) as e:
Expand All @@ -81,7 +85,9 @@ def join_form(request):
time.sleep(3)
# If we run out of tries, bail.
if nyc_addr_info == None:
return Response("(NYC) Error validating address", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(
{"detail": "Your address could not be validated."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)

# Check if there's an existing member. Dedupe on email for now.
# A member can have multiple install requests
Expand Down Expand Up @@ -140,15 +146,20 @@ def join_form(request):
join_form_member.save()
except IntegrityError as e:
print(e)
return Response("Could not save member.", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(
{"detail": "There was a problem saving your Member information"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

try:
join_form_building.save()
except IntegrityError as e:
print(e)
# Delete the member and bail
join_form_member.delete()
return Response("Could not save building", status=status.HTTP_400_BAD_REQUEST)
return Response(
{"detail": "There was a problem saving your Building information"}, status=status.HTTP_400_BAD_REQUEST
)

try:
join_form_install.save()
Expand All @@ -158,14 +169,17 @@ def join_form(request):
join_form_member.delete()
if len(existing_buildings) == 0:
join_form_building.delete()
return Response("Could not save request", status=status.HTTP_400_BAD_REQUEST)
return Response(
{"detail": "There was a problem saving your Install information"}, status=status.HTTP_400_BAD_REQUEST
)

print(
f"JoinForm submission success. building_id: {join_form_building.id}, member_id: {join_form_member.id}, install_number: {join_form_install.install_number}"
)

return Response(
{
"detail": "Thanks! A volunteer will email you shortly",
"building_id": join_form_building.id,
"member_id": join_form_member.id,
"install_number": join_form_install.install_number,
Expand Down Expand Up @@ -198,20 +212,21 @@ def network_number_assignment(request):
r = NetworkNumberAssignmentRequest(**request_json)
except (TypeError, JSONDecodeError) as e:
print(f"NN Request failed. Could not decode request: {e}")
return Response({"Got incomplete request"}, status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": "Got incomplete request"}, status=status.HTTP_400_BAD_REQUEST)

try:
nn_install = Install.objects.get(install_number=r.install_number)
except Exception as e:
print(f'NN Request failed. Could not get Install w/ Install Number "{r.install_number}": {e}')
return Response({"Install Number not found"}, status=status.HTTP_404_NOT_FOUND)
return Response({"detail": "Install Number not found"}, status=status.HTTP_404_NOT_FOUND)

# Check if the install already has a network number
if nn_install.network_number != None:
message = f"This Install Number ({r.install_number}) already has a Network Number ({nn_install.network_number}) associated with it!"
print(message)
return Response(
{
"detail": message,
"building_id": nn_install.building.id,
"install_number": nn_install.install_number,
"network_number": nn_install.network_number,
Expand Down Expand Up @@ -239,7 +254,9 @@ def network_number_assignment(request):

# Sanity check to make sure we don't assign something crazy
if free_nn <= 100 or free_nn >= 8000:
return Response(f"NN Request failed. Invalid NN: {free_nn}", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(
{"detail": f"NN Request failed. Invalid NN: {free_nn}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)

# Set the NN on both the install and the Building
nn_install.network_number = free_nn
Expand All @@ -252,10 +269,13 @@ def network_number_assignment(request):
nn_install.save()
except IntegrityError as e:
print(e)
return Response("NN Request failed. Could not save node number.", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(
{"detail": "NN Request failed. Could not save node number."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)

return Response(
{
"detail": "Network Number has been assigned!",
"building_id": nn_building.id,
"install_number": nn_install.install_number,
"network_number": nn_install.network_number,
Expand Down
Loading