find($refNumID); if (!$ref) { return null; } // Get patient info from order $orderModel = new OrderTestModel(); $order = $orderModel->find($orderID); if (!$order) { return null; } $patientModel = new PatientModel(); $patient = $patientModel->find($order['InternalPID']); if (!$patient) { return null; } // Check if patient matches criteria (sex) if (!empty($ref['Sex']) && $ref['Sex'] !== 'ALL') { if ($patient['Sex'] !== $ref['Sex']) { return null; } } // Check age criteria if ($ref['AgeStart'] !== null || $ref['AgeEnd'] !== null) { $birthdate = new \DateTime($patient['Birthdate']); $today = new \DateTime(); $age = $birthdate->diff($today)->y; if ($ref['AgeStart'] !== null && $age < $ref['AgeStart']) { return null; } if ($ref['AgeEnd'] !== null && $age > $ref['AgeEnd']) { return null; } } $value = floatval($resultValue); $low = floatval($ref['Low']); $high = floatval($ref['High']); // Check low if ($ref['LowSign'] === '<=' && $value <= $low) { return 'L'; } if ($ref['LowSign'] === '<' && $value < $low) { return 'L'; } // Check high if ($ref['HighSign'] === '>=' && $value >= $high) { return 'H'; } if ($ref['HighSign'] === '>' && $value > $high) { return 'H'; } return null; // Normal } /** * Get all results for an order with test names and reference ranges * * @param int $orderID * @return array */ public function getByOrder(int $orderID): array { $builder = $this->db->table('patres pr'); $builder->select(' pr.ResultID, pr.OrderID, pr.TestSiteID, pr.TestSiteCode, pr.Result, pr.ResultDateTime, pr.RefNumID, pr.RefTxtID, pr.CreateDate, tds.TestSiteName, tds.Unit1, tds.Unit2, rn.Low, rn.High, rn.LowSign, rn.HighSign, rn.Display as RefDisplay '); $builder->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left'); $builder->join('refnum rn', 'rn.RefNumID = pr.RefNumID', 'left'); $builder->where('pr.OrderID', $orderID); $builder->where('pr.DelDate', null); $builder->orderBy('tds.SeqScr', 'ASC'); return $builder->get()->getResultArray(); } /** * Get cumulative patient results across all orders * * @param int $internalPID * @return array */ public function getByPatient(int $internalPID): array { $builder = $this->db->table('patres pr'); $builder->select(' pr.ResultID, pr.OrderID, pr.TestSiteID, pr.TestSiteCode, pr.Result, pr.ResultDateTime, pr.RefNumID, tds.TestSiteName, tds.Unit1, tds.Unit2, ot.OrderID as OrderNumber, ot.TrnDate as OrderDate '); $builder->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left'); $builder->join('ordertest ot', 'ot.InternalOID = pr.OrderID', 'left'); $builder->where('ot.InternalPID', $internalPID); $builder->where('pr.DelDate', null); $builder->orderBy('pr.ResultDateTime', 'DESC'); return $builder->get()->getResultArray(); } /** * Update result with validation and return flag (not stored) * * @param int $resultID * @param array $data * @return array ['success' => bool, 'flag' => string|null, 'message' => string] */ public function updateWithValidation(int $resultID, array $data): array { $this->db->transStart(); try { $result = $this->find($resultID); if (!$result) { throw new \Exception('Result not found'); } $flag = null; // If result value is being updated, validate it if (isset($data['Result']) && !empty($data['Result'])) { $refNumID = $data['RefNumID'] ?? $result['RefNumID']; if ($refNumID) { $flag = $this->validateAndFlag($data['Result'], $refNumID, $result['OrderID']); } } // Set update timestamp $data['StartDate'] = date('Y-m-d H:i:s'); $updated = $this->update($resultID, $data); if (!$updated) { throw new \Exception('Failed to update result'); } $this->db->transComplete(); return [ 'success' => true, 'flag' => $flag, 'message' => 'Result updated successfully' ]; } catch (\Exception $e) { $this->db->transRollback(); return [ 'success' => false, 'flag' => null, 'message' => $e->getMessage() ]; } } /** * Get single result with related data * * @param int $resultID * @return array|null */ public function getWithRelations(int $resultID): ?array { $builder = $this->db->table('patres pr'); $builder->select(' pr.*, tds.TestSiteName, tds.TestSiteCode, tds.Unit1, tds.Unit2, rn.Low, rn.High, rn.LowSign, rn.HighSign, rn.Display as RefDisplay, ot.OrderID as OrderNumber, ot.InternalPID '); $builder->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left'); $builder->join('refnum rn', 'rn.RefNumID = pr.RefNumID', 'left'); $builder->join('ordertest ot', 'ot.InternalOID = pr.OrderID', 'left'); $builder->where('pr.ResultID', $resultID); $builder->where('pr.DelDate', null); $result = $builder->get()->getRowArray(); return $result ?: null; } /** * Soft delete result * * @param int $resultID * @return bool */ public function softDelete(int $resultID): bool { return $this->update($resultID, ['DelDate' => date('Y-m-d H:i:s')]); } }