Ausgangsbeleg-Tabs schneller rendern
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 43s
Build and Push Docker Images / build-frontend (push) Successful in 1m26s
Build and Push Docker Images / build-central-services-admin (push) Successful in 31s
Build and Push Docker Images / build-website (push) Successful in 23s
Build and Push Docker Images / build-central-services-api (push) Successful in 22s
Build and Push Docker Images / build-docs (push) Successful in 22s

This commit is contained in:
2026-08-17 17:59:51 +02:00
parent 391375b3a7
commit d0755020ad

View File

@@ -57,12 +57,14 @@
</UBadge>
</template>
<template #content="{item}">
<div style="height: 80vh; overflow-y: scroll">
<div class="flex h-[80vh] flex-col">
<div class="min-h-0 flex-1 overflow-y-auto">
<UTable
:columns="normalizeTableColumns(getColumnsForTab(item.key))"
:data="getRowsForTab(item.key)"
:data="getVisibleRowsForTab(item.key)"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
class="w-full"
:watch-options="{ deep: false }"
:on-select="selectItem"
>
<template #type-cell="{row}">
@@ -118,19 +120,19 @@
<template #paid-cell="{row}">
<div
v-if="(row.original.type === 'invoices' ||row.original.type === 'advanceInvoices') && row.original.state === 'Gebucht' && !hasCancellationInvoice(row.original)">
<span v-if="useSum().getIsPaid(row.original,items)" class="text-primary-500">Bezahlt</span>
<span v-if="isPaid(row.original)" class="text-primary-500">Bezahlt</span>
<span v-else class="text-rose-600">Offen</span>
</div>
</template>
<template #amount-cell="{row}">
<span v-if="!deliveryNoteLikeDocumentTypes.includes(row.original.type)">{{ displayCurrency(useSum().getCreatedDocumentSum(row.original, items)) }}</span>
<span v-if="!deliveryNoteLikeDocumentTypes.includes(row.original.type)">{{ displayCurrency(getDocumentAmount(row.original)) }}</span>
</template>
<template #amountOpen-cell="{row}">
<span
v-if="!['cancellationInvoices','confirmationOrders', ...quoteLikeDocumentTypes, ...deliveryNoteLikeDocumentTypes].includes(row.original.type) && row.original.state !== 'Entwurf' && !hasCancellationInvoice(row.original) && !useSum().getIsPaid(row.original,items) ">
{{ displayCurrency(useSum().getCreatedDocumentOpenAmount(row.original, items)) }}
v-if="!['cancellationInvoices','confirmationOrders', ...quoteLikeDocumentTypes, ...deliveryNoteLikeDocumentTypes].includes(row.original.type) && row.original.state !== 'Entwurf' && !hasCancellationInvoice(row.original) && !isPaid(row.original) ">
{{ displayCurrency(getDocumentOpenAmount(row.original)) }}
</span>
</template>
<template #empty>
@@ -138,13 +140,25 @@
</template>
</UTable>
</div>
<div
v-if="getRowsForTab(item.key).length > rowsPerPage"
class="flex items-center justify-center border-t border-gray-200 bg-white p-3 dark:border-gray-800 dark:bg-gray-900"
>
<UPagination
v-model:page="tabPages[item.key]"
:items-per-page="rowsPerPage"
:total="getRowsForTab(item.key).length"
:show-edges="true"
/>
</div>
</div>
</template>
</UTabs>
</template>
<script setup>
import dayjs from "dayjs";
import { ref, computed, watch } from 'vue';
import { ref, computed, reactive, watch } from 'vue';
const dataStore = useDataStore()
const tempStore = useTempStore()
@@ -158,6 +172,17 @@ const dataType = dataStore.dataTypes[type]
const items = ref([])
const selectedItem = ref(0)
const activeTabIndex = ref(0)
const rowsPerPage = 100
const tabPages = reactive({
drafts: 1,
invoices: 1,
quotes: 1,
costEstimates: 1,
deliveryNotes: 1,
packingSlips: 1,
confirmationOrders: 1
})
const sum = useSum()
// Debounce-Logik für die Suche
const searchString = ref(tempStore.searchStrings['createddocuments'] || '')
@@ -281,22 +306,53 @@ const clearSearchString = () => {
debouncedSearchString.value = ''
}
const getCancellationInvoice = (row) => {
return items.value.find((item) => {
const linkedDocumentId = item.createddocument?.id || item.createddocument
return item.type === 'cancellationInvoices'
&& item.state !== 'Entwurf'
&& !item.archived
&& linkedDocumentId === row.id
})
}
const cancellationInvoicesByDocument = computed(() => {
const result = new Map()
items.value.forEach((item) => {
const linkedDocumentId = item.createddocument?.id || item.createddocument
if (item.type === 'cancellationInvoices' && item.state !== 'Entwurf' && !item.archived && linkedDocumentId) {
result.set(linkedDocumentId, item)
}
})
return result
})
const documentAmounts = computed(() => {
const result = new Map()
items.value.forEach((item) => {
const amount = sum.getCreatedDocumentSum(item, items.value)
const amountPaid = (item.statementallocations || []).reduce(
(total, allocation) => total + Number(allocation.amount || 0),
0
)
result.set(item.id, {
amount,
openAmount: Number((amount - amountPaid).toFixed(2))
})
})
return result
})
const getCancellationInvoice = (row) => cancellationInvoicesByDocument.value.get(row.id)
const hasCancellationInvoice = (row) => Boolean(getCancellationInvoice(row))
const getDocumentAmount = (row) => documentAmounts.value.get(row.id)?.amount || 0
const getDocumentOpenAmount = (row) => documentAmounts.value.get(row.id)?.openAmount || 0
const isPaid = (row) => getDocumentOpenAmount(row) === 0
const openUnpaidInvoicesFilter = {
name: 'Nur offene Belege',
filterFunction: (row) => {
return row.state === 'Entwurf' || useSum().isOpenCreatedDocument(row, items.value)
return row.state === 'Entwurf' || (
['invoices', 'advanceInvoices'].includes(row.type)
&& row.state === 'Gebucht'
&& !hasCancellationInvoice(row)
&& !isPaid(row)
)
}
}
@@ -339,16 +395,33 @@ const filteredRows = computed(() => {
return results
})
const getRowsForTab = (tabKey) => {
return filteredRows.value.filter(row => {
if (tabKey === 'drafts') return row.state === 'Entwurf'
if (row.state === 'Entwurf') return false
if (tabKey === 'invoices') return ['invoices', 'advanceInvoices', 'cancellationInvoices'].includes(row.type)
return row.type === tabKey
const rowsByTab = computed(() => {
const result = Object.fromEntries(templateTypes.map(type => [type.key, []]))
filteredRows.value.forEach(row => {
if (row.state === 'Entwurf') {
result.drafts.push(row)
} else if (['invoices', 'advanceInvoices', 'cancellationInvoices'].includes(row.type)) {
result.invoices.push(row)
} else if (result[row.type]) {
result[row.type].push(row)
}
})
return result
})
const getRowsForTab = (tabKey) => rowsByTab.value[tabKey] || []
const getVisibleRowsForTab = (tabKey) => {
const rows = getRowsForTab(tabKey)
const start = (tabPages[tabKey] - 1) * rowsPerPage
return rows.slice(start, start + rowsPerPage)
}
const isPaid = (item) => {
return useSum().getIsPaid(item, items.value)
}
watch([debouncedSearchString, selectedFilters, selectedTypes], () => {
Object.keys(tabPages).forEach((key) => {
tabPages[key] = 1
})
}, { deep: true })
</script>