Saltar al contenido principal

🔧 PDF Attachment - Troubleshooting Guide

Issue: Empty attachments array
Your Request: Working correctly! ✅
Problem: Endpoint was returning placeholder data


ISSUE FIXED!

I've updated the getAttachments endpoint to return actual data from the database instead of a placeholder empty array.

What was wrong:

// BEFORE (placeholder):
return {
communicationId: id,
attachments: [], // Always empty!
};

// AFTER (fixed):
const attachments = await this.attachmentHandler.getAttachments(id);
return {
communicationId: id,
attachments, // Real data from database!
};

🧪 TEST AGAIN NOW!

Step 1: Restart Backend

cd apps/backend

# Stop the current server (Ctrl+C)
# Then restart:
pnpm start:dev

Step 2: Try Your Curl Commands Again

# 1. Send communication
curl --location --request POST 'http://localhost:4000/communications/send' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--data-raw '{
"businessId": "33b6db4b-51c5-45ee-8d04-c01c2d157f66",
"createdBy": "6c0c4f32-d74a-4a84-892f-3bead447d765",
"channel": "email",
"type": "invoice",
"recipientType": "customer",
"recipientId": "824e2bec-8402-4846-b974-1fd543fa2cb1",
"recipientContact": "luisrangelc@gmail.com",
"subject": "Your Invoice #1234",
"content": "Please see attached invoice",
"entityType": "sale",
"entityId": "3be5a997-ab73-41fb-8900-d2002a08736e"
}'

# Note the ID from response (e.g., "2a2938c2-5cfe-483b-ae68-d3bc0c836ed2")

# 2. Attach PDF
curl --location --request POST 'http://localhost:4000/communications/2a2938c2-5cfe-483b-ae68-d3bc0c836ed2/attach-pdf' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--data '{
"templateType": "invoice",
"templateData": {
"invoiceNumber": "INV-001",
"invoiceDate": "2025-11-01",
"companyName": "FlowPOS",
"customerName": "John Doe",
"totalAmount": "$100.00",
"items": [
{
"name": "Product A",
"quantity": 2,
"unitPrice": "$50.00",
"amount": "$100.00"
}
]
},
"autoAttach": true
}'

# 3. Get attachments (should now show data!)
curl --location --request GET 'http://localhost:4000/communications/2a2938c2-5cfe-483b-ae68-d3bc0c836ed2/attachments' \
--header 'Authorization: Bearer YOUR_TOKEN'

Expected Response:

{
"communicationId": "2a2938c2-5cfe-483b-ae68-d3bc0c836ed2",
"attachments": [
{
"communicationId": "2a2938c2-5cfe-483b-ae68-d3bc0c836ed2",
"filename": "invoice-2025-11-01-2a2938c2.pdf",
"mimeType": "application/pdf",
"sizeBytes": 12345,
"fileUrl": null,
"filePath": null,
"createdAt": "2025-11-01T..."
}
]
}

🔍 CHECK IF PDF WAS ACTUALLY CREATED

Look at Backend Logs:

After calling /attach-pdf, you should see:

[CommunicationPdfService] Generating invoice PDF for communication 2a2938c2-5cfe-483b-ae68-d3bc0c836ed2
[CommunicationPdfService] PDF generated successfully: invoice-2025-11-01-2a2938c2.pdf (12345 bytes)
[AttachPdfToCommunicationUseCase] Auto-attaching PDF to email communication 2a2938c2-5cfe-483b-ae68-d3bc0c836ed2
[AttachmentHandlerService] Saved 1 attachment(s) for communication 2a2938c2-5cfe-483b-ae68-d3bc0c836ed2

If you see these logs → PDF was created and saved! ✅

If you DON'T see these logs → Check for errors in the logs


🐛 COMMON ISSUES & FIXES

Issue 1: Empty Attachments Array

Status:FIXED!

What was wrong:
The endpoint was returning a placeholder instead of querying the database.

Fix applied:
Updated getAttachments to call attachmentHandler.getAttachments(id)


Issue 2: Template File Not Found

Error: Template not found: communication-invoice.html

Cause: Template files not in the correct location

Fix:

# Check if templates exist:
ls -la apps/backend/src/communications/templates/

# Should see:
# communication-invoice.html
# communication-payment.html
# communication-order.html
# communication-general.html

If missing: The templates were created in the source directory and need to be there.


Issue 3: Module Not Reloaded

Symptom: Old code still running after changes

Fix:

# Stop backend (Ctrl+C)
# Restart:
cd apps/backend
pnpm start:dev

# NestJS should auto-reload, but sometimes restart is needed

Issue 4: Database Connection

Error: Cannot query database

Fix: Check database connection in logs

# Backend should show on startup:
[DatabaseModule] Connected to database

Issue 5: Missing Template Data

