diff --git a/src/functional_tests/test_address.py b/src/functional_tests/test_address.py
new file mode 100644
index 0000000..374d3ea
--- /dev/null
+++ b/src/functional_tests/test_address.py
@@ -0,0 +1,60 @@
+import os, time
+from selenium.webdriver.firefox.webdriver import WebDriver
+from selenium.webdriver.common.keys import Keys
+from selenium.webdriver.support.ui import Select
+from selenium.common.exceptions import WebDriverException
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+
+class AddressTests(StaticLiveServerTestCase):
+ fixtures = ['products.json']
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.browser = WebDriver()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.browser.quit()
+ super().tearDownClass()
+
+ def test_invalid_address_returns_errorlist(self):
+ self.browser.get(self.live_server_url + '/checkout/address/')
+ self.assertEqual(
+ self.browser.title,
+ 'Checkout | Port Townsend Roasting Co.'
+ )
+
+ full_name_input = self.browser.find_element_by_name("full_name")
+ full_name_input.send_keys('John Doe')
+ email_input = self.browser.find_element_by_id('id_email')
+ email_input.send_keys('john@example.com')
+ street_address_1_input = self.browser.find_element_by_name('street_address_1')
+ street_address_1_input.send_keys('1579')
+ city_input = self.browser.find_element_by_name('city')
+ city_input.send_keys('Logan')
+ state_select = select = Select(self.browser.find_element_by_name('state'))
+ state_select.select_by_value('UT')
+ postal_code_input = self.browser.find_element_by_name('postal_code')
+ postal_code_input.send_keys('37461')
+ self.browser.find_element_by_xpath('//input[@value="Continue to Payment"]').click()
+ # try:
+ # WebDriverWait(self.browser, 4).until(
+ # EC.presence_of_element_located((By.CLASS_NAME, 'errorlist'))
+ # )
+ # finally:
+ # self.browser.quit()
+
+ self.assertEqual(
+ self.browser.find_element_by_css_selector(
+ '.errorlist li'
+ ).text,
+ 'USPS: Address Not Found.'
+ )
+
+
+
+
diff --git a/src/functional_tests/tests_home.py b/src/functional_tests/test_home.py
similarity index 100%
rename from src/functional_tests/tests_home.py
rename to src/functional_tests/test_home.py
diff --git a/src/ptcoffee/settings.py b/src/ptcoffee/settings.py
index 793f7a5..a38a457 100644
--- a/src/ptcoffee/settings.py
+++ b/src/ptcoffee/settings.py
@@ -190,57 +190,40 @@ TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBacke
SITE_ID = 1
# Logging
-if DEBUG:
- LOGGING = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'formatters': {
- 'verbose': {
- 'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
- 'style': '{',
- }
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'filters': {
+ 'require_debug_false': {
+ '()': 'django.utils.log.RequireDebugFalse',
},
- 'handlers': {
- 'console': {
- 'class': 'logging.StreamHandler',
- 'formatter': 'verbose',
- },
+ 'require_debug_true': {
+ '()': 'django.utils.log.RequireDebugTrue',
},
- 'root': {
- 'handlers': ['console'],
+ },
+ 'formatters': {
+ 'verbose': {
+ 'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
+ 'style': '{',
+ },
+ },
+ 'handlers': {
+ 'file': {
'level': 'DEBUG',
+ 'class': 'logging.FileHandler',
+ 'filters': ['require_debug_false'],
+ 'filename': '/var/log/django-ptcoffee/debug.log',
+ 'formatter': 'verbose',
},
- }
-else:
- LOGGING = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'formatters': {
- 'verbose': {
- 'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
- 'style': '{',
- },
- 'simple': {
- 'format': '{levelname} {message}',
- 'style': '{',
- }
+ },
+ 'loggers': {
+ 'django.file': {
+ 'handlers': ['file'],
+ 'level': 'INFO',
+ 'propagate': True,
},
- 'handlers': {
- 'file': {
- 'level': 'DEBUG',
- 'class': 'logging.FileHandler',
- 'filename': '/var/log/django-ptcoffee/debug.log',
- 'formatter': 'verbose',
- },
- },
- 'loggers': {
- 'django': {
- 'handlers': ['file'],
- 'level': 'DEBUG',
- 'propagate': True,
- },
- },
- }
+ },
+}
CART_SESSION_ID = 'cart'
diff --git a/src/static/styles/main.css b/src/static/styles/main.css
index 745fd84..329a342 100644
--- a/src/static/styles/main.css
+++ b/src/static/styles/main.css
@@ -193,7 +193,7 @@ input[type=submit],
color: var(--fg-color);
background-color: var(--yellow-color);
- padding: 0.25rem 1rem;
+ padding: 0.4rem 1rem;
border-radius: 0.2rem;
border: none;
@@ -206,6 +206,15 @@ input[type=submit]:hover,
background-color: var(--yellow-alt-color);
}
+.errorlist {
+ background-color: var(--red-color);
+ color: white;
+ list-style: none;
+ padding: 0 1rem;
+ box-sizing: border-box;
+ font-weight: bold;
+}
+
/* Contact form
========================================================================== */
@@ -788,11 +797,33 @@ article + article {
/* Checkout / Shipping Address
========================================================================== */
+.checkout__address-form {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 0 2rem;
+}
+
+
+.checkout__address-form .errorlist {
+ grid-column: span 2;
+}
+
+@media screen and (max-width: 600px) {
+ .checkout__address-form {
+ grid-template-columns: 1fr;
+ }
+ .checkout__address-form .errorlist {
+ grid-column: 1;
+}
+}
+.checkout__address-form p:last-child {
+ align-self: end;
+}
+
.checkout__address-form input,
.checkout__address-form select {
display: block;
width: 100%;
- max-width: 24rem;
}
.checkout__address {
diff --git a/src/storefront/cart.py b/src/storefront/cart.py
index c4596ff..5ab3a40 100644
--- a/src/storefront/cart.py
+++ b/src/storefront/cart.py
@@ -121,7 +121,14 @@ class Cart:
except TypeError as e:
return Decimal('0.00')
usps = USPSApiWithRate(settings.USPS_USER_ID, test=True)
- validation = usps.get_rate(usps_rate_request)
+
+ try:
+ validation = usps.get_rate(usps_rate_request)
+ except ConnectionError:
+ raise ValidationError(
+ 'Could not connect to USPS, try again.'
+ )
+
logger.info(validation.result)
if not 'Error' in validation.result['RateV4Response']['Package']:
rate = validation.result['RateV4Response']['Package']['Postage']['CommercialRate']
diff --git a/src/storefront/forms.py b/src/storefront/forms.py
index cfa559c..78891a5 100644
--- a/src/storefront/forms.py
+++ b/src/storefront/forms.py
@@ -1,6 +1,10 @@
-import logging
+import logging, json
+from requests import ConnectionError
from django import forms
+from django.conf import settings
from django.core.mail import EmailMessage
+from django.core.exceptions import ValidationError
+from usps import USPSApi, Address
from core.models import Order
from core import CoffeeGrind
@@ -35,8 +39,7 @@ class AddToSubscriptionForm(forms.Form):
class AddressForm(forms.Form):
- first_name = forms.CharField()
- last_name = forms.CharField()
+ full_name = forms.CharField()
email = forms.EmailField()
street_address_1 = forms.CharField()
street_address_2 = forms.CharField(required=False)
@@ -46,6 +49,54 @@ class AddressForm(forms.Form):
)
postal_code = forms.CharField()
+ def process_full_name(self, full_name):
+ name = full_name.split()
+
+ if len(name) > 2:
+ last_name = ''.join(name.pop(-1))
+ first_name = ' '.join(name)
+ elif len(name) > 1:
+ first_name = name[0]
+ last_name = name[1]
+ else:
+ first_name = name[0]
+ last_name = ''
+
+ return first_name, last_name
+
+ def clean(self):
+ cleaned_data = super().clean()
+ address = Address(
+ name=cleaned_data.get('full_name'),
+ address_1=cleaned_data.get('street_address_1'),
+ address_2=cleaned_data.get('street_address_2'),
+ city=cleaned_data.get('city'),
+ state=cleaned_data.get('state'),
+ zipcode=cleaned_data.get('postal_code')
+ )
+ usps = USPSApi(settings.USPS_USER_ID, test=True)
+
+ try:
+ validation = usps.validate_address(address)
+ except ConnectionError:
+ raise ValidationError(
+ 'Could not connect to USPS, try again.'
+ )
+
+
+ if 'Error' in validation.result['AddressValidateResponse']['Address']:
+ error = validation.result['AddressValidateResponse']['Address']['Error']['Description']
+ raise ValidationError(
+ "USPS: " + error
+ )
+
+ try:
+ cleaned_data['postal_code'] = validation.result['AddressValidateResponse']['Address']['Zip5']
+ except KeyError:
+ raise ValidationError(
+ 'Could not find Zip5'
+ )
+
class OrderCreateForm(forms.ModelForm):
email = forms.CharField(widget=forms.HiddenInput())
first_name = forms.CharField(widget=forms.HiddenInput())
diff --git a/src/storefront/templates/storefront/address_create_form.html b/src/storefront/templates/storefront/address_create_form.html
new file mode 100644
index 0000000..80dd853
--- /dev/null
+++ b/src/storefront/templates/storefront/address_create_form.html
@@ -0,0 +1,19 @@
+{% extends 'base.html' %}
+
+{% block content %}
+Create Address
+
We validate addresses with USPS, if you are having issues please contact us at support@ptcoffee.com or use the contact information found on our contact page.
{% endblock %} diff --git a/src/storefront/templates/storefront/customer_detail.html b/src/storefront/templates/storefront/customer_detail.html index 5f2ff72..52cba99 100644 --- a/src/storefront/templates/storefront/customer_detail.html +++ b/src/storefront/templates/storefront/customer_detail.html @@ -30,8 +30,13 @@ {% endwith %} + ++ + New address +
All addresses
{% for address in customer.addresses.all %}diff --git a/src/storefront/templates/storefront/order_form.html b/src/storefront/templates/storefront/order_form.html index 037e91d..ff960ce 100644 --- a/src/storefront/templates/storefront/order_form.html +++ b/src/storefront/templates/storefront/order_form.html @@ -15,6 +15,7 @@
{{shipping_address.email}}
{{shipping_address.first_name}} {{shipping_address.last_name}}