mirror of
https://github.com/fsecada01/Pygentic-AI.git
synced 2026-05-12 04:04:57 +00:00
feat(pdf): improve download filename with company names and date
- Generate descriptive filenames: swot-{company}-vs-{competitor}-{date}.pdf
- Sanitize company names for filesystem safety
- Include date in YYYY-MM-DD format
- Handle multiple comparison entities (e.g., "plus2" for 2 additional)
Examples:
- Single entity: "swot-Apple-2026-02-04.pdf"
- With comparison: "swot-Apple-vs-Microsoft-2026-02-04.pdf"
- Multiple comparisons: "swot-Apple-vs-Microsoft-plus2-2026-02-04.pdf"
Fixes: Downloaded PDF had generic filename with .txt suffix
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -218,8 +218,35 @@ async def download_pdf(request: Request) -> StreamingResponse:
|
||||
# Cache the generated PDF
|
||||
pdf_cache.set(session_id, result, pdf_buffer)
|
||||
|
||||
# Prepare filename
|
||||
filename = f"swot-analysis-{session_id[:8]}.pdf"
|
||||
# Prepare filename with company names and date
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
# Sanitize company names for filename (remove special chars, limit length)
|
||||
def sanitize_filename(text: str, max_length: int = 30) -> str:
|
||||
# Remove special characters, keep alphanumeric, spaces, hyphens
|
||||
text = re.sub(r"[^\w\s-]", "", text)
|
||||
# Replace spaces with hyphens
|
||||
text = re.sub(r"\s+", "-", text.strip())
|
||||
# Limit length
|
||||
return text[:max_length].rstrip("-")
|
||||
|
||||
# Build entity string
|
||||
primary = sanitize_filename(result.primary_entity)
|
||||
if result.comparison_entities:
|
||||
# Include first comparison entity
|
||||
comparison = sanitize_filename(result.comparison_entities[0])
|
||||
entities_str = f"{primary}-vs-{comparison}"
|
||||
if len(result.comparison_entities) > 1:
|
||||
entities_str += f"-plus{len(result.comparison_entities) - 1}"
|
||||
else:
|
||||
entities_str = primary
|
||||
|
||||
# Add date
|
||||
date_str = datetime.now().strftime("%Y-%m-%d")
|
||||
|
||||
# Build final filename
|
||||
filename = f"swot-{entities_str}-{date_str}.pdf"
|
||||
|
||||
# Return as streaming response (iterate over BytesIO in chunks)
|
||||
def iterfile():
|
||||
@ -230,7 +257,7 @@ async def download_pdf(request: Request) -> StreamingResponse:
|
||||
content=iterfile(),
|
||||
media_type="application/pdf",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename={filename}",
|
||||
"Content-Disposition": f'attachment; filename="{filename}"',
|
||||
"Cache-Control": "no-cache",
|
||||
},
|
||||
)
|
||||
|
||||
@ -230,7 +230,9 @@ class TestPDFDownloadEndpoint:
|
||||
assert response.status_code == 200
|
||||
assert response.headers["content-type"] == "application/pdf"
|
||||
assert "attachment" in response.headers["content-disposition"]
|
||||
assert "swot-analysis" in response.headers["content-disposition"]
|
||||
# New filename format: swot-{company}-{date}.pdf
|
||||
assert "swot-" in response.headers["content-disposition"]
|
||||
assert ".pdf" in response.headers["content-disposition"]
|
||||
|
||||
# Verify it's a valid PDF by reading the stream
|
||||
body_content = b""
|
||||
@ -281,7 +283,9 @@ class TestPDFDownloadEndpoint:
|
||||
async def test_download_pdf_filename_format(
|
||||
self, mock_session_id: str, sample_swot_analysis
|
||||
):
|
||||
"""Test PDF filename follows expected format"""
|
||||
"""Test PDF filename follows expected format: swot-{company}-{date}.pdf"""
|
||||
from datetime import datetime
|
||||
|
||||
from backend.site.router import download_pdf
|
||||
|
||||
# Create mock request
|
||||
@ -297,5 +301,10 @@ class TestPDFDownloadEndpoint:
|
||||
|
||||
assert response.status_code == 200
|
||||
disposition = response.headers["content-disposition"]
|
||||
# Format: swot-analysis-{session_id[:8]}.pdf
|
||||
assert f"swot-analysis-{mock_session_id[:8]}.pdf" in disposition
|
||||
|
||||
# New format: swot-{primary_entity}-vs-{comparison[0]}-{date}.pdf
|
||||
# Sample has primary_entity="Google", comparison_entities=["Microsoft", "Amazon"]
|
||||
assert "swot-Google-vs-Microsoft" in disposition
|
||||
assert "plus1" in disposition # +1 more comparison (Amazon)
|
||||
assert datetime.now().strftime("%Y-%m-%d") in disposition
|
||||
assert ".pdf" in disposition
|
||||
|
||||
Reference in New Issue
Block a user