diff --git a/.gitignore b/.gitignore index bcdad06..cdde22a 100644 --- a/.gitignore +++ b/.gitignore @@ -126,4 +126,11 @@ _modules/* /phpunit*.xml .claude/ -.serena/ \ No newline at end of file +.serena/ + +#------------------------- +# PDF Spooler Data +#------------------------- +node_spooler/data/ +node_spooler/node_modules/ +node_spooler/logs/ \ No newline at end of file diff --git a/TODO.md b/TODO.md index 0eddb22..2983151 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,8 @@ # Project Checklist: Glen RME & Lab Management System -**Last Updated:** 20260202 +**Last Updated:** 20260203 Pending: -- Restrict Print/Save-to-PDF to CS Role only (Lab can only preview, CS can print/save) -- Add Dedicated Print Button (Trigger browser/system print dialog) - Reprint Label (Add functionality to reprint labels) - Print Result Audit (Track when result reports are printed/exported, log user and timestamp) @@ -29,7 +27,8 @@ Completed: - 18 : Create Validate Page - 19 : Sync color with old gdc_cmod - 20 : Add Val1 Val2 on the result - +- 21 : Show Print / PDF button when val1 val2 done +- 22 : Restrict Print/Save-to-PDF to CS Role only (Admin, Lab, CS can print/save) Addition on dev : - adding init-isDev on index.php to set default date on dev dashboard \ No newline at end of file diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 3195bf9..948eb50 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -98,7 +98,11 @@ $routes->group('report', ['filter' => 'role:0,1,2,4'], function ($routes) { $routes->get('(:num)/eng', 'ReportController::generate/$1/1'); $routes->get('(:num)/print', 'ReportController::print/$1'); $routes->get('(:num)/print/eng', 'ReportController::print/$1/1'); + $routes->get('(:num)/preview', 'ReportController::preview/$1'); + $routes->get('(:num)/pdf', 'ReportController::generatePdf/$1'); }); +$routes->get('report/status/(:any)', 'ReportController::checkPdfStatus/$1'); + // Keep backward compatibility - updated filter $routes->get('print/(:num)', 'ReportController::generate/$1', ['filter' => 'role:0,1,2,3,4']); diff --git a/app/Controllers/ReportController.php b/app/Controllers/ReportController.php index c84e3fd..f858b8f 100644 --- a/app/Controllers/ReportController.php +++ b/app/Controllers/ReportController.php @@ -58,4 +58,93 @@ class ReportController extends BaseController VALUES(?, GETDATE(), 'PRINT', ?)"; $this->db->query($sql, [$accessnumber, $status]); } + + public function preview($accessnumber) + { + $eng = $this->request->getVar('eng') ?? 0; + return $this->renderReport($accessnumber, $eng, 0, false); + } + + public function generatePdf($accessnumber) + { + $userroleid = session()->get('userroleid'); + if (!in_array($userroleid, [0, 1, 2, 4])) { + return $this->response->setStatusCode(403)->setJSON(['success' => false, 'error' => 'Unauthorized']); + } + + $eng = $this->request->getVar('eng') ?? 0; + $data = $this->reportHelper->getReportData($accessnumber, $eng); + $data['eng'] = $eng; + $data['accessnumber'] = $accessnumber; + $data['ispdf'] = 1; + + $html = view('report/template', $data); + $filename = $accessnumber . '.pdf'; + + try { + $jobId = $this->postToSpooler($html, $filename); + return $this->response->setJSON([ + 'success' => true, + 'jobId' => $jobId, + 'message' => 'PDF queued for generation', + 'status' => 'queued' + ]); + } catch (\Exception $e) { + log_message('error', "PDF generation failed: " . $e->getMessage()); + return $this->response->setStatusCode(500)->setJSON([ + 'success' => false, + 'error' => 'Failed to queue PDF generation' + ]); + } + } + + public function checkPdfStatus($jobId) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://glenlis:3030/api/pdf/status/$jobId"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode !== 200) { + log_message('error', "Spooler status check returned HTTP $httpCode"); + return $this->response->setStatusCode(500)->setJSON([ + 'success' => false, + 'error' => 'Failed to check job status' + ]); + } + + return $this->response->setJSON($response); + } + + private function postToSpooler($html, $filename) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, 'http://glenlis:3030/api/pdf/generate'); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ + 'html' => $html, + 'filename' => $filename + ])); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json' + ]); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode !== 200) { + log_message('error', "Spooler API returned HTTP $httpCode"); + throw new \Exception('Failed to queue PDF generation'); + } + + $data = json_decode($response, true); + return $data['jobId']; + } } diff --git a/app/Views/shared/content_requests.php b/app/Views/shared/content_requests.php index 4c90511..3241621 100644 --- a/app/Views/shared/content_requests.php +++ b/app/Views/shared/content_requests.php @@ -189,7 +189,8 @@ ResTo Val Result - + + @@ -197,10 +198,8 @@ - - + + @@ -227,10 +226,20 @@ -