Fix BWA Calc
This commit is contained in:
@@ -7,7 +7,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
getIncomingInvoiceDepreciationRows,
|
getIncomingInvoiceDepreciationRows,
|
||||||
getIncomingInvoiceImmediateExpenseNet,
|
getIncomingInvoiceImmediateExpenseNet,
|
||||||
getStatementAllocationDepreciationRow,
|
|
||||||
getStatementAllocationImmediateExpenseAmount
|
getStatementAllocationImmediateExpenseAmount
|
||||||
} from "~/composables/useDepreciation"
|
} from "~/composables/useDepreciation"
|
||||||
|
|
||||||
@@ -79,9 +78,9 @@ const loadSummary = async () => {
|
|||||||
|
|
||||||
const statementDate = allocation?.bankstatement?.date || allocation?.bankstatement?.valueDate || allocation?.date || allocation?.created_at
|
const statementDate = allocation?.bankstatement?.date || allocation?.bankstatement?.valueDate || allocation?.date || allocation?.created_at
|
||||||
const date = dayjs(statementDate)
|
const date = dayjs(statementDate)
|
||||||
const amount = Number(allocation?.amount || 0)
|
const amount = getStatementAllocationImmediateExpenseAmount(allocation)
|
||||||
|
|
||||||
return amount < 0 && date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
|
return amount > 0 && date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
|
||||||
})
|
})
|
||||||
|
|
||||||
const income = outputDocs.reduce((sum: number, doc: any) => {
|
const income = outputDocs.reduce((sum: number, doc: any) => {
|
||||||
@@ -103,12 +102,11 @@ const loadSummary = async () => {
|
|||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const directAccountExpenses = directExpenses.reduce((sum: number, allocation: any) => {
|
const directAccountExpenses = directExpenses.reduce((sum: number, allocation: any) => {
|
||||||
return sum + getStatementAllocationImmediateExpenseAmount(allocation)
|
return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const depreciationRows = [
|
const depreciationRows = [
|
||||||
...inputDocs.flatMap((invoice: any) => getIncomingInvoiceDepreciationRows(invoice, bounds.start, bounds.end)),
|
...inputDocs.flatMap((invoice: any) => getIncomingInvoiceDepreciationRows(invoice, bounds.start, bounds.end))
|
||||||
...(allocations || []).map((allocation: any) => getStatementAllocationDepreciationRow(allocation, bounds.start, bounds.end)).filter(Boolean)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const depreciations = depreciationRows.reduce((sum: number, row: any) => sum + Number(row.amount || 0), 0)
|
const depreciations = depreciationRows.reduce((sum: number, row: any) => sum + Number(row.amount || 0), 0)
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
import customParseFormat from "dayjs/plugin/customParseFormat";
|
import customParseFormat from "dayjs/plugin/customParseFormat";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { Line } from "vue-chartjs";
|
import { Line } from "vue-chartjs";
|
||||||
|
import {
|
||||||
|
getIncomingInvoiceImmediateExpenseGross,
|
||||||
|
getIncomingInvoiceImmediateExpenseNet
|
||||||
|
} from "~/composables/useDepreciation";
|
||||||
|
|
||||||
dayjs.extend(customParseFormat)
|
dayjs.extend(customParseFormat)
|
||||||
|
|
||||||
@@ -84,7 +88,7 @@ const loadData = async () => {
|
|||||||
])
|
])
|
||||||
|
|
||||||
incomeDocuments.value = (docs || []).filter((item) => item.state === "Gebucht" && ["invoices", "advanceInvoices", "cancellationInvoices"].includes(item.type))
|
incomeDocuments.value = (docs || []).filter((item) => item.state === "Gebucht" && ["invoices", "advanceInvoices", "cancellationInvoices"].includes(item.type))
|
||||||
expenseInvoices.value = (incoming || []).filter((item) => item.date)
|
expenseInvoices.value = (incoming || []).filter((item) => item.state === "Gebucht" && item.date)
|
||||||
}
|
}
|
||||||
|
|
||||||
const yearsInData = computed(() => {
|
const yearsInData = computed(() => {
|
||||||
@@ -128,18 +132,9 @@ const computeDocumentAmount = (doc) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const computeIncomingInvoiceAmount = (invoice) => {
|
const computeIncomingInvoiceAmount = (invoice) => {
|
||||||
let amount = 0
|
return amountMode.value === "gross"
|
||||||
|
? getIncomingInvoiceImmediateExpenseGross(invoice)
|
||||||
;(invoice.accounts || []).forEach((account) => {
|
: getIncomingInvoiceImmediateExpenseNet(invoice)
|
||||||
const net = Number(account.amountNet || 0)
|
|
||||||
const tax = Number(account.amountTax || 0)
|
|
||||||
const grossValue = Number(account.amountGross)
|
|
||||||
const gross = Number.isFinite(grossValue) ? grossValue : (net + tax)
|
|
||||||
|
|
||||||
amount += amountMode.value === "gross" ? gross : net
|
|
||||||
})
|
|
||||||
|
|
||||||
return Number(amount.toFixed(2))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const buckets = computed(() => {
|
const buckets = computed(() => {
|
||||||
|
|||||||
@@ -291,6 +291,9 @@ export const getIncomingInvoiceDepreciationRows = (invoice: any, rangeStart: any
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getStatementAllocationImmediateExpenseAmount = (allocation: any) => {
|
export const getStatementAllocationImmediateExpenseAmount = (allocation: any) => {
|
||||||
|
const hasLinkedDocument = allocation?.incominginvoice || allocation?.createddocument || allocation?.ii_id || allocation?.cd_id
|
||||||
|
if (hasLinkedDocument) return 0
|
||||||
|
|
||||||
const mode = normalizeExpenseBookingMode(allocation?.bookingMode)
|
const mode = normalizeExpenseBookingMode(allocation?.bookingMode)
|
||||||
const amount = Number(allocation?.amount || 0)
|
const amount = Number(allocation?.amount || 0)
|
||||||
if (mode !== "expense" || amount >= 0) return 0
|
if (mode !== "expense" || amount >= 0) return 0
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
getIncomingInvoiceImmediateExpenseNet,
|
getIncomingInvoiceImmediateExpenseNet,
|
||||||
isDepreciationBookingMode,
|
isDepreciationBookingMode,
|
||||||
normalizeIncomingInvoiceAccount,
|
normalizeIncomingInvoiceAccount,
|
||||||
getStatementAllocationDepreciationRow,
|
|
||||||
getStatementAllocationImmediateExpenseAmount
|
getStatementAllocationImmediateExpenseAmount
|
||||||
} from "~/composables/useDepreciation"
|
} from "~/composables/useDepreciation"
|
||||||
|
|
||||||
@@ -156,7 +155,13 @@ const filteredStatementAllocations = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const filteredAccountStatementAllocations = computed(() => {
|
const filteredAccountStatementAllocations = computed(() => {
|
||||||
return filteredStatementAllocations.value.filter((allocation) => allocation.account !== null && allocation.account !== undefined)
|
return filteredStatementAllocations.value.filter((allocation) => {
|
||||||
|
if (allocation.account === null || allocation.account === undefined) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return getStatementAllocationImmediateExpenseAmount(allocation) > 0
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedPeriodBounds = computed(() => {
|
const selectedPeriodBounds = computed(() => {
|
||||||
@@ -181,7 +186,7 @@ const expenseNetTotal = computed(() => {
|
|||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => {
|
const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => {
|
||||||
return sum + getStatementAllocationImmediateExpenseAmount(allocation)
|
return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const depreciations = depreciationTotal.value
|
const depreciations = depreciationTotal.value
|
||||||
@@ -193,7 +198,7 @@ const expenseGrossTotal = computed(() => {
|
|||||||
const invoiceExpenses = filteredIncomingInvoices.value.reduce((sum, invoice) => sum + getIncomingInvoiceImmediateExpenseGross(invoice), 0)
|
const invoiceExpenses = filteredIncomingInvoices.value.reduce((sum, invoice) => sum + getIncomingInvoiceImmediateExpenseGross(invoice), 0)
|
||||||
|
|
||||||
const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => {
|
const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => {
|
||||||
return sum + getStatementAllocationImmediateExpenseAmount(allocation)
|
return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const depreciations = depreciationTotal.value
|
const depreciations = depreciationTotal.value
|
||||||
@@ -249,13 +254,9 @@ const expenseDocumentCount = computed(() => {
|
|||||||
const depreciationRows = computed(() => {
|
const depreciationRows = computed(() => {
|
||||||
const invoiceRows = filteredIncomingInvoices.value.flatMap((invoice) => getIncomingInvoiceDepreciationRows(invoice, selectedPeriodBounds.value.start, selectedPeriodBounds.value.end))
|
const invoiceRows = filteredIncomingInvoices.value.flatMap((invoice) => getIncomingInvoiceDepreciationRows(invoice, selectedPeriodBounds.value.start, selectedPeriodBounds.value.end))
|
||||||
|
|
||||||
const allocationRows = filteredStatementAllocations.value
|
|
||||||
.map((allocation) => getStatementAllocationDepreciationRow(allocation, selectedPeriodBounds.value.start, selectedPeriodBounds.value.end))
|
|
||||||
.filter(Boolean)
|
|
||||||
|
|
||||||
const grouped = new Map<string, any>()
|
const grouped = new Map<string, any>()
|
||||||
|
|
||||||
;[...invoiceRows, ...allocationRows].forEach((row: any) => {
|
;invoiceRows.forEach((row: any) => {
|
||||||
const key = row.group || `${row.mode}:${row.label}`
|
const key = row.group || `${row.mode}:${row.label}`
|
||||||
const current = grouped.get(key) || {
|
const current = grouped.get(key) || {
|
||||||
id: key,
|
id: key,
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ const loading = ref(true)
|
|||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
const incomingInvoices = ref<any[]>([])
|
const incomingInvoices = ref<any[]>([])
|
||||||
const statementAllocations = ref<any[]>([])
|
const statementAllocations = ref<any[]>([])
|
||||||
const asOfDate = ref(dayjs().format("YYYY-MM-DD"))
|
const periodStart = ref(dayjs().startOf("month").format("YYYY-MM-DD"))
|
||||||
|
const periodEnd = ref(dayjs().endOf("month").format("YYYY-MM-DD"))
|
||||||
const selectedAsset = ref<any | null>(null)
|
const selectedAsset = ref<any | null>(null)
|
||||||
const editState = ref<any | null>(null)
|
const editState = ref<any | null>(null)
|
||||||
const editOpen = computed({
|
const editOpen = computed({
|
||||||
@@ -32,6 +33,22 @@ const formatCurrency = (value: number) => new Intl.NumberFormat("de-DE", {
|
|||||||
}).format(Number(value || 0))
|
}).format(Number(value || 0))
|
||||||
|
|
||||||
const isRelevantInputInvoice = (invoice: any) => invoice?.state === "Gebucht" && !!invoice?.date
|
const isRelevantInputInvoice = (invoice: any) => invoice?.state === "Gebucht" && !!invoice?.date
|
||||||
|
const normalizedPeriod = computed(() => {
|
||||||
|
const start = dayjs(periodStart.value)
|
||||||
|
const end = dayjs(periodEnd.value)
|
||||||
|
|
||||||
|
if (start.isValid() && end.isValid() && start.isAfter(end, "day")) {
|
||||||
|
return {
|
||||||
|
start: end.startOf("day"),
|
||||||
|
end: start.endOf("day"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start.isValid() ? start.startOf("day") : dayjs().startOf("month"),
|
||||||
|
end: end.isValid() ? end.endOf("day") : dayjs().endOf("month"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -62,9 +79,9 @@ const depreciationAssets = computed(() => {
|
|||||||
depreciationStartDate: normalized.depreciationStartDate || invoice.date,
|
depreciationStartDate: normalized.depreciationStartDate || invoice.date,
|
||||||
depreciationMethod: normalized.depreciationMethod,
|
depreciationMethod: normalized.depreciationMethod,
|
||||||
residualValue: normalized.residualValue,
|
residualValue: normalized.residualValue,
|
||||||
}, asOfDate.value)
|
}, normalizedPeriod.value.end)
|
||||||
|
|
||||||
const currentPeriodRow = getIncomingInvoiceDepreciationRows(invoice, dayjs(asOfDate.value).startOf("month"), dayjs(asOfDate.value).endOf("month"))
|
const currentPeriodRow = getIncomingInvoiceDepreciationRows(invoice, normalizedPeriod.value.start, normalizedPeriod.value.end)
|
||||||
.find((row: any) => row.index === index)
|
.find((row: any) => row.index === index)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -102,9 +119,9 @@ const depreciationAssets = computed(() => {
|
|||||||
depreciationStartDate: allocation.depreciationStartDate || allocation.created_at,
|
depreciationStartDate: allocation.depreciationStartDate || allocation.created_at,
|
||||||
depreciationMethod: allocation.depreciationMethod,
|
depreciationMethod: allocation.depreciationMethod,
|
||||||
residualValue: allocation.residualValue,
|
residualValue: allocation.residualValue,
|
||||||
}, asOfDate.value)
|
}, normalizedPeriod.value.end)
|
||||||
|
|
||||||
const currentPeriodRow = getStatementAllocationDepreciationRow(allocation, dayjs(asOfDate.value).startOf("month"), dayjs(asOfDate.value).endOf("month"))
|
const currentPeriodRow = getStatementAllocationDepreciationRow(allocation, normalizedPeriod.value.start, normalizedPeriod.value.end)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: `allocation-${allocation.id}`,
|
key: `allocation-${allocation.id}`,
|
||||||
@@ -260,7 +277,8 @@ onMounted(loadData)
|
|||||||
<UDashboardNavbar title="Abschreibungen">
|
<UDashboardNavbar title="Abschreibungen">
|
||||||
<template #right>
|
<template #right>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<UInput v-model="asOfDate" type="date" class="w-44" />
|
<UInput v-model="periodStart" type="date" class="w-44" />
|
||||||
|
<UInput v-model="periodEnd" type="date" class="w-44" />
|
||||||
<UButton icon="i-heroicons-arrow-path" variant="outline" :loading="loading" @click="loadData">
|
<UButton icon="i-heroicons-arrow-path" variant="outline" :loading="loading" @click="loadData">
|
||||||
Aktualisieren
|
Aktualisieren
|
||||||
</UButton>
|
</UButton>
|
||||||
@@ -278,7 +296,7 @@ onMounted(loadData)
|
|||||||
<UCard>
|
<UCard>
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400">Bereits abgeschrieben</div>
|
<div class="text-sm text-gray-500 dark:text-gray-400">Bereits abgeschrieben</div>
|
||||||
<div class="mt-2 text-2xl font-semibold text-primary-600 dark:text-primary-400">{{ formatCurrency(totals.depreciated) }}</div>
|
<div class="mt-2 text-2xl font-semibold text-primary-600 dark:text-primary-400">{{ formatCurrency(totals.depreciated) }}</div>
|
||||||
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">Stand {{ dayjs(asOfDate).format("DD.MM.YYYY") }}</div>
|
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">Stand {{ normalizedPeriod.end.format("DD.MM.YYYY") }}</div>
|
||||||
</UCard>
|
</UCard>
|
||||||
<UCard>
|
<UCard>
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400">Restbuchwert</div>
|
<div class="text-sm text-gray-500 dark:text-gray-400">Restbuchwert</div>
|
||||||
@@ -286,9 +304,9 @@ onMounted(loadData)
|
|||||||
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">Nach Restwertlogik</div>
|
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">Nach Restwertlogik</div>
|
||||||
</UCard>
|
</UCard>
|
||||||
<UCard>
|
<UCard>
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400">Aktuelle Abschreibung</div>
|
<div class="text-sm text-gray-500 dark:text-gray-400">Abschreibung im Zeitraum</div>
|
||||||
<div class="mt-2 text-2xl font-semibold text-error">{{ formatCurrency(totals.currentPeriodAmount) }}</div>
|
<div class="mt-2 text-2xl font-semibold text-error">{{ formatCurrency(totals.currentPeriodAmount) }}</div>
|
||||||
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">{{ totals.bundleCount }} Sammelposten</div>
|
<div class="mt-2 text-sm text-gray-500 dark:text-gray-400">{{ normalizedPeriod.start.format("DD.MM.YYYY") }} - {{ normalizedPeriod.end.format("DD.MM.YYYY") }}</div>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -351,7 +369,7 @@ onMounted(loadData)
|
|||||||
<div class="mt-1 font-semibold text-primary-600 dark:text-primary-400">{{ formatCurrency(asset.depreciated) }}</div>
|
<div class="mt-1 font-semibold text-primary-600 dark:text-primary-400">{{ formatCurrency(asset.depreciated) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-xs text-gray-500 dark:text-gray-400">Aktueller Zeitraum</div>
|
<div class="text-xs text-gray-500 dark:text-gray-400">Im Zeitraum</div>
|
||||||
<div class="mt-1 font-semibold text-error">{{ formatCurrency(asset.currentPeriodAmount) }}</div>
|
<div class="mt-1 font-semibold text-error">{{ formatCurrency(asset.currentPeriodAmount) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user