@php use App\Support\LaundrySemaphoreColorResolver; use App\Support\TicketObservationLines; use App\Support\TicketThermalSections; $entregaCarbon = LaundrySemaphoreColorResolver::promisedAt($orden); if (! $entregaCarbon instanceof \Illuminate\Support\Carbon) { $entregaCarbon = \Illuminate\Support\Carbon::parse($entregaCarbon, config('app.timezone')); } $entregaStr = LaundrySemaphoreColorResolver::formatEntregaTicket($entregaCarbon); $replaceVars = [ '{folio}' => (string) ($orden->folio_unico ?? ''), '{fecha_hora}' => (string) optional($orden->created_at)->format('d/m/Y H:i:s'), '{fecha}' => (string) optional($orden->created_at)->format('d/m/Y'), '{cliente}' => (string) ($orden->cliente_nombre ?? ''), '{total}' => number_format((float) ($orden->total ?? 0), 2), '{fecha_entrega}' => $entregaCarbon->format('d/m/Y'), '{fecha_entrega_hora}' => $entregaCarbon->format('H:i'), '{fecha_entrega_dia}' => strtoupper($entregaCarbon->locale('es')->isoFormat('ddd')), '{fecha_entrega_completa}' => $entregaStr, '{recepcionista}' => (string) ($orden->recepcionista->name ?? 'N/D'), ]; $headerLines = collect([ $config?->ticket_encabezado_nombre ?? null, ! empty($config?->ticket_encabezado_rfc) ? 'RFC: '.$config->ticket_encabezado_rfc : null, $config?->ticket_encabezado_domicilio ?? null, $config?->ticket_encabezado_cp_ciudad ?? null, ! empty($config?->ticket_encabezado_telefono) ? 'TELEFONO: '.$config->ticket_encabezado_telefono : null, $config?->ticket_encabezado_linea_folio ?? null, ]) ->map(fn ($line) => trim((string) $line)) ->filter(fn ($line) => $line !== '') ->map(fn ($line) => strtr($line, $replaceVars)) ->values(); $footerLines = collect(preg_split("/\r\n|\n|\r/", (string) ($config?->ticket_footer_text ?? ''))) ->map(fn ($line) => trim((string) $line)) ->filter(fn ($line) => $line !== '') ->map(fn ($line) => strtr($line, $replaceVars)) ->values(); $part = TicketThermalSections::partition($detalles); $cargas = $part['cargas']; $servicios = $part['servicios']; $contenido = $part['contenido']; $subCargas = TicketThermalSections::sectionSubtotal($cargas); $subServicios = TicketThermalSections::sectionSubtotal($servicios); $ropaSublines = TicketThermalSections::detalleRopaSublines($orden->detalles_ropa ?? null); $sumLineas = (float) collect($detalles)->sum(fn ($d) => (float) $d->subtotal); $subtotalOrden = (float) ($orden->subtotal ?? 0) > 0 ? (float) $orden->subtotal : $sumLineas; $impuestos = (float) ($orden->impuestos ?? 0); $total = (float) ($orden->total ?? 0); $anticipo = 0.0; $saldo = max(0, $total - $anticipo); $registros = collect($detalles)->count(); $entrega = $entregaCarbon->copy(); $entregaStr = LaundrySemaphoreColorResolver::formatEntregaTicket($entrega); $politicasDefault = [ 'LA CARGA MÍNIMA ES DE 3 KG. PARA SERVICIOS NORMAL, EXPRESS y SÚPER EXPRESS.', 'EL TICKET ES INDISPENSABLE PARA RECOGER SUS PRENDAS.', 'LOS CAMBIOS O RECLAMACIONES POR PIEZAS FALTANTES O DAÑOS DEBERÁN HACERSE A MÁS TARDAR 3 DÍAS DESPUÉS DE LA ENTREGA.', 'TIEMPO MÁXIMO EN BODEGA ES DE 8 DÍAS A PARTIR DE LA FECHA DE ENTREGA DE LA PRENDA, DESPUÉS DE ESE TIEMPO LA LAVANDERÍA QUEDA LIBERADA DE TODA RESPONSABILIDAD.', ]; @endphp
@if($config && $config->logo_url) @endif
@if($headerLines->isNotEmpty()) @foreach($headerLines as $line)
{{ $line }}
@endforeach @else
{{ $config->nombre_empresa ?? config('app.name') }}
@if($config && ($config->rfc || $config->direccion))
@if(!empty($config->rfc)) RFC: {{ $config->rfc }}
@endif @if(!empty($config->direccion)) {{ $config->direccion }} @endif @if(!empty($config->telefono))
{{ $config->telefono }} @endif
@endif @endif
TICKET: {{ $orden->folio_unico }}  |  EXP: {{ $orden->created_at->format('d/m/Y') }}  |  {{ $orden->created_at->format('H:i:s') }}

