1from abc import ABC, abstractmethod
2from enum import Enum
3from functools import lru_cache
4from typing import Any, Dict, Type, Optional, Union
5
6from app.models.admin import Admin
7from app.models.notification import (
8 Notification,
9 AdminNotif,
10 UserNotification,
11 UserCreated,
12 UserUpdated,
13 UserActivated,
14 UserDeactivated,
15 UserDeleted,
16 UserEnabled,
17 UserDisabled,
18 UserDataUsageReset,
19 UserSubscriptionRevoked,
20 ReachedUsagePercent,
21 ReachedDaysLeft,
22)
23from app.models.user import UserResponse
24
25
26class NotificationFactory(ABC):
27 @abstractmethod
28 def create_notification(self, action: Enum, **kwargs: Any) -> Notification:
29 raise NotImplementedError()
30
31
32class AdminNotificationFactory(NotificationFactory):
33 def create_notification(self, action: Enum, **kwargs: Any) -> Notification:
34 pass
35
36
37class UserNotificationFactory(NotificationFactory):
38 Action = UserNotification.Action
39
40 notification_classes: Dict[
41 UserNotification.Action, Type[UserNotification]
42 ] = {
43 Action.user_created: UserCreated,
44 Action.user_updated: UserUpdated,
45 Action.user_activated: UserActivated,
46 Action.user_deactivated: UserDeactivated,
47 Action.user_deleted: UserDeleted,
48 Action.user_enabled: UserEnabled,
49 Action.user_disabled: UserDisabled,
50 Action.data_usage_reset: UserDataUsageReset,
51 Action.subscription_revoked: UserSubscriptionRevoked,
52 Action.reached_usage_percent: ReachedUsagePercent,
53 Action.reached_days_left: ReachedDaysLeft,
54 }
55
56 def create_notification(
57 self,
58 action: UserNotification.Action,
59 user: UserResponse,
60 by: Optional[Admin] = None,
61 **kwargs: Any
62 ) -> UserNotification:
63 notification_class = self.notification_classes.get(action)
64 return notification_class(user=user, by=by, **kwargs)
65
66
67class NotificationStrategy:
68 def __init__(self):
69 self.user_factory = UserNotificationFactory()
70 self.admin_factory = AdminNotificationFactory()
71
72 def create_notification(
73 self, action: Enum, **kwargs: Any
74 ) -> Union[UserNotification, AdminNotif]:
75 if isinstance(action, UserNotification.Action):
76 return self.user_factory.create_notification(action, **kwargs)
77 elif isinstance(action, AdminNotif.Action):
78 return self.admin_factory.create_notification(action, **kwargs)
79
80
81@lru_cache(maxsize=1)
82def get_notification_strategy() -> NotificationStrategy:
83 return NotificationStrategy()