@extends('layouts.enterprise') @section('title', 'Dashboard') @section('content')

Pagos de la semana

Rango: {{ $start->toDateString() }} a {{ $end->toDateString() }} (solo facturas aprobadas/programadas)

@php $defaultPayStart = \Illuminate\Support\Carbon::now()->startOfWeek(\Illuminate\Support\Carbon::MONDAY)->toDateString(); $defaultPayEnd = \Illuminate\Support\Carbon::now()->startOfWeek(\Illuminate\Support\Carbon::MONDAY)->addDays(6)->toDateString(); $payHasActiveFilters = (($payFilters['q'] ?? '') !== '') || (($payFilters['status'] ?? 'approved_scheduled') !== 'approved_scheduled') || (($payFilters['date_from'] ?? $defaultPayStart) !== $defaultPayStart) || (($payFilters['date_to'] ?? $defaultPayEnd) !== $defaultPayEnd); @endphp
Filtros @if($payHasActiveFilters) Activos @endif
@if(!empty($filters['date_from'] ?? null)) @endif @if(!empty($filters['date_to'] ?? null)) @endif @if(($filters['progress_min'] ?? null) !== null) @endif @if(($filters['progress_max'] ?? null) !== null) @endif @if(($filters['amount_progress_min'] ?? null) !== null) @endif @if(($filters['amount_progress_max'] ?? null) !== null) @endif
Limpiar Resultados: {{ $toPayThisWeek->count() }}
Pagos por estatus
Monto por proveedor
@foreach($toPayThisWeek as $inv) @php $payProviderFinancialKey = ($inv->pipefy_request_id && $inv->pipefy_request_provider_id) ? ((int) $inv->pipefy_request_id.'|'.(int) $inv->pipefy_request_provider_id) : null; $payProviderAmounts = $payProviderFinancialKey ? ($payProviderFinancials[$payProviderFinancialKey] ?? null) : null; $payCoveredAmount = (float) ($payProviderAmounts['invoiced_total'] ?? 0); $payPendingAmount = (float) ($payProviderAmounts['pending_total_sale'] ?? 0); $paidAmount = $hasInvoicePayments ? (float) ($inv->paid_total ?? 0) : ($inv->status === \App\Models\Invoice::STATUS_PAID ? (float) $inv->total : 0.0); if ($hasInvoicePayments && $paidAmount <= 0.009 && $inv->status === \App\Models\Invoice::STATUS_PAID) { $paidAmount = (float) $inv->total; } $pendingPayment = max(((float) $inv->total) - $paidAmount, 0); $canRegisterPayment = in_array($inv->status, [ \App\Models\Invoice::STATUS_APPROVED, \App\Models\Invoice::STATUS_SCHEDULED, \App\Models\Invoice::STATUS_PAID, ], true) && $pendingPayment > 0.009; $invoicePdf = $inv->files->firstWhere('type', \App\Models\InvoiceFile::TYPE_INVOICE_PDF); $proof = $inv->files->firstWhere('type', \App\Models\InvoiceFile::TYPE_PAYMENT_PROOF); @endphp @endforeach
ID Proveedor PROJECT NAME Estatus Fecha pago Factura Total Monto facturado Monto pendiente Pagado Saldo pago Acciones
{{ $inv->id }} {{ $inv->company?->legal_name }}
{{ $inv->pipefyRequest?->project_name ?: '-' }}
{{ $inv->pipefyRequest?->title ?: '-' }}
{{ $inv->status }} {{ optional($inv->payment_date)->format('Y-m-d') }} @if($invoicePdf) Ver factura @else Sin factura @endif {{ number_format((float) $inv->total, 2) }} @if($payProviderAmounts) ${{ number_format($payCoveredAmount, 2) }} @else - @endif @if($payProviderAmounts) ${{ number_format($payPendingAmount, 2) }} @else - @endif ${{ number_format($paidAmount, 2) }} ${{ number_format($pendingPayment, 2) }} @if(!$hasInvoicePayments) Ejecuta migraciones @elseif($canRegisterPayment) @else @if($proof) Ver comprobante @else Liquidada @endif @endif
Total con filtros: ${{ number_format((float) $toPayFilteredTotal, 2) }} Total búsqueda actual: ${{ number_format((float) $toPayCurrentTotal, 2) }}
@csrf
Saldo pendiente: $0.00

Marcar como anticipo de pago

