fix: align test members payload with top-level API contract

This commit is contained in:
mahdahar 2026-04-02 04:52:50 +07:00
parent 399f4d615b
commit eeaed768c9
5 changed files with 142 additions and 160 deletions

View File

@ -90,11 +90,11 @@ class TestsController extends BaseController
$typeCode = $row['TestType'] ?? '';
if ($typeCode === 'CALC') {
$row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
$row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
} elseif ($typeCode === 'GROUP') {
$row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
if ($typeCode === 'CALC') {
$row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
$row['members'] = $this->modelGrp->getGroupMembers($id);
} elseif ($typeCode === 'GROUP') {
$row['members'] = $this->modelGrp->getGroupMembers($id);
} elseif ($typeCode !== 'TITLE') {
$refType = $row['RefType'] ?? '';
$resultType = $row['ResultType'] ?? '';
@ -491,7 +491,7 @@ class TestsController extends BaseController
$this->modelGrp->disableByTestSiteID($testSiteID);
}
$memberIDs = $this->resolveCalcMemberIDs($data, $input);
$memberIDs = $this->resolveMemberIDs($input);
// Validate member IDs before insertion
$validation = $this->validateMemberIDs($memberIDs);
@ -507,18 +507,17 @@ class TestsController extends BaseController
}
}
private function resolveCalcMemberIDs(array $data, array $input): array
{
$memberIDs = [];
$rawMembers = $data['members'] ?? ($input['members'] ?? []);
if (is_array($rawMembers)) {
foreach ($rawMembers as $member) {
if (is_array($member)) {
// Only accept TestSiteID, not Member (which might be SeqScr)
$rawID = $member['TestSiteID'] ?? null;
} else {
$rawID = is_numeric($member) ? $member : null;
private function resolveMemberIDs(array $input): array
{
$memberIDs = [];
$rawMembers = $input['members'] ?? [];
if (is_array($rawMembers)) {
foreach ($rawMembers as $member) {
if (is_array($member)) {
$rawID = $member['TestSiteID'] ?? null;
} else {
$rawID = is_numeric($member) ? $member : null;
}
if ($rawID !== null && is_numeric($rawID)) {
@ -557,26 +556,13 @@ class TestsController extends BaseController
];
}
private function saveGroupDetails($testSiteID, $data, $input, $action)
{
if ($action === 'update') {
$this->modelGrp->disableByTestSiteID($testSiteID);
}
$members = $data['members'] ?? ($input['Members'] ?? []);
$memberIDs = [];
if (is_array($members)) {
foreach ($members as $m) {
// Only accept TestSiteID, not Member (which might be SeqScr)
$memberID = is_array($m) ? ($m['TestSiteID'] ?? null) : $m;
if ($memberID && is_numeric($memberID)) {
$memberIDs[] = (int) $memberID;
}
}
}
$memberIDs = array_values(array_unique(array_filter($memberIDs)));
private function saveGroupDetails($testSiteID, $data, $input, $action)
{
if ($action === 'update') {
$this->modelGrp->disableByTestSiteID($testSiteID);
}
$memberIDs = $this->resolveMemberIDs($input);
// Validate member IDs before insertion
$validation = $this->validateMemberIDs($memberIDs);

View File

@ -4671,21 +4671,17 @@ paths:
FormulaCode:
type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
testdefgrp:
type: object
description: Group member payload stored in the `testdefgrp` table.
properties:
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum:
type: array
items:
@ -5100,10 +5096,9 @@ paths:
DepartmentID: 2
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
testdefgrp:
members:
- TestSiteID: 21
- TestSiteID: 22
members:
- TestSiteID: 21
- TestSiteID: 22
CALC_full:
summary: Calculated test with numeric reference ranges and map
value:
@ -5142,10 +5137,9 @@ paths:
DepartmentID: 2
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
testdefgrp:
members:
- TestSiteID: 21
- TestSiteID: 22
members:
- TestSiteID: 21
- TestSiteID: 22
GROUP_with_members:
summary: Group/profile test with members and mapping
value:
@ -5169,10 +5163,9 @@ paths:
ConDefID: 1
ClientTestCode: LIPID_C
ClientTestName: Lipid Client
testdefgrp:
members:
- TestSiteID: 169
- TestSiteID: 170
members:
- TestSiteID: 169
- TestSiteID: 170
responses:
'201':
description: Test definition created
@ -5334,21 +5327,17 @@ paths:
FormulaCode:
type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
testdefgrp:
type: object
description: Group member payload stored in the `testdefgrp` table.
properties:
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum:
type: array
items:
@ -7061,12 +7050,12 @@ components:
description: Calculated test details (only for CALC type)
items:
type: object
testdefgrp:
members:
type: array
description: |
Group members (for GROUP and CALC types).
When creating or updating, provide members in details.members array with TestSiteID field.
Do NOT use Member or SeqScr fields when creating/updating.
When creating or updating, provide members in members array with TestSiteID field.
Do NOT use Member, SeqScr, or Members fields when creating/updating.
items:
type: object
properties:
@ -7080,7 +7069,7 @@ components:
type: integer
description: |
Member TestSiteID (foreign key to testdefsite).
**Note**: This field is in the response. When creating/updating, use TestSiteID in details.members array instead.
**Note**: This field is in the response. When creating/updating, use TestSiteID in members array instead.
TestSiteCode:
type: string
description: Member test code
@ -7349,7 +7338,7 @@ components:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
Unit1: mL/min/1.73m2
Decimal: 0
testdefgrp:
members:
- TestSiteID: 21
TestSiteCode: CREA
TestSiteName: Creatinine
@ -7391,7 +7380,7 @@ components:
isVisibleScr: 1
isVisibleRpt: 1
isCountStat: 1
testdefgrp:
members:
- TestGrpID: 1
TestSiteID: 6
Member: 100

View File

@ -183,26 +183,26 @@ TestDefinition:
description: Calculated test details (only for CALC type)
items:
type: object
testdefgrp:
type: array
description: |
Group members (for GROUP and CALC types).
When creating or updating, provide members in details.members array with TestSiteID field.
Do NOT use Member or SeqScr fields when creating/updating.
members:
type: array
description: |
Group members (for GROUP and CALC types).
When creating or updating, provide members in members array with TestSiteID field.
Do NOT use Member, SeqScr, or Members fields when creating/updating.
items:
type: object
properties:
TestGrpID:
type: integer
description: Group membership record ID
TestSiteID:
type: integer
description: Parent group TestSiteID
Member:
type: integer
description: |
Member TestSiteID (foreign key to testdefsite).
**Note**: This field is in the response. When creating/updating, use TestSiteID in details.members array instead.
TestSiteID:
type: integer
description: Parent group TestSiteID
Member:
type: integer
description: |
Member TestSiteID (foreign key to testdefsite).
**Note**: This field is in the response. When creating/updating, use TestSiteID in members array instead.
TestSiteCode:
type: string
description: Member test code
@ -467,11 +467,11 @@ TestDefinition:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
Unit1: mL/min/1.73m2
Decimal: 0
testdefgrp:
- TestSiteID: 21
TestSiteCode: CREA
TestSiteName: Creatinine
TestType: TEST
members:
- TestSiteID: 21
TestSiteCode: CREA
TestSiteName: Creatinine
TestType: TEST
- TestSiteID: 51
TestSiteCode: AGE
TestSiteName: Age
@ -509,10 +509,10 @@ TestDefinition:
isVisibleScr: 1
isVisibleRpt: 1
isCountStat: 1
testdefgrp:
- TestGrpID: 1
TestSiteID: 6
Member: 100
members:
- TestGrpID: 1
TestSiteID: 6
Member: 100
MemberTestSiteID: 100
TestSiteCode: CHOL
TestSiteName: Total Cholesterol

View File

@ -185,21 +185,17 @@
FormulaCode:
type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
testdefgrp:
type: object
description: Group member payload stored in the `testdefgrp` table.
properties:
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum:
type: array
items:
@ -612,12 +608,11 @@
isCountStat: 0
DisciplineID: 2
DepartmentID: 2
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
testdefgrp:
members:
- TestSiteID: 21
- TestSiteID: 22
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
members:
- TestSiteID: 21
- TestSiteID: 22
CALC_full:
summary: Calculated test with numeric reference ranges and map
value:
@ -654,12 +649,11 @@
ClientTestName: eGFR Client
DisciplineID: 2
DepartmentID: 2
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
testdefgrp:
members:
- TestSiteID: 21
- TestSiteID: 22
testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER)
members:
- TestSiteID: 21
- TestSiteID: 22
GROUP_with_members:
summary: Group/profile test with members and mapping
value:
@ -683,10 +677,9 @@
ConDefID: 1
ClientTestCode: LIPID_C
ClientTestName: Lipid Client
testdefgrp:
members:
- TestSiteID: 169
- TestSiteID: 170
members:
- TestSiteID: 169
- TestSiteID: 170
responses:
'201':
@ -834,21 +827,17 @@
FormulaCode:
type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
testdefgrp:
type: object
description: Group member payload stored in the `testdefgrp` table.
properties:
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
members:
type: array
description: Array of member TestSiteIDs for CALC/GROUP definitions.
items:
type: object
properties:
TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum:
type: array
items:

View File

@ -359,6 +359,17 @@ class TestCreateVariantsTest extends CIUnitTestCase
$this->assertArrayHasKey('data', $json);
$this->assertArrayHasKey('TestSiteId', $json['data']);
$this->assertIsInt($json['data']['TestSiteId']);
$show = $this->call('get', $this->endpoint . '/' . $json['data']['TestSiteId']);
$show->assertStatus(200);
$showData = json_decode($show->getJSON(), true)['data'];
$this->assertArrayHasKey('members', $showData);
$this->assertArrayNotHasKey('testdefgrp', $showData);
if ($members !== []) {
$this->assertCount(count($members), $showData['members']);
}
}
private function assertTechnicalCreated(
@ -390,6 +401,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
$this->assertArrayHasKey('data', $json);
$this->assertArrayHasKey('TestSiteId', $json['data']);
$this->assertIsInt($json['data']['TestSiteId']);
}
private function assertCalculatedCreated(
@ -418,6 +430,14 @@ class TestCreateVariantsTest extends CIUnitTestCase
$this->assertArrayHasKey('data', $json);
$this->assertArrayHasKey('TestSiteId', $json['data']);
$this->assertIsInt($json['data']['TestSiteId']);
$show = $this->call('get', $this->endpoint . '/' . $json['data']['TestSiteId']);
$show->assertStatus(200);
$showData = json_decode($show->getJSON(), true)['data'];
$this->assertArrayHasKey('members', $showData);
$this->assertArrayNotHasKey('testdefgrp', $showData);
$this->assertCount(count($members), $showData['members']);
}
private function buildTechnicalPayload(string $testType, array $details = []): array
@ -451,11 +471,11 @@ class TestCreateVariantsTest extends CIUnitTestCase
'isVisibleScr' => 1,
'isVisibleRpt' => 1,
'isCountStat' => 0,
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
'details' => [
'DisciplineID' => 2,
'DepartmentID' => 2,
'FormulaCode' => '{GLU} + {CREA}',
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
],
];
@ -474,9 +494,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
'isVisibleScr' => 1,
'isVisibleRpt' => 1,
'isCountStat' => 1,
'details' => [
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
],
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
'testmap' => $testmap,
];
}
@ -491,7 +509,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
'Decimal' => array_key_exists('Decimal', $details) ? $details['Decimal'] : 0,
];
foreach (['ResultType', 'RefType', 'FormulaCode', 'members', 'ExpectedTAT', 'Factor', 'ReqQty', 'ReqQtyUnit', 'Unit2', 'VSet', 'CollReq'] as $key) {
foreach (['ResultType', 'RefType', 'FormulaCode', 'ExpectedTAT', 'Factor', 'ReqQty', 'ReqQtyUnit', 'Unit2', 'VSet', 'CollReq'] as $key) {
if (array_key_exists($key, $details)) {
$normalized[$key] = $details[$key];
}