Cahnges in Invoice allocation in statements

This commit is contained in:
2024-08-09 11:52:11 +02:00
parent baa06b60fb
commit 4ded159c49
3 changed files with 175 additions and 55 deletions

View File

@@ -1,6 +1,7 @@
<script setup> <script setup>
import dayjs from "dayjs"; import dayjs from "dayjs";
import {filter} from "vuedraggable/dist/vuedraggable.common.js";
definePageMeta({ definePageMeta({
middleware: "auth" middleware: "auth"
@@ -22,6 +23,8 @@ const itemInfo = ref({statementallocations:[]})
const oldItemInfo = ref({}) const oldItemInfo = ref({})
const openDocuments = ref([]) const openDocuments = ref([])
const allocatedDocuments = ref([])
const openIncomingInvoices = ref([])
const setup = async () => { const setup = async () => {
if(route.params.id) { if(route.params.id) {
@@ -29,7 +32,14 @@ const setup = async () => {
} }
if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value)) if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
openDocuments.value = (await supabase.from("createddocuments").select("*, statementallocations(*)")).data.filter(i => i.statementallocations.length === 0 || i.statementallocations.find(x => x.bs_id === itemInfo.value.id)) const documents = (await useSupabaseSelect("createddocuments","*, statementallocations(*), customer(id,name)")).filter(i => i.type === "invoices" ||i.type === "advanceInvoices")
openDocuments.value = documents.filter(i => i.statementallocations.length === 0 )
allocatedDocuments.value = documents.filter(i => i.statementallocations.find(x => x.bs_id === itemInfo.value.id))
openIncomingInvoices.value = (await useSupabaseSelect("incominginvoices","*, statementallocations(*)")).filter(i => i.statementallocations.length === 0 || i.statementallocations.find(x => x.bs_id === itemInfo.value.id))
console.log(openIncomingInvoices.value)
// return incominginvoices.value.filter(i => bankstatements.value.filter(x => x.assignments.find(y => y.type === 'incomingInvoice' && y.id === i.id)).length === 0)
let allocations = (await supabase.from("createddocuments").select(`*, statementallocations(*)`).eq("id",50)).data let allocations = (await supabase.from("createddocuments").select(`*, statementallocations(*)`).eq("id",50)).data
@@ -80,6 +90,21 @@ const calculateOpenSum = computed(() => {
return startingAmount.toFixed(2) return startingAmount.toFixed(2)
}) })
const calculateAllocatedSum = computed(() => {
let startingAmount = 0
itemInfo.value.statementallocations.forEach(item => {
if(item.cd_id) {
startingAmount = startingAmount + item.amount
} else if(item.ii_id) {
startingAmount = Number(startingAmount) - item.amount
}
})
return startingAmount
})
const saveAllocations = async () => { const saveAllocations = async () => {
let allocationsToBeSaved = itemInfo.value.statementallocations.filter(i => !i.id) let allocationsToBeSaved = itemInfo.value.statementallocations.filter(i => !i.id)
@@ -90,6 +115,32 @@ const saveAllocations = async () => {
} }
const saveAllocation = async (allocation) => {
const {data,error} = await supabase.from("statementallocations").insert({
...allocation,
tenant: dataStore.currentTenant
}).select()
if(data) {
await setup()
}
}
const removeAllocation = async (allocationId) => {
const {data,error} = await supabase.from("statementallocations").delete().eq("id",allocationId)
await setup()
}
const searchString = ref("")
const filteredRows = computed(() => {
return useSearch(searchString.value, openDocuments.value)
})
setup() setup()
@@ -179,9 +230,9 @@ setup()
</span> </span>
<span v-if="itemInfo.amount > 0" class="text-primary-500 font-semibold">{{itemInfo.amount.toFixed(2).replace(".",",")}} {{itemInfo.currency}}</span> <span v-if="itemInfo.amount > 0" class="text-primary-500 font-semibold text-nowrap">{{displayCurrency(itemInfo.amount)}}</span>
<span v-else-if="itemInfo.amount < 0" class="text-rose-600 font-semibold">{{itemInfo.amount.toFixed(2).replace(".",",")}} {{itemInfo.currency}}</span> <span v-else-if="itemInfo.amount < 0" class="text-rose-600 font-semibold text-nowrap">{{displayCurrency(itemInfo.amount)}}</span>
<span v-else>{{(itemInfo.amount || 0).toFixed(2).replace(".",",")}} {{itemInfo.currency}}</span> <span v-else>{{displayCurrency(itemInfo.amount)}}</span>
</div> </div>
</template> </template>
@@ -202,12 +253,13 @@ setup()
{{dayjs(itemInfo.valueDate).format("DD.MM.YYYY")}} {{dayjs(itemInfo.valueDate).format("DD.MM.YYYY")}}
</td> </td>
</tr> </tr>
<tr class="flex-row flex justify-between"> <tr class="flex-row flex justify-between text-right">
<td> <td>
<span class="font-semibold">Partner:</span> <span class="font-semibold">Partner:</span>
</td> </td>
<td> <td>
{{itemInfo.amount > 0 ? itemInfo.debName : itemInfo.credName}} {{itemInfo.amount > 0 ? itemInfo.debName : itemInfo.credName}}
</td> </td>
</tr> </tr>
<tr class="flex-row flex justify-between"> <tr class="flex-row flex justify-between">
@@ -284,18 +336,19 @@ setup()
class="w-2/5 mx-auto" class="w-2/5 mx-auto"
v-if="itemInfo.amount > 0 " v-if="itemInfo.amount > 0 "
> >
<UDivider>
<span>Offene Summe: {{displayCurrency(calculateOpenSum)}}</span> <UDivider v-if="allocatedDocuments.length > 0">
<span>Zugewiesene Summe: {{displayCurrency(calculateAllocatedSum)}}</span>
</UDivider> </UDivider>
<UCard <UCard
class="mt-5" class="mt-5"
:ui="{ring: itemInfo.statementallocations.find(i => i.cd_id === document.id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}" :ui="{ring: itemInfo.statementallocations.find(i => i.cd_id === document.id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}"
v-for="document in openDocuments" v-for="document in allocatedDocuments"
> >
<template #header> <template #header>
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<span>{{dataStore.getCustomerById(document.customer).name}} - {{document.documentNumber}}</span> <span>{{document.customer ? document.customer.name : ""}} - {{document.documentNumber}}</span>
<span class="font-semibold text-primary-500">{{displayCurrency(getDocumentSum(document))}}</span> <span class="font-semibold text-primary-500 text-nowrap">{{displayCurrency(getDocumentSum(document))}}</span>
</div> </div>
</template> </template>
<UButton <UButton
@@ -303,7 +356,7 @@ setup()
variant="outline" variant="outline"
class="mr-3" class="mr-3"
v-if="!itemInfo.statementallocations.find(i => i.cd_id === document.id)" v-if="!itemInfo.statementallocations.find(i => i.cd_id === document.id)"
@click="itemInfo.statementallocations.push({cd_id: document.id, bs_id: itemInfo.id, amount: Number(getDocumentSum(document))})" @click="saveAllocation({cd_id: document.id, bs_id: itemInfo.id, amount: Number(getDocumentSum(document))})"
/> />
<UButton <UButton
icon="i-heroicons-x-mark" icon="i-heroicons-x-mark"
@@ -311,7 +364,56 @@ setup()
color="rose" color="rose"
class="mr-3" class="mr-3"
v-if="itemInfo.statementallocations.find(i => i.cd_id === document.id)" v-if="itemInfo.statementallocations.find(i => i.cd_id === document.id)"
@click="itemInfo.statementallocations = itemInfo.statementallocations.filter(i => i.cd_id !== document.id)" @click="removeAllocation(itemInfo.statementallocations.find(i => i.cd_id === document.id).id)"
/>
<UButton
variant="outline"
icon="i-heroicons-arrow-right-end-on-rectangle"
@click="router.push(`/createDocument/show/${document.id}`)"
/>
</UCard>
<UDivider class="mt-3">
<span>Offene Summe: {{displayCurrency(calculateOpenSum)}}</span>
</UDivider>
<UInput
id="searchinput"
v-model="searchString"
icon="i-heroicons-funnel"
autocomplete="off"
placeholder="Suche..."
class="hidden lg:block mt-3"
@keydown.esc="$event.target.blur()"
>
<template #trailing>
<UKbd value="/" />
</template>
</UInput>
<UCard
class="mt-5"
:ui="{ring: itemInfo.statementallocations.find(i => i.cd_id === document.id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}"
v-for="document in filteredRows"
>
<template #header>
<div class="flex flex-row justify-between">
<span>{{document.customer ? document.customer.name : ""}} - {{document.documentNumber}}</span>
<span class="font-semibold text-primary-500 text-nowrap">{{displayCurrency(getDocumentSum(document))}}</span>
</div>
</template>
<UButton
icon="i-heroicons-check"
variant="outline"
class="mr-3"
v-if="!itemInfo.statementallocations.find(i => i.cd_id === document.id)"
@click="saveAllocation({cd_id: document.id, bs_id: itemInfo.id, amount: Number(getDocumentSum(document))})"
/>
<UButton
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
class="mr-3"
v-if="itemInfo.statementallocations.find(i => i.cd_id === document.id)"
@click="removeAllocation(itemInfo.statementallocations.find(i => i.ii_id === document.id).id)"
/> />
<UButton <UButton
@@ -331,34 +433,34 @@ setup()
</UDivider> </UDivider>
<UCard <UCard
class="mt-5" class="mt-5"
:ui="{ring: itemInfo.assignments.find(i => i.id === invoice.id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}" :ui="{ring: /*itemInfo.assignments.find(i => i.id === invoice.id)*/ false ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}"
v-for="invoice in dataStore.getOpenIncomingInvoices()" v-for="item in openIncomingInvoices"
> >
<template #header> <template #header>
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<span>{{dataStore.getVendorById(invoice.vendor).name}} - {{invoice.reference}}</span> <span>{{dataStore.getVendorById(item.vendor).name}} - {{item.reference}}</span>
<span class="font-semibold text-rose-600">-{{displayCurrency(getInvoiceSum(invoice))}}</span> <span class="font-semibold text-rose-600 text-nowrap">-{{displayCurrency(getInvoiceSum(item))}}</span>
</div> </div>
</template> </template>
<UButton <UButton
icon="i-heroicons-check" icon="i-heroicons-check"
variant="outline" variant="outline"
class="mr-3" class="mr-3"
v-if="!itemInfo.assignments.find(i => i.id === invoice.id)" v-if="!itemInfo.statementallocations.find(i => i.ii_id === item.id)"
@click="itemInfo.assignments.push({type: 'incomingInvoice',id: invoice.id})" @click="saveAllocation({ii_id: item.id, bs_id: itemInfo.id, amount: Number(getInvoiceSum(item))})"
/> />
<UButton <UButton
icon="i-heroicons-x-mark" icon="i-heroicons-x-mark"
variant="outline" variant="outline"
color="rose" color="rose"
class="mr-3" class="mr-3"
v-if="itemInfo.assignments.find(i => i.id === invoice.id)" v-if="itemInfo.statementallocations.find(i => i.ii_id === item.id)"
@click="itemInfo.assignments = itemInfo.assignments.filter(i => i.id !== invoice.id)" @click="removeAllocation(itemInfo.statementallocations.find(i => i.ii_id === item.id).id)"
/> />
<UButton <UButton
variant="outline" variant="outline"
icon="i-heroicons-arrow-right-end-on-rectangle" icon="i-heroicons-arrow-right-end-on-rectangle"
@click="router.push(`/incominginvoices/show/${invoice.id}`)" @click="router.push(`/incominginvoices/show/${item.id}`)"
/> />
</UCard> </UCard>

View File

@@ -105,24 +105,13 @@
<span :class="dayjs(row.dueDate).diff(dayjs()) <= 0 ? ['text-rose-500'] : '' ">{{row.dueDate ? dayjs(row.dueDate).format("DD.MM.YY") : ''}}</span> <span :class="dayjs(row.dueDate).diff(dayjs()) <= 0 ? ['text-rose-500'] : '' ">{{row.dueDate ? dayjs(row.dueDate).format("DD.MM.YY") : ''}}</span>
</template> </template>
<template #paid-data="{row}"> <template #paid-data="{row}">
<!-- <div v-if="row.type === 'invoices' ||row.type === 'advanceInvoices'">
<span v-if="dataStore.bankstatements.find(x => x.assignments.find(y => y.type === 'createdDocument' && y.id === row.id))" class="text-primary-500">Bezahlt</span> <span v-if="isPaid(row)" class="text-primary-500">Bezahlt</span>
--> <span v-else class="text-rose-600">Offen</span>
<!-- </div>
<span v-else :class="dayjs(row.dueDate).diff(dayjs()) <= 0 ? ['text-rose-500'] : ['text-cyan-500'] ">Offen</span>
-->
<!-- {{dataStore.bankstatements.find(x => x.assignments.find(y => y.id === row.id)) ? true : false}}-->
</template> </template>
<template #amount-data="{row}"> <template #amount-data="{row}">
<div {{displayCurrency(calculateDocSum(row))}}
class="text-right font-bold"
v-if="row.type === 'incomingInvoice'"
>
{{getRowAmount(row) === 0 ? '' : `${String(getRowAmount(row).toFixed(2)).replace('.',',')}`}}
</div>
<div v-else class="text-right">
{{calculateDocSum(row.rows)}}
</div>
</template> </template>
</UTable> </UTable>
@@ -173,8 +162,7 @@ const items = ref([])
const selectedItem = ref(0) const selectedItem = ref(0)
const setupPage = async () => { const setupPage = async () => {
items.value = await useSupabaseSelect("createddocuments","*, customer(id,name)") items.value = await useSupabaseSelect("createddocuments","*, customer(id,name), statementallocations(id,amount)","documentDate")
console.log(items.value)
} }
setupPage() setupPage()
@@ -257,15 +245,8 @@ const selectItem = (item) => {
} }
const getRowAmount = (row) => { const displayCurrency = (value, currency = "€") => {
let amount = 0 return `${Number(value).toFixed(2).replace(".",",")} ${currency}`
row.accounts.forEach(account => {
amount += account.amountNet
amount += account.amountTax
})
return amount
} }
@@ -285,17 +266,28 @@ const filteredRows = computed(() => {
}) })
const calculateDocSum = (rows) => { const calculateDocSum = (row) => {
let sum = 0 let sum = 0
rows.forEach(row => { row.rows.forEach(row => {
if(row.mode !== "pagebreak") { if(row.mode === "normal" || row.mode === "service" || row.mode === "free") {
sum += row.price * row.quantity * ( Number(row.taxPercent) + 100)/100 sum += row.quantity * row.price * (1 - row.discountPercent / 100) * (1 + row.taxPercent / 100)
} }
}) })
return sum.toFixed(2) return sum.toFixed(2)
} }
const isPaid = (item) => {
let amountPaid = 0
item.statementallocations.forEach(allocation => amountPaid += allocation.amount)
console.log(item.documentNumber)
console.log(amountPaid)
console.log(calculateDocSum(item))
return Number(amountPaid.toFixed(2)) === Number(calculateDocSum(item))
}
</script> </script>
<style scoped> <style scoped>

View File

@@ -42,7 +42,7 @@ const items = ref([])
const selectedItem = ref(0) const selectedItem = ref(0)
const setupPage = async () => { const setupPage = async () => {
items.value = await useSupabaseSelect("incominginvoices","*, vendor(id,name)") items.value = await useSupabaseSelect("incominginvoices","*, vendor(id,name), statementallocations(id,amount)")
} }
setupPage() setupPage()
@@ -66,6 +66,10 @@ const templateColumns = [
key: "vendor", key: "vendor",
label: "Lieferant" label: "Lieferant"
}, },
{
key: "amount",
label: "Betrag"
},
{ {
key: "dueDate", key: "dueDate",
label: "Fälligkeitsdatum" label: "Fälligkeitsdatum"
@@ -89,6 +93,25 @@ const filteredRows = computed(() => {
}) })
const displayCurrency = (value, currency = "€") => {
return `${Number(value).toFixed(2).replace(".",",")} ${currency}`
}
const getInvoiceSum = (invoice) => {
let sum = 0
invoice.accounts.forEach(account => {
sum += account.amountTax
sum += account.amountNet
})
return sum.toFixed(2)
}
const isPaid = (item) => {
let amountPaid = 0
item.statementallocations.forEach(allocation => amountPaid += allocation.amount)
return amountPaid === Number(getInvoiceSum(item))
}
</script> </script>
@@ -149,12 +172,15 @@ const filteredRows = computed(() => {
<template #vendor-data="{row}"> <template #vendor-data="{row}">
{{row.vendor ? row.vendor.name : ""}} {{row.vendor ? row.vendor.name : ""}}
</template> </template>
<template #amount-data="{row}">
{{displayCurrency(getInvoiceSum(row))}}
</template>
<template #dueDate-data="{row}"> <template #dueDate-data="{row}">
{{dayjs(row.dueDate).format("DD.MM.YYYY")}} {{dayjs(row.dueDate).format("DD.MM.YYYY")}}
</template> </template>
<template #paid-data="{row}"> <template #paid-data="{row}">
<!-- <span v-if="dataStore.bankstatements.find(x => x.statementallocations.find(y => y.ii_id === row.id))" class="text-primary-500">Bezahlt</span> <span v-if="isPaid(row)" class="text-primary-500">Bezahlt</span>
<span v-else class="text-rose-600">Offen</span>--> <span v-else class="text-rose-600">Offen</span>
</template> </template>
</UTable> </UTable>
</UDashboardPanelContent> </UDashboardPanelContent>