@@ -23,9 +23,6 @@ let {documentData, openShowModal:openShowModalProp, returnEmit } = props;
|
|||||||
const tags = dataStore.getDocumentTags
|
const tags = dataStore.getDocumentTags
|
||||||
const openShowModal = ref(false)
|
const openShowModal = ref(false)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Functions
|
//Functions
|
||||||
const openDocument = async () => {
|
const openDocument = async () => {
|
||||||
//selectedDocument.value = doc
|
//selectedDocument.value = doc
|
||||||
@@ -140,7 +137,7 @@ const updateDocumentAssignment = async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :id="`docDisplay-${documentData.id}`" class="documentListItem" @click="returnEmit ? $emit('clicked', documentData.id) : openShowModal = true">
|
<div class="documentListItem" @click="returnEmit ? $emit('clicked', documentData.id) : openShowModal = true">
|
||||||
<iframe
|
<iframe
|
||||||
:src="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
:src="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
||||||
class="previewEmbed"
|
class="previewEmbed"
|
||||||
@@ -153,8 +150,8 @@ const updateDocumentAssignment = async () => {
|
|||||||
:src="documentData.url"
|
:src="documentData.url"
|
||||||
/>
|
/>
|
||||||
<!-- TODO: Remove Scrollbar -->
|
<!-- TODO: Remove Scrollbar -->
|
||||||
<UTooltip class="w-full" :text="documentData.path.split('/')[documentData.path.split('/').length -1]">
|
<UTooltip class="w-full" :text="documentData.path.split('_')[documentData.path.split('_').length -1]">
|
||||||
<p class="truncate my-3">{{documentData.path.split("/")[documentData.path.split("/").length -1]}}</p>
|
<p class="truncate my-3">{{documentData.path.split("_")[documentData.path.split("_").length -1]}}</p>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
|
|
||||||
<InputGroup class="mt-3 flex-wrap">
|
<InputGroup class="mt-3 flex-wrap">
|
||||||
@@ -229,14 +226,6 @@ const updateDocumentAssignment = async () => {
|
|||||||
>
|
>
|
||||||
Archivieren
|
Archivieren
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
|
||||||
:to="documentData.url"
|
|
||||||
variant="outline"
|
|
||||||
icon="i-heroicons-arrow-top-right-on-square"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Öffnen
|
|
||||||
</UButton>
|
|
||||||
<!-- <UButton
|
<!-- <UButton
|
||||||
v-if="documentData.tags.includes('Eingangsrechnung')"
|
v-if="documentData.tags.includes('Eingangsrechnung')"
|
||||||
@click="createVendorInvoice"
|
@click="createVendorInvoice"
|
||||||
@@ -244,11 +233,11 @@ const updateDocumentAssignment = async () => {
|
|||||||
Eingangsrechnung erstellen
|
Eingangsrechnung erstellen
|
||||||
</UButton>-->
|
</UButton>-->
|
||||||
</UButtonGroup>
|
</UButtonGroup>
|
||||||
<!-- <br>
|
<br>
|
||||||
<a
|
<a
|
||||||
:href="documentData.url"
|
:href="documentData.url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>In neuen Tab anzeigen</a>-->
|
>In neuen Tab anzeigen</a>
|
||||||
|
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="Tags ändern:"
|
label="Tags ändern:"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script setup >
|
<script setup lang="ts">
|
||||||
import { format, isToday } from 'date-fns'
|
import { format, isToday } from 'date-fns'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -12,15 +12,15 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue','emailSelected'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const mailsRefs = ref([])
|
const mailsRefs = ref<Element[]>([])
|
||||||
|
|
||||||
const selectedMail = computed({
|
const selectedMail = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.modelValue
|
return props.modelValue
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value: Mail | null) {
|
||||||
emit('update:modelValue', value)
|
emit('update:modelValue', value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -30,17 +30,12 @@ watch(selectedMail, () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const ref1 = mailsRefs.value[selectedMail.value.id]
|
const ref = mailsRefs.value[selectedMail.value.id]
|
||||||
if (ref1) {
|
if (ref) {
|
||||||
ref1.scrollIntoView({ block: 'nearest' })
|
ref.scrollIntoView({ block: 'nearest' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const changeMail = (mail) => {
|
|
||||||
selectedMail.value = mail
|
|
||||||
emit("emailSelected")
|
|
||||||
}
|
|
||||||
|
|
||||||
defineShortcuts({
|
defineShortcuts({
|
||||||
arrowdown: () => {
|
arrowdown: () => {
|
||||||
const index = props.mails.findIndex((mail) => mail.id === selectedMail.value?.id)
|
const index = props.mails.findIndex((mail) => mail.id === selectedMail.value?.id)
|
||||||
@@ -64,15 +59,15 @@ defineShortcuts({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="p-0 scrollCont overflow-scroll">
|
<UDashboardPanelContent class="p-0">
|
||||||
<div v-for="(mail, index) in mails" :key="index" :ref="el => { mailsRefs[mail.id] = el }">
|
<div v-for="(mail, index) in mails" :key="index" :ref="el => { mailsRefs[mail.id] = el as Element }">
|
||||||
<div
|
<div
|
||||||
class="p-4 text-sm cursor-pointer border-l-2"
|
class="p-4 text-sm cursor-pointer border-l-2"
|
||||||
:class="[
|
:class="[
|
||||||
!mail.seen ? 'text-gray-900 dark:text-white' : 'text-gray-600 dark:text-gray-300',
|
mail.unread ? 'text-gray-900 dark:text-white' : 'text-gray-600 dark:text-gray-300',
|
||||||
selectedMail && selectedMail.id === mail.id ? 'border-primary-500 dark:border-primary-400 bg-primary-100 dark:bg-primary-900/25' : 'border-white dark:border-gray-900 hover:border-primary-500/25 dark:hover:border-primary-400/25 hover:bg-primary-100/50 dark:hover:bg-primary-900/10'
|
selectedMail && selectedMail.id === mail.id ? 'border-primary-500 dark:border-primary-400 bg-primary-100 dark:bg-primary-900/25' : 'border-white dark:border-gray-900 hover:border-primary-500/25 dark:hover:border-primary-400/25 hover:bg-primary-100/50 dark:hover:bg-primary-900/10'
|
||||||
]"
|
]"
|
||||||
@click="changeMail(mail)"
|
@click="selectedMail = mail"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-between" :class="[mail.unread && 'font-semibold']">
|
<div class="flex items-center justify-between" :class="[mail.unread && 'font-semibold']">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
@@ -87,17 +82,11 @@ defineShortcuts({
|
|||||||
{{ mail.subject }}
|
{{ mail.subject }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-gray-400 dark:text-gray-500 line-clamp-1">
|
<p class="text-gray-400 dark:text-gray-500 line-clamp-1">
|
||||||
{{ mail.text }}
|
{{ mail.body }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<UDivider />
|
<UDivider />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</UDashboardPanelContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
.scrollCont {
|
|
||||||
height: 90vh;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -17,11 +17,11 @@ defineProps({
|
|||||||
<UDashboardPanelContent>
|
<UDashboardPanelContent>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<UAvatar v-bind="mail.from.avatar" :alt="mail.from.name||mail.from.address" size="lg" />
|
<UAvatar v-bind="mail.from.avatar" :alt="mail.from.name" size="lg" />
|
||||||
|
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<p class="text-gray-900 dark:text-white font-semibold">
|
<p class="text-gray-900 dark:text-white font-semibold">
|
||||||
{{ mail.from.name ||mail.from.address}}
|
{{ mail.from.name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-gray-500 dark:text-gray-400 font-medium">
|
<p class="text-gray-500 dark:text-gray-400 font-medium">
|
||||||
{{ mail.subject }}
|
{{ mail.subject }}
|
||||||
@@ -36,33 +36,18 @@ defineProps({
|
|||||||
|
|
||||||
<UDivider class="my-5" />
|
<UDivider class="my-5" />
|
||||||
|
|
||||||
<InputGroup class="mb-3">
|
<div class="flex-1">
|
||||||
<UButton
|
<p class="text-lg">
|
||||||
v-for="attachment in mail.attachments"
|
{{ mail.body }}
|
||||||
icon="i-heroicons-arrow-down-tray"
|
</p>
|
||||||
disabled
|
|
||||||
>
|
|
||||||
{{attachment.filename}}
|
|
||||||
</UButton>
|
|
||||||
</InputGroup>
|
|
||||||
|
|
||||||
<div class="contentscroll overflow-scroll">
|
|
||||||
<iframe class="flex-1 h-full w-full" :srcdoc="mail.html" v-if="mail.html"/>
|
|
||||||
|
|
||||||
<!-- <div class="flex-1" v-html="mail.html" v-if="mail.html">
|
|
||||||
|
|
||||||
</div>-->
|
|
||||||
<div class="flex-1" v-else>
|
|
||||||
<p>{{mail.text}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<UDivider class="my-5" />
|
||||||
|
|
||||||
|
<form @submit.prevent>
|
||||||
|
<UTextarea color="gray" required size="xl" :rows="5" :placeholder="`Reply to ${mail.from.name}`">
|
||||||
|
<UButton type="submit" color="black" label="Send" icon="i-heroicons-paper-airplane" class="absolute bottom-2.5 right-3.5" />
|
||||||
|
</UTextarea>
|
||||||
|
</form>
|
||||||
</UDashboardPanelContent>
|
</UDashboardPanelContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
.contentscroll{
|
|
||||||
height: 80vh;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useRole} from "~/composables/useRole.js";
|
|
||||||
|
|
||||||
const dataStore = useDataStore()
|
const dataStore = useDataStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const role = useRole()
|
|
||||||
console.log(role)
|
|
||||||
console.log(role.checkRight("projects"))
|
|
||||||
|
|
||||||
const links = computed(() => {
|
const links = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -42,7 +36,7 @@ const links = computed(() => {
|
|||||||
icon: "i-heroicons-calendar-days"
|
icon: "i-heroicons-calendar-days"
|
||||||
}] : [],
|
}] : [],
|
||||||
{
|
{
|
||||||
label: "Dateien",
|
label: "Dokumente",
|
||||||
to: "/documents",
|
to: "/documents",
|
||||||
icon: "i-heroicons-document"
|
icon: "i-heroicons-document"
|
||||||
},
|
},
|
||||||
@@ -208,22 +202,37 @@ const links = computed(() => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
... role.checkRight("checks") ? [{
|
/*... dataStore.ownTenant.features.projects ? [{
|
||||||
|
label: "Projekte",
|
||||||
|
defaultOpen: false,
|
||||||
|
icon: "i-heroicons-clipboard-document-check",
|
||||||
|
children: [
|
||||||
|
...dataStore.ownTenant.projecttypes.map(i => {
|
||||||
|
return {
|
||||||
|
label: i.label,
|
||||||
|
to: `/projects?type=${i.label}`,
|
||||||
|
icon: i.icon
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
]
|
||||||
|
},] : [],*/
|
||||||
|
{
|
||||||
label: "Überprüfungen",
|
label: "Überprüfungen",
|
||||||
to: "/checks",
|
to: "/checks",
|
||||||
icon: "i-heroicons-magnifying-glass"
|
icon: "i-heroicons-magnifying-glass"
|
||||||
},] : [],
|
},
|
||||||
... (role.checkRight("projects") && dataStore.ownTenant.features.projects) ? [{
|
... dataStore.ownTenant.features.projects ? [{
|
||||||
label: "Projekte",
|
label: "Projekte",
|
||||||
to: "/projects",
|
to: "/projects",
|
||||||
icon: "i-heroicons-clipboard-document-check"
|
icon: "i-heroicons-clipboard-document-check"
|
||||||
},] : [],
|
},] : [],
|
||||||
... (role.checkRight("contracts") && dataStore.ownTenant.features.contracts) ? [{
|
... dataStore.ownTenant.features.contracts ? [{
|
||||||
label: "Verträge",
|
label: "Verträge",
|
||||||
to: "/contracts",
|
to: "/contracts",
|
||||||
icon: "i-heroicons-clipboard-document"
|
icon: "i-heroicons-clipboard-document"
|
||||||
}] : [],
|
}] : [],
|
||||||
... (role.checkRight("objects") && dataStore.ownTenant.features.objects) ? [{
|
... dataStore.ownTenant.features.objects ? [{
|
||||||
label: "Objekte",
|
label: "Objekte",
|
||||||
to: "/plants",
|
to: "/plants",
|
||||||
icon: "i-heroicons-clipboard-document"
|
icon: "i-heroicons-clipboard-document"
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ export const useCreatePdf = async (invoiceData,backgroundSourceBuffer) => {
|
|||||||
maxWidth: 240
|
maxWidth: 240
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(row)
|
console.log(row.text.match(/.{1,35}/g))
|
||||||
|
|
||||||
if(invoiceData.type !== "deliveryNotes") {
|
if(invoiceData.type !== "deliveryNotes") {
|
||||||
pages[pageCounter - 1].drawText(row.text.match(/.{1,35}/g).join("\n"), {
|
pages[pageCounter - 1].drawText(row.text.match(/.{1,35}/g).join("\n"), {
|
||||||
@@ -933,8 +933,6 @@ export const useCreatePdf = async (invoiceData,backgroundSourceBuffer) => {
|
|||||||
//console.log(rowHeight)
|
//console.log(rowHeight)
|
||||||
//rowHeight += 25
|
//rowHeight += 25
|
||||||
|
|
||||||
let endTextDiff = 45
|
|
||||||
|
|
||||||
if(invoiceData.type !== "deliveryNotes"){
|
if(invoiceData.type !== "deliveryNotes"){
|
||||||
pages[pageCounter - 1].drawRectangle({
|
pages[pageCounter - 1].drawRectangle({
|
||||||
...getCoordinatesForPDFLib(20,rowHeight, page1),
|
...getCoordinatesForPDFLib(20,rowHeight, page1),
|
||||||
@@ -1014,86 +1012,11 @@ export const useCreatePdf = async (invoiceData,backgroundSourceBuffer) => {
|
|||||||
maxWidth: 240,
|
maxWidth: 240,
|
||||||
font:fontBold
|
font:fontBold
|
||||||
})
|
})
|
||||||
|
|
||||||
if(invoiceData.total.totalGrossAlreadyPaid !== "0,00 €") {
|
|
||||||
pages[pageCounter - 1].drawText("Bereits bezahlt:", {
|
|
||||||
...getCoordinatesForPDFLib(21,rowHeight+21, page1),
|
|
||||||
size:11,
|
|
||||||
color:rgb(0,0,0),
|
|
||||||
lineHeight:11,
|
|
||||||
opacity: 1,
|
|
||||||
maxWidth: 240,
|
|
||||||
font: fontBold
|
|
||||||
})
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawText(invoiceData.total.totalGrossAlreadyPaid, {
|
|
||||||
y: getCoordinatesForPDFLib(21,rowHeight+21,page1).y,
|
|
||||||
x: getCoordinatesForPDFLib(21,rowHeight+21,page1).x + 500 - fontBold.widthOfTextAtSize(invoiceData.total.totalGrossAlreadyPaid,11),
|
|
||||||
size:11,
|
|
||||||
color:rgb(0,0,0),
|
|
||||||
lineHeight:11,
|
|
||||||
opacity: 1,
|
|
||||||
maxWidth: 240,
|
|
||||||
font:fontBold
|
|
||||||
})
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawRectangle({
|
|
||||||
...getCoordinatesForPDFLib(20,rowHeight +32, page1),
|
|
||||||
width: 180 * 2.83,
|
|
||||||
height: 8 * 2.83,
|
|
||||||
color: rgb(0,0,0),
|
|
||||||
opacity: 0.25
|
|
||||||
})
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawText("Offene Summe:", {
|
|
||||||
...getCoordinatesForPDFLib(21,rowHeight+29, page1),
|
|
||||||
size:11,
|
|
||||||
color:rgb(0,0,0),
|
|
||||||
lineHeight:11,
|
|
||||||
opacity: 1,
|
|
||||||
maxWidth: 240,
|
|
||||||
font: fontBold
|
|
||||||
})
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawText(invoiceData.total.totalSumToPay, {
|
|
||||||
y: getCoordinatesForPDFLib(21,rowHeight+29,page1).y,
|
|
||||||
x: getCoordinatesForPDFLib(21,rowHeight+29,page1).x + 500 - fontBold.widthOfTextAtSize(invoiceData.total.totalSumToPay,11),
|
|
||||||
size:11,
|
|
||||||
color:rgb(0,0,0),
|
|
||||||
lineHeight:11,
|
|
||||||
opacity: 1,
|
|
||||||
maxWidth: 240,
|
|
||||||
font:fontBold
|
|
||||||
})
|
|
||||||
|
|
||||||
invoiceData.usedAdvanceInvoices.forEach((advanceInvoice,index) => {
|
|
||||||
//For Each Advance Invoice
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawText(String(advanceInvoice.documentNumber), {
|
|
||||||
...getCoordinatesForPDFLib(21,rowHeight+36+5*index, page1),
|
|
||||||
size:11,
|
|
||||||
color:rgb(0,0,0),
|
|
||||||
lineHeight:11,
|
|
||||||
opacity: 1,
|
|
||||||
maxWidth: 240
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
endTextDiff = 22
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pages[pageCounter - 1].drawText(invoiceData.endText,{
|
pages[pageCounter - 1].drawText(invoiceData.endText,{
|
||||||
...getCoordinatesForPDFLib(20,rowHeight+endTextDiff, page1),
|
...getCoordinatesForPDFLib(20,rowHeight+22, page1),
|
||||||
size: 10,
|
size: 10,
|
||||||
color: rgb(0,0,0),
|
color: rgb(0,0,0),
|
||||||
lineHeight: 10,
|
lineHeight: 10,
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
/*const rights2 = ref({
|
|
||||||
projects: {
|
|
||||||
label: "Projekte",
|
|
||||||
children: {
|
|
||||||
viewOwnProjects: {label: "Eigene Projekte sehen"},
|
|
||||||
viewAllProjects: {label: "Alle Projekte sehen"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createUser: {label: "Benutzer erstellen"},
|
|
||||||
modifyUser: {label: "Benutzer bearbeiten"},
|
|
||||||
deactivateUser: {label: "Benutzer sperren"},
|
|
||||||
createProject: {label: "Projekt erstellen"},
|
|
||||||
|
|
||||||
createTask: {label: "Aufgabe erstellen"},
|
|
||||||
viewOwnTasks: {label:"Eigene Aufgaben sehen"},
|
|
||||||
viewAllTasks: {label: "Alle Aufgaben sehen"},
|
|
||||||
trackOwnTime: {label:"Eigene Zeite erfassen"},
|
|
||||||
createOwnTime: {label:"Eigene Zeiten erstellen"},
|
|
||||||
createTime: {label:"Zeiten erstellen"},
|
|
||||||
viewOwnTimes: {label:"Eigene Zeiten anzeigen"},
|
|
||||||
viewTimes: {label:"Zeiten anzeigen"},
|
|
||||||
})*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useRole = () => {
|
|
||||||
const supabase = useSupabaseClient()
|
|
||||||
const dataStore = useDataStore()
|
|
||||||
|
|
||||||
|
|
||||||
const rights = ref({
|
|
||||||
projects: {
|
|
||||||
label: "Projekte"
|
|
||||||
},
|
|
||||||
"projects-viewAll": {
|
|
||||||
label: "Alle Projekte einsehen",
|
|
||||||
parent: "projects"
|
|
||||||
},
|
|
||||||
"projects-viewOwn": {
|
|
||||||
label: "Eigene Projekte einsehen",
|
|
||||||
parent: "projects"
|
|
||||||
},
|
|
||||||
"projects-create": {
|
|
||||||
label: "Projekte erstellen",
|
|
||||||
parent: "projects"
|
|
||||||
},
|
|
||||||
contracts: {
|
|
||||||
label: "Verträge"
|
|
||||||
},
|
|
||||||
objects: {
|
|
||||||
label: "Objekte"
|
|
||||||
},
|
|
||||||
checks: {
|
|
||||||
label: "Überprüfungen"
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
let role = dataStore.activeProfile.role
|
|
||||||
|
|
||||||
/*const checkRight = (right) => {
|
|
||||||
let rightsToCheck = [right]
|
|
||||||
|
|
||||||
if(rights.value[right].parent) {
|
|
||||||
rightsToCheck.push(rights.value[right].parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
let hasAllNeccessaryRights = false
|
|
||||||
|
|
||||||
rightsToCheck.forEach(i => {
|
|
||||||
if(role.rights.includes(i)){
|
|
||||||
hasAllNeccessaryRights = true
|
|
||||||
} else {
|
|
||||||
hasAllNeccessaryRights = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return hasAllNeccessaryRights
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const checkRight = (right) => {
|
|
||||||
let rightsToCheck = [right]
|
|
||||||
|
|
||||||
//console.log(right.split("-"))
|
|
||||||
|
|
||||||
if(right.split("-").length > 1) {
|
|
||||||
rightsToCheck.push(right.split("-")[0])
|
|
||||||
}
|
|
||||||
//console.log(rightsToCheck)
|
|
||||||
|
|
||||||
let hasAllNeccessaryRights = true
|
|
||||||
|
|
||||||
//console.log(role.rights)
|
|
||||||
|
|
||||||
rightsToCheck.forEach(i => {
|
|
||||||
if(!role.rights.includes(i)){
|
|
||||||
hasAllNeccessaryRights = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
//console.log(hasAllNeccessaryRights)
|
|
||||||
|
|
||||||
return hasAllNeccessaryRights
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
role,
|
|
||||||
checkRight
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -33,12 +33,14 @@ export const useSupabaseSelectDocuments = async (select = '*', sortColumn = null
|
|||||||
.from("documents")
|
.from("documents")
|
||||||
.select(select)
|
.select(select)
|
||||||
.eq("tenant", dataStore.currentTenant)
|
.eq("tenant", dataStore.currentTenant)
|
||||||
|
.eq("folderPath", folderPath)
|
||||||
.order(sortColumn, {ascending: true})).data
|
.order(sortColumn, {ascending: true})).data
|
||||||
} else {
|
} else {
|
||||||
data = (await supabase
|
data = (await supabase
|
||||||
.from("documents")
|
.from("documents")
|
||||||
.select(select)
|
.select(select)
|
||||||
.eq("tenant", dataStore.currentTenant)).data
|
.eq("tenant", dataStore.currentTenant)
|
||||||
|
.eq("folderPath",folderPath)).data
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,7 @@ const itemInfo = ref({
|
|||||||
dateDirection: "Rückwirkend",
|
dateDirection: "Rückwirkend",
|
||||||
},
|
},
|
||||||
letterhead: null,
|
letterhead: null,
|
||||||
agriculture: {},
|
agriculture: {}
|
||||||
usedAdvanceInvoices: []
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -72,10 +71,7 @@ const selectedProductcategorie = ref(null)
|
|||||||
const services = ref([])
|
const services = ref([])
|
||||||
const servicecategories = ref([])
|
const servicecategories = ref([])
|
||||||
const selectedServicecategorie = ref(null)
|
const selectedServicecategorie = ref(null)
|
||||||
const customers = ref([])
|
|
||||||
const contacts = ref([])
|
|
||||||
|
|
||||||
const loaded = ref(false)
|
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
|
|
||||||
letterheads.value = (await useSupabaseSelect("letterheads","*")).filter(i => i.documentTypes.length === 0 || i.documentTypes.includes(itemInfo.value.type))
|
letterheads.value = (await useSupabaseSelect("letterheads","*")).filter(i => i.documentTypes.length === 0 || i.documentTypes.includes(itemInfo.value.type))
|
||||||
@@ -85,8 +81,6 @@ const setupPage = async () => {
|
|||||||
servicecategories.value = (await useSupabaseSelect("servicecategories","*"))
|
servicecategories.value = (await useSupabaseSelect("servicecategories","*"))
|
||||||
products.value = (await useSupabaseSelect("products","*"))
|
products.value = (await useSupabaseSelect("products","*"))
|
||||||
productcategories.value = (await useSupabaseSelect("productcategories","*"))
|
productcategories.value = (await useSupabaseSelect("productcategories","*"))
|
||||||
customers.value = (await useSupabaseSelect("customers","*","customerNumber"))
|
|
||||||
contacts.value = (await useSupabaseSelect("contacts","*"))
|
|
||||||
if(productcategories.value.length > 0) selectedProductcategorie.value = productcategories.value[0].id
|
if(productcategories.value.length > 0) selectedProductcategorie.value = productcategories.value[0].id
|
||||||
if(servicecategories.value.length > 0) selectedServicecategorie.value = servicecategories.value[0].id
|
if(servicecategories.value.length > 0) selectedServicecategorie.value = servicecategories.value[0].id
|
||||||
|
|
||||||
@@ -171,33 +165,13 @@ const setupPage = async () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(route.query.project) {
|
if(route.query.project) itemInfo.value.project = Number(route.query.project)
|
||||||
itemInfo.value.project = Number(route.query.project)
|
|
||||||
checkForOpenAdvanceInvoices()
|
|
||||||
}
|
|
||||||
if(route.query.contact) itemInfo.value.contact = Number(route.query.contact)
|
if(route.query.contact) itemInfo.value.contact = Number(route.query.contact)
|
||||||
if(route.query.customer) {
|
if(route.query.customer) {
|
||||||
itemInfo.value.customer = Number(route.query.customer)
|
itemInfo.value.customer = Number(route.query.customer)
|
||||||
setCustomerData()
|
setCustomerData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded.value = true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const openAdvanceInvoices = ref([])
|
|
||||||
const checkForOpenAdvanceInvoices = async () => {
|
|
||||||
const {data,error} = await supabase.from("createddocuments").select().eq("project", itemInfo.value.project).eq("advanceInvoiceResolved", false).eq("type","advanceInvoices")
|
|
||||||
|
|
||||||
console.log(data)
|
|
||||||
|
|
||||||
openAdvanceInvoices.value = data
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const addAdvanceInvoiceToInvoice = (advanceInvoice) => {
|
|
||||||
itemInfo.value.usedAdvanceInvoices.push(advanceInvoice)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const setDocumentTypeConfig = (withTexts = false) => {
|
const setDocumentTypeConfig = (withTexts = false) => {
|
||||||
@@ -227,6 +201,7 @@ const setDocumentTypeConfig = (withTexts = false) => {
|
|||||||
|
|
||||||
const setCustomerData = () => {
|
const setCustomerData = () => {
|
||||||
|
|
||||||
|
|
||||||
let customer = dataStore.getCustomerById(itemInfo.value.customer)
|
let customer = dataStore.getCustomerById(itemInfo.value.customer)
|
||||||
itemInfo.value.contact = null
|
itemInfo.value.contact = null
|
||||||
if(customer) {
|
if(customer) {
|
||||||
@@ -235,8 +210,6 @@ const setCustomerData = () => {
|
|||||||
itemInfo.value.address.city = customer.infoData.city
|
itemInfo.value.address.city = customer.infoData.city
|
||||||
itemInfo.value.address.special = customer.infoData.special
|
itemInfo.value.address.special = customer.infoData.special
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const setContactPersonData = async () => {
|
const setContactPersonData = async () => {
|
||||||
@@ -283,6 +256,8 @@ const importPositions = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getRowAmount = (row) => {
|
const getRowAmount = (row) => {
|
||||||
return String(Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(2)).replace('.',',')
|
return String(Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(2)).replace('.',',')
|
||||||
}
|
}
|
||||||
@@ -357,6 +332,13 @@ const addPosition = (mode) => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const showEditRowDescription = ref(false)
|
||||||
|
const rowToEdit = ref("")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const removePosition = (id) => {
|
const removePosition = (id) => {
|
||||||
let rows = itemInfo.value.rows.filter(row => row.id !== id)
|
let rows = itemInfo.value.rows.filter(row => row.id !== id)
|
||||||
/*rows = rows.sort((a,b) => a.pos - b.pos)
|
/*rows = rows.sort((a,b) => a.pos - b.pos)
|
||||||
@@ -371,15 +353,6 @@ const removePosition = (id) => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRowMargin = (row) => {
|
|
||||||
if(row.mode === "normal" && row.product) {
|
|
||||||
let purchasePrice = dataStore.getProductById(row.product).purchasePrice || 0
|
|
||||||
return row.price - purchasePrice
|
|
||||||
} else {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const findDocumentErrors = computed(() => {
|
const findDocumentErrors = computed(() => {
|
||||||
let errors = []
|
let errors = []
|
||||||
|
|
||||||
@@ -432,7 +405,6 @@ const tabItems = computed(() => {
|
|||||||
const renderCurrency = (value, currency = "€") => {
|
const renderCurrency = (value, currency = "€") => {
|
||||||
return Number(value).toFixed(2).replace(".",",") + " €"
|
return Number(value).toFixed(2).replace(".",",") + " €"
|
||||||
}
|
}
|
||||||
|
|
||||||
const documentTotal = computed(() => {
|
const documentTotal = computed(() => {
|
||||||
let totalNet = 0
|
let totalNet = 0
|
||||||
let total19 = 0
|
let total19 = 0
|
||||||
@@ -440,7 +412,7 @@ const documentTotal = computed(() => {
|
|||||||
|
|
||||||
itemInfo.value.rows.forEach(row => {
|
itemInfo.value.rows.forEach(row => {
|
||||||
if(!['pagebreak','title','text'].includes(row.mode)){
|
if(!['pagebreak','title','text'].includes(row.mode)){
|
||||||
let rowPrice = Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(3)
|
let rowPrice = Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(2)
|
||||||
totalNet = totalNet + Number(rowPrice)
|
totalNet = totalNet + Number(rowPrice)
|
||||||
|
|
||||||
if(row.taxPercent === 19) {
|
if(row.taxPercent === 19) {
|
||||||
@@ -449,33 +421,11 @@ const documentTotal = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
totalGross = totalNet + total19
|
|
||||||
|
|
||||||
let totalGrossAlreadyPaid = 0
|
|
||||||
|
|
||||||
itemInfo.value.usedAdvanceInvoices.forEach(advanceInvoiceId => {
|
|
||||||
let advanceInvoice = openAdvanceInvoices.value.find(i => i.id === advanceInvoiceId)
|
|
||||||
|
|
||||||
let priceNet = advanceInvoice.rows.find(i => i.advanceInvoiceData).price
|
|
||||||
|
|
||||||
let partSum = priceNet * ((100 + advanceInvoice.rows.find(i => i.advanceInvoiceData).taxPercent) / 100)
|
|
||||||
|
|
||||||
totalGrossAlreadyPaid += partSum
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(totalGrossAlreadyPaid)
|
|
||||||
|
|
||||||
let sumToPay = totalGross - totalGrossAlreadyPaid
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalNet: `${String(totalNet.toFixed(2)).replace(".",",")} €`,
|
totalNet: `${String(totalNet.toFixed(2)).replace(".",",")} €`,
|
||||||
total19: `${String(total19.toFixed(2)).replace(".",",")} €`,
|
total19: `${String(total19.toFixed(2)).replace(".",",")} €`,
|
||||||
totalGross: renderCurrency(totalGross),
|
totalGross: `${String(Number(totalNet + total19).toFixed(2)).replace(".",",")} €`
|
||||||
totalGrossAlreadyPaid: renderCurrency(totalGrossAlreadyPaid),
|
|
||||||
totalSumToPay: renderCurrency(sumToPay)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -526,6 +476,7 @@ const processDieselPosition = () => {
|
|||||||
itemInfo.value.agriculture = {...itemInfo.value.agriculture, ...agricultureData}
|
itemInfo.value.agriculture = {...itemInfo.value.agriculture, ...agricultureData}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const getDocumentData = () => {
|
const getDocumentData = () => {
|
||||||
|
|
||||||
let customerData = dataStore.getCustomerById(itemInfo.value.customer)
|
let customerData = dataStore.getCustomerById(itemInfo.value.customer)
|
||||||
@@ -581,7 +532,6 @@ const getDocumentData = () => {
|
|||||||
return {
|
return {
|
||||||
vorname:contactData && contactData.firstName,
|
vorname:contactData && contactData.firstName,
|
||||||
nachname: contactData && contactData.lastName,
|
nachname: contactData && contactData.lastName,
|
||||||
kundenname: customerData && customerData.name,
|
|
||||||
zahlungsziel_in_tagen:itemInfo.paymentDays,
|
zahlungsziel_in_tagen:itemInfo.paymentDays,
|
||||||
diesel_gesamtverbrauch: (itemInfo.agriculture && itemInfo.agriculture.dieselUsageTotal) && itemInfo.agriculture.dieselUsageTotal
|
diesel_gesamtverbrauch: (itemInfo.agriculture && itemInfo.agriculture.dieselUsageTotal) && itemInfo.agriculture.dieselUsageTotal
|
||||||
}
|
}
|
||||||
@@ -616,10 +566,7 @@ const getDocumentData = () => {
|
|||||||
startText: templateStartText(generateContext(itemInfo.value, contactData)),
|
startText: templateStartText(generateContext(itemInfo.value, contactData)),
|
||||||
rows: rows,
|
rows: rows,
|
||||||
total: documentTotal.value,
|
total: documentTotal.value,
|
||||||
agriculture: itemInfo.value.agriculture,
|
agriculture: itemInfo.value.agriculture
|
||||||
usedAdvanceInvoices: itemInfo.value.usedAdvanceInvoices.map(i => {
|
|
||||||
return openAdvanceInvoices.value.find(x => x.id === i)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(returnData)
|
//console.log(returnData)
|
||||||
@@ -627,6 +574,7 @@ const getDocumentData = () => {
|
|||||||
return returnData
|
return returnData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const showDocument = ref(false)
|
const showDocument = ref(false)
|
||||||
const uri = ref("")
|
const uri = ref("")
|
||||||
const generateDocument = async () => {
|
const generateDocument = async () => {
|
||||||
@@ -764,8 +712,7 @@ const saveDocument = async (state) => {
|
|||||||
contactPerson: itemInfo.value.contactPerson,
|
contactPerson: itemInfo.value.contactPerson,
|
||||||
linkedDocument: itemInfo.value.linkedDocument,
|
linkedDocument: itemInfo.value.linkedDocument,
|
||||||
agriculture: itemInfo.value.agriculture,
|
agriculture: itemInfo.value.agriculture,
|
||||||
letterhead: itemInfo.value.letterhead,
|
letterhead: itemInfo.value.letterhead
|
||||||
usedAdvanceInvoices: itemInfo.value.usedAdvanceInvoices
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(route.params.id) {
|
if(route.params.id) {
|
||||||
@@ -849,7 +796,7 @@ setupPage()
|
|||||||
</UDashboardNavbar>
|
</UDashboardNavbar>
|
||||||
|
|
||||||
<UDashboardPanelContent>
|
<UDashboardPanelContent>
|
||||||
<UTabs class="p-5" :items="tabItems" @change="onChangeTab" v-if="loaded">
|
<UTabs class="p-5" :items="tabItems" @change="onChangeTab">
|
||||||
<template #item="{item}">
|
<template #item="{item}">
|
||||||
|
|
||||||
|
|
||||||
@@ -993,9 +940,11 @@ setupPage()
|
|||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="Kunde:"
|
label="Kunde:"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row">
|
<InputGroup
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
:options="customers"
|
:options="dataStore.customers"
|
||||||
option-attribute="name"
|
option-attribute="name"
|
||||||
value-attribute="id"
|
value-attribute="id"
|
||||||
:search-attributes="['name']"
|
:search-attributes="['name']"
|
||||||
@@ -1003,15 +952,14 @@ setupPage()
|
|||||||
searchable-placeholder="Suche..."
|
searchable-placeholder="Suche..."
|
||||||
v-model="itemInfo.customer"
|
v-model="itemInfo.customer"
|
||||||
@change="setCustomerData"
|
@change="setCustomerData"
|
||||||
class="flex-auto mr-2"
|
class="flex-auto"
|
||||||
>
|
>
|
||||||
<UButton
|
<UButton
|
||||||
:color="itemInfo.customer ? 'primary' : 'rose'"
|
:color="itemInfo.customer ? 'primary' : 'rose'"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="w-full"
|
class="w-full">
|
||||||
>
|
<span class="truncate">{{dataStore.getCustomerById(itemInfo.customer) ? dataStore.getCustomerById(itemInfo.customer).name : "Kein Kunde ausgewählt"}}</span>
|
||||||
<!-- <span class="truncate text-left">{{dataStore.getCustomerById(itemInfo.customer) ? dataStore.getCustomerById(itemInfo.customer).name : "Kein Kunde ausgewählt"}}</span>-->
|
|
||||||
{{dataStore.getCustomerById(itemInfo.customer) ? dataStore.getCustomerById(itemInfo.customer).name : "Kein Kunde ausgewählt"}}
|
|
||||||
|
|
||||||
<UIcon name="i-heroicons-chevron-right-20-solid" class="w-5 h-5 transition-transform text-gray-400 dark:text-gray-500" :class="['transform rotate-90']" />
|
<UIcon name="i-heroicons-chevron-right-20-solid" class="w-5 h-5 transition-transform text-gray-400 dark:text-gray-500" :class="['transform rotate-90']" />
|
||||||
</UButton>
|
</UButton>
|
||||||
@@ -1021,14 +969,11 @@ setupPage()
|
|||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
<UButton
|
<UButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="w-25"
|
|
||||||
v-if="itemInfo.customer"
|
v-if="itemInfo.customer"
|
||||||
icon="i-heroicons-arrow-right-end-on-rectangle"
|
icon="i-heroicons-arrow-right-end-on-rectangle"
|
||||||
@click="router.push(`/customers/show/${itemInfo.customer}`)"
|
@click="router.push(`/customers/show/${itemInfo.customer}`)"
|
||||||
>Kunde</UButton>
|
>Kunde</UButton>
|
||||||
</div>
|
</InputGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<UAlert
|
<UAlert
|
||||||
v-if="itemInfo.customer"
|
v-if="itemInfo.customer"
|
||||||
@@ -1052,7 +997,7 @@ setupPage()
|
|||||||
>
|
>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
:options="contacts.filter(i => i.customer === itemInfo.customer)"
|
:options="dataStore.getContactsByCustomerId(itemInfo.customer)"
|
||||||
option-attribute="fullName"
|
option-attribute="fullName"
|
||||||
value-attribute="id"
|
value-attribute="id"
|
||||||
:search-attributes="['name']"
|
:search-attributes="['name']"
|
||||||
@@ -1176,13 +1121,9 @@ setupPage()
|
|||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
class="w-full"
|
label="Zahlungziel in Tagen:"
|
||||||
|
class="flex-auto"
|
||||||
>
|
>
|
||||||
<template #label>
|
|
||||||
<span class="truncate">
|
|
||||||
Zahlungsziel in Tagen:
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<UInput
|
<UInput
|
||||||
type="number"
|
type="number"
|
||||||
v-model="itemInfo.paymentDays"
|
v-model="itemInfo.paymentDays"
|
||||||
@@ -1228,7 +1169,6 @@ setupPage()
|
|||||||
:search-attributes="['name']"
|
:search-attributes="['name']"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:disabled="!itemInfo.customer"
|
:disabled="!itemInfo.customer"
|
||||||
@change="checkForOpenAdvanceInvoices"
|
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
||||||
@@ -1330,6 +1270,9 @@ setupPage()
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<UDivider
|
<UDivider
|
||||||
class="my-3"
|
class="my-3"
|
||||||
/>
|
/>
|
||||||
@@ -1446,7 +1389,6 @@ setupPage()
|
|||||||
<UInput
|
<UInput
|
||||||
v-model="row.text"
|
v-model="row.text"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
class="min-w-40"
|
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
@@ -1616,8 +1558,7 @@ setupPage()
|
|||||||
<UInput
|
<UInput
|
||||||
v-model="row.price"
|
v-model="row.price"
|
||||||
type="number"
|
type="number"
|
||||||
step="0.001"
|
step="0.01"
|
||||||
:color="getRowMargin(row) > 0 ? 'primary' : 'rose'"
|
|
||||||
>
|
>
|
||||||
<template #trailing>
|
<template #trailing>
|
||||||
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
||||||
@@ -1774,21 +1715,18 @@ setupPage()
|
|||||||
<UButton
|
<UButton
|
||||||
@click="addPosition('service')"
|
@click="addPosition('service')"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
:disabled="itemInfo.type === 'advanceInvoices'"
|
|
||||||
>
|
>
|
||||||
+ Leistung
|
+ Leistung
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
@click="addPosition('normal')"
|
@click="addPosition('normal')"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
:disabled="itemInfo.type === 'advanceInvoices'"
|
|
||||||
>
|
>
|
||||||
+ Artikel
|
+ Artikel
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
@click="addPosition('free')"
|
@click="addPosition('free')"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
:disabled="itemInfo.type === 'advanceInvoices'"
|
|
||||||
>
|
>
|
||||||
+ Freie Position
|
+ Freie Position
|
||||||
</UButton>
|
</UButton>
|
||||||
@@ -1812,44 +1750,6 @@ setupPage()
|
|||||||
</UButton>
|
</UButton>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
|
||||||
<UDivider
|
|
||||||
class="mt-5 mb-3"
|
|
||||||
v-if="openAdvanceInvoices.length > 0"
|
|
||||||
>
|
|
||||||
Noch nicht abgerechnete Abschlagsrechnungen
|
|
||||||
</UDivider>
|
|
||||||
|
|
||||||
<!-- Abzurechnende Abschlagsrechnungen -->
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="advanceInvoice in openAdvanceInvoices"
|
|
||||||
:key="advanceInvoice.id"
|
|
||||||
class="flex flex-row justify-between my-2"
|
|
||||||
>
|
|
||||||
<span>{{advanceInvoice.documentNumber}}</span>
|
|
||||||
<span>Summe: {{renderCurrency(advanceInvoice.rows[0].price * (1 + advanceInvoice.rows[0].taxPercent/100))}}</span>
|
|
||||||
<InputGroup>
|
|
||||||
<UButton
|
|
||||||
@click="addAdvanceInvoiceToInvoice(advanceInvoice.id)"
|
|
||||||
:disabled="itemInfo.usedAdvanceInvoices.includes(advanceInvoice.id)"
|
|
||||||
class="mr-2"
|
|
||||||
>
|
|
||||||
Verwenden
|
|
||||||
</UButton>
|
|
||||||
<UButton
|
|
||||||
@click="itemInfo.usedAdvanceInvoices = itemInfo.usedAdvanceInvoices.filter(i => i !== advanceInvoice.id)"
|
|
||||||
:disabled="!itemInfo.usedAdvanceInvoices.includes(advanceInvoice.id)"
|
|
||||||
color="rose"
|
|
||||||
variant="outline"
|
|
||||||
>
|
|
||||||
X
|
|
||||||
</UButton>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<UDivider class="my-3" v-if="itemInfo.rows.length > 0"/>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="w-full flex justify-end" v-if="itemInfo.type !== 'deliveryNotes'">
|
<div class="w-full flex justify-end" v-if="itemInfo.type !== 'deliveryNotes'">
|
||||||
<table class="w-1/3" v-if="itemInfo.rows.length > 0">
|
<table class="w-1/3" v-if="itemInfo.rows.length > 0">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -1864,19 +1764,6 @@ setupPage()
|
|||||||
<td class="font-bold">Brutto:</td>
|
<td class="font-bold">Brutto:</td>
|
||||||
<td class="text-right">{{documentTotal.totalGross}}</td>
|
<td class="text-right">{{documentTotal.totalGross}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr v-if="documentTotal.totalGrossAlreadyPaid !== '0,00 €'">
|
|
||||||
<td class="font-bold">Bereits bezahlt:</td>
|
|
||||||
<td class="text-right">{{documentTotal.totalGrossAlreadyPaid}}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<tr v-if="documentTotal.totalGrossAlreadyPaid !== '0,00 €'">
|
|
||||||
<td class="font-bold">Offene Summe:</td>
|
|
||||||
<td class="text-right">{{documentTotal.totalSumToPay}}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1928,7 +1815,6 @@ setupPage()
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</UTabs>
|
</UTabs>
|
||||||
<UProgress animation="carousel" v-else/>
|
|
||||||
</UDashboardPanelContent>
|
</UDashboardPanelContent>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
|
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
|
||||||
import {useSupabaseSelectDocuments, useSupabaseSelectSingle} from "~/composables/useSupabase.js";
|
import {useSupabaseSelectDocuments} from "~/composables/useSupabase.js";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
@@ -11,8 +11,6 @@ const dataStore = useDataStore()
|
|||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
const user = useSupabaseUser()
|
const user = useSupabaseUser()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const router = useRouter()
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
dataStore.fetchDocuments()
|
dataStore.fetchDocuments()
|
||||||
|
|
||||||
@@ -21,31 +19,29 @@ const uploadInProgress = ref(false)
|
|||||||
const fileUploadFormData = ref({
|
const fileUploadFormData = ref({
|
||||||
tags: ["Eingang"],
|
tags: ["Eingang"],
|
||||||
path: "",
|
path: "",
|
||||||
tenant: dataStore.currentTenant,
|
tenant: dataStore.currentTenant
|
||||||
folder: null
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
let tags = dataStore.getDocumentTags
|
let tags = dataStore.getDocumentTags
|
||||||
|
|
||||||
|
const selectedTags = ref("Eingang")
|
||||||
const documents = ref([])
|
const documents = ref([])
|
||||||
const folders = ref([])
|
const folders = ref([])
|
||||||
|
const selectedPath = ref("_")
|
||||||
const currentFolder = ref(null)
|
|
||||||
|
|
||||||
const loadingDocs = ref(false)
|
const loadingDocs = ref(false)
|
||||||
const isDragTarget = ref(false)
|
const isDragTarget = ref(false)
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
folders.value = await useSupabaseSelect("folders")
|
//documents.value = await useSupabaseSelectDocuments("*, project(id,name), customer(id,name), contract(id,name), vendor(id,name), plant(id,name), vehicle(id,licensePlate), product(id,name), profile(id,fullName) ")
|
||||||
|
//documents.value = await useSupabaseSelectDocuments("*",null, selectedPath.value)
|
||||||
|
//console.log(documents.value)
|
||||||
|
|
||||||
documents.value = await useSupabaseSelectDocuments("*",null)
|
folders.value = dataStore.ownTenant.documentFolders
|
||||||
|
|
||||||
if(route.query) {
|
documents.value = await useSupabaseSelectDocuments("*",null,selectedPath.value)
|
||||||
if(route.query.folder) {
|
//await supabase.from("documents").select().eq("folderPath",selectedPath.value).eq("tenant",dataStore.currentTenant)
|
||||||
console.log(route.query.folder)
|
|
||||||
currentFolder.value = await useSupabaseSelectSingle("folders", route.query.folder)
|
//console.log(await supabase.from("documents").select().eq("folderPath",selectedPath.value))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const dropZone = document.getElementById("drop_zone")
|
const dropZone = document.getElementById("drop_zone")
|
||||||
@@ -75,63 +71,37 @@ const setupPage = async () => {
|
|||||||
setupPage()
|
setupPage()
|
||||||
const currentFolders = computed(() => {
|
const currentFolders = computed(() => {
|
||||||
if(folders.value.length > 0) {
|
if(folders.value.length > 0) {
|
||||||
|
/*console.log(folders.value[0].path.split("/").filter(x => x.length > 0))
|
||||||
|
console.log(selectedPath.value.split("/").filter(x => x.length > 0))*/
|
||||||
|
|
||||||
let tempFolders = folders.value.filter(i => currentFolder.value ? i.parent === currentFolder.value.id : !i.parent)
|
let tempFolders = folders.value.filter(i => (i.path.split("_").filter(x => x.length > 0) || []).length === selectedPath.value.split("_").filter(x => x.length > 0).length + 1)
|
||||||
|
|
||||||
|
tempFolders = tempFolders.filter(i => i.path.includes(selectedPath.value))
|
||||||
|
|
||||||
return tempFolders
|
return tempFolders
|
||||||
} else return []
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const breadcrumbLinks = computed(() => {
|
const breadcrumbLinks = computed(() => {
|
||||||
|
return [{
|
||||||
if(currentFolder.value) {
|
label: "Home",
|
||||||
let parents = []
|
click: () => {
|
||||||
|
changePath("_")
|
||||||
const addParent = (parent) => {
|
|
||||||
parents.push(parent)
|
|
||||||
if(parent.parent) {
|
|
||||||
addParent(folders.value.find(i => i.id === currentFolder.value.parent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(currentFolder.value.parent) {
|
|
||||||
addParent(folders.value.find(i => i.id === currentFolder.value.parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
return [{
|
|
||||||
label: "Home",
|
|
||||||
click: () => {
|
|
||||||
changeFolder(null)
|
|
||||||
},
|
|
||||||
icon: "i-heroicons-folder"
|
|
||||||
},
|
},
|
||||||
...parents.map(i => {
|
icon: "i-heroicons-folder"
|
||||||
return {
|
},...selectedPath.value.split("_").filter(x => x.length > 0).map((i,index) => {
|
||||||
label: folders.value.find(x => x.id === i.id).name,
|
let re = new RegExp(".+?" + i )
|
||||||
click: () => {
|
let path = selectedPath.value.match(re)[0]
|
||||||
changeFolder(i)
|
|
||||||
},
|
|
||||||
icon: "i-heroicons-folder"
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
label: currentFolder.value.name,
|
|
||||||
click: () => {
|
|
||||||
changeFolder(currentFolder.value)
|
|
||||||
},
|
|
||||||
icon: "i-heroicons-folder"
|
|
||||||
}]
|
|
||||||
|
|
||||||
} else {
|
return {
|
||||||
return [{
|
label: folders.value.find(x => x.path === path).name ||path,
|
||||||
label: "Home",
|
|
||||||
click: () => {
|
click: () => {
|
||||||
changeFolder(null)
|
changePath(path)
|
||||||
},
|
},
|
||||||
icon: "i-heroicons-folder"
|
icon: "i-heroicons-folder"
|
||||||
}]
|
}
|
||||||
}
|
})]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -140,22 +110,23 @@ const breadcrumbLinks = computed(() => {
|
|||||||
|
|
||||||
const filteredDocuments = computed(() => {
|
const filteredDocuments = computed(() => {
|
||||||
|
|
||||||
return documents.value.filter(i => currentFolder.value ? i.folder === currentFolder.value.id : !i.folder)
|
/*if(selectedTags.value !== "Archiviert") {
|
||||||
|
return documents.value.filter(i => i.tags.find(t => selectedTags.value === t) && !i.tags.includes("Archiviert"))
|
||||||
|
} else {
|
||||||
|
return documents.value.filter(i => i.tags.find(t => selectedTags.value === t))
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return documents.value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const changeFolder = async (newFolder) => {
|
const changePath = async (newPath) => {
|
||||||
loadingDocs.value = true
|
loadingDocs.value = true
|
||||||
currentFolder.value = newFolder
|
selectedPath.value = newPath
|
||||||
|
|
||||||
if(newFolder) {
|
|
||||||
fileUploadFormData.value.folder = newFolder.id
|
|
||||||
await router.push(`/documents?folder=${newFolder.id}`)
|
|
||||||
} else {
|
|
||||||
fileUploadFormData.value.folder = null
|
|
||||||
await router.push(`/documents`)
|
|
||||||
}
|
|
||||||
|
|
||||||
setupPage()
|
setupPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +134,7 @@ const uploadFiles = async (files) => {
|
|||||||
uploadInProgress.value = true;
|
uploadInProgress.value = true;
|
||||||
|
|
||||||
if(files) {
|
if(files) {
|
||||||
await dataStore.uploadFiles({tags: ["Ablage"],tenant: dataStore.currentTenant,folder: currentFolder.value.id}, files, true)
|
await dataStore.uploadFiles({tags: ["Ablage"],tenant: dataStore.currentTenant, folderPath: selectedPath.value}, files, true)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
|
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
|
||||||
@@ -242,7 +213,7 @@ const downloadSelected = async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UDashboardNavbar
|
<UDashboardNavbar
|
||||||
title="Dateien"
|
title="Dokumente"
|
||||||
>
|
>
|
||||||
|
|
||||||
</UDashboardNavbar>
|
</UDashboardNavbar>
|
||||||
@@ -283,7 +254,7 @@ const downloadSelected = async () => {
|
|||||||
<a
|
<a
|
||||||
class="w-1/6 folderIcon flex flex-col p-5 m-2"
|
class="w-1/6 folderIcon flex flex-col p-5 m-2"
|
||||||
v-for="folder in currentFolders"
|
v-for="folder in currentFolders"
|
||||||
@click="changeFolder(folder)"
|
@click="changePath(folder.path)"
|
||||||
>
|
>
|
||||||
|
|
||||||
<UIcon
|
<UIcon
|
||||||
@@ -294,8 +265,8 @@ const downloadSelected = async () => {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<UDivider class="my-5" v-if="currentFolder">{{currentFolder.name}}</UDivider>
|
<UDivider class="my-5" v-if="currentFolders.length > 0">Dokumente</UDivider>
|
||||||
<UDivider class="my-5" v-else>Ablage</UDivider>
|
|
||||||
|
|
||||||
<div v-if="!loadingDocs">
|
<div v-if="!loadingDocs">
|
||||||
<DocumentList
|
<DocumentList
|
||||||
|
|||||||
@@ -43,9 +43,6 @@
|
|||||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||||
@select="(i) => router.push(`/inventoryitems/show/${i.id}`) "
|
@select="(i) => router.push(`/inventoryitems/show/${i.id}`) "
|
||||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Inventarartikel anzuzeigen' }"
|
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Inventarartikel anzuzeigen' }"
|
||||||
v-model:sort="sortConfig"
|
|
||||||
sort-mode="manual"
|
|
||||||
@update:sort="setupPage"
|
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
@@ -53,8 +50,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {sort} from "fast-sort"
|
|
||||||
|
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
@@ -75,13 +70,8 @@ const dataStore = useDataStore()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const items = ref([])
|
const items = ref([])
|
||||||
|
|
||||||
const sortConfig = ref({
|
|
||||||
column: "articleNumber",
|
|
||||||
direction: "desc"
|
|
||||||
})
|
|
||||||
|
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
items.value = await useSupabaseSelect("inventoryitems","*")
|
items.value = await useSupabaseSelect("inventoryitems","*", "articleNumber")
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPage()
|
setupPage()
|
||||||
@@ -106,20 +96,17 @@ const selectedColumns = ref(templateColumns)
|
|||||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const searchString = ref('')
|
const searchString = ref('')
|
||||||
const filteredRows = computed(() => {
|
const filteredRows = computed(() => {
|
||||||
|
if(!searchString.value) {
|
||||||
let sorted = []
|
return items.value
|
||||||
|
|
||||||
if(sortConfig.value.direction === "asc"){
|
|
||||||
sorted = sort(items.value).asc(i => i[sortConfig.value.column])
|
|
||||||
} else {
|
|
||||||
sorted = sort(items.value).desc(i => i[sortConfig.value.column])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return useListFilter(searchString.value, sorted)
|
return items.value.filter(product => {
|
||||||
|
return Object.values(product).some((value) => {
|
||||||
|
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ setupPage()
|
|||||||
<UInput
|
<UInput
|
||||||
v-model="itemInfo.sellingPrice"
|
v-model="itemInfo.sellingPrice"
|
||||||
type="number"
|
type="number"
|
||||||
steps="0.001"
|
steps="0.01"
|
||||||
>
|
>
|
||||||
<template #trailing>
|
<template #trailing>
|
||||||
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
|
|
||||||
const lexofficeActiveFunctions = ref({
|
|
||||||
sendInvoicesToLexoffice: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<UDashboardNavbar title="Integrationen"></UDashboardNavbar>
|
|
||||||
<UDashboardPanelContent>
|
|
||||||
<UAccordion
|
|
||||||
class="p-5"
|
|
||||||
color="primary"
|
|
||||||
variant="soft"
|
|
||||||
size="sm"
|
|
||||||
:items="[{ label: 'Lexoffice', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit' }]"
|
|
||||||
>
|
|
||||||
<template #item="{item}">
|
|
||||||
<div v-if="item.label === 'Lexoffice'">
|
|
||||||
Scopes:
|
|
||||||
<UCheckbox v-model="lexofficeActiveFunctions.sendInvoicesToLexoffice" name="notifications" label="Rechnungen an Lexoffice übertragen" />
|
|
||||||
|
|
||||||
<UButton>
|
|
||||||
Kunden importieren
|
|
||||||
</UButton>
|
|
||||||
<UButton>
|
|
||||||
Lieferanten importieren
|
|
||||||
</UButton>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</UAccordion>
|
|
||||||
</UDashboardPanelContent>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -48,9 +48,9 @@ const projects = ref([])
|
|||||||
//Functions
|
//Functions
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
if(mode.value === "show" ){
|
if(mode.value === "show" ){
|
||||||
itemInfo.value = await useSupabaseSelectSingle("trackingtripsgen",route.params.id,"*, trackingDevice(*, vehicle(*))")
|
itemInfo.value = await useSupabaseSelectSingle("trackingtrips",route.params.id,"*, trackingDevice(*, vehicle(*))")
|
||||||
} else if(mode.value === "edit") {
|
} else if(mode.value === "edit") {
|
||||||
itemInfo.value = await useSupabaseSelectSingle("trackingtripsgen",route.params.id,"*")
|
itemInfo.value = await useSupabaseSelectSingle("trackingtrips",route.params.id,"*")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +141,8 @@ const zoom = ref(6)
|
|||||||
</template>
|
</template>
|
||||||
</UDashboardNavbar>
|
</UDashboardNavbar>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<UTabs
|
<UTabs
|
||||||
:items="[{label: 'Informationen'}]"
|
:items="[{label: 'Informationen'}]"
|
||||||
v-if="mode === 'show' && itemInfo.id"
|
v-if="mode === 'show' && itemInfo.id"
|
||||||
@@ -190,9 +192,9 @@ const zoom = ref(6)
|
|||||||
|
|
||||||
</UCard>
|
</UCard>
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Map :markers="[[itemInfo.startLat, itemInfo.startLon],[itemInfo.endLat, itemInfo.endLon]]"
|
<Map :markers="[[itemInfo.startLatitude, itemInfo.startLongitude],[itemInfo.endLatitude, itemInfo.endLongitude]]"
|
||||||
:startMarker="[itemInfo.startLat, itemInfo.startLon]"
|
:startMarker="[itemInfo.startLatitude, itemInfo.startLongitude]"
|
||||||
:endMarker="[itemInfo.endLat, itemInfo.endLon]"
|
:endMarker="[itemInfo.endLatitude, itemInfo.endLongitude]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,12 +57,8 @@
|
|||||||
<template #endTime-data="{row}">
|
<template #endTime-data="{row}">
|
||||||
{{dayjs(row.endTime).format("DD.MM.YY HH:mm")}}
|
{{dayjs(row.endTime).format("DD.MM.YY HH:mm")}}
|
||||||
</template>
|
</template>
|
||||||
<template #gpsDistance-data="{row}">
|
<template #distance-data="{row}">
|
||||||
{{row.gpsDistance > 0 ? (row.gpsDistance/1000).toFixed(2) : 0 }} km
|
{{row.distance > 0 ? (row.distance/1000).toFixed(2) : 0 }} km
|
||||||
</template>
|
|
||||||
<template #usedFuel-data="{row}">
|
|
||||||
<span v-if="row.endFuelLevel - row.startFuelLevel < 0">{{row.endFuelLevel - row.startFuelLevel}} / {{(row.vehicle.tankSize / 100 * Math.abs(row.endFuelLevel - row.startFuelLevel)).toFixed(2)}}</span>
|
|
||||||
<span v-else>0</span>
|
|
||||||
</template>
|
</template>
|
||||||
</UTable>
|
</UTable>
|
||||||
</template>
|
</template>
|
||||||
@@ -110,8 +106,7 @@ const items = ref([])
|
|||||||
const selectedItem = ref(0)
|
const selectedItem = ref(0)
|
||||||
|
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
items.value = await useSupabaseSelect("trackingtripsgen","*, trackingDevice(*), vehicle(*)","startTime",false)
|
items.value = await useSupabaseSelect("trackingtrips","*, trackingDevice(*), vehicle (*)","startTime",false)
|
||||||
console.log(items.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPage()
|
setupPage()
|
||||||
@@ -142,13 +137,9 @@ const templateColumns = [
|
|||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "gpsDistance",
|
key: "distance",
|
||||||
label: "Entfernung:",
|
label: "Entfernung:",
|
||||||
sortable: true
|
sortable: true
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "usedFuel",
|
|
||||||
label: "Kraftstoff:"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const selectedColumns = ref(templateColumns)
|
const selectedColumns = ref(templateColumns)
|
||||||
|
|||||||
8
pages/vendors/[mode]/[[id]].vue
vendored
8
pages/vendors/[mode]/[[id]].vue
vendored
@@ -121,7 +121,6 @@ setupPage()
|
|||||||
<p>E-Mail: {{currentItem.infoData.email}}</p>
|
<p>E-Mail: {{currentItem.infoData.email}}</p>
|
||||||
<p>Web: {{currentItem.infoData.web}}</p>
|
<p>Web: {{currentItem.infoData.web}}</p>
|
||||||
<p>USt-Id: {{currentItem.infoData.ustid}}</p>
|
<p>USt-Id: {{currentItem.infoData.ustid}}</p>
|
||||||
<p>SEPA Mandat: {{currentItem.hasSEPA ? "Ja" : "Nein"}}</p>
|
|
||||||
<p>Notizen:<br> {{currentItem.notes}}</p>
|
<p>Notizen:<br> {{currentItem.notes}}</p>
|
||||||
</div>
|
</div>
|
||||||
</UCard>
|
</UCard>
|
||||||
@@ -252,13 +251,6 @@ setupPage()
|
|||||||
v-model="itemInfo.infoData.web"
|
v-model="itemInfo.infoData.web"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
<UFormGroup
|
|
||||||
label="SEPA Mandat abgeschlossen:"
|
|
||||||
>
|
|
||||||
<UCheckbox
|
|
||||||
v-model="itemInfo.hasSEPA"
|
|
||||||
/>
|
|
||||||
</UFormGroup>
|
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="USt-Id:"
|
label="USt-Id:"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
const resources =ref([])
|
const resources =ref([])
|
||||||
|
|
||||||
|
|
||||||
/*const rights = ref({
|
const rights = ref({
|
||||||
createUser: {label: "Benutzer erstellen"},
|
createUser: {label: "Benutzer erstellen"},
|
||||||
modifyUser: {label: "Benutzer bearbeiten"},
|
modifyUser: {label: "Benutzer bearbeiten"},
|
||||||
deactivateUser: {label: "Benutzer sperren"},
|
deactivateUser: {label: "Benutzer sperren"},
|
||||||
@@ -328,9 +328,9 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
createTime: {label:"Zeiten erstellen"},
|
createTime: {label:"Zeiten erstellen"},
|
||||||
viewOwnTimes: {label:"Eigene Zeiten anzeigen"},
|
viewOwnTimes: {label:"Eigene Zeiten anzeigen"},
|
||||||
viewTimes: {label:"Zeiten anzeigen"},
|
viewTimes: {label:"Zeiten anzeigen"},
|
||||||
})*/
|
})
|
||||||
|
|
||||||
/*const roles = ref([
|
const roles = ref([
|
||||||
{
|
{
|
||||||
key: "tenantAdmin",
|
key: "tenantAdmin",
|
||||||
label: "Firmenadministrator",
|
label: "Firmenadministrator",
|
||||||
@@ -369,12 +369,12 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
"viewAllTimes"
|
"viewAllTimes"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
])*/
|
])
|
||||||
|
|
||||||
async function initializeData (userId) {
|
async function initializeData (userId) {
|
||||||
|
|
||||||
let profileconnections = (await supabase.from("profileconnections").select()).data
|
let profileconnections = (await supabase.from("profileconnections").select()).data
|
||||||
let profiles = (await supabase.from("profiles").select("*, role(*)")).data
|
let profiles = (await supabase.from("profiles").select()).data
|
||||||
let activeProfileConnection = profileconnections.find(i => i.active)
|
let activeProfileConnection = profileconnections.find(i => i.active)
|
||||||
if(activeProfileConnection) {
|
if(activeProfileConnection) {
|
||||||
activeProfile.value = profiles.find(i => i.id === activeProfileConnection.profile_id)
|
activeProfile.value = profiles.find(i => i.id === activeProfileConnection.profile_id)
|
||||||
@@ -521,7 +521,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
resources.value = []
|
resources.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
/*function hasRight (right) {
|
function hasRight (right) {
|
||||||
const role = profiles.value.find(i => i.id === activeProfile.value.id).role
|
const role = profiles.value.find(i => i.id === activeProfile.value.id).role
|
||||||
const grantedRights = roles.value.find(i => i.key === role).rights
|
const grantedRights = roles.value.find(i => i.key === role).rights
|
||||||
|
|
||||||
@@ -529,7 +529,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
return true
|
return true
|
||||||
} else return false
|
} else return false
|
||||||
|
|
||||||
}*/
|
}
|
||||||
|
|
||||||
var deepDiffMapper = function () {
|
var deepDiffMapper = function () {
|
||||||
return {
|
return {
|
||||||
@@ -1749,6 +1749,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
initializeData,
|
initializeData,
|
||||||
changeProfile,
|
changeProfile,
|
||||||
uploadFiles,
|
uploadFiles,
|
||||||
|
hasRight,
|
||||||
generateHistoryItems,
|
generateHistoryItems,
|
||||||
dataTypes,
|
dataTypes,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user