elemento-loyalty-processing 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ prune *
2
+ include app/__init__.py
3
+ include app/client.py
4
+ include app/types.py
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: elemento-loyalty-processing
3
+ Version: 1.0.0
4
+ Summary: Elemento Loyalty Processing
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: kaiju-tools<3,>=2.4.9
7
+ Requires-Dist: kaiju-models<2,>=1.0.4
8
+ Provides-Extra: server
9
+ Requires-Dist: kaiju-db<3,>=2.3.0; extra == "server"
10
+ Requires-Dist: kaiju-redis<3,>=2.4.1; extra == "server"
11
+ Provides-Extra: dev
12
+ Requires-Dist: kaiju-tools[dev]; extra == "dev"
File without changes
@@ -0,0 +1,5 @@
1
+ """Project information."""
2
+
3
+ __author__ = "Anton Taraskin"
4
+ __email__ = "hel.nidhoggr@gmail.com"
5
+ __version__ = "1.0.0"
@@ -0,0 +1,129 @@
1
+ """RPC client services for customer app."""
2
+
3
+ import datetime
4
+ from typing import Any
5
+
6
+ from kaiju_tools.http import RPCClientService
7
+ from kaiju_tools.services import SERVICE_CLASS_REGISTRY
8
+
9
+ from .types import *
10
+
11
+
12
+ class ElementoLoyaltyProcessingClient(RPCClientService):
13
+ """Auto-generated ElementoCustomers RPC client."""
14
+
15
+ async def lists_set_product_list(
16
+ self, id: ListId, items: list[str], _max_timeout: int = None, _nowait: bool = False
17
+ ):
18
+ """Call Lists.products.set."""
19
+ return await self.call(
20
+ method="Lists.products.set", params=dict(id=id, items=items), max_timeout=_max_timeout, nowait=_nowait
21
+ )
22
+
23
+ async def lists_get_product_list(self, id: ListId, _max_timeout: int = None, _nowait: bool = False):
24
+ """Call Lists.products.get."""
25
+ return await self.call(
26
+ method="Lists.products.get", params=dict(id=id), max_timeout=_max_timeout, nowait=_nowait
27
+ )
28
+
29
+ async def lists_set_store_list(self, id: ListId, items: list[str], _max_timeout: int = None, _nowait: bool = False):
30
+ """Call Lists.stores.set."""
31
+ return await self.call(
32
+ method="Lists.stores.set", params=dict(id=id, items=items), max_timeout=_max_timeout, nowait=_nowait
33
+ )
34
+
35
+ async def lists_get_store_list(self, id: ListId, _max_timeout: int = None, _nowait: bool = False):
36
+ """Call Lists.stores.get."""
37
+ return await self.call(method="Lists.stores.get", params=dict(id=id), max_timeout=_max_timeout, nowait=_nowait)
38
+
39
+ async def balance_get_balance(
40
+ self, customer_id: CustomerId, _max_timeout: int = None, _nowait: bool = False
41
+ ) -> Points:
42
+ """Call Balance.get."""
43
+ return await self.call(
44
+ method="Balance.get", params=dict(customer_id=customer_id), max_timeout=_max_timeout, nowait=_nowait
45
+ )
46
+
47
+ async def balance_calculate(
48
+ self,
49
+ customer: dict[str, Any],
50
+ items: list[Item],
51
+ custom_attributes: dict[str, Any] = None,
52
+ points_sub: int = 0,
53
+ transaction_id: TransactionId = None,
54
+ order_id: str = None,
55
+ timestamp: datetime.datetime = None,
56
+ actions: list[BalanceAction | str] = None,
57
+ meta: dict[str, Any] = None,
58
+ _max_timeout: int = None,
59
+ _nowait: bool = False,
60
+ ) -> Cart:
61
+ """Call Balance.calculate_cart."""
62
+ return await self.call(
63
+ method="Balance.calculate_cart",
64
+ params=dict(
65
+ customer=customer,
66
+ items=items,
67
+ custom_attributes=custom_attributes,
68
+ points_sub=points_sub,
69
+ transaction_id=transaction_id,
70
+ order_id=order_id,
71
+ timestamp=timestamp,
72
+ actions=actions,
73
+ meta=meta,
74
+ ),
75
+ max_timeout=_max_timeout,
76
+ nowait=_nowait,
77
+ )
78
+
79
+ async def balance_confirm_transaction(
80
+ self, transaction_id: TransactionId, _max_timeout: int = None, _nowait: bool = False
81
+ ) -> None:
82
+ """Call Balance.transaction.confirm."""
83
+ return await self.call(
84
+ method="Balance.transaction.confirm",
85
+ params=dict(transaction_id=transaction_id),
86
+ max_timeout=_max_timeout,
87
+ nowait=_nowait,
88
+ )
89
+
90
+ async def balance_revert_transaction(
91
+ self, transaction_id: TransactionId, _max_timeout: int = None, _nowait: bool = False
92
+ ) -> None:
93
+ """Call Balance.transaction.revert."""
94
+ return await self.call(
95
+ method="Balance.transaction.revert",
96
+ params=dict(transaction_id=transaction_id),
97
+ max_timeout=_max_timeout,
98
+ nowait=_nowait,
99
+ )
100
+
101
+ async def balance_commit_transaction(
102
+ self, transaction_id: TransactionId, _max_timeout: int = None, _nowait: bool = False
103
+ ) -> None:
104
+ """Call Balance.transaction.commit."""
105
+ return await self.call(
106
+ method="Balance.transaction.commit",
107
+ params=dict(transaction_id=transaction_id),
108
+ max_timeout=_max_timeout,
109
+ nowait=_nowait,
110
+ )
111
+
112
+ async def balance_create_event(
113
+ self,
114
+ customer: dict[str, Any],
115
+ event_type: EventTypeId,
116
+ meta: dict[str, Any] = None,
117
+ _max_timeout: int = None,
118
+ _nowait: bool = False,
119
+ ) -> bool:
120
+ """Call Balance.create_event."""
121
+ return await self.call(
122
+ method="Balance.create_event",
123
+ params=dict(customer=customer, event_type=event_type, meta=meta),
124
+ max_timeout=_max_timeout,
125
+ nowait=_nowait,
126
+ )
127
+
128
+
129
+ SERVICE_CLASS_REGISTRY.register(ElementoLoyaltyProcessingClient)
@@ -0,0 +1,152 @@
1
+ from datetime import date, datetime
2
+ from decimal import Decimal
3
+ from enum import Enum
4
+ from typing import Any, NewType, TypedDict
5
+
6
+ from msgspec import Struct
7
+
8
+
9
+ __all__ = [
10
+ "DATE_MAXVALUE",
11
+ "ListId",
12
+ "CustomerId",
13
+ "ItemList",
14
+ "ItemListType",
15
+ "EventTypeId",
16
+ "BalanceStatus",
17
+ "Balance",
18
+ "TransactionType",
19
+ "OrderItem",
20
+ "TransactionId",
21
+ "CustomerId",
22
+ "Transaction",
23
+ "EventTypeId",
24
+ "Item",
25
+ "Cart",
26
+ "BalanceAction",
27
+ "Customer",
28
+ "StoredTransaction",
29
+ "OfferId",
30
+ "GroupId",
31
+ "OfferEventTypes",
32
+ "ConditionId",
33
+ "LifetimeId",
34
+ "ActionId",
35
+ "Points",
36
+ ]
37
+
38
+ DATE_MAXVALUE = date.fromisoformat("3000-01-01")
39
+
40
+ TransactionId = NewType("TransactionId", str)
41
+ EventTypeId = NewType("EventTypeId", str)
42
+ ListId = NewType("ListId", str)
43
+ CustomerId = NewType("CustomerId", int)
44
+ OfferId = NewType("OfferId", int)
45
+ LifetimeId = NewType("LifetimeId", int)
46
+ GroupId = NewType("GroupId", int)
47
+ ConditionId = NewType("ConditionId", int)
48
+ ActionId = NewType("ActionId", int)
49
+ Points = NewType("Points", int)
50
+
51
+
52
+ class OfferEventTypes(Enum):
53
+ PointsAdd = "PointsAdd"
54
+ PointsUse = "PointsUse"
55
+ Purchase = "Purchase"
56
+ Return = "Return"
57
+ Birthday = "Birthday"
58
+ RegistrationDone = "RegistrationDone"
59
+
60
+
61
+ class Customer(TypedDict):
62
+ id: CustomerId
63
+ profile: dict[str, Any]
64
+
65
+
66
+ class ItemListType(Enum):
67
+ STORE = "STORE"
68
+ PRODUCT = "PRODUCT"
69
+ TERMINAL = "TERMINAL"
70
+
71
+
72
+ class ItemList(Struct):
73
+ type: ItemListType
74
+ id: ListId
75
+ items: frozenset[str]
76
+
77
+
78
+ class BalanceStatus(Enum):
79
+ FUTURE = "FUTURE"
80
+ HOLD = "HOLD"
81
+ ACTIVE = "ACTIVE"
82
+
83
+
84
+ class Balance(Struct):
85
+ customer_id: CustomerId
86
+ active_from: date
87
+ active_to: date
88
+ status: BalanceStatus
89
+ amount: int
90
+ transaction_id: TransactionId | None = None
91
+
92
+
93
+ class OrderItem(Struct):
94
+ product_id: str
95
+ quantity: int
96
+ price: Decimal
97
+ balance: Points
98
+ active: bool
99
+
100
+
101
+ class TransactionType(Enum):
102
+ ORDER = "ORDER"
103
+ SCRIPT = "SCRIPT"
104
+
105
+
106
+ class StoredTransaction(Struct):
107
+ created: datetime
108
+ customer_id: CustomerId
109
+ type: TransactionType
110
+ ext_id: TransactionId | None = None
111
+ order_id: str | None = None
112
+ active: bool = True
113
+ meta: dict[str, Any] | None = None
114
+ items: list[OrderItem] | None = None
115
+ id: int = None
116
+
117
+
118
+ class BalanceAction(Enum):
119
+ CALC = "CALC"
120
+ SUB = "SUB"
121
+ ADD = "ADD"
122
+
123
+
124
+ class Item(Struct):
125
+ pos: int
126
+ product_id: str
127
+ quantity: int
128
+ total: Decimal
129
+ price: Decimal
130
+ cashback: Points = 0
131
+ discount: Decimal = Decimal("0.00")
132
+ points_add: Points = 0
133
+ points_sub: Points = 0
134
+ points_sub_max: Points = 0
135
+
136
+
137
+ class Cart(Struct):
138
+ points_add: Points
139
+ points_sub: Points
140
+ points_sub_max: Points
141
+ items: list[Item]
142
+ cashier_message: str | None = None
143
+ customer_message: str | None = None
144
+
145
+
146
+ class Transaction(Struct):
147
+ id: TransactionId = None
148
+ order_id: str = None
149
+ customer_id: CustomerId = None
150
+ timestamp: datetime = None
151
+ cart: Cart = None
152
+ confirmed: bool = False
@@ -0,0 +1,6 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ app/__init__.py
5
+ app/client.py
6
+ app/types.py
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "elemento-loyalty-processing"
3
+ version = "1.0.0"
4
+ description = "Elemento Loyalty Processing"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "kaiju-tools>=2.4.9,<3",
8
+ "kaiju-models>=1.0.4,<2"
9
+ ]
10
+
11
+ [project.optional-dependencies]
12
+ server = [
13
+ "kaiju-db>=2.3.0,<3",
14
+ "kaiju-redis>=2.4.1,<3",
15
+ ]
16
+ dev = [
17
+ "kaiju-tools [dev]"
18
+ ]
19
+
20
+ # --- BUILD CONFIGURATION ---
21
+
22
+ [build-system]
23
+ requires = ["setuptools"]
24
+ build-backend = "setuptools.build_meta"
25
+
26
+ [tool.setuptools]
27
+ packages = ["elemento_loyalty_processing"]
28
+ py-modules = []
29
+ package-dir={elemento_loyalty_processing = 'app'}
30
+
31
+ # --- TOOL CONFIGURATION ---
32
+
33
+ [tool.bandit]
34
+ skips = ["B101"] # , "B105", "B110", "B310", "B311", "B404", "B601", "B602", "B603", "B608", "B701"
35
+
36
+ [tool.black]
37
+ line-length = 120
38
+ target-version = ['py311']
39
+
40
+ [tool.isort]
41
+ profile = "black"
42
+ multi_line_output = 3
43
+ lines_after_imports = 2
44
+ skip_gitignore = true
45
+ balanced_wrapping = true
46
+ line_length = 120
47
+ wrap_length = 120
48
+ known_first_party = ["app"]
49
+ src_paths = ["app"]
50
+ skip = ['conftest.py', '__init__.py', '__main__.py', 'setup.py']
51
+ skip_glob = ['docs/*', 'tests/*']
52
+
53
+ [tool.pylint]
54
+ load-plugins = [
55
+ 'pylint.extensions.check_elif',
56
+ 'pylint.extensions.docstyle',
57
+ 'pylint.extensions.dunder',
58
+ 'pylint.extensions.eq_without_hash',
59
+ 'pylint.extensions.mccabe',
60
+ 'pylint.extensions.overlapping_exceptions',
61
+ 'pylint.extensions.private_import'
62
+ ]
63
+ disable = ['C0114', 'C0116', 'C0115', 'R0902', 'R0903', 'R0913', 'R1735', 'W0622', 'W0611', 'W0707', 'R0917', 'R1260', 'W0613']
64
+ max-line-length = 120
65
+
66
+ [tool.pytest.ini_options]
67
+ log_cli = true
68
+ log_level = "DEBUG"
69
+ log_format = '"%(name)s %(levelname)s %(message)s"'
70
+ log_cli_level = "DEBUG"
71
+ max_args = 10
72
+ addopts = "--doctest-modules --doctest-continue-on-failure --ignore=docs/source/conf.py --ignore=conftest.py --ignore=setup.py"
73
+ markers = ['docker', 'benchmark']
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+