import React, { useState, useMemo } from 'react';
import { FinancialReportType, Expense, Receivable } from '../types';
import { Download, Printer, Filter, ChevronRight, X, Calendar, Building2, CheckCircle2, FileText } from 'lucide-react';
import { useToast } from '../contexts/ToastContext';
import { CustomSelect } from './CustomSelect';
interface FinancialReportsViewProps {
expenses: Expense[];
receivables: Receivable[];
}
const ReportTab = ({ active, label, onClick }: { active: boolean, label: string, onClick: () => void }) => (
);
const TableRow = ({ label, value, indent = 0, isTotal = false, isHeader = false }: { label: string, value: string | React.ReactNode, indent?: number, isTotal?: boolean, isHeader?: boolean }) => (
{label}
{value}
);
export const FinancialReportsView: React.FC = ({ expenses, receivables }) => {
const { addToast } = useToast();
const [activeTab, setActiveTab] = useState('DRE');
const [showFilters, setShowFilters] = useState(false);
const [filters, setFilters] = useState({
period: 'mensal',
costCenter: 'Todos'
});
const handleExport = () => {
addToast({ type: 'info', title: 'Gerando PDF...', message: 'O download iniciará em instantes.', duration: 2000 });
setTimeout(() => {
addToast({ type: 'success', title: 'Exportação Concluída', message: `Relatório ${activeTab} salvo com sucesso.` });
}, 2000);
};
// --- ACCOUNTING ENGINE (Cálculos Reais) ---
const reportData = useMemo(() => {
// 1. Data Preparation
const paidRevenue = receivables.filter(r => r.status === 'paid').reduce((sum, r) => sum + r.value, 0);
const pendingRevenue = receivables.filter(r => r.status === 'pending').reduce((sum, r) => sum + r.value, 0);
const totalRevenue = paidRevenue + pendingRevenue; // Competência
const paidExpenses = expenses.filter(e => e.status === 'paid');
const pendingExpenses = expenses.filter(e => e.status === 'pending');
// Categorização de Despesas Pagas
const taxExpenses = paidExpenses.filter(e => e.category === 'Impostos').reduce((sum, e) => sum + e.amount, 0);
const costExpenses = paidExpenses.filter(e => e.category === 'Operacional').reduce((sum, e) => sum + e.amount, 0); // Mocking Op as CMV/CPV
const adminExpenses = paidExpenses.filter(e => e.category === 'Administrativo' || e.category === 'TI').reduce((sum, e) => sum + e.amount, 0);
const salesExpenses = paidExpenses.filter(e => e.category === 'Marketing').reduce((sum, e) => sum + e.amount, 0);
const personnelExpenses = paidExpenses.filter(e => e.category === 'Pessoal').reduce((sum, e) => sum + e.amount, 0);
// Totais
const totalDeductions = taxExpenses; // Simplificação
const netRevenue = paidRevenue - totalDeductions;
const grossProfit = netRevenue - costExpenses;
const totalOpExpenses = adminExpenses + salesExpenses + personnelExpenses;
const netIncome = grossProfit - totalOpExpenses;
// 2. Balance Sheet (BP) Calculations (Estimated)
// Assets
const cashAndEquivalents = 50000 + (netIncome > 0 ? netIncome : 0); // Mock Start Cash + Profit
const accountsReceivable = pendingRevenue;
const fixedAssets = 150000; // Mocked Fixed Assets (Computers, Furniture)
const totalCurrentAssets = cashAndEquivalents + accountsReceivable;
const totalNonCurrentAssets = fixedAssets;
const totalAssets = totalCurrentAssets + totalNonCurrentAssets;
// Liabilities
const accountsPayable = pendingExpenses.reduce((sum, e) => sum + e.amount, 0);
const loansShortTerm = 20000; // Mock
const loansLongTerm = 100000; // Mock
const totalCurrentLiabilities = accountsPayable + loansShortTerm;
const totalNonCurrentLiabilities = loansLongTerm;
// Equity
const shareCapital = 50000; // Mock
const retainedEarnings = totalAssets - (totalCurrentLiabilities + totalNonCurrentLiabilities + shareCapital); // Balancing figure
const totalEquity = shareCapital + retainedEarnings;
// 3. Cash Flow (DFC) - Direct Method Simplified
const cashInflow = paidRevenue;
const cashOutflowOp = paidExpenses.reduce((sum, e) => sum + e.amount, 0);
const netCashOperating = cashInflow - cashOutflowOp;
// 4. Value Added (DVA)
const inputs = costExpenses + adminExpenses + salesExpenses; // Consumo de terceiros
const grossValueAdded = paidRevenue - inputs;
const netValueAdded = grossValueAdded; // Assuming no depreciation for simplicity
return {
dre: {
grossRevenue: paidRevenue,
taxes: taxExpenses,
netRevenue,
costs: costExpenses,
grossProfit,
adminExpenses,
salesExpenses,
personnelExpenses,
netIncome
},
bp: {
cashAndEquivalents,
accountsReceivable,
totalCurrentAssets,
fixedAssets,
totalAssets,
accountsPayable,
loansShortTerm,
totalCurrentLiabilities,
loansLongTerm,
shareCapital,
retainedEarnings,
totalEquityAndLiabilities: totalCurrentLiabilities + totalNonCurrentLiabilities + totalEquity
},
dfc: {
netCashOperating,
cashInflow,
cashOutflowOp
},
dva: {
grossRevenue: paidRevenue,
inputs,
grossValueAdded,
personnelExpenses,
taxExpenses,
rentals: 0,
equityRemuneration: netIncome
}
};
}, [expenses, receivables]);
const formatCurrency = (val: number) => val.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
const formatNegative = (val: number) => `(${formatCurrency(val)})`;
const periodLabel = filters.period === 'anual' ? '2024' : filters.period === 'trimestral' ? '1º Trimestre 2024' : 'Maio/2024';
const renderContent = () => {
switch (activeTab) {
case 'DRE':
return (
Demonstração do Resultado do Exercício (DRE)
Período: {periodLabel} | Centro de Custo: {filters.costCenter}
= LUCRO / PREJUÍZO LÍQUIDO
{formatCurrency(reportData.dre.netIncome)}
);
case 'BP':
return (
{/* ATIVO */}
ATIVO
TOTAL DO ATIVO
{formatCurrency(reportData.bp.totalAssets)}
{/* PASSIVO */}
PASSIVO E PATRIMÔNIO LÍQUIDO
TOTAL PASSIVO + PL
{formatCurrency(reportData.bp.totalEquityAndLiabilities)}
);
case 'DFC':
return (
Demonstração do Fluxo de Caixa (Método Direto)
Período: {periodLabel}
= 0 ? 'bg-green-50 text-green-800' : 'bg-red-50 text-red-800'}`}>
AUMENTO/REDUÇÃO LÍQUIDA DE CAIXA
{formatCurrency(reportData.dfc.netCashOperating)}
);
case 'DLPA':
return (
Demonstração de Lucros ou Prejuízos Acumulados (DLPA)
SALDO FINAL
{formatCurrency(reportData.bp.retainedEarnings)}
);
case 'DMPL':
return (
Demonstração das Mutações do Patrimônio Líquido (DMPL)
| Histórico |
Capital Social |
Reservas de Lucro |
Lucros Acumulados |
Total |
| Saldo Inicial |
{formatCurrency(reportData.bp.shareCapital)} |
R$ 0,00 |
{formatCurrency(reportData.bp.retainedEarnings - reportData.dre.netIncome)} |
{formatCurrency(reportData.bp.shareCapital + (reportData.bp.retainedEarnings - reportData.dre.netIncome))} |
| Lucro Líquido do Período |
- |
- |
{formatCurrency(reportData.dre.netIncome)} |
{formatCurrency(reportData.dre.netIncome)} |
| Saldo Final |
{formatCurrency(reportData.bp.shareCapital)} |
R$ 0,00 |
{formatCurrency(reportData.bp.retainedEarnings)} |
{formatCurrency(reportData.bp.shareCapital + reportData.bp.retainedEarnings)} |
);
case 'DRA':
return (
Demonstração do Resultado Abrangente (DRA)
RESULTADO ABRANGENTE TOTAL
{formatCurrency(reportData.dre.netIncome)}
);
case 'DVA':
return (
Demonstração do Valor Adicionado (DVA)
6. DISTRIBUIÇÃO DO VALOR ADICIONADO
TOTAL DISTRIBUÍDO
{formatCurrency(reportData.dva.personnelExpenses + reportData.dva.taxExpenses + reportData.dva.rentals + reportData.dva.equityRemuneration)}
);
default:
return null;
}
};
return (
Demonstrações Contábeis
Relatórios gerados em tempo real com base nos lançamentos.
{/* Filter Panel */}
{showFilters && (
setFilters({...filters, period: val})}
options={[
{ value: 'mensal', label: 'Mensal (Mês Atual)' },
{ value: 'trimestral', label: 'Trimestral' },
{ value: 'semestral', label: 'Semestral' },
{ value: 'anual', label: 'Anual (Acumulado)' }
]}
/>
setFilters({...filters, costCenter: val})}
options={[
{ value: 'Todos', label: 'Todos' },
{ value: 'Administrativo', label: 'Administrativo' },
{ value: 'Comercial', label: 'Comercial / Vendas' },
{ value: 'Operacional', label: 'Operacional' },
{ value: 'TI', label: 'Tecnologia (TI)' }
]}
/>
)}
{/* Tabs */}
setActiveTab('DRE')} />
setActiveTab('BP')} />
setActiveTab('DFC')} />
setActiveTab('DLPA')} />
setActiveTab('DMPL')} />
setActiveTab('DRA')} />
setActiveTab('DVA')} />
{renderContent()}
);
};