- Implement AuthController with login/logout functionality - Create UsersModel with bcrypt password hashing - Add AuthFilter to protect all application routes - Create login page with error handling - Add users database migration with email/username fields - Rename ResultComments to TestComments for consistency - Update all routes to require authentication filter - Enhance EntryApiController with comment deletion and better error handling - Update seeder to include demo users and improved test data - Fix BaseController to handle auth sessions properly - Update entry views (daily/monthly) with new API endpoints - Update layout with logout button and user info display - Refactor control test index view for better organization
126 lines
4.8 KiB
PHP
126 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Api;
|
|
|
|
use App\Controllers\BaseController;
|
|
use CodeIgniter\API\ResponseTrait;
|
|
use App\Models\Master\MasterControlsModel;
|
|
use App\Models\Master\MasterTestsModel;
|
|
use App\Models\Qc\ControlTestsModel;
|
|
use App\Models\Qc\ResultsModel;
|
|
use App\Models\Qc\TestCommentsModel;
|
|
|
|
class ReportApiController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
|
|
protected $dictControlModel;
|
|
protected $dictTestModel;
|
|
protected $controlTestModel;
|
|
protected $resultModel;
|
|
protected $commentModel;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->dictControlModel = new MasterControlsModel();
|
|
$this->dictTestModel = new MasterTestsModel();
|
|
$this->controlTestModel = new ControlTestsModel();
|
|
$this->resultModel = new ResultsModel();
|
|
$this->commentModel = new TestCommentsModel();
|
|
}
|
|
|
|
public function getReport()
|
|
{
|
|
try {
|
|
$control1 = $this->request->getGet('control1') ?? 0;
|
|
$control2 = $this->request->getGet('control2') ?? 0;
|
|
$control3 = $this->request->getGet('control3') ?? 0;
|
|
$dates = $this->request->getGet('dates') ?? date('Y-m');
|
|
$test = $this->request->getGet('test') ?? 0;
|
|
|
|
$controlIds = array_filter([$control1, $control2, $control3]);
|
|
|
|
$reportData = [];
|
|
foreach ($controlIds as $controlId) {
|
|
$control = $this->dictControlModel->find($controlId);
|
|
if (!$control) continue;
|
|
|
|
$controlTest = $this->controlTestModel->getByControlAndTest($control['controlId'], $test);
|
|
$results = $this->resultModel->getByControlAndMonth($control['controlId'], $test, $dates);
|
|
// Get all comments for this test in the month (comments are now per test + date)
|
|
$allComments = $this->commentModel->getByTestAndMonth($test, $dates);
|
|
// Index comments by date for easy lookup
|
|
$commentsByDate = [];
|
|
foreach ($allComments as $c) {
|
|
$commentsByDate[$c['commentDate']] = $c['commentText'];
|
|
}
|
|
$testInfo = $this->dictTestModel->find($test);
|
|
|
|
$outOfRangeCount = 0;
|
|
$processedResults = [];
|
|
if ($controlTest && $controlTest['sd'] > 0) {
|
|
foreach ($results as $res) {
|
|
$zScore = ($res['resValue'] - $controlTest['mean']) / $controlTest['sd'];
|
|
$outOfRange = abs($zScore) > 2;
|
|
if ($outOfRange) $outOfRangeCount++;
|
|
|
|
$processedResults[] = [
|
|
'resdate' => $res['resDate'],
|
|
'resvalue' => $res['resValue'],
|
|
'zScore' => round($zScore, 2),
|
|
'outOfRange' => $outOfRange,
|
|
'status' => $zScore === null ? '-' : (abs($zScore) > 2 ? 'Out' : (abs($zScore) > 1 ? 'Warn' : 'OK'))
|
|
];
|
|
}
|
|
} else {
|
|
foreach ($results as $res) {
|
|
$processedResults[] = [
|
|
'resdate' => $res['resDate'],
|
|
'resvalue' => $res['resValue'],
|
|
'zScore' => null,
|
|
'outOfRange' => false,
|
|
'status' => '-'
|
|
];
|
|
}
|
|
}
|
|
|
|
$daysInMonth = date('t', strtotime($dates . '-01'));
|
|
$values = [];
|
|
for ($day = 1; $day <= $daysInMonth; $day++) {
|
|
$value = null;
|
|
foreach ($processedResults as $res) {
|
|
if (date('j', strtotime($res['resdate'])) == $day) {
|
|
$value = $res['resvalue'];
|
|
break;
|
|
}
|
|
}
|
|
$values[] = $value;
|
|
}
|
|
|
|
$reportData[] = [
|
|
'control' => $control,
|
|
'controlTest' => $controlTest,
|
|
'results' => $processedResults,
|
|
'values' => $values,
|
|
'test' => $testInfo,
|
|
'comments' => $commentsByDate,
|
|
'outOfRange' => $outOfRangeCount
|
|
];
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'fetch success',
|
|
'data' => [
|
|
'reportData' => $reportData,
|
|
'dates' => $dates,
|
|
'test' => $test,
|
|
'daysInMonth' => $daysInMonth
|
|
]
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|