@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

Reservas

@include('reservation._nav', ['active' => '']) {{-- Encabezado --}}

{{ $reservation->reference_no }}

{{ $reservation->status_label }} @if($reservation->status != 3) Pago: {{ $reservation->financial_label }} Paquete: {{ $reservation->logistic_label }} @else@endif
Ver PDF
@if($reservation->step !== null) @php $steps = ['Activa', 'Pagada · ' . ($reservation->is_pickup ? 'por retirar' : 'por enviar'), 'Entregada']; $cur = $reservation->step; @endphp
    @foreach($steps as $i => $label) @php $done = $i < $cur || $cur == 2; @endphp
  1. {{ $done ? '✓' : $i + 1 }}{{ $label }}
  2. @endforeach
@endif
Cliente: @if($customer->id){{ $customer->name }} ({{ $customer->tax_no ?: $customer->ruc }}) · {{ $customer->phone_number }}@else{{ $customer->name }}@endif @if($reservation->client_code && $customer->id) · Código {{ $reservation->client_code }}@endif
Tienda: {{ $reservation->warehouse->name ?? '' }}@if($reservation->biller) · Caja {{ $reservation->biller->name }}@endif
Responsable: {{ $reservation->user->name ?? '' }} @if($reservation->creator && $reservation->created_by != $reservation->user_id)(registró: {{ $reservation->creator->name }})@endif
Creada: {{ $reservation->created_at->format('d/m/Y H:i') }}
Vence (plazo de pago): {{ $reservation->due_date ? \Carbon\Carbon::parse($reservation->due_date)->format('d/m/Y') : 'sin vencimiento' }} @if($reservation->due_date && $reservation->status == 1)({{ $reservation->is_overdue ? 'vencida' : 'quedan ' . now()->startOfDay()->diffInDays(\Carbon\Carbon::parse($reservation->due_date)) . ' días' }})@endif
@if($reservation->note)Nota: {{ $reservation->note }}@endif
{{-- Totales --}}
PRODUCTOS
${{ number_format($reservation->products_total, 2) }}
ENVÍO
${{ number_format($reservation->shipping_cost, 2) }}
{{ $reservation->delivery_mode ? ($reservation->is_pickup ? 'Retiro' : 'Envío') : 'Por definir' }}
TOTAL
${{ number_format($reservation->total, 2) }}
ABONADO
${{ number_format($reservation->paid, 2) }}
SALDO
${{ number_format($reservation->balance, 2) }}

Saldo = productos + envío − abonos. Retiro = $0.

@if($reservation->status == 1 && $reservation->total > 0 && $reservation->balance <= 0 && !$reservation->delivery_mode)
Productos pagados. Elige abajo el método de entrega (retiro o envío) para que pase a POR PROCESAR. Si es envío, su costo se suma al saldo.
@endif {{-- Facturación: la reserva no es factura. Se puede reservar solo con el código y completar el cliente después. --}} @if($reservation->status != 3)
@if($reservation->customer_id) Datos de facturación: {{ $customer->name }} ({{ $customer->tax_no ?: $customer->ruc ?: 'sin cédula/RUC' }}). @else Datos de facturación pendientes: esta reserva se hizo solo con el código. No impide reservar, abonar ni entregar. @endif La reserva no genera factura. Cuándo y cómo se factura una reserva lo define el contador; aquí solo se guarda el cliente. @if($can_assign)
@include('reservation._assign_customer', ['reservation' => $reservation])
@endif
@endif @if($reservation->merged_into)
Esta reserva se unió a la reserva {{ $reservation->mergedInto->reference_no ?? ('#' . $reservation->merged_into) }}: sus productos y abonos están ahora allí.
@endif @if($merged->isNotEmpty())

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

