{{-- Part E §1 — Earned Value Analysis (SPI/CPI remarks follow Result value; extended metrics by report type) --}} @push('stylesheets') @endpush @php use App\Models\ReportSubSectorChecklistItem; use App\Support\MecReportType; $e1Base = 'report.part_e.earned_value_analysis.rows'; $evaReportType = (string) ($reportType ?? request()->query('report_type', '')); $itemsAll = isset($subSectorChecklistItemsEarnedValueAnalysis) ? collect($subSectorChecklistItemsEarnedValueAnalysis) : collect(); $items = ReportSubSectorChecklistItem::filterEarnedValueAnalysisItems($itemsAll, $evaReportType); $isPmrEva = MecReportType::isPmr($evaReportType); $rowsOld = report_wizard_rows('part_e.earned_value_analysis.rows', [], $reportPayload ?? null); $evaRowsByItemId = []; if (is_array($rowsOld)) { foreach ($rowsOld as $savedRow) { if (! is_array($savedRow)) { continue; } $itemId = (int) ($savedRow['report_sub_sector_checklist_item_id'] ?? 0); if ($itemId > 0) { $evaRowsByItemId[$itemId] = $savedRow; } } } $evaParseResult = static function (?string $s): ?float { if ($s === null || trim((string) $s) === '') { return null; } $t = str_replace([' ', ','], ['', '.'], trim((string) $s)); if ($t === '' || ! is_numeric($t)) { return null; } return (float) $t; }; $evaSpiRemarkHtml = static function (?float $n): string { if ($n === null) { return 'Enter a numeric result to show the matching remark.'; } if (abs($n - 1.0) < 1e-6) { return '

The Scheme is exactly on schedule.

'; } if ($n > 1.0) { return '

The Scheme is ahead of schedule, completing more work than planned.

'; } return '

The Scheme is behind schedule, completing less work than planned.

'; }; $evaCpiRemarkHtml = static function (?float $n): string { if ($n === null) { return 'Enter a numeric result to show the matching remark.'; } if ($n > 1.0) { return '

The Scheme is under budget and performing efficiently.

'; } if (abs($n - 1.0) < 1e-6) { return '

The Scheme is exactly on budget.

'; } return '

The Scheme is over budget, spending more than planned.

'; }; $evaFixedRemark = static function (int $ord): string { return match ($ord) { 1 => 'Budgeted Cost of Work Scheduled', 2 => 'Budgeted Cost of Work Performed', 3 => 'Actual cost of work performed (same unit as PV/EV)', 6 => 'Positive = underrun, negative = overrun', 7 => 'Positive = ahead of schedule, negative = behind', 8 => 'Forecast total cost at project completion', 9 => 'Performance needed to meet original BAC', 10 => 'Performance needed to meet forecasted EAC', default => '', }; }; $reportEvaCalcJsI18n = [ 'errBac' => __('Enter a valid project cost (BAC) greater than zero.'), 'errPhys' => __('Enter physical progress between 0 and 100%.'), 'errDuration' => __('Enter total planned duration in months (greater than zero).'), 'errStart' => __('Select the project start date.'), 'errAc' => __('Enter actual cost (ACWP) as zero or greater.'), 'errEtcNew' => __('Revised ETC is required when EAC Method 4 is selected.'), 'errInvalidDates' => __('Invalid date(s).'), 'errAssessBeforeStart' => __('Assessment date cannot be earlier than the start date.'), 'checkInputs' => __('Check inputs'), 'swalSuccessTitle' => __('EVA updated'), 'swalSuccessText' => $isPmrEva ? __('Earned value metrics (including variances, EAC, and TCPI) were filled from the calculator.') : __('Earned value metrics, EAC, and TCPI were filled from the calculator.'), ]; @endphp
@if ($items->isEmpty())

Earned Value Analysis catalog is empty. Run php artisan migrate (or seed ReportSubSectorChecklistSeeder).

@else
@foreach ($items as $rIdx => $it) @php $row = $evaRowsByItemId[(int) $it->id] ?? ((is_array($rowsOld) && isset($rowsOld[$rIdx])) ? $rowsOld[$rIdx] : []); $result = old($e1Base.'.'.$rIdx.'.result', $row['result'] ?? ''); $dotBase = $e1Base.'.'.$rIdx.'.'; $ord = (int) $it->sort_order; $metricKey = ReportSubSectorChecklistItem::earnedValueMetricKeyForSortOrder($ord); $n = $evaParseResult((string) $result); $resultIsNeg = \App\Services\ReportPreviewPresenter::earnedValueResultIsNegative($result, $ord); @endphp @endforeach
Items Result Remarks
{{ $it->name }} @error($dotBase.'result') {{ $message }} @enderror @switch($ord) @case(4)
{!! $evaSpiRemarkHtml($n) !!}
@break @case(5)
{!! $evaCpiRemarkHtml($n) !!}
@break @default @php $fixedRm = $evaFixedRemark($ord); @endphp @if ($fixedRm !== '') {{ $fixedRm }} @else @endif @endswitch
@endif
@if (! $items->isEmpty()) @endif @push('scripts') @include('reports.partials.eva-compute-engine') @endpush