bw-essentials-core 0.0.9__tar.gz → 0.1.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.
Potentially problematic release.
This version of bw-essentials-core might be problematic. Click here for more details.
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/PKG-INFO +1 -1
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/constants/services.py +1 -0
- bw_essentials_core-0.1.0/bw_essentials/services/user_app.py +323 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/PKG-INFO +1 -1
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/SOURCES.txt +1 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/setup.py +1 -1
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/README.md +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/constants/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/data_loch/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/data_loch/data_loch.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/email_client/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/email_client/email_client.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/notifications/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/notifications/teams_notification_schemas.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/notifications/teams_notifications.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/s3_utils/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/s3_utils/s3_utils.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/__init__.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/api_client.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/broker.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/market_pricer.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/master_data.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/model_portfolio_reporting.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/trade_placement.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/user_portfolio.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/user_portfolio_reporting.py +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/dependency_links.txt +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/requires.txt +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/top_level.txt +0 -0
- {bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/setup.cfg +0 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""
|
|
2
|
+
prometheus_user_app.py
|
|
3
|
+
|
|
4
|
+
Module to interact with the Prometheus User App Service API.
|
|
5
|
+
|
|
6
|
+
This module provides a high-level client wrapper around the Prometheus User App Service,
|
|
7
|
+
enabling secure, structured, and logged communication with its endpoints. It includes:
|
|
8
|
+
|
|
9
|
+
- Type-safe interfaces
|
|
10
|
+
- Detailed request and response logging
|
|
11
|
+
- Validated endpoint routing
|
|
12
|
+
- Clear, maintainable service integration points
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from typing import Optional, Dict, Any
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
from bw_essentials.constants.services import Services
|
|
19
|
+
from bw_essentials.services.api_client import ApiClient
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PrometheusUserApp(ApiClient):
|
|
25
|
+
"""
|
|
26
|
+
Client for interacting with the Prometheus User App Service API.
|
|
27
|
+
|
|
28
|
+
This class handles API communication with Prometheus User App endpoints. It abstracts
|
|
29
|
+
request handling, URL construction, and logging while ensuring robust error management.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
base_url (str): Base URL derived from tenant configuration
|
|
33
|
+
name (str): Service identifier
|
|
34
|
+
urls (Dict[str, str]): A dictionary of endpoint path templates
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, service_user: str):
|
|
38
|
+
"""
|
|
39
|
+
Initialize the PrometheusUserApp client with the given service user.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
service_user (str): Username or service identifier for authentication.
|
|
43
|
+
"""
|
|
44
|
+
super().__init__(user=service_user)
|
|
45
|
+
self.base_url = self.get_base_url(Services.PROMETHEUS_USER_APP.value)
|
|
46
|
+
self.name = Services.PROMETHEUS_USER_APP.value
|
|
47
|
+
self.urls = {
|
|
48
|
+
"user_details": "user/details",
|
|
49
|
+
"profile": "user/profile",
|
|
50
|
+
"get_profile": "user/profile/",
|
|
51
|
+
"login": "user/login",
|
|
52
|
+
"register_user": "user/register",
|
|
53
|
+
"update_dealer_disclaimer": "user/{}/dealer/disclaimer/",
|
|
54
|
+
"dealer_users": "user/{}/dealer/users",
|
|
55
|
+
"user_disclaimer": "user/{}/disclaimer/",
|
|
56
|
+
"dealer_login": "user/{}/login/dealer",
|
|
57
|
+
"send_otp": "user/{}/otp/send",
|
|
58
|
+
"verify_otp": "user/{}/otp/verify",
|
|
59
|
+
"register_dealer_user": "user/{}/register/dealer",
|
|
60
|
+
"sso": "user/{}/sso"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
def get_user_details(self, user_id: str) -> Optional[Dict[str, Any]]:
|
|
64
|
+
"""
|
|
65
|
+
Fetch detailed user information by user ID.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
user_id (str): Unique identifier of the user.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Optional[Dict[str, Any]]: Parsed user data if found, else None.
|
|
72
|
+
"""
|
|
73
|
+
logger.info("Fetching user details for user_id=%s", user_id)
|
|
74
|
+
response = self._get(
|
|
75
|
+
endpoint=self.urls["user_details"],
|
|
76
|
+
url=self.base_url,
|
|
77
|
+
params={'user_id': user_id}
|
|
78
|
+
)
|
|
79
|
+
return response.get('data')
|
|
80
|
+
|
|
81
|
+
def update_user_profile(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
82
|
+
"""
|
|
83
|
+
Update the user profile with provided data.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data (Dict[str, Any]): Dictionary containing user profile updates.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Optional[Dict[str, Any]]: Updated profile data if successful, else None.
|
|
90
|
+
"""
|
|
91
|
+
logger.info("Updating user profile with data: %s", data)
|
|
92
|
+
response = self._put(
|
|
93
|
+
endpoint=self.urls["profile"],
|
|
94
|
+
url=self.base_url,
|
|
95
|
+
data=data
|
|
96
|
+
)
|
|
97
|
+
return response.get('data')
|
|
98
|
+
|
|
99
|
+
def login(self, user_id: str, password: str) -> Optional[Dict[str, Any]]:
|
|
100
|
+
"""
|
|
101
|
+
Authenticate a user using credentials.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
user_id (str): User identifier (e.g., username).
|
|
105
|
+
password (str): User password.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Optional[Dict[str, Any]]: Auth token or login response if successful.
|
|
109
|
+
"""
|
|
110
|
+
logger.info("Logging in user %s", user_id)
|
|
111
|
+
response = self._post(
|
|
112
|
+
endpoint=self.urls["login"],
|
|
113
|
+
url=self.base_url,
|
|
114
|
+
json={'username': user_id, 'password': password}
|
|
115
|
+
)
|
|
116
|
+
return response.get('data')
|
|
117
|
+
|
|
118
|
+
def get_user_profile(self, user_id: str) -> Optional[Dict[str, Any]]:
|
|
119
|
+
"""
|
|
120
|
+
Retrieve profile details of a user.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
user_id (str): Unique user identifier.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Optional[Dict[str, Any]]: User profile information if successful.
|
|
127
|
+
"""
|
|
128
|
+
logger.info("Fetching profile for user %s", user_id)
|
|
129
|
+
response = self._get(
|
|
130
|
+
endpoint=self.urls["get_profile"],
|
|
131
|
+
url=self.base_url
|
|
132
|
+
)
|
|
133
|
+
return response.get('data')
|
|
134
|
+
|
|
135
|
+
def register_user(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
136
|
+
"""
|
|
137
|
+
Register a new user with the service.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
data (Dict[str, Any]): Registration details including user information.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Optional[Dict[str, Any]]: Registration confirmation or created user details.
|
|
144
|
+
"""
|
|
145
|
+
logger.info("Registering new user with data: %s", data)
|
|
146
|
+
response = self._post(
|
|
147
|
+
endpoint=self.urls["register_user"],
|
|
148
|
+
url=self.base_url,
|
|
149
|
+
json=data
|
|
150
|
+
)
|
|
151
|
+
return response
|
|
152
|
+
|
|
153
|
+
def update_dealer_disclaimer(self, broker: str, user_id: str, disclaimer_accepted: bool) -> Optional[Dict[str, Any]]:
|
|
154
|
+
"""
|
|
155
|
+
Update a user's dealer disclaimer status.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
broker (str): Broker identifier.
|
|
159
|
+
user_id (str): User ID whose disclaimer is being updated.
|
|
160
|
+
disclaimer_accepted (bool): Whether disclaimer is accepted.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Optional[Dict[str, Any]]: Updated disclaimer status if successful.
|
|
164
|
+
"""
|
|
165
|
+
logger.info("Updating dealer disclaimer for user_id=%s, broker=%s", user_id, broker)
|
|
166
|
+
response = self._put(
|
|
167
|
+
endpoint=self.urls["update_dealer_disclaimer"].format(broker),
|
|
168
|
+
url=self.base_url,
|
|
169
|
+
json={'disclaimer_accepted': disclaimer_accepted, 'user_id': user_id}
|
|
170
|
+
)
|
|
171
|
+
return response.get('data')
|
|
172
|
+
|
|
173
|
+
def dealer_users(self, broker: str, dealer_id: str) -> Optional[Dict[str, Any]]:
|
|
174
|
+
"""
|
|
175
|
+
Get users associated with a specific dealer.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
broker (str): Broker name.
|
|
179
|
+
dealer_id (str): Dealer identifier.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Optional[Dict[str, Any]]: List of users or None if failed.
|
|
183
|
+
"""
|
|
184
|
+
logger.info("Fetching dealer users for broker=%s, dealer_id=%s", broker, dealer_id)
|
|
185
|
+
response = self._post(
|
|
186
|
+
endpoint=self.urls["dealer_users"].format(broker),
|
|
187
|
+
url=self.base_url,
|
|
188
|
+
json={'dealer_id': dealer_id}
|
|
189
|
+
)
|
|
190
|
+
return response.get('data')
|
|
191
|
+
|
|
192
|
+
def user_disclaimer(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
193
|
+
"""
|
|
194
|
+
Fetch disclaimer details for a user under a specific broker.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
broker (str): Broker name.
|
|
198
|
+
data (Dict[str, Any]): Payload for disclaimer lookup.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Optional[Dict[str, Any]]: Disclaimer information if available.
|
|
202
|
+
"""
|
|
203
|
+
logger.info("Fetching user disclaimer for broker=%s, data=%s", broker, data)
|
|
204
|
+
response = self._post(
|
|
205
|
+
endpoint=self.urls["user_disclaimer"].format(broker),
|
|
206
|
+
url=self.base_url,
|
|
207
|
+
json=data
|
|
208
|
+
)
|
|
209
|
+
return response.get('data')
|
|
210
|
+
|
|
211
|
+
def dealer_login(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
212
|
+
"""
|
|
213
|
+
Perform login for a dealer under the specified broker.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
broker (str): Broker identifier.
|
|
217
|
+
data (Dict[str, Any]): Login payload.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Optional[Dict[str, Any]]: Login response if successful.
|
|
221
|
+
"""
|
|
222
|
+
logger.info("Dealer login request for broker=%s, data=%s", broker, data)
|
|
223
|
+
response = self._post(
|
|
224
|
+
endpoint=self.urls["dealer_login"].format(broker),
|
|
225
|
+
url=self.base_url,
|
|
226
|
+
json=data
|
|
227
|
+
)
|
|
228
|
+
return response.get('data')
|
|
229
|
+
|
|
230
|
+
def send_otp(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
231
|
+
"""
|
|
232
|
+
Send OTP to user for verification under a broker.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
broker (str): Broker name.
|
|
236
|
+
data (Dict[str, Any]): Payload including mobile/email.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Optional[Dict[str, Any]]: Response with OTP status.
|
|
240
|
+
"""
|
|
241
|
+
logger.info("Sending OTP for broker=%s, data=%s", broker, data)
|
|
242
|
+
response = self._post(
|
|
243
|
+
endpoint=self.urls["send_otp"].format(broker),
|
|
244
|
+
url=self.base_url,
|
|
245
|
+
json=data
|
|
246
|
+
)
|
|
247
|
+
return response.get('data')
|
|
248
|
+
|
|
249
|
+
def verify_otp(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
250
|
+
"""
|
|
251
|
+
Verify user OTP under a broker.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
broker (str): Broker name.
|
|
255
|
+
data (Dict[str, Any]): OTP verification data.
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Optional[Dict[str, Any]]: Verification status.
|
|
259
|
+
"""
|
|
260
|
+
logger.info("Verifying OTP for broker=%s, data=%s", broker, data)
|
|
261
|
+
response = self._post(
|
|
262
|
+
endpoint=self.urls["verify_otp"].format(broker),
|
|
263
|
+
url=self.base_url,
|
|
264
|
+
json=data
|
|
265
|
+
)
|
|
266
|
+
return response.get('data')
|
|
267
|
+
|
|
268
|
+
def register_dealer_user(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
269
|
+
"""
|
|
270
|
+
Register a new dealer user.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
broker (str): Broker name.
|
|
274
|
+
data (Dict[str, Any]): Dealer user details.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Optional[Dict[str, Any]]: Registration status or dealer user details.
|
|
278
|
+
"""
|
|
279
|
+
logger.info("Registering dealer user for broker=%s, data=%s", broker, data)
|
|
280
|
+
response = self._post(
|
|
281
|
+
endpoint=self.urls["register_dealer_user"].format(broker),
|
|
282
|
+
url=self.base_url,
|
|
283
|
+
json=data
|
|
284
|
+
)
|
|
285
|
+
return response.get('data')
|
|
286
|
+
|
|
287
|
+
def update_dealer_user(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
288
|
+
"""
|
|
289
|
+
Update an existing dealer user's information.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
broker (str): Broker name.
|
|
293
|
+
data (Dict[str, Any]): Dealer user update payload.
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
Optional[Dict[str, Any]]: Updated dealer user data.
|
|
297
|
+
"""
|
|
298
|
+
logger.info("Updating dealer user for broker=%s, data=%s", broker, data)
|
|
299
|
+
response = self._put(
|
|
300
|
+
endpoint=self.urls["register_dealer_user"].format(broker),
|
|
301
|
+
url=self.base_url,
|
|
302
|
+
json=data
|
|
303
|
+
)
|
|
304
|
+
return response.get('data')
|
|
305
|
+
|
|
306
|
+
def sso(self, broker: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
307
|
+
"""
|
|
308
|
+
Perform Single Sign-On (SSO) operation.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
broker (str): Broker identifier.
|
|
312
|
+
data (Dict[str, Any]): SSO payload.
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Optional[Dict[str, Any]]: SSO token or user session.
|
|
316
|
+
"""
|
|
317
|
+
logger.info("Performing SSO for broker=%s, data=%s", broker, data)
|
|
318
|
+
response = self._post(
|
|
319
|
+
endpoint=self.urls["sso"].format(broker),
|
|
320
|
+
url=self.base_url,
|
|
321
|
+
json=data
|
|
322
|
+
)
|
|
323
|
+
return response.get('data')
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/SOURCES.txt
RENAMED
|
@@ -19,6 +19,7 @@ bw_essentials/services/market_pricer.py
|
|
|
19
19
|
bw_essentials/services/master_data.py
|
|
20
20
|
bw_essentials/services/model_portfolio_reporting.py
|
|
21
21
|
bw_essentials/services/trade_placement.py
|
|
22
|
+
bw_essentials/services/user_app.py
|
|
22
23
|
bw_essentials/services/user_portfolio.py
|
|
23
24
|
bw_essentials/services/user_portfolio_reporting.py
|
|
24
25
|
bw_essentials_core.egg-info/PKG-INFO
|
|
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
|
|
10
10
|
|
|
11
11
|
setup(
|
|
12
12
|
name="bw-essentials-core",
|
|
13
|
-
version="0.0
|
|
13
|
+
version="0.1.0",
|
|
14
14
|
author="InvestorAI",
|
|
15
15
|
author_email="support+tech@investorai.in",
|
|
16
16
|
description="Reusable utilities for S3, email, Data Loch, Microsoft Teams Notifications and more.",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/email_client/__init__.py
RENAMED
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/email_client/email_client.py
RENAMED
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/notifications/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/market_pricer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/trade_placement.py
RENAMED
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials/services/user_portfolio.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/requires.txt
RENAMED
|
File without changes
|
{bw_essentials_core-0.0.9 → bw_essentials_core-0.1.0}/bw_essentials_core.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|