@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', $reservation->id], 'method' => 'post', 'class' => 'd-inline', 'onsubmit' => "return confirm('¿Unir " . $other->reference_no . " a " . $reservation->reference_no . "? Sus productos y abonos pasan a esta reserva. " . $other->reference_no . " queda como Unida (no se borra).')"]) !!} {!! Form::close() !!} @endforeach
@endif {{-- Paquete: método de envío y, si está pagada, marcar enviado/entregado (bodega) --}} @if(in_array($reservation->status, [1, 4, 5]))
@if(in_array($reservation->status, [4, 5])) {{-- Acción principal de una pagada: un solo paso hasta ENTREGADA --}}
PAGADA · {{ mb_strtoupper($reservation->status == 5 ? 'Enviada, por cerrar' : $reservation->pending_action_label) }} @if($reservation->paid_at)(desde el {{ \Carbon\Carbon::parse($reservation->paid_at)->format('d/m/Y') }})@endif
@if($reservation->status == 5 || !$reservation->exit_issues) {!! Form::open(['route' => ['reservations.deliver', $reservation->id], 'method' => 'post', 'class' => 'mb-0', 'onsubmit' => "return confirm('¿" . $reservation->confirm_label . " de " . $reservation->reference_no . "? Pasa a ENTREGADA.')"]) !!} {!! Form::close() !!} @endif
@if($reservation->status == 4 && $reservation->exit_issues)
Todavía no se puede entregar: {{ implode('; ', $reservation->exit_issues) }}.
@endif @endif {!! Form::open(['route' => ['reservations.shipping', $reservation->id], 'method' => 'post', 'class' => 'row align-items-end']) !!}
status == 5) disabled @endif>
{!! Form::close() !!}
@endif @if($reservation->surplus > 0)
El cliente tiene un excedente de ${{ number_format($reservation->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 @include('reservation._invoicing', ['reservation' => $reservation]) {{-- Productos --}}
Productos
@if($editable) @endif
@if($editable)
{!! Form::open(['route' => ['reservations.items.add', $reservation->id], 'method' => 'post', 'class' => 'row align-items-end', 'id' => 'add-item-form']) !!}
 
{!! Form::close() !!}
@endif
@if($editable)@endif @foreach($reservation->items as $item) @if($editable) @endif @endforeach @if($editable)@endif @if($reservation->shipping_cost > 0)@if($editable)@endif@endif @if($editable)@endif
ProductoCantidadPrecioSubtotalAcción
{{ $item->product->name ?? '' }} {{ $item->product->code ?? '' }} @if($editable) {!! Form::open(['route' => ['reservations.items.update', $reservation->id, $item->id], 'method' => 'post', 'class' => 'd-flex justify-content-end no-print', 'id' => 'item-form-' . $item->id]) !!} {!! Form::close() !!} {{ (float) $item->qty }} @else {{ (float) $item->qty }} @endif @if($editable)
$
${{ number_format($item->unit_price, 2) }} @else ${{ number_format($item->unit_price, 2) }} @endif
${{ number_format($item->subtotal, 2) }} {!! Form::open(['route' => ['reservations.items.remove', $reservation->id, $item->id], 'method' => 'post', 'onsubmit' => "return confirm('¿Quitar " . e(addslashes($item->product->name ?? 'este producto')) . " de la reserva? Sus unidades vuelven al stock.')"]) !!} {!! Form::close() !!}
Productos${{ number_format($reservation->products_total, 2) }}
Envío${{ number_format($reservation->shipping_cost, 2) }}
TOTAL${{ number_format($reservation->total, 2) }}
{{-- Abonos --}}
Abonos
@if($reservation->payments->isEmpty())

Todavía no hay abonos.

@else
@foreach($reservation->payments->sortBy('id') as $p) @endforeach
#FechaMontoForma de pagoUsuarioNota
Abono {{ $loop->iteration }} {{ $p->created_at->format('d/m/Y H:i') }} ${{ number_format($p->amount, 2) }} {{ $formas_pago[$p->forma_pago] ?? $p->forma_pago }} {{ $p->user->name ?? '' }} {{ $p->note }}
Total abonado${{ number_format($reservation->paid, 2) }}
@endif @if($editable)
@if($reservation->balance > 0)
Agregar abono
{!! Form::open(['route' => ['reservations.payment', $reservation->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 @if($reservation->paid == 0)
{!! Form::open(['route' => ['reservations.cancel', $reservation->id], 'method' => 'post', 'onsubmit' => "return confirm('¿Cancelar la reserva? Los productos vuelven al stock disponible. La reserva no se borra: queda en Canceladas.')"]) !!} {!! Form::close() !!}
@else

Esta reserva tiene abonos: no se puede cancelar todavía (la devolución o crédito se definirá más adelante).

@endif
@elseif($reservation->status == 2)
{{ $reservation->package_label }} {{ $reservation->delivered_at ? 'el ' . \Carbon\Carbon::parse($reservation->delivered_at)->format('d/m/Y H:i') : '' }} @if($reservation->deliverer) · marcó {{ $reservation->deliverer->name }}@endif @if($reservation->shipping_method)
{{ $reservation->shipping_method }}@endif @if($reservation->shipping_note) · {{ $reservation->shipping_note }}@endif
@if($reservation->delivery_type) {!! Form::open(['route' => ['reservations.undo-deliver', $reservation->id], 'method' => 'post', 'class' => 'no-print', 'onsubmit' => "return confirm('¿Se marcó por error? La reserva vuelve a PAGADA.')"]) !!} {!! Form::close() !!} @endif
@elseif($reservation->status == 3 && !$reservation->merged_into)
Reserva cancelada: sus productos volvieron al stock disponible.
@endif {{-- Historial (reservation_events): consolidaciones, abonos, pagos, envíos y entregas, con quién y cuándo --}}
Historial
@if($events === null)

El historial detallado se activa al ejecutar database/cambios/2026-10-18b_reservas_historial.sql. Mientras tanto, los abonos de arriba muestran fecha y usuario.

@elseif($events->isEmpty())

Sin movimientos registrados todavía (el historial empezó a guardarse el 18/10/2026).

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