Saltar al contenido principal

✅ Simplified PDF API - Final Design

Based on user feedback: Removed confusing /attach-pdf endpoint
New design: Simple, logical, works correctly
Workflow: Generate PDF first, then send with attachment


🎯 CLEAN API DESIGN

Only 3 PDF Endpoints (Simple!):

POST /communications/generate-pdf          → Generate PDF, get base64
POST /communications/send → Send with attachments
GET /communications/:id/attachments → View what was sent
GET /communications/pdf-templates → List available templates

That's it! Simple and clear! ✅


📡 THE CORRECT WORKFLOW

Two Steps:

Step 1: Generate PDF

POST /communications/generate-pdf

Returns: { filename, content (base64), mimeType }

Step 2: Send with PDF

POST /communications/send
{
attachments: [
{ filename, content, mimeType } ← From step 1
]
}

Email sent WITH PDF! ✅

🚀 EXAMPLE USAGE

Complete Example:

# Step 1: Generate PDF
curl -X POST 'http://localhost:4000/communications/generate-pdf' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{
"templateType": "invoice",
"templateData": {
"invoiceNumber": "INV-12350",
"invoiceDate": "2025-11-01",
"companyName": "RPA Solution",
"customerName": "John Doe",
"totalAmount": "$550.00",
"items": [
{
"name": "Product A",
"quantity": 2,
"unitPrice": "$100.00",
"amount": "$200.00"
}
]
}
}' | jq '.'

# Response:
# {
# "filename": "invoice-2025-11-01-temp123.pdf",
# "content": "JVBERi0xLjQK...", ← COPY THIS!
# "mimeType": "application/pdf",
# "sizeBytes": 12345
# }

# Step 2: Send with PDF (paste the content from step 1)
curl -X POST 'http://localhost:4000/communications/send' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{
"businessId": "33b6db4b-51c5-45ee-8d04-c01c2d157f66",
"createdBy": "6c0c4f32-d74a-4a84-892f-3bead447d765",
"channel": "email",
"type": "invoice",
"recipientType": "customer",
"recipientContact": "luisrangelc@gmail.com",
"subject": "Invoice #12350 - With PDF!",
"content": "<p>Your invoice is attached.</p>",
"attachments": [
{
"filename": "invoice-12350.pdf",
"content": "PASTE_BASE64_FROM_STEP_1_HERE",
"mimeType": "application/pdf"
}
]
}'

Check Gmail → Email with PDF attachment! 📧📎


💻 BACKEND CODE (TypeScript)

Simple Service Method:

@Injectable()
export class InvoiceService {
constructor(
private readonly generatePdfUseCase: GenerateCommunicationPdfUseCase,
private readonly communicationsService: CommunicationsService,
) {}

async sendInvoiceWithPdf(invoice: Invoice) {
// 1. Generate PDF
const pdf = await this.generatePdfUseCase.execute({
templateType: 'invoice',
templateData: {
invoiceNumber: invoice.number,
companyName: invoice.business.name,
customerName: invoice.customer.name,
totalAmount: `$${invoice.total.toFixed(2)}`,
// ... more fields
}
});

// 2. Send email with PDF
return await this.communicationsService.send({
businessId: invoice.businessId,
recipientContact: invoice.customerEmail,
channel: 'email',
type: 'invoice',
subject: `Invoice ${invoice.number}`,
content: '<p>Invoice attached as PDF</p>',
attachments: [
{
filename: pdf.filename,
content: pdf.content,
mimeType: pdf.mimeType
}
]
});
}
}

Usage:

await invoiceService.sendInvoiceWithPdf(invoice);
// ✅ Generates PDF and sends email in one call!

🎨 FRONTEND CODE (React/TypeScript)

// Frontend service
export const generatePdf = async (templateType, templateData) => {
const response = await api.post('/communications/generate-pdf', {
templateType,
templateData
});
return response.data;
};

export const sendCommunication = async (data) => {
const response = await api.post('/communications/send', data);
return response.data;
};

// Component
const handleSendInvoice = async (invoice: Invoice) => {
try {
setLoading(true);

// 1. Generate PDF
const pdf = await generatePdf('invoice', {
invoiceNumber: invoice.number,
customerName: invoice.customerName,
companyName: 'RPA Solution',
totalAmount: formatCurrency(invoice.total)
});

// 2. Send with PDF
await sendCommunication({
recipientContact: invoice.customerEmail,
channel: 'email',
type: 'invoice',
subject: `Invoice ${invoice.number}`,
content: '<p>Invoice attached</p>',
attachments: [
{
filename: pdf.filename,
content: pdf.content,
mimeType: pdf.mimeType
}
]
});

toast.success('Invoice sent with PDF!');
} catch (error) {
toast.error('Failed to send invoice');
} finally {
setLoading(false);
}
};

📊 CLEAN API SUMMARY

All Communication Endpoints:

GET    /communications                    List communications
GET /communications/:id Get by ID
POST /communications Create (draft)
POST /communications/send Send communication
PATCH /communications/:id Update
DELETE /communications/:id Delete
POST /communications/:id/resend Resend failed
GET /communications/stats Statistics

PDF Endpoints:
POST /communications/generate-pdf ✨ Generate PDF
GET /communications/:id/attachments View attachments
GET /communications/pdf-templates List templates

Clean, simple, logical!


🏆 WHAT WE CLEANED UP

Removed (Confusing):

  • POST /communications/:id/attach-pdf - Implied you could attach after sending
  • AttachPdfToCommunicationUseCase - Not needed

Kept (Makes Sense):

  • POST /communications/generate-pdf - Generate PDF before sending
  • GenerateCommunicationPdfUseCase - Clean use case
  • POST /communications/send - Send with attachments
  • GET /communications/:id/attachments - View what was sent

🎯 FILES UPDATED

✅ communications.controller.ts (cleaned up)
- Removed: attach-pdf endpoint
- Kept: generate-pdf endpoint

✅ communications.module.ts (cleaned up)
- Removed: AttachPdfToCommunicationUseCase
- Kept: GenerateCommunicationPdfUseCase

✅ attach-pdf-to-communication.use-case.ts (deleted)
- Not needed anymore

✅ generate-communication-pdf.use-case.ts (kept)
- This is what we need!

🎊 FINAL API DESIGN

PDF Workflow (Simple!):

1. Generate PDF
POST /communications/generate-pdf
Body: { templateType, templateData }
Returns: { filename, content (base64), mimeType }

2. Send Email
POST /communications/send
Body: {
...,
attachments: [
{ filename, content, mimeType } ← From step 1
]
}

✅ Email sent with PDF attachment!

No confusion, no extra steps, just works! 🚀


🎉 TRY IT NOW!

After restarting backend:

# Generate PDF
curl -X POST 'http://localhost:4000/communications/generate-pdf' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{
"templateType": "invoice",
"templateData": {
"invoiceNumber": "TEST-001",
"companyName": "RPA Solution",
"customerName": "Your Name",
"totalAmount": "$99.99"
}
}'

# Copy the "content" value from response
# Then send email with that PDF

SUMMARY

You were right! The /attach-pdf endpoint was confusing and didn't make sense.

New clean design:

  • ✅ Simple workflow (generate → send)
  • ✅ Clear purpose for each endpoint
  • ✅ No confusion about when to use what
  • ✅ Works the way users expect

API is now clean and logical! 🎊


Document Version: 1.0
Last Updated: November 1, 2025, 12:15 PM
Status: ✅ Simplified and improved!