fix: wrap test group members under testdefgrp

Align CALC/GROUP request and response payloads to use the testdefgrp.members structure in controller handling, feature tests, and OpenAPI schemas/examples for a consistent API contract.
This commit is contained in:
mahdahar 2026-04-02 09:06:42 +07:00
parent eeaed768c9
commit 694c5a6211
5 changed files with 235 additions and 191 deletions

View File

@ -92,9 +92,13 @@ class TestsController extends BaseController
if ($typeCode === 'CALC') { if ($typeCode === 'CALC') {
$row['testdefcal'] = $this->modelCal->getByTestSiteID($id); $row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
$row['members'] = $this->modelGrp->getGroupMembers($id); $row['testdefgrp'] = [
'members' => $this->modelGrp->getGroupMembers($id),
];
} elseif ($typeCode === 'GROUP') { } elseif ($typeCode === 'GROUP') {
$row['members'] = $this->modelGrp->getGroupMembers($id); $row['testdefgrp'] = [
'members' => $this->modelGrp->getGroupMembers($id),
];
} elseif ($typeCode !== 'TITLE') { } elseif ($typeCode !== 'TITLE') {
$refType = $row['RefType'] ?? ''; $refType = $row['RefType'] ?? '';
$resultType = $row['ResultType'] ?? ''; $resultType = $row['ResultType'] ?? '';
@ -511,7 +515,7 @@ class TestsController extends BaseController
{ {
$memberIDs = []; $memberIDs = [];
$rawMembers = $input['members'] ?? []; $rawMembers = $input['testdefgrp']['members'] ?? [];
if (is_array($rawMembers)) { if (is_array($rawMembers)) {
foreach ($rawMembers as $member) { foreach ($rawMembers as $member) {
if (is_array($member)) { if (is_array($member)) {

View File

@ -4671,17 +4671,21 @@ paths:
FormulaCode: FormulaCode:
type: string type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}") description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
members: testdefgrp:
type: array type: object
description: Array of member TestSiteIDs for CALC/GROUP definitions. description: Group definition wrapper for CALC/GROUP member assignments.
items: properties:
type: object members:
properties: type: array
TestSiteID: description: Array of member TestSiteIDs for CALC/GROUP definitions.
type: integer items:
description: Foreign key referencing the member test's TestSiteID. type: object
required: properties:
- TestSiteID TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum: refnum:
type: array type: array
items: items:
@ -5096,9 +5100,10 @@ paths:
DepartmentID: 2 DepartmentID: 2
testdefcal: testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER) FormulaCode: CKD_EPI(CREA,AGE,GENDER)
members: testdefgrp:
- TestSiteID: 21 members:
- TestSiteID: 22 - TestSiteID: 21
- TestSiteID: 22
CALC_full: CALC_full:
summary: Calculated test with numeric reference ranges and map summary: Calculated test with numeric reference ranges and map
value: value:
@ -5137,9 +5142,10 @@ paths:
DepartmentID: 2 DepartmentID: 2
testdefcal: testdefcal:
FormulaCode: CKD_EPI(CREA,AGE,GENDER) FormulaCode: CKD_EPI(CREA,AGE,GENDER)
members: testdefgrp:
- TestSiteID: 21 members:
- TestSiteID: 22 - TestSiteID: 21
- TestSiteID: 22
GROUP_with_members: GROUP_with_members:
summary: Group/profile test with members and mapping summary: Group/profile test with members and mapping
value: value:
@ -5163,9 +5169,10 @@ paths:
ConDefID: 1 ConDefID: 1
ClientTestCode: LIPID_C ClientTestCode: LIPID_C
ClientTestName: Lipid Client ClientTestName: Lipid Client
members: testdefgrp:
- TestSiteID: 169 members:
- TestSiteID: 170 - TestSiteID: 169
- TestSiteID: 170
responses: responses:
'201': '201':
description: Test definition created description: Test definition created
@ -5327,17 +5334,21 @@ paths:
FormulaCode: FormulaCode:
type: string type: string
description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}") description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
members: testdefgrp:
type: array type: object
description: Array of member TestSiteIDs for CALC/GROUP definitions. description: Group definition wrapper for CALC/GROUP member assignments.
items: properties:
type: object members:
properties: type: array
TestSiteID: description: Array of member TestSiteIDs for CALC/GROUP definitions.
type: integer items:
description: Foreign key referencing the member test's TestSiteID. type: object
required: properties:
- TestSiteID TestSiteID:
type: integer
description: Foreign key referencing the member test's TestSiteID.
required:
- TestSiteID
refnum: refnum:
type: array type: array
items: items:
@ -7050,41 +7061,45 @@ components:
description: Calculated test details (only for CALC type) description: Calculated test details (only for CALC type)
items: items:
type: object type: object
members: testdefgrp:
type: array type: object
description: | description: Group definition payload for GROUP and CALC types.
Group members (for GROUP and CALC types). properties:
When creating or updating, provide members in members array with TestSiteID field. members:
Do NOT use Member, SeqScr, or Members fields when creating/updating. type: array
items: description: |
type: object Group members (for GROUP and CALC types).
properties: When creating or updating, provide members in testdefgrp.members with TestSiteID field.
TestGrpID: Do NOT use Member, SeqScr, or Members fields when creating/updating.
type: integer items:
description: Group membership record ID type: object
TestSiteID: properties:
type: integer TestGrpID:
description: Parent group TestSiteID type: integer
Member: description: Group membership record ID
type: integer TestSiteID:
description: | type: integer
Member TestSiteID (foreign key to testdefsite). description: Parent group TestSiteID
**Note**: This field is in the response. When creating/updating, use TestSiteID in members array instead. Member:
TestSiteCode: type: integer
type: string description: |
description: Member test code Member TestSiteID (foreign key to testdefsite).
TestSiteName: **Note**: This field is in the response. When creating/updating, use TestSiteID in testdefgrp.members instead.
type: string TestSiteCode:
description: Member test name type: string
TestType: description: Member test code
type: string TestSiteName:
description: Member test type type: string
CreateDate: description: Member test name
type: string TestType:
format: date-time type: string
EndDate: description: Member test type
type: string CreateDate:
format: date-time type: string
format: date-time
EndDate:
type: string
format: date-time
testmap: testmap:
type: array type: array
description: Flat test mapping payload for /api/test create/update description: Flat test mapping payload for /api/test create/update
@ -7338,15 +7353,16 @@ components:
FormulaCode: CKD_EPI(CREA,AGE,GENDER) FormulaCode: CKD_EPI(CREA,AGE,GENDER)
Unit1: mL/min/1.73m2 Unit1: mL/min/1.73m2
Decimal: 0 Decimal: 0
members: testdefgrp:
- TestSiteID: 21 members:
TestSiteCode: CREA - TestSiteID: 21
TestSiteName: Creatinine TestSiteCode: CREA
TestType: TEST TestSiteName: Creatinine
- TestSiteID: 51 TestType: TEST
TestSiteCode: AGE - TestSiteID: 51
TestSiteName: Age TestSiteCode: AGE
TestType: PARAM TestSiteName: Age
TestType: PARAM
refnum: refnum:
- RefNumID: 5 - RefNumID: 5
NumRefType: NMRC NumRefType: NMRC
@ -7380,21 +7396,22 @@ components:
isVisibleScr: 1 isVisibleScr: 1
isVisibleRpt: 1 isVisibleRpt: 1
isCountStat: 1 isCountStat: 1
members: testdefgrp:
- TestGrpID: 1 members:
TestSiteID: 6 - TestGrpID: 1
Member: 100 TestSiteID: 6
MemberTestSiteID: 100 Member: 100
TestSiteCode: CHOL MemberTestSiteID: 100
TestSiteName: Total Cholesterol TestSiteCode: CHOL
TestType: TEST TestSiteName: Total Cholesterol
- TestGrpID: 2 TestType: TEST
TestSiteID: 6 - TestGrpID: 2
Member: 101 TestSiteID: 6
MemberTestSiteID: 101 Member: 101
TestSiteCode: TG MemberTestSiteID: 101
TestSiteName: Triglycerides TestSiteCode: TG
TestType: TEST TestSiteName: Triglycerides
TestType: TEST
TITLE: TITLE:
summary: Section header summary: Section header
value: value:

View File

@ -183,41 +183,45 @@ TestDefinition:
description: Calculated test details (only for CALC type) description: Calculated test details (only for CALC type)
items: items:
type: object type: object
members: testdefgrp:
type: array type: object
description: | description: Group definition payload for GROUP and CALC types.
Group members (for GROUP and CALC types). properties:
When creating or updating, provide members in members array with TestSiteID field. members:
Do NOT use Member, SeqScr, or Members fields when creating/updating. type: array
items: description: |
type: object Group members (for GROUP and CALC types).
properties: When creating or updating, provide members in testdefgrp.members with TestSiteID field.
TestGrpID: Do NOT use Member, SeqScr, or Members fields when creating/updating.
type: integer items:
description: Group membership record ID type: object
TestSiteID: properties:
type: integer TestGrpID:
description: Parent group TestSiteID type: integer
Member: description: Group membership record ID
type: integer TestSiteID:
description: | type: integer
Member TestSiteID (foreign key to testdefsite). description: Parent group TestSiteID
**Note**: This field is in the response. When creating/updating, use TestSiteID in members array instead. Member:
TestSiteCode: type: integer
type: string description: |
description: Member test code Member TestSiteID (foreign key to testdefsite).
TestSiteName: **Note**: This field is in the response. When creating/updating, use TestSiteID in testdefgrp.members instead.
type: string TestSiteCode:
description: Member test name type: string
TestType: description: Member test code
type: string TestSiteName:
description: Member test type type: string
CreateDate: description: Member test name
type: string TestType:
format: date-time type: string
EndDate: description: Member test type
type: string CreateDate:
format: date-time type: string
format: date-time
EndDate:
type: string
format: date-time
testmap: testmap:
type: array type: array
description: Flat test mapping payload for /api/test create/update description: Flat test mapping payload for /api/test create/update
@ -467,15 +471,16 @@ TestDefinition:
FormulaCode: CKD_EPI(CREA,AGE,GENDER) FormulaCode: CKD_EPI(CREA,AGE,GENDER)
Unit1: mL/min/1.73m2 Unit1: mL/min/1.73m2
Decimal: 0 Decimal: 0
members: testdefgrp:
- TestSiteID: 21 members:
TestSiteCode: CREA - TestSiteID: 21
TestSiteName: Creatinine TestSiteCode: CREA
TestType: TEST TestSiteName: Creatinine
- TestSiteID: 51 TestType: TEST
TestSiteCode: AGE - TestSiteID: 51
TestSiteName: Age TestSiteCode: AGE
TestType: PARAM TestSiteName: Age
TestType: PARAM
refnum: refnum:
- RefNumID: 5 - RefNumID: 5
NumRefType: NMRC NumRefType: NMRC
@ -509,21 +514,22 @@ TestDefinition:
isVisibleScr: 1 isVisibleScr: 1
isVisibleRpt: 1 isVisibleRpt: 1
isCountStat: 1 isCountStat: 1
members: testdefgrp:
- TestGrpID: 1 members:
TestSiteID: 6 - TestGrpID: 1
Member: 100 TestSiteID: 6
MemberTestSiteID: 100 Member: 100
TestSiteCode: CHOL MemberTestSiteID: 100
TestSiteName: Total Cholesterol TestSiteCode: CHOL
TestType: TEST TestSiteName: Total Cholesterol
- TestGrpID: 2 TestType: TEST
TestSiteID: 6 - TestGrpID: 2
Member: 101 TestSiteID: 6
MemberTestSiteID: 101 Member: 101
TestSiteCode: TG MemberTestSiteID: 101
TestSiteName: Triglycerides TestSiteCode: TG
TestType: TEST TestSiteName: Triglycerides
TestType: TEST
TITLE: TITLE:
summary: Section header summary: Section header
value: value:

View File

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

View File

@ -364,11 +364,12 @@ class TestCreateVariantsTest extends CIUnitTestCase
$show->assertStatus(200); $show->assertStatus(200);
$showData = json_decode($show->getJSON(), true)['data']; $showData = json_decode($show->getJSON(), true)['data'];
$this->assertArrayHasKey('members', $showData); $this->assertArrayHasKey('testdefgrp', $showData);
$this->assertArrayNotHasKey('testdefgrp', $showData); $this->assertArrayHasKey('members', $showData['testdefgrp']);
$this->assertArrayNotHasKey('members', $showData);
if ($members !== []) { if ($members !== []) {
$this->assertCount(count($members), $showData['members']); $this->assertCount(count($members), $showData['testdefgrp']['members']);
} }
} }
@ -435,9 +436,10 @@ class TestCreateVariantsTest extends CIUnitTestCase
$show->assertStatus(200); $show->assertStatus(200);
$showData = json_decode($show->getJSON(), true)['data']; $showData = json_decode($show->getJSON(), true)['data'];
$this->assertArrayHasKey('members', $showData); $this->assertArrayHasKey('testdefgrp', $showData);
$this->assertArrayNotHasKey('testdefgrp', $showData); $this->assertArrayHasKey('members', $showData['testdefgrp']);
$this->assertCount(count($members), $showData['members']); $this->assertArrayNotHasKey('members', $showData);
$this->assertCount(count($members), $showData['testdefgrp']['members']);
} }
private function buildTechnicalPayload(string $testType, array $details = []): array private function buildTechnicalPayload(string $testType, array $details = []): array
@ -471,7 +473,9 @@ class TestCreateVariantsTest extends CIUnitTestCase
'isVisibleScr' => 1, 'isVisibleScr' => 1,
'isVisibleRpt' => 1, 'isVisibleRpt' => 1,
'isCountStat' => 0, 'isCountStat' => 0,
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members), 'testdefgrp' => [
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
],
'details' => [ 'details' => [
'DisciplineID' => 2, 'DisciplineID' => 2,
'DepartmentID' => 2, 'DepartmentID' => 2,
@ -494,7 +498,9 @@ class TestCreateVariantsTest extends CIUnitTestCase
'isVisibleScr' => 1, 'isVisibleScr' => 1,
'isVisibleRpt' => 1, 'isVisibleRpt' => 1,
'isCountStat' => 1, 'isCountStat' => 1,
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members), 'testdefgrp' => [
'members' => array_map(fn ($id) => ['TestSiteID' => $id], $members),
],
'testmap' => $testmap, 'testmap' => $testmap,
]; ];
} }