views.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. import json
  2. from django.core.mail import send_mail
  3. import locale
  4. import logging
  5. from django.contrib.auth import login
  6. from django.core.serializers.json import DjangoJSONEncoder
  7. from django.core.urlresolvers import reverse
  8. from django.conf import settings
  9. from django.forms import model_to_dict
  10. from django.http import HttpResponseRedirect, HttpResponse
  11. from django.shortcuts import render_to_response, get_object_or_404
  12. from django.template import RequestContext
  13. from accounts.forms import (ProfileSecondaryAddressForm, ProfileUpdateForm,
  14. ProfileCreateForm)
  15. from accounts.profile import get_profile, get_profile_secondary_address
  16. from accounts import utils as account_utils
  17. from cart.cart import add_to_cart, remove_subscriptions
  18. from catalog import models as catalog_models
  19. from catalog.models import Subscription
  20. from catalog.utils import get_type_by_profile, get_type
  21. from . import constants
  22. from . import forms
  23. from . import utils
  24. LOG = logging.getLogger(__name__)
  25. STOREFRONT_HELP_TO = getattr(settings, 'STOREFRONT_HELP_TO')
  26. def storefront_help(request):
  27. """ Store Help """
  28. form = forms.HelpForm(request.POST or None)
  29. if request.method == 'POST':
  30. if form.is_valid():
  31. message = ''.join(["{0}: {1}\n".format(
  32. key, value) for key, value in form.cleaned_data.iteritems()])
  33. LOG.info("Help Form Contents (Sending To: {0}): {1}".format(
  34. STOREFRONT_HELP_TO, message))
  35. send_mail(
  36. 'PBP Community Storefront Feedback',
  37. message,
  38. 'subscriptions@pbp.me',
  39. [STOREFRONT_HELP_TO],
  40. fail_silently=True)
  41. return HttpResponseRedirect(reverse('help_confirm'))
  42. return render_to_response(
  43. "storefront/help.html", {"form": form},
  44. context_instance=RequestContext(request))
  45. def storefront_help_confirm(request):
  46. """ Store Help Confirmation Page"""
  47. return render_to_response(
  48. "storefront/help_confirm.html", context_instance=RequestContext(
  49. request))
  50. def storefront_privacy(request):
  51. """ Store Help """
  52. return render_to_response(
  53. "storefront/privacy.html", context_instance=RequestContext(request))
  54. def storefront_index(request):
  55. """ Store Front Home page """
  56. return render_to_response(
  57. "storefront/index.html", context_instance=RequestContext(request))
  58. def category(request, category):
  59. """ Category page """
  60. # TODO: security, etc
  61. # TODO: sorting by price, or title.
  62. config = {'movie': catalog_models.Movie,
  63. 'book': catalog_models.Book,
  64. 'map': catalog_models.Map}
  65. sort_type = {'p': 'price', '-p': '-price', 't': 'title', '-t': '-title'}
  66. sort = request.GET.get('sort', 't')
  67. sort_by = sort_type.get(sort)
  68. model = config.get(category)
  69. # sort by title or price, asc or desc default to title asc
  70. items = model.objects.active().order_by(sort_by)
  71. return render_to_response(
  72. "storefront/category.html", {'items': items, 'category': category,
  73. 'sort_by': sort_by},
  74. context_instance=RequestContext(request))
  75. def item_price(request):
  76. """ Ajax call to return the item price """
  77. def _currency(value):
  78. """ convert value to a nice looking currency """
  79. try:
  80. locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
  81. except Exception:
  82. locale.setlocale(locale.LC_ALL, '')
  83. loc = locale.localeconv()
  84. return locale.currency(value, loc['currency_symbol'], grouping=True)
  85. response_data = "$N/A"
  86. if request.method == 'POST':
  87. try:
  88. LOG.debug("Post info: {0}".format(request.POST))
  89. # use the form data to determine the shipping_type
  90. region1 = request.POST.get('region1', None)
  91. postal_code1 = request.POST.get('postal_code1', None)
  92. country_code1 = request.POST.get('country_code1', None)
  93. region2 = request.POST.get('region2', None)
  94. postal_code2 = request.POST.get('postal_code2', None)
  95. country_code2 = request.POST.get('country_code2', None)
  96. shipping_type = get_type(
  97. postal_code1, region1, country_code1,
  98. postal_code2=postal_code2, region2=region2,
  99. country_code2=country_code2)
  100. LOG.debug("Found shipping type as: {0}".format(shipping_type))
  101. # Recast the id values to searchable values
  102. title = request.POST.get('title', None)
  103. duration = request.POST.get('duration', None)
  104. shipping_method = request.POST.get('shipping_method', None)
  105. title = utils.get_value_by_index(
  106. utils.unique_titles(shipping_type), title)
  107. duration = utils.get_value_by_index(
  108. utils.unique_durations(shipping_type), duration)
  109. shipping_method = utils.get_value_by_index(
  110. utils.unique_shipping_methods(), shipping_method)
  111. LOG.debug("{0}, {1}, {2}, {3}".format(
  112. title, duration, shipping_method, shipping_type))
  113. try:
  114. # Renewals are the same price as regular. This might
  115. # need to change if that changes
  116. subscription = Subscription.objects.get(
  117. title=title, duration=duration,
  118. shipping_type=shipping_type,
  119. shipping_method=shipping_method,
  120. renewal=False)
  121. response_data = _currency(subscription.price)
  122. except Subscription.DoesNotExist:
  123. pass
  124. except Exception, e:
  125. LOG.error(e)
  126. raise e
  127. return HttpResponse(
  128. json.dumps(response_data, cls=DjangoJSONEncoder),
  129. content_type="application/json")
  130. def item_detail(request, sku):
  131. item = get_object_or_404(catalog_models.Item, sku=sku).child
  132. return render_to_response("storefront/item_detail.html", {'item': item},
  133. context_instance=RequestContext(request))
  134. def subscription_home(request):
  135. """ Subscription Home page """
  136. return render_to_response(
  137. "storefront/subscriptions_home.html",
  138. context_instance=RequestContext(request))
  139. def choose_new_subscription(
  140. request, template="storefront/subscriptions_new.html"):
  141. """ View used to manage a new subscription """
  142. def _render(request, form, user_form, second_address_form, shipping_type):
  143. return render_to_response(
  144. template, {'form': form, 'userform': user_form,
  145. 'second_address': second_address_form,
  146. 'type': shipping_type},
  147. context_instance=RequestContext(request))
  148. # set some sane defaults
  149. user = request.user
  150. subscription_initial = {'duration': 1}
  151. primary_initial = {'region': 'ME', 'country': 'US'}
  152. secondary_initial = {}
  153. shipping_type = get_type(None, 'ME', 'US')
  154. if user.is_authenticated():
  155. profile = get_profile(user)
  156. secondary_address = get_profile_secondary_address(user)
  157. shipping_type = get_type_by_profile(profile)
  158. primary_initial = model_to_dict(user)
  159. primary_initial.update(model_to_dict(profile))
  160. secondary_initial = model_to_dict(secondary_address)
  161. user_form = ProfileUpdateForm(
  162. user, request.POST or None, initial=primary_initial,
  163. prefix='form2')
  164. else:
  165. user_form = ProfileCreateForm(
  166. request.POST or None, initial=primary_initial, prefix='form2')
  167. form = forms.SubscriptionForm(
  168. request.POST or None, initial=subscription_initial,
  169. shipping_type=shipping_type, prefix='form1')
  170. second_address_form = ProfileSecondaryAddressForm(
  171. request.POST or None, initial=secondary_initial, prefix='form3')
  172. if request.method == 'POST' and user_form.is_valid() and \
  173. second_address_form.is_valid():
  174. # we've called is_valid for both the profile and address forms
  175. shipping_type = get_type(
  176. user_form.cleaned_data.get('postal_code', None),
  177. user_form.cleaned_data.get('region', None),
  178. user_form.cleaned_data.get('country', None),
  179. postal_code2=second_address_form.cleaned_data.get(
  180. 'postal_code', None),
  181. region2=second_address_form.cleaned_data.get('region', None),
  182. country_code2=second_address_form.cleaned_data.get('country',
  183. None))
  184. form = forms.SubscriptionForm(
  185. request.POST or None, shipping_type=shipping_type,
  186. initial=subscription_initial, prefix='form1')
  187. if form.is_valid():
  188. user = user_form.save(request=request)
  189. second_address_form.save(user=user)
  190. subscription = form.save()
  191. remove_subscriptions(request)
  192. add_to_cart(request, subscription, quantity=1)
  193. return HttpResponseRedirect(reverse('checkout'))
  194. return _render(request, form, user_form, second_address_form,
  195. shipping_type)
  196. def choose_gift_subscription(
  197. request, template='storefront/subscriptions_gift_subs.html'):
  198. def render(subscription_form, gift_from_form, gift_to_form,
  199. gift_info_form):
  200. return render_to_response(
  201. template, {
  202. 'form': subscription_form,
  203. 'gift_from': gift_from_form,
  204. 'gift_to': gift_to_form,
  205. 'gift_info_form': gift_info_form},
  206. context_instance=RequestContext(request))
  207. # set some sane defaults
  208. shipping_type = get_type(None, 'ME', 'US')
  209. subscription_initial = {'duration': 1}
  210. gift_from_initial = {'region': 'ME', 'country': 'US'}
  211. gift_to_initial = {'region': 'ME', 'country': 'US'}
  212. user = request.user
  213. LOG.debug("Checking authentication status...")
  214. if user.is_authenticated():
  215. LOG.debug("User is authenticated...creating user specific forms.")
  216. gift_from_initial = model_to_dict(user)
  217. gift_from_initial.update(model_to_dict(user.get_profile()))
  218. shipping_type = get_type_by_profile(get_profile(user))
  219. gift_from_form = ProfileUpdateForm(
  220. user, request.POST or None, initial=gift_from_initial,
  221. prefix='form5')
  222. else:
  223. LOG.debug("User is not authenticated...creating user creation forms.")
  224. gift_from_form = ProfileCreateForm(
  225. request.POST or None, initial=gift_from_initial, prefix='form5')
  226. subscription_form = forms.SubscriptionForm(
  227. request.POST or None, shipping_type=shipping_type,
  228. initial=subscription_initial, prefix='form1')
  229. gift_to_form = forms.GiftToForm(
  230. request.POST or None, initial=gift_to_initial, prefix='form2')
  231. gift_info_form = forms.GiftInformationForm(
  232. request.POST or None, prefix='form4')
  233. if request.method == 'POST' and gift_from_form.is_valid():
  234. LOG.debug("Processing POST data...")
  235. # we've called is_valid on the gift from form and since we are
  236. # here..it is. We intentionally have not called saved so that a user
  237. # isn't created yet as this would cause confusion if the other forms
  238. # do not validate. We need the data from the cleaned form to pass to
  239. # the Subscription form which will determine if the subscription type
  240. # is valid.
  241. shipping_type = get_type(
  242. gift_from_form.cleaned_data.get('postal_code', None),
  243. gift_from_form.cleaned_data.get('region', None),
  244. gift_from_form.cleaned_data.get('country', None))
  245. subscription_form = forms.SubscriptionForm(
  246. request.POST or None, shipping_type=shipping_type,
  247. initial=subscription_initial, prefix='form1')
  248. LOG.debug("Checking validity of forms....")
  249. if gift_to_form.is_valid() and subscription_form.is_valid() and \
  250. gift_info_form.is_valid() and gift_from_form.is_valid():
  251. LOG.debug("Forms are valid...processing.")
  252. gift_from_form.save(request=request)
  253. subscription = subscription_form.save()
  254. gift_to_form.save()
  255. gift_detail = gift_to_form.cleaned_data or {}
  256. gift_detail.update(gift_info_form.cleaned_data)
  257. remove_subscriptions(request)
  258. add_to_cart(
  259. request, subscription, gift_detail=gift_detail,
  260. quantity=1)
  261. return HttpResponseRedirect(reverse('checkout'))
  262. else:
  263. LOG.debug("Forms are not valid.")
  264. LOG.debug("subscription_form: {0}".format(subscription_form))
  265. LOG.debug("gift_from_form: {0}".format(gift_from_form))
  266. LOG.debug("gift_to_form: {0}".format(gift_to_form))
  267. LOG.debug("gift_info_form: {0}".format(gift_info_form))
  268. return render(subscription_form, gift_from_form, gift_to_form,
  269. gift_info_form)
  270. def change_of_address(
  271. request, template='storefront/subscriptions_change_address.html'):
  272. """ Submits a change of address form. If the user is not logged in, it
  273. also creates a new user account.
  274. """
  275. # set some sane defaults
  276. user = request.user
  277. primary_initial = {'region': 'ME', 'country': 'US'}
  278. old_address_initial = {'region': 'ME', 'country': 'US'}
  279. form = forms.ChangeOfAddressForm(
  280. request.POST or None,
  281. initial={'date_effective': constants.NEXT_ISSUE})
  282. if user.is_authenticated():
  283. profile = get_profile(user)
  284. old_address_initial = model_to_dict(user)
  285. old_address_initial.update(model_to_dict(profile))
  286. old_address = forms.AddressForm(
  287. request.POST or None, initial=old_address_initial,
  288. prefix='form5')
  289. new_address = ProfileUpdateForm(
  290. user, request.POST or None, initial=primary_initial,
  291. prefix='form2')
  292. else:
  293. old_address = forms.AddressForm(
  294. request.POST or None, initial=old_address_initial, prefix='form5')
  295. new_address = ProfileCreateForm(
  296. request.POST or None, initial=primary_initial, prefix='form2')
  297. if request.method == 'POST':
  298. if (form.is_valid() and old_address.is_valid() and
  299. new_address.is_valid()):
  300. new_address.save(request=request)
  301. # recast the title index from the form to the
  302. # actual title
  303. raw_title = form.cleaned_data.get('title', None)
  304. title = utils.get_value_by_index(
  305. utils.unique_titles(), raw_title)
  306. old_address_initial.update(old_address.cleaned_data)
  307. account_utils.send_change_of_address_email(
  308. title,
  309. form.cleaned_data.get('account_number', None),
  310. form.cleaned_data.get('date_effective', None),
  311. form.cleaned_data.get('from_date', None),
  312. form.cleaned_data.get('to_date', None),
  313. old_address_initial,
  314. new_address.cleaned_data)
  315. return HttpResponseRedirect(
  316. reverse('subscriptions_address_change_complete'))
  317. return render_to_response(
  318. template, {
  319. 'form': form,
  320. 'old_address': old_address,
  321. 'new_address': new_address},
  322. context_instance=RequestContext(request))
  323. def change_of_address_complete(
  324. request,
  325. template='storefront/subscriptions_change_address_complete.html'):
  326. user = request.user
  327. new_address_initial = model_to_dict(user)
  328. new_address_initial.update(model_to_dict(user.get_profile()))
  329. new_address = forms.AddressForm(initial=new_address_initial)
  330. return render_to_response(
  331. template, {'new_address': new_address},
  332. context_instance=RequestContext(request))
  333. def subscriptions_renew(
  334. request, template='storefront/subscriptions_renewals.html'):
  335. def _render(request, form, userform, second_address_form, shipping_type):
  336. return render_to_response(
  337. template, {
  338. 'form': form, 'userform': userform,
  339. 'second_address': second_address_form, 'type': shipping_type},
  340. context_instance=RequestContext(request))
  341. # set some sane defaults
  342. user = request.user
  343. subscription_initial = {'duration': 1}
  344. primary_initial = {'region': 'ME', 'country': 'US'}
  345. secondary_initial = {}
  346. shipping_type = get_type(None, 'ME', 'US')
  347. if user.is_authenticated():
  348. profile = get_profile(user)
  349. secondary_address = get_profile_secondary_address(user)
  350. shipping_type = get_type_by_profile(profile)
  351. primary_initial = model_to_dict(user)
  352. primary_initial.update(model_to_dict(profile))
  353. secondary_initial = model_to_dict(secondary_address)
  354. userform = ProfileUpdateForm(
  355. user, request.POST or None, initial=primary_initial,
  356. prefix='form2')
  357. else:
  358. userform = ProfileCreateForm(
  359. request.POST or None, initial=primary_initial, prefix='form2')
  360. subscription_form = forms.SubscriptionForm(
  361. request.POST or None, initial=subscription_initial,
  362. shipping_type=shipping_type, prefix='form1', use_account_number=True,
  363. renewal=True)
  364. second_address_form = ProfileSecondaryAddressForm(
  365. request.POST or None, initial=secondary_initial, prefix='form3')
  366. if request.method == 'POST' and userform.is_valid() and \
  367. second_address_form.is_valid():
  368. # we've called is_valid for both the profile and address forms
  369. shipping_type = get_type(
  370. userform.cleaned_data.get('postal_code', None),
  371. userform.cleaned_data.get('region', None),
  372. userform.cleaned_data.get('country', None),
  373. postal_code2=second_address_form.cleaned_data.get(
  374. 'postal_code', None),
  375. region2=second_address_form.cleaned_data.get('region', None),
  376. country_code2=second_address_form.cleaned_data.get(
  377. 'country', None))
  378. subscription_form = forms.SubscriptionForm(
  379. request.POST or None, shipping_type=shipping_type,
  380. initial=subscription_initial, prefix='form1',
  381. use_account_number=True, renewal=True)
  382. if subscription_form.is_valid():
  383. user = userform.save(request=request)
  384. if not user.is_authenticated():
  385. login(request, user)
  386. second_address_form.save(user=user)
  387. subscription = subscription_form.save()
  388. account_number = \
  389. subscription_form.cleaned_data['account_number']
  390. remove_subscriptions(request)
  391. add_to_cart(request, subscription,
  392. account_number=account_number, quantity=1)
  393. return HttpResponseRedirect(reverse('checkout'))
  394. return _render(request, subscription_form, userform, second_address_form,
  395. shipping_type)