request->getGet('date1') ?: $today); $date2 = (string) ($this->request->getGet('date2') ?: $today); $userroleid = (int) session()->get('userroleid'); $page = max(1, (int) ($this->request->getGet('page') ?? 1)); $pageSize = (int) ($this->request->getGet('pageSize') ?? 50); $pageSize = max(1, min(self::MAX_PAGE_SIZE, $pageSize)); $offset = ($page - 1) * $pageSize; $sortCol = (string) ($this->request->getGet('sortCol') ?? 'REQDATE'); $sortDirRaw = strtoupper((string) ($this->request->getGet('sortDir') ?? 'DESC')); $sortDir = $sortDirRaw === 'ASC' ? 'ASC' : 'DESC'; $sortSql = $this->resolveSortColumn($sortCol); $filterKey = (string) ($this->request->getGet('filterKey') ?? 'Total'); $search = trim((string) ($this->request->getGet('search') ?? '')); [$baseWhereSql, $baseParams] = $this->buildBaseWhereClause($date1, $date2, $userroleid); [$whereSql, $whereParams] = $this->buildDashboardWhereClause($baseWhereSql, $baseParams, $filterKey, $search); $rowsSql = "SELECT d.REQDATE, d.[Name], d.SP_ACCESSNUMBER, d.HOSTORDERNUMBER, d.REFF, d.DOC, d.TESTS, d.ODR_CRESULT_TO, d.STATS, d.COLLECTIONDATE, d.[Name] AS PATNAME, CAST(NULL AS VARCHAR(32)) AS PATNUMBER, r.VAL1USER, r.VAL2USER, r.ISPENDING, r.REPORT_LANG, r.ISPDF FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER WHERE {$whereSql} ORDER BY {$sortSql} {$sortDir} OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; $rowsParams = [...$whereParams, $offset, $pageSize]; $rows = $db->query($rowsSql, $rowsParams)->getResultArray(); $countSql = "SELECT COUNT(1) AS total FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER WHERE {$whereSql}"; $countRow = $db->query($countSql, $whereParams)->getRowArray(); $totalRows = (int) ($countRow['total'] ?? 0); $counterSql = "SELECT SUM(CASE WHEN d.STATS = 'Pend' THEN 1 ELSE 0 END) AS Pend, SUM(CASE WHEN d.STATS IN ('Coll', 'PartColl') THEN 1 ELSE 0 END) AS Coll, SUM(CASE WHEN d.STATS IN ('Recv', 'PartRecv') THEN 1 ELSE 0 END) AS Recv, SUM(CASE WHEN d.STATS = 'Inc' THEN 1 ELSE 0 END) AS Inc, SUM(CASE WHEN d.STATS = 'Fin' THEN 1 ELSE 0 END) AS Fin, COUNT(1) AS Total, SUM(CASE WHEN r.VAL1USER IS NOT NULL AND r.VAL2USER IS NOT NULL AND ISNULL(r.ISPENDING, 0) <> 1 THEN 1 ELSE 0 END) AS Validated FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER = d.SP_ACCESSNUMBER WHERE {$baseWhereSql}"; $counterRow = $db->query($counterSql, $baseParams)->getRowArray() ?? []; foreach ($rows as &$row) { $row['COLLECTIONDATE'] = date('Y-m-d H:i', strtotime($row['COLLECTIONDATE'])); $row['REQDATE'] = date('Y-m-d H:i', strtotime($row['REQDATE'])); $this->normalizeTelephoneFields($row); } $data = [ 'data' => $rows, 'pagination' => [ 'page' => $page, 'pageSize' => $pageSize, 'totalRows' => $totalRows, 'totalPages' => max(1, (int) ceil($totalRows / $pageSize)), ], 'counters' => [ 'Pend' => (int) ($counterRow['Pend'] ?? 0), 'Coll' => (int) ($counterRow['Coll'] ?? 0), 'Recv' => (int) ($counterRow['Recv'] ?? 0), 'Inc' => (int) ($counterRow['Inc'] ?? 0), 'Fin' => (int) ($counterRow['Fin'] ?? 0), 'Total' => (int) ($counterRow['Total'] ?? 0), ], 'validatedCount' => (int) ($counterRow['Validated'] ?? 0), ]; return $this->response->setJSON($data); } private function buildBaseWhereClause(string $date1, string $date2, int $userroleid): array { $where = [ 'd.COLLECTIONDATE BETWEEN ? AND ?', 'd.ODR_DDATE BETWEEN ? AND ?', ]; $params = [ $date1 . ' 00:00', $date2 . ' 23:59', $date1 . ' 00:00', $date2 . ' 23:59', ]; if ($userroleid === 2) { $where[] = "(d.TESTS IS NOT NULL AND d.TESTS LIKE '%[A-Za-z]%')"; } return [implode(' AND ', $where), $params]; } private function buildDashboardWhereClause(string $baseWhereSql, array $baseParams, string $filterKey, string $search): array { $where = [$baseWhereSql]; $params = $baseParams; $statusClauses = [ 'Pend' => "d.STATS = 'Pend'", 'Coll' => "d.STATS IN ('Coll', 'PartColl')", 'Recv' => "d.STATS IN ('Recv', 'PartRecv')", 'Inc' => "d.STATS = 'Inc'", 'Fin' => "d.STATS = 'Fin'", 'Validated' => 'r.VAL1USER IS NOT NULL AND r.VAL2USER IS NOT NULL AND ISNULL(r.ISPENDING, 0) <> 1', ]; if (isset($statusClauses[$filterKey])) { $where[] = $statusClauses[$filterKey]; } if ($search !== '') { $where[] = '(d.SP_ACCESSNUMBER LIKE ? OR d.HOSTORDERNUMBER LIKE ? OR d.[Name] LIKE ? OR d.REFF LIKE ? OR d.DOC LIKE ? OR d.TESTS LIKE ? OR d.ODR_CRESULT_TO LIKE ?)'; $like = '%' . $search . '%'; $params = [...$params, $like, $like, $like, $like, $like, $like, $like]; } return [implode(' AND ', $where), $params]; } private function resolveSortColumn(string $sortCol): string { $map = [ 'REQDATE' => 'd.REQDATE', 'Name' => 'd.[Name]', 'SP_ACCESSNUMBER' => 'd.SP_ACCESSNUMBER', 'HOSTORDERNUMBER' => 'd.HOSTORDERNUMBER', 'REFF' => 'd.REFF', 'DOC' => 'd.DOC', 'STATS' => 'd.STATS', ]; return $map[$sortCol] ?? 'd.REQDATE'; } public function show($accessnumber) { $db = \Config\Database::connect(); $data['accessnumber'] = $accessnumber; $sql = "SELECT d.STATS, r.* FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d left join GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER WHERE d.SP_ACCESSNUMBER='$accessnumber'"; $result = $db ->query($sql) ->getResultArray(); $data['val1'] = $result[0]['ISVAL1']; $data['val1user'] = $result[0]['VAL1USER']; $data['val2'] = $result[0]['ISVAL2']; $data['val2user'] = $result[0]['VAL2USER']; return view('admin/modal_request', $data); } public function showUnval($accessnumber) { $data['accessnumber'] = $accessnumber; return view('admin/modal_unvalidate', $data); } public function unval($accessnumber) { $input = $this->request->getJSON(true); $userid = session('userid'); $comment = $input['comment']; $db = \Config\Database::connect(); $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=null, VAL1USER=null, VAL1DATE=null, ISVAL2=null, VAL2USER=null, VAL2DATE=null, ISPENDING=1, PENDINGTEXT='$comment', PENDINGUSER='$userid', PENDINGDATE=GETDATE() where ACCESSNUMBER='$accessnumber'"; $db->query($sql); $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT, REASON) VALUES (?, 'UNVAL', ?, GETDATE(), ?)"; $db->query($logAudit, [$accessnumber, $userid, $comment]); $data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber"]; return $this->response->setJSON($data); } public function val($accessnumber) { $input = $this->request->getJSON(true); // Securely get userid from session $userid = session('userid'); $db = \Config\Database::connect(); $sql = "select * from GDC_CMOD.dbo.CM_REQUESTS where ACCESSNUMBER='$accessnumber'"; $result = $db->query($sql)->getResultArray(); if (!isset($result[0])) { $sql = "insert into GDC_CMOD.dbo.CM_REQUESTS(ACCESSNUMBER, ISVAL1, VAL1USER, VAL1DATE) VALUES ('$accessnumber', 1, '$userid', GETDATE())"; $db->query($sql); $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())"; $db->query($logAudit, [$accessnumber, $userid]); $data['val'] = 1; $data['userid'] = $userid; } else { $row = $result[0]; $isval1 = $row['ISVAL1']; $isval2 = $row['ISVAL2']; $val1user = $row['VAL1USER']; if ($isval1 == 1) { if ($isval2 == 1) { return $this->response->setJSON(['message' => 'validation done, not updating anything']); } else { if ($val1user != $userid) { $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL2=1, VAL2USER='$userid', VAL2DATE=GETDATE() where ACCESSNUMBER='$accessnumber'"; $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL2', ?, GETDATE())"; $db->query($logAudit, [$accessnumber, $userid]); $data['val'] = 2; $data['userid'] = $userid; } else { $this->response->setStatusCode(500); return $this->response->setJSON(['message' => 'user already validate this request']); } } } else { $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=1, VAL1USER='$userid', VAL1DATE=GETDATE() where ACCESSNUMBER='$accessnumber'"; $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())"; $db->query($logAudit, [$accessnumber, $userid]); $data['val'] = 1; $data['userid'] = $userid; } $db->query($sql); } return $this->response->setJSON($data); } private function normalizeTelephoneFields(array &$row): void { foreach (['TELEPHON', 'TELEPHONE'] as $field) { if (isset($row[$field]) && is_string($row[$field])) { $row[$field] = $this->ensureUtf8($row[$field]); } } } private function ensureUtf8(string $value): string { if (mb_check_encoding($value, 'UTF-8')) { return $value; } $encoding = mb_detect_encoding($value, ['UTF-8', 'CP1252', 'ISO-8859-1'], true); return $encoding ? mb_convert_encoding($value, 'UTF-8', $encoding) : mb_convert_encoding($value, 'UTF-8', 'CP1252'); } public function setEngLanguage($accessnumber) { $userid = session('userid'); $db = \Config\Database::connect(); // Set REPORT_LANG to 1 (English) $sql = "UPDATE GDC_CMOD.dbo.CM_REQUESTS SET REPORT_LANG=1 WHERE ACCESSNUMBER='$accessnumber'"; $db->query($sql); // Log the action $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'SET_ENG', ?, GETDATE())"; $db->query($logAudit, [$accessnumber, $userid]); // Auto-generate English PDF $pdfResult = $this->generateEngPdf($accessnumber); return $this->response->setJSON([ 'status' => 'success', 'message' => 'English result created', 'pdf' => $pdfResult ]); } private function generateEngPdf(string $accessnumber): array { $db = \Config\Database::connect(); $reportHelper = new \App\Libraries\ReportHelper($db); $data = $reportHelper->getReportData($accessnumber, 1); $data['eng'] = 1; $data['accessnumber'] = $accessnumber; $data['ispdf'] = 1; $html = view('report/template', $data); $filename = $accessnumber . '_eng.pdf'; // Post to spooler $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://glenlis:3000/api/pdf/generate'); curl_setopt($ch, CURLOPT_POST, 1); $payload = [ 'html' => $html, 'filename' => $filename, 'accessnumber' => $accessnumber ]; if (!empty($data['collectionDate'])) { $payload['collectionDate'] = $data['collectionDate']; } curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); 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', "PDF spooler returned HTTP $httpCode for ENG result $accessnumber"); return ['success' => false, 'error' => 'Failed to queue PDF generation']; } $responseData = json_decode($response, true); // Log PDF generation $stepType = 'ENG_PDF'; $stepStatus = 'English'; $sqlLog = "INSERT INTO GDC_CMOD.dbo.AUDIT_REQUESTS(ACCESSNUMBER, STEPDATE, STEPTYPE, STEPSTATUS) VALUES (?, GETDATE(), ?, ?)"; $db->query($sqlLog, [(string)$accessnumber, $stepType, $stepStatus]); return [ 'success' => true, 'jobId' => $responseData['jobId'] ?? null, 'message' => 'English PDF queued for generation' ]; } public function setPdfFlag(string $accessnumber): \CodeIgniter\HTTP\ResponseInterface { $db = \Config\Database::connect(); $sql = "UPDATE GDC_CMOD.dbo.CM_REQUESTS SET ISPDF = 1 WHERE ACCESSNUMBER = ?"; $db->query($sql, [$accessnumber]); $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'PDF_FLAG', 'SYSTEM', GETDATE())"; $db->query($logAudit, [$accessnumber]); return $this->response->setJSON([ 'status' => 'success', 'accessnumber' => $accessnumber ]); } }