qrpa 1.0.23__py3-none-any.whl → 1.0.25__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/shein_excel.py CHANGED
@@ -1,16 +1,1431 @@
1
1
  from .fun_excel import *
2
- from .fun_base import log
2
+ from .fun_base import *
3
3
  from .fun_file import read_dict_from_file, read_dict_from_file_ex, write_dict_to_file, write_dict_to_file_ex, delete_file
4
4
  from .time_utils import TimeUtils
5
5
  from .wxwork import WxWorkBot
6
6
  from .shein_daily_report_model import SheinStoreSalesDetailManager, SheinStoreSalesDetail
7
7
 
8
+ import pandas as pd
9
+ import numpy as np
10
+
8
11
  class SheinExcel:
9
12
 
10
13
  def __init__(self, config):
11
14
  self.config = config
12
15
  pass
13
16
 
17
+ def dealReturn(self, sheet):
18
+ # 遍历可用行
19
+ used_range_row = sheet.range('A1').expand('down')
20
+ last_row = len(used_range_row)
21
+
22
+ col_0 = find_column_by_data(sheet, 1, '实际退货/报废总数')
23
+ if last_row < 3:
24
+ fm = f'=SUM({col_0}3:{col_0}3)'
25
+ else:
26
+ fm = f'=SUM({col_0}3:{col_0}{last_row})'
27
+
28
+ sheet.range(f'{col_0}2').formula = fm
29
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
30
+
31
+ for i, cell in enumerate(used_range_row):
32
+ row = i + 1
33
+ if row < 3:
34
+ continue
35
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
36
+ sheet.range(f'{row}:{row}').font.size = 11
37
+
38
+ used_range_col = sheet.range('A1').expand('right')
39
+ for j, cell in enumerate(used_range_col):
40
+ col = j + 1
41
+ col_name = index_to_column_name(col)
42
+ col_val = sheet.range(f'{col_name}1').value
43
+ if col_val not in ['']:
44
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
45
+
46
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
47
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
48
+
49
+ if '时间' in col_val:
50
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
51
+
52
+ if '月份' == col_val:
53
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
54
+
55
+ # # 设置标题栏字体颜色与背景色
56
+ # sheet.range(f'{col_name}1').color = (252,228,214)
57
+ # sheet.range(f'{col_name}1').font.size = 12
58
+ # sheet.range(f'{col_name}1').font.bold = True
59
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
60
+
61
+ # 所有列水平居中和垂直居中
62
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
63
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
64
+
65
+ # 水平对齐:
66
+ # -4108:居中
67
+ # -4131:左对齐
68
+ # -4152:右对齐
69
+
70
+ # 垂直对齐:
71
+ # -4108:居中
72
+ # -4160:顶部对齐
73
+ # -4107:底部对齐
74
+
75
+ add_borders(sheet)
76
+
77
+ # 获取第一行和第二行
78
+ rows = sheet.range('1:2')
79
+ # 设置字体名称
80
+ rows.font.name = '微软雅黑'
81
+ # 设置字体大小
82
+ rows.font.size = 11
83
+ # 设置字体加粗
84
+ rows.font.bold = True
85
+ # 设置标题栏字体颜色与背景色
86
+ rows.color = (252, 228, 214)
87
+ # 设置行高
88
+ rows.row_height = 30
89
+
90
+ def dealReplenish(self, sheet):
91
+ # 遍历可用行
92
+ used_range_row = sheet.range('A1').expand('down')
93
+ last_row = len(used_range_row)
94
+ # 获取最后一行的索引
95
+ last_col = index_to_column_name(sheet.range('A1').end('right').column)
96
+ # last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
97
+
98
+ col_3 = find_column_by_data(sheet, 1, '总金额')
99
+ if last_row < 3:
100
+ fm = f'=SUM({col_3}3:{col_3}3)'
101
+ else:
102
+ fm = f'=SUM({col_3}3:{col_3}{last_row})'
103
+
104
+ sheet.range(f'{col_3}2').formula = fm
105
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
106
+
107
+ for i, cell in enumerate(used_range_row):
108
+ row = i + 1
109
+ if row < 3:
110
+ continue
111
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
112
+ sheet.range(f'{row}:{row}').font.size = 11
113
+
114
+ used_range_col = sheet.range('A1').expand('right')
115
+ for j, cell in enumerate(used_range_col):
116
+ col = j + 1
117
+ col_name = index_to_column_name(col)
118
+ col_val = sheet.range(f'{col_name}1').value
119
+ if col_val not in ['']:
120
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
121
+
122
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
123
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
124
+
125
+ if '时间' in col_val:
126
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
127
+
128
+ if '月份' == col_val:
129
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
130
+
131
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
132
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
133
+ # 所有列水平居中和垂直居中
134
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
135
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
136
+
137
+ add_borders(sheet)
138
+
139
+ # === 批量字体设置 ===
140
+ if last_row > 3:
141
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
142
+ data_range.api.Font.Name = "Calibri"
143
+ data_range.api.Font.Size = 11
144
+
145
+ # 获取第一行和第二行
146
+ rows = sheet.range('1:2')
147
+ # 设置字体名称
148
+ rows.font.name = '微软雅黑'
149
+ # 设置字体大小
150
+ rows.font.size = 11
151
+ # 设置字体加粗
152
+ rows.font.bold = True
153
+ # 设置标题栏字体颜色与背景色
154
+ rows.color = (252, 228, 214)
155
+ # 设置行高
156
+ rows.row_height = 30
157
+
158
+ def dealSheinStock(self, sheet):
159
+ col_0 = find_column_by_data(sheet, 1, '期末库存数量')
160
+ col_1 = find_column_by_data(sheet, 1, '期末库存金额')
161
+ col_2 = find_column_by_data(sheet, 1, '单价成本')
162
+ col_3 = find_column_by_data(sheet, 1, '希音仓成本总额')
163
+
164
+ col_4 = find_column_by_data(sheet, 1, '期初库存数量')
165
+ col_5 = find_column_by_data(sheet, 1, '期初库存金额')
166
+
167
+ col_6 = find_column_by_data(sheet, 1, '入库数量')
168
+ col_7 = find_column_by_data(sheet, 1, '入库金额')
169
+ col_8 = find_column_by_data(sheet, 1, '出库数量')
170
+ col_9 = find_column_by_data(sheet, 1, '出库金额')
171
+
172
+ col_10 = find_column_by_data(sheet, 1, '出库成本总额')
173
+ col_11 = find_column_by_data(sheet, 1, '出库利润')
174
+ col_12 = find_column_by_data(sheet, 1, '出库利润率')
175
+
176
+ # 遍历可用行
177
+ used_range_row = sheet.range('A1').expand('down')
178
+ last_row = len(used_range_row)
179
+ # # 获取最后一行的索引
180
+ last_col = index_to_column_name(sheet.range('A1').end('right').column)
181
+ # last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
182
+ if last_row > 2:
183
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
184
+ sheet.range(f'{col_0}2').font.color = (225, 0, 0)
185
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
186
+ sheet.range(f'{col_1}2').font.color = (225, 0, 0)
187
+ sheet.range(f'{col_3}2').formula = f'=SUM({col_3}3:{col_3}{last_row})'
188
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
189
+
190
+ sheet.range(f'{col_4}2').formula = f'=SUM({col_4}3:{col_4}{last_row})'
191
+ sheet.range(f'{col_4}2').font.color = (225, 0, 0)
192
+ sheet.range(f'{col_5}2').formula = f'=SUM({col_5}3:{col_5}{last_row})'
193
+ sheet.range(f'{col_5}2').font.color = (225, 0, 0)
194
+
195
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
196
+ sheet.range(f'{col_6}2').font.color = (225, 0, 0)
197
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
198
+ sheet.range(f'{col_7}2').font.color = (225, 0, 0)
199
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
200
+ sheet.range(f'{col_8}2').font.color = (225, 0, 0)
201
+ sheet.range(f'{col_9}2').formula = f'=SUM({col_9}3:{col_9}{last_row})'
202
+ sheet.range(f'{col_9}2').font.color = (225, 0, 0)
203
+
204
+ sheet.range(f'{col_10}2').formula = f'=SUM({col_10}3:{col_10}{last_row})'
205
+ sheet.range(f'{col_10}2').font.color = (225, 0, 0)
206
+
207
+ sheet.range(f'{col_11}2').formula = f'=SUM({col_11}3:{col_11}{last_row})'
208
+ sheet.range(f'{col_11}2').font.color = (225, 0, 0)
209
+
210
+ if last_row > 3:
211
+ # 设置毛利润和毛利润率列公式与格式
212
+ sheet.range(f'{col_3}3').formula = f'={col_0}3*{col_2}3'
213
+ # AutoFill 快速填充到所有行(3 到 last_row)
214
+ sheet.range(f'{col_3}3').api.AutoFill(sheet.range(f'{col_3}3:{col_3}{last_row}').api)
215
+
216
+ sheet.range(f'{col_10}3').formula = f'={col_8}3*{col_2}3'
217
+ sheet.range(f'{col_10}3').api.AutoFill(sheet.range(f'{col_10}3:{col_10}{last_row}').api)
218
+
219
+ sheet.range(f'{col_11}3').formula = f'={col_9}3-{col_10}3'
220
+ sheet.range(f'{col_11}3').api.AutoFill(sheet.range(f'{col_11}3:{col_11}{last_row}').api)
221
+
222
+ sheet.range(f'{col_12}3').number_format = '0.00%'
223
+ sheet.range(f'{col_12}3').formula = f'=IF({col_9}3 > 0,{col_11}3/{col_9}3,0)'
224
+ sheet.range(f'{col_12}3').api.AutoFill(sheet.range(f'{col_12}3:{col_12}{last_row}').api)
225
+
226
+ used_range_col = sheet.range('A1').expand('right')
227
+ for j, cell in enumerate(used_range_col):
228
+ col = j + 1
229
+ col_name = index_to_column_name(col)
230
+ col_val = sheet.range(f'{col_name}1').value
231
+ if col_val not in ['']:
232
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
233
+
234
+ if col_val in ['业务单号']:
235
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
236
+
237
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or ('利润' in col_val and '率' not in col_val):
238
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
239
+
240
+ if '时间' in col_val:
241
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
242
+
243
+ if '月份' == col_val:
244
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
245
+
246
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
247
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
248
+ # 所有列水平居中和垂直居中
249
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
250
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
251
+
252
+ add_borders(sheet)
253
+
254
+ # === 批量字体设置 ===
255
+ if last_row > 3:
256
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
257
+ data_range.api.Font.Name = "Calibri"
258
+ data_range.api.Font.Size = 11
259
+
260
+ set_title_style(sheet)
261
+
262
+ def dealSalesPercentageExcel(self, sheet):
263
+ col_0 = find_column_by_data(sheet, 1, '商家SKU')
264
+ col_1 = find_column_by_data(sheet, 1, '售出数量')
265
+ col_2 = find_column_by_data(sheet, 1, '销量占比')
266
+ col_3 = find_column_by_data(sheet, 1, '售出金额')
267
+ col_4 = find_column_by_data(sheet, 1, '销售额占比')
268
+ col_5 = find_column_by_data(sheet, 1, '利润')
269
+ col_6 = find_column_by_data(sheet, 1, '利润占比')
270
+ col_7 = find_column_by_data(sheet, 1, 'SKU图片')
271
+
272
+ # 遍历可用行
273
+ used_range_row = sheet.range('B1').expand('down')
274
+ last_row = len(used_range_row)
275
+ if last_row > 2:
276
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
277
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
278
+ sheet.range(f'{col_3}2').formula = f'=SUM({col_3}3:{col_3}{last_row})'
279
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
280
+ sheet.range(f'{col_5}2').formula = f'=SUM({col_5}3:{col_5}{last_row})'
281
+ sheet.range(f'{col_5}2').font.color = (255, 0, 0)
282
+ # sheet.range(f'{col_7}1:{col_7}2').merge()
283
+
284
+ for i, cell in enumerate(used_range_row):
285
+ row = i + 1
286
+ if row < 3:
287
+ continue
288
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
289
+ sheet.range(f'{row}:{row}').font.size = 11
290
+
291
+ sheet.range(f'{col_2}{row}').formula = f'={col_1}{row}/{col_1}2'
292
+ sheet.range(f'{col_4}{row}').formula = f'={col_3}{row}/{col_3}2'
293
+ sheet.range(f'{col_6}{row}').formula = f'={col_5}{row}/{col_5}2'
294
+
295
+ used_range_col = sheet.range('A1').expand('right')
296
+ for j, cell in enumerate(used_range_col):
297
+ col = j + 1
298
+ col_name = index_to_column_name(col)
299
+ col_val = sheet.range(f'{col_name}1').value
300
+ if col_val not in ['']:
301
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
302
+
303
+ if col_val in ['占比']:
304
+ sheet.range(f'{col_name}:{col_name}').number_format = '0.00%'
305
+
306
+ if ('价' in col_val or '成本' in col_val or '金额' in col_val or '利润' == col_val):
307
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
308
+
309
+ if '时间' in col_val:
310
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
311
+
312
+ # # 设置标题栏字体颜色与背景色
313
+ # sheet.range(f'{col_name}1').color = (252,228,214)
314
+ # sheet.range(f'{col_name}1').font.size = 12
315
+ # sheet.range(f'{col_name}1').font.bold = True
316
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
317
+
318
+ # 所有列水平居中和垂直居中
319
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
320
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
321
+
322
+ # 水平对齐:
323
+ # -4108:居中
324
+ # -4131:左对齐
325
+ # -4152:右对齐
326
+
327
+ # 垂直对齐:
328
+ # -4108:居中
329
+ # -4160:顶部对齐
330
+ # -4107:底部对齐
331
+
332
+ add_borders(sheet)
333
+
334
+ # 获取第一行和第二行
335
+ rows = sheet.range('1:2')
336
+ # 设置字体名称
337
+ rows.font.name = '微软雅黑'
338
+ # 设置字体大小
339
+ rows.font.size = 11
340
+ # 设置字体加粗
341
+ rows.font.bold = True
342
+ # 设置标题栏字体颜色与背景色
343
+ rows.color = (252, 228, 214)
344
+ # 设置行高
345
+ rows.row_height = 30
346
+
347
+ def dealMonthNoSettleMentExcel(self, sheet):
348
+ col_0 = find_column_by_data(sheet, 1, '数量')
349
+ col_2 = find_column_by_data(sheet, 1, '金额')
350
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
351
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
352
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
353
+ col_8 = find_column_by_data(sheet, 1, '成本总额')
354
+
355
+ # 设置格式
356
+ used_range_col = sheet.range('A1').expand('right')
357
+ for j, cell in enumerate(used_range_col):
358
+ col = j + 1
359
+ col_name = index_to_column_name(col)
360
+ col_val = sheet.range(f'{col_name}1').value
361
+ if col_val not in ['']:
362
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
363
+
364
+ if col_val in ['业务单号']:
365
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
366
+
367
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
368
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
369
+
370
+ if '时间' in col_val:
371
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
372
+
373
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
374
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
375
+ # 所有列水平居中和垂直居中
376
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
377
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
378
+
379
+ # 批量设置公式
380
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
381
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
382
+ if last_row > 2:
383
+ # 第3行公式(填一次)
384
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
385
+ sheet.range(f'{col_8}2').font.color = (255, 0, 0)
386
+ # AutoFill 快速填充到所有行(3 到 last_row)
387
+ sheet.range(f'{col_8}3').formula = f'={col_3}3*{col_0}3'
388
+
389
+ if last_row > 3:
390
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
391
+
392
+ sheet.range(f'{col_4}1').column_width = 0
393
+
394
+ # 批量设置边框
395
+ add_borders(sheet)
396
+
397
+ if last_row > 2:
398
+ # === 批量字体设置 ===
399
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
400
+ data_range.api.Font.Name = "Calibri"
401
+ data_range.api.Font.Size = 11
402
+
403
+ set_title_style(sheet)
404
+
405
+ def dealMonthBackDetailExcel(self, sheet, summary=0):
406
+ col_0 = find_column_by_data(sheet, 1, '数量')
407
+ col_2 = find_column_by_data(sheet, 1, '金额')
408
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
409
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
410
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
411
+ col_8 = find_column_by_data(sheet, 1, '成本总额')
412
+
413
+ # 设置格式
414
+ used_range_col = sheet.range('A1').expand('right')
415
+ for j, cell in enumerate(used_range_col):
416
+ col = j + 1
417
+ col_name = index_to_column_name(col)
418
+ col_val = sheet.range(f'{col_name}1').value
419
+ if col_val not in ['']:
420
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
421
+
422
+ if col_val in ['业务单号']:
423
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
424
+
425
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
426
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
427
+
428
+ if '时间' in col_val:
429
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
430
+
431
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
432
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
433
+ # 所有列水平居中和垂直居中
434
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
435
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
436
+
437
+ # 批量设置公式
438
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
439
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
440
+ if summary == 1:
441
+ if last_row > 1:
442
+ sheet.range(f'{col_8}2').formula = f'={col_3}2*{col_0}2'
443
+ if last_row > 2:
444
+ # AutoFill 快速填充到所有行(3 到 last_row)
445
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
446
+ else:
447
+ if last_row > 2:
448
+ # 合计行设置
449
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
450
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
451
+
452
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
453
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
454
+
455
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
456
+ sheet.range(f'{col_8}2').font.color = (255, 0, 0)
457
+
458
+ # AutoFill 快速填充到所有行(3 到 last_row)
459
+ sheet.range(f'{col_8}3').formula = f'={col_3}3*{col_0}3'
460
+
461
+ if last_row > 3:
462
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
463
+
464
+ set_title_style(sheet)
465
+
466
+ sheet.range(f'{col_4}1').column_width = 0
467
+
468
+ # 批量设置边框
469
+ add_borders(sheet)
470
+
471
+ if last_row > 3:
472
+ # === 批量字体设置 ===
473
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
474
+ data_range.api.Font.Name = "Calibri"
475
+ data_range.api.Font.Size = 11
476
+
477
+ def dealMonthSalesDetailExcel(self, sheet):
478
+ col_0 = find_column_by_data(sheet, 1, '数量')
479
+ col_1 = find_column_by_data(sheet, 1, '利润')
480
+ col_2 = find_column_by_data(sheet, 1, '金额')
481
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
482
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
483
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
484
+ col_6 = find_column_by_data(sheet, 1, '售出数量')
485
+ col_7 = find_column_by_data(sheet, 1, '售出金额')
486
+
487
+ # 设置格式
488
+ used_range_col = sheet.range('A1').expand('right')
489
+ for j, cell in enumerate(used_range_col):
490
+ col = j + 1
491
+ col_name = index_to_column_name(col)
492
+ col_val = sheet.range(f'{col_name}1').value
493
+ if col_val not in ['']:
494
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
495
+
496
+ if col_val in ['业务单号']:
497
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
498
+
499
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
500
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
501
+
502
+ if '时间' in col_val:
503
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
504
+
505
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
506
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
507
+ # 所有列水平居中和垂直居中
508
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
509
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
510
+
511
+ # 批量设置公式
512
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
513
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
514
+ if last_row > 2:
515
+ # 第3行公式(填一次)
516
+ sheet.range(
517
+ f'{col_1}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_2}3-{col_3}3*{col_0}3,0)'
518
+ sheet.range(f'{col_6}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_0}3,0)'
519
+ sheet.range(f'{col_7}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_2}3,0)'
520
+
521
+ if last_row > 3:
522
+ # AutoFill 快速填充到所有行(3 到 last_row)
523
+ sheet.range(f'{col_1}3').api.AutoFill(sheet.range(f'{col_1}3:{col_1}{last_row}').api)
524
+ sheet.range(f'{col_6}3').api.AutoFill(sheet.range(f'{col_6}3:{col_6}{last_row}').api)
525
+ sheet.range(f'{col_7}3').api.AutoFill(sheet.range(f'{col_7}3:{col_7}{last_row}').api)
526
+
527
+ # 合计行设置
528
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
529
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
530
+
531
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
532
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
533
+
534
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
535
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
536
+
537
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
538
+ sheet.range(f'{col_6}2').font.color = (255, 0, 0)
539
+
540
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
541
+ sheet.range(f'{col_7}2').font.color = (255, 0, 0)
542
+
543
+ sheet.range(f'{col_4}1').column_width = 0
544
+
545
+ # 批量设置边框
546
+ add_borders(sheet)
547
+
548
+ if last_row > 3:
549
+ # === 批量字体设置 ===
550
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
551
+ data_range.api.Font.Name = "Calibri"
552
+ data_range.api.Font.Size = 11
553
+ log(f'设置字体: A3:{col_7}{last_row}')
554
+
555
+ # 获取第一行和第二行
556
+ rows = sheet.range('1:2')
557
+ # 设置字体名称
558
+ rows.font.name = '微软雅黑'
559
+ # 设置字体大小
560
+ rows.font.size = 11
561
+ # 设置字体加粗
562
+ rows.font.bold = True
563
+ # 设置标题栏字体颜色与背景色
564
+ rows.color = (252, 228, 214)
565
+ # 设置行高
566
+ rows.row_height = 30
567
+
568
+ def calc_month_sales_percentage(self, month_data):
569
+ df = pd.DataFrame(data=month_data[2:], columns=month_data[:1][0])
570
+
571
+ # 确保 "商家SKU" 是字符串
572
+ df["商家SKU"] = df["商家SKU"].astype(str).str.strip()
573
+
574
+ # 确保 "数量", "金额", "单价成本" 是数值类型
575
+ df["售出数量"] = pd.to_numeric(df["售出数量"], errors="coerce")
576
+ df["售出金额"] = pd.to_numeric(df["售出金额"], errors="coerce")
577
+ df["单价成本"] = pd.to_numeric(df["单价成本"], errors="coerce")
578
+
579
+ # 重新计算利润
580
+ df["利润"] = np.where(
581
+ df["结算类型"] == "收入结算",
582
+ df["售出金额"] - (df["单价成本"] * df["售出数量"]),
583
+ 0
584
+ )
585
+
586
+ # 进行分组统计(求和)
587
+ summary = df.groupby("商家SKU", as_index=False).agg({
588
+ "售出数量": "sum",
589
+ "售出金额": "sum",
590
+ "利润" : "sum",
591
+ "SKU图片" : "first"
592
+ })
593
+
594
+ # 计算总值
595
+ total_quantity = summary["售出数量"].sum()
596
+ total_amount = summary["售出金额"].sum()
597
+ total_profit = summary["利润"].sum()
598
+
599
+ # 计算占比
600
+ summary["销量占比"] = summary["售出数量"] / total_quantity * 100
601
+ summary["销售额占比"] = summary["售出金额"] / total_amount * 100
602
+ summary["利润占比"] = summary["利润"] / total_profit * 100
603
+
604
+ # 确保显示 2 位小数,并加上百分号
605
+ summary["销量占比"] = summary["销量占比"].map(lambda x: f"{x:.2f}%")
606
+ summary["销售额占比"] = summary["销售额占比"].map(lambda x: f"{x:.2f}%")
607
+ summary["利润占比"] = summary["利润占比"].map(lambda x: f"{x:.2f}%")
608
+
609
+ # 重新排序列
610
+ summary = summary[["SKU图片", "商家SKU", "售出数量", "销量占比", "售出金额", "销售额占比", "利润", "利润占比"]]
611
+ summary_list = summary.values.tolist()
612
+
613
+ summary_list.insert(0, ['', '合计', '', '', '', '', '', '']) # 把表头插入到数据列表的第一行
614
+ # 添加标题行(表头)
615
+ header = summary.columns.tolist()
616
+ summary_list.insert(0, header) # 把表头插入到数据列表的第一行
617
+
618
+ return summary_list
619
+
620
+ def dealMonthSalesDetailExcel_old(self, sheet):
621
+ col_0 = find_column_by_data(sheet, 1, '数量')
622
+ col_1 = find_column_by_data(sheet, 1, '利润')
623
+ col_2 = find_column_by_data(sheet, 1, '金额')
624
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
625
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
626
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
627
+ col_6 = find_column_by_data(sheet, 1, '售出数量')
628
+ col_7 = find_column_by_data(sheet, 1, '售出金额')
629
+ # 遍历可用行
630
+ used_range_row = sheet.range('A1').expand('down')
631
+ last_row = len(used_range_row)
632
+ for i, cell in enumerate(used_range_row):
633
+ row = i + 1
634
+ if row < 3:
635
+ continue
636
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
637
+ sheet.range(f'{row}:{row}').font.size = 11
638
+ range0 = f'{col_0}{row}'
639
+ range2 = f'{col_2}{row}'
640
+ range3 = f'{col_3}{row}'
641
+ range5 = f'{col_5}{row}'
642
+ # 设置毛利润和毛利润率列公式与格式
643
+ sheet.range(
644
+ f'{col_1}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range2}-{range3}*{range0},0)'
645
+ sheet.range(f'{col_6}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range0},0)'
646
+ sheet.range(f'{col_7}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range2},0)'
647
+ log(f'处理公式: {row}/{last_row}')
648
+
649
+ if last_row > 2:
650
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
651
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
652
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
653
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
654
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
655
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
656
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
657
+ sheet.range(f'{col_6}2').font.color = (255, 0, 0)
658
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
659
+ sheet.range(f'{col_7}2').font.color = (255, 0, 0)
660
+ sheet.range(f'{col_4}1').column_width = 0
661
+ # # 设置计算模式为自动计算
662
+ # sheet.api.Application.Calculation = -4105 # -4105 代表自动计算模式
663
+ # # 手动触发一次计算
664
+ # sheet.api.Calculate()
665
+
666
+ used_range_col = sheet.range('A1').expand('right')
667
+ for j, cell in enumerate(used_range_col):
668
+ col = j + 1
669
+ col_name = index_to_column_name(col)
670
+ col_val = sheet.range(f'{col_name}1').value
671
+ if col_val not in ['']:
672
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
673
+
674
+ if col_val in ['业务单号']:
675
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
676
+
677
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
678
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
679
+
680
+ if '时间' in col_val:
681
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
682
+
683
+ # # 设置标题栏字体颜色与背景色
684
+ # sheet.range(f'{col_name}1').color = (252,228,214)
685
+ # sheet.range(f'{col_name}1').font.size = 12
686
+ # sheet.range(f'{col_name}1').font.bold = True
687
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
688
+
689
+ # 所有列水平居中和垂直居中
690
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
691
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
692
+
693
+ # 水平对齐:
694
+ # -4108:居中
695
+ # -4131:左对齐
696
+ # -4152:右对齐
697
+
698
+ # 垂直对齐:
699
+ # -4108:居中
700
+ # -4160:顶部对齐
701
+ # -4107:底部对齐
702
+
703
+ add_borders(sheet)
704
+
705
+ # 获取第一行和第二行
706
+ rows = sheet.range('1:2')
707
+ # 设置字体名称
708
+ rows.font.name = '微软雅黑'
709
+ # 设置字体大小
710
+ rows.font.size = 11
711
+ # 设置字体加粗
712
+ rows.font.bold = True
713
+ # 设置标题栏字体颜色与背景色
714
+ rows.color = (252, 228, 214)
715
+ # 设置行高
716
+ rows.row_height = 30
717
+
718
+ def write_month_sales_detail(self, store_username, store_name, ledger_list, shein_stock_list, shein_replenish_list, shein_return_list, shein_back_list, shein_no_settlement_list):
719
+ last_month = TimeUtils.get_last_month()
720
+
721
+ supplierName = ''
722
+
723
+ excel_path_month = str(self.config.excel_shein_finance_month_report).replace('#store_name#', store_name)
724
+
725
+ month_data = [[
726
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '利润', '售出数量', '售出金额', '添加时间',
727
+ '业务单号', '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', 'SKU图片',
728
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']]
729
+ log('len(ledger_list)', len(ledger_list))
730
+ for month_item in ledger_list:
731
+ row_item = []
732
+ supplierName = month_item['supplierName']
733
+ platform_sku = month_item['sku']
734
+ row_item.append(platform_sku)
735
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
736
+ row_item.append(supplier_sku)
737
+ row_item.append(month_item['suffixZh'])
738
+ row_item.append(month_item['quantity'])
739
+ row_item.append(month_item['cost'])
740
+ row_item.append(month_item['amount'])
741
+ row_item.append(month_item['cost_price'])
742
+ row_item.append('')
743
+ row_item.append(
744
+ month_item['quantity'] if month_item['cost_price'] and month_item['settleTypeName'] == '收入结算' else 0)
745
+ row_item.append(
746
+ month_item['amount'] if month_item['cost_price'] and month_item['settleTypeName'] == '收入结算' else 0)
747
+ row_item.append(month_item['addTime'])
748
+ row_item.append(month_item['businessNo'])
749
+ row_item.append(month_item['billNo'])
750
+ row_item.append(month_item['displayChangeTypeName'])
751
+ row_item.append(month_item['settleTypeName'])
752
+ row_item.append(month_item['skc'])
753
+ row_item.append(month_item['supplierCode'])
754
+ row_item.append(month_item['supplierName'])
755
+ row_item.append(month_item['sku_img'])
756
+ month_data.append(row_item)
757
+
758
+ sheet_name = f'{last_month}月销售明细'
759
+
760
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 1, 2, False), ['L'])
761
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
762
+ set_title_style(sheet, 2)
763
+ set_body_style(sheet, 3)
764
+ add_borders(sheet)
765
+ format_to_money(sheet, ['单价', '金额', '利润'])
766
+ format_to_datetime(sheet, ['时间'])
767
+ add_formula_for_column(sheet, '利润', '=IF(AND(ISNUMBER(G3),O3="收入结算"),F3-G3*D3,0)', 3)
768
+ add_formula_for_column(sheet, '售出数量', '=IF(AND(ISNUMBER(G3),O3="收入结算"),D3,0)', 3)
769
+ add_formula_for_column(sheet, '售出金额', '=IF(AND(ISNUMBER(G3),O3="收入结算"),F3,0)', 3)
770
+ add_sum_for_cell(sheet, ['数量', '金额', '利润', '售出数量', '售出金额'])
771
+ column_to_left(sheet, ['平台SKU', '商家SKU', '属性集'])
772
+ column_to_right(sheet, ['单价', '金额', '利润'])
773
+ hidden_columns(sheet, ['SKU图片'])
774
+ close_excel(app, wb)
775
+
776
+ summary_list = self.calc_month_sales_percentage(month_data)
777
+
778
+ sheet_name = f'{last_month}月销售占比'
779
+
780
+ write_data(excel_path_month, sheet_name, sort_by_column(summary_list, 6, 2))
781
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
782
+ set_title_style(sheet, 2)
783
+ set_body_style(sheet, 3)
784
+ add_borders(sheet)
785
+ format_to_money(sheet, ['金额', '利润'])
786
+ format_to_percent(sheet, ['占比'])
787
+ add_sum_for_cell(sheet, ['利润', '售出数量', '售出金额'])
788
+ column_to_left(sheet, ['商家SKU'])
789
+ column_to_right(sheet, ['金额', '利润'])
790
+ InsertImageV2(sheet, ['SKU图片'], 'shein', 90, None, None, True, 3)
791
+ close_excel(app, wb)
792
+
793
+ stock_data = [[
794
+ '月份', 'SKC', '供方货号', '平台SKU', '商家SKU', '属性集', '期初库存数量', '期初库存金额', '入库数量',
795
+ '入库金额', '出库数量', '出库金额', '期末库存数量', '期末库存金额', '单价成本', '出库成本总额',
796
+ '希音仓成本总额', '出库利润', '出库利润率', '供应商名称', '店铺账号', '店铺别名'
797
+ ], [
798
+ '合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''
799
+ ]]
800
+
801
+ for stock_item in shein_stock_list:
802
+ row_item = []
803
+ row_item.append(stock_item['reportDate'])
804
+ row_item.append(stock_item['skc'])
805
+ row_item.append(stock_item['supplierCode'])
806
+ row_item.append(stock_item['skuCode'])
807
+ row_item.append(stock_item['supplierSku'])
808
+ row_item.append(stock_item['suffixZh'])
809
+ row_item.append(stock_item['beginBalanceCnt'])
810
+ row_item.append(stock_item['beginBalanceAmount'])
811
+ row_item.append(stock_item['inCnt'])
812
+ row_item.append(stock_item['inAmount'])
813
+ row_item.append(stock_item['outCnt'])
814
+ row_item.append(stock_item['outAmount'])
815
+ row_item.append(stock_item['endBalanceCnt'])
816
+ row_item.append(stock_item['endBalanceAmount'])
817
+ row_item.append(stock_item['cost_price'])
818
+ row_item.append('')
819
+ row_item.append('')
820
+ row_item.append('')
821
+ row_item.append('')
822
+ row_item.append(stock_item['supplierName'])
823
+ row_item.append(store_username)
824
+ row_item.append(store_name)
825
+ stock_data.append(row_item)
826
+
827
+ sheet_name = f'{last_month}月库存结余'
828
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_库存结余.json', {store_username: stock_data[:1] + stock_data[2:]}, [store_username])
829
+
830
+ write_data(excel_path_month, sheet_name, sort_by_column(stock_data, 11, 2))
831
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
832
+ set_title_style(sheet, 2)
833
+ set_body_style(sheet, 3)
834
+ add_borders(sheet)
835
+ format_to_money(sheet, ['金额', '总额', '成本', '出库利润'])
836
+ column_to_right(sheet, ['金额', '总额', '成本', '出库利润'])
837
+ format_to_percent(sheet, ['利润率'])
838
+ column_to_left(sheet, ['供方货号', '平台SKU', '商家SKU', '属性集'])
839
+ add_sum_for_cell(sheet, ['期初库存数量', '期初库存金额', '入库数量', '入库金额', '出库数量', '出库金额', '期末库存数量', '期末库存金额', '出库成本总额', '希音仓成本总额', '出库利润'])
840
+ add_formula_for_column(sheet, '出库成本总额', '=K3*O3', 3)
841
+ add_formula_for_column(sheet, '希音仓成本总额', '=M3*O3', 3)
842
+ add_formula_for_column(sheet, '出库利润', '=L3-P3', 3)
843
+ add_formula_for_column(sheet, '出库利润率', '=IF(L3 > 0,R3/L3,0)', 3)
844
+ sheet.autofit()
845
+ close_excel(app, wb)
846
+
847
+ replenish_data = [[
848
+ "补扣款单号", "款项类型", "补扣款分类", "对单类型", "关联单据", "单价", "数量", "总金额", "币种", "创建时间",
849
+ "单据状态", "关联报账单", "拒绝原因", "确认/拒绝时间", "操作人", "会计日期", "是否可报账", "申诉单号",
850
+ "公司主体", "出口模式", "备注", "供货商名称", "店铺账号", "店铺别名"
851
+ ], [
852
+ "合计", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
853
+ ]]
854
+
855
+ for replenish_item in shein_replenish_list:
856
+ row_item = []
857
+ row_item.append(replenish_item['replenishNo'])
858
+ row_item.append(replenish_item['replenishTypeName'])
859
+ row_item.append(replenish_item['categoryName'])
860
+ row_item.append(replenish_item['toOrderTypeName'])
861
+ row_item.append(replenish_item['relationNo'])
862
+ row_item.append(replenish_item['unitPrice'])
863
+ row_item.append(replenish_item['quantity'])
864
+ row_item.append(replenish_item['amount'])
865
+ row_item.append(replenish_item['currencyCode'])
866
+ row_item.append(replenish_item['addTime'])
867
+ row_item.append(replenish_item['replenishStatusName'])
868
+ row_item.append(replenish_item['reportOrderNo'])
869
+ row_item.append(replenish_item['refuseReason'])
870
+ row_item.append(replenish_item['decisionTime'])
871
+ row_item.append(replenish_item['operator'])
872
+ row_item.append(replenish_item['accountDate'])
873
+ row_item.append(replenish_item['reportableName'])
874
+ row_item.append(replenish_item['billNo'])
875
+ row_item.append(replenish_item['companyName'])
876
+ row_item.append(replenish_item['exportingModeName'])
877
+ row_item.append(replenish_item['remark'])
878
+ row_item.append(supplierName)
879
+ row_item.append(store_username)
880
+ row_item.append(store_name)
881
+ replenish_data.append(row_item)
882
+
883
+ sheet_name = f'{last_month}月补扣款列表'
884
+
885
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_补扣款列表.json', {store_username: replenish_data[:1] + replenish_data[2:]}, [store_username])
886
+
887
+ write_data(excel_path_month, sheet_name, replenish_data)
888
+
889
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
890
+ set_title_style(sheet, 2)
891
+ set_body_style(sheet, 3)
892
+ add_borders(sheet)
893
+ format_to_money(sheet, ['金额', '单价'])
894
+ column_to_right(sheet, ['金额', '单价'])
895
+ format_to_datetime(sheet, ['时间'])
896
+ add_sum_for_cell(sheet, ['总金额'])
897
+ sheet.autofit()
898
+ close_excel(app, wb)
899
+
900
+ return_data = [[
901
+ "退货单号", "退货计划单号", "处理类型", "发起原因", "说明", "状态", "退货方式", "退货仓库", "商家货号", "SKC",
902
+ "待退货总数", "实际退货/报废总数", "签收时间", "创建时间", "运单号", "退货联系人", "联系人手机号", "退货地址"
903
+ ], [
904
+ "合计", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
905
+ ]]
906
+
907
+ if len(shein_return_list) > 0:
908
+ log(shein_return_list)
909
+ for return_item in shein_return_list:
910
+ row_item = []
911
+ log(return_item)
912
+ row_item.append(return_item['returnOrderNo'])
913
+ row_item.append(return_item['returnPlanNo'])
914
+ row_item.append(return_item['returnOrderTypeName'])
915
+ row_item.append(return_item['returnReasonTypeName'])
916
+ row_item.append(return_item['returnReason'])
917
+ row_item.append(return_item['returnOrderStatusName'])
918
+ row_item.append(return_item['returnWayTypeName'])
919
+ row_item.append(return_item['warehouseName'])
920
+ row_item.append(','.join(return_item['supplierCodeList']))
921
+ row_item.append(','.join(return_item['skcNameList']))
922
+ row_item.append(return_item['waitReturnQuantity'])
923
+ row_item.append(return_item['returnQuantity'])
924
+ row_item.append(return_item['signTime'])
925
+ row_item.append(return_item['addTime'])
926
+ row_item.append(return_item['expressNoList'])
927
+ row_item.append(return_item['sellerContract'])
928
+ row_item.append(return_item['sellerContractPhone'])
929
+ row_item.append(return_item['returnAddress'])
930
+ return_data.append(row_item)
931
+
932
+ sheet_name = f'{last_month}月退货与报废单列表'
933
+
934
+ write_data(excel_path_month, sheet_name, return_data, ['O', 'Q'])
935
+
936
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
937
+ set_title_style(sheet, 2)
938
+ set_body_style(sheet, 3)
939
+ add_borders(sheet)
940
+ format_to_datetime(sheet, ['时间'])
941
+ add_sum_for_cell(sheet, ['实际退货/报废总数'])
942
+ sheet.autofit()
943
+ close_excel(app, wb)
944
+
945
+ ###############################退供#######################################
946
+ month_data = [[
947
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '成本总额', '添加时间', '业务单号',
948
+ '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', '店铺账号', '店铺别名', 'SKU图片',
949
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']]
950
+ log('len(back_list)', len(shein_back_list))
951
+ for month_item in shein_back_list:
952
+ row_item = []
953
+ platform_sku = month_item['sku']
954
+ row_item.append(platform_sku)
955
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
956
+ row_item.append(supplier_sku)
957
+ row_item.append(month_item['suffixZh'])
958
+ row_item.append(month_item['quantity'])
959
+ row_item.append(month_item['cost'])
960
+ row_item.append(month_item['amount'])
961
+ row_item.append(month_item['cost_price'])
962
+ row_item.append('')
963
+ row_item.append(month_item['addTime'])
964
+ row_item.append(month_item['businessNo'])
965
+ row_item.append(month_item['billNo'])
966
+ row_item.append(month_item['displayChangeTypeName'])
967
+ row_item.append(month_item['settleTypeName'])
968
+ row_item.append(month_item['skc'])
969
+ row_item.append(month_item['supplierCode'])
970
+ row_item.append(month_item['supplierName'])
971
+ row_item.append(store_username)
972
+ row_item.append(store_name)
973
+ row_item.append(month_item['sku_img'])
974
+ month_data.append(row_item)
975
+
976
+ sheet_name = f'{last_month}月退供明细'
977
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_退供列表.json', {store_username: month_data[:1] + month_data[2:]}, [store_username])
978
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 2, 2))
979
+
980
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
981
+ set_title_style(sheet, 2)
982
+ set_body_style(sheet, 3)
983
+ add_borders(sheet)
984
+ format_to_money(sheet, ['金额', '单价', '总额'])
985
+ column_to_right(sheet, ['金额', '单价', '总额'])
986
+ format_to_datetime(sheet, ['时间'])
987
+ add_sum_for_cell(sheet, ['数量', '金额', '成本总额'])
988
+ add_formula_for_column(sheet, '成本总额', '=G3*D3', 3)
989
+ hidden_columns(sheet, ['SKU图片'])
990
+ sheet.autofit()
991
+ close_excel(app, wb)
992
+
993
+ ###############################不结算#######################################
994
+ month_data = [[
995
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '成本总额', '添加时间', '业务单号',
996
+ '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', '店铺账号', '店铺别名', 'SKU图片',
997
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''
998
+ ]]
999
+ log('len(shein_no_settlement_list)', len(shein_no_settlement_list))
1000
+ for month_item in shein_no_settlement_list:
1001
+ row_item = []
1002
+ platform_sku = month_item['sku']
1003
+ row_item.append(platform_sku)
1004
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
1005
+ row_item.append(supplier_sku)
1006
+ row_item.append(month_item['suffixZh'])
1007
+ row_item.append(month_item['quantity'])
1008
+ row_item.append(month_item['cost'])
1009
+ row_item.append(month_item['amount'])
1010
+ row_item.append(month_item['cost_price'])
1011
+ row_item.append('')
1012
+ row_item.append(month_item['addTime'])
1013
+ row_item.append(month_item['businessNo'])
1014
+ row_item.append(month_item['billNo'])
1015
+ row_item.append(month_item['displayChangeTypeName'])
1016
+ row_item.append(month_item['settleTypeName'])
1017
+ row_item.append(month_item['skc'])
1018
+ row_item.append(month_item['supplierCode'])
1019
+ row_item.append(month_item['supplierName'])
1020
+ row_item.append(store_username)
1021
+ row_item.append(store_name)
1022
+ row_item.append(month_item['sku_img'])
1023
+ month_data.append(row_item)
1024
+
1025
+ sheet_name = f'{last_month}月不结算明细'
1026
+
1027
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_不结算列表.json', {store_username: month_data[:1] + month_data[2:]}, [store_username])
1028
+
1029
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 2, 2))
1030
+
1031
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
1032
+ set_title_style(sheet, 2)
1033
+ set_body_style(sheet, 3)
1034
+ add_borders(sheet)
1035
+ format_to_money(sheet, ['金额', '单价', '总额'])
1036
+ column_to_right(sheet, ['金额', '单价', '总额'])
1037
+ format_to_datetime(sheet, ['时间'])
1038
+ add_sum_for_cell(sheet, ['数量', '金额', '成本总额'])
1039
+ add_formula_for_column(sheet, '成本总额', '=G3*D3', 3)
1040
+ hidden_columns(sheet, ['SKU图片'])
1041
+ sheet.autofit()
1042
+ close_excel(app, wb)
1043
+
1044
+ sheet_name = f'{last_month}月利润汇总'
1045
+ # 建立利润汇总sheet页
1046
+ write_json_to_excel('excel_json_profit_detail.json', excel_path_month, sheet_name)
1047
+
1048
+ # 填入数据 销售数量
1049
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
1050
+ delete_sheet_if_exists(wb, 'Sheet1')
1051
+ move_sheet_to_position(wb, sheet_name, 1)
1052
+ wb.save()
1053
+ sheet.activate()
1054
+
1055
+ target_month = find_column_by_data(sheet, 2, last_month)
1056
+ sheet.range(f'{target_month}3').value = f"='{last_month}月销售明细'!I2"
1057
+ sheet.range(f'{target_month}4').number_format = f"¥#,##0.00;¥-#,##0.00"
1058
+ sheet.range(f'{target_month}4').value = f"='{last_month}月销售明细'!J2"
1059
+ sheet.range(f'{target_month}5').number_format = f"¥#,##0.00;¥-#,##0.00"
1060
+ sheet.range(f'{target_month}5').value = f"='{last_month}月销售明细'!H2"
1061
+ sheet.range(f'{target_month}6').number_format = f"¥#,##0.00;¥-#,##0.00"
1062
+ # sheet.range(f'{target_month}6').value = f"=-'{last_month}月退货与报废单列表'!L2 * 3"
1063
+ sheet.range(f'{target_month}7').number_format = f"¥#,##0.00;¥-#,##0.00"
1064
+ sheet.range(f'{target_month}7').value = f"=-'{last_month}月补扣款列表'!H2"
1065
+ sheet.range(f'{target_month}8').number_format = f"¥#,##0.00;¥-#,##0.00"
1066
+ sheet.range(f'{target_month}9').number_format = f"¥#,##0.00;¥-#,##0.00"
1067
+ sheet.range(f'{target_month}9').value = f"=SUM({target_month}5:{target_month}8)"
1068
+ sheet.range(f'{target_month}10').number_format = f"¥#,##0.00;¥-#,##0.00"
1069
+ sheet.range(f'{target_month}10').value = f"='{last_month}月库存结余'!J2"
1070
+ sheet.range('A1').value = f'2025年{last_month}月 shein 利润汇总表 {store_name}'
1071
+ sheet.range(f'{target_month}:{target_month}').autofit()
1072
+ wb.save()
1073
+ close_excel(app, wb)
1074
+
1075
+ def write_summary_algorithm_1(self):
1076
+ excel_path = self.config.excel_shein_finance_month_report_summary
1077
+
1078
+ sheet_name = '总表-算法1'
1079
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1080
+ total_data = []
1081
+ header = ['店铺账号', '店铺别名']
1082
+ for mall_id, excel_data in dict_store_manager_shein.items():
1083
+ total_data += [[mall_id, excel_data]]
1084
+
1085
+ log(total_data)
1086
+ filtered_value = [header] + total_data
1087
+ log(filtered_value)
1088
+ filtered_value = add_suffixed_column(filtered_value, '店长', '')
1089
+ filtered_value = add_suffixed_column(filtered_value, '出库金额', '')
1090
+ filtered_value = add_suffixed_column(filtered_value, '出库成本', '')
1091
+ filtered_value = add_suffixed_column(filtered_value, '不结算金额', '')
1092
+ filtered_value = add_suffixed_column(filtered_value, '不结算成本', '')
1093
+ filtered_value = add_suffixed_column(filtered_value, '实际出库金额', '')
1094
+ filtered_value = add_suffixed_column(filtered_value, '实际出库成本', '')
1095
+ filtered_value = add_suffixed_column(filtered_value, '补扣款', '')
1096
+ filtered_value = add_suffixed_column(filtered_value, '线下运费', '')
1097
+ filtered_value = add_suffixed_column(filtered_value, '侵权扣款', '')
1098
+ filtered_value = add_suffixed_column(filtered_value, '希音仓成本总额', '')
1099
+ filtered_value = add_suffixed_column(filtered_value, '毛利', '')
1100
+
1101
+ # 匹配店铺店长
1102
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1103
+ for row in filtered_value:
1104
+ mall_name = row[0]
1105
+ if mall_name == '店铺账号':
1106
+ continue
1107
+ row[2] = dict_store_manager_shein.get(str(mall_name).lower())
1108
+ self.write_to_one(filtered_value, excel_path, sheet_name)
1109
+
1110
+ def write_summary_algorithm_2(self):
1111
+ excel_path = self.config.excel_shein_finance_month_report_summary
1112
+
1113
+ app, wb, sheet = open_excel(excel_path, 2)
1114
+
1115
+ sheet_name = '总表-算法2'
1116
+ # 将目标工作表移动到第一个工作表之前
1117
+ sheet.api.Move(Before=wb.sheets[0].api)
1118
+ wb.save()
1119
+ close_excel(app, wb)
1120
+
1121
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1122
+ total_data = []
1123
+ header = ['店铺账号', '店铺别名']
1124
+ for mall_id, excel_data in dict_store_manager_shein.items():
1125
+ total_data += [[mall_id, excel_data]]
1126
+
1127
+ filtered_value = [header] + total_data
1128
+ filtered_value = add_suffixed_column(filtered_value, '店长', '')
1129
+ filtered_value = add_suffixed_column(filtered_value, '出库金额', '')
1130
+ filtered_value = add_suffixed_column(filtered_value, '出库成本', '')
1131
+ filtered_value = add_suffixed_column(filtered_value, '退供金额', '')
1132
+ filtered_value = add_suffixed_column(filtered_value, '退供成本', '')
1133
+ filtered_value = add_suffixed_column(filtered_value, '实际出库金额', '')
1134
+ filtered_value = add_suffixed_column(filtered_value, '实际出库成本', '')
1135
+ filtered_value = add_suffixed_column(filtered_value, '补扣款', '')
1136
+ filtered_value = add_suffixed_column(filtered_value, '线下运费', '')
1137
+ filtered_value = add_suffixed_column(filtered_value, '侵权扣款', '')
1138
+ filtered_value = add_suffixed_column(filtered_value, '希音仓成本总额', '')
1139
+ filtered_value = add_suffixed_column(filtered_value, '毛利', '')
1140
+
1141
+ # 匹配店铺店长
1142
+ for row in filtered_value:
1143
+ mall_name = row[0]
1144
+ if mall_name == '店铺账号':
1145
+ continue
1146
+ row[2] = dict_store_manager_shein.get(str(mall_name).lower())
1147
+ self.write_to_one(filtered_value, excel_path, sheet_name)
1148
+
1149
+ def sumary_part(self):
1150
+ excel_path = self.config.excel_shein_finance_month_report_summary
1151
+ src_directory = f'{self.config.auto_dir}/shein/cache'
1152
+ for file in os.listdir(src_directory):
1153
+ # 检查是否为文件且符合命名模式
1154
+ if file.startswith(f"sheet_{TimeUtils.get_last_month()}") and file.endswith(".json"):
1155
+ file_path = os.path.join(src_directory, file)
1156
+ filename = os.path.basename(file_path) # 获取 "tool.py"
1157
+ name = os.path.splitext(filename)[0]
1158
+ sheet_name = name.split('_')[2]
1159
+ dict = read_dict_from_file(file_path)
1160
+ total_data = []
1161
+ header = []
1162
+ for mall_id, excel_data in dict.items():
1163
+ header = excel_data[0]
1164
+ if len(excel_data) > 1:
1165
+ total_data += excel_data[1:]
1166
+
1167
+ filtered_value = [header] + total_data
1168
+ self.write_to_one(filtered_value, excel_path, f'{sheet_name}-汇总-{TimeUtils.get_last_month()}月')
1169
+
1170
+ def write_to_one(self, data, excel_path, sheet_name="Sheet1", header_column=None):
1171
+ write_data(excel_path, sheet_name, data)
1172
+ app, wb, sheet = open_excel(excel_path, sheet_name)
1173
+ add_borders(sheet)
1174
+ format_to_money(sheet, ['金额', '成本'])
1175
+ format_to_datetime(sheet, ['时间'])
1176
+ if '库存结余' in sheet_name:
1177
+ format_to_percent(sheet, ['利润率'])
1178
+ format_to_month(sheet, ['月份'])
1179
+ add_formula_for_column(sheet, '出库成本总额', f'=IF(ISNUMBER(O2),K2*O2,0)', 2)
1180
+ add_formula_for_column(sheet, '希音仓成本总额', f'=IF(ISNUMBER(O2),M2*O2,0)', 2)
1181
+ add_formula_for_column(sheet, '出库利润', f'=L2-P2', 2)
1182
+ add_formula_for_column(sheet, '出库利润率', f'=IF(L2 > 0,R2/L2,0)', 2)
1183
+ if '退供列表' in sheet_name:
1184
+ add_formula_for_column(sheet, '成本总额', f'=IF(ISNUMBER(G2),D2*G2,0)', 2)
1185
+ if '不结算列表' in sheet_name:
1186
+ add_formula_for_column(sheet, '成本总额', f'=IF(ISNUMBER(G2),D2*G2,0)', 2)
1187
+ if '总表-算法1' in sheet_name:
1188
+ format_to_money(sheet, ['补扣款', '线下运费', '侵权扣款', '毛利'])
1189
+ add_formula_for_column(sheet, '出库金额',
1190
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!L:L)",
1191
+ 2)
1192
+ add_formula_for_column(sheet, '出库成本',
1193
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!P:P)",
1194
+ 2)
1195
+ add_formula_for_column(sheet, '不结算金额',
1196
+ f"=SUMIF('不结算列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'不结算列表-汇总-{TimeUtils.get_last_month()}月'!F:F)",
1197
+ 2)
1198
+ add_formula_for_column(sheet, '不结算成本',
1199
+ f"=SUMIF('不结算列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'不结算列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1200
+ 2)
1201
+ add_formula_for_column(sheet, '实际出库金额', f"=D2-F2", 2)
1202
+ add_formula_for_column(sheet, '实际出库成本', f"=E2-G2", 2)
1203
+ add_formula_for_column(sheet, '补扣款',
1204
+ f"=SUMIF('补扣款列表-汇总-{TimeUtils.get_last_month()}月'!W:W,'总表-算法1'!A:A,'补扣款列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1205
+ 2)
1206
+ add_formula_for_column(sheet, '希音仓成本总额',
1207
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!Q:Q)",
1208
+ 2)
1209
+ add_formula_for_column(sheet, '毛利', f"=H2-I2-J2-K2-L2", 2)
1210
+ # 全是公式 无法排序
1211
+
1212
+ if '总表-算法2' in sheet_name:
1213
+ format_to_money(sheet, ['补扣款', '线下运费', '侵权扣款', '毛利'])
1214
+ add_formula_for_column(sheet, '出库金额',
1215
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!L:L)",
1216
+ 2)
1217
+ add_formula_for_column(sheet, '出库成本',
1218
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!P:P)",
1219
+ 2)
1220
+ add_formula_for_column(sheet, '退供金额',
1221
+ f"=SUMIF('退供列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'退供列表-汇总-{TimeUtils.get_last_month()}月'!F:F)",
1222
+ 2)
1223
+ add_formula_for_column(sheet, '退供成本',
1224
+ f"=SUMIF('退供列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'退供列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1225
+ 2)
1226
+ add_formula_for_column(sheet, '实际出库金额', f"=D2-F2", 2)
1227
+ add_formula_for_column(sheet, '实际出库成本', f"=E2-G2", 2)
1228
+ add_formula_for_column(sheet, '补扣款',
1229
+ f"=SUMIF('补扣款列表-汇总-{TimeUtils.get_last_month()}月'!W:W,'总表-算法1'!A:A,'补扣款列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1230
+ 2)
1231
+ add_formula_for_column(sheet, '希音仓成本总额',
1232
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!Q:Q)",
1233
+ 2)
1234
+ add_formula_for_column(sheet, '毛利', f"=H2-I2-J2-K2-L2", 2)
1235
+
1236
+ move_sheet_to_position(wb, '总表-算法1', 1)
1237
+ move_sheet_to_position(wb, '总表-算法2', 1)
1238
+
1239
+ set_title_style(sheet, 1)
1240
+ wb.save()
1241
+ close_excel(app, wb)
1242
+
1243
+ def format_funds(self, sheet):
1244
+ beautify_title(sheet)
1245
+ column_to_right(sheet, ['金额', '汇总'])
1246
+ format_to_money(sheet, ['金额', '汇总'])
1247
+ add_sum_for_cell(sheet, ['在途商品金额', '在仓商品金额', '待结算金额', '可提现金额', '销售出库金额', '汇总'])
1248
+ add_formula_for_column(sheet, '汇总', '=SUM(D3:G3)', 3)
1249
+ sheet.autofit()
1250
+
1251
+ def format_bad_comment(self, sheet):
1252
+ beautify_title(sheet)
1253
+ column_to_left(sheet, ['商品信息'])
1254
+ autofit_column(sheet, ['买家评价', '时间信息', '标签关键词'])
1255
+ specify_column_width(sheet, ['买家评价', '商品信息'], 150 / 6)
1256
+ color_for_column(sheet, ['买家评分'], '红色')
1257
+ colorize_by_field(sheet, 'skc')
1258
+ add_borders(sheet)
1259
+ InsertImageV2(sheet, ['商品图片', '图1', '图2', '图3', '图4', '图5'])
1260
+
1261
+ def write_bad_comment(self):
1262
+ excel_path = create_file_path(self.config.excel_bad_comment)
1263
+ header = ['评价ID', '商品图片', '商品信息', '买家评分', '买家评价', '标签关键词', '区域', '时间信息', '有图', '图1',
1264
+ '图2', '图3', '图4', '图5', 'skc']
1265
+ summary_excel_data = [header]
1266
+
1267
+ cache_file = f'{self.config.auto_dir}/shein/dict/comment_list_{TimeUtils.today_date()}.json'
1268
+ dict = read_dict_from_file(cache_file)
1269
+ dict_store = read_dict_from_file(self.config.shein_store_alias)
1270
+
1271
+ for store_username, comment_list in dict.items():
1272
+ store_name = dict_store.get(store_username)
1273
+ sheet_name = store_name
1274
+
1275
+ store_excel_data = [header]
1276
+ for comment in comment_list:
1277
+ row_item = []
1278
+ row_item.append(comment['commentId'])
1279
+ row_item.append(comment['goodsThumb'])
1280
+ product_info = f'属性:{comment["goodsAttribute"]}\n货号:{comment["goodSn"]}\nSPU:{comment["spu"]}\nSKC:{comment["skc"]}\nSKU:{comment["sku"]}'
1281
+ row_item.append(product_info)
1282
+ row_item.append(calculate_star_symbols(comment['goodsCommentStar']))
1283
+ row_item.append(comment['goodsCommentContent'])
1284
+ qualityLabel = '存在质量问题\n' if comment['isQualityLabel'] == 1 else ''
1285
+ bad_comment_label = qualityLabel + '\n'.join([item['labelName'] for item in comment['badCommentLabelList']])
1286
+
1287
+ row_item.append(bad_comment_label)
1288
+ row_item.append(comment['dataCenterName'])
1289
+ time_info = f'下单时间:{comment["orderTime"]}\n评论时间:{comment["commentTime"]}'
1290
+ row_item.append(time_info)
1291
+
1292
+ # 获取图片数量
1293
+ image_num = len(comment.get('goodsCommentImages', []))
1294
+ # 设置imgFlag值(如果comment中没有imgFlag字段,默认设为0)
1295
+ imgFlag = image_num if comment.get('imgFlag') == 1 else 0
1296
+ row_item.append(imgFlag)
1297
+
1298
+ images = comment.get('goodsCommentImages', [])
1299
+ for i in range(5):
1300
+ row_item.append(images[i] if i < len(images) else '')
1301
+
1302
+ row_item.append(comment['skc'])
1303
+
1304
+ store_excel_data.append(row_item)
1305
+ summary_excel_data.append(row_item)
1306
+
1307
+ # write_data(excel_path, sheet_name, store_excel_data)
1308
+ # format_bad_comment(excel_path, sheet_name)
1309
+
1310
+ sheet_name = 'Sheet1'
1311
+
1312
+ batch_excel_operations(excel_path, [
1313
+ (sheet_name, 'write', summary_excel_data),
1314
+ (sheet_name, 'format', self.format_bad_comment),
1315
+ ])
1316
+
1317
+ def write_funds(self):
1318
+ cache_file = f'{self.config.auto_dir}/shein/cache/stat_fund_{TimeUtils.today_date()}.json'
1319
+ dict = read_dict_from_file(cache_file)
1320
+ data = []
1321
+ for key, val in dict.items():
1322
+ data.append(val)
1323
+
1324
+ excel_path = create_file_path(self.config.excel_shein_fund)
1325
+ sheet_name = 'Sheet1'
1326
+ data.insert(0, ['汇总', '', '', '', '', '', '', '', '', ''])
1327
+ data.insert(0, ['店铺名称', '店铺账号', '店长', '在途商品金额', '在仓商品金额', '待结算金额', '可提现金额',
1328
+ '销售出库金额', '汇总', '导出时间'])
1329
+ batch_excel_operations(excel_path, [
1330
+ ('Sheet1', 'write', sort_by_column(data, 7, 2)),
1331
+ ('Sheet1', 'format', self.format_funds),
1332
+ ])
1333
+ WxWorkBot('b30aaa8d-1a1f-4378-841a-8b0f8295f2d9').send_file(excel_path)
1334
+
1335
+ def format_skc_quality(self, sheet):
1336
+ beautify_title(sheet)
1337
+ colorize_by_field(sheet, 'skc')
1338
+ add_borders(sheet)
1339
+ InsertImageV2(sheet, ['商品图片'])
1340
+
1341
+ def sort_site_desc_by_sale_cnt_14d(self, data, reverse=True):
1342
+ """
1343
+ 对data中的site_desc_vo_list按照skc_site_sale_cnt_14d进行排序
1344
+
1345
+ 参数:
1346
+ data: 包含site_desc_vo_list的字典
1347
+ reverse: 是否倒序排序,默认为True(从大到小)
1348
+
1349
+ 返回:
1350
+ 排序后的data(原数据会被修改)
1351
+ """
1352
+ if 'site_desc_vo_list' in data and isinstance(data['site_desc_vo_list'], list):
1353
+ # 处理None值,将它们放在排序结果的最后
1354
+ data['site_desc_vo_list'].sort(
1355
+ key=lambda x: float('-inf') if x.get('skc_site_sale_cnt_14d') is None else x['skc_site_sale_cnt_14d'],
1356
+ reverse=reverse
1357
+ )
1358
+ return data
1359
+
1360
+ def write_skc_quality_estimate(self):
1361
+ excel_path = create_file_path(self.config.excel_skc_quality_estimate)
1362
+ header = ['店铺信息', '商品图片', '统计日期', '国家', '当日销量', '14日销量', '14日销量占比', '质量等级',
1363
+ '客评数/客评分', '差评数/差评率', '退货数/退货率', 'skc', 'skc当日销量', 'skc14日销量', 'skc14日销量占比']
1364
+ summary_excel_data = [header]
1365
+
1366
+ stat_date = TimeUtils.before_yesterday()
1367
+ cache_file = f'{self.config.auto_dir}/shein/dict/googs_estimate_{stat_date}.json'
1368
+ dict = read_dict_from_file(cache_file)
1369
+ if len(dict) == 0:
1370
+ log('昨日质量评估数据不存在')
1371
+ return
1372
+
1373
+ dict_store = read_dict_from_file(self.config.shein_store_alias)
1374
+
1375
+ operations = []
1376
+ for store_username, skc_list in dict.items():
1377
+ store_name = dict_store.get(store_username)
1378
+ sheet_name = store_name
1379
+
1380
+ store_excel_data = [header]
1381
+ for skc_item in skc_list:
1382
+ sorted_skc_item = self.sort_site_desc_by_sale_cnt_14d(skc_item, True)
1383
+ # for site in sorted_skc_item['site_desc_vo_list']:
1384
+ # print(f"{site['country_site']}: {site['skc_site_sale_cnt_14d']}")
1385
+ # continue
1386
+ store_info = f'{store_name}'
1387
+ skc = sorted_skc_item['skc']
1388
+ sites = sorted_skc_item['site_desc_vo_list']
1389
+ skc_sale_cnt = sorted_skc_item['skc_sale_cnt']
1390
+ skc_sale_cnt_14d = sorted_skc_item['skc_sale_cnt_14d']
1391
+ skc_sale_rate_14d = sorted_skc_item['skc_sale_rate_14d']
1392
+ for site in sites:
1393
+ row_item = []
1394
+ row_item.append(store_info)
1395
+ row_item.append(skc_item['goods_image'])
1396
+ row_item.append(stat_date)
1397
+ row_item.append(site['country_site'])
1398
+ row_item.append(site['skc_site_sale_cnt'])
1399
+ cnt_14d = site['skc_site_sale_cnt_14d']
1400
+ if cnt_14d is None or cnt_14d <= 0:
1401
+ continue
1402
+ row_item.append(cnt_14d)
1403
+ row_item.append(site['skc_site_sale_rate_14d'])
1404
+ row_item.append(site['quality_level'])
1405
+ customer_info = f'{site["customer_evaluate_num"]}/{site["customer_evaluate_score"][:-1]}'
1406
+ row_item.append(customer_info)
1407
+ negative_info = f'{site["negative_quantity"]}/{site["negative_percent"]}'
1408
+ row_item.append(negative_info)
1409
+ return_info = f'{site["goods_return_quantity"]}/{site["goods_return_percent"]}'
1410
+ row_item.append(return_info)
1411
+ row_item.append(skc)
1412
+ row_item.append(skc_sale_cnt)
1413
+ row_item.append(skc_sale_cnt_14d)
1414
+ row_item.append(skc_sale_rate_14d)
1415
+ store_excel_data.append(row_item)
1416
+ summary_excel_data.append(row_item)
1417
+
1418
+ operations.append((
1419
+ sheet_name, 'write', store_excel_data
1420
+ ))
1421
+ operations.append((
1422
+ sheet_name, 'format', self.format_skc_quality
1423
+ ))
1424
+ operations.append((
1425
+ 'Sheet1', 'delete'
1426
+ ))
1427
+ batch_excel_operations(excel_path, operations)
1428
+
14
1429
  def write_sales_data(self):
