beginTransaction(); // 1. Fetch Invoice $stmt = $db->prepare("SELECT * FROM invoices WHERE id = ? FOR UPDATE"); $stmt->execute([$id]); $invoice = $stmt->fetch(); if (!$invoice) { json_error('Invoice not found', 404); } if ($invoice['status'] === 'approved') { json_error('Invoice is already approved', 400); } // Authorization if ($decoded['role'] !== 'super_admin' && $invoice['tenant_id'] !== $decoded['tenant_id']) { json_error('Unauthorized', 403); } // 2. Fetch Line Items $stmtLines = $db->prepare("SELECT * FROM invoice_lines WHERE invoice_id = ?"); $stmtLines->execute([$id]); $invoice['items'] = $stmtLines->fetchAll(); // 3. Decrypt Sensitive Data for XML Generation $invoice['supplier_name'] = \App\Core\Encryption::decrypt($invoice['supplier_name']) ?: ''; $invoice['supplier_tin'] = \App\Core\Encryption::decrypt($invoice['supplier_tin']) ?: ''; $invoice['buyer_name'] = \App\Core\Encryption::decrypt($invoice['buyer_name']) ?: ''; $invoice['buyer_tin'] = \App\Core\Encryption::decrypt($invoice['buyer_tin']) ?: ''; // 4. Initialize JoFotara Core $jofotara = new JoFotara(); // 5. Generate TLV QR Code Base64 $qrBase64 = $jofotara->generateQRCode($invoice); // 6. Generate UBL 2.1 XML $xmlContent = $jofotara->generateXML($invoice); // 7. Submit to JoFotara API (Simulation for now) $apiResponse = $jofotara->submitInvoice($xmlContent); if (!$apiResponse['success']) { throw new \Exception("JoFotara Rejection: " . ($apiResponse['error'] ?? 'Unknown Error')); } // 8. Update Invoice Status & Save JoFotara UUID/QR $updateStmt = $db->prepare(" UPDATE invoices SET status = 'approved', jofotara_uuid = ?, qr_code = ?, updated_at = NOW() WHERE id = ? "); $updateStmt->execute([$apiResponse['uuid'] ?? 'mock-uuid', $qrBase64, $id]); $db->commit(); json_success([ 'message' => 'Invoice approved and submitted to JoFotara successfully.', 'jofotara_uuid' => $apiResponse['uuid'] ?? 'mock-uuid', 'qr_code' => $qrBase64 ]); } catch (\Exception $e) { $db->rollBack(); error_log("JoFotara Approve Error: " . $e->getMessage()); json_error('Failed to approve invoice: ' . $e->getMessage(), 500); }