Módulos visuais
mad-reconcile
Básico (zero PHP)
mad-reconcile só por valor — context próprio isola esta conciliação da de baixo, mesmo usando os mesmos models.
Extrato bancário
4
| — | TED Fornecedor Beta | 980,00 |
| — | PIX recebido cliente | 250,75 |
| — | Depósito consolidado | 700,00 |
| — | Tarifa bancária | 24,90 |
Lançamentos
5
| — | Pagto fornecedor Beta | 980,00 |
| — | Recebimento cliente | 250,75 |
| — | Venda balcão manhã | 300,00 |
| — | Venda balcão tarde | 400,00 |
| — | Aluguel sala 9 | 1.500,00 |
resources/views/tutor/examples/modulos-reconcile/basico.blade.php
{{-- Zero PHP: mesma fixture do demo grande, mas com `context` PRÓPRIO e
match-on mais simples (só valor) — contexts diferentes = conciliações
independentes sobre os MESMOS models (não interferem uma na outra). --}}
<mad-reconcile left-model="TutorDemoReconcileExtrato" right-model="TutorDemoReconcileLancamento"
database="business" match-on="amount"
left-amount="valor" right-amount="valor"
left-label="descricao" right-label="historico"
left-title="Extrato bancário" right-title="Lançamentos"
context="tutor_modulos_reconcile_basico" />
Auto-match completo (valor + data + documento)
match-on com os 3 passes do MatchEngine: par exato, tolerância de data e N:1 por soma.
Extrato bancário
4
| 2026-08-30 | PIX recebido cliente | 250,75 | |
| 2026-09-02 | NF-2001 | TED Fornecedor Beta | 980,00 |
| 2026-09-03 | Depósito consolidado | 700,00 | |
| 2026-09-04 | TAR-12 | Tarifa bancária | 24,90 |
Lançamentos
5
| 2026-08-31 | AL-9 | Aluguel sala 9 | 1.500,00 |
| 2026-09-01 | Recebimento cliente | 250,75 | |
| 2026-09-02 | NF-2001 | Pagto fornecedor Beta | 980,00 |
| 2026-09-03 | Venda balcão manhã | 300,00 | |
| 2026-09-03 | Venda balcão tarde | 400,00 |
resources/views/tutor/examples/modulos-reconcile/completo.blade.php
@php
// Partial de <x-tutor-demo> = escopo Blade ISOLADO — `$that` não
// atravessa esse aninhamento sozinho. Reabre aqui só por coerência com o
// padrão dos outros módulos grandes: mad-reconcile NÃO exige host (todas
// as props vêm de attrs), mas usar o HOST deixa a página consistente com
// o `context` "completo" declarado na classe (matchOn com os 3 passes).
$that = \Mad\Component\MadRenderContext::getComponent();
@endphp
{{-- Tag inline sem atributos reusa a config declarada nas props protected da
classe (leftModel/rightModel/matchOn="amount,date:3,document"/context). --}}
<mad-reconcile />
Código-fonte completo da página
app/control/Tutor/TutorModulosReconcile.php
<?php
namespace App\Control\Tutor;
use App\Models\TutorDemo\TutorDemoReconcileExtrato;
use App\Models\TutorDemo\TutorDemoReconcileLancamento;
use Illuminate\Support\Facades\Schema;
use Mad\Reconcile\MadReconcile;
/**
* TutorModulosReconcile — página "Conciliação" do MAD Lab (catálogo
* modulos_reconcile). Cobre: mad-reconcile (self-closing, sem filhos).
*
* Os dois demos leem a MESMA fixture (tutor_reconcile_extrato/lancamentos)
* mas usam `context` diferente — é exatamente o propósito documentado do
* prop (§2 de docs/mad-reconcile.md): separar conciliações independentes
* sobre os MESMOS models. O demo pequeno (basico.blade.php) não reabre
* `$that` — cai num MadReconcileStandalone novo por request (zero PHP); o
* grande (completo.blade.php) reabre `$that` pra usar o HOST (esta classe,
* subclasse de MadReconcile) e demonstrar o `match-on` com os 3 passes do
* MatchEngine (exato, tolerância de data, N:1 por soma).
*/
class TutorModulosReconcile extends MadReconcile
{
protected static string $wrapper = self::INTERNAL;
protected string $leftModel = TutorDemoReconcileExtrato::class;
protected string $rightModel = TutorDemoReconcileLancamento::class;
protected string $database = 'business';
protected string $leftAmount = 'valor';
protected string $rightAmount = 'valor';
protected string $leftDate = 'data';
protected string $rightDate = 'data';
protected string $leftDoc = 'documento';
protected string $rightDoc = 'documento';
protected string $leftLabel = 'descricao';
protected string $rightLabel = 'historico';
protected string $leftTitle = 'Extrato bancário';
protected string $rightTitle = 'Lançamentos';
protected string $matchOn = 'amount,date:3,document';
protected string $context = 'tutor_modulos_reconcile_completo';
public function mount(array $params = []): void
{
$this->ensureFixture();
parent::mount($params);
}
// ── Fixture ──────────────────────────────────────────────────────────
private function ensureFixture(): void
{
$schema = Schema::connection('business');
foreach (['tutor_reconcile_extrato' => 'descricao', 'tutor_reconcile_lancamentos' => 'historico'] as $table => $labelCol) {
if (!$schema->hasTable($table)) {
$schema->create($table, function ($t) use ($labelCol) {
$t->increments('id');
$t->string('data', 10);
$t->string('documento', 40)->nullable();
$t->string($labelCol);
$t->decimal('valor', 12, 2);
});
}
}
if (TutorDemoReconcileExtrato::query()->count() > 0) {
return;
}
$d = fn (int $offset) => date('Y-m-d', strtotime("-{$offset} days"));
TutorDemoReconcileExtrato::query()->insert([
// pass 1: valor exato + mesmo documento
['data' => $d(2), 'documento' => 'NF-2001', 'descricao' => 'TED Fornecedor Beta', 'valor' => 980.00],
// pass 2: valor exato, data dentro da tolerância (±3d), sem doc
['data' => $d(5), 'documento' => null, 'descricao' => 'PIX recebido cliente', 'valor' => 250.75],
// pass 3: 1 linha do extrato = soma de 2 lançamentos
['data' => $d(1), 'documento' => null, 'descricao' => 'Depósito consolidado', 'valor' => 700.00],
// sem par (sobra no painel)
['data' => $d(0), 'documento' => 'TAR-12', 'descricao' => 'Tarifa bancária', 'valor' => 24.90],
]);
TutorDemoReconcileLancamento::query()->insert([
['data' => $d(2), 'documento' => 'NF-2001', 'historico' => 'Pagto fornecedor Beta', 'valor' => 980.00],
['data' => $d(3), 'documento' => null, 'historico' => 'Recebimento cliente', 'valor' => 250.75],
['data' => $d(1), 'documento' => null, 'historico' => 'Venda balcão manhã', 'valor' => 300.00],
['data' => $d(1), 'documento' => null, 'historico' => 'Venda balcão tarde', 'valor' => 400.00],
['data' => $d(4), 'documento' => 'AL-9', 'historico' => 'Aluguel sala 9', 'valor' => 1500.00],
]);
}
protected function view(): string|array
{
return ['tutor.modulos.reconcile', []];
}
}
resources/views/tutor/modulos/reconcile.blade.php
<x-tutor-page page="modulos_reconcile">
<x-tutor-demo demo="tutor.examples.modulos-reconcile.basico"
title="Básico (zero PHP)" desc="mad-reconcile só por valor — context próprio isola esta conciliação da de baixo, mesmo usando os mesmos models." />
<x-tutor-demo demo="tutor.examples.modulos-reconcile.completo"
title="Auto-match completo (valor + data + documento)" desc="match-on com os 3 passes do MatchEngine: par exato, tolerância de data e N:1 por soma." />
</x-tutor-page>