You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.py 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import datetime
  2. from django.views.generic import ListView, FormView, DeleteView, DetailView
  3. from django.db.models.loading import get_model
  4. from django.core.urlresolvers import reverse
  5. from django.contrib import messages
  6. from django.http import HttpResponseRedirect
  7. from django.shortcuts import get_object_or_404
  8. from oscar.core.loading import get_classes
  9. ConditionalOffer = get_model('offer', 'ConditionalOffer')
  10. Condition= get_model('offer', 'Condition')
  11. OrderDiscount = get_model('order', 'OrderDiscount')
  12. Benefit = get_model('offer', 'Benefit')
  13. MetaDataForm, ConditionForm, BenefitForm, PreviewForm, OfferSearchForm = get_classes(
  14. 'dashboard.offers.forms', [
  15. 'MetaDataForm', 'ConditionForm', 'BenefitForm', 'PreviewForm',
  16. 'OfferSearchForm'])
  17. class OfferListView(ListView):
  18. model = ConditionalOffer
  19. context_object_name = 'offers'
  20. template_name = 'dashboard/offers/offer_list.html'
  21. form_class = OfferSearchForm
  22. def get_queryset(self):
  23. qs = self.model._default_manager.all()
  24. self.description = "All offers"
  25. self.form = self.form_class(self.request.GET)
  26. if not self.form.is_valid():
  27. return qs
  28. data = self.form.cleaned_data
  29. if data['name']:
  30. qs = qs.filter(name__icontains=data['name'])
  31. self.description = "Offers matching '%s'" % data['name']
  32. if data['is_active']:
  33. today = datetime.date.today()
  34. qs = qs.filter(start_date__lte=today, end_date__gt=today)
  35. return qs
  36. def get_context_data(self, **kwargs):
  37. ctx = super(OfferListView, self).get_context_data(**kwargs)
  38. ctx['queryset_description'] = self.description
  39. ctx['form'] = self.form
  40. return ctx
  41. class OfferWizardStepView(FormView):
  42. wizard_name = 'offer_wizard'
  43. form_class = None
  44. step_name = None
  45. update = False
  46. url_name = None
  47. # Keep a reference to previous view class to allow checks to be made on whether
  48. # prior steps have been completed
  49. previous_view = None
  50. def get(self, request, *args, **kwargs):
  51. if self.update:
  52. self.offer = get_object_or_404(ConditionalOffer, id=kwargs['pk'])
  53. if not self.is_previous_step_complete(request):
  54. messages.warning(request, "%s step not complete" % self.previous_view.step_name.title())
  55. return HttpResponseRedirect(self.get_back_url())
  56. return super(OfferWizardStepView, self).get(request, *args, **kwargs)
  57. def post(self, request, *args, **kwargs):
  58. if self.update:
  59. self.offer = get_object_or_404(ConditionalOffer, id=kwargs['pk'])
  60. if not self.is_previous_step_complete(request):
  61. messages.warning(request, "%s step not complete" %
  62. self.previous_view.step_name.title())
  63. return HttpResponseRedirect(self.get_back_url())
  64. return super(OfferWizardStepView, self).post(request, *args, **kwargs)
  65. def is_previous_step_complete(self, request):
  66. if not self.previous_view:
  67. return True
  68. return self.previous_view.is_valid(self, request)
  69. def _key(self, step_name=None, is_object=False):
  70. key = step_name if step_name else self.step_name
  71. if self.update:
  72. key += str(self.offer.id)
  73. if is_object:
  74. key += '_obj'
  75. return key
  76. def _store_form_kwargs(self, form):
  77. session_data = self.request.session.setdefault(self.wizard_name, {})
  78. form_kwargs = {'data': form.cleaned_data.copy()}
  79. session_data[self._key()] = form_kwargs
  80. self.request.session.save()
  81. def _fetch_form_kwargs(self, step_name=None):
  82. if not step_name:
  83. step_name = self.step_name
  84. session_data = self.request.session.setdefault(self.wizard_name, {})
  85. return session_data.get(self._key(step_name), {})
  86. def _store_object(self, form):
  87. session_data = self.request.session.setdefault(self.wizard_name, {})
  88. session_data[self._key(is_object=True)] = form.save(commit=False)
  89. self.request.session.save()
  90. def _fetch_object(self, step_name):
  91. session_data = self.request.session.setdefault(self.wizard_name, {})
  92. return session_data.get(self._key(step_name, is_object=True), None)
  93. def _flush_session(self):
  94. self.request.session[self.wizard_name] = {}
  95. self.request.session.save()
  96. def get_form_kwargs(self, *args, **kwargs):
  97. form_kwargs = {}
  98. if self.update:
  99. form_kwargs['instance'] = self.get_instance()
  100. session_kwargs = self._fetch_form_kwargs()
  101. form_kwargs.update(session_kwargs)
  102. parent_kwargs = super(OfferWizardStepView, self).get_form_kwargs(*args, **kwargs)
  103. form_kwargs.update(parent_kwargs)
  104. return form_kwargs
  105. def get_context_data(self, **kwargs):
  106. ctx = super(OfferWizardStepView, self).get_context_data(**kwargs)
  107. if self.update:
  108. ctx['pk'] = self.kwargs.get('pk', None)
  109. ctx['back_url'] = self.get_back_url()
  110. ctx['title'] = self.get_title()
  111. return ctx
  112. def get_back_url(self):
  113. if not self.previous_view:
  114. return None
  115. if self.update:
  116. return reverse(self.previous_view.url_name,
  117. kwargs={'pk': self.kwargs['pk']})
  118. return reverse(self.previous_view.url_name)
  119. def get_title(self):
  120. if self.update:
  121. return "Edit %s for offer #%d" % (self.step_name, self.offer.id)
  122. return 'Create new offer: %s' % self.step_name
  123. def form_valid(self, form):
  124. self._store_form_kwargs(form)
  125. self._store_object(form)
  126. return super(OfferWizardStepView, self).form_valid(form)
  127. def get_success_url(self):
  128. if self.update:
  129. return reverse(self.success_url_name,
  130. kwargs={'pk': self.kwargs['pk']})
  131. return reverse(self.success_url_name)
  132. @classmethod
  133. def is_valid(cls, current_view, request):
  134. if current_view.update:
  135. return True
  136. return current_view._fetch_object(cls.step_name) is not None
  137. class OfferMetaDataView(OfferWizardStepView):
  138. step_name = 'metadata'
  139. form_class = MetaDataForm
  140. template_name = 'dashboard/offers/metadata_form.html'
  141. url_name = 'dashboard:offer-metadata'
  142. success_url_name = 'dashboard:offer-condition'
  143. def get_instance(self):
  144. return self.offer
  145. class OfferConditionView(OfferWizardStepView):
  146. step_name = 'condition'
  147. form_class = ConditionForm
  148. template_name = 'dashboard/offers/condition_form.html'
  149. url_name = 'dashboard:offer-condition'
  150. success_url_name = 'dashboard:offer-benefit'
  151. previous_view = OfferMetaDataView
  152. def get_instance(self):
  153. return self.offer.condition
  154. class OfferBenefitView(OfferWizardStepView):
  155. step_name = 'benefit'
  156. form_class = BenefitForm
  157. template_name = 'dashboard/offers/benefit_form.html'
  158. url_name = 'dashboard:offer-benefit'
  159. success_url_name = 'dashboard:offer-preview'
  160. previous_view = OfferConditionView
  161. def get_instance(self):
  162. return self.offer.benefit
  163. class OfferPreviewView(OfferWizardStepView):
  164. step_name = 'preview'
  165. form_class = PreviewForm
  166. template_name = 'dashboard/offers/preview.html'
  167. previous_view = OfferBenefitView
  168. url_name = 'dashboard:offer-preview'
  169. def get_context_data(self, **kwargs):
  170. ctx = super(OfferPreviewView, self).get_context_data(**kwargs)
  171. ctx['offer'] = self._fetch_object('metadata') or self.offer
  172. ctx['condition'] = self._fetch_object('condition') or self.offer.condition
  173. ctx['benefit'] = self._fetch_object('benefit') or self.offer.benefit
  174. return ctx
  175. def get_form_kwargs(self, *args, **kwargs):
  176. return super(OfferWizardStepView, self).get_form_kwargs(*args, **kwargs)
  177. def form_valid(self, form):
  178. condition = self._fetch_object('condition') or self.offer.condition
  179. condition.save()
  180. benefit = self._fetch_object('benefit') or self.offer.benefit
  181. benefit.save()
  182. offer = self._fetch_object('metadata') or self.offer
  183. offer.condition = condition
  184. offer.benefit = benefit
  185. offer.save()
  186. self._flush_session()
  187. if self.update:
  188. msg = "Offer #%d updated" % offer.id
  189. else:
  190. msg = "Offer created!"
  191. messages.success(self.request, msg)
  192. return HttpResponseRedirect(self.get_success_url())
  193. def get_title(self):
  194. if self.update:
  195. return "Preview offer #%d" % self.offer.id
  196. return 'Preview offer'
  197. def get_success_url(self):
  198. return reverse('dashboard:offer-list')
  199. class OfferDeleteView(DeleteView):
  200. model = ConditionalOffer
  201. template_name = 'dashboard/offers/offer_delete.html'
  202. context_object_name = 'offer'
  203. def get_success_url(self):
  204. messages.success(self.request, "Offer deleted!")
  205. return reverse('dashboard:offer-list')
  206. class OfferDetailView(DetailView):
  207. model = ConditionalOffer
  208. template_name = 'dashboard/offers/offer_detail.html'
  209. context_object_name = 'offer'
  210. def get_context_data(self, **kwargs):
  211. ctx = super(OfferDetailView, self).get_context_data(**kwargs)
  212. ctx['order_discounts'] = OrderDiscount.objects.filter(offer_id=self.object.id).order_by('-id')
  213. return ctx