From 06500a614d2c1aff8129d9b7b4fb1379cd052bc1 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 9 Jul 2025 22:47:52 -0400 Subject: [PATCH] updates --- server/api/expenses/generate-pdf.ts | 91 +++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/server/api/expenses/generate-pdf.ts b/server/api/expenses/generate-pdf.ts index c9670af..25ded80 100644 --- a/server/api/expenses/generate-pdf.ts +++ b/server/api/expenses/generate-pdf.ts @@ -291,18 +291,18 @@ async function addExpenseTable(doc: PDFKit.PDFDocument, expenses: Expense[], opt const rowHeight = 25; const fontSize = 9; - // Column definitions + // Column definitions - adjusted for better layout const columns = [ - { header: 'Date', width: 70, x: 60 }, - { header: 'Establishment', width: 120, x: 130 }, - { header: 'Category', width: 60, x: 250 }, - { header: 'Payer', width: 60, x: 310 }, - { header: 'Amount', width: 60, x: 370 }, - { header: 'Payment', width: 50, x: 430 } + { header: 'Date', width: 65, x: 60 }, + { header: 'Establishment', width: 110, x: 125 }, + { header: 'Category', width: 55, x: 235 }, + { header: 'Payer', width: 50, x: 290 }, + { header: 'Amount', width: 55, x: 340 }, + { header: 'Payment', width: 45, x: 395 } ]; if (options.includeReceiptContents) { - columns.push({ header: 'Description', width: 85, x: 480 }); + columns.push({ header: 'Description', width: 105, x: 440 }); } // Draw table header @@ -404,7 +404,7 @@ async function drawExpenseRows( if (options.includeReceiptContents) { const description = expense.Contents || 'N/A'; - rowData.push(description.length > 30 ? description.substring(0, 27) + '...' : description); + rowData.push(description.length > 40 ? description.substring(0, 37) + '...' : description); } rowData.forEach((data, colIndex) => { @@ -534,30 +534,75 @@ async function fetchReceiptImage(receipt: any): Promise { const client = getMinioClient(); const bucketName = useRuntimeConfig().minio.bucketName; - // Determine the file path - let filePath = receipt.url; - if (!filePath && receipt.directus_files_id?.filename_download) { + // Determine the file path - try multiple possible locations + let filePath = null; + + // Try different receipt data structures + if (receipt.url) { + filePath = receipt.url; + } else if (receipt.directus_files_id?.filename_download) { filePath = receipt.directus_files_id.filename_download; + } else if (receipt.filename_download) { + filePath = receipt.filename_download; + } else if (receipt.id && receipt.filename_disk) { + filePath = receipt.filename_disk; + } else if (typeof receipt === 'string') { + filePath = receipt; } if (!filePath) { - console.log('[expenses/generate-pdf] No file path found for receipt'); + console.log('[expenses/generate-pdf] No file path found for receipt:', JSON.stringify(receipt, null, 2)); return null; } - console.log('[expenses/generate-pdf] Fetching receipt image:', filePath); + console.log('[expenses/generate-pdf] Fetching receipt image from path:', filePath); - // Get the object from MinIO - const dataStream = await client.getObject(bucketName, filePath); + // Remove any URL prefixes if present + if (filePath.includes('/files/')) { + const parts = filePath.split('/files/'); + if (parts.length > 1) { + filePath = parts[parts.length - 1]; + } + } - // Convert stream to buffer - const chunks: Buffer[] = []; + // Ensure we're looking in the right place - sometimes files are in receipts/ folder + const possiblePaths = [ + filePath, + `receipts/${filePath}`, + `expenses/${filePath}`, + filePath.startsWith('receipts/') ? filePath : `receipts/${filePath}` + ]; - return new Promise((resolve, reject) => { - dataStream.on('data', (chunk) => chunks.push(chunk)); - dataStream.on('end', () => resolve(Buffer.concat(chunks))); - dataStream.on('error', reject); - }); + for (const testPath of possiblePaths) { + try { + console.log('[expenses/generate-pdf] Trying path:', testPath); + + // Check if object exists first + await client.statObject(bucketName, testPath); + + // Get the object from MinIO + const dataStream = await client.getObject(bucketName, testPath); + + // Convert stream to buffer + const chunks: Buffer[] = []; + + const imageBuffer = await new Promise((resolve, reject) => { + dataStream.on('data', (chunk) => chunks.push(chunk)); + dataStream.on('end', () => resolve(Buffer.concat(chunks))); + dataStream.on('error', reject); + }); + + console.log('[expenses/generate-pdf] Successfully fetched image from:', testPath, 'Size:', imageBuffer.length); + return imageBuffer; + + } catch (pathError) { + console.log('[expenses/generate-pdf] Path not found:', testPath); + continue; + } + } + + console.log('[expenses/generate-pdf] Could not find image in any of the attempted paths'); + return null; } catch (error) { console.error('[expenses/generate-pdf] Error fetching receipt image:', error);