Arrastra y suelta tu comprobante aquí
PDF/JPG/PNG · máx. 10 MB
Seleccionar archivo Ningún archivo seleccionado
Cancelar Guardar pago

Cobros de la semana

Rango: {{ \Illuminate\Support\Carbon::parse($collectFilters['date_from'] ?? $start->toDateString())->toDateString() }} a {{ \Illuminate\Support\Carbon::parse($collectFilters['date_to'] ?? $end->toDateString())->toDateString() }} (fecha estimada de cobro por cliente)

@php $defaultCollectStart = \Illuminate\Support\Carbon::now()->startOfWeek(\Illuminate\Support\Carbon::MONDAY)->toDateString(); $defaultCollectEnd = \Illuminate\Support\Carbon::now()->startOfWeek(\Illuminate\Support\Carbon::MONDAY)->addDays(6)->toDateString(); $collectHasActiveFilters = (($collectFilters['q'] ?? '') !== '') || (($collectFilters['status'] ?? 'all') !== 'all') || (($collectFilters['date_from'] ?? $defaultCollectStart) !== $defaultCollectStart) || (($collectFilters['date_to'] ?? $defaultCollectEnd) !== $defaultCollectEnd); @endphp
Filtros @if($collectHasActiveFilters) Activos @endif
@if(!empty($filters['date_from'] ?? null)) @endif @if(!empty($filters['date_to'] ?? null)) @endif @if(($filters['progress_min'] ?? null) !== null) @endif @if(($filters['progress_max'] ?? null) !== null) @endif @if(($filters['amount_progress_min'] ?? null) !== null) @endif @if(($filters['amount_progress_max'] ?? null) !== null) @endif
Limpiar Resultados: {{ $toCollectThisWeek->count() }}
Cobros por estatus
Monto por cliente
@forelse($toCollectThisWeek as $collect) @empty @endforelse
ID Folio Cliente Días pago Emisión Cobro estimado Proyecto Subtotal IVA Total Cobrado Saldo Estatus
{{ $collect['id'] }} {{ $collect['folio'] }} {{ $collect['client_name'] }} {{ $collect['payment_days'] }} {{ $collect['issue_date']->format('Y-m-d') }} {{ $collect['estimated_collection_date']->format('Y-m-d') }}
{{ $collect['project_name'] }}
{{ $collect['title'] }}
${{ number_format((float) $collect['subtotal'], 2) }} ${{ number_format((float) $collect['tax'], 2) }} ${{ number_format((float) $collect['total'], 2) }} ${{ number_format((float) $collect['collected_total'], 2) }} ${{ number_format((float) $collect['pending_total'], 2) }} {{ $collect['status_label'] }}
No hay cobros estimados para el rango seleccionado.
Total con filtros: ${{ number_format((float) $toCollectFilteredTotal, 2) }} Saldo con filtros: ${{ number_format((float) $toCollectFilteredPendingTotal, 2) }} Total búsqueda actual: ${{ number_format((float) $toCollectCurrentTotal, 2) }} Saldo búsqueda actual: ${{ number_format((float) $toCollectCurrentPendingTotal, 2) }}

Estatus por petición (Solicitud)

Control de proveedores por Proyecto, montos facturados y pendientes (solo facturas aprobadas).

@if($errors->any())
    @foreach($errors->all() as $error)
  • {{ $error }}
  • @endforeach
