@php
$canEdit = $canEdit ?? false;
$canEditDeclined = $canEditDeclined ?? false;
$lastReturnRemark = $lastReturnRemark ?? null;
$workflowHistory = $workflowHistory ?? [];
$allSchemes = $plan->latestVersion?->schemes ?? collect();
$activeSchemes = ($activeSchemes ?? null) instanceof \Illuminate\Support\Collection ? $activeSchemes : $allSchemes->filter(fn ($s) => ! filled($s->rd_rejected_at ?? null))->values();
$declinedSchemes = ($declinedSchemes ?? null) instanceof \Illuminate\Support\Collection ? $declinedSchemes : $allSchemes->filter(fn ($s) => filled($s->rd_rejected_at ?? null))->values();
$schemes = $activeSchemes;
$planMeta = $planMeta ?? [
'region_label' => plan_region_label_for_plan($plan),
'created_by_display' => $plan->creator->name ?? '—',
'consolidated_by_label' => $plan->consolidatedSourcePlanIds() !== [] ? ($plan->creator->name ?? '—') : '—',
'plan_type_label' => match ($plan->plan_type ?? '') {
'RVP' => 'Regular Visit Plan (RVP)',
'CVP' => 'Compliance Visit Plan (CVP)',
'SVP' => 'Special Visit Plan (SVP)',
'DRP' => 'Desk Review Plan (DRP)',
'ERP' => 'Evaluation Report Plan (ERP)',
'PMP' => 'Project Monitoring Plan (PMP)',
default => $plan->plan_type ?? 'Plan',
},
];
$mecActivitySingleScheme = (bool) ($mecActivitySingleScheme ?? false);
$planIsConsolidated = $mecActivitySingleScheme ? false : $plan->consolidatedSourcePlanIds() !== [];
$periodLabel = \Carbon\Carbon::create()->month((int) $plan->month)->format('F') . ' ' . $plan->year;
$planSchemeLtbcByProjectId = $planSchemeLtbcByProjectId ?? [];
$schemeTypeLabelByProjectId = $schemeTypeLabelByProjectId ?? [];
$mecCategoryLabelByProjectId = $mecCategoryLabelByProjectId ?? [];
$planTypeUpper = strtoupper(trim((string) ($plan->plan_type ?? '')));
$planFinalizesAtSdm = plan_type_finalizes_at_sdm($planTypeUpper);
$checkerForwardStepLabel = plan_checker_forward_step_label($planTypeUpper);
$verifierForwardStepLabel = plan_verifier_forward_step_label($planTypeUpper);
$dgDeclineReturnStepLabel = plan_decline_return_step_label($plan);
$planMayForward = \App\Support\WorkflowActorRules::visitPlanMayForward($plan);
$planMayApprove = \App\Support\WorkflowActorRules::visitPlanMayDirectApprove($plan);
$rdCanForwardToSdm = $planMayForward && $plan->status === 'rd_review' && ! $planIsConsolidated;
$sdmCanFinalApprovePlan = $planMayApprove && $plan->status === 'sdm_review' && $planFinalizesAtSdm;
$sdmCanForwardToDg = $planMayForward && $plan->status === 'sdm_review' && \App\Support\WorkflowActorRules::visitPlanTypeRequiresDgStage($planTypeUpper);
$dgCanApprove = $planMayApprove && $plan->status === 'dg_review';
$approverCanDecline = $dgCanApprove || $sdmCanFinalApprovePlan;
$verifierCanDecline = $plan->status === 'sdm_review'
&& plan_type_has_verifier_stage($planTypeUpper)
&& \App\Support\WorkflowActorRules::visitPlanMayForward($plan);
$showSscCheck = $showSscCheck ?? false;
@endphp
{{ $planMeta['plan_type_label'] }}
{{ $periodLabel }}
@if($plan->status === 'rejected')
@php
$lastDeclineEntry = collect($workflowHistory)->where('action', 'rejected')->last();
$declineReason = $lastReturnRemark ?? ($lastDeclineEntry['remarks'] ?? '');
@endphp
Plan declined
{{ plan_declined_status_label($plan) }}
Reason: {{ $declineReason !== '' ? $declineReason : '—' }}
@elseif($plan->status === 'returned')
@php
$lastReturnEntry = collect($workflowHistory)->where('action', 'returned')->last();
$returnReason = $lastReturnRemark ?? ($lastReturnEntry['remarks'] ?? '');
$rdSchemeFlaggedCount = $declinedSchemes->count();
@endphp
Plan returned
{{ plan_returned_status_label($plan) }}
Reason: {{ $returnReason !== '' ? $returnReason : '—' }}
@if($rdSchemeFlaggedCount > 0)
{{ $rdSchemeFlaggedCount }} scheme(s) were flagged individually for revision (see each scheme below).
@endif
@endif
@if(!empty($workflowHistory))
Plan History
@foreach($workflowHistory as $idx => $entry)
@php
$actionLabel = plan_forward_history_action_label($entry);
$hideConsolidationRouting = in_array((string) ($entry['action'] ?? ''), [
'merged_into_consolidated',
'created_from_consolidation',
], true);
$timestamp = $entry['action_date']->format('d M Y') . ' • ' . $entry['action_date']->format('H:i');
$isLast = $idx === count($workflowHistory) - 1;
@endphp
-
{{ $actionLabel }}
@unless($hideConsolidationRouting)
{{ $entry['routing_line'] ?? (($entry['from_user_label'] ?? $entry['from_user_name']).' → '.($entry['to_user_label'] ?? $entry['to_user_name'])) }}
@endunless
{{ $timestamp }}
@if(filled($entry['remarks'] ?? null))
Note:
{!! nl2br(e((string) $entry['remarks'])) !!}
@endif
@endforeach
@endif
@php
$planSchemesOrdered = $allSchemes->values();
$highlightPlanSchemeId = (int) ($highlightPlanSchemeId ?? 0);
$fieldVisitLetterContext = $fieldVisitLetterContext ?? [
'may_generate' => false,
'may_edit' => false,
'is_published' => false,
'editor_url' => null,
'view_url' => null,
'department_view_urls' => [],
'letter_department_count' => 0,
'letter_scheme_count' => 0,
];
@endphp
@php
$planSchemeAdpByProjectId = $planSchemeAdpByProjectId ?? [];
@endphp
Plan schemes ({{ $planSchemesOrdered->count() }})
@if($planSchemesOrdered->isEmpty())
No schemes in this plan.
@else
@foreach($planSchemesOrdered as $idx => $scheme)
@php
$isDeclined = filled($scheme->rd_rejected_at ?? null);
$p = $projectsMap->get($scheme->scheme_id);
$schemeCode = $p ? trim((string) ($p->code ?? '')) : '';
$schemeAdp = $planSchemeAdpByProjectId[(int) ($scheme->scheme_id ?? 0)] ?? ($p ? plan_scheme_adp_display_for_plan($p, $plan) : '');
$schemeName = $p ? trim((string) ($p->name ?? '')) : '';
$visitTeamNames = $scheme->visitingTeams->map(fn ($t) => $t->user->name ?? '')->filter()->values()->implode(', ');
$additionalDates = $scheme->dates->map(fn ($d) => $d->visit_date?->format('d-m-Y'))->filter()->values();
$physical = $scheme->physical_progress !== null ? (float) $scheme->physical_progress : null;
$financial = $scheme->financial_progress !== null ? (float) $scheme->financial_progress : null;
$effectiveMoId = $scheme->effectiveMonitoringOfficerUserId($plan);
$monitoringOfficerDisplay = '—';
if ($effectiveMoId > 0) {
if ((int) ($scheme->monitoring_officer_id ?? 0) > 0 && $scheme->monitoringOfficer) {
$monitoringOfficerDisplay = $scheme->monitoringOfficer->name ?? '—';
} elseif ((int) ($plan->created_by ?? 0) === $effectiveMoId && $plan->creator) {
$monitoringOfficerDisplay = $plan->creator->name ?? '—';
} else {
$monitoringOfficerDisplay = optional(\App\Models\PC\User::find($effectiveMoId))->name ?? ('User #' . $effectiveMoId);
}
}
$psNames = ($p && $p->relationLoaded('ps'))
? $p->ps->pluck('name')->map(fn ($n) => trim((string) $n))->filter()->values()
: collect();
$moInitials = '?';
$moInitSource = ($monitoringOfficerDisplay !== '—' && $monitoringOfficerDisplay !== '') ? $monitoringOfficerDisplay : '';
if ($moInitSource !== '') {
$stop = ['dr', 'mr', 'mrs', 'ms', 'eng', 'engr', 'prof'];
$parts = preg_split('/\s+/u', $moInitSource);
$toks = [];
foreach ($parts as $part) {
$low = mb_strtolower(trim($part, '.'));
if ($low === '' || in_array($low, $stop, true)) {
continue;
}
$toks[] = $part;
}
if ($toks === []) {
$moInitials = mb_strtoupper(mb_substr($moInitSource, 0, 2));
} elseif (count($toks) === 1) {
$moInitials = mb_strtoupper(mb_substr($toks[0], 0, 1).mb_substr($toks[0], 1, 1));
} else {
$a = $toks[count($toks) - 2];
$b = $toks[count($toks) - 1];
$moInitials = mb_strtoupper(mb_substr($a, 0, 1).mb_substr($b, 0, 1));
}
}
$isHighlight = $highlightPlanSchemeId > 0 && (int) ($scheme->id ?? 0) === $highlightPlanSchemeId;
$isFirst = $isHighlight || ($highlightPlanSchemeId <= 0 && $idx === 0);
$collapseDomId = 'plan-scheme-collapse-' . $plan->id . '-' . (int) ($scheme->id ?? 0) . '-' . $idx;
$headingDomId = 'plan-scheme-heading-' . $plan->id . '-' . $idx;
$schemeTitleDisplay = $schemeName !== '' ? $schemeName : ($schemeCode !== '' ? $schemeCode : 'Scheme #'.($idx + 1));
$projCostDisplay = '—';
$projDeptDisplay = '—';
$projLtbcDisplay = '—';
$projSectorDisplay = '—';
$projSubSectorDisplay = '—';
$projCatDisplay = '—';
$projTargetDisplay = '—';
$projSchemeTypeDisplay = '—';
if ($p) {
$ap = (float) ($p->approved_amount ?? 0);
$costBase = ($ap > 0 && ($p->approved ?? false)) ? $ap : (float) ($p->estimated_amount ?? 0);
$projCostDisplay = number_format($costBase, 0);
$deptParts = array_values(array_filter([
trim((string) ($p->department?->name ?? '')),
trim((string) ($p->subDepartment?->name ?? '')),
]));
$projDeptDisplay = $deptParts !== [] ? implode(' / ', $deptParts) : '—';
$ltbc = $planSchemeLtbcByProjectId[(int) ($p->project_id ?? 0)] ?? false;
$projLtbcDisplay = $ltbc ? 'Yes' : 'No';
$projSectorDisplay = trim((string) ($p->sector?->name ?? '')) !== '' ? trim((string) $p->sector->name) : '—';
$projSubSectorDisplay = \App\Services\PC\MecSchemeDisplayLabels::subSectorLabelForProject($p);
$projCatDisplay = trim((string) (($mecCategoryLabelByProjectId[(int) ($p->project_id ?? 0)] ?? '') ?: ''));
if ($projCatDisplay === '' || $projCatDisplay === '—') {
$projCatDisplay = '—';
}
$td = $p->target_completion_date ?? null;
if ($td !== null && $td !== '') {
try {
$projTargetDisplay = \Carbon\Carbon::parse($td)->format('d M Y');
} catch (\Throwable $e) {
$projTargetDisplay = (string) $td;
}
}
$projSchemeTypeDisplay = $schemeTypeLabelByProjectId[(int) $p->project_id] ?? '—';
}
@endphp
@if($isDeclined && filled($scheme->rd_rejection_remarks ?? null))
RD note: {{ $scheme->rd_rejection_remarks }}
@endif
Visit location
{{ $scheme->visit_location ?: '—' }}
Visiting team
{{ $visitTeamNames ?: '—' }}
Physical progress
@if($physical !== null)
{{ $physical }}%
@else
—
@endif
@if($physical !== null)
@else
@endif
Financial progress
@if($financial !== null)
{{ $financial }}%
@else
—
@endif
@if($financial !== null)
@else
@endif
Project components
Cost
{{ $projCostDisplay }} M
Department
{{ $projDeptDisplay }}
LTBC
{{ $projLtbcDisplay }}
Sector
{{ $projSectorDisplay }}
Sub sector
{{ $projSubSectorDisplay }}
Cat
{{ $projCatDisplay }}
Scheme type
{{ $projSchemeTypeDisplay }}
Target completion
{{ $projTargetDisplay }}
@if($psNames->isNotEmpty())
Physical scopes (PS)
{{ $psNames->implode(', ') }}
@elseif(! $p)
Project record not found for this scheme.
@else
@endif
@if($additionalDates->isNotEmpty())
Additional visit dates
{{ $additionalDates->implode(', ') }}
@endif
@endforeach
@endif
@if($rdCanForwardToSdm && $activeSchemes->isNotEmpty())
@endif
@if(can_visit_plan($plan, 'can_check') && $plan->status === 'rd_review' && ! $planIsConsolidated)
@endif
@once
@endonce
@if($verifierCanDecline)
@if($sdmCanForwardToDg)
@endif
@endif
@if($sdmCanFinalApprovePlan)
@endif
@if($dgCanApprove)
@endif
@if($approverCanDecline)
@endif