import { promisify } from 'node:util' import child_process from 'node:child_process' import { existsSync, mkdirSync } from 'node:fs' import { writeFile } from 'node:fs/promises' import strapiHelper from "../../utils/strapiHelper" // PDF page size detection // A4: 595 x 842 points (210 x 297 mm) // Letter: 612 x 792 points (8.5 x 11 inches) // Small labels are typically under 400 points in either dimension const PAGE_SIZE_THRESHOLDS = { // A4/Letter size PDFs have width around 595-612 points A4_MIN_WIDTH: 500, // Small labels are typically under this width LABEL_MAX_WIDTH: 450, LABEL_MAX_HEIGHT: 450 } // Function to detect PDF page size using pdfinfo command const detectPdfPageSize = async (filePath: string): Promise<{ width: number; height: number; isSmall: boolean }> => { const exec = promisify(child_process.exec) try { // Use pdfinfo to get page dimensions const { stdout } = await exec(`pdfinfo "${filePath}" 2>/dev/null | grep -i "Page size"`) // Parse output like "Page size: 595.276 x 841.89 pts (A4)" const match = stdout.match(/Page size:\s+([\d.]+)\s*x\s*([\d.]+)/) if (match) { const width = parseFloat(match[1]) const height = parseFloat(match[2]) // Determine if it's a small label-size PDF const isSmall = width < PAGE_SIZE_THRESHOLDS.A4_MIN_WIDTH || (width < PAGE_SIZE_THRESHOLDS.LABEL_MAX_WIDTH && height < PAGE_SIZE_THRESHOLDS.LABEL_MAX_HEIGHT) return { width, height, isSmall } } } catch (err) { console.log('[PDF Size Detection] pdfinfo failed, trying alternative method') } // Fallback: Try using pdftk or gs if pdfinfo fails try { const { stdout } = await exec(`gs -q -dNODISPLAY -c "(${filePath}) (r) file runpdfbegin 1 pdfgetpage /MediaBox get == quit" 2>/dev/null`) // Parse MediaBox output like [0 0 595.276 841.89] const match = stdout.match(/\[[\d.\s]+\s+([\d.]+)\s+([\d.]+)\]/) if (match) { const width = parseFloat(match[1]) const height = parseFloat(match[2]) const isSmall = width < PAGE_SIZE_THRESHOLDS.A4_MIN_WIDTH return { width, height, isSmall } } } catch (err) { console.log('[PDF Size Detection] Ghostscript method failed') } // Default to A4 if detection fails return { width: 595, height: 842, isSmall: false } } export default defineEventHandler(async (event) => { let data: any = { printed: [], status: 200, message: '' } const body = await readBody(event) const exec = promisify(child_process.exec) const config = useRuntimeConfig() const orderId = body.orderId const labelPrinter = body.labelPrinter || 'labelprinter-1' const defaultPrinter = 'default' // CUPS printer name for A4/Letter PDFs if (!orderId) { return { printed: [], status: 400, message: 'Order ID is required' } } console.log(`[Order Attachment Print] Starting for order ID: ${orderId}, Label printer: ${labelPrinter}`) try { // Step 1: Get the Strapi attachment record for this order (AD_Table_ID 259 = C_Order) const attachmentRecordResponse: any = await strapiHelper( event, `ad-attachments?filters[AD_Table_ID][$eq]=259&filters[Record_ID][$eq]=${orderId}`, 'GET', null ) console.log(`[Order Attachment Print] Step 1 - Attachment record response for order ${orderId}:`, JSON.stringify(attachmentRecordResponse?.data?.[0] || 'No record')) if (!attachmentRecordResponse?.data?.[0]?.documentId) { console.log(`[Order Attachment Print] No attachment record found for order ${orderId}`) return { printed: [], status: 200, message: 'No attachments found for this order' } } const strapiDocumentId = attachmentRecordResponse.data[0].documentId // Step 2: Get the actual attachment files using the documentId const filesResponse: any = await strapiHelper( event, `ad-attachments/${strapiDocumentId}?populate=attachment`, 'GET', null ) console.log(`[Order Attachment Print] Step 2 - Files response for documentId ${strapiDocumentId}:`, JSON.stringify(filesResponse?.data?.attachment?.length || 0, null, 2)) const files = filesResponse?.data?.attachment || [] // Filter only PDF files const pdfFiles = files.filter((file: any) => file.mime === 'application/pdf') console.log(`[Order Attachment Print] Found ${files.length} total files, ${pdfFiles.length} PDF files for order ${orderId}`) if (pdfFiles.length === 0) { console.log(`[Order Attachment Print] No PDF attachments found for order ${orderId}`) return { printed: [], status: 200, message: 'No PDF attachments found' } } const pathName = `order-attachments/${new Date().getFullYear()}` const filePath = `/root/storage/${pathName}` // Ensure directory exists if (!existsSync(filePath)) { mkdirSync(filePath, { recursive: true }) } for (const pdfFile of pdfFiles) { try { // Download the PDF file from Strapi // Try multiple URL patterns: direct url, files-api with hash, or strapiupload base let pdfUrl = '' // Log available file properties for debugging console.log(`[Order Attachment Print] File properties:`, JSON.stringify({ name: pdfFile.name, hash: pdfFile.hash, ext: pdfFile.ext, url: pdfFile.url, mime: pdfFile.mime })) // Use strapiupload config (direct Strapi URL) with files-api endpoint const strapiBase = config.api.strapiupload || 'http://127.0.0.1:1337' pdfUrl = `${strapiBase}/files-api/${pdfFile.hash}${pdfFile.ext}` console.log(`[Order Attachment Print] Downloading file from: ${pdfUrl}`) const pdfResponse = await $fetch(pdfUrl, { responseType: 'arrayBuffer' }) const pdfBuffer = Buffer.from(pdfResponse as ArrayBuffer) const fileName = `${Date.now()}-${pdfFile.name}` const fullFilePath = `${filePath}/${fileName}` // Save the PDF temporarily await writeFile(fullFilePath, pdfBuffer) // Detect PDF size const pageSize = await detectPdfPageSize(fullFilePath) // Determine which printer to use based on PDF size const printerToUse = pageSize.isSmall ? labelPrinter : defaultPrinter const printOptions = pageSize.isSmall ? '' : '-o sides=one-sided' console.log(`[Order Attachment Print] File: ${pdfFile.name}, Size: ${pageSize.width}x${pageSize.height}, Small: ${pageSize.isSmall}, Printer: ${printerToUse}`) // Print the PDF const printCommand = `lp -d ${printerToUse} ${printOptions} "${fullFilePath}"` console.log(`[Order Attachment Print] Executing: ${printCommand}`) const { stdout, stderr } = await exec(printCommand) console.log(`[Order Attachment Print] Print result - stdout: ${stdout}, stderr: ${stderr}`) // lp command returns success if stdout contains "request id" const printSuccess = stdout && stdout.includes('request id') data.printed.push({ fileName: pdfFile.name, fileId: pdfFile.id, printer: printerToUse, pageSize: { width: pageSize.width, height: pageSize.height, isSmall: pageSize.isSmall }, success: printSuccess, stdout: stdout, stderr: stderr }) } catch (fileErr: any) { console.error(`[Order Attachment Print] Error printing file ${pdfFile.name}:`, fileErr) data.printed.push({ fileName: pdfFile.name, fileId: pdfFile.id, success: false, error: fileErr.message || 'Unknown error' }) } } data.message = `Processed ${data.printed.length} PDF attachment(s)` } catch (err: any) { console.error('[Order Attachment Print] Error:', err) data = { printed: [], status: err.status || err.statusCode || 500, message: err.detail || err.message || err.statusMessage || 'Error printing attachments' } } return data })