feat(ordertest): add PVADTID filter support and sync order API docs
- Add PVADTID query param handling in OrderTestController::index() (supports both PVADTID and pvadtid, with numeric casting). - Extend OrderTestModel::getOrdersByPatient() with optional PVADTID filtering. - Apply PVADTID filtering to general order listing queries. - Update public/paths/orders.yaml to document PVADTID on GET /api/ordertest. - Regenerate public/api-docs.bundled.yaml to keep OpenAPI bundle in sync.
This commit is contained in:
parent
0ec13e404a
commit
4aad7d331a
@ -4,9 +4,9 @@ namespace App\Controllers;
|
||||
use App\Traits\ResponseTrait;
|
||||
use CodeIgniter\Controller;
|
||||
use App\Libraries\ValueSet;
|
||||
use App\Models\OrderTest\OrderTestModel;
|
||||
use App\Models\Patient\PatientModel;
|
||||
use App\Models\PatVisit\PatVisitModel;
|
||||
use App\Models\OrderTest\OrderTestModel;
|
||||
use App\Models\Patient\PatientModel;
|
||||
use App\Models\PatVisit\PatVisitModel;
|
||||
|
||||
class OrderTestController extends Controller {
|
||||
use ResponseTrait;
|
||||
@ -29,14 +29,22 @@ class OrderTestController extends Controller {
|
||||
|
||||
public function index() {
|
||||
$internalPID = $this->request->getVar('InternalPID');
|
||||
$pvadtid = $this->request->getVar('PVADTID') ?? $this->request->getVar('pvadtid');
|
||||
$pvadtid = is_numeric($pvadtid) ? (int) $pvadtid : null;
|
||||
$includeDetails = $this->request->getVar('include') === 'details';
|
||||
|
||||
try {
|
||||
if ($internalPID) {
|
||||
$rows = $this->model->getOrdersByPatient($internalPID);
|
||||
$rows = $this->model->getOrdersByPatient((int) $internalPID, $pvadtid);
|
||||
} else {
|
||||
$rows = $this->db->table('ordertest')
|
||||
->where('DelDate', null)
|
||||
$builder = $this->db->table('ordertest')
|
||||
->where('DelDate', null);
|
||||
|
||||
if ($pvadtid !== null) {
|
||||
$builder->where('PVADTID', $pvadtid);
|
||||
}
|
||||
|
||||
$rows = $builder
|
||||
->orderBy('TrnDate', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
@ -179,35 +187,35 @@ class OrderTestController extends Controller {
|
||||
$order['Specimens'] = $this->getOrderSpecimens($order['InternalOID']);
|
||||
$order['Tests'] = $this->getOrderTests($order['InternalOID']);
|
||||
|
||||
// Rule engine triggers are fired at the test/result level (test_created, result_updated)
|
||||
|
||||
return $this->respondCreated([
|
||||
'status' => 'success',
|
||||
'message' => 'Order created successfully',
|
||||
'data' => $order
|
||||
], 201);
|
||||
// Rule engine triggers are fired at the test/result level (test_created, result_updated)
|
||||
|
||||
return $this->respondCreated([
|
||||
'status' => 'success',
|
||||
'message' => 'Order created successfully',
|
||||
'data' => $order
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function update($OrderID = null) {
|
||||
$input = $this->request->getJSON(true);
|
||||
|
||||
if ($OrderID === null || $OrderID === '') {
|
||||
return $this->failValidationErrors(['OrderID' => 'OrderID is required']);
|
||||
}
|
||||
|
||||
if (isset($input['OrderID']) && (string) $input['OrderID'] !== (string) $OrderID) {
|
||||
return $this->failValidationErrors(['OrderID' => 'OrderID in URL does not match body']);
|
||||
}
|
||||
|
||||
try {
|
||||
$input['OrderID'] = $OrderID;
|
||||
$order = $this->model->getOrder($OrderID);
|
||||
if (!$order) {
|
||||
return $this->failNotFound('Order not found');
|
||||
}
|
||||
public function update($OrderID = null) {
|
||||
$input = $this->request->getJSON(true);
|
||||
|
||||
if ($OrderID === null || $OrderID === '') {
|
||||
return $this->failValidationErrors(['OrderID' => 'OrderID is required']);
|
||||
}
|
||||
|
||||
if (isset($input['OrderID']) && (string) $input['OrderID'] !== (string) $OrderID) {
|
||||
return $this->failValidationErrors(['OrderID' => 'OrderID in URL does not match body']);
|
||||
}
|
||||
|
||||
try {
|
||||
$input['OrderID'] = $OrderID;
|
||||
$order = $this->model->getOrder($OrderID);
|
||||
if (!$order) {
|
||||
return $this->failNotFound('Order not found');
|
||||
}
|
||||
|
||||
$updateData = [];
|
||||
if (isset($input['Priority'])) $updateData['Priority'] = $input['Priority'];
|
||||
@ -220,9 +228,9 @@ class OrderTestController extends Controller {
|
||||
$this->model->update($order['InternalOID'], $updateData);
|
||||
}
|
||||
|
||||
$updatedOrder = $this->model->getOrder($OrderID);
|
||||
$updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']);
|
||||
$updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']);
|
||||
$updatedOrder = $this->model->getOrder($OrderID);
|
||||
$updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']);
|
||||
$updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']);
|
||||
|
||||
return $this->respond([
|
||||
'status' => 'success',
|
||||
|
||||
@ -161,25 +161,25 @@ class OrderTestModel extends BaseModel {
|
||||
}
|
||||
}
|
||||
|
||||
// Insert unique tests into patres with specimen links
|
||||
if (!empty($testToOrder)) {
|
||||
$resModel = new \App\Models\PatResultModel();
|
||||
$patientModel = new \App\Models\Patient\PatientModel();
|
||||
$patient = $patientModel->find((int) $data['InternalPID']);
|
||||
$age = null;
|
||||
if (is_array($patient) && !empty($patient['Birthdate'])) {
|
||||
try {
|
||||
$birthdate = new \DateTime((string) $patient['Birthdate']);
|
||||
$age = (new \DateTime())->diff($birthdate)->y;
|
||||
} catch (\Throwable $e) {
|
||||
$age = null;
|
||||
}
|
||||
}
|
||||
|
||||
$ruleEngine = new \App\Services\RuleEngineService();
|
||||
|
||||
foreach ($testToOrder as $tid => $tinfo) {
|
||||
$specimenInfo = $specimenConDefMap[$tid] ?? null;
|
||||
// Insert unique tests into patres with specimen links
|
||||
if (!empty($testToOrder)) {
|
||||
$resModel = new \App\Models\PatResultModel();
|
||||
$patientModel = new \App\Models\Patient\PatientModel();
|
||||
$patient = $patientModel->find((int) $data['InternalPID']);
|
||||
$age = null;
|
||||
if (is_array($patient) && !empty($patient['Birthdate'])) {
|
||||
try {
|
||||
$birthdate = new \DateTime((string) $patient['Birthdate']);
|
||||
$age = (new \DateTime())->diff($birthdate)->y;
|
||||
} catch (\Throwable $e) {
|
||||
$age = null;
|
||||
}
|
||||
}
|
||||
|
||||
$ruleEngine = new \App\Services\RuleEngineService();
|
||||
|
||||
foreach ($testToOrder as $tid => $tinfo) {
|
||||
$specimenInfo = $specimenConDefMap[$tid] ?? null;
|
||||
|
||||
$patResData = [
|
||||
'OrderID' => $internalOID,
|
||||
@ -191,32 +191,32 @@ class OrderTestModel extends BaseModel {
|
||||
'CreateDate' => date('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
if ($specimenInfo) {
|
||||
$patResData['InternalSID'] = $specimenInfo['InternalSID'];
|
||||
}
|
||||
|
||||
$resModel->insert($patResData);
|
||||
|
||||
// Fire test_created rules after the test row is persisted
|
||||
try {
|
||||
$ruleEngine->run('test_created', [
|
||||
'order' => [
|
||||
'InternalOID' => $internalOID,
|
||||
'Priority' => $orderData['Priority'] ?? 'R',
|
||||
'TestSiteID' => $tid,
|
||||
],
|
||||
'patient' => [
|
||||
'Sex' => is_array($patient) ? ($patient['Sex'] ?? null) : null,
|
||||
],
|
||||
'age' => $age,
|
||||
'testSiteID' => $tid,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'OrderTestModel::createOrder rule engine error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($specimenInfo) {
|
||||
$patResData['InternalSID'] = $specimenInfo['InternalSID'];
|
||||
}
|
||||
|
||||
$resModel->insert($patResData);
|
||||
|
||||
// Fire test_created rules after the test row is persisted
|
||||
try {
|
||||
$ruleEngine->run('test_created', [
|
||||
'order' => [
|
||||
'InternalOID' => $internalOID,
|
||||
'Priority' => $orderData['Priority'] ?? 'R',
|
||||
'TestSiteID' => $tid,
|
||||
],
|
||||
'patient' => [
|
||||
'Sex' => is_array($patient) ? ($patient['Sex'] ?? null) : null,
|
||||
],
|
||||
'age' => $age,
|
||||
'testSiteID' => $tid,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'OrderTestModel::createOrder rule engine error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->transComplete();
|
||||
|
||||
@ -299,10 +299,16 @@ class OrderTestModel extends BaseModel {
|
||||
->getRowArray();
|
||||
}
|
||||
|
||||
public function getOrdersByPatient(int $internalPID): array {
|
||||
return $this->select('*')
|
||||
public function getOrdersByPatient(int $internalPID, ?int $pvadtid = null): array {
|
||||
$builder = $this->select('*')
|
||||
->where('InternalPID', $internalPID)
|
||||
->where('DelDate', null)
|
||||
->where('DelDate', null);
|
||||
|
||||
if ($pvadtid !== null) {
|
||||
$builder->where('PVADTID', $pvadtid);
|
||||
}
|
||||
|
||||
return $builder
|
||||
->orderBy('TrnDate', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/api/ordertest:
|
||||
get:
|
||||
tags: [Order]
|
||||
get:
|
||||
tags: [Order]
|
||||
summary: List orders
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@ -18,6 +18,11 @@
|
||||
schema:
|
||||
type: integer
|
||||
description: Filter by internal patient ID
|
||||
- name: PVADTID
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
description: Filter by patient visit ADT ID
|
||||
- name: OrderStatus
|
||||
in: query
|
||||
schema:
|
||||
@ -47,8 +52,8 @@
|
||||
items:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTestList'
|
||||
|
||||
post:
|
||||
tags: [Order]
|
||||
post:
|
||||
tags: [Order]
|
||||
summary: Create order with specimens and tests
|
||||
description: Creates an order with associated specimens and patres records. Tests are grouped by container type to minimize specimen creation.
|
||||
security:
|
||||
@ -124,8 +129,8 @@
|
||||
description: Server error
|
||||
|
||||
|
||||
delete:
|
||||
tags: [Order]
|
||||
delete:
|
||||
tags: [Order]
|
||||
summary: Delete order
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@ -144,9 +149,9 @@
|
||||
'200':
|
||||
description: Order deleted
|
||||
|
||||
/api/ordertest/status:
|
||||
post:
|
||||
tags: [Order]
|
||||
/api/ordertest/status:
|
||||
post:
|
||||
tags: [Order]
|
||||
summary: Update order status
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@ -187,9 +192,9 @@
|
||||
data:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTest'
|
||||
|
||||
/api/ordertest/{id}:
|
||||
get:
|
||||
tags: [Order]
|
||||
/api/ordertest/{id}:
|
||||
get:
|
||||
tags: [Order]
|
||||
summary: Get order by ID
|
||||
description: Returns order details with associated specimens and tests
|
||||
security:
|
||||
@ -201,63 +206,63 @@
|
||||
schema:
|
||||
type: string
|
||||
description: Order ID (e.g., 0025030300001)
|
||||
responses:
|
||||
'200':
|
||||
description: Order details with specimens and tests
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTest'
|
||||
|
||||
patch:
|
||||
tags: [Order]
|
||||
summary: Update order
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Order ID
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
Priority:
|
||||
type: string
|
||||
enum: [R, S, U]
|
||||
OrderStatus:
|
||||
type: string
|
||||
enum: [ORD, SCH, ANA, VER, REV, REP]
|
||||
OrderingProvider:
|
||||
type: string
|
||||
DepartmentID:
|
||||
type: integer
|
||||
WorkstationID:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Order updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTest'
|
||||
responses:
|
||||
'200':
|
||||
description: Order details with specimens and tests
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTest'
|
||||
|
||||
patch:
|
||||
tags: [Order]
|
||||
summary: Update order
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Order ID
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
Priority:
|
||||
type: string
|
||||
enum: [R, S, U]
|
||||
OrderStatus:
|
||||
type: string
|
||||
enum: [ORD, SCH, ANA, VER, REV, REP]
|
||||
OrderingProvider:
|
||||
type: string
|
||||
DepartmentID:
|
||||
type: integer
|
||||
WorkstationID:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Order updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
data:
|
||||
$ref: '../components/schemas/orders.yaml#/OrderTest'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user