15
1430
  yesterday = TimeUtils.get_yesterday()
16
1431
  model = SheinStoreSalesDetailManager(self.config.database_url)
@@ -333,9 +1748,9 @@ class SheinExcel:
333
1748
  add_formula_for_column(sheet, '本地和采购可售天数', '=IF(H2>0, (F2+G2)/H2,0)')
334
1749
  add_formula_for_column(sheet, '建议采购', '=IF(I2 > J2,0,E2)')
335
1750
 
336
- colorize_by_field(app, wb, sheet, 'SKC')
1751
+ colorize_by_field(sheet, 'SKC')
337
1752
  specify_column_width(sheet, ['商品信息'], 180 / 6)
338
- InsertImageV2(app, wb, sheet, ['SKC图片', 'SKU图片'])
1753
+ InsertImageV2(sheet, ['SKC图片', 'SKU图片'])
339
1754
  wb.save()
340
1755
  close_excel(app, wb)
341
1756
  if mode == 4:
@@ -372,11 +1787,11 @@ class SheinExcel:
372
1787
  new_excel_path_list.append(new_excel_path)
373
1788
  sheet_name = 'Sheet1'
374
1789
 
375
- log(new_excel_path)
376
- if mode in [2]:
377
- excel_data = sort_by_column(excel_data, 4, 1)
378
- write_data(new_excel_path, sheet_name, excel_data)
379
- self.format_bak_advice(new_excel_path, sheet_name, mode)
1790
+ log(new_excel_path)
1791
+ if mode in [2]:
1792
+ excel_data = sort_by_column(excel_data, 4, 1)
1793
+ write_data(new_excel_path, sheet_name, excel_data)
1794
+ self.format_bak_advice(new_excel_path, sheet_name, mode)
380
1795
 
