import json from django.core.mail import send_mail import locale import logging from django.contrib.auth import login from django.core.serializers.json import DjangoJSONEncoder from django.core.urlresolvers import reverse from django.conf import settings from django.forms import model_to_dict from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from accounts.forms import (ProfileSecondaryAddressForm, ProfileUpdateForm, ProfileCreateForm) from accounts.profile import get_profile, get_profile_secondary_address from accounts import utils as account_utils from cart.cart import add_to_cart, remove_subscriptions from catalog import models as catalog_models from catalog.models import Subscription from catalog.utils import get_type_by_profile, get_type from . import constants from . import forms from . import utils LOG = logging.getLogger(__name__) STOREFRONT_HELP_TO = getattr(settings, 'STOREFRONT_HELP_TO') def storefront_help(request): """ Store Help """ form = forms.HelpForm(request.POST or None) if request.method == 'POST': if form.is_valid(): message = ''.join(["{0}: {1}\n".format( key, value) for key, value in form.cleaned_data.iteritems()]) LOG.info("Help Form Contents (Sending To: {0}): {1}".format( STOREFRONT_HELP_TO, message)) send_mail( 'PBP Community Storefront Feedback', message, 'subscriptions@pbp.me', [STOREFRONT_HELP_TO], fail_silently=True) return HttpResponseRedirect(reverse('help_confirm')) return render_to_response( "storefront/help.html", {"form": form}, context_instance=RequestContext(request)) def storefront_help_confirm(request): """ Store Help Confirmation Page""" return render_to_response( "storefront/help_confirm.html", context_instance=RequestContext( request)) def storefront_privacy(request): """ Store Help """ return render_to_response( "storefront/privacy.html", context_instance=RequestContext(request)) def storefront_index(request): """ Store Front Home page """ return render_to_response( "storefront/index.html", context_instance=RequestContext(request)) def category(request, category): """ Category page """ # TODO: security, etc # TODO: sorting by price, or title. config = {'movie': catalog_models.Movie, 'book': catalog_models.Book, 'map': catalog_models.Map} sort_type = {'p': 'price', '-p': '-price', 't': 'title', '-t': '-title'} sort = request.GET.get('sort', 't') sort_by = sort_type.get(sort) model = config.get(category) # sort by title or price, asc or desc default to title asc items = model.objects.active().order_by(sort_by) return render_to_response( "storefront/category.html", {'items': items, 'category': category, 'sort_by': sort_by}, context_instance=RequestContext(request)) def item_price(request): """ Ajax call to return the item price """ def _currency(value): """ convert value to a nice looking currency """ try: locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') except Exception: locale.setlocale(locale.LC_ALL, '') loc = locale.localeconv() return locale.currency(value, loc['currency_symbol'], grouping=True) response_data = "$N/A" if request.method == 'POST': try: LOG.debug("Post info: {0}".format(request.POST)) # use the form data to determine the shipping_type region1 = request.POST.get('region1', None) postal_code1 = request.POST.get('postal_code1', None) country_code1 = request.POST.get('country_code1', None) region2 = request.POST.get('region2', None) postal_code2 = request.POST.get('postal_code2', None) country_code2 = request.POST.get('country_code2', None) shipping_type = get_type( postal_code1, region1, country_code1, postal_code2=postal_code2, region2=region2, country_code2=country_code2) LOG.debug("Found shipping type as: {0}".format(shipping_type)) # Recast the id values to searchable values title = request.POST.get('title', None) duration = request.POST.get('duration', None) shipping_method = request.POST.get('shipping_method', None) title = utils.get_value_by_index( utils.unique_titles(shipping_type), title) duration = utils.get_value_by_index( utils.unique_durations(shipping_type), duration) shipping_method = utils.get_value_by_index( utils.unique_shipping_methods(), shipping_method) LOG.debug("{0}, {1}, {2}, {3}".format( title, duration, shipping_method, shipping_type)) try: # Renewals are the same price as regular. This might # need to change if that changes subscription = Subscription.objects.get( title=title, duration=duration, shipping_type=shipping_type, shipping_method=shipping_method, renewal=False) response_data = _currency(subscription.price) except Subscription.DoesNotExist: pass except Exception, e: LOG.error(e) raise e return HttpResponse( json.dumps(response_data, cls=DjangoJSONEncoder), content_type="application/json") def item_detail(request, sku): item = get_object_or_404(catalog_models.Item, sku=sku).child return render_to_response("storefront/item_detail.html", {'item': item}, context_instance=RequestContext(request)) def subscription_home(request): """ Subscription Home page """ return render_to_response( "storefront/subscriptions_home.html", context_instance=RequestContext(request)) def choose_new_subscription( request, template="storefront/subscriptions_new.html"): """ View used to manage a new subscription """ def _render(request, form, user_form, second_address_form, shipping_type): return render_to_response( template, {'form': form, 'userform': user_form, 'second_address': second_address_form, 'type': shipping_type}, context_instance=RequestContext(request)) # set some sane defaults user = request.user subscription_initial = {'duration': 1} primary_initial = {'region': 'ME', 'country': 'US'} secondary_initial = {} shipping_type = get_type(None, 'ME', 'US') if user.is_authenticated(): profile = get_profile(user) secondary_address = get_profile_secondary_address(user) shipping_type = get_type_by_profile(profile) primary_initial = model_to_dict(user) primary_initial.update(model_to_dict(profile)) secondary_initial = model_to_dict(secondary_address) user_form = ProfileUpdateForm( user, request.POST or None, initial=primary_initial, prefix='form2') else: user_form = ProfileCreateForm( request.POST or None, initial=primary_initial, prefix='form2') form = forms.SubscriptionForm( request.POST or None, initial=subscription_initial, shipping_type=shipping_type, prefix='form1') second_address_form = ProfileSecondaryAddressForm( request.POST or None, initial=secondary_initial, prefix='form3') if request.method == 'POST' and user_form.is_valid() and \ second_address_form.is_valid(): # we've called is_valid for both the profile and address forms shipping_type = get_type( user_form.cleaned_data.get('postal_code', None), user_form.cleaned_data.get('region', None), user_form.cleaned_data.get('country', None), postal_code2=second_address_form.cleaned_data.get( 'postal_code', None), region2=second_address_form.cleaned_data.get('region', None), country_code2=second_address_form.cleaned_data.get('country', None)) form = forms.SubscriptionForm( request.POST or None, shipping_type=shipping_type, initial=subscription_initial, prefix='form1') if form.is_valid(): user = user_form.save(request=request) second_address_form.save(user=user) subscription = form.save() remove_subscriptions(request) add_to_cart(request, subscription, quantity=1) return HttpResponseRedirect(reverse('checkout')) return _render(request, form, user_form, second_address_form, shipping_type) def choose_gift_subscription( request, template='storefront/subscriptions_gift_subs.html'): def render(subscription_form, gift_from_form, gift_to_form, gift_info_form): return render_to_response( template, { 'form': subscription_form, 'gift_from': gift_from_form, 'gift_to': gift_to_form, 'gift_info_form': gift_info_form}, context_instance=RequestContext(request)) # set some sane defaults shipping_type = get_type(None, 'ME', 'US') subscription_initial = {'duration': 1} gift_from_initial = {'region': 'ME', 'country': 'US'} gift_to_initial = {'region': 'ME', 'country': 'US'} user = request.user LOG.debug("Checking authentication status...") if user.is_authenticated(): LOG.debug("User is authenticated...creating user specific forms.") gift_from_initial = model_to_dict(user) gift_from_initial.update(model_to_dict(user.get_profile())) shipping_type = get_type_by_profile(get_profile(user)) gift_from_form = ProfileUpdateForm( user, request.POST or None, initial=gift_from_initial, prefix='form5') else: LOG.debug("User is not authenticated...creating user creation forms.") gift_from_form = ProfileCreateForm( request.POST or None, initial=gift_from_initial, prefix='form5') subscription_form = forms.SubscriptionForm( request.POST or None, shipping_type=shipping_type, initial=subscription_initial, prefix='form1') gift_to_form = forms.GiftToForm( request.POST or None, initial=gift_to_initial, prefix='form2') gift_info_form = forms.GiftInformationForm( request.POST or None, prefix='form4') if request.method == 'POST' and gift_from_form.is_valid(): LOG.debug("Processing POST data...") # we've called is_valid on the gift from form and since we are # here..it is. We intentionally have not called saved so that a user # isn't created yet as this would cause confusion if the other forms # do not validate. We need the data from the cleaned form to pass to # the Subscription form which will determine if the subscription type # is valid. shipping_type = get_type( gift_from_form.cleaned_data.get('postal_code', None), gift_from_form.cleaned_data.get('region', None), gift_from_form.cleaned_data.get('country', None)) subscription_form = forms.SubscriptionForm( request.POST or None, shipping_type=shipping_type, initial=subscription_initial, prefix='form1') LOG.debug("Checking validity of forms....") if gift_to_form.is_valid() and subscription_form.is_valid() and \ gift_info_form.is_valid() and gift_from_form.is_valid(): LOG.debug("Forms are valid...processing.") gift_from_form.save(request=request) subscription = subscription_form.save() gift_to_form.save() gift_detail = gift_to_form.cleaned_data or {} gift_detail.update(gift_info_form.cleaned_data) remove_subscriptions(request) add_to_cart( request, subscription, gift_detail=gift_detail, quantity=1) return HttpResponseRedirect(reverse('checkout')) else: LOG.debug("Forms are not valid.") LOG.debug("subscription_form: {0}".format(subscription_form)) LOG.debug("gift_from_form: {0}".format(gift_from_form)) LOG.debug("gift_to_form: {0}".format(gift_to_form)) LOG.debug("gift_info_form: {0}".format(gift_info_form)) return render(subscription_form, gift_from_form, gift_to_form, gift_info_form) def change_of_address( request, template='storefront/subscriptions_change_address.html'): """ Submits a change of address form. If the user is not logged in, it also creates a new user account. """ # set some sane defaults user = request.user primary_initial = {'region': 'ME', 'country': 'US'} old_address_initial = {'region': 'ME', 'country': 'US'} form = forms.ChangeOfAddressForm( request.POST or None, initial={'date_effective': constants.NEXT_ISSUE}) if user.is_authenticated(): profile = get_profile(user) old_address_initial = model_to_dict(user) old_address_initial.update(model_to_dict(profile)) old_address = forms.AddressForm( request.POST or None, initial=old_address_initial, prefix='form5') new_address = ProfileUpdateForm( user, request.POST or None, initial=primary_initial, prefix='form2') else: old_address = forms.AddressForm( request.POST or None, initial=old_address_initial, prefix='form5') new_address = ProfileCreateForm( request.POST or None, initial=primary_initial, prefix='form2') if request.method == 'POST': if (form.is_valid() and old_address.is_valid() and new_address.is_valid()): new_address.save(request=request) # recast the title index from the form to the # actual title raw_title = form.cleaned_data.get('title', None) title = utils.get_value_by_index( utils.unique_titles(), raw_title) old_address_initial.update(old_address.cleaned_data) account_utils.send_change_of_address_email( title, form.cleaned_data.get('account_number', None), form.cleaned_data.get('date_effective', None), form.cleaned_data.get('from_date', None), form.cleaned_data.get('to_date', None), old_address_initial, new_address.cleaned_data) return HttpResponseRedirect( reverse('subscriptions_address_change_complete')) return render_to_response( template, { 'form': form, 'old_address': old_address, 'new_address': new_address}, context_instance=RequestContext(request)) def change_of_address_complete( request, template='storefront/subscriptions_change_address_complete.html'): user = request.user new_address_initial = model_to_dict(user) new_address_initial.update(model_to_dict(user.get_profile())) new_address = forms.AddressForm(initial=new_address_initial) return render_to_response( template, {'new_address': new_address}, context_instance=RequestContext(request)) def subscriptions_renew( request, template='storefront/subscriptions_renewals.html'): def _render(request, form, userform, second_address_form, shipping_type): return render_to_response( template, { 'form': form, 'userform': userform, 'second_address': second_address_form, 'type': shipping_type}, context_instance=RequestContext(request)) # set some sane defaults user = request.user subscription_initial = {'duration': 1} primary_initial = {'region': 'ME', 'country': 'US'} secondary_initial = {} shipping_type = get_type(None, 'ME', 'US') if user.is_authenticated(): profile = get_profile(user) secondary_address = get_profile_secondary_address(user) shipping_type = get_type_by_profile(profile) primary_initial = model_to_dict(user) primary_initial.update(model_to_dict(profile)) secondary_initial = model_to_dict(secondary_address) userform = ProfileUpdateForm( user, request.POST or None, initial=primary_initial, prefix='form2') else: userform = ProfileCreateForm( request.POST or None, initial=primary_initial, prefix='form2') subscription_form = forms.SubscriptionForm( request.POST or None, initial=subscription_initial, shipping_type=shipping_type, prefix='form1', use_account_number=True, renewal=True) second_address_form = ProfileSecondaryAddressForm( request.POST or None, initial=secondary_initial, prefix='form3') if request.method == 'POST' and userform.is_valid() and \ second_address_form.is_valid(): # we've called is_valid for both the profile and address forms shipping_type = get_type( userform.cleaned_data.get('postal_code', None), userform.cleaned_data.get('region', None), userform.cleaned_data.get('country', None), postal_code2=second_address_form.cleaned_data.get( 'postal_code', None), region2=second_address_form.cleaned_data.get('region', None), country_code2=second_address_form.cleaned_data.get( 'country', None)) subscription_form = forms.SubscriptionForm( request.POST or None, shipping_type=shipping_type, initial=subscription_initial, prefix='form1', use_account_number=True, renewal=True) if subscription_form.is_valid(): user = userform.save(request=request) if not user.is_authenticated(): login(request, user) second_address_form.save(user=user) subscription = subscription_form.save() account_number = \ subscription_form.cleaned_data['account_number'] remove_subscriptions(request) add_to_cart(request, subscription, account_number=account_number, quantity=1) return HttpResponseRedirect(reverse('checkout')) return _render(request, subscription_form, userform, second_address_form, shipping_type)