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) { return $this->db->table('patres pr') ->select('pr.*, tds.TestSiteCode, tds.TestSiteName') ->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left') ->where('pr.OrderID', $internalOID) ->where('pr.DelDate IS NULL') ->get() ->getResultArray(); } 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']); // Run common rules for ORDER_CREATED (non-blocking) try { $ruleEngine = new RuleEngineService(); $ruleEngine->run('ORDER_CREATED', [ 'order' => $order, 'tests' => $order['Tests'], 'input' => $input, ]); // Refresh tests in case rules updated results $order['Tests'] = $this->getOrderTests($order['InternalOID']); } catch (\Throwable $e) { log_message('error', 'OrderTestController::create rule engine error: ' . $e->getMessage()); } 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()); } } }