firstWhere(['cid' => $cid]); } /** * Find Patient by Hospital Number (HN) */ public function findByHn(string $hn): ?array { return $this->firstWhere(['hn' => $hn]); } /** * Search patients by Name, CID, or Phone */ public function search(string $keyword): array { $sql = "SELECT p.*, l.total_points, l.tier FROM `{$this->table}` p LEFT JOIN `patient_loyalty` l ON p.id = l.patient_id WHERE p.cid LIKE :kw OR p.hn LIKE :kw OR p.first_name_th LIKE :kw OR p.last_name_th LIKE :kw OR p.phone LIKE :kw ORDER BY p.id DESC LIMIT 50"; $stmt = self::getDB()->prepare($sql); $stmt->execute(['kw' => "%{$keyword}%"]); return $stmt->fetchAll(); } /** * Save or Update from Smart Card Reader APDU / WebUSB Payload */ public function saveFromSmartCard(array $cardData): int { $existing = $this->findByCid($cardData['cid']); if ($existing) { $this->update((int)$existing['id'], [ 'first_name_th' => $cardData['first_name_th'], 'last_name_th' => $cardData['last_name_th'], 'first_name_en' => $cardData['first_name_en'] ?? null, 'last_name_en' => $cardData['last_name_en'] ?? null, 'birth_date' => $cardData['birth_date'], 'gender' => $cardData['gender'] === '1' || $cardData['gender'] === 'Male' ? 'Male' : 'Female', 'address' => $cardData['address'] ?? null, 'photo_url' => $cardData['photo_url'] ?? null, 'updated_at' => date('Y-m-d H:i:s'), ]); return (int)$existing['id']; } // Generate auto HN if not synced yet $hn = $cardData['hn'] ?? ('HN-' . date('ym') . sprintf('%04d', random_int(1, 9999))); return $this->create([ 'cid' => $cardData['cid'], 'hn' => $hn, 'first_name_th' => $cardData['first_name_th'], 'last_name_th' => $cardData['last_name_th'], 'first_name_en' => $cardData['first_name_en'] ?? null, 'last_name_en' => $cardData['last_name_en'] ?? null, 'birth_date' => $cardData['birth_date'], 'gender' => $cardData['gender'] === '1' || $cardData['gender'] === 'Male' ? 'Male' : 'Female', 'address' => $cardData['address'] ?? null, 'phone' => $cardData['phone'] ?? '080-000-0000', 'photo_url' => $cardData['photo_url'] ?? null, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]); } /** * Sync data from HIS / HOSxP REST API */ public function updateHisData(int $patientId, array $hisRawData): bool { return $this->update($patientId, [ 'his_synced_at' => date('Y-m-d H:i:s'), 'his_raw_data' => json_encode($hisRawData, JSON_UNESCAPED_UNICODE), ]); } }