qrpa 1.0.100__py3-none-any.whl → 1.1.3__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/fun_excel.py CHANGED
@@ -151,6 +151,34 @@ def wrap_column(sheet, columns=None, WrapText=True):
151
151
  log(f'设置[{c}] 换行 {WrapText}')
152
152
  sheet.range(f'{col_name}:{col_name}').api.WrapText = WrapText
153
153
 
154
+ def sort_by_column_excel(sheet, sort_col: str, has_header=True, order="desc"):
155
+ """
156
+ 对整个表格按照某一列排序
157
+
158
+ :param sheet: xlwings 的 sheet 对象
159
+ :param sort_col: 排序依据的列(如 'D')
160
+ :param has_header: 是否有表头(默认 True)
161
+ :param order: 'asc' 升序,'desc' 降序
162
+ """
163
+ # 找到表格的最后一行和列
164
+ last_cell = sheet.used_range.last_cell
165
+ rng = sheet.range((1, 1), (last_cell.row, last_cell.column))
166
+
167
+ # 排序依据列
168
+ col_index = ord(sort_col.upper()) - ord('A') + 1
169
+ key = sheet.range((2 if has_header else 1, col_index)).api
170
+
171
+ # 排序顺序
172
+ order_val = 1 if order == "asc" else 2
173
+
174
+ # 调用 Excel 的 Sort 方法
175
+ rng.api.Sort(
176
+ Key1=key,
177
+ Order1=order_val,
178
+ Orientation=1,
179
+ Header=1 if has_header else 0
180
+ )
181
+
154
182
  def sort_by_column(data, col_index, header_rows=2, reverse=True):
155
183
  if not data or header_rows >= len(data):
156
184
  return data
qrpa/shein_excel.py CHANGED
@@ -15,6 +15,78 @@ class SheinExcel:
15
15
  self.bridge = bridge
16
16
  pass
17
17
 
18
+ def write_product(self):
19
+ erp = self.config.erp_source
20
+ excel_path = create_file_path(self.config.excel_shein_skc_profit)
21
+ cache_file = f'{self.config.auto_dir}/shein/product/product_{TimeUtils.today_date()}.json'
22
+ dict_product = read_dict_from_file(cache_file)
23
+
24
+ skc_header = ['SKC', '商家SKC', 'SKC图片', '近7天利润', '近30天利润']
25
+ skc_excel_data = []
26
+ dict_skc = []
27
+
28
+ summary_excel_data = []
29
+ header = []
30
+ for store_username, excel_data in dict_product.items():
31
+ header = excel_data[0]
32
+ new_data = []
33
+ for row_item in excel_data[1:]:
34
+ supplier_sku = row_item[5]
35
+ row_item[10] = self.bridge.get_sku_cost(supplier_sku, erp)
36
+ new_data.append(row_item)
37
+
38
+ if row_item[2] not in dict_skc:
39
+ dict_skc.append(row_item[2])
40
+ stat_data = []
41
+ stat_data.append(row_item[2])
42
+ stat_data.append(row_item[3])
43
+ stat_data.append(row_item[4])
44
+ stat_data.append('')
45
+ stat_data.append('')
46
+ skc_excel_data.append(stat_data)
47
+
48
+ summary_excel_data += new_data
49
+
50
+ sheet_name = '商品库'
51
+
52
+ batch_excel_operations(excel_path, [
53
+ (sheet_name, 'write', [header] + summary_excel_data),
54
+ (sheet_name, 'format', self.format_product),
55
+ ])
56
+
57
+ sheet_name = 'Sheet1'
58
+ profit_data = [skc_header] + skc_excel_data
59
+ batch_excel_operations(excel_path, [
60
+ (sheet_name, 'write', sort_by_column(profit_data, 4, 1)),
61
+ (sheet_name, 'format', self.format_profit),
62
+ (sheet_name, 'format', sort_by_column_excel, 'E'),
63
+ ])
64
+
65
+ def format_profit(self, sheet):
66
+ beautify_title(sheet)
67
+ add_borders(sheet)
68
+ format_to_money(sheet, ['成本价', '核价', '利润'])
69
+ column_to_right(sheet, ['成本价', '核价', '利润'])
70
+ add_formula_for_column(sheet, '近7天利润', '=SUMIFS(商品库!L:L,商品库!P:P,A2)')
71
+ add_formula_for_column(sheet, '近30天利润', '=SUMIFS(商品库!M:M,商品库!P:P,A2)')
72
+ InsertImageV2(sheet, ['SKC图片'], 'shein', 90)
73
+
74
+ def format_product(self, sheet):
75
+ merge_by_column_v2(sheet, 'SPU', ['店铺信息', '产品信息'])
76
+ merge_by_column_v2(sheet, 'SKC', ['SKC图片', '商家SKC'])
77
+ beautify_title(sheet)
78
+ add_borders(sheet)
79
+ format_to_datetime(sheet, ['时间'])
80
+ format_to_money(sheet, ['成本价', '核价', '利润'])
81
+ column_to_right(sheet, ['成本价', '核价', '利润'])
82
+ autofit_column(sheet, ['产品信息'])
83
+ column_to_left(sheet, ['产品信息', '商家SKU', '商家SKC', '属性集'])
84
+ specify_column_width(sheet, ['店铺信息', '产品信息', '属性集'], 160 / 6)
85
+ specify_column_width(sheet, ['商家SKU', '商家SKC'], 220 / 6)
86
+ add_formula_for_column(sheet, '近7天利润', '=IF(ISNUMBER(K2), H2*(J2-K2),0)')
87
+ add_formula_for_column(sheet, '近30天利润', '=IF(ISNUMBER(K2), I2*(J2-K2),0)')
88
+ InsertImageV2(sheet, ['SKC图片'], 'shein', 150, '商家SKC', 'shein_skc_img')
89
+
18
90
  def write_week_ntb(self):
