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,14 +57,16 @@
</UBadge> </UBadge>
</template> </template>
<template #content="{item}"> <template #content="{item}">
<div style="height: 80vh; overflow-y: scroll"> <div class="flex h-[80vh] flex-col">
<UTable <div class="min-h-0 flex-1 overflow-y-auto">
:columns="normalizeTableColumns(getColumnsForTab(item.key))" <UTable
:data="getRowsForTab(item.key)" :columns="normalizeTableColumns(getColumnsForTab(item.key))"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }" :data="getVisibleRowsForTab(item.key)"
class="w-full" :ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
:on-select="selectItem" class="w-full"
> :watch-options="{ deep: false }"
:on-select="selectItem"
>
<template #type-cell="{row}"> <template #type-cell="{row}">
<span v-if="row.original.type === 'cancellationInvoices'" class="text-cyan-500">{{ <span v-if="row.original.type === 'cancellationInvoices'" class="text-cyan-500">{{
dataStore.documentTypesForCreation[row.original.type].labelSingle dataStore.documentTypesForCreation[row.original.type].labelSingle
@@ -118,25 +120,37 @@
<template #paid-cell="{row}"> <template #paid-cell="{row}">
<div <div
v-if="(row.original.type === 'invoices' ||row.original.type === 'advanceInvoices') && row.original.state === 'Gebucht' && !hasCancellationInvoice(row.original)"> 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> <span v-else class="text-rose-600">Offen</span>
</div> </div>
</template> </template>
<template #amount-cell="{row}"> <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>
<template #amountOpen-cell="{row}"> <template #amountOpen-cell="{row}">
<span <span
v-if="!['cancellationInvoices','confirmationOrders', ...quoteLikeDocumentTypes, ...deliveryNoteLikeDocumentTypes].includes(row.original.type) && row.original.state !== 'Entwurf' && !hasCancellationInvoice(row.original) && !useSum().getIsPaid(row.original,items) "> v-if="!['cancellationInvoices','confirmationOrders', ...quoteLikeDocumentTypes, ...deliveryNoteLikeDocumentTypes].includes(row.original.type) && row.original.state !== 'Entwurf' && !hasCancellationInvoice(row.original) && !isPaid(row.original) ">
{{ displayCurrency(useSum().getCreatedDocumentOpenAmount(row.original, items)) }} {{ displayCurrency(getDocumentOpenAmount(row.original)) }}
</span> </span>
</template> </template>
<template #empty> <template #empty>
<TableEmptyState label="Keine Belege anzuzeigen" /> <TableEmptyState label="Keine Belege anzuzeigen" />
</template> </template>
</UTable> </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> </div>
</template> </template>
</UTabs> </UTabs>
@@ -144,7 +158,7 @@
<script setup> <script setup>
import dayjs from "dayjs"; import dayjs from "dayjs";
import { ref, computed, watch } from 'vue'; import { ref, computed, reactive, watch } from 'vue';
const dataStore = useDataStore() const dataStore = useDataStore()
const tempStore = useTempStore() const tempStore = useTempStore()
@@ -158,6 +172,17 @@ const dataType = dataStore.dataTypes[type]
const items = ref([]) const items = ref([])
const selectedItem = ref(0) const selectedItem = ref(0)
const activeTabIndex = 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 // Debounce-Logik für die Suche
const searchString = ref(tempStore.searchStrings['createddocuments'] || '') const searchString = ref(tempStore.searchStrings['createddocuments'] || '')
@@ -281,22 +306,53 @@ const clearSearchString = () => {
debouncedSearchString.value = '' debouncedSearchString.value = ''
} }
const getCancellationInvoice = (row) => { const cancellationInvoicesByDocument = computed(() => {
return items.value.find((item) => { const result = new Map()
const linkedDocumentId = item.createddocument?.id || item.createddocument
return item.type === 'cancellationInvoices'
&& item.state !== 'Entwurf'
&& !item.archived
&& linkedDocumentId === row.id
})
}
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 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 = { const openUnpaidInvoicesFilter = {
name: 'Nur offene Belege', name: 'Nur offene Belege',
filterFunction: (row) => { 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 return results
}) })
const getRowsForTab = (tabKey) => { const rowsByTab = computed(() => {
return filteredRows.value.filter(row => { const result = Object.fromEntries(templateTypes.map(type => [type.key, []]))
if (tabKey === 'drafts') return row.state === 'Entwurf'
if (row.state === 'Entwurf') return false filteredRows.value.forEach(row => {
if (tabKey === 'invoices') return ['invoices', 'advanceInvoices', 'cancellationInvoices'].includes(row.type) if (row.state === 'Entwurf') {
return row.type === tabKey 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) => { watch([debouncedSearchString, selectedFilters, selectedTypes], () => {
return useSum().getIsPaid(item, items.value) Object.keys(tabPages).forEach((key) => {
} tabPages[key] = 1
})
}, { deep: true })
</script> </script>