import warnings
from ._process import CheckoutProcess
from ._storage import CheckoutPhaseStorage
class CheckoutPhaseViewMixin:
identifier = None
title = None # User-visible
final = False # Should be set for final steps (those that may be accessed via the previous step's URL)
phases = () # set as an instance variable; likely accessed via template (`view.phases`)
next_phase = None # set as an instance variable
previous_phase = None # set as an instance variable
request = None # exists via being a view
[docs]
def __init__(self, checkout_process=None, horizontal_template=True, *args, **kwargs):
"""
Initialize a checkout phase view.
:type checkout_process: shuup.front.checkout.CheckoutProcess|None
:param checkout_process: The checkout process of this phase.
:type horizontal_template: bool
:param horizontal_template:
Set this to False if you want to use single page checkout.
"""
# TODO: (2.0) Make checkout_process argument mandatory
if not checkout_process:
warnings.warn(
"Warning! Using checkout view without a checkout process is deprecated.",
DeprecationWarning,
2,
)
self._checkout_process = checkout_process
self.horizontal_template = horizontal_template
super().__init__(*args, **kwargs)
@property
def checkout_process(self):
"""
Get the checkout process of this phase.
:rtype: shuup.front.checkout.CheckoutProcess
"""
if not self._checkout_process:
self._checkout_process = _get_dummy_checkout_process(self)
return self._checkout_process
[docs]
def is_visible_for_user(self):
return bool(self.title)
[docs]
def is_valid(self):
return True
[docs]
def should_skip(self):
return False
[docs]
def process(self):
raise NotImplementedError(
"Error! Not implemented: `CheckoutPhaseViewMixin` -> `process()`. "
f"`process()` MUST be overridden in {self.__class__!r}."
)
[docs]
def reset(self):
self.storage.reset()
[docs]
def get_success_url(self, *args, **kwargs):
if self.next_phase:
return self.checkout_process.get_phase_url(self.next_phase)
next_obj = super()
if hasattr(next_obj, "get_success_url"):
return next_obj.get_success_url(*args, **kwargs)
[docs]
def get_url(self):
return self.checkout_process.get_phase_url(self)
@property
def basket(self):
"""
The basket used in this checkout phase.
:rtype: shuup.front.basket.objects.BaseBasket
"""
return self.checkout_process.basket
@property
def storage(self):
if not hasattr(self, "_storage"):
self._storage = CheckoutPhaseStorage(request=self.request, phase_identifier=self.identifier)
return self._storage
[docs]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["current_phase_url"] = self.get_url()
context["next_phase_url"] = self.next_phase.get_url() if self.next_phase else None
context["previous_phase_url"] = self.previous_phase.get_url() if self.previous_phase else None
context["phase_urls"] = {phase.identifier: phase.get_url() for phase in self.phases}
return context
[docs]
@classmethod
def spawn_phases(cls, checkout_process):
"""
Returns an iterator of new phases generated by this phase for the given checkout process
:type checkout_process: shuup.front.checkout.CheckoutProcess
:param checkout_process: The checkout process to check for new phases.
"""
return []
def _get_dummy_checkout_process(phase):
phase_specs = [f"{type(phase).__module__}:{type(phase).__name__}"]
phase_kwargs = {key: getattr(phase, key) for key in ["request", "args", "kwargs"] if hasattr(phase, key)}
checkout_process = CheckoutProcess(phase_specs, phase_kwargs)
checkout_process._phases = [phase]
checkout_process.horizontal_template = phase.horizontal_template
return checkout_process