2025-11-26 16:53:14 +07:00
|
|
|
<?php
|
|
|
|
|
namespace App\Controllers;
|
|
|
|
|
|
|
|
|
|
use CodeIgniter\API\ResponseTrait;
|
|
|
|
|
use App\Controllers\BaseController;
|
|
|
|
|
|
|
|
|
|
class Tests extends BaseController {
|
2025-12-17 07:03:16 +07:00
|
|
|
use ResponseTrait;
|
2025-11-26 16:53:14 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
protected $db;
|
|
|
|
|
protected $rules;
|
|
|
|
|
protected $model;
|
|
|
|
|
protected $modelCal;
|
|
|
|
|
protected $modelTech;
|
|
|
|
|
protected $modelGrp;
|
|
|
|
|
protected $modelValueSet;
|
2025-11-26 16:53:14 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
public function __construct() {
|
|
|
|
|
$this->db = \Config\Database::connect();
|
|
|
|
|
$this->model = new \App\Models\Test\TestDefSiteModel;
|
|
|
|
|
$this->modelCal = new \App\Models\Test\TestDefCalModel;
|
|
|
|
|
$this->modelTech = new \App\Models\Test\TestDefTechModel;
|
2025-12-17 10:06:05 +07:00
|
|
|
$this->modelGrp = new \App\Models\Test\TestDefGrpModel;
|
2025-12-17 07:03:16 +07:00
|
|
|
$this->modelValueSet = new \App\Models\ValueSet\ValueSetModel;
|
2025-12-17 10:06:05 +07:00
|
|
|
|
|
|
|
|
// Basic validation for the main part
|
|
|
|
|
$this->rules = [
|
|
|
|
|
'TestSiteCode' => 'required',
|
|
|
|
|
'TestSiteName' => 'required',
|
|
|
|
|
'TestType' => 'required'
|
|
|
|
|
];
|
2025-12-17 07:03:16 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function index() {
|
|
|
|
|
$rows = $this->model->getTests();
|
2025-12-17 10:06:05 +07:00
|
|
|
if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); }
|
2025-12-17 07:03:16 +07:00
|
|
|
return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200);
|
|
|
|
|
}
|
2025-11-26 16:53:14 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
public function show($id = null) {
|
2025-12-17 10:06:05 +07:00
|
|
|
if (!$id) return $this->failValidationErrors('ID is required');
|
2025-12-17 07:03:16 +07:00
|
|
|
$rows = $this->model->getTest($id);
|
2025-12-17 10:06:05 +07:00
|
|
|
if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200); }
|
2025-12-17 07:03:16 +07:00
|
|
|
return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function create() {
|
|
|
|
|
$input = $this->request->getJSON(true);
|
2025-12-17 10:06:05 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
if (!$this->validateData($input, $this->rules)) {
|
2025-12-17 10:06:05 +07:00
|
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
2025-11-26 16:53:14 +07:00
|
|
|
}
|
|
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
$this->db->transStart();
|
|
|
|
|
|
|
|
|
|
try {
|
2025-12-17 10:06:05 +07:00
|
|
|
// 1. Insert into Main Table (testdefsite)
|
2025-12-17 07:03:16 +07:00
|
|
|
$id = $this->model->insert($input);
|
2025-12-17 10:06:05 +07:00
|
|
|
if (!$id) {
|
|
|
|
|
throw new \Exception("Failed to insert main test definition");
|
2025-12-17 07:03:16 +07:00
|
|
|
}
|
|
|
|
|
|
2025-12-17 10:06:05 +07:00
|
|
|
// 2. Handle Details based on TestType
|
|
|
|
|
$this->handleDetails($id, $input, 'insert');
|
|
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
$this->db->transComplete();
|
|
|
|
|
|
|
|
|
|
if ($this->db->transStatus() === false) {
|
|
|
|
|
return $this->failServerError('Transaction failed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->respondCreated([ 'status' => 'success', 'message' => "data created successfully", 'data'=> $id ]);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
$this->db->transRollback();
|
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
2025-11-26 16:53:14 +07:00
|
|
|
}
|
2025-12-17 07:03:16 +07:00
|
|
|
}
|
2025-11-26 16:53:14 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
public function update($id = null) {
|
|
|
|
|
$input = $this->request->getJSON(true);
|
|
|
|
|
|
2025-12-17 10:06:05 +07:00
|
|
|
// Determine ID
|
|
|
|
|
if (!$id && isset($input["TestSiteID"])) { $id = $input["TestSiteID"]; }
|
2025-12-17 07:03:16 +07:00
|
|
|
if (!$id) { return $this->failValidationErrors('TestSiteID is required.'); }
|
|
|
|
|
|
2025-12-17 10:06:05 +07:00
|
|
|
// Optional validation
|
|
|
|
|
// if (!$this->validateData($input, $this->rules)) { ... }
|
|
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
$this->db->transStart();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 1. Update Main Table
|
|
|
|
|
$this->model->update($id, $input);
|
|
|
|
|
|
2025-12-17 10:06:05 +07:00
|
|
|
// 2. Handle Details
|
|
|
|
|
$this->handleDetails($id, $input, 'update');
|
2025-12-17 07:03:16 +07:00
|
|
|
|
|
|
|
|
$this->db->transComplete();
|
2025-11-26 16:53:14 +07:00
|
|
|
|
2025-12-17 07:03:16 +07:00
|
|
|
if ($this->db->transStatus() === false) {
|
|
|
|
|
return $this->failServerError('Transaction failed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->respondCreated([ 'status' => 'success', 'message' => "data updated successfully", 'data'=> $id ]);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
$this->db->transRollback();
|
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-17 10:06:05 +07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper to handle inserting/updating sub-tables based on TestType
|
|
|
|
|
*/
|
|
|
|
|
private function handleDetails($testSiteID, $input, $action) {
|
|
|
|
|
$testTypeID = $input['TestType'] ?? null;
|
|
|
|
|
|
|
|
|
|
// If update and TestType not in payload, fetch from DB
|
|
|
|
|
if (!$testTypeID && $action === 'update') {
|
|
|
|
|
$existing = $this->model->find($testSiteID);
|
|
|
|
|
$testTypeID = $existing['TestType'] ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$testTypeID) return; // Should not happen if required
|
|
|
|
|
|
|
|
|
|
// Get Type Code (TEST, PARAM, CALC, GROUP, TITLE)
|
|
|
|
|
$vs = $this->modelValueSet->find($testTypeID);
|
|
|
|
|
$typeCode = $vs['VValue'] ?? '';
|
|
|
|
|
|
|
|
|
|
// Get details data if present (for 'details' key in unified JSON)
|
|
|
|
|
// We accept both flat (top-level) and nested 'details' for flexibility, prefer 'details'
|
|
|
|
|
$details = $input['details'] ?? $input;
|
|
|
|
|
$details['TestSiteID'] = $testSiteID; // Ensure foreign key is set
|
|
|
|
|
$details['SiteID'] = $input['SiteID'] ?? 1;
|
|
|
|
|
|
|
|
|
|
switch ($typeCode) {
|
|
|
|
|
case 'CALC':
|
|
|
|
|
$this->saveSubTable($this->modelCal, $testSiteID, $details, $action, 'TestCalID');
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'GROUP':
|
|
|
|
|
// Groups are special: List of members
|
|
|
|
|
// Payload expected: details: { members: [{Member: 1}, {Member: 2}] }
|
|
|
|
|
if ($action === 'update') {
|
|
|
|
|
$this->modelGrp->where('TestSiteID', $testSiteID)->delete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$members = $details['members'] ?? ($input['Members'] ?? []);
|
|
|
|
|
if (is_array($members)) {
|
|
|
|
|
foreach ($members as $m) {
|
|
|
|
|
$memberID = is_array($m) ? ($m['Member'] ?? null) : $m;
|
|
|
|
|
if ($memberID) {
|
|
|
|
|
$this->modelGrp->insert([
|
|
|
|
|
'SiteID' => $details['SiteID'],
|
|
|
|
|
'TestSiteID' => $testSiteID,
|
|
|
|
|
'Member' => $memberID
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'TEST':
|
|
|
|
|
case 'PARAM':
|
|
|
|
|
default:
|
|
|
|
|
// Default to TestDefTech for 'TEST' and 'PARAM'
|
|
|
|
|
$this->saveSubTable($this->modelTech, $testSiteID, $details, $action, 'TestTechID');
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function saveSubTable($model, $testSiteID, $data, $action, $pkName) {
|
|
|
|
|
if ($action === 'update') {
|
|
|
|
|
// Check existence
|
|
|
|
|
$exists = $model->where('TestSiteID', $testSiteID)->first();
|
|
|
|
|
if ($exists) {
|
|
|
|
|
$model->update($exists[$pkName], $data);
|
|
|
|
|
} else {
|
|
|
|
|
$model->insert($data);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$model->insert($data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-26 16:53:14 +07:00
|
|
|
}
|