Harden ABDM bridge auth flow and sync handling
This commit is contained in:
parent
bf6090cfd5
commit
90831d4b39
|
|
@ -1206,10 +1206,11 @@ class AbdmGateway extends BaseController
|
|||
}
|
||||
|
||||
$patientName = '';
|
||||
$patientRow = [];
|
||||
if ($this->db->tableExists('patient_master')) {
|
||||
$pmFields = $this->db->getFieldNames('patient_master') ?? [];
|
||||
$pmSelect = ['id'];
|
||||
foreach (['p_fname', 'p_lname', 'abha_address', 'abha_id', 'abha_no', 'abha'] as $f) {
|
||||
foreach (['p_fname', 'p_lname', 'dob', 'p_dob', 'birth_date', 'date_of_birth', 'birth_year', 'year_of_birth', 'age', 'p_age', 'abha_address', 'abha_id', 'abha_no', 'abha'] as $f) {
|
||||
if (in_array($f, $pmFields, true)) {
|
||||
$pmSelect[] = $f;
|
||||
}
|
||||
|
|
@ -1221,10 +1222,7 @@ class AbdmGateway extends BaseController
|
|||
->get(1)
|
||||
->getRowArray() ?? [];
|
||||
|
||||
$patientName = trim(
|
||||
trim((string) ($patientRow['p_fname'] ?? '')) . ' ' .
|
||||
trim((string) ($patientRow['p_lname'] ?? ''))
|
||||
);
|
||||
$patientName = $this->patientDisplayName($patientRow);
|
||||
|
||||
if ($abhaAddress === '') {
|
||||
foreach (['abha_address', 'abha', 'abha_id', 'abha_no'] as $field) {
|
||||
|
|
@ -1248,6 +1246,8 @@ class AbdmGateway extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
$patientBirthYear = $this->resolvePatientBirthYear($patientRow, $abhaAddress, $abhaNumber);
|
||||
|
||||
if ($abhaAddress === '' && $abhaNumber === '') {
|
||||
$logBridge('error', ['ok' => 0, 'error_text' => 'ABHA address or ABHA number is required for record push.'], 'ABHA address or ABHA number is required for record push.', 'abdm.opd.prescription.share.validation');
|
||||
return $this->response->setJSON([
|
||||
|
|
@ -1442,6 +1442,7 @@ class AbdmGateway extends BaseController
|
|||
'patient_name' => $patientName !== '' ? $patientName : ('PATIENT-' . $patientId),
|
||||
'abha_id' => $abhaNumber,
|
||||
'abha_address' => $abhaAddress,
|
||||
'year_of_birth' => $patientBirthYear,
|
||||
'hi_type' => $hiType,
|
||||
'record_type' => $hiType,
|
||||
'visit_date' => $visitDate,
|
||||
|
|
@ -1560,6 +1561,7 @@ class AbdmGateway extends BaseController
|
|||
$patName = (string) ($fhirPayload['patient_name'] ?? '');
|
||||
$doctorName = (string) ($fhirPayload['doctor_name'] ?? '');
|
||||
$visitDate = (string) ($fhirPayload['visit_date'] ?? date('Y-m-d'));
|
||||
$birthYear = (int) ($fhirPayload['year_of_birth'] ?? 0);
|
||||
$ccRef = (string) ($fhirPayload['care_context_reference'] ?? ('IPD-' . $ipdId . '-' . $visitDate));
|
||||
$ccDisplay = (string) ($fhirPayload['care_context_display'] ?? ('Discharge Summary ' . $visitDate));
|
||||
$bundle = (array) ($fhirPayload['bundle'] ?? []);
|
||||
|
|
@ -1613,8 +1615,9 @@ class AbdmGateway extends BaseController
|
|||
try {
|
||||
$result = $this->connector->pushRecord([
|
||||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patName,
|
||||
'patient_name' => $patName !== '' ? $patName : ('PATIENT-' . $patientId),
|
||||
'abha_id' => $abhaId,
|
||||
'year_of_birth' => $birthYear,
|
||||
'hi_type' => 'DischargeSummaryRecord',
|
||||
'record_type' => 'DischargeSummaryRecord',
|
||||
'visit_date' => $visitDate,
|
||||
|
|
@ -1708,10 +1711,11 @@ class AbdmGateway extends BaseController
|
|||
if ($this->db->tableExists('patient_master')) {
|
||||
$patientRow = $this->db->table('patient_master')->where('id', $patientId)->get(1)->getRowArray() ?? [];
|
||||
}
|
||||
$patName = trim(
|
||||
trim((string) ($patientRow['p_fname'] ?? '')) . ' ' .
|
||||
trim((string) ($patientRow['p_lname'] ?? ''))
|
||||
) ?: trim((string) ($labReq->patient_name ?? ''));
|
||||
$patName = $this->patientDisplayName($patientRow);
|
||||
if ($patName === '') {
|
||||
$patName = trim((string) ($labReq->patient_name ?? ''));
|
||||
}
|
||||
$patientBirthYear = $this->resolvePatientBirthYear($patientRow, str_contains($abhaId, '@') ? $abhaId : '', str_contains($abhaId, '@') ? '' : $abhaId);
|
||||
|
||||
// ── Load test / charge name ────────────────────────────────────────────
|
||||
$testTitle = '';
|
||||
|
|
@ -1856,6 +1860,7 @@ class AbdmGateway extends BaseController
|
|||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patName,
|
||||
'abha_id' => $abhaId,
|
||||
'year_of_birth' => $patientBirthYear,
|
||||
'hi_type' => 'DiagnosticReportRecord',
|
||||
'record_type' => 'DiagnosticReportRecord',
|
||||
'visit_date' => $visitDate,
|
||||
|
|
@ -1939,10 +1944,10 @@ class AbdmGateway extends BaseController
|
|||
if ($this->db->tableExists('patient_master')) {
|
||||
$patientRow = $this->db->table('patient_master')->where('id', $patientId)->get(1)->getRowArray() ?? [];
|
||||
}
|
||||
$patName = trim(
|
||||
trim((string) ($patientRow['p_fname'] ?? '')) . ' ' .
|
||||
trim((string) ($patientRow['p_lname'] ?? ''))
|
||||
) ?: trim((string) ($labReq->patient_name ?? ''));
|
||||
$patName = $this->patientDisplayName($patientRow);
|
||||
if ($patName === '') {
|
||||
$patName = trim((string) ($labReq->patient_name ?? ''));
|
||||
}
|
||||
|
||||
$testTitle = '';
|
||||
$chargeId = (int) ($labReq->charge_id ?? 0);
|
||||
|
|
@ -2162,6 +2167,7 @@ class AbdmGateway extends BaseController
|
|||
'patient_name' => $patientName,
|
||||
'abha_id' => preg_match('/^\d{14}$/', $abhaId) === 1 ? $abhaId : '',
|
||||
'abha_address' => str_contains($abhaId, '@') ? $abhaId : '',
|
||||
'year_of_birth' => (int) ($payload['year_of_birth'] ?? 0),
|
||||
'hi_type' => 'ImmunizationRecord',
|
||||
'record_type' => 'ImmunizationRecord',
|
||||
'visit_date' => $visitDate,
|
||||
|
|
@ -2342,7 +2348,7 @@ class AbdmGateway extends BaseController
|
|||
$patientRow = $this->db->table('patient_master')->where('id', $patientId)->get(1)->getRowArray() ?? [];
|
||||
}
|
||||
|
||||
$patientName = trim(trim((string) ($patientRow['p_fname'] ?? '')) . ' ' . trim((string) ($patientRow['p_lname'] ?? '')));
|
||||
$patientName = $this->patientDisplayName($patientRow);
|
||||
if ($patientName === '') {
|
||||
$patientName = trim((string) ($ipdRow['P_name'] ?? ''));
|
||||
}
|
||||
|
|
@ -2673,7 +2679,7 @@ class AbdmGateway extends BaseController
|
|||
return null;
|
||||
}
|
||||
|
||||
$patientName = trim(trim((string) ($patientRow['p_fname'] ?? '')) . ' ' . trim((string) ($patientRow['p_lname'] ?? '')));
|
||||
$patientName = $this->patientDisplayName($patientRow);
|
||||
$rawAbha = trim($preferredAbhaId);
|
||||
if ($rawAbha === '') {
|
||||
foreach (['abha_address', 'abha_id', 'abha_no', 'abha'] as $field) {
|
||||
|
|
@ -2751,6 +2757,7 @@ class AbdmGateway extends BaseController
|
|||
'care_context_reference' => $ccRef,
|
||||
'care_context_display' => 'Immunization Record - ' . $visitDate,
|
||||
'patient_name' => $patient['name'],
|
||||
'year_of_birth' => $this->resolvePatientBirthYear($patientRow, str_contains($rawAbha, '@') ? $rawAbha : '', str_contains($rawAbha, '@') ? '' : $rawAbha),
|
||||
'visit_date' => $visitDate,
|
||||
'records' => $records,
|
||||
];
|
||||
|
|
@ -3345,12 +3352,24 @@ class AbdmGateway extends BaseController
|
|||
$queueId = null;
|
||||
$connectorErr = null;
|
||||
try {
|
||||
$patientRowForPush = $this->loadPatientRow($patientId);
|
||||
$sanitizedPatientName = trim((string) $patientName);
|
||||
if ($sanitizedPatientName === '' || preg_match('/\s0$/', $sanitizedPatientName) === 1) {
|
||||
$sanitizedPatientName = $this->patientDisplayName($patientRowForPush);
|
||||
}
|
||||
$patientBirthYear = $this->resolvePatientBirthYear(
|
||||
$patientRowForPush,
|
||||
str_contains($abhaId, '@') ? $abhaId : '',
|
||||
str_contains($abhaId, '@') ? '' : $abhaId
|
||||
);
|
||||
|
||||
// Use the new store-and-link flow (POST /v3/records/push) for re-push:
|
||||
// No consent needed — bridge stores record and serves it when ABDM requests data.
|
||||
$result = $this->connector->pushRecord([
|
||||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patientName,
|
||||
'patient_name' => $sanitizedPatientName !== '' ? $sanitizedPatientName : ('PATIENT-' . $patientId),
|
||||
'abha_id' => $abhaId,
|
||||
'year_of_birth' => $patientBirthYear,
|
||||
'hi_type' => $hiType,
|
||||
'record_type' => $this->mapHiTypeToRecordType($hiType),
|
||||
'visit_date' => $visitDate !== '' ? $visitDate : date('Y-m-d'),
|
||||
|
|
@ -5559,11 +5578,18 @@ class AbdmGateway extends BaseController
|
|||
$bridgeRecordId = 0;
|
||||
$connectorError = null;
|
||||
try {
|
||||
$patientRowForPush = $this->loadPatientRow($patientId);
|
||||
$patientBirthYear = $this->resolvePatientBirthYear(
|
||||
$patientRowForPush,
|
||||
str_contains($abhaId, '@') ? $abhaId : '',
|
||||
str_contains($abhaId, '@') ? '' : $abhaId
|
||||
);
|
||||
$result = $this->connector->pushRecord([
|
||||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patientName,
|
||||
'abha_id' => preg_match('/^\d{14}$/', $abhaId) === 1 ? $abhaId : '',
|
||||
'abha_address' => str_contains($abhaId, '@') ? $abhaId : '',
|
||||
'year_of_birth' => $patientBirthYear,
|
||||
'hi_type' => $hiType,
|
||||
'record_type' => $hiType,
|
||||
'visit_date' => $visitDate,
|
||||
|
|
@ -5755,7 +5781,66 @@ class AbdmGateway extends BaseController
|
|||
|
||||
private function patientDisplayName(array $patientRow): string
|
||||
{
|
||||
return trim(trim((string) ($patientRow['p_fname'] ?? '')) . ' ' . trim((string) ($patientRow['p_lname'] ?? ''))) ?: 'Patient';
|
||||
$first = trim((string) ($patientRow['p_fname'] ?? ''));
|
||||
$last = trim((string) ($patientRow['p_lname'] ?? ''));
|
||||
|
||||
if (in_array(strtolower($last), ['0', '00', 'na', 'n/a', 'null', 'nil', '-'], true)) {
|
||||
$last = '';
|
||||
}
|
||||
|
||||
$full = trim($first . ' ' . $last);
|
||||
return $full !== '' ? $full : 'Patient';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve patient birth year required by ABDM link-token flow.
|
||||
*/
|
||||
private function resolvePatientBirthYear(array $patientRow, string $abhaAddress = '', string $abhaNumber = ''): int
|
||||
{
|
||||
$year = 0;
|
||||
|
||||
foreach (['birth_year', 'year_of_birth'] as $field) {
|
||||
$candidate = preg_replace('/\D/', '', (string) ($patientRow[$field] ?? ''));
|
||||
$candidate = is_string($candidate) ? (int) $candidate : 0;
|
||||
if ($candidate >= 1900 && $candidate <= 2200) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['dob', 'p_dob', 'birth_date', 'date_of_birth'] as $field) {
|
||||
$raw = trim((string) ($patientRow[$field] ?? ''));
|
||||
if ($raw === '') {
|
||||
continue;
|
||||
}
|
||||
$ts = strtotime($raw);
|
||||
if ($ts !== false) {
|
||||
$candidate = (int) date('Y', $ts);
|
||||
if ($candidate >= 1900 && $candidate <= 2200) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['age', 'p_age', 'patient_age'] as $field) {
|
||||
$ageDigits = preg_replace('/\D/', '', (string) ($patientRow[$field] ?? ''));
|
||||
$age = is_string($ageDigits) ? (int) $ageDigits : 0;
|
||||
if ($age > 0 && $age < 130) {
|
||||
$candidate = (int) date('Y') - $age;
|
||||
if ($candidate >= 1900 && $candidate <= 2200) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$source = trim($abhaAddress !== '' ? $abhaAddress : $abhaNumber);
|
||||
if ($source !== '' && preg_match('/(19\d{2}|20\d{2}|21\d{2}|2200)/', $source, $m) === 1) {
|
||||
$year = (int) ($m[1] ?? 0);
|
||||
if ($year >= 1900 && $year <= 2200) {
|
||||
return $year;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function buildAbdmPatientResource(array $patientRow, int $patientId, string $abhaId): array
|
||||
|
|
|
|||
|
|
@ -1039,13 +1039,80 @@ class Abha extends BaseController
|
|||
}
|
||||
|
||||
if (empty($result['ok']) || $result['ok'] != 1) {
|
||||
$errorText = '';
|
||||
foreach ([
|
||||
$result['error_text'] ?? null,
|
||||
$result['message'] ?? null,
|
||||
$result['description'] ?? null,
|
||||
$result['error'] ?? null,
|
||||
$result['error']['message'] ?? null,
|
||||
$result['error']['description'] ?? null,
|
||||
$result['data']['message'] ?? null,
|
||||
$result['data']['description'] ?? null,
|
||||
$result['data']['error'] ?? null,
|
||||
$result['data']['error']['message'] ?? null,
|
||||
$result['data']['error']['description'] ?? null,
|
||||
$result['data']['raw_response'] ?? null,
|
||||
] as $candidate) {
|
||||
if (is_string($candidate) && trim($candidate) !== '') {
|
||||
$errorText = trim($candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$requestId = '';
|
||||
foreach ([
|
||||
$result['request_id'] ?? null,
|
||||
$result['data']['request_id'] ?? null,
|
||||
$result['result']['request_id'] ?? null,
|
||||
] as $candidate) {
|
||||
if (is_string($candidate) && trim($candidate) !== '') {
|
||||
$requestId = trim($candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($errorText === '') {
|
||||
$errorText = 'ABHA validation failed';
|
||||
}
|
||||
if ($requestId !== '' && stripos($errorText, $requestId) === false) {
|
||||
$errorText .= ' (Ref: ' . $requestId . ')';
|
||||
}
|
||||
|
||||
if (stripos($errorText, 'Please make a valid request.') !== false) {
|
||||
$errorText = 'Bridge validation rejected this request. Please contact bridge support with the reference shown. '
|
||||
. $errorText;
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'ok' => 0,
|
||||
'error_text' => $result['error_text'] ?? $result['message']
|
||||
?? $result['data']['message'] ?? 'ABHA validation failed',
|
||||
'error_text' => $errorText,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->response->setJSON(['ok' => 1, 'status' => (string) ($result['data']['status'] ?? 'UNKNOWN')]);
|
||||
$statusRaw = '';
|
||||
foreach ([
|
||||
$result['status'] ?? null,
|
||||
$result['validation_status'] ?? null,
|
||||
$result['data']['status'] ?? null,
|
||||
$result['data']['validation_status'] ?? null,
|
||||
$result['result']['status'] ?? null,
|
||||
$result['data']['result']['status'] ?? null,
|
||||
] as $candidate) {
|
||||
if (is_string($candidate) && trim($candidate) !== '') {
|
||||
$statusRaw = strtoupper(trim($candidate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge adapters may return ACTIVE/VERIFIED/EXISTS for successful ABHA checks.
|
||||
$validStates = ['VALID', 'ACTIVE', 'VERIFIED', 'EXISTS', 'FOUND', 'SUCCESS'];
|
||||
$status = in_array($statusRaw, $validStates, true) || $statusRaw === '' ? 'VALID' : $statusRaw;
|
||||
|
||||
return $this->response->setJSON([
|
||||
'ok' => 1,
|
||||
'status' => $status,
|
||||
'raw_status' => $statusRaw,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -492,11 +492,107 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface
|
|||
|
||||
public function validateAbha(string $abhaId, array $fullPayload = []): array
|
||||
{
|
||||
$body = $fullPayload !== [] ? $fullPayload : ['abha_id' => $abhaId];
|
||||
if ($this->hfrId !== '' && empty($body['hfr_id'])) {
|
||||
$inputValue = '';
|
||||
$inputType = 'abha-number';
|
||||
|
||||
if ($fullPayload !== []) {
|
||||
$abhaAddress = trim((string) ($fullPayload['abha_address'] ?? ''));
|
||||
$abhaNumber = trim((string) ($fullPayload['abha_id'] ?? $abhaId));
|
||||
|
||||
if ($abhaAddress !== '') {
|
||||
$inputType = 'abha-address';
|
||||
$inputValue = $abhaAddress;
|
||||
} else {
|
||||
$digits = preg_replace('/\D/', '', $abhaNumber);
|
||||
$inputValue = $digits !== '' ? $digits : $abhaNumber;
|
||||
}
|
||||
} else {
|
||||
$abhaRaw = trim((string) $abhaId);
|
||||
if (str_contains($abhaRaw, '@')) {
|
||||
$inputType = 'abha-address';
|
||||
$inputValue = $abhaRaw;
|
||||
} else {
|
||||
$digits = preg_replace('/\D/', '', $abhaRaw);
|
||||
$inputValue = $digits !== '' ? $digits : $abhaRaw;
|
||||
}
|
||||
}
|
||||
|
||||
$body = [
|
||||
'type' => $inputType,
|
||||
'value' => $inputValue,
|
||||
];
|
||||
if ($this->hfrId !== '') {
|
||||
$body['hfr_id'] = $this->hfrId;
|
||||
}
|
||||
return $this->post('/v3/abha/validate', $body);
|
||||
|
||||
$result = $this->post('/v3/abha/login/search', $body);
|
||||
|
||||
// Backward-compat: if a bridge does not yet expose login/search, retry legacy validate.
|
||||
if (empty($result['ok']) || (int) ($result['ok'] ?? 0) !== 1) {
|
||||
$httpCode = (int) ($result['http_code'] ?? 0);
|
||||
if (in_array($httpCode, [404, 405], true)) {
|
||||
$legacyBody = $inputType === 'abha-address'
|
||||
? ['abha_address' => $inputValue]
|
||||
: ['abha_id' => $inputValue];
|
||||
if ($this->hfrId !== '') {
|
||||
$legacyBody['hfr_id'] = $this->hfrId;
|
||||
}
|
||||
$result = $this->post('/v3/abha/validate', $legacyBody);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($result['ok']) || (int) ($result['ok'] ?? 0) !== 1) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$data = is_array($result['data'] ?? null) ? $result['data'] : [];
|
||||
$accounts = is_array($data['accounts'] ?? null) ? $data['accounts'] : [];
|
||||
$firstAccount = isset($accounts[0]) && is_array($accounts[0]) ? $accounts[0] : [];
|
||||
|
||||
$status = '';
|
||||
foreach ([
|
||||
$result['status'] ?? null,
|
||||
$result['account_status'] ?? null,
|
||||
$data['status'] ?? null,
|
||||
$data['account_status'] ?? null,
|
||||
$data['accountStatus'] ?? null,
|
||||
$data['abhaStatus'] ?? null,
|
||||
$firstAccount['status'] ?? null,
|
||||
$firstAccount['accountStatus'] ?? null,
|
||||
$firstAccount['abhaStatus'] ?? null,
|
||||
] as $candidate) {
|
||||
if (is_string($candidate) && trim($candidate) !== '') {
|
||||
$status = strtoupper(trim($candidate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$authMethods = [];
|
||||
foreach ([
|
||||
$data['authMethods'] ?? null,
|
||||
$data['auth_methods'] ?? null,
|
||||
$data['availableAuthMethods'] ?? null,
|
||||
$firstAccount['authMethods'] ?? null,
|
||||
$firstAccount['auth_methods'] ?? null,
|
||||
$firstAccount['availableAuthMethods'] ?? null,
|
||||
] as $candidate) {
|
||||
if (is_array($candidate) && ! empty($candidate)) {
|
||||
foreach ($candidate as $method) {
|
||||
$m = strtoupper(trim((string) $method));
|
||||
if ($m !== '' && ! in_array($m, $authMethods, true)) {
|
||||
$authMethods[] = $m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($authMethods)) {
|
||||
$result['auth_methods'] = $authMethods;
|
||||
}
|
||||
|
||||
// HMS callers expect a status-like field; treat successful search as VALID when absent.
|
||||
$result['status'] = $status !== '' ? $status : 'VALID';
|
||||
return $result;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -917,6 +917,24 @@ class M3HiuWorkflowService
|
|||
$hiuId = trim((string) ($payload['hfr_id'] ?? ''));
|
||||
}
|
||||
|
||||
$istTz = new \DateTimeZone('Asia/Kolkata');
|
||||
$utcTz = new \DateTimeZone('UTC');
|
||||
$nowIst = new \DateTimeImmutable('now', $istTz);
|
||||
$fromUtc = $nowIst
|
||||
->modify('-365 days')
|
||||
->setTime(0, 0, 0)
|
||||
->setTimezone($utcTz)
|
||||
->format('Y-m-d\TH:i:s.000\Z');
|
||||
$toUtc = $nowIst
|
||||
->setTime(23, 59, 59)
|
||||
->setTimezone($utcTz)
|
||||
->format('Y-m-d\TH:i:s.000\Z');
|
||||
$eraseAtUtc = $nowIst
|
||||
->modify('+365 days')
|
||||
->setTime(23, 59, 59)
|
||||
->setTimezone($utcTz)
|
||||
->format('Y-m-d\TH:i:s.000\Z');
|
||||
|
||||
$consent = [
|
||||
'purpose' => [
|
||||
'code' => 'CAREMGT',
|
||||
|
|
@ -933,10 +951,10 @@ class M3HiuWorkflowService
|
|||
'permission' => [
|
||||
'accessMode' => 'VIEW',
|
||||
'dateRange' => [
|
||||
'from' => gmdate('Y-m-d\T00:00:00.000\Z', strtotime('-365 days')),
|
||||
'to' => gmdate('Y-m-d\T00:00:00.000\Z'),
|
||||
'from' => $fromUtc,
|
||||
'to' => $toUtc,
|
||||
],
|
||||
'dataEraseAt' => gmdate('Y-m-d\T00:00:00.000\Z', strtotime('+365 days')),
|
||||
'dataEraseAt' => $eraseAtUtc,
|
||||
'frequency' => [
|
||||
'unit' => 'HOUR',
|
||||
'value' => 1,
|
||||
|
|
|
|||
|
|
@ -297,8 +297,14 @@ class AbdmSyncWorkerService
|
|||
|
||||
$name = trim((string) ($payload['patient_name'] ?? ''));
|
||||
if ($name === '') {
|
||||
$name = trim(trim((string) ($row['p_fname'] ?? '')) . ' ' . trim((string) ($row['p_lname'] ?? '')));
|
||||
$first = trim((string) ($row['p_fname'] ?? ''));
|
||||
$last = trim((string) ($row['p_lname'] ?? ''));
|
||||
if (in_array(strtolower($last), ['0', '00', 'na', 'n/a', 'null', 'nil', '-'], true)) {
|
||||
$last = '';
|
||||
}
|
||||
$name = trim($first . ' ' . $last);
|
||||
}
|
||||
$name = preg_replace('/\s0$/', '', $name) ?? $name;
|
||||
if ($name === '') {
|
||||
$name = 'PATIENT-' . $localPatientId;
|
||||
}
|
||||
|
|
@ -351,12 +357,15 @@ class AbdmSyncWorkerService
|
|||
}
|
||||
}
|
||||
|
||||
$birthYearRaw = trim((string) ($payload['birth_year'] ?? $payload['year_of_birth'] ?? $row['birth_year'] ?? $row['year_of_birth'] ?? ''));
|
||||
$ageRaw = trim((string) ($payload['age'] ?? $payload['patient_age'] ?? $row['age'] ?? $row['p_age'] ?? ''));
|
||||
|
||||
return [
|
||||
'patient_id' => (string) ($localPatientId > 0 ? $localPatientId : ($payload['local_patient_id'] ?? '')),
|
||||
'name' => $name,
|
||||
'mobile' => $mobile,
|
||||
'gender' => $this->normalizeBridgeGenderCode($genderRaw),
|
||||
'year_of_birth' => $this->extractBirthYear($dobRaw),
|
||||
'year_of_birth' => $this->extractBirthYear($dobRaw, $birthYearRaw, $ageRaw, $abhaAddress),
|
||||
'abha_address' => $abhaAddress,
|
||||
'abha_number' => $abhaDigits,
|
||||
];
|
||||
|
|
@ -378,13 +387,38 @@ class AbdmSyncWorkerService
|
|||
return 'O';
|
||||
}
|
||||
|
||||
private function extractBirthYear(string $dob): int
|
||||
private function extractBirthYear(string $dob, string $birthYear = '', string $age = '', string $abhaAddress = ''): int
|
||||
{
|
||||
$birthYearDigits = preg_replace('/\D/', '', $birthYear);
|
||||
$birthYearInt = is_string($birthYearDigits) ? (int) $birthYearDigits : 0;
|
||||
if ($birthYearInt >= 1900 && $birthYearInt <= 2200) {
|
||||
return $birthYearInt;
|
||||
}
|
||||
|
||||
$dob = trim($dob);
|
||||
if ($dob !== '') {
|
||||
$ts = strtotime($dob);
|
||||
if ($ts !== false) {
|
||||
return (int) date('Y', $ts);
|
||||
$year = (int) date('Y', $ts);
|
||||
if ($year >= 1900 && $year <= 2200) {
|
||||
return $year;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ageDigits = preg_replace('/\D/', '', $age);
|
||||
$ageInt = is_string($ageDigits) ? (int) $ageDigits : 0;
|
||||
if ($ageInt > 0 && $ageInt < 130) {
|
||||
$year = (int) date('Y') - $ageInt;
|
||||
if ($year >= 1900 && $year <= 2200) {
|
||||
return $year;
|
||||
}
|
||||
}
|
||||
|
||||
if ($abhaAddress !== '' && preg_match('/(19\d{2}|20\d{2}|21\d{2}|2200)/', $abhaAddress, $match) === 1) {
|
||||
$year = (int) ($match[1] ?? 0);
|
||||
if ($year >= 1900 && $year <= 2200) {
|
||||
return $year;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -285,7 +285,13 @@
|
|||
$bridgeRecordId = trim((string) ($r['bridge_record_id'] ?? ''));
|
||||
$hasFhir = (int) ($r['has_fhir'] ?? 0) === 1;
|
||||
$pushStatusRaw = strtolower(trim((string) ($r['push_status'] ?? '')));
|
||||
$canSubmitGateway = $hasFhir && ! in_array($pushStatusRaw, ['queued', 'linked'], true);
|
||||
$canSubmitGateway = $hasFhir;
|
||||
$submitButtonLabel = in_array($pushStatusRaw, ['queued', 'linked', 'failed'], true)
|
||||
? 'Submit Again'
|
||||
: 'Submit to ABDM';
|
||||
$submitButtonClass = in_array($pushStatusRaw, ['queued', 'linked'], true)
|
||||
? 'btn-outline-secondary'
|
||||
: 'btn-outline-warning';
|
||||
$statusBadgeClass = 'badge bg-' . $statusTone;
|
||||
if ($statusTone === 'warning') {
|
||||
$statusBadgeClass .= ' text-dark';
|
||||
|
|
@ -323,10 +329,10 @@
|
|||
<?php if ($canSubmitGateway): ?>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline-warning btn-opd-consult-submit-gateway ms-1"
|
||||
class="btn btn-sm <?= esc($submitButtonClass) ?> btn-opd-consult-submit-gateway ms-1"
|
||||
data-opd-id="<?= (int) ($r['opd_id'] ?? 0) ?>"
|
||||
data-abha-id="<?= esc((string) ($r['abha_id'] ?? '')) ?>"
|
||||
>Submit to ABDM</button>
|
||||
><?= esc($submitButtonLabel) ?></button>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -2441,9 +2447,9 @@
|
|||
detailsCell.innerHTML = '<div>Submitted to gateway and waiting for link workflow.</div>' + queueHtml + bridgeHtml;
|
||||
}
|
||||
}
|
||||
rowSubmitBtn.disabled = true;
|
||||
rowSubmitBtn.className = 'btn btn-sm btn-success ms-1';
|
||||
rowSubmitBtn.textContent = 'Submitted';
|
||||
rowSubmitBtn.disabled = false;
|
||||
rowSubmitBtn.className = 'btn btn-sm btn-outline-secondary btn-opd-consult-submit-gateway ms-1';
|
||||
rowSubmitBtn.textContent = 'Submit Again';
|
||||
}
|
||||
|
||||
var qInfo = res.queue_id ? ' Queue ID: ' + res.queue_id : '';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user