Error: PDF generated but looks incomplete

Cause: Missing required template variables

Fix: Include all required fields for each template type

Invoice requires:

{
invoiceNumber: "INV-001", // Required
companyName: "FlowPOS", // Required
customerName: "John Doe", // Required
totalAmount: "$100.00" // Required
}

🧪 STEP-BY-STEP DEBUGGING

Step 1: Verify Backend is Running

# Check if backend is running
curl http://localhost:4000/health

# Should return: {"status":"ok"}

Step 2: Check Communication Exists

# Get the communication
curl http://localhost:4000/communications/2a2938c2-5cfe-483b-ae68-d3bc0c836ed2 \
--header 'Authorization: Bearer YOUR_TOKEN'

# Should return communication object

Step 3: Check Templates Endpoint

# List available templates
curl http://localhost:4000/communications/pdf-templates/available \
--header 'Authorization: Bearer YOUR_TOKEN'

# Should return:
# [
# { "type": "invoice", "name": "Invoice", ... },
# { "type": "payment", "name": "Payment Confirmation", ... },
# ...
# ]

Step 4: Attach PDF with Logging

# Call attach-pdf and watch backend logs
curl --location --request POST 'http://localhost:4000/communications/YOUR_COMM_ID/attach-pdf' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--data '{
"templateType": "invoice",
"templateData": {
"invoiceNumber": "INV-TEST-001",
"invoiceDate": "2025-11-01",
"companyName": "FlowPOS",
"customerName": "Test Customer",
"totalAmount": "$99.99"
},
"autoAttach": true
}'

# Watch backend terminal for logs:
# ✅ Should see PDF generation logs
# ✅ Should see attachment save logs

Expected logs:

[CommunicationPdfService] Generating invoice PDF for communication YOUR_COMM_ID
[CommunicationPdfService] PDF generated successfully: invoice-2025-11-01-YOUR_COMM_ID.pdf (XXXX bytes)
[AttachmentHandlerService] Saved 1 attachment(s) for communication YOUR_COMM_ID

Step 5: Get Attachments

# Now get attachments - should have data!
curl http://localhost:4000/communications/YOUR_COMM_ID/attachments \
--header 'Authorization: Bearer YOUR_TOKEN'

Expected response:

{
"communicationId": "YOUR_COMM_ID",
"attachments": [
{
"communicationId": "YOUR_COMM_ID",
"filename": "invoice-2025-11-01-YOUR_COMM_ID.pdf",
"mimeType": "application/pdf",
"sizeBytes": 12345,
"createdAt": "2025-11-01T..."
}
]
}

🔍 CHECK DATABASE DIRECTLY

Query Attachments Table:

-- Connect to your database
-- Then run:

SELECT * FROM communication_attachment
WHERE communication_id = '2a2938c2-5cfe-483b-ae68-d3bc0c836ed2';

-- Should show:
-- id | communication_id | filename | mime_type | size_bytes | file_url | created_at

If empty → PDF was not saved
If has data → PDF was saved, but endpoint had bug (now fixed!)


⚠️ IMPORTANT NOTES

Note 1: PDF Content is Placeholder

Currently, the generatePdfFromHtml() method returns HTML as a buffer instead of actual PDF.

Why? The implementation is a placeholder that needs Puppeteer integration.

Current behavior:

// Returns HTML buffer (not real PDF yet)
private async generatePdfFromHtml(html: string): Promise<Buffer> {
return Buffer.from(html, "utf-8");
}

To get real PDFs: Integrate with your existing PDF service:

// Use your existing Puppeteer service
import { PuppeteerPdfGeneratorAdapter } from '@/pdf/infrastructure/adapters/puppeteer-pdf-generator.adapter';

private async generatePdfFromHtml(html: string): Promise<Buffer> {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(html);
const pdf = await page.pdf({ format: 'A4' });
await browser.close();
return pdf;
}

Note 2: Template Path

I updated the template path to work in both dev and production:

// Updated to use process.cwd()
private readonly templatesPath = path.join(
process.cwd(),
'src/communications/templates',
);

In production build: You may need to adjust this path or copy templates to dist/ folder.


WHAT SHOULD WORK NOW

After the fix and restart:

Attach PDF endpoint → Should save to database
Get attachments endpoint → Should return saved attachments
PDF generation → Should create HTML buffer (placeholder PDF)
Database storage → Should save attachment record


🎯 TO COMPLETE REAL PDF GENERATION

Option 1: Integrate with Existing PDF Service

You already have a complete PDF infrastructure at:

apps/backend/src/pdf/infrastructure/adapters/puppeteer-pdf-generator.adapter.ts

Update communication-pdf.service.ts:

import { PuppeteerPdfGeneratorAdapter } from '@/pdf/infrastructure/adapters/puppeteer-pdf-generator.adapter';