381
1796
  # 是否合并表格数据
382
1797
  if mode in [1, 3]:
@@ -411,7 +1826,7 @@ class SheinExcel:
411
1826
  beautify_title(sheet)
412
1827
  add_borders(sheet)
413
1828
  column_to_left(sheet, ['活动信息'])
414
- colorize_by_field(app, wb, sheet, '店铺名称')
1829
+ colorize_by_field(sheet, '店铺名称')
415
1830
  autofit_column(sheet, ['店铺名称', '活动信息'])
416
1831
  wb.save()
417
1832
  close_excel(app, wb)
@@ -462,11 +1877,11 @@ class SheinExcel:
462
1877
  app, wb, sheet = open_excel(excel_path, sheet_name)
463
1878
  beautify_title(sheet)
464
1879
  add_borders(sheet)
465
- colorize_by_field(app, wb, sheet, 'SKC')
1880
+ colorize_by_field(sheet, 'SKC')
466
1881
  column_to_left(sheet, ["商品信息", "近7天SKU销量/SKC销量/SKC曝光", "SKC点击率/SKC转化率", "自主参与活动"])
467
1882
  autofit_column(sheet,
468
1883
  ['店铺名称', '商品信息', "近7天SKU销量/SKC销量/SKC曝光", "SKC点击率/SKC转化率", "自主参与活动"])
