@extends('layouts.app')
@section('title', 'Lançamentos — '.config('app.name'))
{{--
LANÇAMENTOS — a tela única do financeiro.
A tela inteira gira em torno de UMA distinção, e ela precisa ficar visível o
tempo todo: PREVISTO é pelo vencimento ("quanto o período deveria
movimentar"), REALIZADO é pela baixa ("quanto entrou e saiu de fato"). Uma
conta de junho paga em julho aparece nos dois, em meses diferentes — e as
duas afirmações estão certas.
AS AÇÕES MORAM NA LINHA, não numa segunda tela: clicar no lançamento abre a
edição, o polegar dá e desfaz a baixa, e o "+" do cabeçalho cadastra receita
ou despesa. Todas postam para as rotas de escrita de sempre — esta tela não
tem regra de dinheiro própria.
--}}
@php
$money = fn (int $cents) => App\Support\Money::format($cents);
$signed = fn (int $cents) => ($cents < 0 ? '− ' : '').App\Support\Money::format(abs($cents));
$income = App\Enums\FinancialOperation::In;
$expense = App\Enums\FinancialOperation::Out;
@endphp
@section('content')
Lançamentos
O que a arena movimentou no período.
{{-- O "+" abre um menu em vez de um modal direto porque a escolha
receita/despesa é a PRIMEIRA decisão do cadastro e define o lado do
caixa — que vem da rota (o `action` de cada formulário), nunca de um
campo. Um seletor dentro do modal reintroduziria pelo formulário
exatamente o que a rota existe para impedir. --}}
@can('create', App\Models\FinancialEntry::class)
{{-- `data-hover-dropdown`: o menu abre ao passar o mouse, sem exigir
o clique. O clique CONTINUA valendo — é o que mantém o botão
utilizável no celular, que não tem hover, e no teclado. Ver
resources/js/cashflow.js. --}}
{{-- A TRANSFERÊNCIA VEM DEPOIS, e separada: ela não é um
terceiro lado do caixa. Agrupá-la com receita e despesa
sugeriria que as três somam no mesmo lugar, e ela não
entra em soma nenhuma. --}}
@can('create', App\Models\FinancialTransfer::class)
@endcan
@endcan
@include('partials.status')
{{-- Inadimplência: o que venceu no período e ninguém pagou. Fica em
destaque próprio porque é a única linha do relatório sobre a qual dá
para AGIR hoje. --}}
@if ($overdue['in'] > 0 || $overdue['out'] > 0)
Vencido e em aberto
A receber:
{{ $money($overdue['in']) }}
A pagar:
{{ $money($overdue['out']) }}
{{-- Antes este botão levava para a tela de Contas a Receber
filtrada. Agora ele FILTRA A PRÓPRIA TELA: a lista das
receitas em aberto já está aqui, e mandar o usuário embora
para ver um recorte do que ele está olhando era a duplicação
de tela que esta sprint eliminou. --}}
Ver receitas em aberto
@endif
{{-- LANÇAMENTOS DO MÊS.
Ficou no lugar da antiga tabela "mês a mês", que era só resumo. Com os
lançamentos à vista, o efeito de cada filtro é visível LINHA A LINHA,
em vez de ter de ser deduzido de um total que mudou — era o que fazia
parecer que os filtros não estavam sendo aplicados.
Tudo aqui vem do servidor, inclusive a troca de mês e de leitura: um
caminho de código só para a tela e para o filtro elimina a classe
inteira de defeito em que a lista e os totais discordam. --}}
{{-- A lista é AGRUPADA POR DIA, não uma tabela com uma coluna de data:
o dia repetido em vinte linhas seguidas é ruído, e o separador
responde "o que aconteceu no dia 10?" de relance.
`groupBy` sobre a PÁGINA já carregada, e não uma consulta por dia:
os lançamentos estão em memória, e agrupar aqui não custa ida ao
banco nenhuma. --}}
{{-- `listedOn()` e não `due_date`: a lista tem DUAS coisas dentro —
lançamentos e transferências — e só essa pergunta as duas sabem
responder. Ver App\Models\FinancialTransfer::listedOn(). --}}
@forelse ($entries->groupBy(fn ($row) => $row->listedOn()->format('d/m/Y')) as $day => $group)
{{ $day }}
@foreach ($group as $entry)
{{-- A TRANSFERÊNCIA TEM LINHA PRÓPRIA: não tem lado do caixa,
nem categoria, nem baixa a dar, então nada da linha de
lançamento abaixo se aplicaria a ela. --}}
@if ($entry instanceof App\Models\FinancialTransfer)
@include('financial._transfer-row', ['transfer' => $entry])
@continue
@endif
@php
$isIncome = $entry->operation === App\Enums\FinancialOperation::In;
$isPaid = $entry->isPaid();
/*
* A comanda de origem, se este lançamento veio de uma —
* já resolvida pelo controller para a página inteira
* (ver FinancialReportController::ordersBehind()). Aqui
* é só uma consulta em memória: um `Order::find()` nesta
* linha seria um N+1 na tela mais movimentada do sistema.
*/
$sourceOrder = $sourceOrders[$entry->id] ?? null;
/*
* O agendamento de origem, pelo mesmo caminho e pelo
* mesmo motivo da comanda acima — já resolvido em lote
* pelo controller (ver ReservationSummary::forEntries()).
*/
$sourceReservation = $sourceReservations[$entry->id] ?? null;
@endphp
{{-- Ícone da OPERAÇÃO: verde para o que entra, vermelho
para o que sai. É a leitura mais rápida da linha,
antes mesmo do valor. --}}
{{-- O CORPO DA LINHA É O GATILHO DA EDIÇÃO quando o
usuário pode editar, e texto puro quando não pode.
Um lápis por linha competiria visualmente com o
polegar, que é a ação do dia a dia; clicar no
lançamento é o gesto que a referência usa e o que já
se espera de uma lista assim.
É um