19
91
  excel_path = create_file_path(self.config.excel_week_report)
20
92
 
qrpa/shein_lib.py CHANGED
@@ -80,11 +80,9 @@ class SheinLib:
80
80
 
81
81
  while retries < MAX_RETRIES:
82
82
  try:
83
-
84
83
  retries += 1
85
84
 
86
85
  while not web_page.locator('//div[contains(text(),"商家后台")]').nth(1).is_visible():
87
-
88
86
  try:
89
87
  current_url = web_page.url
90
88
  current_title = web_page.title()
@@ -170,7 +168,6 @@ class SheinLib:
170
168
  web_page.wait_for_timeout(3000)
171
169
 
172
170
  if 'https://sso.geiwohuo.com/#/home' in web_page.url:
173
-
174
171
  if 'SHEIN全球商家中心' in web_page.title() or '后台首页' in web_page.title() or '商家后台' in web_page.title():
175
172
  log(web_page.title(), '中断循环', self.store_username, self.store_name)
176
173
  web_page.wait_for_timeout(5000)
@@ -354,7 +351,6 @@ class SheinLib:
354
351
  return list_item
355
352
 
356
353
  def get_return_order_list(self, start_date, end_date, only_yesterday=1):
357
-
358
354
  log(f'获取退货列表: {self.store_username} {self.store_name} {start_date} {end_date}')
359
355
 
360
356
  page_num = 1
@@ -865,6 +861,63 @@ class SheinLib:
865
861
  write_dict_to_file(cache_file, info)
866
862
  return info
867
863
 
