Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

views.py 11KB

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