Gabriel00A commited on
Commit
2b0fa1b
·
verified ·
1 Parent(s): 795f7ca

Update process_report.py

Browse files
Files changed (1) hide show
  1. process_report.py +59 -56
process_report.py CHANGED
@@ -13,7 +13,6 @@ import json
13
  import base64
14
  from io import BytesIO
15
  from typing import Optional, Tuple, List
16
-
17
  from datetime import datetime, date
18
 
19
  import pandas as pd
@@ -55,6 +54,14 @@ EMAIL_COLS_DEFAULT = [
55
  "主数量","需求日期","供应商","到货日期","到货主数量","入库日期","入库主数量","目前进度"
56
  ]
57
 
 
 
 
 
 
 
 
 
58
  # ====== 工具函数 ======
59
  def _today() -> date:
60
  return datetime.now().date()
@@ -139,18 +146,30 @@ def aggregate_for_email(df: pd.DataFrame) -> pd.DataFrame:
139
  grouped = df.groupby(group_keys, dropna=False).agg(final_agg_map).reset_index()
140
  grouped["目前进度"] = grouped.apply(_calc_progress_row, axis=1)
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  if "计划到货日期" in grouped.columns:
143
  grouped = grouped.drop(columns=["计划到货日期"])
144
 
145
  final_cols = [col for col in EMAIL_COLS_DEFAULT if col in grouped.columns]
146
  final = grouped[final_cols]
147
 
148
- # --- 唯一的修改在此处 ---
149
- # 将日期格式化为 yyyy-mm-dd 标准格式
150
  date_cols_to_format = ["请购日期", "需求日期", "到货日期", "入库日期"]
151
  for col in date_cols_to_format:
152
  if col in final.columns:
153
- final[col] = pd.to_datetime(final[col], errors='coerce').dt.strftime('%Y-%m-%d') # 已更新为 yyyy-mm-dd 格式
154
 
155
  return final
156
 
@@ -199,9 +218,40 @@ def _find_latest_input(input_dir: str) -> Optional[str]:
199
  files.sort(key=os.path.getmtime, reverse=True)
200
  return files[0]
201
 
202
- def _df_to_excel_bytes(df: pd.DataFrame) -> bytes:
203
  bio = BytesIO()
