From b17af2620bc94e4212d8c9f8ee13f2723b54cd5e Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Tue, 20 May 2025 16:18:47 +0200 Subject: [PATCH 01/15] Removed Text Justify in GlobalMessages.vue --- components/GlobalMessages.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/GlobalMessages.vue b/components/GlobalMessages.vue index 9e3a3e7..d8f212c 100644 --- a/components/GlobalMessages.vue +++ b/components/GlobalMessages.vue @@ -48,7 +48,7 @@ setup() -

+

Date: Tue, 20 May 2025 16:24:02 +0200 Subject: [PATCH 02/15] =?UTF-8?q?Rechnungs=20E-Mail=20Adresse=20zu=20Kunde?= =?UTF-8?q?n=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/email/new.vue | 2 ++ stores/data.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/pages/email/new.vue b/pages/email/new.vue index 95e00b7..3136eb8 100644 --- a/pages/email/new.vue +++ b/pages/email/new.vue @@ -57,6 +57,8 @@ const setupPage = async () => { if(loadedDocuments.value[0].createddocument.contact && loadedDocuments.value[0].createddocument.contact.email) { console.log("Contact") emailData.value.to = loadedDocuments.value[0].createddocument.contact.email + } else if(loadedDocuments.value[0].createddocument.customer && loadedDocuments.value[0].createddocument.customer.infoData.invoiceEmail) { + emailData.value.to = loadedDocuments.value[0].createddocument.customer.infoData.invoiceEmail } else if(loadedDocuments.value[0].createddocument.customer && loadedDocuments.value[0].createddocument.customer.infoData.email) { emailData.value.to = loadedDocuments.value[0].createddocument.customer.infoData.email } diff --git a/stores/data.js b/stores/data.js index 82deea1..f640f3d 100644 --- a/stores/data.js +++ b/stores/data.js @@ -345,6 +345,11 @@ export const useDataStore = defineStore('data', () => { label: "E-Mail", inputType: "text" }, + { + key: "infoData.invoiceEmail", + label: "E-Mail für Rechnungen", + inputType: "text" + }, { key: "infoData.web", label: "Web", From 6a68c2fbcd2ed1500ee1d7633bf65d75583cb1ab Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Tue, 20 May 2025 16:24:16 +0200 Subject: [PATCH 03/15] Fixed BCC when no standard E-Mail is present --- pages/createDocument/show/[id].vue | 57 +----------------------------- 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/pages/createDocument/show/[id].vue b/pages/createDocument/show/[id].vue index 2330ec4..0c2db3e 100644 --- a/pages/createDocument/show/[id].vue +++ b/pages/createDocument/show/[id].vue @@ -45,7 +45,7 @@ setupPage() const openEmail = () => { if(["invoices","advanceInvoices"].includes(itemInfo.value.type)){ - router.push(`/email/new?loadDocuments=["${linkedDocument.value.id}"]&bcc=${encodeURIComponent(currentTenant.value.standardEmailForInvoices)}`) + router.push(`/email/new?loadDocuments=["${linkedDocument.value.id}"]&bcc=${encodeURIComponent(currentTenant.value.standardEmailForInvoices || "")}`) } else { router.push(`/email/new?loadDocuments=["${linkedDocument.value.id}"]`) } @@ -80,61 +80,6 @@ const openEmail = () => { > Kopieren - Date: Tue, 20 May 2025 16:52:17 +0200 Subject: [PATCH 04/15] Added Name Edition to Company Customers --- pages/createDocument/edit/[[id]].vue | 4 ++++ stores/data.js | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pages/createDocument/edit/[[id]].vue b/pages/createDocument/edit/[[id]].vue index 59ac87d..6378b18 100644 --- a/pages/createDocument/edit/[[id]].vue +++ b/pages/createDocument/edit/[[id]].vue @@ -939,6 +939,7 @@ const getDocumentData = () => { },*/ recipient: [ customerData.name, + ... customerData.nameAddition ? [customerData.nameAddition] : [], ... contactData ? [`${contactData.firstName} ${contactData.lastName}`] : [], itemInfo.value.address.street, ... itemInfo.value.address.special ? [itemInfo.value.address.special] : [], @@ -1531,6 +1532,9 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = { @change="setCustomerData" class="flex-auto" > + { disabledFunction: function (item) { return !item.isCompany }, + }, { + key: "nameAddition", + label: "Firmenname Zusatz", + inputType: "text", + disabledFunction: function (item) { + return !item.isCompany + }, },{ key: "salutation", label: "Anrede", @@ -2617,6 +2624,8 @@ export const useDataStore = defineStore('data', () => { name = "Nachname" } else if(key === "name") { name = "Name" + } else if(key === "nameAddition") { + name = "Name Zusatz" } else if(key === "approved") { name = "Genehmigt" } else if(key === "manufacturer") { @@ -2710,7 +2719,7 @@ export const useDataStore = defineStore('data', () => { let text = "" if(prop.type === "updated" && newVal !== "-" && oldVal !== "-") { - text = `Gerändert: ${name} von "${oldVal}" zu "${newVal}"` + text = `Geändert: ${name} von "${oldVal}" zu "${newVal}"` } else if(prop.type === "updated" && newVal !== "-" && oldVal === "-") { text = `Hinzugefügt: ${name} "${newVal}"` } else if(prop.type === "created") { From db53043b190e6f4135d81503d6bd4c433ed9899b Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Tue, 20 May 2025 17:12:35 +0200 Subject: [PATCH 05/15] Added Support for Conditional Rendering of Inputs --- components/EntityEdit.vue | 462 +++++++++++++++++++------------------- 1 file changed, 234 insertions(+), 228 deletions(-) diff --git a/components/EntityEdit.vue b/components/EntityEdit.vue index 82e833c..6d445ee 100644 --- a/components/EntityEdit.vue +++ b/components/EntityEdit.vue @@ -334,255 +334,261 @@ const updateItem = async () => { Die Form Group darf nur in der ersten bearbeitet werden und muss dann runterkopiert werden --> - - - - - - - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - + Eigene Felder + + + + + + --> + + + + + - Date: Tue, 20 May 2025 17:13:06 +0200 Subject: [PATCH 06/15] Added Support for Conditional Rendering of Inputs Added Some InputColumns in anticipation of required InputColumns --- stores/data.js | 107 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/stores/data.js b/stores/data.js index c2ad032..edfe855 100644 --- a/stores/data.js +++ b/stores/data.js @@ -92,12 +92,14 @@ export const useDataStore = defineStore('data', () => { key: "created_at", label: "Erstellt am", component: created_at, + inputColumn: "Allgemeines" },{ key: "name", label: "Name", title: true, required: true, - inputType: "text" + inputType: "text", + inputColumn: "Allgemeines" },{ key: "categorie", label: "Kategorie", @@ -109,6 +111,7 @@ export const useDataStore = defineStore('data', () => { {label:"In Bearbeitung"}, {label:"Abgeschlossen"} ], + inputColumn: "Allgemeines" },{ key: "profile", label: "Mitarbeiter", @@ -117,6 +120,7 @@ export const useDataStore = defineStore('data', () => { selectDataType: "profiles", selectOptionAttribute: "fullName", selectSearchAttributes: ['fullName'], + inputColumn: "Zuweisungen" },{ key: "project", label: "Projekt", @@ -125,6 +129,7 @@ export const useDataStore = defineStore('data', () => { selectDataType: "projects", selectOptionAttribute: "name", selectSearchAttributes: ['name'], + inputColumn: "Zuweisungen" },{ key: "customer", label: "Kunde", @@ -133,6 +138,7 @@ export const useDataStore = defineStore('data', () => { selectDataType: "customers", selectOptionAttribute: "name", selectSearchAttributes: ['name'], + inputColumn: "Zuweisungen" },{ key: "plant", label: "Objekt", @@ -141,11 +147,17 @@ export const useDataStore = defineStore('data', () => { selectDataType: "plants", selectOptionAttribute: "name", selectSearchAttributes: ['name'], + inputColumn: "Zuweisungen" },{ key: "description", - label: "Beschreibung" + label: "Beschreibung", + inputColumn: "Allgemeines" }, ], + inputColumns: [ + "Allgemeines", + "Zuweisungen" + ], showTabs: [{label: 'Informationen'}] }, customers: { @@ -169,12 +181,23 @@ export const useDataStore = defineStore('data', () => { } } }], + inputColumns: [ + "Allgemeines", + "Kontaktdaten" + ], templateColumns: [ { key: 'customerNumber', label: "Kundennummer", inputIsNumberRange: true, - inputType: "text" + inputType: "text", + inputColumn: "Allgemeines" + }, { + key: "isCompany", + label: "Firmenkunde", + component: isCompany, + inputType: "bool", + inputColumn: "Allgemeines" }, { key: "name", label: "Firmenname", @@ -184,6 +207,10 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return !item.isCompany }, + showFunction: function (item) { + return item.isCompany + }, + inputColumn: "Allgemeines" }, { key: "nameAddition", label: "Firmenname Zusatz", @@ -191,6 +218,10 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return !item.isCompany }, + showFunction: function (item) { + return item.isCompany + }, + inputColumn: "Allgemeines" },{ key: "salutation", label: "Anrede", @@ -213,6 +244,10 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return item.isCompany }, + showFunction: function (item) { + return !item.isCompany + }, + inputColumn: "Allgemeines" },{ key: "title", label: "Titel", @@ -235,6 +270,10 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return item.isCompany }, + showFunction: function (item) { + return !item.isCompany + }, + inputColumn: "Allgemeines" },{ key: "firstname", label: "Vorname",//TODO: Add Conditional Rendering to Datatypes @@ -258,10 +297,15 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return item.isCompany }, + showFunction: function (item) { + return !item.isCompany + }, + inputColumn: "Allgemeines" },{ key: "lastname", label: "Nachname", title: true, + required: true, inputType: "text", inputChangeFunction: function (row) { row.name = "" @@ -281,35 +325,39 @@ export const useDataStore = defineStore('data', () => { disabledFunction: function (item) { return item.isCompany }, - }, { - key: "isCompany", - label: "Firmenkunde", - component: isCompany, - inputType: "bool" + showFunction: function (item) { + return !item.isCompany + }, + inputColumn: "Allgemeines" },{ key: "active", label: "Aktiv", component: active, - inputType: "bool" + inputType: "bool", + inputColumn: "Allgemeines" }, { key: "customPaymentDays", label: "Zahlungsziel in Tagen", - inputType: "number" + inputType: "number", + inputColumn: "Allgemeines" }, { key: "customSurchargePercentage", label: "Individueller Aufschlag", - inputType: "number" + inputType: "number", + inputColumn: "Allgemeines" }, { key: "infoData.street", label: "Straße + Hausnummer", inputType: "text", - disabledInTable: true + disabledInTable: true, + inputColumn: "Kontaktdaten" }, { key: "infoData.special", label: "Adresszusatz", inputType: "text", - disabledInTable: true + disabledInTable: true, + inputColumn: "Kontaktdaten" }, { key: "infoData.zip", @@ -320,13 +368,15 @@ export const useDataStore = defineStore('data', () => { row.infoData.city = (await useZipCheck(row.infoData.zip)) } }, - disabledInTable: true + disabledInTable: true, + inputColumn: "Kontaktdaten" }, { key: "infoData.city", label: "Stadt", inputType: "text", - disabledInTable: true + disabledInTable: true, + inputColumn: "Kontaktdaten" }, { key: "infoData.country", @@ -335,42 +385,50 @@ export const useDataStore = defineStore('data', () => { selectDataType: "countrys", selectOptionAttribute: "name", selectValueAttribute: "name", - disabledInTable: true + disabledInTable: true, + inputColumn: "Kontaktdaten" }, { key: "address", label: "Adresse", - component: address + component: address, + inputColumn: "Kontaktdaten" }, { key: "infoData.tel", label: "Telefon", - inputType: "text" + inputType: "text", + inputColumn: "Kontaktdaten" }, { key: "infoData.email", label: "E-Mail", - inputType: "text" + inputType: "text", + inputColumn: "Kontaktdaten" }, { key: "infoData.invoiceEmail", label: "E-Mail für Rechnungen", - inputType: "text" + inputType: "text", + inputColumn: "Kontaktdaten" }, { key: "infoData.web", label: "Web", - inputType: "text" + inputType: "text", + inputColumn: "Kontaktdaten" }, { key: "infoData.ustid", label: "USt-Id", - inputType: "text" + inputType: "text", + inputColumn: "Kontaktdaten" }, { key: "notes", label: "Notizen", - inputType: "textarea" + inputType: "textarea", + inputColumn: "Allgemeines" }, { key: "profiles", @@ -380,7 +438,8 @@ export const useDataStore = defineStore('data', () => { selectOptionAttribute: "fullName", selectSearchAttributes: ['fullName'], selectMultiple: true, - component: profiles + component: profiles, + inputColumn: "Allgemeines" }, ], showTabs: [{label: 'Informationen'},{label: 'Ansprechpartner'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Termine'},{label: 'Verträge'}] From f5431ddade35e0375306fed99ccd52d0e25d1cd8 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Tue, 20 May 2025 17:15:01 +0200 Subject: [PATCH 07/15] Removed Log Output --- composables/useRole.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/composables/useRole.js b/composables/useRole.js index 9548a13..053fc4f 100644 --- a/composables/useRole.js +++ b/composables/useRole.js @@ -5,8 +5,6 @@ export const useRole = () => { const profileStore = useProfileStore() - console.log(profileStore.currentTenant) - const generalAvailableRights = ref({ projects: { From 6599fdc6c25c052ab238157446372a15fcbdd107 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sun, 25 May 2025 15:53:14 +0200 Subject: [PATCH 08/15] Removed Required for Lastname in Customers --- stores/data.js | 1 - 1 file changed, 1 deletion(-) diff --git a/stores/data.js b/stores/data.js index edfe855..41c7753 100644 --- a/stores/data.js +++ b/stores/data.js @@ -305,7 +305,6 @@ export const useDataStore = defineStore('data', () => { key: "lastname", label: "Nachname", title: true, - required: true, inputType: "text", inputChangeFunction: function (row) { row.name = "" From c94e4c319453628c3a9990da8e0458cd574f4f29 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sun, 25 May 2025 15:54:08 +0200 Subject: [PATCH 09/15] Added Optional and Alternative in Quotes Redesigned the Row Edit Modal Added Errors for Optional and Alternative Rows --- pages/createDocument/edit/[[id]].vue | 93 +++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/pages/createDocument/edit/[[id]].vue b/pages/createDocument/edit/[[id]].vue index 6378b18..15ab604 100644 --- a/pages/createDocument/edit/[[id]].vue +++ b/pages/createDocument/edit/[[id]].vue @@ -577,6 +577,14 @@ const findDocumentErrors = computed(() => { } else { itemInfo.value.rows.forEach(row => { + if(itemInfo.value.type !== "quotes" && row.optional) { + errors.push({message: `Position ${row.pos} ist als Optional markiert. Dies wird nur in Angeboten unterstützt.`, type: "breaking"}) + } + + if(itemInfo.value.type !== "quotes" && row.alternative) { + errors.push({message: `Position ${row.pos} ist als Alternativ markiert. Dies wird nur in Angeboten unterstützt.`, type: "breaking"}) + } + if(row.mode === "normal" && !row.product) errors.push({message: `In Position ${row.pos} ist kein Artikel ausgewählt`, type: "breaking"}) if(row.mode === "service" && !row.service) errors.push({message: `In Position ${row.pos} ist keine Leistung ausgewählt`, type: "breaking"}) if(row.mode === "title" && !row.text) errors.push({message: `In Position ${row.pos} ist kein Titel hinterlegt`, type: "breaking"}) @@ -637,7 +645,7 @@ const documentTotal = computed(() => { let total19 = 0 let total7 = 0 - itemInfo.value.rows.forEach(row => { + itemInfo.value.rows.filter(i => !i.optional && !i.alternative).forEach(row => { if(!['pagebreak','title','text'].includes(row.mode)){ let rowPrice = Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(3) totalNet = totalNet + Number(rowPrice) @@ -659,7 +667,7 @@ const documentTotal = computed(() => { if(row.mode === 'title'){ titleSums[`${row.pos} - ${row.text}`] = 0 lastTitle = `${row.pos} - ${row.text}` - } else if(!['pagebreak','text'].includes(row.mode) && lastTitle !== ""){ + } else if(!['pagebreak','text'].includes(row.mode) && lastTitle !== "" && !row.optional && !row.alternative){ titleSums[lastTitle] = Number(titleSums[lastTitle]) + Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ) } }) @@ -2317,7 +2325,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = { v-if="!['pagebreak','title','text'].includes(row.mode)" > -