ey-commerce-lib 1.0.6__py3-none-any.whl → 1.0.8__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 ey-commerce-lib might be problematic. Click here for more details.
- ey_commerce_lib/four_seller/__init__.py +0 -0
- ey_commerce_lib/four_seller/constant/__init__.py +0 -0
- ey_commerce_lib/four_seller/constant/response.py +8 -0
- ey_commerce_lib/four_seller/main.py +280 -0
- ey_commerce_lib/four_seller/parser/__init__.py +0 -0
- ey_commerce_lib/four_seller/parser/order.py +19 -0
- ey_commerce_lib/four_seller/schemas/__init__.py +0 -0
- ey_commerce_lib/four_seller/schemas/query/__init__.py +0 -0
- ey_commerce_lib/four_seller/schemas/query/order.py +101 -0
- ey_commerce_lib/four_seller/schemas/vo/__init__.py +0 -0
- ey_commerce_lib/four_seller/schemas/vo/order.py +437 -0
- ey_commerce_lib/kogan/__init__.py +0 -0
- ey_commerce_lib/kogan/main.py +40 -0
- ey_commerce_lib/kogan/schemas/__init__.py +0 -0
- ey_commerce_lib/kogan/schemas/query/__init__.py +0 -0
- ey_commerce_lib/kogan/schemas/query/order.py +20 -0
- ey_commerce_lib/kogan/schemas/query/product.py +75 -0
- ey_commerce_lib/kogan/schemas/response/__init__.py +0 -0
- ey_commerce_lib/kogan/schemas/response/order.py +69 -0
- ey_commerce_lib/kogan/schemas/response/product.py +96 -0
- ey_commerce_lib/model.py +12 -0
- ey_commerce_lib/utils/close.py +6 -0
- {ey_commerce_lib-1.0.6.dist-info → ey_commerce_lib-1.0.8.dist-info}/METADATA +3 -1
- ey_commerce_lib-1.0.8.dist-info/RECORD +47 -0
- ey_commerce_lib-1.0.6.dist-info/RECORD +0 -25
- {ey_commerce_lib-1.0.6.dist-info → ey_commerce_lib-1.0.8.dist-info}/WHEEL +0 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Callable
|
|
5
|
+
|
|
6
|
+
from httpx import AsyncClient, ReadTimeout
|
|
7
|
+
from playwright.async_api import async_playwright, TimeoutError
|
|
8
|
+
import ddddocr
|
|
9
|
+
|
|
10
|
+
from ey_commerce_lib.four_seller.constant.response import ResponseCodeEnum
|
|
11
|
+
from ey_commerce_lib.four_seller.parser.order import parse_order
|
|
12
|
+
from ey_commerce_lib.four_seller.schemas.query.order import FourSellerOrderQueryModel
|
|
13
|
+
from ey_commerce_lib.four_seller.schemas.vo.order import FourSellerOrderVO
|
|
14
|
+
from ey_commerce_lib.model import Page
|
|
15
|
+
from ey_commerce_lib.utils.close import safe_close
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FourSellerClient:
|
|
21
|
+
|
|
22
|
+
def __init__(self, user_name: str,
|
|
23
|
+
password: str,
|
|
24
|
+
user_token: str,
|
|
25
|
+
login_success_call_back: Callable,
|
|
26
|
+
sem: int = 10):
|
|
27
|
+
self.user_name = user_name
|
|
28
|
+
self.password = password
|
|
29
|
+
self.user_token = user_token
|
|
30
|
+
# 登录成功回调函数
|
|
31
|
+
self.login_success_call_back = login_success_call_back
|
|
32
|
+
# 信号量
|
|
33
|
+
self.__sem = asyncio.Semaphore(sem)
|
|
34
|
+
# 自动登录锁
|
|
35
|
+
self.__login_lock = asyncio.Lock()
|
|
36
|
+
# 当前登录任务的 future
|
|
37
|
+
self.__login_in_progress = None
|
|
38
|
+
# ddddocr实例
|
|
39
|
+
self.__ocr = ddddocr.DdddOcr()
|
|
40
|
+
# 异步客户端
|
|
41
|
+
self.__async_client = AsyncClient(base_url="https://www.4seller.com", cookies={"userToken": user_token},
|
|
42
|
+
headers={
|
|
43
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
44
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 "
|
|
45
|
+
"Safari/537.36"
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
async def __auto_login_4seller(self) -> str:
|
|
49
|
+
"""
|
|
50
|
+
自动登录4seller
|
|
51
|
+
:return: 登录
|
|
52
|
+
"""
|
|
53
|
+
browser = None
|
|
54
|
+
context = None
|
|
55
|
+
page = None
|
|
56
|
+
try:
|
|
57
|
+
async with async_playwright() as p:
|
|
58
|
+
browser = await p.chromium.launch(
|
|
59
|
+
headless=True,
|
|
60
|
+
args=[
|
|
61
|
+
'--start-maximized',
|
|
62
|
+
'--disable-blink-features=AutomationControlled',
|
|
63
|
+
]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
context = await browser.new_context(
|
|
67
|
+
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
|
68
|
+
"(KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
|
|
69
|
+
viewport={"width": 1920, "height": 1080},
|
|
70
|
+
locale='zh-CN', # 中文环境
|
|
71
|
+
timezone_id='Asia/Shanghai', # 中国时区
|
|
72
|
+
geolocation={"longitude": 116.4074, "latitude": 39.9042}, # 北京位置
|
|
73
|
+
permissions=["geolocation"]
|
|
74
|
+
)
|
|
75
|
+
page = await context.new_page()
|
|
76
|
+
await page.goto('https://www.4seller.com/login.html')
|
|
77
|
+
# 等待元素出现
|
|
78
|
+
await page.locator('.el-input__inner').first.wait_for()
|
|
79
|
+
input_locators = await page.locator('.el-input__inner').all()
|
|
80
|
+
username_input_element = input_locators[0]
|
|
81
|
+
password_input_element = input_locators[1]
|
|
82
|
+
await username_input_element.fill(self.user_name)
|
|
83
|
+
await password_input_element.fill(self.password)
|
|
84
|
+
login_button_element = page.locator('.el-button.sign_up')
|
|
85
|
+
await login_button_element.click()
|
|
86
|
+
# 获取验证码图片
|
|
87
|
+
capcha_code_img_element = page.locator('.el-input__wrapper img')
|
|
88
|
+
await capcha_code_img_element.wait_for()
|
|
89
|
+
captcha_code_input_element = page.locator('[autocomplete="new-password"]')
|
|
90
|
+
login_count = 1
|
|
91
|
+
# 只能允许一百次登录
|
|
92
|
+
while login_count <= 100:
|
|
93
|
+
# 等图片 src 被赋值
|
|
94
|
+
max_attempts = 10
|
|
95
|
+
for attempt in range(max_attempts):
|
|
96
|
+
src = await capcha_code_img_element.get_attribute("src")
|
|
97
|
+
if src and src.strip() != "":
|
|
98
|
+
break
|
|
99
|
+
await page.wait_for_timeout(500)
|
|
100
|
+
else:
|
|
101
|
+
raise Exception("获取不到图片验证码")
|
|
102
|
+
# 识别验证码
|
|
103
|
+
# 如果有前缀 "data:image/xxx;base64,", 需要去掉
|
|
104
|
+
if ',' in src:
|
|
105
|
+
base64_str = src.split(',')[1]
|
|
106
|
+
|
|
107
|
+
# 解码 base64 为字节流
|
|
108
|
+
img_bytes = base64.b64decode(base64_str)
|
|
109
|
+
captcha_code = self.__ocr.classification(img_bytes)
|
|
110
|
+
# 回填验证码
|
|
111
|
+
await captcha_code_input_element.fill(captcha_code)
|
|
112
|
+
# 再次点击登录按钮
|
|
113
|
+
await login_button_element.click()
|
|
114
|
+
try:
|
|
115
|
+
await page.wait_for_selector(".el-message.el-message--error", timeout=10000)
|
|
116
|
+
except TimeoutError:
|
|
117
|
+
# 获取userToken的cookie
|
|
118
|
+
cookies = await context.cookies()
|
|
119
|
+
for cookie in cookies:
|
|
120
|
+
if cookie["name"] == "userToken":
|
|
121
|
+
userToken = cookie["value"]
|
|
122
|
+
# 返回token
|
|
123
|
+
return userToken
|
|
124
|
+
# 防止验证码切换过快
|
|
125
|
+
await page.wait_for_timeout(2000)
|
|
126
|
+
login_count += 1
|
|
127
|
+
except Exception as e:
|
|
128
|
+
raise e
|
|
129
|
+
finally:
|
|
130
|
+
# 不管成功与否函数都要关闭
|
|
131
|
+
for close_obj in (page, context, browser):
|
|
132
|
+
await safe_close(close_obj)
|
|
133
|
+
|
|
134
|
+
async def __refresh_user_token(self):
|
|
135
|
+
"""
|
|
136
|
+
刷新token
|
|
137
|
+
:return:
|
|
138
|
+
"""
|
|
139
|
+
# 如果有登录任务正在运行
|
|
140
|
+
if self.__login_in_progress is not None:
|
|
141
|
+
# 已有协程在处理登录,我们等待它完成
|
|
142
|
+
await self.__login_in_progress
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
# 没有登录任务,当前协程负责登录
|
|
146
|
+
self.__login_in_progress = asyncio.get_event_loop().create_future()
|
|
147
|
+
# 检测锁,确保只有一个线程在登录
|
|
148
|
+
async with self.__login_lock:
|
|
149
|
+
try:
|
|
150
|
+
user_token = await self.__auto_login_4seller()
|
|
151
|
+
except Exception as e:
|
|
152
|
+
# 如果future没有被终结掉手动设置终结future
|
|
153
|
+
if not self.__login_in_progress.done():
|
|
154
|
+
self.__login_in_progress.set_exception(e)
|
|
155
|
+
logger.error(f'FourSeller自动登录失败 {e}')
|
|
156
|
+
raise Exception(f'FourSeller登录身份失效, 尝试自动登录失败 {e}')
|
|
157
|
+
else:
|
|
158
|
+
# 登录成功后重置token
|
|
159
|
+
self.user_token = user_token
|
|
160
|
+
# 清空原cookies
|
|
161
|
+
self.__async_client.cookies.clear()
|
|
162
|
+
# 重新设置客户端的cookie
|
|
163
|
+
self.__async_client.cookies.set('userToken', self.user_token, domain='www.4seller.com', path='/')
|
|
164
|
+
# 如果future没有被终结掉手动设置终结future,否则会抛出异常影响回调执行
|
|
165
|
+
if not self.__login_in_progress.done():
|
|
166
|
+
self.__login_in_progress.set_result(True)
|
|
167
|
+
# 回调函数可能会失败,但是不能影响其它协程操作
|
|
168
|
+
try:
|
|
169
|
+
await self.login_success_call_back(user_token)
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.error(f'FourSeller登录成功回调函数执行失败 {e}')
|
|
172
|
+
pass
|
|
173
|
+
finally:
|
|
174
|
+
# 提示登录任务完成
|
|
175
|
+
self.__login_in_progress = None
|
|
176
|
+
|
|
177
|
+
async def __request(self, url, method, retry_count=0, **kwargs):
|
|
178
|
+
"""
|
|
179
|
+
4seller基本请求
|
|
180
|
+
:param url: url路径
|
|
181
|
+
:param method: 请求方法
|
|
182
|
+
:param kwargs: 请求参数
|
|
183
|
+
:return:
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
async with self.__sem:
|
|
187
|
+
response = await self.__async_client.request(method, url, **kwargs)
|
|
188
|
+
except ReadTimeout:
|
|
189
|
+
raise Exception(f'FourSeller请求接口超时')
|
|
190
|
+
except Exception as e:
|
|
191
|
+
logger.error(f'FourSeller请求接口失败{e}')
|
|
192
|
+
raise Exception(f'FourSeller请求接口失败{e}')
|
|
193
|
+
else:
|
|
194
|
+
try:
|
|
195
|
+
data = response.json()
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logger.error(f'FourSeller请求,json序列化失败{e},原始数据{response.text}')
|
|
198
|
+
raise Exception(f'FourSeller请求,json序列化失败{e},原始数据{response.text}')
|
|
199
|
+
else:
|
|
200
|
+
if data.get('code') == ResponseCodeEnum.LOGIN_VALIDATION_FAILED:
|
|
201
|
+
# 刷新token
|
|
202
|
+
await self.__refresh_user_token()
|
|
203
|
+
if retry_count < 1:
|
|
204
|
+
# 最多重试一次
|
|
205
|
+
return await self.__request(url, method, 1, **kwargs)
|
|
206
|
+
else:
|
|
207
|
+
raise Exception(f'FourSeller登录成功后,再次请求登录验证失败, 请求接口{url},返回信息{data}')
|
|
208
|
+
return data
|
|
209
|
+
|
|
210
|
+
async def __get(self, url, **kwargs):
|
|
211
|
+
return await self.__request(url, 'GET', **kwargs)
|
|
212
|
+
|
|
213
|
+
async def __post(self, url, **kwargs):
|
|
214
|
+
return await self.__request(url, 'POST', **kwargs)
|
|
215
|
+
|
|
216
|
+
async def __put(self, url, **kwargs):
|
|
217
|
+
return await self.__request(url, 'PUT', **kwargs)
|
|
218
|
+
|
|
219
|
+
async def __delete(self, url, **kwargs):
|
|
220
|
+
return await self.__request(url, 'DELETE', **kwargs)
|
|
221
|
+
|
|
222
|
+
async def __order_page_api(self, query_params: FourSellerOrderQueryModel):
|
|
223
|
+
return await self.__post('/api/v2/order/page', json=query_params.model_dump(by_alias=True))
|
|
224
|
+
|
|
225
|
+
async def __order_page_history_api(self, query_params: FourSellerOrderQueryModel):
|
|
226
|
+
return await self.__post('/api/v2/order/history/page', json=query_params.model_dump(by_alias=True))
|
|
227
|
+
|
|
228
|
+
async def order_page(self, query_params: FourSellerOrderQueryModel) -> Page[FourSellerOrderVO]:
|
|
229
|
+
page_data = await self.__order_page_api(query_params)
|
|
230
|
+
# 能到这里说明登录验证什么的都没有问题,接口返回代码也是代表成功
|
|
231
|
+
if page_data.get('code') != ResponseCodeEnum.SUCCESS:
|
|
232
|
+
raise Exception(f'FourSeller请求接口失败, 请求接口{page_data}')
|
|
233
|
+
return parse_order(page_data.get('data'))
|
|
234
|
+
|
|
235
|
+
async def order_page_history(self, query_params: FourSellerOrderQueryModel) -> Page[FourSellerOrderVO]:
|
|
236
|
+
page_data = await self.__order_page_history_api(query_params)
|
|
237
|
+
# 能到这里说明登录验证什么的都没有问题,接口返回代码也是代表成功
|
|
238
|
+
if page_data.get('code') != ResponseCodeEnum.SUCCESS:
|
|
239
|
+
raise Exception(f'FourSeller拉取历史分页订单失败, 请求接口{page_data}')
|
|
240
|
+
return parse_order(page_data.get('data'))
|
|
241
|
+
|
|
242
|
+
async def list_order(self, query_params: FourSellerOrderQueryModel) -> list[FourSellerOrderVO]:
|
|
243
|
+
# 获取分页信息
|
|
244
|
+
order_list = list()
|
|
245
|
+
page = await self.order_page(query_params)
|
|
246
|
+
# 采用并发提高速度
|
|
247
|
+
page_order_task_list = list()
|
|
248
|
+
for page_number in range(1, page.total_page + 1):
|
|
249
|
+
page_order_task_list.append(
|
|
250
|
+
self.order_page(query_params.copy(update={"page_current": page_number}))
|
|
251
|
+
)
|
|
252
|
+
page_list = await asyncio.gather(*page_order_task_list)
|
|
253
|
+
# 所有的数据
|
|
254
|
+
for every_page in page_list:
|
|
255
|
+
# 插入数据
|
|
256
|
+
order_list.extend(every_page.records)
|
|
257
|
+
return order_list
|
|
258
|
+
|
|
259
|
+
async def list_history_order(self, query_params: FourSellerOrderQueryModel):
|
|
260
|
+
# 获取分页信息
|
|
261
|
+
order_history_list = list()
|
|
262
|
+
page = await self.order_page_history(query_params)
|
|
263
|
+
# 采用并发提高速度
|
|
264
|
+
page_order_task_list = list()
|
|
265
|
+
for page_number in range(1, page.total_page + 1):
|
|
266
|
+
page_order_task_list.append(self.order_page_history(
|
|
267
|
+
query_params.copy(update={"page_current": page_number})
|
|
268
|
+
))
|
|
269
|
+
page_list = await asyncio.gather(*page_order_task_list)
|
|
270
|
+
# 所有的数据
|
|
271
|
+
for every_page in page_list:
|
|
272
|
+
# 插入数据
|
|
273
|
+
order_history_list.extend(every_page.records)
|
|
274
|
+
return order_history_list
|
|
275
|
+
|
|
276
|
+
async def __aenter__(self):
|
|
277
|
+
return self
|
|
278
|
+
|
|
279
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
280
|
+
await self.__async_client.aclose()
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from ey_commerce_lib.four_seller.schemas.vo.order import FourSellerOrderVO
|
|
4
|
+
from ey_commerce_lib.model import Page
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_order(data: dict) -> Page[FourSellerOrderVO]:
|
|
8
|
+
# 计算total_page
|
|
9
|
+
page_size = data.get('pageSize')
|
|
10
|
+
total = data.get('total')
|
|
11
|
+
page_number = data.get('pageCurrent')
|
|
12
|
+
total_page = math.ceil(total / page_size) if total > 0 else 0
|
|
13
|
+
return Page(
|
|
14
|
+
records=[FourSellerOrderVO(**record) for record in data.get('records')],
|
|
15
|
+
total=total,
|
|
16
|
+
page_size=page_size,
|
|
17
|
+
page_number=page_number,
|
|
18
|
+
total_page=total_page
|
|
19
|
+
)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from pydantic import BaseModel, ConfigDict
|
|
2
|
+
|
|
3
|
+
from ey_commerce_lib.utils.str import to_camel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FourSellerOrderQueryModel(BaseModel):
|
|
7
|
+
# 页码
|
|
8
|
+
page_current: int = 1
|
|
9
|
+
# 每页条数
|
|
10
|
+
page_size: int = 100
|
|
11
|
+
# 平台
|
|
12
|
+
platform: str = ""
|
|
13
|
+
# 店铺id列表
|
|
14
|
+
shop_id_list: list[str] = []
|
|
15
|
+
# 仓库id 页面未知来源
|
|
16
|
+
warehouse_id: str = ""
|
|
17
|
+
# 物流id 例如: 13554
|
|
18
|
+
logistics_service_id: str = ""
|
|
19
|
+
# 物流服务id映射关系父子id,id连接起来 例如: ["470", "13554"]
|
|
20
|
+
logistics_service_map: list[str] = []
|
|
21
|
+
# 单品单数: onlyOne 全部包裹类型: "" 单品多数: gtOne 多品: multiple
|
|
22
|
+
item_type: str = ""
|
|
23
|
+
"""
|
|
24
|
+
打印状态 全部: "" 面单已打印: labelPrinted 面单未打印: labelUnPrinted 装箱已打印: packingPrinted 装箱未打印: packingUnPrinted
|
|
25
|
+
拣货单已打印: pickPrinted 拣货单未打印: pickUnPrinted
|
|
26
|
+
"""
|
|
27
|
+
print_status: str = ""
|
|
28
|
+
# 买家指定
|
|
29
|
+
shipping_method: list[str] = []
|
|
30
|
+
# 搜索类型 订单号: orderNo 物流跟踪号: trackNo 其余请参考页面
|
|
31
|
+
search_type: str = "orderNo"
|
|
32
|
+
# 搜索方式 模糊: like 精确: exact
|
|
33
|
+
search_method: str = "exact"
|
|
34
|
+
# 搜索内容
|
|
35
|
+
search_value: str = ""
|
|
36
|
+
# 商品总数最小
|
|
37
|
+
item_min: str = ""
|
|
38
|
+
# 商品总数最大
|
|
39
|
+
item_max: str = ""
|
|
40
|
+
# 重量最小
|
|
41
|
+
weight_min: str = ""
|
|
42
|
+
# 重量最大
|
|
43
|
+
weight_max: str = ""
|
|
44
|
+
# 重量单位 lb oz kg g
|
|
45
|
+
weight_unit: str = "lb"
|
|
46
|
+
# 到期时间 如果是数字就是小时 如果为空字符串是全部
|
|
47
|
+
expires_hour: str | int = ""
|
|
48
|
+
hours: str = ""
|
|
49
|
+
# 平台状态 待发货: Awaiting_Shipment 待揽收: Awaiting_Collection 其它参考页面
|
|
50
|
+
platform_status: str = ""
|
|
51
|
+
# 发货地址id 如果为空字符串就是没有选择
|
|
52
|
+
ship_from_address_id: str | int = ""
|
|
53
|
+
# 国家编码 具体参考筛选页面
|
|
54
|
+
country_code: str = ""
|
|
55
|
+
# 国家名称 具体参考筛选页面
|
|
56
|
+
country_name: str = ""
|
|
57
|
+
# 省份或者洲
|
|
58
|
+
state: str = ""
|
|
59
|
+
# 买家备注 空字符串未选 有:1 无: 0
|
|
60
|
+
buyer_note: str | int = ""
|
|
61
|
+
# 卖家备注 空字符串未选 有:1 无: 0
|
|
62
|
+
seller_note: str = ""
|
|
63
|
+
# 系统备注: 空字符串未选 有:1 无: 0
|
|
64
|
+
internal_note: str = ""
|
|
65
|
+
# 平台标记 PRE_SALE: Temu预售
|
|
66
|
+
platform_marker: str = ""
|
|
67
|
+
# 下单时间 这个时间比上海时间要晚7个小时
|
|
68
|
+
date_query_create_start_time: str = ""
|
|
69
|
+
date_query_create_end_time: str = ""
|
|
70
|
+
# 付款时间
|
|
71
|
+
date_query_paid_start_time: str = ""
|
|
72
|
+
date_query_paid_end_time: str = ""
|
|
73
|
+
# 发货时间
|
|
74
|
+
date_query_ship_start_time: str = ""
|
|
75
|
+
date_query_ship_end_time: str = ""
|
|
76
|
+
# 打印面单时间
|
|
77
|
+
date_query_print_label_start_time: str = ""
|
|
78
|
+
date_query_print_label_end_time: str = ""
|
|
79
|
+
# 取消订单时间
|
|
80
|
+
date_query_cancel_start_time: str = ""
|
|
81
|
+
date_query_cancel_end_time: str = ""
|
|
82
|
+
# 标签页 具体参考筛选页面
|
|
83
|
+
tag_id_list: list[str] = []
|
|
84
|
+
# 订单状态 全部: 空字符串 未付款: un_paid 已发货: shipped 待处理: to_ship 风控中: on_hold 处理中: in_process 已签收: delivered 参考页面
|
|
85
|
+
all_order_status: str = ""
|
|
86
|
+
# 订单状态: 全部: all 已发货: shipped
|
|
87
|
+
order_status: str = "all"
|
|
88
|
+
# 排序字段
|
|
89
|
+
order_by: str = "orderPaidTime"
|
|
90
|
+
# 排序方式 asc: 升序 desc: 降序
|
|
91
|
+
desc: str = "asc"
|
|
92
|
+
|
|
93
|
+
country: str = ""
|
|
94
|
+
note_query: str = ""
|
|
95
|
+
tag_query: str = ""
|
|
96
|
+
exception_type: str = ""
|
|
97
|
+
|
|
98
|
+
model_config = ConfigDict(
|
|
99
|
+
alias_generator=to_camel,
|
|
100
|
+
populate_by_name=True
|
|
101
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FourSellerOrderAddressVo(BaseModel):
|
|
6
|
+
# 地址 ID
|
|
7
|
+
id: int
|
|
8
|
+
|
|
9
|
+
# 收件人姓名
|
|
10
|
+
name: str
|
|
11
|
+
|
|
12
|
+
# 城市
|
|
13
|
+
city: str
|
|
14
|
+
|
|
15
|
+
# 邮编
|
|
16
|
+
postal_code: Optional[str] = Field(..., alias="postalCode")
|
|
17
|
+
|
|
18
|
+
# 完整地址
|
|
19
|
+
address: str
|
|
20
|
+
|
|
21
|
+
# 电话
|
|
22
|
+
phone: str
|
|
23
|
+
|
|
24
|
+
# 邮箱
|
|
25
|
+
email: str
|
|
26
|
+
|
|
27
|
+
# 国家代码
|
|
28
|
+
country_code: str = Field(..., alias="countryCode")
|
|
29
|
+
|
|
30
|
+
# 区/县
|
|
31
|
+
county: Optional[str]
|
|
32
|
+
|
|
33
|
+
# 地址行1
|
|
34
|
+
address1: str
|
|
35
|
+
|
|
36
|
+
# 地址行2
|
|
37
|
+
address2: Optional[str]
|
|
38
|
+
|
|
39
|
+
# 地址行3
|
|
40
|
+
address3: Optional[str] = Field(None)
|
|
41
|
+
|
|
42
|
+
# 州/省
|
|
43
|
+
state: Optional[str] = Field(None)
|
|
44
|
+
|
|
45
|
+
# 地址备注
|
|
46
|
+
msg: Optional[str] = Field(None)
|
|
47
|
+
|
|
48
|
+
# 地址备注映射
|
|
49
|
+
msg_map: Optional[dict] = Field(None, alias="msgMap")
|
|
50
|
+
|
|
51
|
+
# 是否住宅
|
|
52
|
+
residential: Optional[bool]
|
|
53
|
+
|
|
54
|
+
# 是否检查地址
|
|
55
|
+
check_address: bool = Field(..., alias="checkAddress")
|
|
56
|
+
|
|
57
|
+
model_config = ConfigDict(
|
|
58
|
+
populate_by_name=True
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class FourSellerTimeInfoVO(BaseModel):
|
|
63
|
+
# 订单支付时间
|
|
64
|
+
order_paid_time: Optional[str] = Field(..., alias="orderPaidTime")
|
|
65
|
+
|
|
66
|
+
# 订单创建时间
|
|
67
|
+
order_create_time: str = Field(..., alias="orderCreateTime")
|
|
68
|
+
|
|
69
|
+
# 最晚发货日期
|
|
70
|
+
latest_ship_date: Optional[str] = Field(..., alias="latestShipDate")
|
|
71
|
+
|
|
72
|
+
# 发货时间
|
|
73
|
+
order_shipped_time: Optional[str] = Field(..., alias="orderShippedTime")
|
|
74
|
+
|
|
75
|
+
# 最晚送达日期
|
|
76
|
+
latest_delivery_date: Optional[str] = Field(..., alias="latestDeliveryDate")
|
|
77
|
+
|
|
78
|
+
# 取消时间
|
|
79
|
+
cancel_time: Optional[str] = Field(..., alias="cancelTime")
|
|
80
|
+
|
|
81
|
+
# 剩余天数
|
|
82
|
+
leave_day: int = Field(..., alias="leaveDay")
|
|
83
|
+
|
|
84
|
+
model_config = ConfigDict(
|
|
85
|
+
populate_by_name=True
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class FourSellerPackageInfoVO(BaseModel):
|
|
90
|
+
# 重量
|
|
91
|
+
weight: Optional[float]
|
|
92
|
+
|
|
93
|
+
# 重量单位
|
|
94
|
+
weight_unit: Optional[str] = Field(None, alias="weightUnit")
|
|
95
|
+
|
|
96
|
+
# 包裹 ID
|
|
97
|
+
package_id: Optional[int] = Field(None, alias="packageId")
|
|
98
|
+
|
|
99
|
+
# 包裹类型
|
|
100
|
+
package_type: Optional[str] = Field(None, alias="packageType")
|
|
101
|
+
|
|
102
|
+
# 包裹名称
|
|
103
|
+
package_name: Optional[str] = Field(None, alias="packageName")
|
|
104
|
+
|
|
105
|
+
# 平台包裹类型
|
|
106
|
+
platform_package_type: Optional[str] = Field(None, alias="platformPackageType")
|
|
107
|
+
|
|
108
|
+
# 长度
|
|
109
|
+
length: Optional[float]
|
|
110
|
+
|
|
111
|
+
# 宽度
|
|
112
|
+
width: Optional[float]
|
|
113
|
+
|
|
114
|
+
# 高度
|
|
115
|
+
height: Optional[float]
|
|
116
|
+
|
|
117
|
+
# 尺寸单位
|
|
118
|
+
dimension_unit: Optional[str] = Field(None, alias="dimensionUnit")
|
|
119
|
+
|
|
120
|
+
model_config = ConfigDict(
|
|
121
|
+
populate_by_name=True
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class FourSellerShippingServiceInfoVO(BaseModel):
|
|
126
|
+
# 保险金额
|
|
127
|
+
insurance_amount: Optional[float] = Field(None, alias="insuranceAmount")
|
|
128
|
+
|
|
129
|
+
# 保险币种
|
|
130
|
+
insurance_currency: Optional[str] = Field(None, alias="insuranceCurrency")
|
|
131
|
+
|
|
132
|
+
# 物流服务
|
|
133
|
+
shipping_service: Optional[str] = Field(None, alias="shippingService")
|
|
134
|
+
|
|
135
|
+
# 承运商
|
|
136
|
+
carrier: Optional[str]
|
|
137
|
+
|
|
138
|
+
# 运费
|
|
139
|
+
shipping_fee: Optional[float] = Field(None, alias="shippingFee")
|
|
140
|
+
|
|
141
|
+
# 币种
|
|
142
|
+
currency: Optional[str]
|
|
143
|
+
|
|
144
|
+
# 预估送达天数
|
|
145
|
+
estimated_delivery_days: Optional[int] = Field(None, alias="estimatedDeliveryDays")
|
|
146
|
+
|
|
147
|
+
# 物流授权 ID
|
|
148
|
+
logistics_auth_id: Optional[int] = Field(None, alias="logisticsAuthId")
|
|
149
|
+
|
|
150
|
+
# 物流承运商 ID
|
|
151
|
+
logistics_carrier_id: Optional[int] = Field(None, alias="logisticsCarrierId")
|
|
152
|
+
|
|
153
|
+
# 物流承运商代码
|
|
154
|
+
logistics_carrier_code: Optional[str] = Field(None, alias="logisticsCarrierCode")
|
|
155
|
+
|
|
156
|
+
# 物流承运商名称
|
|
157
|
+
logistics_carrier_name: Optional[str] = Field(None, alias="logisticsCarrierName")
|
|
158
|
+
|
|
159
|
+
# 物流平台
|
|
160
|
+
logistics_platform: Optional[str] = Field(None, alias="logisticsPlatform")
|
|
161
|
+
|
|
162
|
+
# 物流服务 ID
|
|
163
|
+
logistics_service_id: Optional[int] = Field(None, alias="logisticsServiceId")
|
|
164
|
+
|
|
165
|
+
# 物流服务代码
|
|
166
|
+
logistics_service_code: Optional[str] = Field(None, alias="logisticsServiceCode")
|
|
167
|
+
|
|
168
|
+
# 物流服务类型
|
|
169
|
+
logistics_service_type: Optional[str] = Field(None, alias="logisticsServiceType")
|
|
170
|
+
|
|
171
|
+
# 物流服务名称
|
|
172
|
+
logistics_service_name: Optional[str] = Field(None, alias="logisticsServiceName")
|
|
173
|
+
|
|
174
|
+
# 平台物流服务 ID
|
|
175
|
+
platform_shipping_service_id: Optional[int] = Field(None, alias="platformShippingServiceId")
|
|
176
|
+
|
|
177
|
+
# 空白箱
|
|
178
|
+
blank_box: Optional[int] = Field(None, alias="blankBox")
|
|
179
|
+
|
|
180
|
+
# 阻止 AMZL
|
|
181
|
+
block_amzl: Optional[int] = Field(None, alias="blockAmzl")
|
|
182
|
+
|
|
183
|
+
# ERP 预估发货日期
|
|
184
|
+
erp_estimated_shipping_date: Optional[str] = Field(None, alias="erpEstimatedShippingDate")
|
|
185
|
+
|
|
186
|
+
# 配送确认类型
|
|
187
|
+
delivery_confirmation_type: Optional[str] = Field(None, alias="deliveryConfirmationType")
|
|
188
|
+
|
|
189
|
+
# 标签价格
|
|
190
|
+
label_price: Optional[float] = Field(None, alias="labelPrice")
|
|
191
|
+
|
|
192
|
+
# 预估运费
|
|
193
|
+
estimated_shipping_price: Optional[float] = Field(None, alias="estimatedShippingPrice")
|
|
194
|
+
|
|
195
|
+
model_config = ConfigDict(
|
|
196
|
+
populate_by_name=True
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class FourSellerOrderItemInfoVO(BaseModel):
|
|
201
|
+
# 订单商品 ID
|
|
202
|
+
order_item_id: int = Field(..., alias="orderItemId")
|
|
203
|
+
|
|
204
|
+
# 订单 ID
|
|
205
|
+
order_id: int = Field(..., alias="orderId")
|
|
206
|
+
|
|
207
|
+
# 卖家 SKU
|
|
208
|
+
seller_sku: Optional[str] = Field(..., alias="sellerSku")
|
|
209
|
+
|
|
210
|
+
# 商品标题
|
|
211
|
+
title: str
|
|
212
|
+
|
|
213
|
+
# 图片 URL
|
|
214
|
+
img_url: Optional[str] = Field(None, alias="imgUrl")
|
|
215
|
+
|
|
216
|
+
# 列表 URL
|
|
217
|
+
listing_url: Optional[str] = Field(None, alias="listingUrl")
|
|
218
|
+
|
|
219
|
+
# SKU ID
|
|
220
|
+
sku_id: Optional[int] = Field(..., alias="skuId")
|
|
221
|
+
|
|
222
|
+
# SKU
|
|
223
|
+
sku: Optional[str] = Field(None)
|
|
224
|
+
|
|
225
|
+
# 数量
|
|
226
|
+
quantity: int
|
|
227
|
+
|
|
228
|
+
# 变体属性
|
|
229
|
+
variant_attr: Optional[str] = Field(None, alias="variantAttr")
|
|
230
|
+
|
|
231
|
+
# 单价
|
|
232
|
+
item_price: Optional[float] = Field(..., alias="itemPrice")
|
|
233
|
+
|
|
234
|
+
# 币种
|
|
235
|
+
currency: Optional[str] = Field(None)
|
|
236
|
+
|
|
237
|
+
# 是否占用库存
|
|
238
|
+
occupy: Optional[bool] = Field(None)
|
|
239
|
+
|
|
240
|
+
# 商品是否未找到
|
|
241
|
+
product_not_found: bool = Field(..., alias="productNotFound")
|
|
242
|
+
|
|
243
|
+
# 地址是否有效
|
|
244
|
+
address_valid: bool = Field(..., alias="addressValid")
|
|
245
|
+
|
|
246
|
+
# 地址错误信息
|
|
247
|
+
address_error_msg: Optional[str] = Field(None, alias="addressErrorMsg")
|
|
248
|
+
|
|
249
|
+
# 来源 URL
|
|
250
|
+
source_url: Optional[str] = Field(None, alias="sourceUrl")
|
|
251
|
+
|
|
252
|
+
# 是否预售
|
|
253
|
+
pre_sale: int = Field(..., alias="preSale")
|
|
254
|
+
|
|
255
|
+
model_config = ConfigDict(
|
|
256
|
+
populate_by_name=True
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class FourSellerOrderVO(BaseModel):
|
|
261
|
+
# 订单 ID
|
|
262
|
+
order_id: int = Field(..., alias="orderId")
|
|
263
|
+
|
|
264
|
+
# 金额
|
|
265
|
+
amount: Optional[float] = Field(None)
|
|
266
|
+
|
|
267
|
+
# 币种
|
|
268
|
+
currency: Optional[str] = Field(None)
|
|
269
|
+
|
|
270
|
+
# 仓库 ID
|
|
271
|
+
warehouse_id: int = Field(..., alias="warehouseId")
|
|
272
|
+
|
|
273
|
+
# 仓库类型
|
|
274
|
+
warehouse_type: str = Field(..., alias="warehouseType")
|
|
275
|
+
|
|
276
|
+
# 仓库代码
|
|
277
|
+
warehouse_code: Optional[str] = Field(None, alias="warehouseCode")
|
|
278
|
+
|
|
279
|
+
# 平台仓名称
|
|
280
|
+
platform_warehouse_name: Optional[str] = Field(None, alias="platformWarehouseName")
|
|
281
|
+
|
|
282
|
+
# 平台物流方式
|
|
283
|
+
platform_shipment_method: Optional[str] = Field(None, alias="platformShipmentMethod")
|
|
284
|
+
|
|
285
|
+
# 支付状态
|
|
286
|
+
paid_status: Optional[str] = Field(None, alias="paidStatus")
|
|
287
|
+
|
|
288
|
+
# 订单状态
|
|
289
|
+
order_status: str = Field(..., alias="orderStatus")
|
|
290
|
+
|
|
291
|
+
# 平台订单状态
|
|
292
|
+
platform_order_status: str = Field(..., alias="platformOrderStatus")
|
|
293
|
+
|
|
294
|
+
# 取消原因
|
|
295
|
+
cancel_reason: Optional[str] = Field(None, alias="cancelReason")
|
|
296
|
+
|
|
297
|
+
# 平台
|
|
298
|
+
platform: str
|
|
299
|
+
|
|
300
|
+
# 平台订单号
|
|
301
|
+
platform_order_id: str = Field(..., alias="platformOrderId")
|
|
302
|
+
|
|
303
|
+
# 平台订单编号
|
|
304
|
+
platform_order_no: str = Field(..., alias="platformOrderNo")
|
|
305
|
+
|
|
306
|
+
# 店铺 ID
|
|
307
|
+
shop_id: int = Field(..., alias="shopId")
|
|
308
|
+
|
|
309
|
+
# 店铺名称
|
|
310
|
+
shop_name: Optional[str] = Field(None, alias="shopName")
|
|
311
|
+
|
|
312
|
+
# 包裹名称
|
|
313
|
+
package_name: Optional[str] = Field(None, alias="packageName")
|
|
314
|
+
|
|
315
|
+
# 买家备注
|
|
316
|
+
buyer_memo: Optional[str] = Field(None, alias="buyerMemo")
|
|
317
|
+
|
|
318
|
+
# 卖家备注
|
|
319
|
+
seller_memo: Optional[str] = Field(None, alias="sellerMemo")
|
|
320
|
+
|
|
321
|
+
# 内部备注
|
|
322
|
+
internal_memo: Optional[str] = Field(None, alias="internalMemo")
|
|
323
|
+
|
|
324
|
+
# 发货单号
|
|
325
|
+
shipment_no: Optional[str] = Field(None, alias="shipmentNo")
|
|
326
|
+
|
|
327
|
+
# 是否三方仓
|
|
328
|
+
third_party: bool = Field(..., alias="thirdParty")
|
|
329
|
+
|
|
330
|
+
# 是否打印标签
|
|
331
|
+
print_label: bool = Field(..., alias="printLabel")
|
|
332
|
+
|
|
333
|
+
# 是否打印装箱单
|
|
334
|
+
print_packing_slip: bool = Field(..., alias="printPackingSlip")
|
|
335
|
+
|
|
336
|
+
# 是否打印拣货单
|
|
337
|
+
print_pick: bool = Field(..., alias="printPick")
|
|
338
|
+
|
|
339
|
+
# 配送选项
|
|
340
|
+
delivery_option_type: Optional[int] = Field(None, alias="deliveryOptionType")
|
|
341
|
+
|
|
342
|
+
# 买标状态
|
|
343
|
+
buy_label_process_status: str = Field(..., alias="buyLabelProcessStatus")
|
|
344
|
+
|
|
345
|
+
# 错误信息
|
|
346
|
+
error_message: Optional[str] = Field(None, alias="errorMessage")
|
|
347
|
+
|
|
348
|
+
# 发货类型
|
|
349
|
+
shipment_type: Optional[str] = Field(..., alias="shipmentType")
|
|
350
|
+
|
|
351
|
+
# 用户设置发货类型
|
|
352
|
+
user_setting_shipment_type: str = Field(..., alias="userSettingShipmentType")
|
|
353
|
+
|
|
354
|
+
# 发货地址 ID
|
|
355
|
+
ship_from_address_id: Optional[int] = Field(None, alias="shipFromAddressId")
|
|
356
|
+
|
|
357
|
+
# 是否可拆分
|
|
358
|
+
can_split: Optional[bool] = Field(..., alias="canSplit")
|
|
359
|
+
|
|
360
|
+
# 追踪号
|
|
361
|
+
tracking_no: Optional[str] = Field(None, alias="trackingNo")
|
|
362
|
+
|
|
363
|
+
# 物流方式
|
|
364
|
+
shipping_method: str = Field(..., alias="shippingMethod")
|
|
365
|
+
|
|
366
|
+
# 标签列表
|
|
367
|
+
tag_list: Optional[list[str]] = Field(None, alias="tagList")
|
|
368
|
+
|
|
369
|
+
# 新标签列表
|
|
370
|
+
new_tag_list: Optional[list[dict]] = Field(None, alias="newTagList")
|
|
371
|
+
|
|
372
|
+
# 拆单编号
|
|
373
|
+
split_no: int = Field(..., alias="splitNo")
|
|
374
|
+
|
|
375
|
+
# 是否拆单
|
|
376
|
+
is_split: int = Field(..., alias="isSplit")
|
|
377
|
+
|
|
378
|
+
# ERP 是否标记发货
|
|
379
|
+
is_erp_mark_ship: int = Field(..., alias="isErpMarkShip")
|
|
380
|
+
|
|
381
|
+
# 标签地址
|
|
382
|
+
shipping_label_url: Optional[str] = Field(None, alias="shippingLabelUrl")
|
|
383
|
+
|
|
384
|
+
# 配送渠道类型
|
|
385
|
+
fulfillment_channel_type: int = Field(..., alias="fulfillmentChannelType")
|
|
386
|
+
|
|
387
|
+
# 标签打印时间
|
|
388
|
+
print_label_time: Optional[str] = Field(None, alias="printLabelTime")
|
|
389
|
+
|
|
390
|
+
# 拣货单打印时间
|
|
391
|
+
print_pick_time: Optional[str] = Field(None, alias="printPickTime")
|
|
392
|
+
|
|
393
|
+
# 装箱单打印时间
|
|
394
|
+
print_packing_slip_time: Optional[str] = Field(None, alias="printPackingSlipTime")
|
|
395
|
+
|
|
396
|
+
# 是否 17 物流挂号
|
|
397
|
+
is_register17: int = Field(..., alias="isRegister17")
|
|
398
|
+
|
|
399
|
+
# 第三方仓状态
|
|
400
|
+
third_party_warehouse_status: Optional[str] = Field(None, alias="thirdPartyWarehouseStatus")
|
|
401
|
+
|
|
402
|
+
# 订单类型
|
|
403
|
+
order_type: int = Field(..., alias="orderType")
|
|
404
|
+
|
|
405
|
+
# 被合并订单列表
|
|
406
|
+
be_merged_order_list: Optional[list[dict]] = Field(None, alias="beMergedOrderList")
|
|
407
|
+
|
|
408
|
+
# 买家申请取消
|
|
409
|
+
is_buyer_requested_cancel: int = Field(..., alias="isBuyerRequestedCancel")
|
|
410
|
+
|
|
411
|
+
# 是否作废
|
|
412
|
+
is_voided: int = Field(..., alias="isVoided")
|
|
413
|
+
|
|
414
|
+
# 地址信息
|
|
415
|
+
order_address_vo: Optional[FourSellerOrderAddressVo] = Field(..., alias="orderAddressVo")
|
|
416
|
+
|
|
417
|
+
# 时间信息
|
|
418
|
+
time_info: FourSellerTimeInfoVO = Field(..., alias="timeInfo")
|
|
419
|
+
|
|
420
|
+
# 包裹信息
|
|
421
|
+
package_info: FourSellerPackageInfoVO = Field(..., alias="packageInfo")
|
|
422
|
+
|
|
423
|
+
# 物流服务信息
|
|
424
|
+
shipping_service_info: FourSellerShippingServiceInfoVO = Field(..., alias="shippingServiceInfo")
|
|
425
|
+
|
|
426
|
+
# 商品列表
|
|
427
|
+
order_item_info_list: list[FourSellerOrderItemInfoVO] = Field(..., alias="orderItemInfoList")
|
|
428
|
+
|
|
429
|
+
# 是否样品订单
|
|
430
|
+
is_sample_order: int = Field(..., alias="isSampleOrder")
|
|
431
|
+
|
|
432
|
+
# 是否预售
|
|
433
|
+
pre_sale: Optional[int] = Field(..., alias="preSale")
|
|
434
|
+
|
|
435
|
+
model_config = ConfigDict(
|
|
436
|
+
populate_by_name=True
|
|
437
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from httpx import AsyncClient
|
|
2
|
+
|
|
3
|
+
from ey_commerce_lib.kogan.schemas.query.order import KoganOrderQuery
|
|
4
|
+
from ey_commerce_lib.kogan.schemas.query.product import KoganProductQuery
|
|
5
|
+
from ey_commerce_lib.kogan.schemas.response.order import OrderResponseModel
|
|
6
|
+
from ey_commerce_lib.kogan.schemas.response.product import ProductResponse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class KoganClient:
|
|
10
|
+
|
|
11
|
+
def __init__(self, seller_id: str, seller_token: str):
|
|
12
|
+
self.seller_id = seller_id
|
|
13
|
+
self.seller_token = seller_token
|
|
14
|
+
# 异步客户端
|
|
15
|
+
self.__async_client = AsyncClient(base_url="https://nimda.kogan.com",
|
|
16
|
+
headers={
|
|
17
|
+
'Accept': 'application/json',
|
|
18
|
+
'SellerId': self.seller_id,
|
|
19
|
+
'SellerToken': self.seller_token
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
async def orders(self, query_params: KoganOrderQuery):
|
|
23
|
+
# 设置查询参数
|
|
24
|
+
orders_res = await self.__async_client.get('/api/marketplace/v2/orders/',
|
|
25
|
+
params=query_params.model_dump(by_alias=True,
|
|
26
|
+
exclude_none=True))
|
|
27
|
+
return OrderResponseModel(**orders_res.json())
|
|
28
|
+
|
|
29
|
+
async def products(self, query_params: KoganProductQuery):
|
|
30
|
+
products_res = await self.__async_client.get('/api/marketplace/v2/products/',
|
|
31
|
+
params=query_params.model_dump(by_alias=True,
|
|
32
|
+
exclude_none=True
|
|
33
|
+
))
|
|
34
|
+
return ProductResponse(**products_res.json())
|
|
35
|
+
|
|
36
|
+
async def __aenter__(self):
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
40
|
+
await self.__async_client.aclose()
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class KoganOrderQuery(BaseModel):
|
|
7
|
+
# 订单状态 只能传入 ReleasedForShipment
|
|
8
|
+
status: str = None
|
|
9
|
+
# 数量 默认值不给为无限制
|
|
10
|
+
limit: Optional[int] = None
|
|
11
|
+
# 开始日期
|
|
12
|
+
start_date_utc: Optional[str] = Field(default=None, alias="startDateUTC")
|
|
13
|
+
# 结束日期
|
|
14
|
+
end_date_utc: Optional[str] = Field(default=None, alias="endDateUTC")
|
|
15
|
+
|
|
16
|
+
model_config = ConfigDict(
|
|
17
|
+
# 允许使用别名
|
|
18
|
+
populate_by_name=True
|
|
19
|
+
)
|
|
20
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class KoganProductQuery(BaseModel):
|
|
6
|
+
enabled: Optional[bool] = Field(
|
|
7
|
+
None,
|
|
8
|
+
alias="enabled",
|
|
9
|
+
description="启用状态过滤(True/true/1 表示启用,False/false/0 表示禁用)"
|
|
10
|
+
)
|
|
11
|
+
category: Optional[str] = Field(
|
|
12
|
+
None,
|
|
13
|
+
alias="category",
|
|
14
|
+
description="按 Kogan.com 类别名称筛选(不区分大小写,可多选)"
|
|
15
|
+
)
|
|
16
|
+
brand: Optional[str] = Field(
|
|
17
|
+
None,
|
|
18
|
+
alias="brand",
|
|
19
|
+
description="按品牌筛选(不区分大小写,可多选,标题中逗号需要转义,例如 '\\,')"
|
|
20
|
+
)
|
|
21
|
+
created: Optional[str] = Field(
|
|
22
|
+
None,
|
|
23
|
+
alias="created",
|
|
24
|
+
description="创建时间"
|
|
25
|
+
)
|
|
26
|
+
ebay_category: Optional[int] = Field(
|
|
27
|
+
None,
|
|
28
|
+
alias="ebay_category",
|
|
29
|
+
description="按 eBay 类别 ID 筛选"
|
|
30
|
+
)
|
|
31
|
+
sku: Optional[str] = Field(
|
|
32
|
+
None,
|
|
33
|
+
alias="sku",
|
|
34
|
+
description="按 SKU 精确匹配(支持多选)"
|
|
35
|
+
)
|
|
36
|
+
search: Optional[str] = Field(
|
|
37
|
+
None,
|
|
38
|
+
alias="search",
|
|
39
|
+
description="搜索商品标题"
|
|
40
|
+
)
|
|
41
|
+
ordering: Optional[str] = Field(
|
|
42
|
+
None,
|
|
43
|
+
alias="ordering",
|
|
44
|
+
description="结果排序字段"
|
|
45
|
+
)
|
|
46
|
+
cursor: Optional[str] = Field(
|
|
47
|
+
None,
|
|
48
|
+
alias="cursor",
|
|
49
|
+
description="用于分页的游标(续接 'next' URL 的分页查询)"
|
|
50
|
+
)
|
|
51
|
+
size: Optional[int] = Field(
|
|
52
|
+
None,
|
|
53
|
+
alias="size",
|
|
54
|
+
description="每页返回结果数量"
|
|
55
|
+
)
|
|
56
|
+
created_after: Optional[str] = Field(
|
|
57
|
+
None,
|
|
58
|
+
alias="created_after",
|
|
59
|
+
description="筛选创建日期 >= 指定日期(AEST/AEDT 格式 YYYY-MM-DD)"
|
|
60
|
+
)
|
|
61
|
+
created_before: Optional[str] = Field(
|
|
62
|
+
None,
|
|
63
|
+
alias="created_before",
|
|
64
|
+
description="筛选创建日期 <= 指定日期(AEST/AEDT 格式 YYYY-MM-DD)"
|
|
65
|
+
)
|
|
66
|
+
detail: Optional[bool] = Field(
|
|
67
|
+
None,
|
|
68
|
+
alias="detail",
|
|
69
|
+
description="是否启用响应中所有字段(True/true/1 表示启用)"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
model_config = ConfigDict(
|
|
73
|
+
# 支持别名
|
|
74
|
+
populate_by_name=True
|
|
75
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AddressModel(BaseModel):
|
|
7
|
+
address_line1: str = Field(..., alias="AddressLine1") # 地址行1
|
|
8
|
+
address_line2: Optional[str] = Field(None, alias="AddressLine2") # 地址行2
|
|
9
|
+
city: str = Field(..., alias="City") # 城市
|
|
10
|
+
company_name: Optional[str] = Field(None, alias="CompanyName") # 公司名称
|
|
11
|
+
country: str = Field(..., alias="Country") # 国家代码
|
|
12
|
+
daytime_phone: Optional[str] = Field(None, alias="DaytimePhone") # 白天联系电话
|
|
13
|
+
email_address: Optional[str] = Field(None, alias="EmailAddress") # 邮箱地址
|
|
14
|
+
evening_phone: Optional[str] = Field(None, alias="EveningPhone") # 夜间联系电话
|
|
15
|
+
first_name: str = Field(..., alias="FirstName") # 名
|
|
16
|
+
last_name: str = Field(..., alias="LastName") # 姓
|
|
17
|
+
name_suffix: Optional[str] = Field(None, alias="NameSuffix") # 姓名后缀
|
|
18
|
+
postal_code: str = Field(..., alias="PostalCode") # 邮政编码
|
|
19
|
+
state_or_province: Optional[str] = Field(None, alias="StateOrProvince") # 州或省
|
|
20
|
+
location_id: Optional[str] = Field(None, alias="LocationId") # 位置 ID
|
|
21
|
+
location_id_source: Optional[str] = Field(None, alias="LocationIdSource") # 位置 ID 来源
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ItemModel(BaseModel):
|
|
25
|
+
id: str = Field(..., alias="ID") # 商品 ID
|
|
26
|
+
quantity: int = Field(..., alias="Quantity") # 商品数量
|
|
27
|
+
seller_sku: str = Field(..., alias="SellerSku") # 卖家 SKU
|
|
28
|
+
product_title: str = Field(..., alias="ProductTitle") # 商品标题
|
|
29
|
+
unit_price: float = Field(..., alias="UnitPrice") # 单价
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class OrderModel(BaseModel):
|
|
33
|
+
id: str = Field(..., alias="ID") # 订单 ID
|
|
34
|
+
currency: str = Field(..., alias="Currency") # 货币代码
|
|
35
|
+
items: list[ItemModel] = Field(..., alias="Items") # 商品列表
|
|
36
|
+
order_date_utc: datetime = Field(..., alias="OrderDateUtc") # 下单时间
|
|
37
|
+
order_status: str = Field(..., alias="OrderStatus") # 订单状态
|
|
38
|
+
requested_shipping_method: str = Field(..., alias="RequestedShippingMethod") # 请求的配送方式
|
|
39
|
+
total_gift_option_price: float = Field(..., alias="TotalGiftOptionPrice") # 礼品选项总价
|
|
40
|
+
total_gift_option_tax_price: float = Field(..., alias="TotalGiftOptionTaxPrice") # 礼品选项税费总价
|
|
41
|
+
total_price: float = Field(..., alias="TotalPrice") # 订单总价
|
|
42
|
+
total_shipping_price: float = Field(..., alias="TotalShippingPrice") # 运费总价
|
|
43
|
+
total_shipping_tax_price: float = Field(..., alias="TotalShippingTaxPrice") # 运费税费总价
|
|
44
|
+
total_tax_price: float = Field(..., alias="TotalTaxPrice") # 总税费
|
|
45
|
+
vat_inclusive: bool = Field(..., alias="VatInclusive") # 是否含税
|
|
46
|
+
buyer_address: AddressModel = Field(..., alias="BuyerAddress") # 买家地址
|
|
47
|
+
deliver_by_date_utc: datetime = Field(..., alias="DeliverByDateUtc") # 要求送达日期
|
|
48
|
+
other_fees: float = Field(..., alias="OtherFees") # 其他费用
|
|
49
|
+
payment_method: Optional[str] = Field(None, alias="PaymentMethod") # 支付方式
|
|
50
|
+
payment_transaction_id: Optional[str] = Field(None, alias="PaymentTransactionID") # 支付交易号
|
|
51
|
+
private_notes: Optional[str] = Field(None, alias="PrivateNotes") # 私有备注
|
|
52
|
+
shipping_address: AddressModel = Field(..., alias="ShippingAddress") # 收货地址
|
|
53
|
+
shipping_label_url: Optional[str] = Field(None, alias="ShippingLabelURL") # 运单 URL
|
|
54
|
+
special_instructions: Optional[str] = Field(None, alias="SpecialInstructions") # 特殊指示
|
|
55
|
+
total_order_discount: float = Field(..., alias="TotalOrderDiscount") # 订单折扣总额
|
|
56
|
+
total_shipping_discount: float = Field(..., alias="TotalShippingDiscount") # 运费折扣总额
|
|
57
|
+
order_label: str = Field(..., alias="OrderLabel") # 订单标签
|
|
58
|
+
dispatched_items: Optional[list[str]] = Field(None, alias="DispatchedItems") # 已发货商品 ID 列表
|
|
59
|
+
cancelled_items: Optional[list[str]] = Field(None, alias="CancelledItems") # 已取消商品 ID 列表
|
|
60
|
+
customer_date_of_birth: Optional[str] = Field(None, alias="CustomerDateOfBirth") # 客户生日
|
|
61
|
+
web_store: Optional[str] = Field(None, alias="WebStore") # 网店标识
|
|
62
|
+
is_premium_subscription: Optional[bool] = Field(None, alias="IsPremiumSubscription") # 是否高级会员订单
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class OrderResponseModel(BaseModel):
|
|
66
|
+
status: str = Field(..., alias="status") # 响应状态
|
|
67
|
+
error: Optional[str] = Field(None, alias="error") # 错误信息
|
|
68
|
+
pending_url: Optional[str] = Field(None, alias="pending_url") # 挂起处理 URL
|
|
69
|
+
body: list[OrderModel] = Field(..., alias="body") # 订单数据列表
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OfferDetail(BaseModel):
|
|
6
|
+
# 价格
|
|
7
|
+
price: str = Field(..., alias="price")
|
|
8
|
+
# Kogan First 价格
|
|
9
|
+
kogan_first_price: Optional[str] = Field(None, alias="kogan_first_price")
|
|
10
|
+
# 是否免税
|
|
11
|
+
tax_exempt: bool = Field(..., alias="tax_exempt")
|
|
12
|
+
# 运费
|
|
13
|
+
shipping: str = Field(..., alias="shipping")
|
|
14
|
+
# 处理天数
|
|
15
|
+
handling_days: int = Field(..., alias="handling_days")
|
|
16
|
+
# 建议零售价
|
|
17
|
+
rrp: Optional[str] = Field(None, alias="rrp")
|
|
18
|
+
|
|
19
|
+
model_config = ConfigDict(
|
|
20
|
+
populate_by_name=True
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class StoreUrl(BaseModel):
|
|
25
|
+
# 商店链接
|
|
26
|
+
url: str = Field(..., alias="url")
|
|
27
|
+
# 商店名称
|
|
28
|
+
store_name: str = Field(..., alias="store_name")
|
|
29
|
+
# 组织名称
|
|
30
|
+
organisation: str = Field(..., alias="organisation")
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(
|
|
33
|
+
populate_by_name=True
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Product(BaseModel):
|
|
38
|
+
# 产品标题
|
|
39
|
+
product_title: str = Field(..., alias="product_title")
|
|
40
|
+
# 产品SKU
|
|
41
|
+
product_sku: str = Field(..., alias="product_sku")
|
|
42
|
+
# 产品副标题
|
|
43
|
+
product_subtitle: str = Field(..., alias="product_subtitle")
|
|
44
|
+
# 产品 GTIN
|
|
45
|
+
product_gtin: str = Field(..., alias="product_gtin")
|
|
46
|
+
# 图片链接列表
|
|
47
|
+
images: list[str] = Field(..., alias="images")
|
|
48
|
+
# 品牌
|
|
49
|
+
brand: Optional[str] = Field(None, alias="brand")
|
|
50
|
+
# 类别
|
|
51
|
+
category: str = Field(..., alias="category")
|
|
52
|
+
# 类别标识
|
|
53
|
+
category_slug: str = Field(..., alias="category_slug")
|
|
54
|
+
# 报价数据
|
|
55
|
+
offer_data: dict[str, OfferDetail] = Field(..., alias="offer_data")
|
|
56
|
+
# 库存数量
|
|
57
|
+
stock: int = Field(..., alias="stock")
|
|
58
|
+
# 是否启用
|
|
59
|
+
enabled: bool = Field(..., alias="enabled")
|
|
60
|
+
# 创建时间
|
|
61
|
+
created: str = Field(..., alias="created")
|
|
62
|
+
# 商店地址列表
|
|
63
|
+
store_urls: list[StoreUrl] = Field(..., alias="store_urls")
|
|
64
|
+
# 标签
|
|
65
|
+
tags: list[str] = Field(..., alias="tags")
|
|
66
|
+
|
|
67
|
+
model_config = ConfigDict(
|
|
68
|
+
populate_by_name=True
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Body(BaseModel):
|
|
73
|
+
# 下一页链接
|
|
74
|
+
next: Optional[str] = Field(None, alias="next")
|
|
75
|
+
# 产品列表
|
|
76
|
+
results: list[Product] = Field(..., alias="results")
|
|
77
|
+
|
|
78
|
+
model_config = ConfigDict(
|
|
79
|
+
populate_by_name=True
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ProductResponse(BaseModel):
|
|
84
|
+
# 状态
|
|
85
|
+
status: str = Field(..., alias="status")
|
|
86
|
+
# 待处理URL
|
|
87
|
+
pending_url: Optional[str] = Field(None, alias="pending_url")
|
|
88
|
+
# 错误信息
|
|
89
|
+
error: Optional[str] = Field(None, alias="error")
|
|
90
|
+
# 响应主体
|
|
91
|
+
body: Body = Field(..., alias="body")
|
|
92
|
+
|
|
93
|
+
model_config = ConfigDict(
|
|
94
|
+
populate_by_name=True
|
|
95
|
+
)
|
|
96
|
+
|
ey_commerce_lib/model.py
ADDED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ey-commerce-lib
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: eeyoung电商客户端调用封装
|
|
5
5
|
Author-email: 饶奇奇 <1124393197@qq.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: ddddocr>=1.5.6
|
|
7
8
|
Requires-Dist: httpx>=0.28.1
|
|
8
9
|
Requires-Dist: lxml>=5.3.2
|
|
10
|
+
Requires-Dist: playwright>=1.52.0
|
|
9
11
|
Requires-Dist: pydantic>=2.11.3
|
|
10
12
|
Requires-Dist: pytest-asyncio>=0.26.0
|
|
11
13
|
Requires-Dist: pytest>=8.3.5
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
ey_commerce_lib/__init__.py,sha256=QTYqXqSTHFRkM9TEgpDFcHvwLbvqHDqvqfQ9EiXkcAM,23
|
|
2
|
+
ey_commerce_lib/model.py,sha256=uL_xo6Zi2B4t44UB0HALv8On3NIV9cgHay00F_Gkecs,230
|
|
3
|
+
ey_commerce_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
ey_commerce_lib/dxm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
ey_commerce_lib/dxm/main.py,sha256=GeUqUoOV9CMBjMucoIWQNhF-Idi2JSk9J0DF8M-AyJ0,21033
|
|
6
|
+
ey_commerce_lib/dxm/order.py,sha256=hMdNm9X5h9tbvMWFnyE5hcSF4butzn7m-akGqLQUD0k,35
|
|
7
|
+
ey_commerce_lib/dxm/constant/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
ey_commerce_lib/dxm/constant/order.py,sha256=U-2NYnkIcqukzMtOFpfqvzIktu_t7jYEms_n9LgKMlY,2213
|
|
9
|
+
ey_commerce_lib/dxm/exception/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
ey_commerce_lib/dxm/exception/common.py,sha256=DM5vItHdZCGK2Piqp2S5TFxPm3pioMzzlV-1RTxty00,159
|
|
11
|
+
ey_commerce_lib/dxm/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
ey_commerce_lib/dxm/parser/common.py,sha256=-3OwoGsuHpugFS96OAzimZTXLkH7qZqmNvP-kvVSndM,3035
|
|
13
|
+
ey_commerce_lib/dxm/parser/order.py,sha256=tOvMuP_Ld8muL6sBoqGXtgaLPBiBW8Xeu5WSDIhzEXY,16580
|
|
14
|
+
ey_commerce_lib/dxm/parser/purchase.py,sha256=7ULQHAIqUuUcpvWM1ut7uqCQhwE-DcQ7K3qftsfNlK8,5768
|
|
15
|
+
ey_commerce_lib/dxm/parser/warehouse.py,sha256=LfmqVixV5IcnPvr6Ma4XYoWUdXixQ16xzPP07bJrWb0,3192
|
|
16
|
+
ey_commerce_lib/dxm/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
ey_commerce_lib/dxm/schemas/common.py,sha256=ihCeYrh4K_-m9_4rVzHm-o8rFNqzcD5XkO0JQd2023g,234
|
|
18
|
+
ey_commerce_lib/dxm/schemas/order.py,sha256=uzhSgW0d7Z3L1yYb0meZ2AEF1OosnVM408W2-wZVriE,7802
|
|
19
|
+
ey_commerce_lib/dxm/schemas/warehouse.py,sha256=kHxNMgkVHCILfAWuDhLN0Q5pDtb3Nd5qexnJowCSnrI,5082
|
|
20
|
+
ey_commerce_lib/four_seller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
ey_commerce_lib/four_seller/main.py,sha256=Mz_Z0Vs-v0UmegOU_lo8eIpXmrWcL7_paRgBrm1s9_o,13131
|
|
22
|
+
ey_commerce_lib/four_seller/constant/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
ey_commerce_lib/four_seller/constant/response.py,sha256=UqGeRCaAV6B_IyNfJR5oJvbKW4BUF5jQGhU5JYpYP1k,163
|
|
24
|
+
ey_commerce_lib/four_seller/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
ey_commerce_lib/four_seller/parser/order.py,sha256=Od8s86eQmq6LzB4nqOWKgF1jN4p2HeyNpBQNYZQ_Sf4,619
|
|
26
|
+
ey_commerce_lib/four_seller/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
ey_commerce_lib/four_seller/schemas/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
ey_commerce_lib/four_seller/schemas/query/order.py,sha256=XV7by4RT9NWvei4C__cQsLTjMMZKLbK73N1GAU7RL7o,3714
|
|
29
|
+
ey_commerce_lib/four_seller/schemas/vo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
ey_commerce_lib/four_seller/schemas/vo/order.py,sha256=aNpnXSaXeUVbBz_7JtP8p6mWIWgUwejUhtYoa3gf4Po,12133
|
|
31
|
+
ey_commerce_lib/kogan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
ey_commerce_lib/kogan/main.py,sha256=hHW-R3CYwzyFGFO7nzLHhwnFsz06a0hPE2cwdsiwwSM,2025
|
|
33
|
+
ey_commerce_lib/kogan/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
ey_commerce_lib/kogan/schemas/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
ey_commerce_lib/kogan/schemas/query/order.py,sha256=ajqO992fiorUDg3-YPPpK2Dgmdy2LoHfz4IatBz1Mro,574
|
|
36
|
+
ey_commerce_lib/kogan/schemas/query/product.py,sha256=EDKnwTqBTVR7YkXbpHiu90f_3E2nFX6BnhIMkthgucs,2287
|
|
37
|
+
ey_commerce_lib/kogan/schemas/response/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
ey_commerce_lib/kogan/schemas/response/order.py,sha256=3AWXAOTd60y-V-1-VWObf4LmqU4q3tQ8cTREr3_83Is,4716
|
|
39
|
+
ey_commerce_lib/kogan/schemas/response/product.py,sha256=0qnoM4UG-Iugyn1o2M1mgz3wy4_QkP-KA5vMhRuvA7Q,2771
|
|
40
|
+
ey_commerce_lib/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
+
ey_commerce_lib/utils/close.py,sha256=-De_H1I-gryytKYhLMsC3HfW67W852XkP1ckK2gLsFs,141
|
|
42
|
+
ey_commerce_lib/utils/dxm.py,sha256=jVNltK_Pm_yMzXReD0Aw5VW6kzIZ5Bn23RucS0DKBI0,1196
|
|
43
|
+
ey_commerce_lib/utils/list_util.py,sha256=R1w7B1m3sEXr38zSHWp-15C3xAs5ykYCCpvwmnRW4xs,545
|
|
44
|
+
ey_commerce_lib/utils/str.py,sha256=939xE0y8U7KEWjwbEezMlaWJNBsfb2BSb-dBpYbOD8Q,138
|
|
45
|
+
ey_commerce_lib-1.0.8.dist-info/METADATA,sha256=pwSNg0XUKe41gqcoJgdBmvqdZtH4E0BGjE4Ban1CLY4,390
|
|
46
|
+
ey_commerce_lib-1.0.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
47
|
+
ey_commerce_lib-1.0.8.dist-info/RECORD,,
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
ey_commerce_lib/__init__.py,sha256=QTYqXqSTHFRkM9TEgpDFcHvwLbvqHDqvqfQ9EiXkcAM,23
|
|
2
|
-
ey_commerce_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
ey_commerce_lib/dxm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
ey_commerce_lib/dxm/main.py,sha256=GeUqUoOV9CMBjMucoIWQNhF-Idi2JSk9J0DF8M-AyJ0,21033
|
|
5
|
-
ey_commerce_lib/dxm/order.py,sha256=hMdNm9X5h9tbvMWFnyE5hcSF4butzn7m-akGqLQUD0k,35
|
|
6
|
-
ey_commerce_lib/dxm/constant/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
ey_commerce_lib/dxm/constant/order.py,sha256=U-2NYnkIcqukzMtOFpfqvzIktu_t7jYEms_n9LgKMlY,2213
|
|
8
|
-
ey_commerce_lib/dxm/exception/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
ey_commerce_lib/dxm/exception/common.py,sha256=DM5vItHdZCGK2Piqp2S5TFxPm3pioMzzlV-1RTxty00,159
|
|
10
|
-
ey_commerce_lib/dxm/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
ey_commerce_lib/dxm/parser/common.py,sha256=-3OwoGsuHpugFS96OAzimZTXLkH7qZqmNvP-kvVSndM,3035
|
|
12
|
-
ey_commerce_lib/dxm/parser/order.py,sha256=tOvMuP_Ld8muL6sBoqGXtgaLPBiBW8Xeu5WSDIhzEXY,16580
|
|
13
|
-
ey_commerce_lib/dxm/parser/purchase.py,sha256=7ULQHAIqUuUcpvWM1ut7uqCQhwE-DcQ7K3qftsfNlK8,5768
|
|
14
|
-
ey_commerce_lib/dxm/parser/warehouse.py,sha256=LfmqVixV5IcnPvr6Ma4XYoWUdXixQ16xzPP07bJrWb0,3192
|
|
15
|
-
ey_commerce_lib/dxm/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
ey_commerce_lib/dxm/schemas/common.py,sha256=ihCeYrh4K_-m9_4rVzHm-o8rFNqzcD5XkO0JQd2023g,234
|
|
17
|
-
ey_commerce_lib/dxm/schemas/order.py,sha256=uzhSgW0d7Z3L1yYb0meZ2AEF1OosnVM408W2-wZVriE,7802
|
|
18
|
-
ey_commerce_lib/dxm/schemas/warehouse.py,sha256=kHxNMgkVHCILfAWuDhLN0Q5pDtb3Nd5qexnJowCSnrI,5082
|
|
19
|
-
ey_commerce_lib/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
ey_commerce_lib/utils/dxm.py,sha256=jVNltK_Pm_yMzXReD0Aw5VW6kzIZ5Bn23RucS0DKBI0,1196
|
|
21
|
-
ey_commerce_lib/utils/list_util.py,sha256=R1w7B1m3sEXr38zSHWp-15C3xAs5ykYCCpvwmnRW4xs,545
|
|
22
|
-
ey_commerce_lib/utils/str.py,sha256=939xE0y8U7KEWjwbEezMlaWJNBsfb2BSb-dBpYbOD8Q,138
|
|
23
|
-
ey_commerce_lib-1.0.6.dist-info/METADATA,sha256=g-djWVYXp7FIvhyeBL04rw_6qJsX4LYf7tQvt2ovCZ8,326
|
|
24
|
-
ey_commerce_lib-1.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
25
|
-
ey_commerce_lib-1.0.6.dist-info/RECORD,,
|
|
File without changes
|