{{-- Diseño moderno (v3): detalle de una reserva. Mismos formularios, rutas y validaciones que reservation/show; solo cambia la presentación. --}} @extends('layout.main') @section('content') @include('reservation._alerts') @php $customer = $reservation->customer ?: new \App\Customer(['name' => $reservation->client_code ? 'Código ' . $reservation->client_code : '(sin cliente)']); $editable = $reservation->status == 1; $phone = preg_replace('/\D/', '', $customer->phone_number ?? ''); if (strlen($phone) == 10 && $phone[0] == '0') $phone = '593' . substr($phone, 1); $lines = []; foreach ($reservation->items as $item) $lines[] = '• ' . ($item->product->name ?? '') . ' x' . (float) $item->qty . ' = $' . number_format($item->subtotal, 2); $waText = "Hola " . ($customer->name ?? '') . ", esta es tu reserva " . $reservation->reference_no . " en " . ($reservation->warehouse->name ?? '') . ":\n" . implode("\n", $lines) . ($reservation->shipping_cost > 0 ? "\nEnvío: $" . number_format($reservation->shipping_cost, 2) : '') . "\nTotal: $" . number_format($reservation->total, 2) . "\nAbonado: $" . number_format($reservation->paid, 2) . "\nSaldo pendiente: $" . number_format($reservation->balance, 2) . ($reservation->due_date ? "\nPlazo de pago hasta: " . \Carbon\Carbon::parse($reservation->due_date)->format('d/m/Y') : ''); @endphp @php $r = $reservation; $pill = $r->is_overdue ? 'v3-pill-red' : ([1 => 'v3-pill-gray', 2 => 'v3-pill-green', 3 => 'v3-pill-gray', 4 => 'v3-pill-brand', 5 => 'v3-pill-brand'][$r->status] ?? 'v3-pill-gray'); $canExit = in_array($r->status, [4, 5]) && ($r->status == 5 || !$r->exit_issues); $backTab = in_array($r->status, [4, 5]) ? 4 : ($r->status == 1 ? ($r->is_overdue ? 'vencidas' : 1) : 'cerradas'); @endphp
← Reservas {{-- Cabecera: cliente, estado y la acción principal --}}

Reserva {{ $r->reference_no }}@if($r->client_code) · Código {{ $r->client_code }}@endif · {{ preg_replace('/\s*-\s*Entre Tu y Yo$/i', '', $r->warehouse->name ?? '') }}

@if($customer->id){{ $customer->name }}@else{{ $customer->name }}@endif

{{ $r->status_label }} @if($r->status != 3)Pago: {{ $r->financial_label }} · Paquete: {{ $r->logistic_label }}@endif
@if($canExit) {!! Form::open(['route' => ['reservations.deliver', $r->id], 'method' => 'post', 'class' => 'mb-0', 'onsubmit' => "return confirm('¿" . $r->confirm_label . " de " . $r->reference_no . "? Pasa a ENTREGADA.')"]) !!} {!! Form::close() !!} @endif
@if($r->step !== null) @php $steps = ['Activa', 'Pagada · ' . ($r->is_pickup ? 'por retirar' : 'por enviar'), 'Entregada']; $cur = $r->step; @endphp
    @foreach($steps as $i => $label) @php $done = $i < $cur || $cur == 2; @endphp
  1. {{ $i + 1 }} · {{ $label }}@if($done) ✓@endif
  2. @endforeach
