From 707d548db079aed0eb5669e5d66694b02d75b0d8 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Mon, 23 Feb 2026 16:49:39 +0700 Subject: [PATCH] feat: implement test mapping functionality with TestMapController and model - Add TestMapController for managing test-to-analyzer mappings - Create TestMapModel with database operations for test mappings - Update TestsController to support test mapping operations - Add testmap API routes to Routes.php - Create migration updates for test definitions table - Add OpenAPI specification for test mapping endpoints - Include unit tests for TestDef models - Update bundled API documentation --- app/Config/Routes.php | 16 + app/Controllers/Test/TestMapController.php | 58 ++++ app/Controllers/TestsController.php | 2 - ...026-01-01-000004_CreateTestDefinitions.php | 2 - app/Models/Test/TestMapModel.php | 20 +- public/api-docs.bundled.yaml | 326 +++++++++++++++++- public/components/schemas/tests.yaml | 6 - public/paths/testmap.yaml | 319 +++++++++++++++++ tests/unit/TestDef/TestDefModelsTest.php | 2 - 9 files changed, 722 insertions(+), 29 deletions(-) create mode 100644 public/paths/testmap.yaml diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 6d79622..3edc63e 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -259,6 +259,22 @@ $routes->group('api', function ($routes) { $routes->patch('/', 'TestsController::update'); }); + // Test Mapping + $routes->group('test', function ($routes) { + $routes->group('testmap', function ($routes) { + $routes->get('/', 'Test\TestMapController::index'); + $routes->get('(:num)', 'Test\TestMapController::show/$1'); + $routes->post('/', 'Test\TestMapController::create'); + $routes->patch('/', 'Test\TestMapController::update'); + $routes->delete('/', 'Test\TestMapController::delete'); + + // Filter routes + $routes->get('by-testsite/(:num)', 'Test\TestMapController::showByTestSite/$1'); + $routes->get('by-host/(:any)/(:any)', 'Test\TestMapController::showByHost/$1/$2'); + $routes->get('by-client/(:any)/(:any)', 'Test\TestMapController::showByClient/$1/$2'); + }); + }); + // Orders $routes->group('ordertest', function ($routes) { $routes->get('/', 'OrderTestController::index'); diff --git a/app/Controllers/Test/TestMapController.php b/app/Controllers/Test/TestMapController.php index dce946c..d57a792 100644 --- a/app/Controllers/Test/TestMapController.php +++ b/app/Controllers/Test/TestMapController.php @@ -66,4 +66,62 @@ class TestMapController extends BaseController { } } + public function delete() { + $input = $this->request->getJSON(true); + $id = $input["TestMapID"] ?? null; + if (!$id) { return $this->failValidationErrors('TestMapID is required.'); } + + try { + $row = $this->model->where('TestMapID', $id)->where('EndDate IS NULL')->first(); + if (empty($row)) { return $this->respond([ 'status' => 'failed', 'message' => "Data not found or already deleted.", 'data' => null ], 404); } + + $this->model->update($id, ['EndDate' => date('Y-m-d H:i:s')]); + return $this->respond([ 'status' => 'success', 'message' => "data deleted successfully", 'data' => $id ], 200); + } catch (\Exception $e) { + return $this->failServerError('Something went wrong: ' . $e->getMessage()); + } + } + + public function showByTestSite($testSiteID = null) { + if (!$testSiteID) { return $this->failValidationErrors('TestSiteID is required.'); } + + $rows = $this->model->getMappingsByTestSite($testSiteID); + if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); } + + $rows = ValueSet::transformLabels($rows, [ + 'HostType' => 'entity_type', + 'ClientType' => 'entity_type', + ]); + + return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200); + } + + public function showByHost($hostType = null, $hostID = null) { + if (!$hostType || !$hostID) { return $this->failValidationErrors('HostType and HostID are required.'); } + + $rows = $this->model->getMappingsByHost($hostType, $hostID); + if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); } + + $rows = ValueSet::transformLabels($rows, [ + 'HostType' => 'entity_type', + 'ClientType' => 'entity_type', + ]); + + return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200); + } + + public function showByClient($clientType = null, $clientID = null) { + if (!$clientType || !$clientID) { return $this->failValidationErrors('ClientType and ClientID are required.'); } + + $rows = $this->model->getMappingsByClient($clientType, $clientID); + if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); } + + $rows = ValueSet::transformLabels($rows, [ + 'HostType' => 'entity_type', + 'ClientType' => 'entity_type', + ]); + + return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200); + } + } diff --git a/app/Controllers/TestsController.php b/app/Controllers/TestsController.php index 1d1b5a7..4a6d259 100644 --- a/app/Controllers/TestsController.php +++ b/app/Controllers/TestsController.php @@ -649,12 +649,10 @@ class TestsController extends BaseController 'TestSiteID' => $testSiteID, 'HostType' => $map['HostType'] ?? null, 'HostID' => $map['HostID'] ?? null, - 'HostDataSource' => $map['HostDataSource'] ?? null, 'HostTestCode' => $map['HostTestCode'] ?? null, 'HostTestName' => $map['HostTestName'] ?? null, 'ClientType' => $map['ClientType'] ?? null, 'ClientID' => $map['ClientID'] ?? null, - 'ClientDataSource' => $map['ClientDataSource'] ?? null, 'ConDefID' => $map['ConDefID'] ?? null, 'ClientTestCode' => $map['ClientTestCode'] ?? null, 'ClientTestName' => $map['ClientTestName'] ?? null diff --git a/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php b/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php index 753d324..6c94c11 100644 --- a/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php +++ b/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php @@ -82,12 +82,10 @@ class CreateTestDefinitions extends Migration { 'TestSiteID' => ['type' => 'INT', 'unsigned' => true, 'null' => false], 'HostType' => ['type' => 'varchar', 'constraint'=> 20, 'null' => true], 'HostID' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], - 'HostDataSource' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], 'HostTestCode' => ['type' => 'varchar', 'constraint'=> 10, 'null' => true], 'HostTestName' => ['type' => 'varchar', 'constraint'=> 100, 'null' => true], 'ClientType' => ['type' => 'varchar', 'constraint'=> 20, 'null' => true], 'ClientID' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], - 'ClientDataSource' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], 'ConDefID' => ['type' => 'INT', 'null' => true], 'ClientTestCode' => ['type' => 'varchar', 'constraint'=> 10, 'null' => true], 'ClientTestName' => ['type' => 'varchar', 'constraint'=> 100, 'null' => true], diff --git a/app/Models/Test/TestMapModel.php b/app/Models/Test/TestMapModel.php index b1c66a2..45f675c 100644 --- a/app/Models/Test/TestMapModel.php +++ b/app/Models/Test/TestMapModel.php @@ -9,20 +9,18 @@ class TestMapModel extends BaseModel { protected $primaryKey = 'TestMapID'; protected $allowedFields = [ 'TestSiteID', - 'HostType', - 'HostID', - 'HostDataSource', - 'HostTestCode', + 'HostType', + 'HostID', + 'HostTestCode', 'HostTestName', - 'ClientType', - 'ClientID', - 'ClientDataSource', + 'ClientType', + 'ClientID', 'ConDefID', - 'ClientTestCode', - 'ClientTestName', - 'CreateDate', + 'ClientTestCode', + 'ClientTestName', + 'CreateDate', 'EndDate' - ]; + ]; protected $useTimestamps = true; protected $createdField = 'CreateDate'; diff --git a/public/api-docs.bundled.yaml b/public/api-docs.bundled.yaml index 2fb2d0a..0c6a05b 100644 --- a/public/api-docs.bundled.yaml +++ b/public/api-docs.bundled.yaml @@ -2556,6 +2556,326 @@ paths: responses: '200': description: Collection method details + /api/test/testmap: + get: + tags: + - Tests + summary: List all test mappings + security: + - bearerAuth: [] + parameters: + - name: page + in: query + schema: + type: integer + default: 1 + description: Page number for pagination + - name: perPage + in: query + schema: + type: integer + default: 20 + description: Number of items per page + responses: + '200': + description: List of test mappings + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMap' + post: + tags: + - Tests + summary: Create test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestSiteID: + type: integer + description: Test Site ID (required) + HostType: + type: string + description: Host type code + HostID: + type: string + description: Host identifier + HostTestCode: + type: string + description: Test code in host system + HostTestName: + type: string + description: Test name in host system + ClientType: + type: string + description: Client type code + ClientID: + type: string + description: Client identifier + ConDefID: + type: integer + description: Connection definition ID + ClientTestCode: + type: string + description: Test code in client system + ClientTestName: + type: string + description: Test name in client system + required: + - TestSiteID + responses: + '201': + description: Test mapping created + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Created TestMapID + patch: + tags: + - Tests + summary: Update test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID (required) + TestSiteID: + type: integer + HostType: + type: string + HostID: + type: string + HostTestCode: + type: string + HostTestName: + type: string + ClientType: + type: string + ClientID: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestMapID + responses: + '200': + description: Test mapping updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Updated TestMapID + delete: + tags: + - Tests + summary: Soft delete test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID to delete (required) + required: + - TestMapID + responses: + '200': + description: Test mapping deleted successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Deleted TestMapID + '404': + description: Test mapping not found or already deleted + /api/test/testmap/{id}: + get: + tags: + - Tests + summary: Get test mapping by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Map ID + responses: + '200': + description: Test mapping details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/TestMap' + '404': + description: Test mapping not found + /api/test/testmap/by-testsite/{testSiteID}: + get: + tags: + - Tests + summary: Get test mappings by test site + security: + - bearerAuth: [] + parameters: + - name: testSiteID + in: path + required: true + schema: + type: integer + description: Test Site ID + responses: + '200': + description: List of test mappings for the test site + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMap' + /api/test/testmap/by-host/{hostType}/{hostID}: + get: + tags: + - Tests + summary: Get test mappings by host + security: + - bearerAuth: [] + parameters: + - name: hostType + in: path + required: true + schema: + type: string + description: Host type code + - name: hostID + in: path + required: true + schema: + type: string + description: Host identifier + responses: + '200': + description: List of test mappings for the host + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMap' + /api/test/testmap/by-client/{clientType}/{clientID}: + get: + tags: + - Tests + summary: Get test mappings by client + security: + - bearerAuth: [] + parameters: + - name: clientType + in: path + required: true + schema: + type: string + description: Client type code + - name: clientID + in: path + required: true + schema: + type: string + description: Client identifier + responses: + '200': + description: List of test mappings for the client + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMap' /api/tests: get: tags: @@ -4567,9 +4887,6 @@ components: HostID: type: string description: Host identifier - HostDataSource: - type: string - description: Host data source HostTestCode: type: string description: Test code in host system @@ -4582,9 +4899,6 @@ components: ClientID: type: string description: Client identifier - ClientDataSource: - type: string - description: Client data source ConDefID: type: integer description: Connection definition ID diff --git a/public/components/schemas/tests.yaml b/public/components/schemas/tests.yaml index 3f38389..f249fcc 100644 --- a/public/components/schemas/tests.yaml +++ b/public/components/schemas/tests.yaml @@ -434,9 +434,6 @@ TestMap: HostID: type: string description: Host identifier - HostDataSource: - type: string - description: Host data source HostTestCode: type: string description: Test code in host system @@ -449,9 +446,6 @@ TestMap: ClientID: type: string description: Client identifier - ClientDataSource: - type: string - description: Client data source ConDefID: type: integer description: Connection definition ID diff --git a/public/paths/testmap.yaml b/public/paths/testmap.yaml new file mode 100644 index 0000000..e2376e8 --- /dev/null +++ b/public/paths/testmap.yaml @@ -0,0 +1,319 @@ +/api/test/testmap: + get: + tags: [Tests] + summary: List all test mappings + security: + - bearerAuth: [] + parameters: + - name: page + in: query + schema: + type: integer + default: 1 + description: Page number for pagination + - name: perPage + in: query + schema: + type: integer + default: 20 + description: Number of items per page + responses: + '200': + description: List of test mappings + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: array + items: + $ref: '../components/schemas/tests.yaml#/TestMap' + + post: + tags: [Tests] + summary: Create test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestSiteID: + type: integer + description: Test Site ID (required) + HostType: + type: string + description: Host type code + HostID: + type: string + description: Host identifier + HostTestCode: + type: string + description: Test code in host system + HostTestName: + type: string + description: Test name in host system + ClientType: + type: string + description: Client type code + ClientID: + type: string + description: Client identifier + ConDefID: + type: integer + description: Connection definition ID + ClientTestCode: + type: string + description: Test code in client system + ClientTestName: + type: string + description: Test name in client system + required: + - TestSiteID + responses: + '201': + description: Test mapping created + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Created TestMapID + + patch: + tags: [Tests] + summary: Update test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID (required) + TestSiteID: + type: integer + HostType: + type: string + HostID: + type: string + HostTestCode: + type: string + HostTestName: + type: string + ClientType: + type: string + ClientID: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestMapID + responses: + '200': + description: Test mapping updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Updated TestMapID + + delete: + tags: [Tests] + summary: Soft delete test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID to delete (required) + required: + - TestMapID + responses: + '200': + description: Test mapping deleted successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Deleted TestMapID + '404': + description: Test mapping not found or already deleted + +/api/test/testmap/{id}: + get: + tags: [Tests] + summary: Get test mapping by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Map ID + responses: + '200': + description: Test mapping details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '../components/schemas/tests.yaml#/TestMap' + '404': + description: Test mapping not found + +/api/test/testmap/by-testsite/{testSiteID}: + get: + tags: [Tests] + summary: Get test mappings by test site + security: + - bearerAuth: [] + parameters: + - name: testSiteID + in: path + required: true + schema: + type: integer + description: Test Site ID + responses: + '200': + description: List of test mappings for the test site + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '../components/schemas/tests.yaml#/TestMap' + +/api/test/testmap/by-host/{hostType}/{hostID}: + get: + tags: [Tests] + summary: Get test mappings by host + security: + - bearerAuth: [] + parameters: + - name: hostType + in: path + required: true + schema: + type: string + description: Host type code + - name: hostID + in: path + required: true + schema: + type: string + description: Host identifier + responses: + '200': + description: List of test mappings for the host + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '../components/schemas/tests.yaml#/TestMap' + +/api/test/testmap/by-client/{clientType}/{clientID}: + get: + tags: [Tests] + summary: Get test mappings by client + security: + - bearerAuth: [] + parameters: + - name: clientType + in: path + required: true + schema: + type: string + description: Client type code + - name: clientID + in: path + required: true + schema: + type: string + description: Client identifier + responses: + '200': + description: List of test mappings for the client + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '../components/schemas/tests.yaml#/TestMap' diff --git a/tests/unit/TestDef/TestDefModelsTest.php b/tests/unit/TestDef/TestDefModelsTest.php index 346d64b..0fd8cd9 100644 --- a/tests/unit/TestDef/TestDefModelsTest.php +++ b/tests/unit/TestDef/TestDefModelsTest.php @@ -167,12 +167,10 @@ class TestDefModelsTest extends CIUnitTestCase $this->assertContains('TestSiteID', $allowedFields); $this->assertContains('HostType', $allowedFields); $this->assertContains('HostID', $allowedFields); - $this->assertContains('HostDataSource', $allowedFields); $this->assertContains('HostTestCode', $allowedFields); $this->assertContains('HostTestName', $allowedFields); $this->assertContains('ClientType', $allowedFields); $this->assertContains('ClientID', $allowedFields); - $this->assertContains('ClientDataSource', $allowedFields); $this->assertContains('ConDefID', $allowedFields); $this->assertContains('ClientTestCode', $allowedFields); $this->assertContains('ClientTestName', $allowedFields);