|
|
|
|
@@ -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>
|
|
|
|
|
|