204
- df.to_excel(bio, index=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  bio.seek(0)
206
  return bio.read()
207
 
@@ -211,8 +261,8 @@ def _build_html_body(df: pd.DataFrame, title: str) -> str:
211
  table {{ border-collapse: collapse; font-size: 13px; }}
212
  table, th, td {{ border: 1px solid #ccc; padding: 6px; }}
213
  th {{ background:#f6f6f6; }}
 
214
  </style></head><body><h3>{title}</h3>{table_html}
215
- <p style="color:#666;">备注:此邮件由自动化系统生成。</p>
216
  </body></html>"""
217
  return html
218
 
@@ -244,12 +294,10 @@ def run_once(file_path: Optional[str] = None) -> dict:
244
  raw = read_system_export(file_path)
245
  final = aggregate_for_email(raw)
246
 
247
- # --- 使用带样式的Excel生成函数 ---
248
- attach = _df_to_styled_excel_bytes(final) # 假设这个函数存在
249
-
250
  out_name = f"邮件发送的格式_{datetime.now().strftime('%Y%m%d')}.xlsx"
251
  out_path = os.path.join(OUTPUT_DIR, out_name)
252
- # 仍然可以在服务器上保存一份不带样式的Excel
 
253
  final.to_excel(out_path, index=False)
254
 
255
  subject = f"采购执行表自动推��� {datetime.now().date()}"
@@ -262,51 +310,6 @@ def run_once(file_path: Optional[str] = None) -> dict:
262
  import traceback
263
  return {"ok": False, "msg": f"处理文件时发生严重错误: {e}", "traceback": traceback.format_exc()}
264
 
265
- def _df_to_styled_excel_bytes(df: pd.DataFrame) -> bytes:
266
- """
267
- 生成带样式的Excel文件。
268
- 使用XlsxWriter引擎来添加字体、边框、条件格式等。
269
- """
270
- bio = BytesIO()
271
- # fillna('') 可以在生成excel时将 <NA> 显示为空字符串
272
- writer = pd.ExcelWriter(bio, engine='xlsxwriter')
273
-
274
- sheet_name = '采购执行表'
275
- df.fillna('').to_excel(writer, sheet_name=sheet_name, index=False)
276
-
277
- workbook = writer.book
278
- worksheet = writer.sheets[sheet_name]
279
-
280
- # 定义格式
281
- header_format = workbook.add_format({'bold': True, 'font_name': 'Arial', 'font_size': 10, 'border': 1, 'align': 'center', 'valign': 'vcenter'})
282
- default_format = workbook.add_format({'font_name': 'Arial', 'font_size': 10, 'border': 1})
283
- overdue_format = workbook.add_format({'font_name': 'Arial', 'font_size': 10, 'border': 1, 'font_color': 'red'})
284
-
285
- # 应用表头格式
286
- for col_num, value in enumerate(df.columns.values):
287
- worksheet.write(0, col_num, value, header_format)
288
-
289
- # 应用内容格式和条件格式
290
- worksheet.conditional_format(1, 0, len(df), len(df.columns)-1, {'type': 'no_blanks', 'format': default_format})
291
-
292
- try:
293
- progress_col_idx = df.columns.get_loc('目前进度')
294
- for row_num in range(len(df)):
295
- status_text = df.iloc[row_num, progress_col_idx]
296
- if isinstance(status_text, str) and "逾期" in status_text:
297
- worksheet.set_row(row_num + 1, None, overdue_format)
298
- except KeyError:
299
- pass
300
-
301
- # 自动调整列宽
302
- for i, col in enumerate(df.columns):
303
- column_len = max(df[col].astype(str).str.len().max(), len(col)) + 2
304
- worksheet.set_column(i, i, min(column_len, 40))
305
-
306
- writer.close()
307
- bio.seek(0)
308
- return bio.read()
309
-
310
  def main():
311
  arg_file = sys.argv[1] if len(sys.argv) > 1 else None
312
  result = run_once(arg_file)
 
13
  import base64
14
  from io import BytesIO
15
  from typing import Optional, Tuple, List
 
16
  from datetime import datetime, date
17
 
18
  import pandas as pd
 
54
  "主数量","需求日期","供应商","到货日期","到货主数量","入库日期","入库主数量","目前进度"
55
  ]
56
 
57
+ TEMPLATE_CANDIDATES = [
58
+ "/workspace/邮件发送的格式.xlsx",
59
+ "/workspace/templates/邮件发送的格式.xlsx",
60
+ "/app/邮件发送的格式.xlsx",
61
+ "/app/templates/邮件发送的格式.xlsx",
62
+ ]
63
+
64
+
65
  # ====== 工具函数 ======
66
  def _today() -> date:
67
  return datetime.now().date()
 
146
  grouped = df.groupby(group_keys, dropna=False).agg(final_agg_map).reset_index()
147
  grouped["目前进度"] = grouped.apply(_calc_progress_row, axis=1)
148
 
149
+ def get_sort_key(status_text):
150
+ if "逾期" in status_text and "未到货" in status_text:
151
+ return 1
152
+ if "逾期" in status_text and "部分到货" in status_text:
153
+ return 2
154
+ if "未来7天" in status_text:
155
+ return 3
156
+ if "完全到货" in status_text:
157
+ return 4
158
+ return 5
159
+
160
+ grouped['sort_key'] = grouped['目前进度'].apply(get_sort_key)
161
+ grouped = grouped.sort_values(by='sort_key').drop(columns=['sort_key'])
162
+
163
  if "计划到货日期" in grouped.columns:
164
  grouped = grouped.drop(columns=["计划到货日期"])
165
 
166
  final_cols = [col for col in EMAIL_COLS_DEFAULT if col in grouped.columns]
167
  final = grouped[final_cols]
168
 
 
 
169
  date_cols_to_format = ["请购日期", "需求日期", "到货日期", "入库日期"]
170
  for col in date_cols_to_format:
171
  if col in final.columns:
172
+ final[col] = pd.to_datetime(final[col], errors='coerce').dt.strftime('%Y-%m-%d')
173
 
174
  return final
175
 
 
218
  files.sort(key=os.path.getmtime, reverse=True)
219
  return files[0]
220
 
221
+ def _df_to_styled_excel_bytes(df: pd.DataFrame) -> bytes:
222
  bio = BytesIO()
223
+ writer = pd.ExcelWriter(bio, engine='xlsxwriter')
224
+
225
+ sheet_name = '采购执行表'
226
+ df.fillna('').to_excel(writer, sheet_name=sheet_name, index=False)
227
+
228
+ workbook = writer.book
229
+ worksheet = writer.sheets[sheet_name]
230
+
231
+ header_format = workbook.add_format({'bold': True, 'font_name': 'Arial', 'font_size': 10, 'border': 1, 'align': 'center', 'valign': 'vcenter'})
232
+ default_format = workbook.add_format({'font_name': 'Arial', 'font_size': 10, 'border': 1})
233
+ overdue_format = workbook.add_format({'font_name': 'Arial', 'font_size': 10, 'border': 1, 'font_color': 'red'})
234
+
235
+ for col_num, value in enumerate(df.columns.values):
236
+ worksheet.write(0, col_num, value, header_format)
237
+
238
+ worksheet.conditional_format(1, 0, len(df), len(df.columns)-1, {'type': 'no_blanks', 'format': default_format})
239
+
240
+ try:
241
+ progress_col_idx = df.columns.get_loc('目前进度')
242
+ for row_num in range(len(df)):
243
+ status_text = df.iloc[row_num, progress_col_idx]
244
+ if isinstance(status_text, str) and "逾期" in status_text:
245
+ worksheet.set_row(row_num + 1, None, overdue_format)
246
+ except KeyError:
247
+ pass
248
+
249
+ for i, col in enumerate(df.columns):
250
+ column_len = df[col].astype(str).str.len().max()
251
+ column_len = max(column_len, len(col) * 2)
252
+ worksheet.set_column(i, i, min(column_len, 40))
253
+
254
+ writer.close()
255
  bio.seek(0)
256
  return bio.read()
257
 
 
261
  table {{ border-collapse: collapse; font-size: 13px; }}
262
  table, th, td {{ border: 1px solid #ccc; padding: 6px; }}
263
  th {{ background:#f6f6f6; }}
264
+ tr:nth-child(even) {{background-color: #f2f2f2;}}
265
  </style></head><body><h3>{title}</h3>{table_html}
 
266
  </body></html>"""
267
  return html
268
 
 
294
  raw = read_system_export(file_path)
295
  final = aggregate_for_email(raw)
296
 
 
 
 
297
  out_name = f"邮件发送的格式_{datetime.now().strftime('%Y%m%d')}.xlsx"
298
  out_path = os.path.join(OUTPUT_DIR, out_name)
299
+
300
+ attach = _df_to_styled_excel_bytes(final)
301
  final.to_excel(out_path, index=False)
302
 
303
  subject = f"采购执行表自动推��� {datetime.now().date()}"
 
310
  import traceback
311
  return {"ok": False, "msg": f"处理文件时发生严重错误: {e}", "traceback": traceback.format_exc()}
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  def main():
314
  arg_file = sys.argv[1] if len(sys.argv) > 1 else None
315
  result = run_once(arg_file)