change charts corlor, update AFI

This commit is contained in:
2026-05-28 13:04:40 +07:00
parent e8c321c4eb
commit c08bd1af1b
76 changed files with 8758 additions and 1139 deletions

View File

@@ -5,6 +5,7 @@ namespace App\Services;
use App\Models\Surveillance;
use App\Models\SurveillanceCase;
use App\Models\CaseLabResult;
use SebastianBergmann\CodeCoverage\Report\Xml\Totals;
class DashboardService
{
@@ -71,78 +72,365 @@ class DashboardService
|--------------------------------------------------------------------------
*/
public function afiTrend($surveillanceId, $startYear, $startWeek, $endYear, $endWeek)
{
return CaseLabResult::join(
public function afiTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
) {
$rows = CaseLabResult::join(
'surveillance_cases',
'case_lab_results.lab_code',
'=',
'surveillance_cases.lab_code'
)
->where('surveillance_cases.surveillance_id', $surveillanceId)
->where(
'surveillance_cases.surveillance_id',
$surveillanceId
)
->where(function ($q) use ($startYear, $startWeek, $endYear, $endWeek) {
$q->whereRaw(
"(year_data > ? OR (year_data = ? AND week_data >= ?))",
"(year_data > ?
OR (
year_data = ?
AND week_data >= ?
)
)",
[$startYear, $startYear, $startWeek]
)
->whereRaw(
"(year_data < ? OR (year_data = ? AND week_data <= ?))",
"(year_data < ?
OR (
year_data = ?
AND week_data <= ?
)
)",
[$endYear, $endYear, $endWeek]
);
})
->where(function ($q) {
$q->whereNotNull('case_lab_results.pathogen_name')
->orWhereRaw("LOWER(case_lab_results.indicator) LIKE '%serum%'");
})
->where('case_lab_results.is_positive', 1)
->whereNotNull('case_lab_results.pathogen_name')
->selectRaw("
surveillance_cases.year_data as year,
surveillance_cases.week_data as period,
CASE
WHEN LOWER(case_lab_results.pathogen_name) LIKE '%influenza%'
THEN 'Influenza'
ELSE case_lab_results.pathogen_name
END as pathogen,
surveillance_cases.year_data as year,
surveillance_cases.week_data as period,
CASE
WHEN LOWER(case_lab_results.indicator) LIKE '%serum%' THEN 'Serum'
ELSE 'PCR'
END as test_type,
COUNT(case_lab_results.id) as total_tests,
COUNT(DISTINCT surveillance_cases.lab_code) as total_tested,
case_lab_results.pathogen_name as pathogen,
case_lab_results.subtype,
COUNT(CASE
WHEN case_lab_results.is_positive = 1
THEN surveillance_cases.lab_code
END) as total_positive
")
CASE
WHEN LOWER(case_lab_results.pathogen_name)
LIKE '%influenza%'
OR LOWER(case_lab_results.pathogen_name)
LIKE '%covid%'
OR LOWER(case_lab_results.pathogen_name)
LIKE '%sars-cov%'
THEN 'section_1'
WHEN LOWER(case_lab_results.indicator)
LIKE '%serum%'
THEN 'section_3'
ELSE 'section_2'
END as afi_section,
COUNT(DISTINCT surveillance_cases.lab_code)
as total_positive
")
->groupBy(
'surveillance_cases.year_data',
'surveillance_cases.week_data',
'pathogen',
'test_type'
'subtype',
'afi_section'
)
->orderBy('surveillance_cases.year_data')
->orderBy('surveillance_cases.week_data')
->get()
->map(function ($r) {
->get();
return [
'section_1' => $rows
->where('afi_section', 'section_1')
->values(),
'section_2' => $rows
->where('afi_section', 'section_2')
->values(),
'section_3' => $rows
->where('afi_section', 'section_3')
->values()
];
}
public function afiCaseTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
) {
/*
|--------------------------------------------------------------------------
| TOTAL CASES BY SECTION
|--------------------------------------------------------------------------
|
| Count DISTINCT lab_code PER SECTION
|
| section_1 = Influenza / Covid
| section_2 = PCR
| section_3 = Serum
|
*/
$totalCases = CaseLabResult::join(
'surveillance_cases',
'case_lab_results.lab_code',
'=',
'surveillance_cases.lab_code'
)
->where(
'surveillance_cases.surveillance_id',
$surveillanceId
)
->where(function ($q) use ($startYear, $startWeek, $endYear, $endWeek) {
$q->whereRaw(
"(year_data > ?
OR (
year_data = ?
AND week_data >= ?
)
)",
[$startYear, $startYear, $startWeek]
)
->whereRaw(
"(year_data < ?
OR (
year_data = ?
AND week_data <= ?
)
)",
[$endYear, $endYear, $endWeek]
);
})
->selectRaw("
surveillance_cases.year_data as year,
surveillance_cases.week_data as period,
CASE
WHEN LOWER(case_lab_results.indicator)
LIKE '%influenza%'
OR LOWER(case_lab_results.indicator)
LIKE '%covid%'
THEN 'section_1'
WHEN LOWER(case_lab_results.indicator)
LIKE '%serum%'
THEN 'section_3'
ELSE 'section_2'
END as afi_section,
COUNT(DISTINCT case_lab_results.lab_code)
as total_cases
")
->groupBy(
'surveillance_cases.year_data',
'surveillance_cases.week_data',
'afi_section'
)
->get()
->keyBy(
fn($r) =>
$r->year .
'-' .
$r->period .
'-' .
$r->afi_section
);
/*
|--------------------------------------------------------------------------
| POSITIVE RESULTS
|--------------------------------------------------------------------------
*/
$rows = CaseLabResult::join(
'surveillance_cases',
'case_lab_results.lab_code',
'=',
'surveillance_cases.lab_code'
)
->where(
'surveillance_cases.surveillance_id',
$surveillanceId
)
->where(function ($q) use ($startYear, $startWeek, $endYear, $endWeek) {
$q->whereRaw(
"(year_data > ?
OR (
year_data = ?
AND week_data >= ?
)
)",
[$startYear, $startYear, $startWeek]
)
->whereRaw(
"(year_data < ?
OR (
year_data = ?
AND week_data <= ?
)
)",
[$endYear, $endYear, $endWeek]
);
})
->where('case_lab_results.is_positive', 1)
->whereNotNull('case_lab_results.pathogen_name')
->selectRaw("
surveillance_cases.year_data as year,
surveillance_cases.week_data as period,
CASE
WHEN LOWER(case_lab_results.pathogen_name)
LIKE '%influenza%'
THEN 'Influenza'
ELSE case_lab_results.pathogen_name
END as pathogen,
case_lab_results.subtype,
CASE
WHEN LOWER(case_lab_results.indicator)
LIKE '%influenza%'
OR LOWER(case_lab_results.indicator)
LIKE '%covid%'
THEN 'section_1'
WHEN LOWER(case_lab_results.indicator)
LIKE '%serum%'
THEN 'section_3'
ELSE 'section_2'
END as afi_section,
COUNT(DISTINCT case_lab_results.lab_code)
as total_positive
")
->groupBy(
'surveillance_cases.year_data',
'surveillance_cases.week_data',
'pathogen',
'subtype',
'afi_section'
)
->orderBy('surveillance_cases.year_data')
->orderBy('surveillance_cases.week_data')
->get()
->map(function ($r) use ($totalCases) {
$key =
$r->year .
'-' .
$r->period .
'-' .
$r->afi_section;
$r->total_cases =
$totalCases[$key]->total_cases ?? 0;
$r->positivity_rate =
$r->total_cases > 0
? round(
($r->total_positive / $r->total_cases) * 100,
1
)
$r->positivity_rate = $r->total_tested > 0
? round(($r->total_positive / $r->total_tested) * 100, 1)
: 0;
return $r;
});
return [
'section_1' => $rows
->where('afi_section', 'section_1')
->values(),
'section_2' => $rows
->where('afi_section', 'section_2')
->values(),
'section_3' => $rows
->where('afi_section', 'section_3')
->values()
];
}
public function programSummaryFast($surveillanceId, $year = null, $week = null, $dateFrom = null, $dateTo = null)
{
$query = SurveillanceCase::leftJoin(
'case_lab_results',
'case_lab_results',
'surveillance_cases.lab_code',
'=',
'case_lab_results.lab_code'
@@ -309,90 +597,7 @@ class DashboardService
|--------------------------------------------------------------------------
*/
public function programDashboardData($surveillanceId, $startYear, $startWeek, $endYear, $endWeek)
{
return [
'summary' => $this->programSummary(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'trend' => $this->trendSingleProgram(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'pathogen_distribution' => $this->pathogenDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'age_distribution' => $this->ageDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'sex_distribution' => $this->sexDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'afi_trend' => $this->afiTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'province_distribution' => $this->provinceProgram(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'virus_trend' => $this->virusTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'subtype_distribution' => $this->subtypeDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'sentinel_sites' => $this->sentinelSites(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
];
}
@@ -610,7 +815,7 @@ class DashboardService
->where(function ($q) use ($startYear, $startWeek, $endYear, $endWeek) {
$q->whereRaw(
"(surveillance_cases.year_data * 100 + surveillance_cases.week_data) BETWEEN ? AND ?",
[
[
$startYear * 100 + $startWeek,
$endYear * 100 + $endWeek
]
@@ -881,13 +1086,13 @@ class DashboardService
})
->where('case_lab_results.is_positive', 1)
->where('case_lab_results.indicator', 'Influenza')
->selectRaw("
COALESCE(NULLIF(case_lab_results.subtype, ''), 'Unsubtyped') as subtype,
case_lab_results.subtype as subtype,
COUNT(DISTINCT case_lab_results.lab_code) as total
")
->where('case_lab_results.subtype', '!=', 'Positive')
->groupBy('subtype')
->orderByDesc('total')
@@ -1053,4 +1258,105 @@ class DashboardService
->get();
}
public function programDashboardData($surveillanceId, $startYear, $startWeek, $endYear, $endWeek)
{
return [
'total_tested' => $this->totalTested(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'summary' => $this->programSummary(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'trend' => $this->trendSingleProgram(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'pathogen_distribution' => $this->pathogenDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'age_distribution' => $this->ageDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'sex_distribution' => $this->sexDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
// 'afi_trend' => $this->afiTrend(
// $surveillanceId,
// $startYear,
// $startWeek,
// $endYear,
// $endWeek
// ),
'afi_case_trend' => $this->afiCaseTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'province_distribution' => $this->provinceProgram(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'virus_trend' => $this->virusTrend(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'subtype_distribution' => $this->subtypeDistribution(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
'sentinel_sites' => $this->sentinelSites(
$surveillanceId,
$startYear,
$startWeek,
$endYear,
$endWeek
),
];
}
}