import type { CashFlowData } from "@/lib/cashflow"; /* Struttura del P&L del Cash Flow. Le etichette sono quelle di oggi (cashFlowRowDefinitions in CashFlow.tsx): non si traducono e non si rinominano. La riga "Total …" di ogni sezione diventa l'intestazione della sezione stessa (con il totale), come nel design. drill: categoria e tipo passati a /transactions quando si clicca un importo. !! Claude Code: allinea questi valori a quelli che CashFlow.tsx passa oggi a nella vista mensile. Se differiscono, vince il codice attuale. */ type Key = keyof CashFlowData; export type Tone = "income" | "cost-1" | "cost-2" | "cost-3" | "income-2" | "cost-4"; export interface PnlLine { label: string; key: Key; drill?: { category: string; type: "income" | "expense" }; } export interface PnlSection { kind: "section"; id: string; label: string; totalKey: Key; tone: Tone; /** true per le sezioni (+): la variazione positiva è buona */ positive: boolean; lines: PnlLine[]; } export interface PnlResult { kind: "subtotal" | "key" | "total"; id: string; label: string; key: Key; } export type PnlBlock = PnlSection | PnlResult; export const PNL: PnlBlock[] = [ { kind: "section", id: "sales", label: "(+) Sales", totalKey: "totalSales", tone: "income", positive: true, lines: [ { label: "Paypal Sales", key: "paypalSales", drill: { category: "PAYPAL Sales", type: "income" } }, { label: "Paypal Disputes Reversal", key: "paypalDisputeReversal", drill: { category: "PAYPAL Disputes Reversal", type: "income" } }, { label: "Stripe Sales", key: "stripeSales", drill: { category: "STRIPE Sales", type: "income" } }, { label: "Stripe Disputes Reversal", key: "stripeDisputeReversal", drill: { category: "STRIPE Disputes Reversal", type: "income" } }, { label: "Sales", key: "sales", drill: { category: "Sales", type: "income" } }, { label: "Economic Variation +", key: "economicVariationPlus", drill: { category: "Economic Variations +", type: "income" } }, ], }, { kind: "section", id: "direct", label: "(−) Direct Costs", totalKey: "totalDirectCosts", tone: "cost-1", positive: false, lines: [ { label: "Paypal Fees", key: "paypalFees", drill: { category: "PAYPAL Fees (-)", type: "expense" } }, { label: "Paypal Refunds", key: "paypalRefund", drill: { category: "PAYPAL Refunds", type: "expense" } }, { label: "Paypal Disputes", key: "paypalDispute", drill: { category: "PAYPAL Disputes", type: "expense" } }, { label: "Stripe Fees", key: "stripeFees", drill: { category: "STRIPE Fees (-)", type: "expense" } }, { label: "Stripe Refunds", key: "stripeRefund", drill: { category: "STRIPE Refunds", type: "expense" } }, { label: "Stripe Disputes", key: "stripeDispute", drill: { category: "STRIPE Disputes", type: "expense" } }, { label: "ADV Cost", key: "advCost", drill: { category: "Advertising", type: "expense" } }, { label: "Economic Variations −", key: "economicVariationMinus", drill: { category: "Economic Variations −", type: "expense" } }, ], }, { kind: "subtotal", id: "gdp", label: "GROSS DIRECT PROFIT", key: "grossDirectProfit" }, { kind: "section", id: "operating", label: "(−) Operating Costs", totalKey: "totalOperatingCosts", tone: "cost-2", positive: false, lines: [ { label: "Softwares & Subscriptions", key: "programSubscription", drill: { category: "Software & Subscriptions", type: "expense" } }, { label: "Payrolls", key: "payroll", drill: { category: "Payrolls", type: "expense" } }, ], }, { kind: "subtotal", id: "gop", label: "GROSS OPERATING PROFIT", key: "grossOperatingProfit" }, { kind: "section", id: "otherOperating", label: "(−) Other Operating Costs", totalKey: "totalOtherOperatingCosts", tone: "cost-3", positive: false, lines: [ { label: "Training", key: "training", drill: { category: "Training", type: "expense" } }, { label: "Physical Products", key: "physicalProduct", drill: { category: "Physical Product", type: "expense" } }, { label: "Accounting", key: "accounting", drill: { category: "Accounting", type: "expense" } }, { label: "Consulting", key: "consulting", drill: { category: "Consulting", type: "expense" } }, // "Bank Fees" usa oggi specialFilter=bankFeesTotal: gestito in onDrill della pagina. { label: "Bank Fees", key: "bankFee", drill: { category: "Bank Fees", type: "expense" } }, ], }, { kind: "key", id: "ebitda", label: "OPERATING INCOME (EBITDA)", key: "operatingIncome" }, { kind: "section", id: "otherIncome", label: "(+) Other Income", totalKey: "totalIncome", tone: "income-2", positive: true, lines: [ { label: "Refunds", key: "subscriptionsRefunds", drill: { category: "Refunds", type: "income" } }, { label: "Interests Income", key: "interestIncome", drill: { category: "Interests Income", type: "income" } }, { label: "Tax Refunds", key: "taxRefund", drill: { category: "Taxes Refund", type: "income" } }, { label: "Loans / Cash Injection", key: "loanCashInjection", drill: { category: "Loans / Cash Injection", type: "income" } }, ], }, { kind: "section", id: "additional", label: "(−) Additional Expenses", totalKey: "totalAdditionalExpenses", tone: "cost-4", positive: false, lines: [ { label: "Personal Expenses", key: "personalExpenses", drill: { category: "Personal Expenses", type: "expense" } }, { label: "Dividends", key: "dividend", drill: { category: "Dividends", type: "expense" } }, { label: "Charitable Contributions", key: "charitableContributions", drill: { category: "Charitable Contributions", type: "expense" } }, { label: "Taxes", key: "incomeTax", drill: { category: "Taxes", type: "expense" } }, { label: "Interests Expense", key: "interestExpense", drill: { category: "Interest Expense", type: "expense" } }, { label: "Other", key: "other1", drill: { category: "Other", type: "expense" } }, ], }, { kind: "total", id: "net", label: "PROFIT NET", key: "profitNet" }, ]; /* Classi statiche (Tailwind non vede le classi costruite a runtime). */ export const TONE: Record = { income: { row: "bg-pl-income", bar: "border-l-pl-income-bar", ink: "text-pl-income-ink", fill: "bg-pl-income-bar" }, "cost-1": { row: "bg-pl-cost-1", bar: "border-l-pl-cost-1-bar", ink: "text-pl-cost-1-ink", fill: "bg-pl-cost-1-bar" }, "cost-2": { row: "bg-pl-cost-2", bar: "border-l-pl-cost-2-bar", ink: "text-pl-cost-2-ink", fill: "bg-pl-cost-2-bar" }, "cost-3": { row: "bg-pl-cost-3", bar: "border-l-pl-cost-3-bar", ink: "text-pl-cost-3-ink", fill: "bg-pl-cost-3-bar" }, "income-2": { row: "bg-pl-income-2", bar: "border-l-pl-income-2-bar", ink: "text-pl-income-2-ink", fill: "bg-pl-income-2-bar" }, "cost-4": { row: "bg-pl-cost-4", bar: "border-l-pl-cost-4-bar", ink: "text-pl-cost-4-ink", fill: "bg-pl-cost-4-bar" }, }; export const RESULT_CLASS: Record = { subtotal: { row: "bg-pl-subtotal", ink: "text-foreground", bar: "border-l-pl-subtotal-bar" }, key: { row: "bg-pl-key", ink: "text-pl-key-ink", bar: "border-l-primary" }, total: { row: "bg-pl-total", ink: "text-pl-total-ink", bar: "border-l-pl-total" }, };