@endif @php $hasActiveFilters = (($filters['completion'] ?? 'all') !== 'all') || !empty($filters['date_from'] ?? null) || !empty($filters['date_to'] ?? null) || (($filters['progress_min'] ?? null) !== null && $filters['progress_min'] !== '') || (($filters['progress_max'] ?? null) !== null && $filters['progress_max'] !== '') || (($filters['amount_progress_min'] ?? null) !== null && $filters['amount_progress_min'] !== '') || (($filters['amount_progress_max'] ?? null) !== null && $filters['amount_progress_max'] !== ''); $providerRanges = [ ['label' => 'Prov 0-25%', 'min' => 0, 'max' => 25], ['label' => 'Prov 26-50%', 'min' => 26, 'max' => 50], ['label' => 'Prov 51-75%', 'min' => 51, 'max' => 75], ['label' => 'Prov 76-100%', 'min' => 76, 'max' => 100], ]; $amountRanges = [ ['label' => 'Monto 0-25%', 'min' => 0, 'max' => 25], ['label' => 'Monto 26-50%', 'min' => 26, 'max' => 50], ['label' => 'Monto 51-75%', 'min' => 51, 'max' => 75], ['label' => 'Monto 76-100%', 'min' => 76, 'max' => 100], ]; @endphp
Filtros @if($hasActiveFilters) Activos @endif
Limpiar Resultados: {{ $requests->count() }}
Atajos % proveedores: @foreach($providerRanges as $range) @php $providerQuery = collect(array_merge(request()->query(), [ 'progress_min' => $range['min'], 'progress_max' => $range['max'], ]))->filter(fn($v) => $v !== null && $v !== '')->all(); $providerActive = (string) request('progress_min') === (string) $range['min'] && (string) request('progress_max') === (string) $range['max']; @endphp {{ $range['label'] }} @endforeach @php $providerClearQuery = collect(array_merge(request()->query(), [ 'progress_min' => null, 'progress_max' => null, ]))->filter(fn($v) => $v !== null && $v !== '')->all(); $providerClearActive = request('progress_min') === null && request('progress_max') === null; @endphp Sin filtro
Atajos % monto: @foreach($amountRanges as $range) @php $amountQuery = collect(array_merge(request()->query(), [ 'amount_progress_min' => $range['min'], 'amount_progress_max' => $range['max'], ]))->filter(fn($v) => $v !== null && $v !== '')->all(); $amountActive = (string) request('amount_progress_min') === (string) $range['min'] && (string) request('amount_progress_max') === (string) $range['max']; @endphp {{ $range['label'] }} @endforeach @php $amountClearQuery = collect(array_merge(request()->query(), [ 'amount_progress_min' => null, 'amount_progress_max' => null, ]))->filter(fn($v) => $v !== null && $v !== '')->all(); $amountClearActive = request('amount_progress_min') === null && request('amount_progress_max') === null; @endphp Sin filtro
Solicitudes completadas
Avance top solicitudes
Tendencia mensual de ganancia (Costo vs Venta)
@forelse($requests as $req) @php $summary = $requestSummaries[$req->id] ?? [ 'providers_total' => 0, 'expected_invoices' => 0, 'providers_with_invoice' => 0, 'providers_partial' => 0, 'providers_without_invoice' => 0, 'completion_percent' => 0, 'is_complete' => false, 'has_expected_amount' => false, 'amount_expected' => null, 'amount_invoiced' => 0, 'amount_pending' => null, 'amount_completion_percent' => 0, 'amount_completion_percent_for_bar' => 0, 'is_amount_complete' => false, 'pending_provider_names' => [], ]; $requestSubtotal = $req->subtotal_cost !== null ? (float) $req->subtotal_cost : (($summary['has_expected_amount'] ?? false) && isset($summary['amount_expected']) ? round(((float) $summary['amount_expected']) / 1.16, 2) : null); $requestSubtotalIva = $requestSubtotal !== null ? round($requestSubtotal * 1.16, 2) : null; @endphp
{{ $req->project_name ?: 'Sin PROJECT NAME' }}
Job Number: {{ $req->title ?: '-' }}
RC(s): {{ $req->rc_list ?: '-' }}
Ejecutivo: {{ $req->executive_display ?: '-' }}
Cliente: {{ $req->client_display ?: '-' }}
Subtotal solicitud: {{ $requestSubtotal !== null ? '$'.number_format($requestSubtotal, 2) : 'Sin subtotal' }} @if($requestSubtotalIva !== null) Con IVA: ${{ number_format($requestSubtotalIva, 2) }} @endif
Prov: {{ $summary['providers_total'] }} Esperadas: {{ $summary['expected_invoices'] }} Con factura: {{ $summary['providers_with_invoice'] }} Parciales: {{ $summary['providers_partial'] ?? 0 }} Pendientes: {{ $summary['providers_without_invoice'] }} Subtotal solicitud: @if($requestSubtotal !== null) ${{ number_format($requestSubtotal, 2) }} @else Sin subtotal @endif @if($requestSubtotalIva !== null) Subtotal + IVA: ${{ number_format($requestSubtotalIva, 2) }} @endif Proveedores: {{ $summary['completion_percent'] }}% Monto: {{ $summary['amount_completion_percent'] }}%
@if($requestSubtotal !== null)
Subtotal de la solicitud (referencia principal): ${{ number_format($requestSubtotal, 2) }} Subtotal + IVA (16%): ${{ number_format($requestSubtotalIva, 2) }}
@endif
Estado de solicitud: {{ $summary['completion_percent'] }}% ({{ $summary['providers_with_invoice'] }}/{{ $summary['expected_invoices'] }})
Avance por monto: @if($summary['has_expected_amount'] && $summary['amount_expected'] !== null) {{ $summary['amount_completion_percent'] }}% (${{ number_format($summary['amount_invoiced'], 2) }}/${{ number_format($summary['amount_expected'], 2) }}) @else Sin monto esperado @endif
@if($summary['has_expected_amount'] && $summary['amount_pending'] !== null)
Saldo pendiente: ${{ number_format($summary['amount_pending'], 2) }}
@endif
PENDIENTES: {{ count($summary['pending_provider_names']) ? implode(', ', $summary['pending_provider_names']) : 'Todos enviaron.' }}
@forelse($req->providers as $provider) @php $totals = $providerTotals[$provider->id] ?? null; $invoicePdf = $providerInvoicePdfLinks[$provider->id] ?? null; $invoicesCount = (int) ($totals?->invoices_count ?? 0); $invoiced = $totals?->total_invoiced ? (float) $totals->total_invoiced : 0.0; $providerItems = $provider->items ->sortBy('product_index') ->values(); $expectedBase = $provider->total_cost; if ($expectedBase === null) { $itemCostTotal = (float) $providerItems->sum(function ($it) { return (float) ($it->total_cost ?? 0); }); if ($itemCostTotal > 0) { $expectedBase = $itemCostTotal; } } if ($expectedBase === null) { $expectedBase = $provider->total_sale; } if ($expectedBase === null) { $itemSaleTotal = (float) $providerItems->sum(function ($it) { return (float) ($it->total_sale ?? 0); }); if ($itemSaleTotal > 0) { $expectedBase = $itemSaleTotal; } } $expected = $expectedBase !== null ? ((float) $expectedBase * 1.16) : null; $pending = $expected !== null ? max($expected - $invoiced, 0) : null; $providerItemsTotal = (int) ($providerItemsTotals[$provider->id] ?? 0); $providerMatchedCount = (int) ($providerMatchedItems[$provider->id] ?? 0); $pendingApprovalCount = (int) ($providerPendingApprovalCounts[$provider->id] ?? 0); $hasLegacyApprovedInvoices = $invoicesCount > 0 && $providerMatchedCount === 0 && $providerItemsTotal > 0; if ($providerItemsTotal > 0 && !$hasLegacyApprovedInvoices) { $providerStatus = $providerMatchedCount <= 0 ? 'none' : ($providerMatchedCount < $providerItemsTotal ? 'partial' : 'complete'); } else { $providerStatus = $invoicesCount > 0 ? 'complete' : 'none'; } @endphp @empty @endforelse
Proveedor Facturas Monto esperado Monto sin IVA Monto facturado Saldo pendiente Productos Estatus
{{ $provider->provider_name }} {{ $invoicesCount }} {{ $expected !== null ? number_format($expected, 2) : '-' }} {{ $expectedBase !== null ? number_format((float) $expectedBase, 2) : '-' }} {{ number_format($invoiced, 2) }} {{ $pending !== null ? number_format($pending, 2) : '-' }} @if($providerItems->isEmpty()) Sin productos @else
Ver productos ({{ $providerItems->count() }}) @foreach($providerItems as $item) @php $displayCode = $item->concept_code ?: \App\Support\ConceptCodeExtractor::extract( (string) ($item->description ?? ''), (string) ($item->product_name ?? '') ); @endphp @endforeach
# COD Producto Cant.
{{ $item->product_index ?: '-' }} {{ $displayCode ?: '-' }} {{ $item->description ?: ($item->product_name ?: '-') }} {{ $item->quantity ?: '-' }}
@endif
@if($providerStatus === 'none') @if($pendingApprovalCount > 0) {{ $pendingApprovalCount === 1 ? 'Factura pendiente por aprobar' : 'Facturas pendientes por aprobar' }} ({{ $pendingApprovalCount }}) @else Sin factura @endif @elseif($providerStatus === 'partial') Parcial ({{ $providerMatchedCount }}/{{ max(1, $providerItemsTotal) }}) @if($invoicePdf) Ver factura @endif @elseif($invoicePdf) Con factura @else Con factura @endif
Sin proveedores asociados.
@empty
No hay solicitudes para mostrar.
@endforelse
@endsection @push('scripts') @endpush