Merge branch 'dev' into devWithMobile

This commit is contained in:
2025-03-25 15:17:34 +01:00
3 changed files with 244 additions and 85 deletions

View File

@@ -28,6 +28,9 @@ const allocatedDocuments = ref([])
const openIncomingInvoices = ref([]) const openIncomingInvoices = ref([])
const allocatedIncomingInvoices = ref([]) const allocatedIncomingInvoices = ref([])
const customers = ref([])
const vendors = ref([])
const createddocuments = ref([]) const createddocuments = ref([])
const accounts = ref([]) const accounts = ref([])
@@ -36,7 +39,7 @@ const ownaccounts = ref([])
const loading = ref(true) const loading = ref(true)
const setup = async () => { const setup = async () => {
if(route.params.id) { if(route.params.id) {
itemInfo.value = (await supabase.from("bankstatements").select("*, statementallocations(*, cd_id(*, customer(*)), ii_id(*))").eq("id",route.params.id).single()).data //dataStore.bankstatements.find(i => i.id === Number(route.params.id)) itemInfo.value = (await supabase.from("bankstatements").select("*, statementallocations(*, cd_id(*), ii_id(*))").eq("id",route.params.id).single()).data //dataStore.bankstatements.find(i => i.id === Number(route.params.id))
} }
if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value)) if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
@@ -48,6 +51,8 @@ const setup = async () => {
accounts.value = (await supabase.from("accounts").select()).data accounts.value = (await supabase.from("accounts").select()).data
ownaccounts.value = (await supabase.from("ownaccounts").select()).data ownaccounts.value = (await supabase.from("ownaccounts").select()).data
customers.value = (await supabase.from("customers").select()).data
vendors.value = (await supabase.from("vendors").select()).data
openDocuments.value = documents.filter(i => i.statementallocations.reduce((n,{amount}) => n + amount, 0).toFixed(2) !== useSum().getCreatedDocumentSum(i,createddocuments.value).toFixed(2)) openDocuments.value = documents.filter(i => i.statementallocations.reduce((n,{amount}) => n + amount, 0).toFixed(2) !== useSum().getCreatedDocumentSum(i,createddocuments.value).toFixed(2))
openDocuments.value = openDocuments.value.map(i => { openDocuments.value = openDocuments.value.map(i => {
@@ -93,17 +98,23 @@ const getInvoiceSum = (invoice) => {
sum += account.amountTax sum += account.amountTax
sum += account.amountNet sum += account.amountNet
}) })
return sum.toFixed(2) console.log(sum)
if(invoice.expense) {
return (sum * -1).toFixed(2)
} else {
return sum.toFixed(2)
}
} }
const calculateOpenSum = computed(() => { const calculateOpenSum = computed(() => {
let startingAmount = 0 let startingAmount = 0
itemInfo.value.statementallocations.forEach(item => { itemInfo.value.statementallocations.forEach(item => {
startingAmount += Math.abs(item.amount) startingAmount += item.amount
}) })
return (Math.abs(itemInfo.value.amount) - startingAmount).toFixed(2) return (itemInfo.value.amount - startingAmount).toFixed(2)
}) })
@@ -121,6 +132,8 @@ const saveAllocations = async () => {
const showAccountSelection = ref(false) const showAccountSelection = ref(false)
const accountToSave = ref("") const accountToSave = ref("")
const ownAccountToSave = ref("") const ownAccountToSave = ref("")
const customerAccountToSave = ref("")
const vendorAccountToSave = ref("")
const selectAccount = (id) => { const selectAccount = (id) => {
accountToSave.value = id accountToSave.value = id
@@ -129,6 +142,8 @@ const selectAccount = (id) => {
const manualAllocationSum = ref(itemInfo.value.amount || 0) const manualAllocationSum = ref(itemInfo.value.amount || 0)
const allocationDescription = ref("")
const showMoreWithoutRecipe = ref(false)
const saveAllocation = async (allocation) => { const saveAllocation = async (allocation) => {
@@ -142,6 +157,10 @@ const saveAllocation = async (allocation) => {
if(data) { if(data) {
await setup() await setup()
accountToSave.value = null accountToSave.value = null
vendorAccountToSave.value = null
customerAccountToSave.value = null
ownAccountToSave.value = null
allocationDescription.value = null
} }
@@ -172,6 +191,23 @@ const filteredIncomingInvoices = computed(() => {
setup() setup()
const archiveStatement = async () => {
let temp = itemInfo.value
delete temp.statementallocations
await dataStore.updateItem("bankstatements", {...temp,archived:true})
const {data,error} = await supabase.from("historyitems").insert({
createdBy: useProfileStore().activeProfile.id,
tenant: useProfileStore().currentTenant,
text: "Bankbuchung archiviert",
bankStatement: itemInfo.value.id
})
}
</script> </script>
<template> <template>
@@ -205,6 +241,21 @@ setup()
Offen Offen
</UBadge> </UBadge>
</template> </template>
<template #right>
<ButtonWithConfirm
color="rose"
variant="outline"
@confirmed="archiveStatement"
>
<template #button>
Archivieren
</template>
<template #header>
<span class="text-md text-black font-bold">Archivieren bestätigen</span>
</template>
Möchten Sie die Kontobewegung wirklich archivieren?
</ButtonWithConfirm>
</template>
</UDashboardNavbar> </UDashboardNavbar>
<UDashboardPanelContent <UDashboardPanelContent
@@ -240,6 +291,15 @@ setup()
</div> </div>
</template> </template>
<UAlert
v-if="itemInfo.archived"
color="rose"
variant="outline"
:title="`Kontobewegung archiviert`"
icon="i-heroicons-archive-box"
class="mb-5"
/>
<table class="w-full" v-if="itemInfo.id"> <table class="w-full" v-if="itemInfo.id">
<tbody> <tbody>
<tr class="flex-row flex justify-between"> <tr class="flex-row flex justify-between">
@@ -343,15 +403,15 @@ setup()
<UAlert <UAlert
class="mb-3 mt-3" class="mb-3 mt-3"
:color="calculateOpenSum > 0 ? 'rose' : 'primary'" :color="calculateOpenSum != 0 ? 'rose' : 'primary'"
variant="outline" variant="outline"
:title="calculateOpenSum > 0 ? `${displayCurrency(calculateOpenSum)} von ${displayCurrency(Math.abs(itemInfo.amount))} nicht zugewiesen` : 'Kontobewegung vollständig zugewiesen'" :title="calculateOpenSum != 0 ? `${displayCurrency(Math.abs(calculateOpenSum))} von ${displayCurrency(Math.abs(itemInfo.amount))} nicht zugewiesen` : 'Kontobewegung vollständig zugewiesen'"
> >
<template #description> <template #description>
<UProgress <UProgress
:value="Math.abs(itemInfo.amount) - calculateOpenSum" :value="Math.abs(itemInfo.amount) - calculateOpenSum"
:max="Math.abs(itemInfo.amount)" :max="Math.abs(itemInfo.amount)"
:color="calculateOpenSum > 0 ? 'rose' : 'primary'" :color="calculateOpenSum != 0 ? 'rose' : 'primary'"
/> />
</template> </template>
</UAlert> </UAlert>
@@ -399,91 +459,105 @@ setup()
</UCard> </UCard>
<UCard <UCard
class="mt-5" class="mt-5"
:ui="{ring: itemInfo.statementallocations.find(i => i.cd_id === item.cd_id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}" v-for="item in itemInfo.statementallocations.filter(i => i.customer)"
>
<template #header>
<div class="flex flex-row justify-between">
<span>{{customers.find(i => i.id === item.customer).customerNumber}} - {{customers.find(i => i.id === item.customer).name}}</span>
<span class="font-semibold text-nowrap">{{displayCurrency(item.amount)}}</span>
</div>
</template>
<UButton
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
class="mr-3"
@click="removeAllocation(item.id)"
/>
</UCard>
<UCard
class="mt-5"
v-for="item in itemInfo.statementallocations.filter(i => i.vendor)"
>
<template #header>
<div class="flex flex-row justify-between">
<span>{{vendors.find(i => i.id === item.vendor).vendorNumber}} - {{vendors.find(i => i.id === item.vendor).name}}</span>
<span class="font-semibold text-nowrap">{{displayCurrency(item.amount)}}</span>
</div>
</template>
<UButton
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
class="mr-3"
@click="removeAllocation(item.id)"
/>
</UCard>
<UCard
class="mt-5"
v-for="item in itemInfo.statementallocations.filter(i => i.ii_id)"
>
<template #header>
<div class="flex flex-row justify-between">
<span>{{vendors.find(i => i.id === item.ii_id.vendor).vendorNumber}} - {{vendors.find(i => i.id === item.ii_id.vendor).name}}</span>
<span class="font-semibold text-nowrap">{{displayCurrency(item.amount)}}</span>
</div>
</template>
<UButton
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
class="mr-3"
@click="removeAllocation(item.id)"
/>
</UCard>
<UCard
class="mt-5"
v-for="item in itemInfo.statementallocations.filter(i => i.cd_id)" v-for="item in itemInfo.statementallocations.filter(i => i.cd_id)"
> >
<template #header> <template #header>
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<span>{{item.cd_id.customer ? item.cd_id.customer.name : ""}} - {{item.cd_id.documentNumber}}</span> <span v-if="customers.find(i => i.id === item.cd_id.customer)">{{customers.find(i => i.id === item.cd_id.customer).customerNumber}} - {{customers.find(i => i.id === item.cd_id.customer).name}}</span>
<span class="font-semibold text-nowrap">{{displayCurrency(item.amount)}}</span> <span class="font-semibold text-nowrap">{{displayCurrency(item.amount)}}</span>
</div> </div>
</template> </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(useSum().getCreatedDocumentSum(document,createddocuments))})"
/>-->
<UButton <UButton
icon="i-heroicons-x-mark" icon="i-heroicons-x-mark"
variant="outline" variant="outline"
color="rose" color="rose"
class="" class="mr-3"
@click="removeAllocation(item.id)" @click="removeAllocation(item.id)"
/> />
<!-- <EntityModalButtons
:button-create="false"
:button-edit="false"
:id="item.cd_id.id"
type="createddocuments"/>
{{item.cd_id.id}}-->
<!-- <UButton
variant="outline"
icon="i-heroicons-arrow-right-end-on-rectangle"
@click="router.push(`/createDocument/show/${document.id}`)"
/>-->
</UCard>
<UCard
class="mt-5"
:ui="{ring: itemInfo.statementallocations.find(i => i.ii_id === invoice.id) ? 'ring-primary-500' : 'ring-gray-200 dark:ring-gray-800'}"
v-for="invoice in allocatedIncomingInvoices"
>
<template #header>
<div class="flex flex-row justify-between">
<span>{{invoice.vendor ? invoice.vendor.name : ""}} - {{invoice.reference}}</span>
<span class="font-semibold text-nowrap">{{displayCurrency(getInvoiceSum(invoice))}}</span>
</div>
</template>
<UButton
icon="i-heroicons-check"
variant="outline"
class="mr-3"
v-if="!itemInfo.statementallocations.find(i => i.ii_id === invoice.id)"
@click="saveAllocation({ii_id: document.id, bs_id: itemInfo.id, amount: Number(getInvoiceSum(invoice))})"
/>
<UButton
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
class="mr-3"
v-if="itemInfo.statementallocations.find(i => i.ii_id === invoice.id)"
@click="removeAllocation(itemInfo.statementallocations.find(i => i.ii_id === invoice.id).id)"
/>
<UButton
variant="outline"
icon="i-heroicons-arrow-right-end-on-rectangle"
@click="router.push(`/createDocument/show/${document.id}`)"
/>
</UCard> </UCard>
</div> </div>
</div> </div>
<div class="w-2/5 mx-auto"> <div class="w-2/5 mx-auto">
<div class="px-2"> <div class="px-2">
<UDivider class="my-3">Buchungssumme</UDivider> <UDivider class="mt-3">Buchungsdaten</UDivider>
<UFormGroup
<UInput label="Summe:"
v-model="manualAllocationSum"
type="number"
step="0.01"
> >
<template #trailing> <UInput
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span> v-model="manualAllocationSum"
</template> type="number"
</UInput> step="0.01"
>
<template #trailing>
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
</template>
</UInput>
</UFormGroup>
<UFormGroup
label="Beschreibung:"
class="mt-3"
>
<UTextarea
v-model="allocationDescription"
rows="3"
/>
</UFormGroup>
<UDivider class="my-3">Ohne Beleg buchen</UDivider> <UDivider class="my-3">Ohne Beleg buchen</UDivider>
@@ -519,7 +593,7 @@ setup()
variant="outline" variant="outline"
icon="i-heroicons-check" icon="i-heroicons-check"
:disabled="!accountToSave" :disabled="!accountToSave"
@click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, account: accountToSave })" @click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, account: accountToSave, description: allocationDescription })"
/> />
<UButton <UButton
@click="accountToSave = ''" @click="accountToSave = ''"
@@ -552,7 +626,13 @@ setup()
</UModal> </UModal>
</UFormGroup> </UFormGroup>
<UButton
class="mt-3"
@click="showMoreWithoutRecipe = !showMoreWithoutRecipe"
variant="outline"
>{{ showMoreWithoutRecipe ? "Weniger anzeigen" : "Mehr anzeigen" }}</UButton>
<UFormGroup <UFormGroup
v-if="showMoreWithoutRecipe"
label="zusätzliche Buchungskonten" label="zusätzliche Buchungskonten"
class="mt-3" class="mt-3"
> >
@@ -579,7 +659,7 @@ setup()
variant="outline" variant="outline"
icon="i-heroicons-check" icon="i-heroicons-check"
:disabled="!ownAccountToSave" :disabled="!ownAccountToSave"
@click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, ownaccount: ownAccountToSave })" @click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, ownaccount: ownAccountToSave, description: allocationDescription })"
/> />
<UButton <UButton
@click="accountToSave = ''" @click="accountToSave = ''"
@@ -589,8 +669,82 @@ setup()
/> />
</InputGroup> </InputGroup>
</UFormGroup> </UFormGroup>
<UFormGroup
v-if="showMoreWithoutRecipe"
label="Kunden"
class="mt-3"
>
<InputGroup class="w-full">
<USelectMenu
class="w-full"
:options="customers"
value-attribute="id"
option-attribute="label"
:ui-menu="{ width: 'min-w-max' }"
v-model="customerAccountToSave"
searchable
:search-attributes="['number','label']"
>
<template #label>
<span v-if="customerAccountToSave">{{customers.find(i => i.id === customerAccountToSave).customerNumber}} - {{customers.find(i => i.id === customerAccountToSave).name}}</span>
<span v-else>Kein Konto ausgewählt</span>
</template>
<template #option="{option}">
{{option.customerNumber}} - {{option.name}}
</template>
</USelectMenu>
<UButton
variant="outline"
icon="i-heroicons-check"
:disabled="!customerAccountToSave"
@click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, customer: customerAccountToSave, description: allocationDescription })"
/>
<UButton
@click="customerAccountToSave = ''"
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
/>
</InputGroup>
</UFormGroup>
<UFormGroup
v-if="showMoreWithoutRecipe"
label="Lieferanten"
class="mt-3"
>
<InputGroup class="w-full">
<USelectMenu
class="w-full"
:options="vendors"
value-attribute="id"
option-attribute="label"
:ui-menu="{ width: 'min-w-max' }"
v-model="vendorAccountToSave"
searchable
:search-attributes="['number','name']"
>
<template #label>
<span v-if="vendorAccountToSave">{{vendors.find(i => i.id === vendorAccountToSave).vendorNumber}} - {{vendors.find(i => i.id === vendorAccountToSave).name}}</span>
<span v-else>Kein Konto ausgewählt</span>
</template>
<template #option="{option}">
{{option.vendorNumber}} - {{option.name}}
</template>
</USelectMenu>
<UButton
variant="outline"
icon="i-heroicons-check"
:disabled="!vendorAccountToSave"
@click="saveAllocation({bs_id: itemInfo.id, amount: manualAllocationSum, vendor: vendorAccountToSave, description: allocationDescription })"
/>
<UButton
@click="vendorAccountToSave = ''"
icon="i-heroicons-x-mark"
variant="outline"
color="rose"
/>
</InputGroup>
</UFormGroup>
<UDivider <UDivider
class="my-3" class="my-3"
@@ -622,7 +776,7 @@ setup()
</InputGroup> </InputGroup>
</div> </div>
<div class="scrollList mt-3 px-2" style="height: 70vh;"> <div class="scrollList mt-3 px-2" style="height: 40vh;">
<UCard <UCard
class="mt-5" class="mt-5"
@@ -639,7 +793,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="saveAllocation({cd_id: document.id, bs_id: itemInfo.id, amount: Number(document.openSum < maunualAllocationSum ? document.openSum : manualAllocationSum)})" @click="saveAllocation({cd_id: document.id, bs_id: itemInfo.id, amount: Number(document.openSum < maunualAllocationSum ? document.openSum : manualAllocationSum), description: allocationDescription})"
/> />
<UButton <UButton
@@ -656,7 +810,7 @@ setup()
<template #header> <template #header>
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<span>{{item.vendor ? item.vendor.name : ''}} - {{item.reference}}</span> <span>{{item.vendor ? item.vendor.name : ''}} - {{item.reference}}</span>
<span class="font-semibold text-rose-600 text-nowrap">-{{displayCurrency(getInvoiceSum(item))}}</span> <span class="font-semibold text-rose-600 text-nowrap">{{displayCurrency(getInvoiceSum(item))}}</span>
</div> </div>
</template> </template>
<UButton <UButton
@@ -664,7 +818,7 @@ setup()
variant="outline" variant="outline"
class="mr-3" class="mr-3"
v-if="!itemInfo.statementallocations.find(i => i.ii_id === item.id)" v-if="!itemInfo.statementallocations.find(i => i.ii_id === item.id)"
@click="saveAllocation({ii_id: item.id, bs_id: itemInfo.id, amount: Number(getInvoiceSum(item))})" @click="saveAllocation({ii_id: item.id, bs_id: itemInfo.id, amount: Number(getInvoiceSum(item)), description: allocationDescription})"
/> />
<UButton <UButton
variant="outline" variant="outline"

View File

@@ -81,6 +81,10 @@ const templateColumns = [
{ {
key: "paymentType", key: "paymentType",
label: "Zahlart" label: "Zahlart"
},
{
key: "description",
label: "Beschreibung"
} }
] ]
const selectedColumns = ref(templateColumns) const selectedColumns = ref(templateColumns)