864
+ def get_product(self):
865
+ excel_data = [
866
+ ['店铺信息', '产品信息', 'SKC', '商家SKC', 'SKC图片', '商家SKU', '属性集', '近7天销量', '近30天销量', '核价', 'ERP成本价', '近7天利润', '近30天利润', '导出时间', 'SPU', 'SKC_FOR_STAT']
867
+ ]
868
+ skc_list = self.get_bak_base_info()
869
+ cache_file = f'{self.config.auto_dir}/shein/sku_price/sku_price_{self.store_username}.json'
870
+ dict_sku = read_dict_from_file(cache_file)
871
+ for skc_item in skc_list:
872
+ categoryName = skc_item['categoryName']
873
+ spu = skc_item['spu']
874
+ skc = skc_item['skc']
875
+ supplierCode = skc_item['supplierCode']
876
+ skc_img = skc_item['picUrl']
877
+ shelfDate = skc_item['shelfDate']
878
+ shelfDays = skc_item['shelfDays']
879
+ shelfStatusName = skc_item['shelfStatus']['name']
880
+ # if shelfStatusName != '已下架':
881
+ # continue
882
+ for sku_item in skc_item['skuList']:
883
+ supplierSku = sku_item['supplierSku']
884
+ attr = sku_item['attr']
885
+ sku = sku_item['skuCode']
886
+ c7dSaleCnt = sku_item['c7dSaleCnt']
887
+ c30dSaleCnt = sku_item['c30dSaleCnt']
888
+ if attr == '合计' or int(c30dSaleCnt) == 0:
889
+ log(f'跳过: {supplierSku},近30天销量: {c30dSaleCnt}')
890
+ continue
891
+
892
+ price = dict_sku[sku]
893
+
894
+ product_info = f'SPU: {spu}\n商品分类: {categoryName}\n上架日期: {shelfDate}\n上架天数: {shelfDays}\n上架状态: {shelfStatusName}'
895
+
896
+ store_info = f'{self.store_username}\n{self.store_name}\n{self.config.shein_store_manager.get(self.store_username)}'
897
+
898
+ row_item = []
899
+ row_item.append(store_info)
900
+ row_item.append(product_info)
901
+ row_item.append(skc)
902
+ row_item.append(supplierCode)
903
+ row_item.append(skc_img)
904
+ row_item.append(supplierSku)
905
+ row_item.append(attr)
906
+ row_item.append(c7dSaleCnt)
907
+ row_item.append(c30dSaleCnt)
908
+ row_item.append(price)
909
+ row_item.append('')
910
+ row_item.append('')
911
+ row_item.append('')
912
+ row_item.append(TimeUtils.current_datetime())
913
+ row_item.append(spu)
914
+ row_item.append(skc)
915
+ excel_data.append(row_item)
916
+
917
+ cache_file = f'{self.config.auto_dir}/shein/product/product_{TimeUtils.today_date()}.json'
918
+ write_dict_to_file_ex(cache_file, {self.store_username: excel_data}, [self.store_username])
919
+ return excel_data
920
+
868
921
  # 存储商品库
869
922
  def store_product_info(self):
870
923
  # todo 商品详情 属性 规格 图片 重量 与 尺寸
