gdc_cmod/app/Controllers/ReportController.php
mahdahar cfb81201a2 feat: Implement configurable printer system and enhance UAT workflow
Add comprehensive printer configuration support:
- New Printers.php config with role-based printer defaults (lab, phlebo, reception)
- Update LabelController for configurable printer routing with error handling
- Add ResponseTrait for proper JSON responses (success/error status)
- Update routes to accept optional printer parameter for label printing
- Add default printer configuration per role in shared config

Enhance report generation workflow:
- Support REPORT_LANG from CM_REQUESTS table for language preference
- Prioritize URL parameter, then database value, then default
- Add language info to PDF generation response (Indonesian/English)
- Update all report methods (view, eng, preview, generate) with unified logic

Improve UI and user experience:
- Add dialog_results_generate to all role dashboards (superuser, admin, lab, phlebo, cs)
- Update skeleton loading states widths in content requests
- Add printer selection capability in sample collection flow

Add comprehensive UAT documentation:
- New UAT_GDC_CMOD_Checklist.md with 150+ test cases
- Cover all roles: superuser, admin, lab, phlebo, cs, and cross-role scenarios
- Include acceptance criteria (functional, security, performance, usability, data integrity)
- Test categories: authentication, user management, validation, sample management, audit trail, reporting
- Detailed sign-off structure for stakeholders

Add barcode printing documentation:
- docs/barcode_print_all.php - all labels printing implementation
- docs/barcode_print_coll.php - collection label implementation
- docs/barcode_print_disp.php - dispatch label implementation

Update TODO tracking:
- Mark Reprint Label and PDF Generation as completed
- Update pending tasks for testing and audit trails
2026-02-05 06:21:08 +07:00

184 lines
6.3 KiB
PHP

<?php
namespace App\Controllers;
use App\Controllers\BaseController;
class ReportController extends BaseController
{
protected $db;
protected $reportHelper;
public function __construct()
{
$this->db = \Config\Database::connect();
$this->reportHelper = new \App\Libraries\ReportHelper($this->db);
helper(['url', 'text']);
}
public function generate($accessnumber, $eng = 0, $ispdf = 0)
{
if ($ispdf == 0) {
$ispdf = $this->request->getVar('ispdf') ?? 0;
}
if ($eng == 0) {
// Read REPORT_LANG from CM_REQUESTS if not provided
$sql = "SELECT REPORT_LANG FROM GDC_CMOD.dbo.CM_REQUESTS WHERE ACCESSNUMBER=?";
$row = $this->db->query($sql, [$accessnumber])->getRowArray();
$eng = $row['REPORT_LANG'] ?? 0;
}
return $this->renderReport($accessnumber, $eng, $ispdf, false);
}
public function print($accessnumber, $eng = 0, $ispdf = 0)
{
if ($ispdf == 0) {
$ispdf = $this->request->getVar('ispdf') ?? 0;
}
if ($eng == 0) {
// Read REPORT_LANG from CM_REQUESTS if not provided
$sql = "SELECT REPORT_LANG FROM GDC_CMOD.dbo.CM_REQUESTS WHERE ACCESSNUMBER=?";
$row = $this->db->query($sql, [$accessnumber])->getRowArray();
$eng = $row['REPORT_LANG'] ?? 0;
}
return $this->renderReport($accessnumber, $eng, $ispdf, true);
}
private function renderReport($accessnumber, $eng, $ispdf, $shouldLog)
{
$userroleid = session()->get('userroleid');
if (!in_array($userroleid, [0, 1, 2, 4])) {
return $this->response->setStatusCode(403)->setJSON(['message' => 'Unauthorized']);
}
$data = $this->reportHelper->getReportData($accessnumber, $eng);
$data['eng'] = $eng;
$data['accessnumber'] = $accessnumber;
$data['ispdf'] = $ispdf;
if ($shouldLog == true) {
$this->logPrintAudit($accessnumber, $data['status']);
}
return view('report/template', $data);
}
private function logPrintAudit($accessnumber, $status)
{
$sql = "INSERT INTO GDC_CMOD.dbo.AUDIT_REQUESTS(ACCESSNUMBER, STEPDATE, STEPTYPE, STEPSTATUS)
VALUES(?, GETDATE(), 'PRINT', ?)";
$this->db->query($sql, [$accessnumber, $status]);
}
public function preview($accessnumber)
{
$eng = $this->request->getVar('eng') ?? 0;
// If eng not provided, read REPORT_LANG from CM_REQUESTS
if ($eng == 0) {
$sql = "SELECT REPORT_LANG FROM GDC_CMOD.dbo.CM_REQUESTS WHERE ACCESSNUMBER=?";
$row = $this->db->query($sql, [$accessnumber])->getRowArray();
$eng = $row['REPORT_LANG'] ?? 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']);
}
// Get language: URL parameter > REPORT_LANG > default (0)
$engParam = $this->request->getVar('eng') ?? null;
if ($engParam !== null) {
$eng = (int) $engParam;
} else {
// Read REPORT_LANG from CM_REQUESTS
$sql = "SELECT REPORT_LANG FROM GDC_CMOD.dbo.CM_REQUESTS WHERE ACCESSNUMBER=?";
$row = $this->db->query($sql, [$accessnumber])->getRowArray();
$eng = (int) ($row['REPORT_LANG'] ?? 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',
'lang' => $eng == 1 ? 'English' : 'Indonesian'
]);
} 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:3000/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:3000/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'];
}
}