Use the base test row's RefType and ResultType to decide refnum/reftxt loading, and fetch discipline/department joins directly in getTestById to avoid redundant relation queries. Add feature coverage for show response behavior and include the related workspace cleanup changes so the branch state is consistent.
637 lines
23 KiB
PHP
637 lines
23 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Test;
|
|
|
|
use App\Controllers\BaseController;
|
|
use App\Libraries\TestValidationService;
|
|
use App\Libraries\ValueSet;
|
|
use App\Traits\ResponseTrait;
|
|
|
|
class TestsController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
|
|
protected $model;
|
|
protected $modelCal;
|
|
protected $modelGrp;
|
|
protected $modelMap;
|
|
protected $modelMapDetail;
|
|
protected $modelRefNum;
|
|
protected $modelRefTxt;
|
|
protected $rules;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->model = new \App\Models\Test\TestDefSiteModel;
|
|
$this->modelCal = new \App\Models\Test\TestDefCalModel;
|
|
$this->modelGrp = new \App\Models\Test\TestDefGrpModel;
|
|
$this->modelMap = new \App\Models\Test\TestMapModel;
|
|
$this->modelMapDetail = new \App\Models\Test\TestMapDetailModel;
|
|
$this->modelRefNum = new \App\Models\RefRange\RefNumModel;
|
|
$this->modelRefTxt = new \App\Models\RefRange\RefTxtModel;
|
|
|
|
$this->rules = [
|
|
'TestSiteCode' => 'required',
|
|
'TestSiteName' => 'required',
|
|
'TestType' => 'required',
|
|
'SiteID' => 'required',
|
|
];
|
|
}
|
|
|
|
public function index()
|
|
{
|
|
$search = $this->request->getGet('search');
|
|
|
|
$filters = [
|
|
'SiteID' => $this->request->getGet('SiteID'),
|
|
'TestType' => $this->request->getGet('TestType'),
|
|
'isVisibleScr' => $this->request->getGet('isVisibleScr'),
|
|
'isVisibleRpt' => $this->request->getGet('isVisibleRpt'),
|
|
'TestSiteName' => $this->request->getGet('TestSiteName'),
|
|
'TestSiteCode' => $this->request->getGet('TestSiteCode'),
|
|
'search' => $search,
|
|
];
|
|
|
|
$rows = $this->model->getTestsWithRelations($filters);
|
|
|
|
if (empty($rows)) {
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'No data.',
|
|
'data' => [],
|
|
], 200);
|
|
}
|
|
|
|
$rows = ValueSet::transformLabels($rows, [
|
|
'TestType' => 'test_type',
|
|
]);
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'Data fetched successfully',
|
|
'data' => $rows,
|
|
], 200);
|
|
}
|
|
|
|
public function show($id = null)
|
|
{
|
|
if (!$id) {
|
|
return $this->failValidationErrors('TestSiteID is required');
|
|
}
|
|
|
|
$row = $this->model->getTestById($id);
|
|
|
|
if (!$row) {
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'No data.',
|
|
'data' => null,
|
|
], 200);
|
|
}
|
|
|
|
$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);
|
|
} elseif ($typeCode !== 'TITLE') {
|
|
$refType = $row['RefType'] ?? '';
|
|
$resultType = $row['ResultType'] ?? '';
|
|
|
|
if (TestValidationService::usesRefNum($resultType, $refType)) {
|
|
$row['refnum'] = $this->modelRefNum->getFormattedByTestSiteID($id);
|
|
}
|
|
|
|
if (TestValidationService::usesRefTxt($resultType, $refType)) {
|
|
$row['reftxt'] = $this->modelRefTxt->getFormattedByTestSiteID($id);
|
|
}
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'Data fetched successfully',
|
|
'data' => $row,
|
|
], 200);
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$input = $this->request->getJSON(true);
|
|
|
|
if (!$this->validateData($input, $this->rules)) {
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
|
}
|
|
|
|
$testType = $input['TestType'] ?? '';
|
|
$details = $input['details'] ?? $input;
|
|
$resultType = $details['ResultType'] ?? '';
|
|
$refType = $details['RefType'] ?? '';
|
|
|
|
if (TestValidationService::isCalc($testType)) {
|
|
$resultType = 'NMRIC';
|
|
$refType = $refType ?: 'RANGE';
|
|
} elseif (TestValidationService::isGroup($testType) || TestValidationService::isTitle($testType)) {
|
|
$resultType = 'NORES';
|
|
$refType = 'NOREF';
|
|
}
|
|
|
|
if ($resultType && $refType) {
|
|
$validation = TestValidationService::validate($testType, $resultType, $refType);
|
|
if (!$validation['valid']) {
|
|
return $this->failValidationErrors(['type_validation' => $validation['error']]);
|
|
}
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$db->transStart();
|
|
|
|
try {
|
|
$testSiteData = [
|
|
'SiteID' => $input['SiteID'],
|
|
'TestSiteCode'=> $input['TestSiteCode'],
|
|
'TestSiteName'=> $input['TestSiteName'],
|
|
'TestType' => $input['TestType'],
|
|
'Description' => $input['Description'] ?? null,
|
|
'SeqScr' => $input['SeqScr'] ?? 0,
|
|
'SeqRpt' => $input['SeqRpt'] ?? 0,
|
|
'IndentLeft' => $input['IndentLeft'] ?? 0,
|
|
'FontStyle' => $input['FontStyle'] ?? null,
|
|
'isVisibleScr' => $input['isVisibleScr'] ?? 1,
|
|
'isVisibleRpt' => $input['isVisibleRpt'] ?? 1,
|
|
'isCountStat' => $input['isCountStat'] ?? 1,
|
|
'StartDate' => $input['StartDate'] ?? date('Y-m-d H:i:s'),
|
|
];
|
|
|
|
$id = $this->model->insert($testSiteData);
|
|
if (!$id) {
|
|
$dbError = $db->error();
|
|
log_message('error', 'Test insert failed: ' . json_encode($dbError, JSON_UNESCAPED_SLASHES));
|
|
$message = $dbError['message'] ?? 'Failed to insert main test definition';
|
|
throw new \Exception('Failed to insert main test definition: ' . $message);
|
|
}
|
|
|
|
$this->handleDetails($id, $input, 'insert');
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
$dbError = $db->error();
|
|
$lastQuery = $db->showLastQuery();
|
|
log_message('error', 'TestController transaction failed: ' . json_encode([
|
|
'error' => $dbError,
|
|
'last_query' => $lastQuery,
|
|
], JSON_UNESCAPED_SLASHES));
|
|
return $this->failServerError('Transaction failed');
|
|
}
|
|
|
|
return $this->respondCreated([
|
|
'status' => 'created',
|
|
'message' => 'Test created successfully',
|
|
'data' => ['TestSiteId' => $id],
|
|
]);
|
|
} catch (\Exception $e) {
|
|
$db->transRollback();
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function update($id = null)
|
|
{
|
|
$input = $this->request->getJSON(true);
|
|
|
|
if (!$id && isset($input['TestSiteID'])) {
|
|
$id = $input['TestSiteID'];
|
|
}
|
|
if (!$id) {
|
|
return $this->failValidationErrors('TestSiteID is required.');
|
|
}
|
|
|
|
$existing = $this->model->find($id);
|
|
if (!$existing) {
|
|
return $this->failNotFound('Test not found');
|
|
}
|
|
|
|
$testType = $input['TestType'] ?? $existing['TestType'] ?? '';
|
|
$details = $input['details'] ?? $input;
|
|
$resultType = $details['ResultType'] ?? $existing['ResultType'] ?? '';
|
|
$refType = $details['RefType'] ?? $existing['RefType'] ?? '';
|
|
|
|
if (TestValidationService::isCalc($testType)) {
|
|
$resultType = 'NMRIC';
|
|
$refType = $refType ?: 'RANGE';
|
|
} elseif (TestValidationService::isGroup($testType) || TestValidationService::isTitle($testType)) {
|
|
$resultType = 'NORES';
|
|
$refType = 'NOREF';
|
|
}
|
|
|
|
if ($resultType && $refType) {
|
|
$validation = TestValidationService::validate($testType, $resultType, $refType);
|
|
if (!$validation['valid']) {
|
|
return $this->failValidationErrors(['type_validation' => $validation['error']]);
|
|
}
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$db->transStart();
|
|
|
|
try {
|
|
$testSiteData = [];
|
|
$allowedUpdateFields = [
|
|
'TestSiteCode',
|
|
'TestSiteName',
|
|
'TestType',
|
|
'Description',
|
|
'SeqScr',
|
|
'SeqRpt',
|
|
'IndentLeft',
|
|
'FontStyle',
|
|
'isVisibleScr',
|
|
'isVisibleRpt',
|
|
'isCountStat',
|
|
'StartDate',
|
|
];
|
|
|
|
foreach ($allowedUpdateFields as $field) {
|
|
if (isset($input[$field])) {
|
|
$testSiteData[$field] = $input[$field];
|
|
}
|
|
}
|
|
|
|
if (!empty($testSiteData)) {
|
|
$this->model->update($id, $testSiteData);
|
|
}
|
|
|
|
$this->handleDetails($id, $input, 'update');
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
return $this->failServerError('Transaction failed');
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'Test updated successfully',
|
|
'data' => ['TestSiteId' => $id],
|
|
]);
|
|
} catch (\Exception $e) {
|
|
$db->transRollback();
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function delete($id = null)
|
|
{
|
|
$input = $this->request->getJSON(true);
|
|
|
|
if (!$id && isset($input['TestSiteID'])) {
|
|
$id = $input['TestSiteID'];
|
|
}
|
|
if (!$id) {
|
|
return $this->failValidationErrors('TestSiteID is required.');
|
|
}
|
|
|
|
$existing = $this->model->find($id);
|
|
if (!$existing) {
|
|
return $this->failNotFound('Test not found');
|
|
}
|
|
|
|
if (!empty($existing['EndDate'])) {
|
|
return $this->failValidationErrors('Test is already disabled');
|
|
}
|
|
|
|
$db = \Config\Database::connect();
|
|
$db->transStart();
|
|
|
|
try {
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
$this->model->update($id, ['EndDate' => $now]);
|
|
|
|
$testType = $existing['TestType'];
|
|
$typeCode = $testType;
|
|
|
|
if (TestValidationService::isCalc($typeCode)) {
|
|
$this->modelCal->disableByTestSiteID($id);
|
|
$this->modelGrp->disableByTestSiteID($id);
|
|
} elseif (TestValidationService::isGroup($typeCode)) {
|
|
$this->modelGrp->disableByTestSiteID($id);
|
|
} elseif (TestValidationService::isTechnicalTest($typeCode)) {
|
|
$this->modelRefNum->disableByTestSiteID($id);
|
|
$this->modelRefTxt->disableByTestSiteID($id);
|
|
}
|
|
|
|
// Disable testmap by test code
|
|
$testSiteCode = $existing['TestSiteCode'] ?? null;
|
|
if ($testSiteCode) {
|
|
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
|
foreach ($existingMaps as $existingMap) {
|
|
$this->modelMapDetail->disableByTestMapID($existingMap['TestMapID']);
|
|
$this->modelMap->update($existingMap['TestMapID'], ['EndDate' => $now]);
|
|
}
|
|
}
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
return $this->failServerError('Transaction failed');
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'Test disabled successfully',
|
|
'data' => ['TestSiteId' => $id, 'EndDate' => $now],
|
|
]);
|
|
} catch (\Exception $e) {
|
|
$db->transRollback();
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function handleDetails($testSiteID, $input, $action)
|
|
{
|
|
$testTypeID = $input['TestType'] ?? null;
|
|
$testSiteCode = null;
|
|
|
|
if (!$testTypeID && $action === 'update') {
|
|
$existing = $this->model->find($testSiteID);
|
|
$testTypeID = $existing['TestType'] ?? null;
|
|
$testSiteCode = $existing['TestSiteCode'] ?? null;
|
|
}
|
|
|
|
if (!$testTypeID) {
|
|
return;
|
|
}
|
|
|
|
$typeCode = $testTypeID;
|
|
|
|
$details = $input['details'] ?? $input;
|
|
$details['TestSiteID'] = $testSiteID;
|
|
$details['SiteID'] = $input['SiteID'] ?? 1;
|
|
|
|
switch ($typeCode) {
|
|
case 'CALC':
|
|
$this->saveCalcDetails($testSiteID, $details, $input, $action);
|
|
|
|
break;
|
|
|
|
case 'GROUP':
|
|
$this->saveGroupDetails($testSiteID, $details, $input, $action);
|
|
|
|
break;
|
|
|
|
case 'TITLE':
|
|
if (isset($input['testmap']) && is_array($input['testmap'])) {
|
|
$this->saveTestMap($testSiteID, $testSiteCode, $input['testmap'], $action);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'TEST':
|
|
case 'PARAM':
|
|
default:
|
|
$this->saveTechDetails($testSiteID, $details, $action, $typeCode);
|
|
|
|
if (in_array($typeCode, ['TEST', 'PARAM']) && isset($details['RefType'])) {
|
|
$refType = (string) $details['RefType'];
|
|
$resultType = $details['ResultType'] ?? '';
|
|
|
|
if (TestValidationService::usesRefNum($resultType, $refType) && isset($input['refnum']) && is_array($input['refnum'])) {
|
|
$this->saveRefNumRanges($testSiteID, $input['refnum'], $action, $input['SiteID'] ?? 1);
|
|
}
|
|
|
|
if (TestValidationService::usesRefTxt($resultType, $refType) && isset($input['reftxt']) && is_array($input['reftxt'])) {
|
|
$this->saveRefTxtRanges($testSiteID, $input['reftxt'], $action, $input['SiteID'] ?? 1);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if ((TestValidationService::isTechnicalTest($typeCode) || TestValidationService::isCalc($typeCode)) && isset($input['testmap']) && is_array($input['testmap'])) {
|
|
$this->saveTestMap($testSiteID, $testSiteCode, $input['testmap'], $action);
|
|
}
|
|
}
|
|
|
|
private function saveTechDetails($testSiteID, $data, $action, $typeCode)
|
|
{
|
|
$techData = [
|
|
'DisciplineID' => $data['DisciplineID'] ?? null,
|
|
'DepartmentID' => $data['DepartmentID'] ?? null,
|
|
'ResultType' => $data['ResultType'] ?? null,
|
|
'RefType' => $data['RefType'] ?? null,
|
|
'VSet' => $data['VSet'] ?? null,
|
|
'ReqQty' => $data['ReqQty'] ?? null,
|
|
'ReqQtyUnit' => $data['ReqQtyUnit'] ?? null,
|
|
'Unit1' => $data['Unit1'] ?? null,
|
|
'Factor' => $data['Factor'] ?? null,
|
|
'Unit2' => $data['Unit2'] ?? null,
|
|
'Decimal' => $data['Decimal'] ?? 2,
|
|
'CollReq' => $data['CollReq'] ?? null,
|
|
'Method' => $data['Method'] ?? null,
|
|
'ExpectedTAT' => $data['ExpectedTAT'] ?? null,
|
|
];
|
|
|
|
$this->model->update($testSiteID, $techData);
|
|
}
|
|
|
|
private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
|
|
{
|
|
if ($action === 'update') {
|
|
$this->modelRefNum->disableByTestSiteID($testSiteID);
|
|
}
|
|
|
|
$this->modelRefNum->batchInsert($testSiteID, $siteID, $ranges);
|
|
}
|
|
|
|
private function saveRefTxtRanges($testSiteID, $ranges, $action, $siteID)
|
|
{
|
|
if ($action === 'update') {
|
|
$this->modelRefTxt->disableByTestSiteID($testSiteID);
|
|
}
|
|
|
|
$this->modelRefTxt->batchInsert($testSiteID, $siteID, $ranges);
|
|
}
|
|
|
|
private function saveCalcDetails($testSiteID, $data, $input, $action)
|
|
{
|
|
$calcData = [
|
|
'TestSiteID' => $testSiteID,
|
|
'DisciplineID' => $data['DisciplineID'] ?? null,
|
|
'DepartmentID' => $data['DepartmentID'] ?? null,
|
|
'FormulaCode' => $data['FormulaCode'] ?? $data['Formula'] ?? null,
|
|
'ResultType' => 'NMRIC',
|
|
'RefType' => $data['RefType'] ?? 'RANGE',
|
|
'Unit1' => $data['Unit1'] ?? $data['ResultUnit'] ?? null,
|
|
'Factor' => $data['Factor'] ?? null,
|
|
'Unit2' => $data['Unit2'] ?? null,
|
|
'Decimal' => $data['Decimal'] ?? 2,
|
|
'Method' => $data['Method'] ?? null,
|
|
];
|
|
|
|
if ($action === 'update') {
|
|
$exists = $this->modelCal->existsByTestSiteID($testSiteID);
|
|
|
|
if ($exists) {
|
|
$this->modelCal->update($exists['TestCalID'], $calcData);
|
|
} else {
|
|
$this->modelCal->insert($calcData);
|
|
}
|
|
} else {
|
|
$this->modelCal->insert($calcData);
|
|
}
|
|
|
|
if ($action === 'update') {
|
|
$this->modelGrp->disableByTestSiteID($testSiteID);
|
|
}
|
|
|
|
$memberIDs = $this->resolveCalcMemberIDs($data, $input);
|
|
|
|
// Validate member IDs before insertion
|
|
$validation = $this->validateMemberIDs($memberIDs);
|
|
if (!$validation['valid']) {
|
|
throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.');
|
|
}
|
|
|
|
foreach ($memberIDs as $memberID) {
|
|
$this->modelGrp->insert([
|
|
'TestSiteID' => $testSiteID,
|
|
'Member' => $memberID,
|
|
]);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if ($rawID !== null && is_numeric($rawID)) {
|
|
$memberIDs[] = (int) $rawID;
|
|
}
|
|
}
|
|
}
|
|
|
|
$memberIDs = array_values(array_unique(array_filter($memberIDs)));
|
|
|
|
return $memberIDs;
|
|
}
|
|
|
|
/**
|
|
* Validate that member IDs exist in testdefsite table
|
|
*
|
|
* @param array $memberIDs Array of TestSiteID values to validate
|
|
* @return array ['valid' => bool, 'invalid' => array]
|
|
*/
|
|
private function validateMemberIDs(array $memberIDs): array
|
|
{
|
|
if (empty($memberIDs)) {
|
|
return ['valid' => true, 'invalid' => []];
|
|
}
|
|
|
|
$existing = $this->model->whereIn('TestSiteID', $memberIDs)
|
|
->where('EndDate IS NULL')
|
|
->findAll();
|
|
|
|
$existingIDs = array_column($existing, 'TestSiteID');
|
|
$invalidIDs = array_diff($memberIDs, $existingIDs);
|
|
|
|
return [
|
|
'valid' => empty($invalidIDs),
|
|
'invalid' => array_values($invalidIDs)
|
|
];
|
|
}
|
|
|
|
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)));
|
|
|
|
// Validate member IDs before insertion
|
|
$validation = $this->validateMemberIDs($memberIDs);
|
|
if (!$validation['valid']) {
|
|
throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.');
|
|
}
|
|
|
|
foreach ($memberIDs as $memberID) {
|
|
$this->modelGrp->insert([
|
|
'TestSiteID' => $testSiteID,
|
|
'Member' => $memberID,
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function saveTestMap($testSiteID, $testSiteCode, $mappings, $action)
|
|
{
|
|
if ($action === 'update' && $testSiteCode) {
|
|
// Find existing mappings by test code through testmapdetail
|
|
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
|
|
|
foreach ($existingMaps as $existingMap) {
|
|
$this->modelMapDetail->disableByTestMapID($existingMap['TestMapID']);
|
|
}
|
|
|
|
// Soft delete the testmap headers
|
|
foreach ($existingMaps as $existingMap) {
|
|
$this->modelMap->update($existingMap['TestMapID'], ['EndDate' => date('Y-m-d H:i:s')]);
|
|
}
|
|
}
|
|
|
|
if (is_array($mappings)) {
|
|
foreach ($mappings as $map) {
|
|
$mapData = [
|
|
'HostType' => $map['HostType'] ?? null,
|
|
'HostID' => $map['HostID'] ?? null,
|
|
'ClientType' => $map['ClientType'] ?? null,
|
|
'ClientID' => $map['ClientID'] ?? null,
|
|
];
|
|
$testMapID = $this->modelMap->insert($mapData);
|
|
|
|
if ($testMapID && isset($map['details']) && is_array($map['details'])) {
|
|
foreach ($map['details'] as $detail) {
|
|
$detailData = [
|
|
'TestMapID' => $testMapID,
|
|
'HostTestCode' => $detail['HostTestCode'] ?? null,
|
|
'HostTestName' => $detail['HostTestName'] ?? null,
|
|
'ConDefID' => $detail['ConDefID'] ?? null,
|
|
'ClientTestCode' => $detail['ClientTestCode'] ?? null,
|
|
'ClientTestName' => $detail['ClientTestName'] ?? null,
|
|
];
|
|
$this->modelMapDetail->insert($detailData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|