@endif {{-- Avisos --}} @if($r->status == 4 && $r->exit_issues)
Todavía no se puede entregar: {{ implode('; ', $r->exit_issues) }}.
@endif @if($r->status == 1 && $r->total > 0 && $r->balance <= 0 && !$r->delivery_mode)
Productos pagados. Elige en «Entrega» el método (retiro o envío) para que pase a POR PROCESAR. Si es envío, su costo se suma al saldo.
@endif @if($r->surplus > 0)
El cliente tiene un excedente de ${{ number_format($r->surplus, 2) }}. Abonó más que el total actual (se quitaron productos). No se devolvió dinero: queda pendiente decidir devolución o crédito.
@endif @if($r->merged_into)
Esta reserva se unió a la reserva {{ $r->mergedInto->reference_no ?? ('#' . $r->merged_into) }}: sus productos y abonos están ahora allí.
@endif @if($mergeable->isNotEmpty())
{{ $customer->name }} tiene otra reserva activa en esta tienda. Únelas para ver todo en una sola (productos y abonos): @foreach($mergeable as $other) {!! Form::open(['route' => ['reservations.merge', $r->id], 'method' => 'post', 'class' => 'd-inline', 'onsubmit' => "return confirm('¿Unir " . $other->reference_no . " a " . $r->reference_no . "? Sus productos y abonos pasan a esta reserva. " . $other->reference_no . " queda como Unida (no se borra).')"]) !!} {!! Form::close() !!} @endforeach
@endif
{{-- Productos --}}

Productos

@if($editable)@endif
@if($merged->isNotEmpty())

Incluye las reservas unidas: {{ $merged->pluck('reference_no')->implode(', ') }}.

@endif @if($editable)
{!! Form::open(['route' => ['reservations.items.add', $r->id], 'method' => 'post', 'class' => 'row align-items-end mb-3', 'id' => 'add-item-form']) !!}
 
{!! Form::close() !!}
@endif
@forelse($r->items as $item)
{{ mb_strtoupper(mb_substr($item->product->name ?? '?', 0, 1)) }}
{{ $item->product->name ?? '' }}
{{ $item->product->code ?? '' }} · {{ (float) $item->qty }} × ${{ number_format($item->unit_price, 2) }}
@if($editable) {!! Form::open(['route' => ['reservations.items.update', $r->id, $item->id], 'method' => 'post', 'class' => 'd-flex flex-wrap align-items-center no-print mt-2', 'id' => 'item-form-' . $item->id, 'style' => 'gap:6px']) !!} {!! Form::close() !!} @endif
${{ number_format($item->subtotal, 2) }} @if($editable) {!! Form::open(['route' => ['reservations.items.remove', $r->id, $item->id], 'method' => 'post', 'class' => 'no-print mb-0', 'onsubmit' => "return confirm('¿Quitar " . e(addslashes($item->product->name ?? 'este producto')) . " de la reserva? Sus unidades vuelven al stock.')"]) !!} {!! Form::close() !!} @endif
@empty

Sin productos.

@endforelse
{{-- Abonos --}}

Abonos

@if($r->payments->isEmpty())

Todavía no hay abonos.

@else
@foreach($r->payments->sortBy('id') as $p)
Abono {{ $loop->iteration }} · {{ $p->created_at->format('d/m/Y H:i') }} · {{ $formas_pago[$p->forma_pago] ?? $p->forma_pago }} {{ $p->user->name ?? '' }}@if($p->note) · {{ $p->note }}@endif${{ number_format($p->amount, 2) }}
@endforeach
@endif @if($editable && $r->balance > 0)
{!! Form::open(['route' => ['reservations.payment', $r->id], 'method' => 'post', 'id' => 'payment-form', 'class' => 'row align-items-end']) !!}
{!! Form::close() !!} Los abonos quedan registrados en la reserva. Se facturan desde «Facturación» (el total o cada abono).
@endif
{{-- Facturar la reserva (total o por abono): en la columna principal para equilibrar con la lateral --}} @include('reservation._invoicing', ['reservation' => $r, 'v3' => true]) {{-- Historial --}}

Historial

@if($events === null)

El historial detallado se activa al ejecutar database/cambios/2026-10-18b_reservas_historial.sql.

@elseif($events->isEmpty())

Sin movimientos registrados todavía.

@else
    @foreach($events as $e)
  • {{ $e->message }} {{ $e->user->name ?? '' }}
  • @endforeach
@endif
@endsection