@extends('layouts.app') @section('title', __('lang_v1.po_followup')) @section('content')

@lang('lang_v1.po_followup') @lang('lang_v1.po_followup_desc')

@include('layouts.partials.error') {{-- Un-chaseable orders. Without a lead time there is no ETA, so these POs can never appear below — say so instead of hiding them. --}} @if(!empty($no_eta_products))
@lang('lang_v1.po_followup_no_eta', ['count' => count($no_eta_products)])
{{ implode(', ', array_slice($no_eta_products, 0, 15)) }}@if(count($no_eta_products) > 15) …@endif
@endif {{-- Bucket counts, most urgent first. Each is a filter link so an operator can work one rung at a time (e.g. "everything overdue"). --}}
@if(empty($buckets)) @lang('lang_v1.no_pos_to_followup') @else @lang('lang_v1.all') @foreach($buckets as $bucket => $count) @php // Same colour ladder the rows use, so the chips and the // table read as one escalation scale. $chip = app(\App\Utils\PoFollowupUtil::class)->stageClass( $bucket === 'OVERDUE' ? \App\Utils\PoFollowupUtil::STAGE_OVERDUE_PREFIX.'1' : $bucket ); @endphp {{ $bucket === 'OVERDUE' ? __('lang_v1.overdue') : $bucket }} {{ $count }} @endforeach @endif
@forelse($rows as $po) @empty @endforelse
@lang('purchase.ref_no') @lang('lang_v1.manufacturer') @lang('business.product') @lang('sale.quantity') @lang('lang_v1.fulfilment') @lang('messages.date') @lang('lang_v1.eta') @lang('lang_v1.days_left') @lang('lang_v1.stage') @lang('lang_v1.last_followup')
{{ $po->ref_no }} {{ optional($po->contact)->name ?: optional($po->contact)->supplier_business_name ?: '-' }} {{ optional($po->fu_product)->name ?: '-' }} {{-- Legacy/store POs can carry several products; never let the extra lines vanish behind the first one. --}} @if($po->fu_extra_lines) +{{ $po->fu_extra_lines }} @lang('lang_v1.more') @endif {{ @num_format($po->fu_qty) }} @if(!empty($po->fu_fulfilment)) @php $f = $po->fu_fulfilment; @endphp {{ app(\App\Utils\PoFollowupUtil::class)->fulfilmentLabel($f['state']) }} {{-- The balance is what is actually being chased, so it is stated outright rather than left to subtraction. --}}
{{ @num_format($f['accounted']) }} / {{ @num_format($f['ordered']) }} @if($f['remaining'] > 0 && $f['state'] == 'partial')
@lang('lang_v1.balance_due'): {{ @num_format($f['remaining']) }} @endif @else -- @endif
{{ @format_date($po->transaction_date) }} {{ $po->fu_eta ? $po->fu_eta->format('d-m-Y') : '-' }} {{-- Negative days = already late. --}} fu_days < 0) class="text-red" @endif>{{ $po->fu_days }} {{ $po->fu_label }} {{-- Date alone says nothing about what happened; the latest outcome and any revised ETA are what tell the operator whether this still needs chasing. --}} @if(!empty($po->fu_trail_last)) {{ @format_datetime($po->fu_trail_last['at']) }}
{{ $po->fu_trail_last['outcome'] ?: '--' }} @if(!empty($po->fu_trail_last['revised_eta']))
@lang('lang_v1.revised_eta'): {{ \Carbon::parse($po->fu_trail_last['revised_eta'])->format('d-m-Y') }} @endif @elseif($po->followup_last_at) {{ @format_date($po->followup_last_at) }} @else @lang('lang_v1.followup_none_yet') @endif
@lang('lang_v1.followup_trail') @if($po->fu_trail_count) {{ $po->fu_trail_count }} @endif
@lang('lang_v1.no_pos_to_followup')
{{-- Record-follow-up modal. One form reused for every row; the row's button injects the PO id into the action and pre-fills the current ETA. --}}
@endsection {{-- MUST be @section('javascript'): the layout yields it after layouts.partials.javascripts, where jQuery is loaded. A @endsection