smartrack-sdk 1.0.0__py3-none-any.whl
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 smartrack-sdk might be problematic. Click here for more details.
- examples/__init__.py +7 -0
- examples/basic_usage.py +360 -0
- examples/callback_server.py +435 -0
- examples/test_client.py +303 -0
- smartrack_sdk/__init__.py +129 -0
- smartrack_sdk/callback/__init__.py +19 -0
- smartrack_sdk/callback/fastapi_handler.py +151 -0
- smartrack_sdk/callback/flask_handler.py +137 -0
- smartrack_sdk/callback/handler.py +220 -0
- smartrack_sdk/callback/service.py +14 -0
- smartrack_sdk/client/__init__.py +13 -0
- smartrack_sdk/client/smart_rack_client.py +523 -0
- smartrack_sdk/exceptions/__init__.py +21 -0
- smartrack_sdk/exceptions/api.py +29 -0
- smartrack_sdk/exceptions/base.py +25 -0
- smartrack_sdk/exceptions/configuration.py +28 -0
- smartrack_sdk/exceptions/network.py +50 -0
- smartrack_sdk/exceptions/validation.py +28 -0
- smartrack_sdk/models/__init__.py +85 -0
- smartrack_sdk/models/callback.py +184 -0
- smartrack_sdk/models/enums.py +203 -0
- smartrack_sdk/models/requests.py +291 -0
- smartrack_sdk/models/responses.py +209 -0
- smartrack_sdk/tests/__init__.py +7 -0
- smartrack_sdk/tests/test_callback.py +295 -0
- smartrack_sdk/tests/test_client.py +264 -0
- smartrack_sdk-1.0.0.dist-info/METADATA +557 -0
- smartrack_sdk-1.0.0.dist-info/RECORD +31 -0
- smartrack_sdk-1.0.0.dist-info/WHEEL +5 -0
- smartrack_sdk-1.0.0.dist-info/entry_points.txt +2 -0
- smartrack_sdk-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
SmartRack SDK 客户端核心类
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import requests
|
|
11
|
+
from typing import Optional, Dict, Any, Union
|
|
12
|
+
from urllib.parse import urlencode
|
|
13
|
+
|
|
14
|
+
from ..exceptions import (
|
|
15
|
+
SmartRackException,
|
|
16
|
+
SmartRackApiException,
|
|
17
|
+
SmartRackNetworkException,
|
|
18
|
+
SmartRackConfigurationException,
|
|
19
|
+
SmartRackValidationException,
|
|
20
|
+
)
|
|
21
|
+
from ..models.requests import (
|
|
22
|
+
BaseRequest,
|
|
23
|
+
ClearErrorRequest,
|
|
24
|
+
RackTestRequest,
|
|
25
|
+
StockInRequest,
|
|
26
|
+
StockOutRequest,
|
|
27
|
+
StockOutSheetRequest,
|
|
28
|
+
StockOutSheetCancelRequest,
|
|
29
|
+
StockOutSheetFinishRequest,
|
|
30
|
+
StockInFinishRequest,
|
|
31
|
+
ResetCellRequest,
|
|
32
|
+
GetStockByGRNListRequest,
|
|
33
|
+
)
|
|
34
|
+
from ..models.responses import (
|
|
35
|
+
BaseResponse,
|
|
36
|
+
ClearErrorResponse,
|
|
37
|
+
StockDataResponse,
|
|
38
|
+
StockOutResponse,
|
|
39
|
+
StockOutSheetResponse,
|
|
40
|
+
)
|
|
41
|
+
from ..models.enums import LedColors, CellStatus
|
|
42
|
+
|
|
43
|
+
# 配置日志
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SmartRackClient:
|
|
48
|
+
"""SmartRack SDK 客户端"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
base_url: str,
|
|
53
|
+
timeout: int = 30,
|
|
54
|
+
auth_token: Optional[str] = None,
|
|
55
|
+
verify_ssl: bool = True,
|
|
56
|
+
):
|
|
57
|
+
"""
|
|
58
|
+
初始化SmartRack客户端
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
base_url: API基础URL
|
|
62
|
+
timeout: 请求超时时间(秒)
|
|
63
|
+
auth_token: 认证Token
|
|
64
|
+
verify_ssl: 是否验证SSL证书
|
|
65
|
+
"""
|
|
66
|
+
if not base_url or not base_url.strip():
|
|
67
|
+
raise SmartRackConfigurationException("Base URL cannot be empty")
|
|
68
|
+
|
|
69
|
+
self.base_url = base_url.rstrip('/')
|
|
70
|
+
self.timeout = timeout
|
|
71
|
+
self.auth_token = auth_token
|
|
72
|
+
self.verify_ssl = verify_ssl
|
|
73
|
+
|
|
74
|
+
# 创建HTTP会话
|
|
75
|
+
self.session = requests.Session()
|
|
76
|
+
self.session.timeout = timeout
|
|
77
|
+
|
|
78
|
+
# 设置默认请求头
|
|
79
|
+
self.session.headers.update({
|
|
80
|
+
'Content-Type': 'application/json',
|
|
81
|
+
'Accept': 'application/json',
|
|
82
|
+
'User-Agent': 'SmartRack-Python-SDK/1.0.0',
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
# 设置认证Token
|
|
86
|
+
if auth_token:
|
|
87
|
+
self.set_auth_token(auth_token)
|
|
88
|
+
|
|
89
|
+
logger.info(f"SmartRack客户端初始化完成: {self.base_url}")
|
|
90
|
+
|
|
91
|
+
def set_auth_token(self, token: str) -> None:
|
|
92
|
+
"""
|
|
93
|
+
设置认证Token
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
token: 认证Token
|
|
97
|
+
"""
|
|
98
|
+
self.auth_token = token
|
|
99
|
+
self.session.headers.update({
|
|
100
|
+
'Authorization': f'Bearer {token}'
|
|
101
|
+
})
|
|
102
|
+
logger.debug("设置认证Token成功")
|
|
103
|
+
|
|
104
|
+
def clear_auth_token(self) -> None:
|
|
105
|
+
"""清除认证Token"""
|
|
106
|
+
self.auth_token = None
|
|
107
|
+
if 'Authorization' in self.session.headers:
|
|
108
|
+
del self.session.headers['Authorization']
|
|
109
|
+
logger.debug("清除认证Token成功")
|
|
110
|
+
|
|
111
|
+
def _make_request(
|
|
112
|
+
self,
|
|
113
|
+
method: str,
|
|
114
|
+
endpoint: str,
|
|
115
|
+
data: Optional[Union[Dict[str, Any], BaseRequest]] = None,
|
|
116
|
+
params: Optional[Dict[str, Any]] = None,
|
|
117
|
+
) -> Dict[str, Any]:
|
|
118
|
+
"""
|
|
119
|
+
发送HTTP请求
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
method: HTTP方法
|
|
123
|
+
endpoint: API端点
|
|
124
|
+
data: 请求数据
|
|
125
|
+
params: 查询参数
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
响应数据
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
SmartRackNetworkException: 网络错误
|
|
132
|
+
SmartRackApiException: API错误
|
|
133
|
+
"""
|
|
134
|
+
url = f"{self.base_url}{endpoint}"
|
|
135
|
+
|
|
136
|
+
# 准备请求参数
|
|
137
|
+
request_kwargs = {
|
|
138
|
+
'verify': self.verify_ssl,
|
|
139
|
+
'timeout': self.timeout,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# 处理查询参数
|
|
143
|
+
if params:
|
|
144
|
+
request_kwargs['params'] = params
|
|
145
|
+
|
|
146
|
+
# 处理请求数据
|
|
147
|
+
if data is not None:
|
|
148
|
+
if isinstance(data, BaseRequest):
|
|
149
|
+
request_kwargs['json'] = data.to_dict()
|
|
150
|
+
else:
|
|
151
|
+
request_kwargs['json'] = data
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
logger.debug(f"发送{method}请求到: {url}")
|
|
155
|
+
if request_kwargs.get('json'):
|
|
156
|
+
logger.debug(f"请求数据: {request_kwargs['json']}")
|
|
157
|
+
|
|
158
|
+
response = self.session.request(method, url, **request_kwargs)
|
|
159
|
+
|
|
160
|
+
# 检查HTTP状态码
|
|
161
|
+
response.raise_for_status()
|
|
162
|
+
|
|
163
|
+
# 解析响应
|
|
164
|
+
response_data = response.json()
|
|
165
|
+
logger.debug(f"响应数据: {response_data}")
|
|
166
|
+
|
|
167
|
+
return response_data
|
|
168
|
+
|
|
169
|
+
except requests.exceptions.Timeout as e:
|
|
170
|
+
error_msg = f"请求超时: {str(e)}"
|
|
171
|
+
logger.error(error_msg)
|
|
172
|
+
raise SmartRackNetworkException(error_msg, cause=e)
|
|
173
|
+
|
|
174
|
+
except requests.exceptions.ConnectionError as e:
|
|
175
|
+
error_msg = f"连接错误: {str(e)}"
|
|
176
|
+
logger.error(error_msg)
|
|
177
|
+
raise SmartRackNetworkException(error_msg, cause=e)
|
|
178
|
+
|
|
179
|
+
except requests.exceptions.HTTPError as e:
|
|
180
|
+
error_msg = f"HTTP错误: {str(e)}"
|
|
181
|
+
logger.error(error_msg)
|
|
182
|
+
|
|
183
|
+
# 尝试解析错误响应
|
|
184
|
+
try:
|
|
185
|
+
error_data = e.response.json()
|
|
186
|
+
status_code = e.response.status_code
|
|
187
|
+
raise SmartRackNetworkException(
|
|
188
|
+
f"HTTP {status_code}: {error_data.get('message', error_msg)}",
|
|
189
|
+
status_code=status_code,
|
|
190
|
+
cause=e
|
|
191
|
+
)
|
|
192
|
+
except (ValueError, AttributeError):
|
|
193
|
+
raise SmartRackNetworkException(error_msg, e.response.status_code, e)
|
|
194
|
+
|
|
195
|
+
except requests.exceptions.RequestException as e:
|
|
196
|
+
error_msg = f"请求异常: {str(e)}"
|
|
197
|
+
logger.error(error_msg)
|
|
198
|
+
raise SmartRackNetworkException(error_msg, cause=e)
|
|
199
|
+
|
|
200
|
+
except json.JSONDecodeError as e:
|
|
201
|
+
error_msg = f"JSON解析错误: {str(e)}"
|
|
202
|
+
logger.error(error_msg)
|
|
203
|
+
raise SmartRackApiException("响应数据格式错误", -500)
|
|
204
|
+
|
|
205
|
+
def _handle_response(self, response_data: Dict[str, Any], response_class=BaseResponse):
|
|
206
|
+
"""
|
|
207
|
+
处理API响应
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
response_data: 响应数据
|
|
211
|
+
response_class: 响应类
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
响应对象
|
|
215
|
+
|
|
216
|
+
Raises:
|
|
217
|
+
SmartRackApiException: API错误
|
|
218
|
+
"""
|
|
219
|
+
try:
|
|
220
|
+
response = response_class.from_dict(response_data)
|
|
221
|
+
|
|
222
|
+
# 检查API返回的状态码
|
|
223
|
+
if response.code != 0:
|
|
224
|
+
error_msg = response.message or f"API错误 (代码: {response.code})"
|
|
225
|
+
raise SmartRackApiException(error_msg, response.code, response.session_id)
|
|
226
|
+
|
|
227
|
+
return response
|
|
228
|
+
|
|
229
|
+
except Exception as e:
|
|
230
|
+
if isinstance(e, SmartRackApiException):
|
|
231
|
+
raise
|
|
232
|
+
error_msg = f"响应处理错误: {str(e)}"
|
|
233
|
+
logger.error(error_msg)
|
|
234
|
+
raise SmartRackApiException(error_msg, -500)
|
|
235
|
+
|
|
236
|
+
# API方法实现
|
|
237
|
+
|
|
238
|
+
def clear_error(self, request: ClearErrorRequest) -> ClearErrorResponse:
|
|
239
|
+
"""
|
|
240
|
+
清错错误
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
request: 清错请求
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
清错响应
|
|
247
|
+
"""
|
|
248
|
+
if not request.rack_id and not request.cell_id:
|
|
249
|
+
raise SmartRackValidationException("必须指定rackId或cellId")
|
|
250
|
+
|
|
251
|
+
response_data = self._make_request(
|
|
252
|
+
'POST',
|
|
253
|
+
'/api/HJWMS/External/SmartRackExternal/ClearError',
|
|
254
|
+
request
|
|
255
|
+
)
|
|
256
|
+
return self._handle_response(response_data, ClearErrorResponse)
|
|
257
|
+
|
|
258
|
+
def rack_test(self, request: RackTestRequest) -> BaseResponse:
|
|
259
|
+
"""
|
|
260
|
+
料架测试
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
request: 测试请求
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
测试响应
|
|
267
|
+
"""
|
|
268
|
+
if not request.rack_id:
|
|
269
|
+
raise SmartRackValidationException("rackId不能为空")
|
|
270
|
+
|
|
271
|
+
response_data = self._make_request(
|
|
272
|
+
'POST',
|
|
273
|
+
'/api/HJWMS/External/SmartRackExternal/RackTest',
|
|
274
|
+
request
|
|
275
|
+
)
|
|
276
|
+
return self._handle_response(response_data)
|
|
277
|
+
|
|
278
|
+
def stock_in_request(self, request: StockInRequest) -> BaseResponse:
|
|
279
|
+
"""
|
|
280
|
+
入库请求
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
request: 入库请求
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
入库响应
|
|
287
|
+
"""
|
|
288
|
+
if not request.sheet_id or not request.rack_id or not request.grn:
|
|
289
|
+
raise SmartRackValidationException("sheetId、rackId和grn不能为空")
|
|
290
|
+
|
|
291
|
+
response_data = self._make_request(
|
|
292
|
+
'POST',
|
|
293
|
+
'/api/HJWMS/External/SmartRackExternal/StockInRequest',
|
|
294
|
+
request
|
|
295
|
+
)
|
|
296
|
+
return self._handle_response(response_data)
|
|
297
|
+
|
|
298
|
+
def stock_out_request(self, request: StockOutRequest) -> StockOutResponse:
|
|
299
|
+
"""
|
|
300
|
+
出库请求
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
request: 出库请求
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
出库响应
|
|
307
|
+
"""
|
|
308
|
+
if not request.grn_list:
|
|
309
|
+
raise SmartRackValidationException("grnList不能为空")
|
|
310
|
+
|
|
311
|
+
response_data = self._make_request(
|
|
312
|
+
'POST',
|
|
313
|
+
'/api/HJWMS/External/SmartRackExternal/StockOutRequest',
|
|
314
|
+
request
|
|
315
|
+
)
|
|
316
|
+
return self._handle_response(response_data, StockOutResponse)
|
|
317
|
+
|
|
318
|
+
def stock_out_sheet_cancel(self, request: StockOutSheetCancelRequest) -> StockOutResponse:
|
|
319
|
+
"""
|
|
320
|
+
单号出库取消
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
request: 取消请求
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
取消响应
|
|
327
|
+
"""
|
|
328
|
+
if not request.sheet_id:
|
|
329
|
+
raise SmartRackValidationException("sheetId不能为空")
|
|
330
|
+
|
|
331
|
+
response_data = self._make_request(
|
|
332
|
+
'POST',
|
|
333
|
+
'/api/HJWMS/External/SmartRackExternal/StockOutSheetCancel',
|
|
334
|
+
request
|
|
335
|
+
)
|
|
336
|
+
return self._handle_response(response_data, StockOutResponse)
|
|
337
|
+
|
|
338
|
+
def stock_out_sheet_finish(self, request: StockOutSheetFinishRequest) -> BaseResponse:
|
|
339
|
+
"""
|
|
340
|
+
单号出库完成
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
request: 完成请求
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
完成响应
|
|
347
|
+
"""
|
|
348
|
+
if not request.sheet_id:
|
|
349
|
+
raise SmartRackValidationException("sheetId不能为空")
|
|
350
|
+
|
|
351
|
+
response_data = self._make_request(
|
|
352
|
+
'POST',
|
|
353
|
+
'/api/HJWMS/External/SmartRackExternal/StockOutSheetFinish',
|
|
354
|
+
request
|
|
355
|
+
)
|
|
356
|
+
return self._handle_response(response_data)
|
|
357
|
+
|
|
358
|
+
def stock_out_sheet_request(self, request: StockOutSheetRequest) -> StockOutSheetResponse:
|
|
359
|
+
"""
|
|
360
|
+
单号出库请求
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
request: 出库请求
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
出库响应
|
|
367
|
+
"""
|
|
368
|
+
if not request.sheet_id or not request.grn_list:
|
|
369
|
+
raise SmartRackValidationException("sheetId和grnList不能为空")
|
|
370
|
+
|
|
371
|
+
response_data = self._make_request(
|
|
372
|
+
'POST',
|
|
373
|
+
'/api/HJWMS/External/SmartRackExternal/StockOutSheetRequest',
|
|
374
|
+
request
|
|
375
|
+
)
|
|
376
|
+
return self._handle_response(response_data, StockOutSheetResponse)
|
|
377
|
+
|
|
378
|
+
def reset_cell(self, request: ResetCellRequest) -> BaseResponse:
|
|
379
|
+
"""
|
|
380
|
+
重置储位状态
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
request: 重置请求
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
重置响应
|
|
387
|
+
"""
|
|
388
|
+
if not request.cell_list:
|
|
389
|
+
raise SmartRackValidationException("cellList不能为空")
|
|
390
|
+
|
|
391
|
+
response_data = self._make_request(
|
|
392
|
+
'POST',
|
|
393
|
+
'/api/HJWMS/External/SmartRackExternal/ResetCell',
|
|
394
|
+
request
|
|
395
|
+
)
|
|
396
|
+
return self._handle_response(response_data)
|
|
397
|
+
|
|
398
|
+
def stock_in_finish(self, request: StockInFinishRequest) -> BaseResponse:
|
|
399
|
+
"""
|
|
400
|
+
入库完成
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
request: 完成请求
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
完成响应
|
|
407
|
+
"""
|
|
408
|
+
if not request.sheet_id:
|
|
409
|
+
raise SmartRackValidationException("sheetId不能为空")
|
|
410
|
+
|
|
411
|
+
response_data = self._make_request(
|
|
412
|
+
'POST',
|
|
413
|
+
'/api/HJWMS/External/SmartRackExternal/StockInFinish',
|
|
414
|
+
request
|
|
415
|
+
)
|
|
416
|
+
return self._handle_response(response_data)
|
|
417
|
+
|
|
418
|
+
def get_stock_data(
|
|
419
|
+
self,
|
|
420
|
+
grn: Optional[str] = None,
|
|
421
|
+
rack_id: Optional[str] = None,
|
|
422
|
+
cell_id: Optional[str] = None,
|
|
423
|
+
stock_out_sheet: Optional[str] = None,
|
|
424
|
+
stock_in_sheet: Optional[str] = None,
|
|
425
|
+
led_color: Optional[LedColors] = None,
|
|
426
|
+
is_blink: Optional[bool] = None,
|
|
427
|
+
status: Optional[CellStatus] = None,
|
|
428
|
+
used: Optional[int] = None,
|
|
429
|
+
flag: Optional[int] = None,
|
|
430
|
+
sorting: Optional[str] = None,
|
|
431
|
+
skip_count: int = 0,
|
|
432
|
+
max_result_count: int = 10,
|
|
433
|
+
) -> StockDataResponse:
|
|
434
|
+
"""
|
|
435
|
+
查询库存
|
|
436
|
+
|
|
437
|
+
Args:
|
|
438
|
+
grn: GRN
|
|
439
|
+
rack_id: 料架号
|
|
440
|
+
cell_id: 储位号
|
|
441
|
+
stock_out_sheet: 出库单号
|
|
442
|
+
stock_in_sheet: 入库单号
|
|
443
|
+
led_color: LED颜色
|
|
444
|
+
is_blink: 是否闪烁
|
|
445
|
+
status: 状态
|
|
446
|
+
used: 占用状态
|
|
447
|
+
flag: 特殊标识
|
|
448
|
+
sorting: 排序
|
|
449
|
+
skip_count: 跳过数量
|
|
450
|
+
max_result_count: 最大结果数量
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
库存数据响应
|
|
454
|
+
"""
|
|
455
|
+
params = {
|
|
456
|
+
'SkipCount': skip_count,
|
|
457
|
+
'MaxResultCount': max_result_count,
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
# 添加可选参数
|
|
461
|
+
if grn:
|
|
462
|
+
params['GRN'] = grn
|
|
463
|
+
if rack_id:
|
|
464
|
+
params['RackId'] = rack_id
|
|
465
|
+
if cell_id:
|
|
466
|
+
params['CellId'] = cell_id
|
|
467
|
+
if stock_out_sheet:
|
|
468
|
+
params['StockOutSheet'] = stock_out_sheet
|
|
469
|
+
if stock_in_sheet:
|
|
470
|
+
params['StockInSheet'] = stock_in_sheet
|
|
471
|
+
if led_color is not None:
|
|
472
|
+
params['LedColor'] = led_color.value
|
|
473
|
+
if is_blink is not None:
|
|
474
|
+
params['IsBlink'] = is_blink
|
|
475
|
+
if status is not None:
|
|
476
|
+
params['Status'] = status.value
|
|
477
|
+
if used is not None:
|
|
478
|
+
params['Used'] = used
|
|
479
|
+
if flag is not None:
|
|
480
|
+
params['Flag'] = flag
|
|
481
|
+
if sorting:
|
|
482
|
+
params['Sorting'] = sorting
|
|
483
|
+
|
|
484
|
+
response_data = self._make_request(
|
|
485
|
+
'GET',
|
|
486
|
+
'/api/HJWMS/External/SmartRackExternal/StockData',
|
|
487
|
+
params=params
|
|
488
|
+
)
|
|
489
|
+
return self._handle_response(response_data, StockDataResponse)
|
|
490
|
+
|
|
491
|
+
def get_stock_by_grn_list(self, request: GetStockByGRNListRequest) -> StockDataResponse:
|
|
492
|
+
"""
|
|
493
|
+
通过GRN列表查询库存
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
request: 查询请求
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
库存数据响应
|
|
500
|
+
"""
|
|
501
|
+
if not request.grn_list:
|
|
502
|
+
raise SmartRackValidationException("grnList不能为空")
|
|
503
|
+
|
|
504
|
+
response_data = self._make_request(
|
|
505
|
+
'POST',
|
|
506
|
+
'/api/HJWMS/External/SmartRackExternal/GetStockByGRNList',
|
|
507
|
+
request
|
|
508
|
+
)
|
|
509
|
+
return self._handle_response(response_data, StockDataResponse)
|
|
510
|
+
|
|
511
|
+
def close(self) -> None:
|
|
512
|
+
"""关闭客户端"""
|
|
513
|
+
if self.session:
|
|
514
|
+
self.session.close()
|
|
515
|
+
logger.info("SmartRack客户端已关闭")
|
|
516
|
+
|
|
517
|
+
def __enter__(self):
|
|
518
|
+
"""上下文管理器入口"""
|
|
519
|
+
return self
|
|
520
|
+
|
|
521
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
522
|
+
"""上下文管理器出口"""
|
|
523
|
+
self.close()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
异常处理包
|
|
6
|
+
包含所有SmartRack SDK相关的异常类
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .base import SmartRackException
|
|
10
|
+
from .api import SmartRackApiException
|
|
11
|
+
from .network import SmartRackNetworkException
|
|
12
|
+
from .configuration import SmartRackConfigurationException
|
|
13
|
+
from .validation import SmartRackValidationException
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"SmartRackException",
|
|
17
|
+
"SmartRackApiException",
|
|
18
|
+
"SmartRackNetworkException",
|
|
19
|
+
"SmartRackConfigurationException",
|
|
20
|
+
"SmartRackValidationException",
|
|
21
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
API调用异常
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .base import SmartRackException
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SmartRackApiException(SmartRackException):
|
|
12
|
+
"""API调用异常"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, message: str, api_code: int, session_id: str = None):
|
|
15
|
+
"""
|
|
16
|
+
初始化异常
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
message: 错误消息
|
|
20
|
+
api_code: API响应代码
|
|
21
|
+
session_id: 会话ID
|
|
22
|
+
"""
|
|
23
|
+
super().__init__(message, api_code)
|
|
24
|
+
self.api_code = api_code
|
|
25
|
+
self.session_id = session_id
|
|
26
|
+
|
|
27
|
+
def __str__(self) -> str:
|
|
28
|
+
return (f"SmartRackApiException(api_code={self.api_code}, "
|
|
29
|
+
f"session_id={self.session_id}, message={self.message})")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
SmartRack SDK 异常基类
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SmartRackException(Exception):
|
|
10
|
+
"""SmartRack SDK 异常基类"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, message: str, error_code: int = -1):
|
|
13
|
+
"""
|
|
14
|
+
初始化异常
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
message: 错误消息
|
|
18
|
+
error_code: 错误代码
|
|
19
|
+
"""
|
|
20
|
+
super().__init__(message)
|
|
21
|
+
self.error_code = error_code
|
|
22
|
+
self.message = message
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return f"SmartRackException(code={self.error_code}, message={self.message})"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
配置异常
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from .base import SmartRackException
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SmartRackConfigurationException(SmartRackException):
|
|
14
|
+
"""配置异常"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, message: str, cause: Optional[Exception] = None):
|
|
17
|
+
"""
|
|
18
|
+
初始化异常
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
message: 错误消息
|
|
22
|
+
cause: 内部异常
|
|
23
|
+
"""
|
|
24
|
+
super().__init__(message, -1)
|
|
25
|
+
self.cause = cause
|
|
26
|
+
|
|
27
|
+
def __str__(self) -> str:
|
|
28
|
+
return f"SmartRackConfigurationException(message={self.message})"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
网络异常
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Optional
|
|
9
|
+
from .base import SmartRackException
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SmartRackNetworkException(SmartRackException):
|
|
13
|
+
"""网络异常"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, message: str, status_code: Optional[int] = None, cause: Optional[Exception] = None):
|
|
16
|
+
"""
|
|
17
|
+
初始化异常
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
message: 错误消息
|
|
21
|
+
status_code: HTTP状态码
|
|
22
|
+
cause: 内部异常
|
|
23
|
+
"""
|
|
24
|
+
super().__init__(message, status_code or -1)
|
|
25
|
+
self.status_code = status_code
|
|
26
|
+
self.cause = cause
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def is_timeout(self) -> bool:
|
|
30
|
+
"""是否为超时异常"""
|
|
31
|
+
return (self.cause is not None and
|
|
32
|
+
hasattr(self.cause, '__class__') and
|
|
33
|
+
('timeout' in str(type(self.cause)).lower() or
|
|
34
|
+
'Timeout' in str(type(self.cause))))
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def is_connection_error(self) -> bool:
|
|
38
|
+
"""是否为连接异常"""
|
|
39
|
+
return (self.cause is not None and
|
|
40
|
+
hasattr(self.cause, '__class__') and
|
|
41
|
+
('Connection' in str(type(self.cause)) or
|
|
42
|
+
'connect' in str(type(self.cause)).lower()))
|
|
43
|
+
|
|
44
|
+
def __str__(self) -> str:
|
|
45
|
+
parts = [f"SmartRackNetworkException"]
|
|
46
|
+
if self.status_code:
|
|
47
|
+
parts.append(f"status_code={self.status_code}")
|
|
48
|
+
if self.message:
|
|
49
|
+
parts.append(f"message={self.message}")
|
|
50
|
+
return f"({', '.join(parts)})"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
验证异常
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from .base import SmartRackException
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SmartRackValidationException(SmartRackException):
|
|
14
|
+
"""验证异常"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, message: str, cause: Optional[Exception] = None):
|
|
17
|
+
"""
|
|
18
|
+
初始化异常
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
message: 错误消息
|
|
22
|
+
cause: 内部异常
|
|
23
|
+
"""
|
|
24
|
+
super().__init__(message, -1)
|
|
25
|
+
self.cause = cause
|
|
26
|
+
|
|
27
|
+
def __str__(self) -> str:
|
|
28
|
+
return f"SmartRackValidationException(message={self.message})"
|