@if($cargas->isNotEmpty())
CARGAS MÍNIMAS
@foreach($cargas as $idx => $d) @endforeach
CONCEPTO P. UNIT. CANT. DESC. IMPORTE
{{ strtoupper(TicketThermalSections::lineConcepto($d)) }} @if($idx === 0 && count($ropaSublines) > 0) @foreach($ropaSublines as $sl)
→ {{ \Illuminate\Support\Str::limit($sl, 120) }}
@endforeach @endif
${{ number_format((float) $d->precio_unitario, 2) }} {{ number_format((float) $d->cantidad, 2) }} $0.00 ${{ number_format((float) $d->subtotal, 2) }}
${{ number_format($subCargas, 2) }}
@endif @if($servicios->isNotEmpty())
SERVICIOS GENERALES
@foreach($servicios as $d) @endforeach
CONCEPTO P. UNIT. CANT. DESC. IMPORTE
{{ TicketThermalSections::lineConcepto($d) }} ${{ number_format((float) $d->precio_unitario, 2) }} {{ number_format((float) $d->cantidad, 2) }} $0.00 ${{ number_format((float) $d->subtotal, 2) }}
${{ number_format($subServicios, 2) }}
@endif @if($contenido->isNotEmpty())
CONTENIDO DEL SERVICIO
@foreach($contenido as $d) @if(!empty($d->observations)) @endif @endforeach
DETALLE CANT.
{{ TicketThermalSections::lineConcepto($d) }} {{ number_format((float) $d->cantidad, 0) }}
→ {{ \Illuminate\Support\Str::limit($d->observations, 120) }}
@endif @if($cargas->isEmpty() && $servicios->isEmpty())
{{ $orden->tipo_servicio ?? 'Servicio' }}
1.00 $0.00 ${{ number_format($total, 2) }}
${{ number_format($total, 2) }}
@endif
Registros:{{ $registros }}
Impuestos:{{ number_format($impuestos, 2) }}
Recibido:$0.00
Cambio:$0.00
TOTAL: ${{ number_format($total, 2) }}
ANTICIPO:$0.00
SALDO:${{ number_format($saldo, 2) }}
@if($anticipo <= 0.0001)
NO DEJO ANTICIPO
@endif
CLIENTE: {{ $orden->cliente_nombre ?? '—' }}
SE ENTREGA: {{ $entregaStr }}
PENDIENTE DE PAGAR: ${{ number_format($saldo, 2) }}
@if(TicketObservationLines::hasAny($ticketObservations))
@if(!empty($ticketObservations['garment_sections']))
{{ $ticketObsTitlePrenda }}
@foreach($ticketObservations['garment_sections'] as $sec)
{{ $sec['title'] }}
@foreach($sec['lines'] as $line)
• {{ \Illuminate\Support\Str::limit($line, 220) }}
@endforeach @endforeach @endif @foreach($ticketObservations['general_lines'] as $gl)
{{ $gl['label'] }}: {{ \Illuminate\Support\Str::limit($gl['text'], 220) }}
@endforeach @endif
¡GRACIAS POR SU PREFERENCIA!
LE ATENDIÓ: {{ \Illuminate\Support\Str::upper(optional($orden->recepcionista)->name ?? 'N/D') }}
POLITICAS DEL SERVICIO
@if($footerLines->isNotEmpty())
@foreach($footerLines as $line)
{{ $line }}
@endforeach
@elseif($config && !empty($config->terminos_condiciones))
{{ \Illuminate\Support\Str::limit(strip_tags((string) $config->terminos_condiciones), 1200) }}
@else
    @foreach($politicasDefault as $p)
  1. {{ $p }}
  2. @endforeach
@endif
@if(!empty($barcodeSeguimientoDataUri))
Código de barras seguimiento
Escanee en Lavandería (Escanear / escaneo por área).
@if(!empty($barcodeSeguimientoPayload))
{{ $barcodeSeguimientoPayload }}
@endif @if(!empty($urlSeguimiento))
Consulta pública: {{ $urlSeguimiento }}
@endif
@else
Consulta pública: {{ e($urlSeguimiento ?? '') }}
@endif