qrpa 1.1.79__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 qrpa might be problematic. Click here for more details.
- qrpa/RateLimitedSender.py +45 -0
- qrpa/__init__.py +31 -0
- qrpa/db_migrator.py +601 -0
- qrpa/feishu_bot_app.py +607 -0
- qrpa/feishu_client.py +410 -0
- qrpa/feishu_logic.py +1443 -0
- qrpa/fun_base.py +339 -0
- qrpa/fun_excel.py +3470 -0
- qrpa/fun_file.py +319 -0
- qrpa/fun_web.py +473 -0
- qrpa/fun_win.py +198 -0
- qrpa/mysql_module/__init__.py +0 -0
- qrpa/mysql_module/new_product_analysis_model.py +556 -0
- qrpa/mysql_module/shein_ledger_model.py +468 -0
- qrpa/mysql_module/shein_ledger_month_report_model.py +599 -0
- qrpa/mysql_module/shein_product_model.py +495 -0
- qrpa/mysql_module/shein_return_order_model.py +776 -0
- qrpa/mysql_module/shein_store_model.py +595 -0
- qrpa/mysql_module/shein_supplier_info_model.py +554 -0
- qrpa/mysql_module/shein_wallet_model.py +638 -0
- qrpa/shein_daily_report_model.py +375 -0
- qrpa/shein_excel.py +3809 -0
- qrpa/shein_lib.py +5780 -0
- qrpa/shein_mysql.py +106 -0
- qrpa/shein_sqlite.py +154 -0
- qrpa/shein_ziniao.py +531 -0
- qrpa/temu_chrome.py +56 -0
- qrpa/temu_excel.py +139 -0
- qrpa/temu_lib.py +156 -0
- qrpa/time_utils.py +882 -0
- qrpa/time_utils_example.py +243 -0
- qrpa/wxwork.py +318 -0
- qrpa-1.1.79.dist-info/METADATA +9 -0
- qrpa-1.1.79.dist-info/RECORD +36 -0
- qrpa-1.1.79.dist-info/WHEEL +5 -0
- qrpa-1.1.79.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
供应商信息数据模型
|
|
5
|
+
使用SQLAlchemy定义供应商公司信息表和财务信息表
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import create_engine, Column, Integer, String, BigInteger, DateTime, Text, Index
|
|
9
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
10
|
+
from sqlalchemy.orm import sessionmaker
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
# 创建基类
|
|
15
|
+
Base = declarative_base()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SheinSupplierCompany(Base):
|
|
19
|
+
"""
|
|
20
|
+
希音供应商公司信息表
|
|
21
|
+
存储供应商公司信息(来自 /mip-eur-api/supplier/companyInfo/detail 接口)
|
|
22
|
+
"""
|
|
23
|
+
__tablename__ = 'shein_store_company'
|
|
24
|
+
|
|
25
|
+
# 主键ID
|
|
26
|
+
id = Column(BigInteger, primary_key=True, autoincrement=True, comment='主键ID')
|
|
27
|
+
|
|
28
|
+
# 关联店铺账号(唯一)
|
|
29
|
+
store_username = Column(String(100), nullable=False, unique=True, comment='店铺账号')
|
|
30
|
+
|
|
31
|
+
# ==================== 供应商基本信息 ====================
|
|
32
|
+
supplier_id = Column(BigInteger, nullable=True, comment='供应商ID')
|
|
33
|
+
supplier_type = Column(Integer, nullable=True, comment='供应商类型(1-个人,2-公司)')
|
|
34
|
+
supplier_type_title = Column(String(50), nullable=True, comment='供应商类型名称')
|
|
35
|
+
supplier_reg_area = Column(String(20), nullable=True, comment='供应商注册地区')
|
|
36
|
+
|
|
37
|
+
# ==================== 营业执照信息 ====================
|
|
38
|
+
company = Column(String(500), nullable=True, comment='公司名称')
|
|
39
|
+
business_license = Column(BigInteger, nullable=True, comment='营业执照文件ID')
|
|
40
|
+
business_license_name = Column(String(200), nullable=True, comment='营业执照文件名')
|
|
41
|
+
business_license_url = Column(String(1000), nullable=True, comment='营业执照图片URL')
|
|
42
|
+
business_license_type = Column(String(20), nullable=True, comment='营业执照类型')
|
|
43
|
+
business_license_type_title = Column(String(100), nullable=True, comment='营业执照类型名称')
|
|
44
|
+
code_register_no = Column(String(100), nullable=True, comment='统一社会信用代码')
|
|
45
|
+
country_code = Column(String(20), nullable=True, comment='国家代码')
|
|
46
|
+
country_code_title = Column(String(100), nullable=True, comment='国家名称')
|
|
47
|
+
district_id = Column(BigInteger, nullable=True, comment='地区ID')
|
|
48
|
+
district_name = Column(String(200), nullable=True, comment='地区名称')
|
|
49
|
+
business_license_address = Column(String(500), nullable=True, comment='营业执照地址')
|
|
50
|
+
business_license_postal_code = Column(String(20), nullable=True, comment='营业执照邮编')
|
|
51
|
+
set_time = Column(String(20), nullable=True, comment='成立日期')
|
|
52
|
+
|
|
53
|
+
# ==================== 法人信息 ====================
|
|
54
|
+
legal_person_name = Column(String(100), nullable=True, comment='法人姓名')
|
|
55
|
+
legal_person_nationality = Column(String(20), nullable=True, comment='法人国籍代码')
|
|
56
|
+
legal_person_nationality_name = Column(String(100), nullable=True, comment='法人国籍名称')
|
|
57
|
+
legal_person_cert_type = Column(Integer, nullable=True, comment='法人证件类型(1-身份证)')
|
|
58
|
+
legal_person_cert_type_title = Column(String(50), nullable=True, comment='法人证件类型名称')
|
|
59
|
+
legal_person_id_num = Column(String(50), nullable=True, comment='法人证件号码')
|
|
60
|
+
legal_person_id_card_front = Column(BigInteger, nullable=True, comment='法人身份证正面文件ID')
|
|
61
|
+
legal_person_id_card_front_url = Column(String(1000), nullable=True, comment='法人身份证正面图片URL')
|
|
62
|
+
legal_person_id_card_back = Column(BigInteger, nullable=True, comment='法人身份证反面文件ID')
|
|
63
|
+
legal_person_id_card_back_url = Column(String(1000), nullable=True, comment='法人身份证反面图片URL')
|
|
64
|
+
legal_person_birth = Column(String(20), nullable=True, comment='法人出生日期')
|
|
65
|
+
legal_person_telephone = Column(String(50), nullable=True, comment='法人电话')
|
|
66
|
+
legal_person_telephone_area_code = Column(String(20), nullable=True, comment='法人电话区号')
|
|
67
|
+
legal_person_telephone_area_code_title = Column(String(50), nullable=True, comment='法人电话区号名称')
|
|
68
|
+
legal_person_email = Column(String(200), nullable=True, comment='法人邮箱')
|
|
69
|
+
|
|
70
|
+
# 法人银行信息
|
|
71
|
+
legal_person_bank_province = Column(String(20), nullable=True, comment='法人银行省份代码')
|
|
72
|
+
legal_person_bank_province_name = Column(String(100), nullable=True, comment='法人银行省份名称')
|
|
73
|
+
legal_person_bank_city = Column(String(20), nullable=True, comment='法人银行城市代码')
|
|
74
|
+
legal_person_bank_city_name = Column(String(100), nullable=True, comment='法人银行城市名称')
|
|
75
|
+
legal_person_bank_code = Column(String(20), nullable=True, comment='法人银行代码')
|
|
76
|
+
legal_person_bank_name = Column(String(100), nullable=True, comment='法人银行名称')
|
|
77
|
+
legal_person_bank_account = Column(String(50), nullable=True, comment='法人银行账号')
|
|
78
|
+
|
|
79
|
+
# ==================== 实际控制人信息 ====================
|
|
80
|
+
controller_list_json = Column(Text, nullable=True, comment='实际控制人列表(JSON)')
|
|
81
|
+
|
|
82
|
+
# ==================== 合作信息 ====================
|
|
83
|
+
has_worked_cbec = Column(String(10), nullable=True, comment='是否有跨境电商经验(1-是,2-否)')
|
|
84
|
+
has_factory = Column(String(10), nullable=True, comment='是否有工厂(1-是,2-否)')
|
|
85
|
+
cooperation_cross_border_json = Column(Text, nullable=True, comment='合作跨境平台列表(JSON)')
|
|
86
|
+
|
|
87
|
+
# ==================== 变更信息 ====================
|
|
88
|
+
change_count = Column(Integer, nullable=True, comment='变更次数')
|
|
89
|
+
last_change_status = Column(Integer, nullable=True, comment='最后变更状态')
|
|
90
|
+
last_change_status_name = Column(String(50), nullable=True, comment='最后变更状态名称')
|
|
91
|
+
last_apply_no = Column(String(100), nullable=True, comment='最后申请编号')
|
|
92
|
+
last_apply_time = Column(String(50), nullable=True, comment='最后申请时间')
|
|
93
|
+
|
|
94
|
+
# ==================== 管理字段 ====================
|
|
95
|
+
is_deleted = Column(Integer, nullable=True, default=0, comment='软删除标志(0-未删除,1-已删除)')
|
|
96
|
+
remark = Column(String(500), nullable=True, comment='备注')
|
|
97
|
+
|
|
98
|
+
# 时间戳
|
|
99
|
+
created_at = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
|
|
100
|
+
updated_at = Column(DateTime, nullable=True, default=datetime.now, onupdate=datetime.now, comment='更新时间')
|
|
101
|
+
|
|
102
|
+
# 创建索引
|
|
103
|
+
__table_args__ = (
|
|
104
|
+
Index('idx_company_supplier_id', 'supplier_id'),
|
|
105
|
+
Index('idx_company_name', 'company'),
|
|
106
|
+
Index('idx_company_code_register_no', 'code_register_no'),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def __repr__(self):
|
|
110
|
+
return f"<SheinSupplierCompany(id={self.id}, store_username='{self.store_username}', company='{self.company}')>"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class SheinSupplierFinance(Base):
|
|
114
|
+
"""
|
|
115
|
+
希音供应商财务信息表
|
|
116
|
+
存储供应商财务信息(来自 /mip-eur-api/supplier/finance/detail 接口)
|
|
117
|
+
"""
|
|
118
|
+
__tablename__ = 'shein_store_finance'
|
|
119
|
+
|
|
120
|
+
# 主键ID
|
|
121
|
+
id = Column(BigInteger, primary_key=True, autoincrement=True, comment='主键ID')
|
|
122
|
+
|
|
123
|
+
# 关联店铺账号(唯一)
|
|
124
|
+
store_username = Column(String(100), nullable=False, unique=True, comment='店铺账号')
|
|
125
|
+
|
|
126
|
+
# ==================== 供应商基本信息 ====================
|
|
127
|
+
supplier_id = Column(BigInteger, nullable=True, comment='供应商ID')
|
|
128
|
+
category_id = Column(BigInteger, nullable=True, comment='类目ID')
|
|
129
|
+
category_name = Column(String(200), nullable=True, comment='类目名称')
|
|
130
|
+
parent_category_id = Column(BigInteger, nullable=True, comment='父类目ID')
|
|
131
|
+
|
|
132
|
+
# ==================== 结算信息 ====================
|
|
133
|
+
pay_currency_id = Column(Integer, nullable=True, comment='结算币种ID')
|
|
134
|
+
pay_currency_name = Column(String(50), nullable=True, comment='结算币种名称')
|
|
135
|
+
exchange_rate_type = Column(String(10), nullable=True, comment='汇率类型')
|
|
136
|
+
exchange_rate_type_name = Column(String(50), nullable=True, comment='汇率类型名称')
|
|
137
|
+
bank_account_tel = Column(String(50), nullable=True, comment='银行账户联系电话')
|
|
138
|
+
|
|
139
|
+
# ==================== 默认收款账户信息 ====================
|
|
140
|
+
default_account_id = Column(BigInteger, nullable=True, comment='默认账户ID')
|
|
141
|
+
default_account_type = Column(String(10), nullable=True, comment='默认账户类型(1-非对公)')
|
|
142
|
+
default_account_type_name = Column(String(50), nullable=True, comment='默认账户类型名称')
|
|
143
|
+
default_location = Column(String(10), nullable=True, comment='默认账户地区(1-中国大陆)')
|
|
144
|
+
default_location_name = Column(String(100), nullable=True, comment='默认账户地区名称')
|
|
145
|
+
default_province = Column(String(20), nullable=True, comment='默认账户省份代码')
|
|
146
|
+
default_province_name = Column(String(100), nullable=True, comment='默认账户省份名称')
|
|
147
|
+
default_city = Column(String(20), nullable=True, comment='默认账户城市代码')
|
|
148
|
+
default_city_name = Column(String(100), nullable=True, comment='默认账户城市名称')
|
|
149
|
+
default_bank_code = Column(String(20), nullable=True, comment='默认银行代码')
|
|
150
|
+
default_bank_name = Column(String(100), nullable=True, comment='默认银行名称')
|
|
151
|
+
default_branch_code = Column(String(50), nullable=True, comment='默认支行代码')
|
|
152
|
+
default_branch_name = Column(String(200), nullable=True, comment='默认支行名称')
|
|
153
|
+
default_bank_account = Column(String(50), nullable=True, comment='默认银行账号')
|
|
154
|
+
default_bank_account_name = Column(String(100), nullable=True, comment='默认银行账户名')
|
|
155
|
+
default_bank_account_id_num = Column(String(50), nullable=True, comment='默认账户持有人证件号')
|
|
156
|
+
default_bank_card_front = Column(BigInteger, nullable=True, comment='默认银行卡正面文件ID')
|
|
157
|
+
default_bank_card_front_url = Column(String(1000), nullable=True, comment='默认银行卡正面图片URL')
|
|
158
|
+
default_id_card_front = Column(BigInteger, nullable=True, comment='默认账户持有人身份证正面文件ID')
|
|
159
|
+
default_id_card_front_url = Column(String(1000), nullable=True, comment='默认账户持有人身份证正面图片URL')
|
|
160
|
+
default_id_card_back = Column(BigInteger, nullable=True, comment='默认账户持有人身份证反面文件ID')
|
|
161
|
+
default_id_card_back_url = Column(String(1000), nullable=True, comment='默认账户持有人身份证反面图片URL')
|
|
162
|
+
default_account_status = Column(Integer, nullable=True, comment='默认账户状态')
|
|
163
|
+
default_account_status_name = Column(String(50), nullable=True, comment='默认账户状态名称')
|
|
164
|
+
default_valid_status = Column(Integer, nullable=True, comment='默认账户有效状态')
|
|
165
|
+
default_payee_legal_person_rel = Column(String(10), nullable=True, comment='收款人与法人关系')
|
|
166
|
+
default_payee_legal_person_rel_name = Column(String(50), nullable=True, comment='收款人与法人关系名称')
|
|
167
|
+
default_payee_country_code = Column(String(20), nullable=True, comment='收款人国家代码')
|
|
168
|
+
default_payee_born_country_code = Column(String(20), nullable=True, comment='收款人出生国家代码')
|
|
169
|
+
default_payee_born_country_code_title = Column(String(100), nullable=True, comment='收款人出生国家名称')
|
|
170
|
+
|
|
171
|
+
# ==================== 所有账户列表 ====================
|
|
172
|
+
account_list_json = Column(Text, nullable=True, comment='所有银行账户列表(JSON)')
|
|
173
|
+
account_count = Column(Integer, nullable=True, comment='银行账户数量')
|
|
174
|
+
|
|
175
|
+
# ==================== 变更信息 ====================
|
|
176
|
+
change_count = Column(Integer, nullable=True, comment='变更次数')
|
|
177
|
+
last_change_status = Column(Integer, nullable=True, comment='最后变更状态')
|
|
178
|
+
last_change_status_name = Column(String(50), nullable=True, comment='最后变更状态名称')
|
|
179
|
+
last_apply_time = Column(String(50), nullable=True, comment='最后申请时间')
|
|
180
|
+
last_approval_type = Column(String(20), nullable=True, comment='最后审批类型')
|
|
181
|
+
last_approval_id = Column(BigInteger, nullable=True, comment='最后审批ID')
|
|
182
|
+
|
|
183
|
+
# ==================== 管理字段 ====================
|
|
184
|
+
is_deleted = Column(Integer, nullable=True, default=0, comment='软删除标志(0-未删除,1-已删除)')
|
|
185
|
+
remark = Column(String(500), nullable=True, comment='备注')
|
|
186
|
+
|
|
187
|
+
# 时间戳
|
|
188
|
+
created_at = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
|
|
189
|
+
updated_at = Column(DateTime, nullable=True, default=datetime.now, onupdate=datetime.now, comment='更新时间')
|
|
190
|
+
|
|
191
|
+
# 创建索引
|
|
192
|
+
__table_args__ = (
|
|
193
|
+
Index('idx_finance_supplier_id', 'supplier_id'),
|
|
194
|
+
Index('idx_finance_category_id', 'category_id'),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
def __repr__(self):
|
|
198
|
+
return f"<SheinSupplierFinance(id={self.id}, store_username='{self.store_username}', supplier_id={self.supplier_id})>"
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class SheinSupplierCompanyManager:
|
|
202
|
+
"""
|
|
203
|
+
供应商公司信息数据管理器
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
def __init__(self, database_url):
|
|
207
|
+
print(f"连接数据库: {database_url}")
|
|
208
|
+
self.engine = create_engine(database_url, echo=False)
|
|
209
|
+
self.Session = sessionmaker(bind=self.engine)
|
|
210
|
+
|
|
211
|
+
def create_table(self):
|
|
212
|
+
Base.metadata.create_all(self.engine)
|
|
213
|
+
print("供应商公司信息表创建成功")
|
|
214
|
+
|
|
215
|
+
def insert_data(self, data_list):
|
|
216
|
+
session = self.Session()
|
|
217
|
+
try:
|
|
218
|
+
insert_count = 0
|
|
219
|
+
update_count = 0
|
|
220
|
+
|
|
221
|
+
for data in data_list:
|
|
222
|
+
existing = session.query(SheinSupplierCompany).filter(
|
|
223
|
+
SheinSupplierCompany.store_username == data.get('store_username')
|
|
224
|
+
).first()
|
|
225
|
+
|
|
226
|
+
if existing:
|
|
227
|
+
exclude_fields = {'is_deleted'}
|
|
228
|
+
for key, value in data.items():
|
|
229
|
+
if key not in exclude_fields:
|
|
230
|
+
setattr(existing, key, value)
|
|
231
|
+
setattr(existing, 'updated_at', datetime.now())
|
|
232
|
+
update_count += 1
|
|
233
|
+
else:
|
|
234
|
+
new_record = SheinSupplierCompany(**data)
|
|
235
|
+
session.add(new_record)
|
|
236
|
+
insert_count += 1
|
|
237
|
+
|
|
238
|
+
session.commit()
|
|
239
|
+
print(f"公司信息: 成功插入 {insert_count} 条记录,更新 {update_count} 条记录")
|
|
240
|
+
return insert_count
|
|
241
|
+
except Exception as e:
|
|
242
|
+
session.rollback()
|
|
243
|
+
print(f"插入数据失败: {e}")
|
|
244
|
+
raise
|
|
245
|
+
finally:
|
|
246
|
+
session.close()
|
|
247
|
+
|
|
248
|
+
def import_from_api_response(self, store_username, api_response):
|
|
249
|
+
"""
|
|
250
|
+
从API响应导入公司信息
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
store_username (str): 店铺账号
|
|
254
|
+
api_response (dict): /mip-eur-api/supplier/companyInfo/detail 接口返回的info字段
|
|
255
|
+
"""
|
|
256
|
+
condition = api_response.get('condition', {})
|
|
257
|
+
|
|
258
|
+
record = {
|
|
259
|
+
'store_username': store_username,
|
|
260
|
+
'supplier_id': api_response.get('supplierId'),
|
|
261
|
+
'supplier_type': api_response.get('supplierType'),
|
|
262
|
+
'supplier_type_title': api_response.get('supplierTypeTitle'),
|
|
263
|
+
'supplier_reg_area': condition.get('supplierRegArea'),
|
|
264
|
+
|
|
265
|
+
# 营业执照信息
|
|
266
|
+
'company': condition.get('company'),
|
|
267
|
+
'business_license': condition.get('businessLicense'),
|
|
268
|
+
'business_license_name': condition.get('businessLicenseName'),
|
|
269
|
+
'business_license_url': condition.get('businessLicensePathOss', {}).get('url') if condition.get('businessLicensePathOss') else condition.get('businessLicensePath'),
|
|
270
|
+
'business_license_type': condition.get('businessLicenseType'),
|
|
271
|
+
'business_license_type_title': condition.get('businessLicenseTypeTitle'),
|
|
272
|
+
'code_register_no': condition.get('codeRegisterNo'),
|
|
273
|
+
'country_code': condition.get('countryCode'),
|
|
274
|
+
'country_code_title': condition.get('countryCodeTitle'),
|
|
275
|
+
'district_id': condition.get('districtId'),
|
|
276
|
+
'district_name': condition.get('districtName'),
|
|
277
|
+
'business_license_address': condition.get('businessLicenseAddress'),
|
|
278
|
+
'business_license_postal_code': condition.get('businessLicensePostalCode'),
|
|
279
|
+
'set_time': condition.get('setTime'),
|
|
280
|
+
|
|
281
|
+
# 法人信息
|
|
282
|
+
'legal_person_name': condition.get('legalPersonName'),
|
|
283
|
+
'legal_person_nationality': condition.get('legalPersonNationality'),
|
|
284
|
+
'legal_person_nationality_name': condition.get('legalPersonNationalityName'),
|
|
285
|
+
'legal_person_cert_type': condition.get('legalPersonCertType'),
|
|
286
|
+
'legal_person_cert_type_title': condition.get('legalPersonCertTypeTitle'),
|
|
287
|
+
'legal_person_id_num': condition.get('legalPersonIdNum'),
|
|
288
|
+
'legal_person_id_card_front': condition.get('legalPersonIdA'),
|
|
289
|
+
'legal_person_id_card_front_url': condition.get('legalPersonIdAPathOss', {}).get('url') if condition.get('legalPersonIdAPathOss') else condition.get('legalPersonIdAPath'),
|
|
290
|
+
'legal_person_id_card_back': condition.get('legalPersonIdB'),
|
|
291
|
+
'legal_person_id_card_back_url': condition.get('legalPersonIdBPathOss', {}).get('url') if condition.get('legalPersonIdBPathOss') else condition.get('legalPersonIdBPath'),
|
|
292
|
+
'legal_person_birth': condition.get('legalPersonBirth'),
|
|
293
|
+
'legal_person_telephone': condition.get('legalPersonTelephone'),
|
|
294
|
+
'legal_person_telephone_area_code': condition.get('legalPersonTelephoneAreaCode'),
|
|
295
|
+
'legal_person_telephone_area_code_title': condition.get('legalPersonTelephoneAreaCodeTitle'),
|
|
296
|
+
'legal_person_email': condition.get('legalPersonEmail'),
|
|
297
|
+
|
|
298
|
+
# 法人银行信息
|
|
299
|
+
'legal_person_bank_province': condition.get('legalPersonBankProvince'),
|
|
300
|
+
'legal_person_bank_province_name': condition.get('legalPersonBankProvinceName'),
|
|
301
|
+
'legal_person_bank_city': condition.get('legalPersonBankCity'),
|
|
302
|
+
'legal_person_bank_city_name': condition.get('legalPersonBankCityName'),
|
|
303
|
+
'legal_person_bank_code': condition.get('legalPersonBankCode'),
|
|
304
|
+
'legal_person_bank_name': condition.get('legalPersonBankName'),
|
|
305
|
+
'legal_person_bank_account': condition.get('legalPersonBankAccount'),
|
|
306
|
+
|
|
307
|
+
# 实际控制人
|
|
308
|
+
'controller_list_json': json.dumps(condition.get('controllerList', []), ensure_ascii=False) if condition.get('controllerList') else None,
|
|
309
|
+
|
|
310
|
+
# 合作信息
|
|
311
|
+
'has_worked_cbec': condition.get('hasWorkedCbec'),
|
|
312
|
+
'has_factory': condition.get('hasFactory'),
|
|
313
|
+
'cooperation_cross_border_json': json.dumps(condition.get('cooperationCrossCorderSupplier', []), ensure_ascii=False) if condition.get('cooperationCrossCorderSupplier') else None,
|
|
314
|
+
|
|
315
|
+
# 变更信息
|
|
316
|
+
'change_count': condition.get('changeCount'),
|
|
317
|
+
'last_change_status': condition.get('lastChangeStatus'),
|
|
318
|
+
'last_change_status_name': condition.get('lastChangeStatusName'),
|
|
319
|
+
'last_apply_no': condition.get('lastApplyNo'),
|
|
320
|
+
'last_apply_time': condition.get('lastApplyTime'),
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return self.insert_data([record])
|
|
324
|
+
|
|
325
|
+
def get_by_store_username(self, store_username, include_deleted=False):
|
|
326
|
+
session = self.Session()
|
|
327
|
+
try:
|
|
328
|
+
query = session.query(SheinSupplierCompany).filter(
|
|
329
|
+
SheinSupplierCompany.store_username == store_username
|
|
330
|
+
)
|
|
331
|
+
if not include_deleted:
|
|
332
|
+
query = query.filter(SheinSupplierCompany.is_deleted == 0)
|
|
333
|
+
return query.first()
|
|
334
|
+
finally:
|
|
335
|
+
session.close()
|
|
336
|
+
|
|
337
|
+
def get_all(self, include_deleted=False):
|
|
338
|
+
session = self.Session()
|
|
339
|
+
try:
|
|
340
|
+
query = session.query(SheinSupplierCompany)
|
|
341
|
+
if not include_deleted:
|
|
342
|
+
query = query.filter(SheinSupplierCompany.is_deleted == 0)
|
|
343
|
+
return query.all()
|
|
344
|
+
finally:
|
|
345
|
+
session.close()
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
class SheinSupplierFinanceManager:
|
|
349
|
+
"""
|
|
350
|
+
供应商财务信息数据管理器
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
def __init__(self, database_url):
|
|
354
|
+
print(f"连接数据库: {database_url}")
|
|
355
|
+
self.engine = create_engine(database_url, echo=False)
|
|
356
|
+
self.Session = sessionmaker(bind=self.engine)
|
|
357
|
+
|
|
358
|
+
def create_table(self):
|
|
359
|
+
Base.metadata.create_all(self.engine)
|
|
360
|
+
print("供应商财务信息表创建成功")
|
|
361
|
+
|
|
362
|
+
def insert_data(self, data_list):
|
|
363
|
+
session = self.Session()
|
|
364
|
+
try:
|
|
365
|
+
insert_count = 0
|
|
366
|
+
update_count = 0
|
|
367
|
+
|
|
368
|
+
for data in data_list:
|
|
369
|
+
existing = session.query(SheinSupplierFinance).filter(
|
|
370
|
+
SheinSupplierFinance.store_username == data.get('store_username')
|
|
371
|
+
).first()
|
|
372
|
+
|
|
373
|
+
if existing:
|
|
374
|
+
exclude_fields = {'is_deleted'}
|
|
375
|
+
for key, value in data.items():
|
|
376
|
+
if key not in exclude_fields:
|
|
377
|
+
setattr(existing, key, value)
|
|
378
|
+
setattr(existing, 'updated_at', datetime.now())
|
|
379
|
+
update_count += 1
|
|
380
|
+
else:
|
|
381
|
+
new_record = SheinSupplierFinance(**data)
|
|
382
|
+
session.add(new_record)
|
|
383
|
+
insert_count += 1
|
|
384
|
+
|
|
385
|
+
session.commit()
|
|
386
|
+
print(f"财务信息: 成功插入 {insert_count} 条记录,更新 {update_count} 条记录")
|
|
387
|
+
return insert_count
|
|
388
|
+
except Exception as e:
|
|
389
|
+
session.rollback()
|
|
390
|
+
print(f"插入数据失败: {e}")
|
|
391
|
+
raise
|
|
392
|
+
finally:
|
|
393
|
+
session.close()
|
|
394
|
+
|
|
395
|
+
def import_from_api_response(self, store_username, api_response):
|
|
396
|
+
"""
|
|
397
|
+
从API响应导入财务信息
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
store_username (str): 店铺账号
|
|
401
|
+
api_response (dict): /mip-eur-api/supplier/finance/detail 接口返回的info字段
|
|
402
|
+
"""
|
|
403
|
+
account_list = api_response.get('accountList', [])
|
|
404
|
+
|
|
405
|
+
# 找到默认账户
|
|
406
|
+
default_account = None
|
|
407
|
+
for account in account_list:
|
|
408
|
+
if account.get('defaultAccount') == 1:
|
|
409
|
+
default_account = account
|
|
410
|
+
break
|
|
411
|
+
|
|
412
|
+
record = {
|
|
413
|
+
'store_username': store_username,
|
|
414
|
+
'supplier_id': api_response.get('supplierId'),
|
|
415
|
+
'category_id': api_response.get('categoryId'),
|
|
416
|
+
'category_name': api_response.get('categoryName'),
|
|
417
|
+
'parent_category_id': api_response.get('parentCategoryId'),
|
|
418
|
+
|
|
419
|
+
# 结算信息
|
|
420
|
+
'pay_currency_id': api_response.get('payCurrencyId'),
|
|
421
|
+
'pay_currency_name': api_response.get('payCurrencyName'),
|
|
422
|
+
'exchange_rate_type': api_response.get('exchangeRateType'),
|
|
423
|
+
'exchange_rate_type_name': api_response.get('exchangeRateTypeName'),
|
|
424
|
+
'bank_account_tel': api_response.get('bankAccountTel'),
|
|
425
|
+
|
|
426
|
+
# 变更信息
|
|
427
|
+
'change_count': api_response.get('changeCount'),
|
|
428
|
+
'last_change_status': api_response.get('lastChangeStatus'),
|
|
429
|
+
'last_change_status_name': api_response.get('lastChangeStatusName'),
|
|
430
|
+
'last_apply_time': api_response.get('lastApplyTime'),
|
|
431
|
+
'last_approval_type': api_response.get('lastApprovalType'),
|
|
432
|
+
'last_approval_id': api_response.get('lastApprovalId'),
|
|
433
|
+
|
|
434
|
+
# 账户列表
|
|
435
|
+
'account_list_json': json.dumps(account_list, ensure_ascii=False) if account_list else None,
|
|
436
|
+
'account_count': len(account_list),
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
# 默认账户信息
|
|
440
|
+
if default_account:
|
|
441
|
+
# 获取银行卡图片URL (bankAccountFileVo.urlOss.url)
|
|
442
|
+
bank_card_front_url = None
|
|
443
|
+
bank_account_file_vo = default_account.get('bankAccountFileVo')
|
|
444
|
+
if bank_account_file_vo:
|
|
445
|
+
url_oss = bank_account_file_vo.get('urlOss')
|
|
446
|
+
if url_oss:
|
|
447
|
+
bank_card_front_url = url_oss.get('url')
|
|
448
|
+
if not bank_card_front_url:
|
|
449
|
+
bank_card_front_url = bank_account_file_vo.get('url')
|
|
450
|
+
|
|
451
|
+
# 获取身份证正面图片URL (bankAccountIdCardFileVo.urlOss.url)
|
|
452
|
+
id_card_front_url = None
|
|
453
|
+
bank_account_id_card_file_vo = default_account.get('bankAccountIdCardFileVo')
|
|
454
|
+
if bank_account_id_card_file_vo:
|
|
455
|
+
url_oss = bank_account_id_card_file_vo.get('urlOss')
|
|
456
|
+
if url_oss:
|
|
457
|
+
id_card_front_url = url_oss.get('url')
|
|
458
|
+
if not id_card_front_url:
|
|
459
|
+
id_card_front_url = bank_account_id_card_file_vo.get('url')
|
|
460
|
+
|
|
461
|
+
record.update({
|
|
462
|
+
'default_account_id': default_account.get('id'),
|
|
463
|
+
'default_account_type': default_account.get('accountType'),
|
|
464
|
+
'default_account_type_name': default_account.get('accountTypeName'),
|
|
465
|
+
'default_location': default_account.get('location'),
|
|
466
|
+
'default_location_name': default_account.get('locationName'),
|
|
467
|
+
'default_province': default_account.get('province'),
|
|
468
|
+
'default_province_name': default_account.get('provinceName'),
|
|
469
|
+
'default_city': default_account.get('city'),
|
|
470
|
+
'default_city_name': default_account.get('cityName'),
|
|
471
|
+
'default_bank_code': default_account.get('bankCode'),
|
|
472
|
+
'default_bank_name': default_account.get('bankName'),
|
|
473
|
+
'default_branch_code': default_account.get('branchCode'),
|
|
474
|
+
'default_branch_name': default_account.get('branchName'),
|
|
475
|
+
'default_bank_account': default_account.get('bankAccount'),
|
|
476
|
+
'default_bank_account_name': default_account.get('bankAccountName'),
|
|
477
|
+
'default_bank_account_id_num': default_account.get('bankAccountIdNum'),
|
|
478
|
+
# 银行卡正面: bankAccountFileId / bankAccountFileVo.urlOss.url
|
|
479
|
+
'default_bank_card_front': default_account.get('bankAccountFileId'),
|
|
480
|
+
'default_bank_card_front_url': bank_card_front_url,
|
|
481
|
+
# 身份证正面: bankAccountIdCardFileId / bankAccountIdCardFileVo.urlOss.url
|
|
482
|
+
'default_id_card_front': default_account.get('bankAccountIdCardFileId'),
|
|
483
|
+
'default_id_card_front_url': id_card_front_url,
|
|
484
|
+
# 身份证反面: API响应中没有此字段,保留为空
|
|
485
|
+
'default_id_card_back': None,
|
|
486
|
+
'default_id_card_back_url': None,
|
|
487
|
+
'default_account_status': default_account.get('accountStatus'),
|
|
488
|
+
'default_account_status_name': default_account.get('accountStatusName'),
|
|
489
|
+
'default_valid_status': default_account.get('validStatus'),
|
|
490
|
+
'default_payee_legal_person_rel': default_account.get('payeeLegalPersonRel'),
|
|
491
|
+
'default_payee_legal_person_rel_name': default_account.get('payeeLegalPersonRelName'),
|
|
492
|
+
'default_payee_country_code': default_account.get('payeeCountryCode'),
|
|
493
|
+
'default_payee_born_country_code': default_account.get('payeeBornCountryCode'),
|
|
494
|
+
'default_payee_born_country_code_title': default_account.get('payeeBornCountryCodeTitle'),
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
return self.insert_data([record])
|
|
498
|
+
|
|
499
|
+
def get_by_store_username(self, store_username, include_deleted=False):
|
|
500
|
+
session = self.Session()
|
|
501
|
+
try:
|
|
502
|
+
query = session.query(SheinSupplierFinance).filter(
|
|
503
|
+
SheinSupplierFinance.store_username == store_username
|
|
504
|
+
)
|
|
505
|
+
if not include_deleted:
|
|
506
|
+
query = query.filter(SheinSupplierFinance.is_deleted == 0)
|
|
507
|
+
return query.first()
|
|
508
|
+
finally:
|
|
509
|
+
session.close()
|
|
510
|
+
|
|
511
|
+
def get_all(self, include_deleted=False):
|
|
512
|
+
session = self.Session()
|
|
513
|
+
try:
|
|
514
|
+
query = session.query(SheinSupplierFinance)
|
|
515
|
+
if not include_deleted:
|
|
516
|
+
query = query.filter(SheinSupplierFinance.is_deleted == 0)
|
|
517
|
+
return query.all()
|
|
518
|
+
finally:
|
|
519
|
+
session.close()
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
# ==================== 便捷函数 ====================
|
|
523
|
+
|
|
524
|
+
_company_manager = None
|
|
525
|
+
_finance_manager = None
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
def get_company_manager(database_url):
|
|
529
|
+
global _company_manager
|
|
530
|
+
if _company_manager is None:
|
|
531
|
+
_company_manager = SheinSupplierCompanyManager(database_url)
|
|
532
|
+
return _company_manager
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def get_finance_manager(database_url):
|
|
536
|
+
global _finance_manager
|
|
537
|
+
if _finance_manager is None:
|
|
538
|
+
_finance_manager = SheinSupplierFinanceManager(database_url)
|
|
539
|
+
return _finance_manager
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
if __name__ == '__main__':
|
|
543
|
+
# 测试代码
|
|
544
|
+
database_url = "mysql+pymysql://root:123wyk@47.83.212.3:3306/lz"
|
|
545
|
+
|
|
546
|
+
# 创建公司信息表
|
|
547
|
+
company_manager = SheinSupplierCompanyManager(database_url)
|
|
548
|
+
company_manager.create_table()
|
|
549
|
+
|
|
550
|
+
# 创建财务信息表
|
|
551
|
+
finance_manager = SheinSupplierFinanceManager(database_url)
|
|
552
|
+
finance_manager.create_table()
|
|
553
|
+
|
|
554
|
+
print("表创建完成")
|