From fcdbc3f20ad8fcf32fea9025cff0464e859e2653 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Thu, 29 Jan 2026 11:21:34 +0700 Subject: [PATCH] feat(patient): handle array format for Custodian and LinkTo fields - PatientModel: Convert Custodian from array to integer InternalPID when received as object - PatientModel: Convert LinkTo from array of objects to comma-separated InternalPID string - API docs: Add LinkedPatient, Custodian, and PatAttEntry schema definitions - API docs: Extend Patient schema with DeathIndicator, TimeOfDeath, PatCom, PatAtt, Province, City, Country, Race, MaritalStatus, Religion, Ethnic fields - Add AGENTS.md to .gitignore --- .gitignore | 3 +- app/Models/Patient/PatientModel.php | 22 ++++++++- public/api-docs.yaml | 75 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4c57c78..fa6fb59 100644 --- a/.gitignore +++ b/.gitignore @@ -127,4 +127,5 @@ _modules/* /public/.htaccess .serena/ -.claude/ \ No newline at end of file +.claude/ +AGENTS.md \ No newline at end of file diff --git a/app/Models/Patient/PatientModel.php b/app/Models/Patient/PatientModel.php index bd64106..5d26bdc 100644 --- a/app/Models/Patient/PatientModel.php +++ b/app/Models/Patient/PatientModel.php @@ -118,7 +118,17 @@ class PatientModel extends BaseModel { $modelPatAtt = new PatAttModel(); $modelPatCom = new PatComModel(); $modelPatIdt = new PatIdtModel(); - + + if (!empty($input['Custodian'])) { + if (is_array($input['Custodian']) && isset($input['Custodian']['InternalPID'])) { + $input['Custodian'] = (int) $input['Custodian']['InternalPID']; + } + } + + if (!empty($input['LinkTo']) && is_array($input['LinkTo'])) { + $internalPids = array_column($input['LinkTo'], 'InternalPID'); + $input['LinkTo'] = implode(',', $internalPids); + } $input['LinkTo'] = empty($input['LinkTo']) ? null : $input['LinkTo']; $db->transBegin(); @@ -160,6 +170,16 @@ class PatientModel extends BaseModel { $modelPatCom = new PatComModel(); $modelPatAtt = new PatAttModel(); + if (!empty($input['Custodian'])) { + if (is_array($input['Custodian']) && isset($input['Custodian']['InternalPID'])) { + $input['Custodian'] = (int) $input['Custodian']['InternalPID']; + } + } + + if (!empty($input['LinkTo']) && is_array($input['LinkTo'])) { + $internalPids = array_column($input['LinkTo'], 'InternalPID'); + $input['LinkTo'] = implode(',', $internalPids); + } $input['LinkTo'] = empty($input['LinkTo']) ? null : $input['LinkTo']; $db->transBegin(); diff --git a/public/api-docs.yaml b/public/api-docs.yaml index ecc29d7..320a8f1 100644 --- a/public/api-docs.yaml +++ b/public/api-docs.yaml @@ -143,6 +143,36 @@ components: type: string maxLength: 255 + LinkedPatient: + type: object + description: Linked patient reference + properties: + InternalPID: + type: integer + description: Internal patient ID of the linked patient + PatientID: + type: string + description: Patient ID of the linked patient + + Custodian: + type: object + description: Patient custodian/guardian + properties: + InternalPID: + type: integer + description: Internal patient ID of the custodian + PatientID: + type: string + description: Patient ID of the custodian + + PatAttEntry: + type: object + description: Patient address/attorney entry + properties: + Address: + type: string + description: Address text + Patient: type: object required: @@ -227,6 +257,51 @@ components: maxLength: 100 PatIdt: $ref: '#/components/schemas/PatientIdentifier' + LinkTo: + type: array + description: Array of linked patient references + items: + $ref: '#/components/schemas/LinkedPatient' + Custodian: + $ref: '#/components/schemas/Custodian' + DeathIndicator: + type: string + enum: [Y, N] + description: 'Y: Yes (deceased), N: No (alive)' + TimeOfDeath: + type: string + format: date-time + description: ISO 8601 UTC datetime of death + PatCom: + type: string + description: Patient comment/notes + PatAtt: + type: array + description: Patient address entries + items: + $ref: '#/components/schemas/PatAttEntry' + Province: + type: string + description: Province area code + City: + type: string + description: City area code + Country: + type: string + maxLength: 100 + Race: + type: string + maxLength: 100 + MaritalStatus: + type: string + enum: [A, B, D, M, S, W] + description: 'A: Annulled, B: Separated, D: Divorced, M: Married, S: Single, W: Widowed' + Religion: + type: string + maxLength: 100 + Ethnic: + type: string + maxLength: 100 PatientListResponse: type: object