Spaces:
Sleeping
Sleeping
| """ | |
| environments/trace_env/tools/report_tool.py | |
| Generates a DOCX report containing a table of financial transactions. | |
| """ | |
| import os | |
| from docx import Document | |
| from docx.shared import Inches, Pt | |
| from docx.enum.text import WD_ALIGN_PARAGRAPH | |
| def export_transactions_to_docx(transactions: list[dict], output_path: str = "financial_report.docx") -> str: | |
| """ | |
| Export a list of parsed transactions into a formatted DOCX table. | |
| Args: | |
| transactions: List of transaction dictionaries. | |
| output_path: Path where the DOCX file will be saved. | |
| Returns: | |
| The absolute path to the generated DOCX file. | |
| """ | |
| doc = Document() | |
| # Title | |
| title = doc.add_heading("Financial Transactions Audit Report", 0) | |
| title.alignment = WD_ALIGN_PARAGRAPH.CENTER | |
| doc.add_paragraph(f"Total Transactions: {len(transactions)}") | |
| # Calculate total spend | |
| import re | |
| total_spend = 0.0 | |
| for t in transactions: | |
| amount_str = re.sub(r'[^\d.]', '', t.get("total") or "") | |
| amount = float(amount_str) if amount_str else 0.0 | |
| total_spend += amount | |
| doc.add_paragraph(f"Total Spend: ₹{total_spend:,.2f}") | |
| # Create Table | |
| table = doc.add_table(rows=1, cols=7) # Increased to 7 columns | |
| table.style = 'Table Grid' | |
| # Set headers | |
| hdr_cells = table.rows[0].cells | |
| headers = ["Date", "Vendor", "Category", "Amount", "Method", "Source", "Notes"] | |
| for i, header_text in enumerate(headers): | |
| hdr_cells[i].text = header_text | |
| for paragraph in hdr_cells[i].paragraphs: | |
| for run in paragraph.runs: | |
| run.font.bold = True | |
| # Add rows | |
| for t in transactions: | |
| row_cells = table.add_row().cells | |
| # Determine amount | |
| amount_str = re.sub(r'[^\d.]', '', t.get("total") or "") | |
| amount = float(amount_str) if amount_str else 0.0 | |
| # Build notes | |
| details = [] | |
| if t.get("details"): | |
| for k, v in t["details"].items(): | |
| if k == "sheet_notes": continue # handle separately | |
| if isinstance(v, list): | |
| details.append(f"{k}: {len(v)} items") | |
| else: | |
| details.append(f"{k}: {v}") | |
| sheet_notes = t.get("notes") or t.get("details", {}).get("sheet_notes") | |
| if sheet_notes and str(sheet_notes) not in details: | |
| details.append(f"[Sheet] {sheet_notes}") | |
| if not details: | |
| subj = t.get("subject", "").strip() | |
| if subj: | |
| details.append(subj[:60]) | |
| notes_str = " | ".join(details) | |
| source = t.get("_source", "gmail").capitalize() | |
| if t.get("image_analyses") or t.get("doc_analyses"): | |
| source += " (+AI)" | |
| row_cells[0].text = t.get("date", "") | |
| row_cells[1].text = t.get("vendor", "Unknown") | |
| row_cells[2].text = t.get("category", "Unknown").capitalize() | |
| row_cells[3].text = f"₹{amount:,.2f}" if amount > 0 else "-" | |
| row_cells[4].text = t.get("payment_method", "Unknown") | |
| row_cells[5].text = source | |
| row_cells[6].text = notes_str | |
| # Save the document with retry logic | |
| abs_path = os.path.abspath(output_path) | |
| try: | |
| doc.save(abs_path) | |
| except IOError: | |
| # Fallback if file is open | |
| import time | |
| suffix = int(time.time()) | |
| alt_path = abs_path.replace(".docx", f"_{suffix}.docx") | |
| doc.save(alt_path) | |
| abs_path = alt_path | |
| return abs_path | |