import logging import json import stripe from requests import ConnectionError from urllib.parse import quote from django import forms from django.conf import settings from django.core.mail import EmailMessage from django.core.exceptions import ValidationError from localflavor.us.us_states import USPS_CHOICES from usps import USPSApi, Address from captcha.fields import CaptchaField from core.models import Order, ProductVariant from core import CoffeeGrind, ShippingContainer logger = logging.getLogger(__name__) class AddToCartForm(forms.Form): quantity = forms.IntegerField(min_value=1, max_value=20, initial=1) def __init__(self, variants, options, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['variant'] = forms.ChoiceField( label='', choices=[(variant.pk, f'{variant.name} | ${variant.price}') for variant in variants] ) for option in options: self.fields[option.name] = forms.ChoiceField( choices=[(opt, opt) for opt in option.options] ) class CartItemUpdateForm(forms.Form): item_index = forms.IntegerField(widget=forms.HiddenInput()) quantity = forms.IntegerField(min_value=1, max_value=20, initial=1) class AddToSubscriptionForm(forms.Form): SEVEN_DAYS = 7 FOURTEEN_DAYS = 14 THIRTY_DAYS = 30 SCHEDULE_CHOICES = [ (SEVEN_DAYS, 'Every 7 days'), (FOURTEEN_DAYS, 'Every 14 days'), (THIRTY_DAYS, 'Every 30 days'), ] quantity = forms.IntegerField(min_value=1, initial=1) grind = forms.ChoiceField(choices=CoffeeGrind.GRIND_CHOICES) schedule = forms.ChoiceField(choices=SCHEDULE_CHOICES) class AddressForm(forms.Form): full_name = forms.CharField() email = forms.EmailField() street_address_1 = forms.CharField() street_address_2 = forms.CharField(required=False) city = forms.CharField() state = forms.ChoiceField( choices=USPS_CHOICES ) 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=quote(cleaned_data.get('full_name')), address_1=quote(cleaned_data.get('street_address_1')), address_2=quote(cleaned_data.get('street_address_2')), city=quote(cleaned_data.get('city')), state=quote(cleaned_data.get('state')), zipcode=quote(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 CheckoutShippingForm(forms.Form): def __init__(self, containers, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['shipping_method'] = forms.ChoiceField( label='', widget=forms.RadioSelect, choices=[(container.pk, f'{container.name} ${container.s_cost}') for container in containers] ) class OrderCreateForm(forms.ModelForm): class Meta: model = Order fields = [] class CouponApplyForm(forms.Form): code = forms.CharField(label='Coupon code') class ContactForm(forms.Form): GOOGLE = 'Google Search' SHOP = 'The coffee shop' WOM = 'Word of mouth' PRODUCT = 'Coffee Bag' STORE = 'Store' OTHER = 'Other' REFERAL_CHOICES = [ (GOOGLE, 'Google Search'), (SHOP, '"Better Living Through Coffee" coffee shop'), (WOM, 'Friend/Relative'), (PRODUCT, 'Our Coffee Bag'), (STORE, 'PT Food Coop/other store'), (OTHER, 'Other (please describe below)'), ] full_name = forms.CharField() email_address = forms.EmailField() referal = forms.ChoiceField( label='How did you find our website?', choices=REFERAL_CHOICES ) subject = forms.CharField() message = forms.CharField(widget=forms.Textarea) captcha = CaptchaField() class SubscriptionCreateForm(forms.Form): SEVEN_DAYS = 7 FOURTEEN_DAYS = 14 THIRTY_DAYS = 30 SCHEDULE_CHOICES = [ (SEVEN_DAYS, 'Every 7 days'), (FOURTEEN_DAYS, 'Every 14 days'), (THIRTY_DAYS, 'Every 30 days'), ] TWELVE_OZ = 12 SIXTEEN_OZ = 16 FIVE_LBS = 75 SIZE_CHOICES = [ (TWELVE_OZ, '12 oz ($10.80)'), (SIXTEEN_OZ, '16 oz ($14.40)'), (FIVE_LBS, '5 lbs ($67.50)'), ] grind = forms.ChoiceField(choices=CoffeeGrind.GRIND_CHOICES) schedule = forms.ChoiceField(choices=SCHEDULE_CHOICES) size = forms.ChoiceField(choices=SIZE_CHOICES)