Skip to content

Commit

Permalink
feat: Implement event service
Browse files Browse the repository at this point in the history
  • Loading branch information
sveneberth committed Feb 22, 2024
1 parent 71bd6ba commit be1c16e
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 13 deletions.
24 changes: 19 additions & 5 deletions src/viur/shop/modules/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

from viur.core import current, db, errors as core_errors, exposed, force_post
from viur.core.prototypes import List

from .abstract import ShopModuleAbstract
from .. import ClientError, exceptions as e
from ..constants import AddressType
from ..payment_providers import PaymentProviderAbstract
from ..response_types import JsonResponse
from ..services.hooks import Kind, hook_service
from ..services import EVENT_SERVICE, Event, HOOK_SERVICE, Hook
from ..skeletons.order import get_payment_providers

if t.TYPE_CHECKING:
Expand Down Expand Up @@ -160,6 +159,7 @@ def checkout_start(

order_skel = self.freeze_order(order_skel)
order_skel.toDB()
EVENT_SERVICE.call(Event.ORDER_STARTED, order_skel=order_skel)
return JsonResponse({
"skel": order_skel,
"payment": self.get_payment_provider_by_name(order_skel["payment_provider"]).get_checkout_start_data(
Expand Down Expand Up @@ -252,13 +252,15 @@ def checkout_order(
}, status_code=400)
raise e.InvalidStateError(", ".join(error_))

order_skel = hook_service.dispatch(Kind.ORDER_ASSIGN_UID, self.assign_uid)(order_skel)
order_skel["is_ordered"] = True
order_skel = HOOK_SERVICE.dispatch(Hook.ORDER_ASSIGN_UID, self.assign_uid)(order_skel)
# order_skel["is_ordered"] = True
# TODO: call hooks
# TODO: charge order if it should directly be charged
pp_res = self.get_payment_provider_by_name(order_skel["payment_provider"]).checkout(order_skel)
# TODO: write in transaction
order_skel.toDB()
# order_skel.toDB()
order_skel = self.set_ordered(order_skel, pp_res)
# EVENT_SERVICE.call(Event.ORDER_ORDERED, order_skel=order_skel, payment=pp_res)
return JsonResponse({
"skel": order_skel,
"payment": pp_res,
Expand All @@ -285,6 +287,18 @@ def can_order(
# TODO: ...
return errors

def set_ordered(self, order_skel: "SkeletonInstance", payment: t.Any) -> "SkeletonInstance":
order_skel["is_ordered"] = True # TODO: transaction
order_skel.toDB()
EVENT_SERVICE.call(Event.ORDER_ORDERED, order_skel=order_skel, payment=payment)
return order_skel

def set_paid(self, order_skel: "SkeletonInstance") -> "SkeletonInstance":
order_skel["is_paid"] = True # TODO: transaction
order_skel.toDB()
EVENT_SERVICE.call(Event.ORDER_PAID, order_skel=order_skel)
return order_skel

# --- Internal helpers ----------------------------------------------------
def get_payment_provider_by_name(
self,
Expand Down
5 changes: 3 additions & 2 deletions src/viur/shop/payment_providers/unzer_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ def return_handler(
logger.info(f'Order {order_skel["key"]} already marked as paid. Nothing to do.')
elif is_paid:
logger.info(f'Mark order {order_skel["key"]} as paid')
order_skel["is_paid"] = True # TODO: transaction
order_skel.toDB()
self.shop.order.set_paid(order_skel)
# order_skel["is_paid"] = True # TODO: transaction
# order_skel.toDB()
else:
raise errors.NotImplemented("Order not paid")
return "OKAY, paid"
Expand Down
10 changes: 10 additions & 0 deletions src/viur/shop/services/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .events import EVENT_SERVICE, Event, EventService, on_event
from .hooks import HOOK_SERVICE, Hook

__all__ = [
"EVENT_SERVICE",
"Event",
"on_event",
"HOOK_SERVICE",
"Hook",
]
58 changes: 58 additions & 0 deletions src/viur/shop/services/events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import collections
import enum
import logging
import typing as t

logger = logging.getLogger("viur.shop").getChild(__name__)


class Event(enum.IntEnum):
ORDER_STARTED = enum.auto()
ORDER_ORDERED = enum.auto()
ORDER_PAID = enum.auto()


class EventService:
observer: t.Final[dict[[Event, list[t.Callable]]]] = collections.defaultdict(list)

def register(self, event: Event, func: t.Callable) -> t.Callable:
if not isinstance(event, Event):
raise TypeError(f"event must be of type Event")
EventService.observer[event].append(func)
return func

def unregister(self, func: t.Callable, event: Event = None) -> None:
for event_, funcs in EventService.observer:
if event is None or event_ == Event:
try:
funcs.pop(func, )
except ValueError:
pass

def call(
self,
_event: Event,
_raise_errors: bool = False,
*args, **kwargs
) -> None:
for func in EventService.observer[_event]:
try:
func(*args, **kwargs)
except Exception as e:
logger.exception(f"Error while calling {func} at event {_event}: {e}")
if _raise_errors:
raise e


EVENT_SERVICE = EventService()


def on_event(event: Event) -> t.Callable:
if not isinstance(event, Event):
raise TypeError

def outer_wrapper(func: t.Callable) -> t.Callable:
EVENT_SERVICE.register(event, func)
return func

return outer_wrapper
8 changes: 4 additions & 4 deletions src/viur/shop/services/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
logger = logging.getLogger("viur.shop").getChild(__name__)


class Kind(enum.IntEnum):
class Hook(enum.IntEnum):
ORDER_ASSIGN_UID = enum.auto()


class Customization(abc.ABC):
@property
@abc.abstractmethod
def kind(self) -> Kind:
def kind(self) -> Hook:
...

@abc.abstractmethod
Expand All @@ -24,7 +24,7 @@ def __repr__(self) -> str:
return f"<Customization {self.__class__.__name__} for {self.kind.name}>"

@classmethod
def from_method(cls, func: t.Callable, kind: Kind) -> t.Self:
def from_method(cls, func: t.Callable, kind: Hook) -> t.Self:
return type(
f"{kind}_{func.__name__}{cls.__name__}",
(cls,),
Expand Down Expand Up @@ -57,4 +57,4 @@ def dispatch(self, kind: Customization, default: t.Callable = None):
return default


hook_service = HookService()
HOOK_SERVICE = HookService()
4 changes: 2 additions & 2 deletions src/viur/shop/shop.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from viur.core.prototypes.instanced_module import InstancedModule
from viur.core.skeleton import MetaSkel, Skeleton, skeletonByKind

from .services.hooks import hook_service
from .services.hooks import HOOK_SERVICE
from .types import Supplier
from .modules import Address, Api, Cart, Discount, DiscountCondition, Order, Shipping, ShippingConfig, Vat
from .payment_providers import PaymentProviderAbstract
Expand Down Expand Up @@ -38,7 +38,7 @@ def __init__(
*args, **kwargs,
):
super().__init__()
self.hooks = hook_service
self.hooks = HOOK_SERVICE

# Store arguments
self.name: str = name
Expand Down

0 comments on commit be1c16e

Please sign in to comment.