Compact order show response

- Return compact test list from order show endpoint
- Add compact order/test OpenAPI schema refs
- Add feature test for compact order show payload
- Remove tracked composer.phar binary
This commit is contained in:
mahdahar 2026-04-23 09:56:37 +07:00
parent 4f87be295b
commit e869ec4ac4
7 changed files with 348 additions and 55 deletions

View File

@ -88,9 +88,7 @@ class OrderTestController extends Controller {
'OrderStatus' => 'order_status', 'OrderStatus' => 'order_status',
])[0]; ])[0];
// Include specimens and tests $row['Tests'] = $this->getOrderTestsCompact($row['InternalOID']);
$row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']);
$row['Tests'] = $this->getOrderTests($row['InternalOID']);
return $this->respond([ return $this->respond([
'status' => 'success', 'status' => 'success',
@ -125,6 +123,18 @@ class OrderTestController extends Controller {
return $specimens; 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) { private function getOrderTests($internalOID) {
$tests = $this->db->table('patres pr') $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') ->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')

Binary file not shown.

View File

@ -1437,7 +1437,7 @@ paths:
tags: tags:
- Order - Order
summary: Get order by ID summary: Get order by ID
description: Returns order details with associated specimens and tests description: Returns compact order details with test list only
security: security:
- bearerAuth: [] - bearerAuth: []
parameters: parameters:
@ -1449,7 +1449,7 @@ paths:
description: Order ID (e.g., 0025030300001) description: Order ID (e.g., 0025030300001)
responses: responses:
'200': '200':
description: Order details with specimens and tests description: Compact order details with tests
content: content:
application/json: application/json:
schema: schema:
@ -1460,7 +1460,7 @@ paths:
message: message:
type: string type: string
data: data:
$ref: '#/components/schemas/OrderTest' $ref: '#/components/schemas/OrderTestCompact'
patch: patch:
tags: tags:
- Order - Order
@ -7790,6 +7790,90 @@ components:
items: items:
$ref: '#/components/schemas/OrderTestItem' $ref: '#/components/schemas/OrderTestItem'
description: Test results (patres) for this order 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: OrderItem:
type: object type: object
properties: properties:

View File

@ -22,45 +22,45 @@ servers:
- url: https://clqms01-api.services-summit.my.id/ - url: https://clqms01-api.services-summit.my.id/
description: Production server description: Production server
tags: tags:
- name: Authentication - name: Authentication
description: User authentication and session management description: User authentication and session management
- name: Patient - name: Patient
description: Patient registration and management description: Patient registration and management
- name: Patient Visit - name: Patient Visit
description: Patient visit/encounter management description: Patient visit/encounter management
- name: Organization - name: Organization
description: Organization structure (accounts, sites, disciplines, departments, workstations) description: Organization structure (accounts, sites, disciplines, departments, workstations)
- name: Location - name: Location
description: Location management (rooms, wards, buildings) description: Location management (rooms, wards, buildings)
- name: Equipment - name: Equipment
description: Laboratory equipment and instrument management description: Laboratory equipment and instrument management
- name: Specimen - name: Specimen
description: Specimen and container management description: Specimen and container management
- name: Test - name: Test
description: Test definitions and test catalog description: Test definitions and test catalog
- name: Rule - name: Rule
description: Rule engine - rules can be linked to multiple tests via testrule mapping table description: Rule engine - rules can be linked to multiple tests via testrule mapping table
- name: Calculation - name: Calculation
description: Lightweight calculator endpoint for retrieving computed values by code or name description: Lightweight calculator endpoint for retrieving computed values by code or name
- name: Order - name: Order
description: Laboratory order management description: Laboratory order management
- name: Result - name: Result
description: Patient results reporting with auto-validation description: Patient results reporting with auto-validation
- name: Report - name: Report
description: Lab report generation (HTML view) description: Lab report generation (HTML view)
- name: Edge API - name: Edge API
description: Instrument integration endpoints description: Instrument integration endpoints
- name: Contact - name: Contact
description: Contact management (doctors, practitioners, etc.) description: Contact management (doctors, practitioners, etc.)
- name: ValueSet - name: ValueSet
description: Value set definitions and items description: Value set definitions and items
- name: User - name: User
description: User management and administration description: User management and administration
- name: Demo - name: Demo
description: Demo/test endpoints (no authentication) description: Demo/test endpoints (no authentication)
- name: Audit - name: Audit
description: Audit log retrieval and filtering description: Audit log retrieval and filtering
components: components:
securitySchemes: securitySchemes:
@ -153,6 +153,10 @@ components:
$ref: './components/schemas/orders.yaml#/OrderTestList' $ref: './components/schemas/orders.yaml#/OrderTestList'
OrderTest: OrderTest:
$ref: './components/schemas/orders.yaml#/OrderTest' $ref: './components/schemas/orders.yaml#/OrderTest'
OrderTestCompact:
$ref: './components/schemas/orders.yaml#/OrderTestCompact'
OrderTestCompactItem:
$ref: './components/schemas/orders.yaml#/OrderTestCompactItem'
OrderItem: OrderItem:
$ref: './components/schemas/orders.yaml#/OrderItem' $ref: './components/schemas/orders.yaml#/OrderItem'
@ -190,13 +194,13 @@ components:
UserListResponse: UserListResponse:
$ref: './components/schemas/user.yaml#/UserListResponse' $ref: './components/schemas/user.yaml#/UserListResponse'
# Rules schemas # Rules schemas
RuleDef: RuleDef:
$ref: './components/schemas/rules.yaml#/RuleDef' $ref: './components/schemas/rules.yaml#/RuleDef'
RuleWithDetails: RuleWithDetails:
$ref: './components/schemas/rules.yaml#/RuleWithDetails' $ref: './components/schemas/rules.yaml#/RuleWithDetails'
TestRule: TestRule:
$ref: './components/schemas/rules.yaml#/TestRule' # Mapping table between rules and tests $ref: './components/schemas/rules.yaml#/TestRule' # Mapping table between rules and tests
# Paths are in separate files in the paths/ directory # Paths are in separate files in the paths/ directory
# To view the complete API with all paths, use: api-docs.bundled.yaml # To view the complete API with all paths, use: api-docs.bundled.yaml

View File

@ -124,6 +124,83 @@ OrderTest:
$ref: '#/OrderTestItem' $ref: '#/OrderTestItem'
description: Test results (patres) for this order 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: OrderSpecimen:
type: object type: object
properties: properties:

View File

@ -196,7 +196,7 @@
get: get:
tags: [Order] tags: [Order]
summary: Get order by ID summary: Get order by ID
description: Returns order details with associated specimens and tests description: Returns compact order details with test list only
security: security:
- bearerAuth: [] - bearerAuth: []
parameters: parameters:
@ -208,7 +208,7 @@
description: Order ID (e.g., 0025030300001) description: Order ID (e.g., 0025030300001)
responses: responses:
'200': '200':
description: Order details with specimens and tests description: Compact order details with tests
content: content:
application/json: application/json:
schema: schema:
@ -219,7 +219,7 @@
message: message:
type: string type: string
data: data:
$ref: '../components/schemas/orders.yaml#/OrderTest' $ref: '../components/schemas/orders.yaml#/OrderTestCompact'
patch: patch:
tags: [Order] tags: [Order]

View File

@ -0,0 +1,118 @@
<?php
declare(strict_types=1);
namespace Tests\Feature\OrderTest;
use App\Models\OrderTest\OrderTestModel;
use App\Models\Patient\PatientModel;
use App\Models\Test\TestDefSiteModel;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;
use Firebase\JWT\JWT;
class OrderTestShowCompactTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected string $token;
protected string $endpoint = 'api/ordertest';
protected function setUp(): void
{
parent::setUp();
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
$payload = [
'iss' => '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);
}
}