import dayjs from "dayjs" import customParseFormat from "dayjs/plugin/customParseFormat" dayjs.extend(customParseFormat) export const TAX_EVALUATION_PERIOD_OPTIONS = [ { label: "Monatlich", value: "monthly" }, { label: "Quartalsweise", value: "quarterly" }, { label: "Jährlich", value: "yearly" }, ] export const normalizeTaxEvaluationPeriod = (value?: string) => { if (value === "quarterly" || value === "yearly") return value return "monthly" } const ZERO_BREAKDOWN = () => ({ net19: 0, tax19: 0, net7: 0, tax7: 0, net0: 0, }) const isTaxFreeDocument = (taxType?: string | null) => { return ["13b UStG", "19 UStG", "12.3 UStG"].includes(String(taxType || "")) } export const getTaxEvaluationPeriodBounds = ( referenceDate: dayjs.ConfigType, period: string ) => { const normalized = normalizeTaxEvaluationPeriod(period) const base = dayjs(referenceDate) if (normalized === "yearly") { return { start: base.startOf("year"), end: base.endOf("year"), } } if (normalized === "quarterly") { const quarterStartMonth = Math.floor(base.month() / 3) * 3 const start = base.month(quarterStartMonth).startOf("month") return { start, end: start.add(2, "month").endOf("month"), } } return { start: base.startOf("month"), end: base.endOf("month"), } } export const shiftTaxEvaluationPeriodStart = ( periodStart: dayjs.ConfigType, period: string, offset: number ) => { const normalized = normalizeTaxEvaluationPeriod(period) const base = dayjs(periodStart) if (normalized === "yearly") return base.add(offset, "year").startOf("year") if (normalized === "quarterly") return base.add(offset * 3, "month").startOf("month") return base.add(offset, "month").startOf("month") } export const formatTaxEvaluationPeriodLabel = ( periodStart: dayjs.ConfigType, period: string ) => { const { start, end } = getTaxEvaluationPeriodBounds(periodStart, period) const normalized = normalizeTaxEvaluationPeriod(period) if (normalized === "yearly") { return start.format("YYYY") } if (normalized === "quarterly") { return `Q${Math.floor(start.month() / 3) + 1} ${start.format("YYYY")}` } return start.format("MMMM YYYY") } export const formatTaxEvaluationPeriodRange = ( periodStart: dayjs.ConfigType, period: string ) => { const { start, end } = getTaxEvaluationPeriodBounds(periodStart, period) return `${start.format("DD.MM.YYYY")} - ${end.format("DD.MM.YYYY")}` } export const getCreatedDocumentTaxBreakdown = (doc: any) => { const breakdown = ZERO_BREAKDOWN() if (!doc || isTaxFreeDocument(doc.taxType)) { return breakdown } ;(doc.rows || []).forEach((row: any) => { if (!row || ["pagebreak", "title", "text"].includes(row.mode)) return const quantity = Number(row.quantity || 0) const price = Number(row.price || 0) const discountPercent = Number(row.discountPercent || 0) const taxPercent = Number(row.taxPercent || 0) const net = Number((quantity * price * (1 - discountPercent / 100)).toFixed(2)) if (!Number.isFinite(net) || net === 0) return if (taxPercent === 19) { breakdown.net19 += net breakdown.tax19 += Number((net * 0.19).toFixed(2)) } else if (taxPercent === 7) { breakdown.net7 += net breakdown.tax7 += Number((net * 0.07).toFixed(2)) } else { breakdown.net0 += net } }) return { net19: Number(breakdown.net19.toFixed(2)), tax19: Number(breakdown.tax19.toFixed(2)), net7: Number(breakdown.net7.toFixed(2)), tax7: Number(breakdown.tax7.toFixed(2)), net0: Number(breakdown.net0.toFixed(2)), } } export const getIncomingInvoiceTaxBreakdown = (invoice: any) => { const breakdown = ZERO_BREAKDOWN() ;(invoice?.accounts || []).forEach((account: any) => { const taxType = String(account?.taxType || "") const amountNet = Number(account?.amountNet || 0) const amountTax = Number(account?.amountTax || 0) if (taxType === "19") { breakdown.net19 += amountNet breakdown.tax19 += amountTax } else if (taxType === "7") { breakdown.net7 += amountNet breakdown.tax7 += amountTax } else { breakdown.net0 += amountNet } }) return { net19: Number(breakdown.net19.toFixed(2)), tax19: Number(breakdown.tax19.toFixed(2)), net7: Number(breakdown.net7.toFixed(2)), tax7: Number(breakdown.tax7.toFixed(2)), net0: Number(breakdown.net0.toFixed(2)), } }