222 lines
5.5 KiB
Vue
222 lines
5.5 KiB
Vue
<script setup>
|
|
|
|
import dayjs from "dayjs";
|
|
|
|
defineShortcuts({
|
|
'/': () => {
|
|
//console.log(searchinput)
|
|
//searchinput.value.focus()
|
|
document.getElementById("searchinput").focus()
|
|
}
|
|
})
|
|
|
|
const tempStore = useTempStore()
|
|
const router = useRouter()
|
|
|
|
const items = ref([])
|
|
const dataLoaded = ref(false)
|
|
|
|
const statementallocations = ref([])
|
|
const incominginvoices = ref([])
|
|
|
|
const setupPage = async () => {
|
|
items.value = await useEntities("accounts").selectSpecial()
|
|
|
|
statementallocations.value = (await useEntities("statementallocations").select("*, bs_id(*)"))
|
|
incominginvoices.value = (await useEntities("incominginvoices").select("*, vendor(*)"))
|
|
|
|
items.value = await Promise.all(items.value.map(async (i) => {
|
|
let renderedAllocationsTemp = await renderedAllocations(i.id)
|
|
let saldo = getSaldo(renderedAllocationsTemp)
|
|
|
|
return {
|
|
...i,
|
|
saldo: saldo,
|
|
allocations: renderedAllocationsTemp.length,
|
|
}
|
|
|
|
}))
|
|
dataLoaded.value = true
|
|
|
|
|
|
}
|
|
|
|
const renderedAllocations = async (account) => {
|
|
|
|
let statementallocationslocal = statementallocations.value.filter(i => i.account === account)
|
|
let incominginvoiceslocal = incominginvoices.value.filter(i => i.accounts.find(x => x.account === account))
|
|
|
|
let tempstatementallocations = statementallocationslocal.map(i => {
|
|
return {
|
|
...i,
|
|
type: "statementallocation",
|
|
date: i.bankstatement.date,
|
|
partner: i.bankstatement ? (i.bankstatement.debName ? i.bankstatement.debName : (i.bankstatement.credName ? i.bankstatement.credName : '')) : ''
|
|
}
|
|
})
|
|
|
|
|
|
let incominginvoicesallocations = []
|
|
|
|
incominginvoiceslocal.forEach(i => {
|
|
|
|
incominginvoicesallocations.push(...i.accounts.filter(x => x.account === account).map(x => {
|
|
return {
|
|
...x,
|
|
incominginvoiceid: i.id,
|
|
type: "incominginvoice",
|
|
amount: x.amountGross ? x.amountGross : x.amountNet,
|
|
date: i.date,
|
|
partner: i.vendor.name,
|
|
description: i.description,
|
|
color: i.expense ? "red" : "green",
|
|
expense: i.expense
|
|
}
|
|
}))
|
|
})
|
|
|
|
return [...tempstatementallocations, ... incominginvoicesallocations]
|
|
}
|
|
|
|
const getSaldo = (allocations) => {
|
|
let value = 0
|
|
|
|
allocations.forEach(i => {
|
|
if(i.incominginvoiceid) {
|
|
if(i.expense) {
|
|
value = value - i.amount
|
|
} else {
|
|
value += i.amount
|
|
}
|
|
} else {
|
|
value += i.amount
|
|
}
|
|
})
|
|
|
|
return value
|
|
}
|
|
|
|
const templateColumns = [
|
|
{
|
|
key: "number",
|
|
label: "Nummer"
|
|
},{
|
|
key: "label",
|
|
label: "Name"
|
|
},{
|
|
key: "allocations",
|
|
label: "Buchungen"
|
|
},{
|
|
key: "saldo",
|
|
label: "Saldo"
|
|
}, {
|
|
key: "description",
|
|
label: "Beschreibung"
|
|
},
|
|
]
|
|
const selectedColumns = ref(templateColumns)
|
|
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
|
|
|
|
|
const searchString = ref(tempStore.searchStrings["bankstatements"] ||'')
|
|
|
|
const clearSearchString = () => {
|
|
tempStore.clearSearchString("bankstatements")
|
|
searchString.value = ''
|
|
}
|
|
|
|
const selectedFilters = ref(['Nur offene anzeigen'])
|
|
|
|
const filteredRows = computed(() => {
|
|
let temp = items.value
|
|
|
|
|
|
return useSearch(searchString.value, temp)
|
|
})
|
|
|
|
setupPage()
|
|
</script>
|
|
|
|
<template>
|
|
<UDashboardNavbar title="Buchungskonten" :badge="filteredRows.length">
|
|
<template #right>
|
|
<UInput
|
|
id="searchinput"
|
|
name="searchinput"
|
|
v-model="searchString"
|
|
icon="i-heroicons-funnel"
|
|
autocomplete="off"
|
|
placeholder="Suche..."
|
|
class="hidden lg:block"
|
|
@keydown.esc="$event.target.blur()"
|
|
@change="tempStore.modifySearchString('bankstatements',searchString)"
|
|
>
|
|
<template #trailing>
|
|
<UKbd value="/" />
|
|
</template>
|
|
</UInput>
|
|
<UButton
|
|
icon="i-heroicons-x-mark"
|
|
variant="outline"
|
|
color="rose"
|
|
@click="clearSearchString()"
|
|
v-if="searchString.length > 0"
|
|
/>
|
|
</template>
|
|
</UDashboardNavbar>
|
|
<UDashboardToolbar>
|
|
<template #right>
|
|
<USelectMenu
|
|
v-model="selectedColumns"
|
|
icon="i-heroicons-adjustments-horizontal-solid"
|
|
:options="templateColumns"
|
|
multiple
|
|
class="hidden lg:block"
|
|
by="key"
|
|
:ui-menu="{ width: 'min-w-max' }"
|
|
>
|
|
<template #label>
|
|
Spalten
|
|
</template>
|
|
</USelectMenu>
|
|
<USelectMenu
|
|
icon="i-heroicons-adjustments-horizontal-solid"
|
|
multiple
|
|
v-model="selectedFilters"
|
|
:options="['Nur offene anzeigen']"
|
|
:color="selectedFilters.length > 0 ? 'primary' : 'white'"
|
|
:ui-menu="{ width: 'min-w-max' }"
|
|
>
|
|
<template #label>
|
|
Filter
|
|
</template>
|
|
</USelectMenu>
|
|
</template>
|
|
</UDashboardToolbar>
|
|
<UTable
|
|
:rows="filteredRows"
|
|
:columns="columns"
|
|
class="w-full"
|
|
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
|
@select="(i) => router.push(`/accounts/show/${i.id}`)"
|
|
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Buchungen anzuzeigen' }"
|
|
>
|
|
<template #allocations-data="{row}">
|
|
<span v-if="dataLoaded">{{row.allocations ? row.allocations : null}}</span>
|
|
<USkeleton v-else class="h-4 w-[250px]" />
|
|
|
|
</template>
|
|
<template #saldo-data="{row}">
|
|
<span v-if="dataLoaded">{{row.allocations ? useCurrency(row.saldo) : null}}</span>
|
|
<USkeleton v-else class="h-4 w-[250px]" />
|
|
</template>
|
|
</UTable>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
</style> |