qrpa/shein_mysql.py CHANGED
@@ -1,62 +1,62 @@
1
- import json
2
-
3
- from .mysql_module.shein_return_order_model import SheinReturnOrderManager
4
- from .mysql_module.shein_product_model import SheinProductManager
5
- from .fun_base import log
6
-
7
- import os
8
-
9
- class SheinMysql:
10
- def __init__(self, config):
11
- self.config = config
12
-
13
- def upsert_shein_return_order(self, json_file):
14
- log(f'当前使用的数据库: {self.config.db.database_url}')
15
- # 创建管理器实例
16
- manager = SheinReturnOrderManager(self.config.db.database_url)
17
- # 创建数据表
18
- manager.create_tables()
19
- # 读取JSON文件
20
- with open(json_file, 'r', encoding='utf-8') as f:
21
- dict = json.load(f)
22
- for store_username, data_list in dict.items():
23
- manager.upsert_return_order_data(store_username, data_list)
24
-
25
- def upsert_shein_product(self, json_file):
26
- log(f'当前使用的数据库: {self.config.db.database_url}')
27
- # 创建管理器实例
28
- manager = SheinProductManager(self.config.db.database_url)
29
- # 创建数据表
30
- manager.create_tables()
31
- with open(json_file, 'r', encoding='utf-8') as f:
32
- file_list = json.load(f)
33
- for store_username, store_skc_list_file in file_list.items():
34
- with open(store_skc_list_file, 'r', encoding='utf-8') as f:
35
- dict_store_skc_list = json.load(f)
36
- for store_username, data_list in dict_store_skc_list.items():
37
- manager.upsert_product_data(data_list)
38
-
39
- def upsert_shein_product_info(self, json_file):
40
- log(f'当前使用的数据库: {self.config.db.database_url}')
41
- # 创建管理器实例
42
- manager = SheinProductManager(self.config.db.database_url)
43
- # 创建数据表
44
- manager.create_tables()
45
- with open(json_file, 'r', encoding='utf-8') as f:
46
- file_list = json.load(f)
47
- for store_username, store_spu_list in file_list.items():
48
- for spu in store_spu_list:
49
- product_detail_file = f'{self.config.auto_dir}/shein/product_detail/product_detail_{spu}.json'
50
- attribute_file = f'{self.config.auto_dir}/shein/attribute/attribute_template_{spu}.json'
51
- if os.path.exists(product_detail_file):
52
- with open(product_detail_file, 'r', encoding='utf-8') as f:
53
- data_list = json.load(f)
54
- manager.upsert_product_detail(spu, 'product_detail', data_list)
55
- else:
56
- log(f'文件不存在: {product_detail_file}')
57
- if os.path.exists(attribute_file):
58
- with open(attribute_file, 'r', encoding='utf-8') as f:
59
- data_list = json.load(f)
60
- manager.upsert_product_detail(spu, 'attribute_template', data_list)
61
- else:
62
- log(f'文件不存在: {attribute_file}')
1
+ import json
2
+
3
+ from .mysql_module.shein_return_order_model import SheinReturnOrderManager
4
+ from .mysql_module.shein_product_model import SheinProductManager
5
+ from .fun_base import log
6
+
7
+ import os
8
+
9
+ class SheinMysql:
10
+ def __init__(self, config):
11
+ self.config = config
12
+
13
+ def upsert_shein_return_order(self, json_file):
14
+ log(f'当前使用的数据库: {self.config.db.database_url}')
15
+ # 创建管理器实例
16
+ manager = SheinReturnOrderManager(self.config.db.database_url)
17
+ # 创建数据表
18
+ manager.create_tables()
19
+ # 读取JSON文件
20
+ with open(json_file, 'r', encoding='utf-8') as f:
21
+ dict = json.load(f)
22
+ for store_username, data_list in dict.items():
23
+ manager.upsert_return_order_data(store_username, data_list)
24
+
25
+ def upsert_shein_product(self, json_file):
26
+ log(f'当前使用的数据库: {self.config.db.database_url}')
27
+ # 创建管理器实例
28
+ manager = SheinProductManager(self.config.db.database_url)
29
+ # 创建数据表
30
+ manager.create_tables()
31
+ with open(json_file, 'r', encoding='utf-8') as f:
32
+ file_list = json.load(f)
33
+ for store_username, store_skc_list_file in file_list.items():
34
+ with open(store_skc_list_file, 'r', encoding='utf-8') as f:
35
+ dict_store_skc_list = json.load(f)
36
+ for store_username, data_list in dict_store_skc_list.items():
37
+ manager.upsert_product_data(data_list)
38
+
39
+ def upsert_shein_product_info(self, json_file):
40
+ log(f'当前使用的数据库: {self.config.db.database_url}')
41
+ # 创建管理器实例
42
+ manager = SheinProductManager(self.config.db.database_url)
43
+ # 创建数据表
44
+ manager.create_tables()
45
+ with open(json_file, 'r', encoding='utf-8') as f:
46
+ file_list = json.load(f)
47
+ for store_username, store_spu_list in file_list.items():
48
+ for spu in store_spu_list:
49
+ product_detail_file = f'{self.config.auto_dir}/shein/product_detail/product_detail_{spu}.json'
50
+ attribute_file = f'{self.config.auto_dir}/shein/attribute/attribute_template_{spu}.json'
51
+ if os.path.exists(product_detail_file):
52
+ with open(product_detail_file, 'r', encoding='utf-8') as f:
53
+ data_list = json.load(f)
54
+ manager.upsert_product_detail(spu, 'product_detail', data_list)
55
+ else:
56
+ log(f'文件不存在: {product_detail_file}')
57
+ if os.path.exists(attribute_file):
58
+ with open(attribute_file, 'r', encoding='utf-8') as f:
59
+ data_list = json.load(f)
60
+ manager.upsert_product_detail(spu, 'attribute_template', data_list)
61
+ else:
62
+ log(f'文件不存在: {attribute_file}')