export class CommunicationPdfService {
constructor(
private readonly puppeteerGenerator: PuppeteerPdfGeneratorAdapter
) {}

private async generatePdfFromHtml(html: string): Promise<Buffer> {
// Use your existing PDF generator!
return await this.puppeteerGenerator.generatePdf({
html,
format: 'A4',
printBackground: true,
});
}
}

Option 2: Use Simple Puppeteer Directly

# Install puppeteer if not already
cd apps/backend
pnpm add puppeteer

Update communication-pdf.service.ts:

import puppeteer from 'puppeteer';

private async generatePdfFromHtml(html: string): Promise<Buffer> {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});

try {
const page = await browser.newPage();
await page.setContent(html, { waitUntil: 'networkidle0' });
const pdf = await page.pdf({
format: 'A4',
printBackground: true,
margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' },
});
return pdf;
} finally {
await browser.close();
}
}

📊 VERIFY THE FIX WORKED

Test Sequence:

# 1. Restart backend
cd apps/backend
pnpm start:dev

# 2. Send communication (note the ID from response)
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": "Test Invoice #2",
"content": "Testing PDF attachment"
}'

# 3. Attach PDF (use the ID from step 2)
curl -X POST 'http://localhost:4000/communications/COMM_ID_HERE/attach-pdf' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{
"templateType": "invoice",
"templateData": {
"invoiceNumber": "INV-002",
"invoiceDate": "2025-11-01",
"companyName": "FlowPOS",
"companyAddress": "123 Main St",
"customerName": "John Doe",
"customerEmail": "john@example.com",
"totalAmount": "$100.00",
"items": [
{
"name": "Product A",
"quantity": 2,
"unitPrice": "$50.00",
"amount": "$100.00"
}
],
"subtotal": "$100.00",
"tax": "$0.00"
},
"autoAttach": true
}'

# Expected response:
# {
# "success": true,
# "pdfFilename": "invoice-2025-11-01-COMM_ID.pdf",
# "pdfSize": 12345,
# "communication": { ... }
# }

# 4. Get attachments (should now have data!)
curl 'http://localhost:4000/communications/COMM_ID_HERE/attachments' \
-H 'Authorization: Bearer YOUR_TOKEN'

# Expected response:
# {
# "communicationId": "COMM_ID_HERE",
# "attachments": [
# {
# "communicationId": "COMM_ID_HERE",
# "filename": "invoice-2025-11-01-COMM_ID.pdf",
# "mimeType": "application/pdf",
# "sizeBytes": 12345,
# "fileUrl": null,
# "filePath": null,
# "createdAt": "2025-11-01T..."
# }
# ]
# }

🎯 WHAT TO CHECK

✅ If It Works:

You should see:

  1. /attach-pdf returns success with filename
  2. /attachments returns array with attachment data
  3. ✅ Backend logs show PDF generation
  4. ✅ Database has record in communication_attachment table

❌ If Still Empty:

Check 1: Backend Logs

Look for errors in terminal where backend is running

Check 2: Database

SELECT * FROM communication_attachment 
WHERE communication_id = 'YOUR_COMM_ID';

Check 3: Network Tab

In browser dev tools, check if:
- Request is sent
- Response is received
- No CORS errors

Check 4: Template Files

# Verify templates exist
ls -la /Users/luisrangel/devLR/rpa/flowpos-workspace/apps/backend/src/communications/templates/

# Should show:
# communication-invoice.html
# communication-payment.html
# communication-order.html
# communication-general.html

💡 QUICK FIX CHECKLIST

  • Fixed getAttachments endpoint to return real data
  • Added AttachmentHandlerService to controller
  • Updated communications.module.ts with new services
  • Restart backend (do this now!)
  • Test with curl commands above
  • Check backend logs for errors
  • Verify database has attachment records

🚀 AFTER RESTART

Your curl commands should work perfectly! The attachments endpoint will now return:

{
"communicationId": "2a2938c2-5cfe-483b-ae68-d3bc0c836ed2",
"attachments": [
{
"communicationId": "2a2938c2-5cfe-483b-ae68-d3bc0c836ed2",
"filename": "invoice-2025-11-01-2a2938c2.pdf",
"mimeType": "application/pdf",
"sizeBytes": 12345,
"fileUrl": null,
"filePath": null,
"createdAt": "2025-11-01T11:30:00.000Z"
}
]
}

📞 NEED MORE HELP?

If you still get empty attachments after restarting, check:

  1. Backend logs - Any errors?
  2. Database - Does communication_attachment table exist?
  3. Request payload - Is it formatted correctly?
  4. Response from attach-pdf - Did it return success?

Send me the backend logs and I'll help debug! 🔍


Document Version: 1.0
Issue: FIXED ✅
Action Required: Restart backend and test again
Expected: Attachments will now show! 🎉