clqms-be/app/Libraries/TestValidationService.php
OpenCode Bot 9946978487 chore: refresh CLQMS backend baseline
Re-synced controllers, configs, libraries, seeds, and docs with the latest API expectations and response helpers.
2026-04-08 16:07:19 +07:00

268 lines
7.4 KiB
PHP
Executable File

<?php
namespace App\Libraries;
/**
* Test Validation Service
*
* Validates TestType, ResultType, and RefType combinations
* according to business rules for CLQMS test definitions.
*/
class TestValidationService
{
/**
* Valid TestType to ResultType mappings
*/
private const TEST_TYPE_RESULT_TYPES = [
'TEST' => ['NMRIC', 'RANGE', 'TEXT', 'VSET'],
'PARAM' => ['NMRIC', 'RANGE', 'TEXT', 'VSET'],
'CALC' => ['NMRIC'],
'GROUP' => ['NORES'],
'TITLE' => ['NORES'],
];
/**
* Valid ResultType to RefType mappings
*/
private const RESULT_TYPE_REF_TYPES = [
'NMRIC' => ['RANGE', 'THOLD'],
'RANGE' => ['RANGE', 'THOLD'],
'VSET' => ['VSET'],
'TEXT' => ['TEXT'],
'NORES' => ['NOREF'],
];
/**
* Reference table mapping based on ResultType and RefType
*/
private const REFERENCE_TABLES = [
'NMRIC' => [
'RANGE' => 'refnum',
'THOLD' => 'refnum',
],
'RANGE' => [
'RANGE' => 'refnum',
'THOLD' => 'refnum',
],
'VSET' => [
'VSET' => 'reftxt',
],
'TEXT' => [
'TEXT' => 'reftxt',
],
'NORES' => [
'NOREF' => null,
],
];
/**
* Validate TestType and ResultType combination
*
* @param string $testType
* @param string $resultType
* @return array ['valid' => bool, 'error' => string|null]
*/
public static function validateTestTypeResultType(string $testType, string $resultType): array
{
$testType = strtoupper($testType);
$resultType = strtoupper($resultType);
if (!isset(self::TEST_TYPE_RESULT_TYPES[$testType])) {
return [
'valid' => false,
'error' => "Invalid TestType '{$testType}'. Allowed: TEST, PARAM, CALC, GROUP, TITLE"
];
}
$validResultTypes = self::TEST_TYPE_RESULT_TYPES[$testType];
if (!in_array($resultType, $validResultTypes, true)) {
return [
'valid' => false,
'error' => "Invalid ResultType '{$resultType}' for TestType '{$testType}'. Allowed: " . implode(', ', $validResultTypes)
];
}
return ['valid' => true, 'error' => null];
}
/**
* Validate ResultType and RefType combination
*
* @param string $resultType
* @param string $refType
* @return array ['valid' => bool, 'error' => string|null]
*/
public static function validateResultTypeRefType(string $resultType, string $refType): array
{
$resultType = strtoupper($resultType);
$refType = strtoupper($refType);
if (!isset(self::RESULT_TYPE_REF_TYPES[$resultType])) {
return [
'valid' => false,
'error' => "Invalid ResultType '{$resultType}'. Allowed: NMRIC, RANGE, TEXT, VSET, NORES"
];
}
$validRefTypes = self::RESULT_TYPE_REF_TYPES[$resultType];
if (!in_array($refType, $validRefTypes, true)) {
return [
'valid' => false,
'error' => "Invalid RefType '{$refType}' for ResultType '{$resultType}'. Allowed: " . implode(', ', $validRefTypes)
];
}
return ['valid' => true, 'error' => null];
}
/**
* Validate complete test type combination
*
* @param string $testType
* @param string $resultType
* @param string $refType
* @return array ['valid' => bool, 'error' => string|null]
*/
public static function validate(string $testType, string $resultType, string $refType): array
{
// First validate TestType and ResultType
$testResultValidation = self::validateTestTypeResultType($testType, $resultType);
if (!$testResultValidation['valid']) {
return $testResultValidation;
}
// Then validate ResultType and RefType
return self::validateResultTypeRefType($resultType, $refType);
}
/**
* Get valid ResultTypes for a TestType
*
* @param string $testType
* @return array
*/
public static function getValidResultTypes(string $testType): array
{
$testType = strtoupper($testType);
return self::TEST_TYPE_RESULT_TYPES[$testType] ?? [];
}
/**
* Get valid RefTypes for a ResultType
*
* @param string $resultType
* @return array
*/
public static function getValidRefTypes(string $resultType): array
{
$resultType = strtoupper($resultType);
return self::RESULT_TYPE_REF_TYPES[$resultType] ?? [];
}
/**
* Get reference table name based on ResultType and RefType
*
* @param string $resultType
* @param string $refType
* @return string|null Returns table name or null if no reference table needed
*/
public static function getReferenceTable(?string $resultType, ?string $refType): ?string
{
if ($resultType === null || $refType === null) {
return null;
}
$resultType = strtoupper($resultType);
$refType = strtoupper($refType);
return self::REFERENCE_TABLES[$resultType][$refType] ?? null;
}
/**
* Check if a test needs reference ranges
*
* @param string $resultType
* @return bool
*/
public static function needsReferenceRanges(?string $resultType): bool
{
if ($resultType === null) {
return false;
}
$resultType = strtoupper($resultType);
return $resultType !== 'NORES';
}
/**
* Check if a test uses refnum table
*
* @param string $resultType
* @param string $refType
* @return bool
*/
public static function usesRefNum(?string $resultType, ?string $refType): bool
{
return self::getReferenceTable($resultType, $refType) === 'refnum';
}
/**
* Check if a test uses reftxt table
*
* @param string $resultType
* @param string $refType
* @return bool
*/
public static function usesRefTxt(?string $resultType, ?string $refType): bool
{
return self::getReferenceTable($resultType, $refType) === 'reftxt';
}
/**
* Check if TestType is CALC
*
* @param string $testType
* @return bool
*/
public static function isCalc(string $testType): bool
{
return strtoupper($testType) === 'CALC';
}
/**
* Check if TestType is GROUP
*
* @param string $testType
* @return bool
*/
public static function isGroup(string $testType): bool
{
return strtoupper($testType) === 'GROUP';
}
/**
* Check if TestType is TITLE
*
* @param string $testType
* @return bool
*/
public static function isTitle(string $testType): bool
{
return strtoupper($testType) === 'TITLE';
}
/**
* Check if TestType is TEST or PARAM (technical tests)
*
* @param string $testType
* @return bool
*/
public static function isTechnicalTest(string $testType): bool
{
$testType = strtoupper($testType);
return in_array($testType, ['TEST', 'PARAM'], true);
}
}