View File

@@ -155,7 +155,7 @@ export const useDataStore = defineStore('data', () => {
numberRangeHolder: "customerNumber", numberRangeHolder: "customerNumber",
historyItemHolder: "customer", historyItemHolder: "customer",
supabaseSortColumn: "customerNumber", supabaseSortColumn: "customerNumber",
supabaseSelectWithInformation: "*, projects(*), plants(*), contracts(*), contacts(*), createddocuments(*), files(*)", supabaseSelectWithInformation: "*, projects(*), plants(*), contracts(*), contacts(*), createddocuments(*), files(*), events(*)",
filters: [{ filters: [{
name: "Archivierte ausblenden", name: "Archivierte ausblenden",
default: true, default: true,
@@ -309,7 +309,7 @@ export const useDataStore = defineStore('data', () => {
component: profiles component: profiles
}, },
], ],
showTabs: [{label: 'Informationen'},{label: 'Ansprechpartner'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Verträge'}] showTabs: [{label: 'Informationen'},{label: 'Ansprechpartner'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Termine'},{label: 'Verträge'}]
}, },
contacts: { contacts: {
isArchivable: true, isArchivable: true,
@@ -1647,7 +1647,7 @@ export const useDataStore = defineStore('data', () => {
labelSingle: "Termin", labelSingle: "Termin",
isStandardEntity: true, isStandardEntity: true,
historyItemHolder: "event", historyItemHolder: "event",
supabaseSelectWithInformation: "*, project(id,name)", supabaseSelectWithInformation: "*, project(id,name), customer(*)",
redirect: true, redirect: true,
filters:[{ filters:[{
name: "Archivierte ausblenden", name: "Archivierte ausblenden",
@@ -1737,6 +1737,7 @@ export const useDataStore = defineStore('data', () => {
selectDataType: "customers", selectDataType: "customers",
selectOptionAttribute: "name", selectOptionAttribute: "name",
selectSearchAttributes: ['name'], selectSearchAttributes: ['name'],
component: customer,
},{ },{
key: "vendor", key: "vendor",
label: "Lieferant", label: "Lieferant",
@@ -2623,9 +2624,9 @@ export const useDataStore = defineStore('data', () => {
await generateHistoryItems(dataType, supabaseData[0]) await generateHistoryItems(dataType, supabaseData[0])
if(!["statementallocations","absencerequests", "productcategories", "servicecategories", "projecttypes", "checks", "profiles","services", "inventoryitems", "inventoryitemgroups", "incominginvoices"].includes(dataType) ){ /*if(!["statementallocations","absencerequests", "productcategories", "servicecategories", "projecttypes", "checks", "profiles","services", "inventoryitems", "inventoryitemgroups", "incominginvoices", "costcentres", "ownaccounts"].includes(dataType) ){
await eval( dataType + '.value.push(' + JSON.stringify(...supabaseData) + ')') await eval( dataType + '.value.push(' + JSON.stringify(...supabaseData) + ')')
} }*/
toast.add({title: `${dataTypes[dataType].labelSingle} hinzugefügt`}) toast.add({title: `${dataTypes[dataType].labelSingle} hinzugefügt`})