469
- InsertImageV2(app, wb, sheet, ['SKC图片', 'SKU图片'])
1884
+ InsertImageV2(sheet, ['SKC图片', 'SKU图片'])
470
1885
  wb.save()
471
1886
  close_excel(app, wb)
472
1887
  WxWorkBot('b30aaa8d-1a1f-4378-841a-8b0f8295f2d9').send_file(excel_path)
@@ -498,12 +1913,12 @@ class SheinExcel:
498
1913
  format_to_money(sheet, ['申报价', '成本价', '毛利润', '利润'])
499
1914
  format_to_percent(sheet, ['支付率', '点击率', '毛利率'])
500
1915
  self.dealFormula(sheet) # 有空再封装优化
501
- colorize_by_field(app, wb, sheet, 'SPU')
1916
+ colorize_by_field(sheet, 'SPU')
502
1917
  autofit_column(sheet, ['商品信息', '店铺名称', 'SKC点击率/SKC转化率', '自主参与活动'])
503
1918
  column_to_left(sheet, ['店铺名称', 'SKC点击率/SKC转化率', '自主参与活动'])
504
1919
  specify_column_width(sheet, ['商品标题'], 150 / 6)
505
1920
  add_borders(sheet)
506
- InsertImageV2(app, wb, sheet, ['SKC图片', 'SKU图片'], 'shein', 120, None, None, True)
1921
+ InsertImageV2(sheet, ['SKC图片', 'SKU图片'], 'shein', 120, None, None, True)
507
1922
  wb.save()
508
1923
  close_excel(app, wb)
509
1924