db = \Config\Database::connect(); $this->model = new OrderTestModel(); $this->patientModel = new PatientModel(); $this->visitModel = new PatVisitModel(); $this->rules = [ 'InternalPID' => 'required|is_natural' ]; } public function index() { $internalPID = $this->request->getVar('InternalPID'); $includeDetails = $this->request->getVar('include') === 'details'; try { if ($internalPID) { $rows = $this->model->getOrdersByPatient($internalPID); } else { $rows = $this->db->table('ordertest') ->where('DelDate', null) ->orderBy('TrnDate', 'DESC') ->get() ->getResultArray(); } $rows = ValueSet::transformLabels($rows, [ 'Priority' => 'order_priority', 'OrderStatus' => 'order_status', ]); if ($includeDetails && !empty($rows)) { foreach ($rows as &$row) { $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']); $row['Tests'] = $this->getOrderTests($row['InternalOID']); } } return $this->respond([ 'status' => 'success', 'message' => 'Data fetched successfully', 'data' => $rows ], 200); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } public function show($orderID = null) { try { $row = $this->model->getOrder($orderID); if (empty($row)) { return $this->respond([ 'status' => 'success', 'message' => 'Data not found.', 'data' => null ], 200); } $row = ValueSet::transformLabels([$row], [ 'Priority' => 'order_priority', 'OrderStatus' => 'order_status', ])[0]; // Include specimens and tests $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']); $row['Tests'] = $this->getOrderTests($row['InternalOID']); return $this->respond([ 'status' => 'success', 'message' => 'Data fetched successfully', 'data' => $row ], 200); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } private function getOrderSpecimens($internalOID) { $specimens = $this->db->table('specimen s') ->select('s.*, cd.ConCode, cd.ConName') ->join('containerdef cd', 'cd.ConDefID = s.ConDefID', 'left') ->where('s.OrderID', $internalOID) ->where('s.EndDate IS NULL') ->get() ->getResultArray(); // Get status for each specimen foreach ($specimens as &$specimen) { $status = $this->db->table('specimenstatus') ->where('SID', $specimen['SID']) ->where('EndDate IS NULL') ->orderBy('CreateDate', 'DESC') ->get() ->getRowArray(); $specimen['Status'] = $status['SpcStatus'] ?? 'PENDING'; } return $specimens; } private function getOrderTests($internalOID) { $tests = $this->db->table('patres pr') ->select('pr.*, tds.TestSiteCode, tds.TestSiteName, tds.TestType, tds.SeqScr AS TestSeqScr, tds.SeqRpt AS TestSeqRpt, tds.DisciplineID, d.DisciplineCode, d.DisciplineName, d.SeqScr AS DisciplineSeqScr, d.SeqRpt AS DisciplineSeqRpt') ->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left') ->join('discipline d', 'd.DisciplineID = tds.DisciplineID', 'left') ->where('pr.OrderID', $internalOID) ->where('pr.DelDate IS NULL') ->orderBy('COALESCE(d.SeqScr, 999999) ASC') ->orderBy('COALESCE(d.SeqRpt, 999999) ASC') ->orderBy('COALESCE(tds.SeqScr, 999999) ASC') ->orderBy('COALESCE(tds.SeqRpt, 999999) ASC') ->orderBy('pr.ResultID ASC') ->get() ->getResultArray(); foreach ($tests as &$test) { $discipline = [ 'DisciplineID' => $test['DisciplineID'] ?? null, 'DisciplineCode' => $test['DisciplineCode'] ?? null, 'DisciplineName' => $test['DisciplineName'] ?? null, 'SeqScr' => $test['DisciplineSeqScr'] ?? null, 'SeqRpt' => $test['DisciplineSeqRpt'] ?? null, ]; $test['Discipline'] = $discipline; $test['SeqScr'] = $test['TestSeqScr'] ?? null; $test['SeqRpt'] = $test['TestSeqRpt'] ?? null; $test['DisciplineID'] = $discipline['DisciplineID']; unset($test['DisciplineCode'], $test['DisciplineName'], $test['DisciplineSeqScr'], $test['DisciplineSeqRpt'], $test['TestSeqScr'], $test['TestSeqRpt']); } unset($test); return $tests; } public function create() { $input = $this->request->getJSON(true); if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); } try { if (!$this->patientModel->find($input['InternalPID'])) { return $this->failValidationErrors(['InternalPID' => 'Patient not found']); } if (!empty($input['PatVisitID'])) { $visit = $this->visitModel->find($input['PatVisitID']); if (!$visit) { return $this->failValidationErrors(['PatVisitID' => 'Visit not found']); } } $orderID = $this->model->createOrder($input); // Fetch complete order details $order = $this->model->getOrder($orderID); $order['Specimens'] = $this->getOrderSpecimens($order['InternalOID']); $order['Tests'] = $this->getOrderTests($order['InternalOID']); // Rule engine triggers are fired at the test/result level (test_created, result_updated) return $this->respondCreated([ 'status' => 'success', 'message' => 'Order created successfully', 'data' => $order ], 201); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } public function update() { $input = $this->request->getJSON(true); if (empty($input['OrderID'])) { return $this->failValidationErrors(['OrderID' => 'OrderID is required']); } try { $order = $this->model->getOrder($input['OrderID']); if (!$order) { return $this->failNotFound('Order not found'); } $updateData = []; if (isset($input['Priority'])) $updateData['Priority'] = $input['Priority']; if (isset($input['OrderStatus'])) $updateData['OrderStatus'] = $input['OrderStatus']; if (isset($input['OrderingProvider'])) $updateData['OrderingProvider'] = $input['OrderingProvider']; if (isset($input['DepartmentID'])) $updateData['DepartmentID'] = $input['DepartmentID']; if (isset($input['WorkstationID'])) $updateData['WorkstationID'] = $input['WorkstationID']; if (!empty($updateData)) { $this->model->update($order['InternalOID'], $updateData); } $updatedOrder = $this->model->getOrder($input['OrderID']); $updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']); $updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']); return $this->respond([ 'status' => 'success', 'message' => 'Order updated successfully', 'data' => $updatedOrder ], 200); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } public function delete() { $input = $this->request->getJSON(true); $orderID = $input['OrderID'] ?? null; if (empty($orderID)) { return $this->failValidationErrors(['OrderID' => 'OrderID is required']); } try { $order = $this->model->getOrder($orderID); if (!$order) { return $this->failNotFound('Order not found'); } $this->model->softDelete($orderID); return $this->respondDeleted([ 'status' => 'success', 'message' => 'Order deleted successfully' ]); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } public function updateStatus() { $input = $this->request->getJSON(true); if (empty($input['OrderID']) || empty($input['OrderStatus'])) { return $this->failValidationErrors(['error' => 'OrderID and OrderStatus are required']); } $validStatuses = ['ORD', 'SCH', 'ANA', 'VER', 'REV', 'REP']; if (!in_array($input['OrderStatus'], $validStatuses)) { return $this->failValidationErrors(['OrderStatus' => 'Invalid status. Valid: ' . implode(', ', $validStatuses)]); } try { $order = $this->model->getOrder($input['OrderID']); if (!$order) { return $this->failNotFound('Order not found'); } $this->model->updateStatus($input['OrderID'], $input['OrderStatus']); $updatedOrder = $this->model->getOrder($input['OrderID']); $updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']); $updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']); return $this->respond([ 'status' => 'success', 'message' => 'Order status updated successfully', 'data' => $updatedOrder ], 200); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } }