Changes in RLS and Tenants

Many Changes in Invoice Editor
Page Loading Rebuilt
Started Rights Management
This commit is contained in:
2024-01-30 21:18:46 +01:00
parent 3167b6a20a
commit fe74e7d91b
13 changed files with 885 additions and 527 deletions

View File

@@ -2,6 +2,11 @@
import dayjs from "dayjs"
const dataStore = useDataStore()
const user = useSupabaseUser()
const route = useRoute()
const tabItems = [
{
@@ -13,52 +18,46 @@ const tabItems = [
]
const itemInfo = ref({
customer: 13,
contact: 8,
type: "invoices",
customer: null,
contact: null,
address: {
street: null,
special: null,
zip: null,
city: null,
},
project: 6,
documentNumber: "RE23-1409",
documentDate: "10.01.2024",
deliveryDate: "10.01.2024",
project: null,
documentNumber: null,
documentDate: null,
deliveryDate: null,
dateOfPerformance: null,
createdBy: user.value.id,
title: "TITEL",
description: "BESCHREIBUNG",
title: null,
description: null,
startText: "Sehr geehrte Frau Sindern,\n" +
"wir bedanken uns für Ihr entgegengebrachtes Vertrauen und Ihren Auftrag und stellen Ihnen\n" +
"folgende Positionen in Rechnung: ",
endText: "Bitte überweisen Sie den Rechnungsbetrag unter Angabe der Rechnungsnummer im Verwendungszweck innerhalb von 10 Tagen auf das unten angegebene Konto. Wir bedanken uns für das entgegengebrachte Vertrauen und freuen uns auf eine weitere gute Zusammenarbeit.",
rows: [
{
id: 1,
pos: 1,
mode: "free",
text: "FahrtkostenFahrtkostenFahrtkostenFahrtkosten",
quantity: 204,
unit: 3,
price: 0.80,
taxPercent: 19,
discountPercent: 0
},
{
id: 2,
pos: 2,
mode: "free",
text: "Test",
quantity: 1,
unit: 1,
price: 10,
taxPercent: 19,
discountPercent: 0
}
]
})
const setupPage = () => {
if(route.params) {
if(route.params.id) itemInfo.value = dataStore.getCreatedDocumentById(Number(route.params.id))
}
if(route.query) {
if(route.query.type) itemInfo.value.type = route.query.type
if(route.query.project) itemInfo.value.project = Number(route.query.project)
if(route.query.customer) itemInfo.value.customer = Number(route.query.customer)
}
}
const getRowAmount = (row) => {
return String(Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(2)).replace('.',',')
}
@@ -218,7 +217,6 @@ const generateDocument = async () => {
uri.value = await useCreatePdf(getDocumentData())
//alert(uri.value)
showDocument.value = true
}
const onChangeTab = (index) => {
@@ -238,20 +236,80 @@ const setPosNumbers = () => {
})
}
const saveDocument = async () => {
let createData = {
type: itemInfo.value.type,
customer: itemInfo.value.customer,
contact: itemInfo.value.contact,
address: itemInfo.value.address,
project: itemInfo.value.project,
documentNumber: itemInfo.value.documentNumber,
documentDate: itemInfo.value.documentDate,
state: "Entwurf",
info: {
},
createdBy: itemInfo.value.createdBy,
title: itemInfo.value.title,
description: itemInfo.value.description,
startText: itemInfo.value.startText,
endText: itemInfo.value.endText,
rows: itemInfo.value.rows
}
if(route.params.id) {
await dataStore.updateItem("createdDocuments", {...createData, id: itemInfo.value.id})
} else {
await dataStore.createNewItem("createdDocuments", createData)
}
}
const closeDocument = () => {
generateDocument()
console.log(uri)
}
setupPage()
</script>
<template>
<!-- <UButton
@click="createPdf"
>TEST</UButton>-->
<UCard class="h-fit">
<InputGroup class="mb-3">
<UButton
icon="i-mdi-content-save"
@click="saveDocument"
>
Entwurf
</UButton>
<UButton
@click="closeDocument"
>
Fertigstellen
</UButton>
</InputGroup>
<UTabs :items="tabItems" @change="onChangeTab">
<template #item="{item}">
<div v-if="item.label === 'Editor'">
<InputGroup>
<div class="flex-auto mr-5">
<UFormGroup
label="Dokumenttyp:"
>
<USelectMenu
:options="Object.keys(dataStore.documentTypesForCreation).map(i => {return {label: dataStore.documentTypesForCreation[i].labelSingle, type: i }})"
v-model="itemInfo.type"
value-attribute="type"
option-attribute="label"
>
<template #label>
{{dataStore.documentTypesForCreation[itemInfo.type].labelSingle}}
</template>
</USelectMenu>
</UFormGroup>
<UFormGroup
label="Kunde:"
>
@@ -324,6 +382,7 @@ const setPosNumbers = () => {
>
<UInput
v-model="itemInfo.documentNumber"
placeholder="Leer lassen für automatisch generierte Nummer"
/>
</UFormGroup>
<UFormGroup
@@ -735,27 +794,6 @@ const setPosNumbers = () => {
</table>
<table>
<tr>
<td class="font-bold">Netto:</td>
<td>{{documentTotal.totalNet}}</td>
</tr>
<tr>
<td class="font-bold">zzgl. 19 % USt:</td>
<td>{{documentTotal.total19}}</td>
</tr>
<tr>
<td class="font-bold">Brutto:</td>
<td>{{documentTotal.totalGross}}</td>
</tr>
</table>
<InputGroup>
<UButton
@click="addPosition('normal')"
@@ -777,6 +815,21 @@ const setPosNumbers = () => {
</UButton>
</InputGroup>
<table>
<tr>
<td class="font-bold">Netto:</td>
<td>{{documentTotal.totalNet}}</td>
</tr>
<tr>
<td class="font-bold">zzgl. 19 % USt:</td>
<td>{{documentTotal.total19}}</td>
</tr>
<tr>
<td class="font-bold">Brutto:</td>
<td>{{documentTotal.totalGross}}</td>
</tr>
</table>
<UDivider
@@ -797,7 +850,6 @@ const setPosNumbers = () => {
>
Show
</UButton>-->
<object
:data="uri"
v-if="showDocument"

View File

@@ -0,0 +1,25 @@
<script setup>
const dataStore = useDataStore()
const route = useRoute()
const itemInfo = ref({})
const setupPage = () => {
if(route.params) {
if(route.params.id) itemInfo.value = dataStore.getCreatedDocumentById(Number(route.params.id))
}
}
setupPage()
</script>
<template>
{{itemInfo}}
</template>
<style scoped>
</style>

View File

@@ -12,11 +12,24 @@ const {fetchData} = useDataStore()
const email = ref("")
const password = ref("")
const fields = [{
name: 'email',
type: 'text',
label: 'Email',
placeholder: 'E-Mail Adresse'
}, {
name: 'password',
label: 'Password',
type: 'password',
placeholder: 'Passwort'
}]
const onSubmit = async (data) => {
const onSubmit = async () => {
const { error } = await supabase.auth.signInWithPassword({
email: email.value,
password: password.value
email: data.email,
password: data.password
})
if(error) {
console.log(error.toString())
@@ -33,7 +46,7 @@ const onSubmit = async () => {
</script>
<template>
<div id="loginSite">
<!-- <div id="loginSite">
<div id="loginForm">
<UFormGroup
label="E-Mail:"
@@ -59,7 +72,23 @@ const onSubmit = async () => {
</UButton>
</div>
</div>
</div>-->
<UCard class="max-w-sm w-full mx-auto mt-5">
<UAuthForm
title="Login"
description="Geben Sie Ihre Anmeldedaten ein um Zugriff auf Ihren Account zu bekommen"
align="bottom"
icon="i-heroicons-user-circle"
:fields="fields"
:loading="false"
@submit="onSubmit"
>
</UAuthForm>
</UCard>
</template>
<style scoped>

View File

@@ -309,11 +309,24 @@ setupPage()
</UAccordion>
</div>
<div v-else-if="item.key === 'documents'" class="space-y-3">
<UButton
@click="uploadModalOpen = true"
>
Hochladen
</UButton>
<InputGroup>
<UButton
@click="uploadModalOpen = true"
>
Hochladen
</UButton>
<UButton
@click="router.push(`/createDocument/edit?project=${currentItem.id}&type=quotes&customer=${currentItem.customer}`)"
>
+ Angebot
</UButton>
<UButton
@click="router.push(`/createDocument/edit?project=${currentItem.id}&type=invoices&customer=${currentItem.customer}`)"
>
+ Rechnung
</UButton>
</InputGroup>
<UModal
v-model="uploadModalOpen"
>

View File

@@ -94,7 +94,7 @@ const setState = async (newState) => {
} else if(mode.value === 'edit') {
await dataStore.updateItem('incomingInvoices',{...itemInfo.value, state: newState})
}
await router.push("/incominginvoices")
await router.push("/receipts")
}
@@ -133,11 +133,11 @@ setupPage()
Status zu Entwurf
</UButton>
<UButton
@click="setState('Offen')"
v-if="currentVendorInvoice.state !== 'Offen'"
@click="setState('Gebucht')"
v-if="currentVendorInvoice.state !== 'Gebucht'"
color="rose"
>
Status zu Offen
Status auf Gebucht
</UButton>
</InputGroup>
@@ -372,13 +372,13 @@ setupPage()
>
Position entfernen
</UButton>
<HistoryDisplay
type="incomingInvoice"
v-if="currentVendorInvoice"
:element-id="currentVendorInvoice.id"
/>
</div>
</div>
<HistoryDisplay
type="incomingInvoice"
v-if="currentVendorInvoice"
:element-id="currentVendorInvoice.id"
/>
</div>
</div>

View File

@@ -8,6 +8,11 @@
v-model="searchString"
placeholder="Suche..."
/>
<UCheckbox
v-model="showDrafts"
label="Entwürfe Anzeigen"
/>
</div>
@@ -18,16 +23,20 @@
@select="selectItem"
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Noch keine Einträge' }"
>
<template #type-data="{row}">
<span v-if="row.type === 'incomingInvoice'">Eingangsrechnung</span>
<span v-else>{{dataStore.documentTypesForCreation[row.type].labelSingle}}</span>
</template>
<template #state-data="{row}">
<span
v-if="row.state === 'Entwurf'"
class="text-cyan-500"
class="text-rose-500"
>
{{row.state}}
</span>
<span
v-if="row.state === 'Offen'"
class="text-rose-500"
v-if="row.state === 'Gebucht'"
class="text-cyan-500"
>
{{row.state}}
</span>
@@ -41,6 +50,10 @@
<template #vendor-data="{row}">
{{dataStore.vendors.find(vendor => vendor.id === row.vendor) ? dataStore.vendors.find(vendor => vendor.id === row.vendor).name : ''}}
</template>
<template #reference-data="{row}">
<span v-if="row.type === 'incomingInvoice'">{{row.reference}}</span>
<span v-else>{{row.documentNumber}}</span>
</template>
<template #date-data="{row}">
<span v-if="row.date">{{row.date ? dayjs(row.date).format("DD.MM.YY") : ''}}</span>
</template>
@@ -52,7 +65,12 @@
<span v-if="!row.paid" :class="dayjs(row.dueDate).diff(dayjs()) <= 0 ? ['text-rose-500'] : ['text-cyan-500'] ">Offen</span>
</template>
<template #amount-data="{row}">
<div class="text-right font-bold">{{getRowAmount(row) === 0 ? '' : `${String(getRowAmount(row).toFixed(2)).replace('.',',')}`}}</div>
<div
class="text-right font-bold"
v-if="row.type === 'incomingInvoice'"
>
{{getRowAmount(row) === 0 ? '' : `${String(getRowAmount(row).toFixed(2)).replace('.',',')}`}}
</div>
</template>
</UTable>
@@ -74,6 +92,10 @@ const mode = ref("show")
const itemColumns = [
{
key: 'type',
label: "Typ",
sortable: true
},{
key: 'state',
label: "Status.",
sortable: true
@@ -113,13 +135,25 @@ const itemColumns = [
const selectItem = (item) => {
console.log(item)
if(item.state === "Entwurf") {
console.log("ENTWURF")
router.push(`/incominginvoices/edit/${item.id} `)
} else if(item.state === "Offen") {
router.push(`/incominginvoices/show/${item.id}`)
if(item.type === "incomingInvoice"){
if(item.state === "Entwurf") {
router.push(`/receipts/incominginvoices/edit/${item.id} `)
} else if(item.state === "Gebucht") {
router.push(`/receipts/incominginvoices/show/${item.id}`)
}
} else {
if(item.state === "Entwurf"){
router.push(`/createDocument/edit/${item.id}`)
} else if(item.state !== "Entwurf") {
router.push(`/createDocument/show/${item.id}`)
}
}
}
const getRowAmount = (row) => {
@@ -135,13 +169,25 @@ const getRowAmount = (row) => {
const searchString = ref('')
const showDrafts = ref(false)
const filteredRows = computed(() => {
if(!searchString.value) {
return dataStore.incomingInvoices
let items = [...dataStore.incomingInvoices.map(i => {return {...i, type: "incomingInvoice"}}),...dataStore.createdDocuments]
console.log(dataStore.createdDocuments)
if(showDrafts.value === true) {
items = items.filter(i => i.state === "Entwurf")
} else {
items = items.filter(i => i.state !== "Entwurf")
}
return dataStore.incomingInvoices.filter(item => {
if(!searchString.value) {
return items
}
return items.filter(item => {
return Object.values(item).some((value) => {
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
})

View File

@@ -36,11 +36,13 @@ const resources = {
},
spaces: {
label: "Lagerplätze"
},
invoices: {
label: "Rechnungen"
}
}
const updateNumberRange = async (range) => {
console.log(range)
const {data,error} = await supabase
.from("numberRanges")

View File

@@ -0,0 +1,78 @@
<script setup>
const supabase = useSupabaseClient()
const data = await supabase.from("profiles").select('* , tenants (id, name)')
console.log(data)
let rights = {
createUser: {label: "Benutzer erstellen"},
modifyUser: {label: "Benutzer bearbeiten"},
deactivateUser: {label: "Benutzer sperren"},
createProject: {label: "Projekt erstellen"},
viewOwnProjects: {label: "Eigene Projekte sehen"},
viewAllProjects: {label: "Alle Projekte sehen"},
createTask: {label: "Aufgabe erstellen"},
viewOwnTasks: {label:"Eigene Aufgaben sehen"},
viewAllTasks: {label: "Alle Aufgaben sehen"},
trackOwnTime: {label:""},
createOwnTime: {label:""},
createTime: {label:""},
viewOwnTimes: {label:""},
viewAllTimesTimes: {label:""},
}
let roles = [
{
key: "tenantAdmin",
label: "Firmenadministrator",
rights: [
...Object.keys(rights)
]
},
{
key:"worker",
label: "Monteur",
rights: [
"viewOwnProjects",
"createTasks",
"viewOwnTasks"
]
},
{
key:"manager",
label: "Vorarbeiter",
rights: [
"createProjects",
"viewOwnProjects",
"createTasks",
"viewOwnTasks",
]
},
{
key:"booker",
label: "Buchhalter",
rights: [
"createTasks",
"viewOwnTasks",
"createTime",
"viewAllTimes"
]
}
]
</script>
<template>
</template>
<style scoped>
</style>

View File

@@ -141,7 +141,7 @@ setupPage()
<UTable
:rows="dataStore.getIncomingInvoicesByVehicleId(currentItem.id)"
:columns="incomingInvoicesColumns"
@select="(row) => router.push('/incominginvoices/show/' + row.id)"
@select="(row) => router.push('/receipts/show/' + row.id)"
>
<template #vendor-data="{row}">
{{dataStore.getVendorById(row.vendor) ? dataStore.getVendorById(row.vendor).name : ""}}