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 )