prepare(" SELECT i.*, c.name as company_name FROM invoices i LEFT JOIN companies c ON i.company_id = c.id WHERE i.id = ? "); $stmt->execute([$id]); $invoice = $stmt->fetch(); if (!$invoice) { json_error('Invoice not found', 404); } // 3. Authorization Check if ($decoded['role'] !== 'super_admin') { if ($invoice['tenant_id'] !== $decoded['tenant_id']) { json_error('Unauthorized access to this invoice', 403); } } // 4. Fetch Line Items $stmtLines = $db->prepare("SELECT * FROM invoice_lines WHERE invoice_id = ? ORDER BY line_number ASC"); $stmtLines->execute([$id]); $invoice['items'] = $stmtLines->fetchAll(); // 5. Decrypt Fields $invoice['supplier_tin'] = Encryption::decrypt($invoice['supplier_tin'] ?? '') ?: $invoice['supplier_tin']; $invoice['supplier_name'] = Encryption::decrypt($invoice['supplier_name'] ?? '') ?: $invoice['supplier_name']; $invoice['supplier_address'] = Encryption::decrypt($invoice['supplier_address'] ?? '') ?: $invoice['supplier_address']; $invoice['buyer_tin'] = Encryption::decrypt($invoice['buyer_tin'] ?? '') ?: $invoice['buyer_tin']; $invoice['buyer_name'] = Encryption::decrypt($invoice['buyer_name'] ?? '') ?: $invoice['buyer_name']; $invoice['buyer_national_id'] = Encryption::decrypt($invoice['buyer_national_id'] ?? '') ?: $invoice['buyer_national_id']; if (!empty($invoice['company_name'])) { $invoice['company_name'] = Encryption::decrypt($invoice['company_name']) ?: $invoice['company_name']; } // 6. Generate Public URL for File (Assuming storage is symlinked or served) // For now, let's just return the relative path or a proxy route // We'll add a proxy route later if needed. $invoice['file_url'] = '/index.php?route=v1/invoices/file&id=' . $invoice['id']; json_success($invoice); } catch (\Exception $e) { json_error('Error fetching invoice: ' . $e->getMessage(), 500); }