// phase3-pages.jsx — P&L · Виплати підрядникам · Авансові звіти // ============ P&L ============ function PnlPage({ role }) { const contracts = window.DATA.CONTRACTS; const invoices = window.DATA.INVOICES; const expenses = window.DATA.EXPENSES; const team = window.DATA.TEAM; const subPayments = window.DATA.SUB_PAYMENTS; const [period, setPeriod] = React.useState("month"); // Спрощений розрахунок P&L const grossIncome = invoices.filter(i => i.status === "paid").reduce((s, i) => s + i.amount, 0); const subIncome = grossIncome * 0.84; // без ПДВ const pdvOut = grossIncome - subIncome; const monthlyExpenses = expenses.reduce((s, e) => s + (e.monthlyAmount || 0), 0); const salary = team.reduce((s, p) => { const pay = window.computePayroll(p.id, p.partRate ? 88 : 176, 176); return s + (pay?.gross || 0); }, 0); const subCosts = subPayments.filter(p => p.status === "paid").reduce((s, p) => s + p.amount, 0); const period_mult = period === "month" ? 1 : period === "quarter" ? 3 : 12; const revenue = subIncome; const directCosts = salary + subCosts * 0.2; // примірний розподіл const grossProfit = revenue - directCosts; const opex = monthlyExpenses * period_mult; const ebitda = grossProfit - opex; const taxes = ebitda > 0 ? ebitda * 0.05 : 0; const netProfit = ebitda - taxes; const margin = revenue > 0 ? (netProfit / revenue) * 100 : 0; return (
| Об'єкт | Договір | Сплачено | Витрати | Прибуток | Маржа |
|---|---|---|---|---|---|
|
{obj?.name}
{obj?.code}
|
{window.formatMoney(c.total)} ₴ | {window.formatMoney(paid)} ₴ | {window.formatMoney(costs)} ₴ | = 0 ? "var(--c-green-deep)" : "var(--late)"}}> {profit >= 0 ? "+" : ""}{window.formatMoney(profit)} ₴ |
{pct.toFixed(0)}%
= 30 ? "var(--c-green-deep)" : pct >= 0 ? "var(--c-orange, var(--c-green))" : "var(--late)"}}>
|
| № рахунку | Підрядник | Об'єкт | Тип | Термін | Сума | Статус | |
|---|---|---|---|---|---|---|---|
| {p.invoiceNumber} |
{sup?.name}
{p.description.substring(0, 50)}{p.description.length > 50 ? "..." : ""}
|
{obj?.code} |
{cType.short}
{p.pdvIncluded > 0 && ПДВ {window.formatMoney(p.pdvIncluded)} ₴ }
|
{window.formatDate(p.dueDate)}
{p.status === "overdue" && +{p.lateDays} дн. }
{p.status === "paid" && p.paidDate && сплачено {window.formatDate(p.paidDate)} }
|
{window.formatMoney(p.amount)} ₴ | {p.status === "paid" && сплачено} {p.status === "overdue" && прострочено} {p.status === "issued" && очікує} |