diff --git a/app/Controllers/OrderTestController.php b/app/Controllers/OrderTestController.php index 8c36f00..7ef36db 100755 --- a/app/Controllers/OrderTestController.php +++ b/app/Controllers/OrderTestController.php @@ -88,9 +88,7 @@ class OrderTestController extends Controller { 'OrderStatus' => 'order_status', ])[0]; - // Include specimens and tests - $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']); - $row['Tests'] = $this->getOrderTests($row['InternalOID']); + $row['Tests'] = $this->getOrderTestsCompact($row['InternalOID']); return $this->respond([ 'status' => 'success', @@ -125,6 +123,18 @@ class OrderTestController extends Controller { return $specimens; } + private function getOrderTestsCompact($internalOID) { + return $this->db->table('patres pr') + ->distinct() + ->select('pr.TestSiteID, tds.TestSiteCode, tds.TestSiteName') + ->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left') + ->where('pr.OrderID', $internalOID) + ->where('pr.DelDate IS NULL') + ->orderBy('tds.TestSiteCode', 'ASC') + ->get() + ->getResultArray(); + } + private function getOrderTests($internalOID) { $tests = $this->db->table('patres pr') ->select('pr.*, tds.TestSiteCode, tds.TestSiteName, tds.TestType, tds.SeqScr AS TestSeqScr, tds.SeqRpt AS TestSeqRpt, tds.DisciplineID, d.DisciplineCode, d.DisciplineName, d.SeqScr AS DisciplineSeqScr, d.SeqRpt AS DisciplineSeqRpt') diff --git a/composer.phar b/composer.phar deleted file mode 100755 index 3d1b983..0000000 Binary files a/composer.phar and /dev/null differ diff --git a/public/api-docs.bundled.yaml b/public/api-docs.bundled.yaml index ca0a6d1..820bd02 100755 --- a/public/api-docs.bundled.yaml +++ b/public/api-docs.bundled.yaml @@ -1437,7 +1437,7 @@ paths: tags: - Order summary: Get order by ID - description: Returns order details with associated specimens and tests + description: Returns compact order details with test list only security: - bearerAuth: [] parameters: @@ -1449,7 +1449,7 @@ paths: description: Order ID (e.g., 0025030300001) responses: '200': - description: Order details with specimens and tests + description: Compact order details with tests content: application/json: schema: @@ -1460,7 +1460,7 @@ paths: message: type: string data: - $ref: '#/components/schemas/OrderTest' + $ref: '#/components/schemas/OrderTestCompact' patch: tags: - Order @@ -7790,6 +7790,90 @@ components: items: $ref: '#/components/schemas/OrderTestItem' description: Test results (patres) for this order + OrderTestCompact: + type: object + properties: + InternalOID: + type: integer + description: Internal order ID + OrderID: + type: string + description: Order ID (e.g., 0025030300001) + PlacerID: + type: string + nullable: true + InternalPID: + type: integer + description: Patient internal ID + SiteID: + type: integer + PVADTID: + type: integer + description: Visit ADT ID + ReqApp: + type: string + nullable: true + Priority: + type: string + enum: + - R + - S + - U + description: | + R: Routine + S: Stat + U: Urgent + PriorityLabel: + type: string + description: Priority display text + TrnDate: + type: string + format: date-time + description: Transaction/Order date + EffDate: + type: string + format: date-time + description: Effective date + CreateDate: + type: string + format: date-time + OrderStatus: + type: string + enum: + - ORD + - SCH + - ANA + - VER + - REV + - REP + description: | + ORD: Ordered + SCH: Scheduled + ANA: Analysis + VER: Verified + REV: Reviewed + REP: Reported + OrderStatusLabel: + type: string + description: Order status display text + Tests: + type: array + items: + $ref: '#/components/schemas/OrderTestCompactItem' + description: Compact test list for this order + OrderTestCompactItem: + type: object + properties: + TestSiteID: + type: integer + description: Test definition site ID + TestSiteCode: + type: string + description: Test code + TestSiteName: + type: string + description: Test name + nullable: true OrderItem: type: object properties: diff --git a/public/api-docs.yaml b/public/api-docs.yaml index 6345cc1..593f6ad 100755 --- a/public/api-docs.yaml +++ b/public/api-docs.yaml @@ -22,45 +22,45 @@ servers: - url: https://clqms01-api.services-summit.my.id/ description: Production server -tags: - - name: Authentication - description: User authentication and session management - - name: Patient - description: Patient registration and management - - name: Patient Visit - description: Patient visit/encounter management - - name: Organization - description: Organization structure (accounts, sites, disciplines, departments, workstations) - - name: Location - description: Location management (rooms, wards, buildings) - - name: Equipment - description: Laboratory equipment and instrument management - - name: Specimen - description: Specimen and container management - - name: Test - description: Test definitions and test catalog - - name: Rule - description: Rule engine - rules can be linked to multiple tests via testrule mapping table - - name: Calculation - description: Lightweight calculator endpoint for retrieving computed values by code or name - - name: Order - description: Laboratory order management - - name: Result - description: Patient results reporting with auto-validation - - name: Report - description: Lab report generation (HTML view) - - name: Edge API - description: Instrument integration endpoints - - name: Contact - description: Contact management (doctors, practitioners, etc.) - - name: ValueSet - description: Value set definitions and items - - name: User - description: User management and administration - - name: Demo - description: Demo/test endpoints (no authentication) - - name: Audit - description: Audit log retrieval and filtering +tags: + - name: Authentication + description: User authentication and session management + - name: Patient + description: Patient registration and management + - name: Patient Visit + description: Patient visit/encounter management + - name: Organization + description: Organization structure (accounts, sites, disciplines, departments, workstations) + - name: Location + description: Location management (rooms, wards, buildings) + - name: Equipment + description: Laboratory equipment and instrument management + - name: Specimen + description: Specimen and container management + - name: Test + description: Test definitions and test catalog + - name: Rule + description: Rule engine - rules can be linked to multiple tests via testrule mapping table + - name: Calculation + description: Lightweight calculator endpoint for retrieving computed values by code or name + - name: Order + description: Laboratory order management + - name: Result + description: Patient results reporting with auto-validation + - name: Report + description: Lab report generation (HTML view) + - name: Edge API + description: Instrument integration endpoints + - name: Contact + description: Contact management (doctors, practitioners, etc.) + - name: ValueSet + description: Value set definitions and items + - name: User + description: User management and administration + - name: Demo + description: Demo/test endpoints (no authentication) + - name: Audit + description: Audit log retrieval and filtering components: securitySchemes: @@ -153,6 +153,10 @@ components: $ref: './components/schemas/orders.yaml#/OrderTestList' OrderTest: $ref: './components/schemas/orders.yaml#/OrderTest' + OrderTestCompact: + $ref: './components/schemas/orders.yaml#/OrderTestCompact' + OrderTestCompactItem: + $ref: './components/schemas/orders.yaml#/OrderTestCompactItem' OrderItem: $ref: './components/schemas/orders.yaml#/OrderItem' @@ -190,13 +194,13 @@ components: UserListResponse: $ref: './components/schemas/user.yaml#/UserListResponse' - # Rules schemas - RuleDef: - $ref: './components/schemas/rules.yaml#/RuleDef' - RuleWithDetails: - $ref: './components/schemas/rules.yaml#/RuleWithDetails' - TestRule: - $ref: './components/schemas/rules.yaml#/TestRule' # Mapping table between rules and tests + # Rules schemas + RuleDef: + $ref: './components/schemas/rules.yaml#/RuleDef' + RuleWithDetails: + $ref: './components/schemas/rules.yaml#/RuleWithDetails' + TestRule: + $ref: './components/schemas/rules.yaml#/TestRule' # Mapping table between rules and tests # Paths are in separate files in the paths/ directory # To view the complete API with all paths, use: api-docs.bundled.yaml diff --git a/public/components/schemas/orders.yaml b/public/components/schemas/orders.yaml index f29ef2e..973ed86 100755 --- a/public/components/schemas/orders.yaml +++ b/public/components/schemas/orders.yaml @@ -124,6 +124,83 @@ OrderTest: $ref: '#/OrderTestItem' description: Test results (patres) for this order +OrderTestCompact: + type: object + properties: + InternalOID: + type: integer + description: Internal order ID + OrderID: + type: string + description: Order ID (e.g., 0025030300001) + PlacerID: + type: string + nullable: true + InternalPID: + type: integer + description: Patient internal ID + SiteID: + type: integer + PVADTID: + type: integer + description: Visit ADT ID + ReqApp: + type: string + nullable: true + Priority: + type: string + enum: [R, S, U] + description: | + R: Routine + S: Stat + U: Urgent + PriorityLabel: + type: string + description: Priority display text + TrnDate: + type: string + format: date-time + description: Transaction/Order date + EffDate: + type: string + format: date-time + description: Effective date + CreateDate: + type: string + format: date-time + OrderStatus: + type: string + enum: [ORD, SCH, ANA, VER, REV, REP] + description: | + ORD: Ordered + SCH: Scheduled + ANA: Analysis + VER: Verified + REV: Reviewed + REP: Reported + OrderStatusLabel: + type: string + description: Order status display text + Tests: + type: array + items: + $ref: '#/OrderTestCompactItem' + description: Compact test list for this order + +OrderTestCompactItem: + type: object + properties: + TestSiteID: + type: integer + description: Test definition site ID + TestSiteCode: + type: string + description: Test code + TestSiteName: + type: string + description: Test name + nullable: true + OrderSpecimen: type: object properties: diff --git a/public/paths/orders.yaml b/public/paths/orders.yaml index 5addf5d..9c8b74b 100755 --- a/public/paths/orders.yaml +++ b/public/paths/orders.yaml @@ -196,7 +196,7 @@ get: tags: [Order] summary: Get order by ID - description: Returns order details with associated specimens and tests + description: Returns compact order details with test list only security: - bearerAuth: [] parameters: @@ -208,7 +208,7 @@ description: Order ID (e.g., 0025030300001) responses: '200': - description: Order details with specimens and tests + description: Compact order details with tests content: application/json: schema: @@ -219,7 +219,7 @@ message: type: string data: - $ref: '../components/schemas/orders.yaml#/OrderTest' + $ref: '../components/schemas/orders.yaml#/OrderTestCompact' patch: tags: [Order] diff --git a/tests/feature/OrderTest/OrderTestShowCompactTest.php b/tests/feature/OrderTest/OrderTestShowCompactTest.php new file mode 100644 index 0000000..3223c1c --- /dev/null +++ b/tests/feature/OrderTest/OrderTestShowCompactTest.php @@ -0,0 +1,118 @@ + 'localhost', + 'aud' => 'localhost', + 'iat' => time(), + 'nbf' => time(), + 'exp' => time() + 3600, + 'uid' => 1, + 'email' => 'admin@admin.com', + ]; + $this->token = JWT::encode($payload, $key, 'HS256'); + } + + private function authHeaders(): array + { + return ['Cookie' => 'token=' . $this->token]; + } + + private function createOrderWithTest(): array + { + $patientModel = new PatientModel(); + $patient = $patientModel->where('DelDate', null)->first(); + $this->assertNotEmpty($patient, 'No active patient found for order show test.'); + + $testModel = new TestDefSiteModel(); + $test = $testModel->where('EndDate', null) + ->where('TestType', 'TEST') + ->first(); + + if (!$test) { + $test = $testModel->where('EndDate', null)->first(); + } + + $this->assertNotEmpty($test, 'No active test definition found for order show test.'); + + $orderModel = new OrderTestModel(); + $orderID = $orderModel->createOrder([ + 'InternalPID' => (int) $patient['InternalPID'], + 'SiteID' => (int) ($test['SiteID'] ?? 1), + 'Tests' => [ + [ + 'TestSiteID' => (int) $test['TestSiteID'], + ], + ], + ]); + + $this->assertNotEmpty($orderID, 'Failed to create order for show test.'); + + return [$orderID, $test]; + } + + public function testShowReturnsCompactTestsOnly(): void + { + [$orderID, $test] = $this->createOrderWithTest(); + + $response = $this->withHeaders($this->authHeaders()) + ->call('get', $this->endpoint . '/' . $orderID); + + $response->assertStatus(200); + + $json = json_decode($response->getJSON(), true); + + $this->assertSame('success', $json['status'] ?? null); + $this->assertArrayHasKey('data', $json); + $this->assertArrayHasKey('Tests', $json['data']); + $this->assertArrayNotHasKey('Specimens', $json['data']); + + $tests = $json['data']['Tests']; + $this->assertNotEmpty($tests, 'Compact tests list is empty.'); + + $firstTest = $tests[0]; + $this->assertSame((int) $test['TestSiteID'], (int) $firstTest['TestSiteID']); + $this->assertArrayHasKey('TestSiteCode', $firstTest); + $this->assertArrayHasKey('TestSiteName', $firstTest); + $this->assertArrayNotHasKey('Result', $firstTest); + $this->assertArrayNotHasKey('Discipline', $firstTest); + $this->assertArrayNotHasKey('OrderID', $firstTest); + $this->assertArrayNotHasKey('InternalSID', $firstTest); + $this->assertArrayNotHasKey('SID', $firstTest); + $this->assertArrayNotHasKey('SampleID', $firstTest); + } + + public function testShowNotFound(): void + { + $response = $this->withHeaders($this->authHeaders()) + ->call('get', $this->endpoint . '/999999999'); + + $response->assertStatus(200); + + $json = json_decode($response->getJSON(), true); + $this->assertSame('success', $json['status'] ?? null); + $this->assertNull($json['data'] ?? null); + } +}