Added IBAN Saving, Automatic Saving, added Mitglieder
This commit is contained in:
@@ -69,20 +69,31 @@ generateOldItemData()
|
||||
const saveAllowed = computed(() => {
|
||||
if (!item.value) return false
|
||||
|
||||
const isFilledValue = (value) => {
|
||||
if (Array.isArray(value)) return value.length > 0
|
||||
if (typeof value === "string") return value.trim().length > 0
|
||||
return value !== null && value !== undefined && value !== false
|
||||
}
|
||||
|
||||
let allowedCount = 0
|
||||
// Nur Input-Felder berücksichtigen
|
||||
const relevantColumns = dataType.templateColumns.filter(i => i.inputType)
|
||||
const relevantColumns = dataType.templateColumns.filter(i => {
|
||||
if (!i.inputType) return false
|
||||
if (i.showFunction && !i.showFunction(item.value)) return false
|
||||
if (i.disabledFunction && i.disabledFunction(item.value)) return false
|
||||
return true
|
||||
})
|
||||
|
||||
relevantColumns.forEach(datapoint => {
|
||||
if(datapoint.required) {
|
||||
if(datapoint.key.includes(".")){
|
||||
const [parentKey, childKey] = datapoint.key.split('.')
|
||||
// Prüfung: Existiert Parent UND ist Child "truthy" (nicht null/undefined/empty)
|
||||
if(item.value[parentKey] && item.value[parentKey][childKey]) {
|
||||
if(item.value[parentKey] && isFilledValue(item.value[parentKey][childKey])) {
|
||||
allowedCount += 1
|
||||
}
|
||||
} else {
|
||||
if(item.value[datapoint.key]) {
|
||||
if(isFilledValue(item.value[datapoint.key])) {
|
||||
allowedCount += 1
|
||||
}
|
||||
}
|
||||
@@ -427,6 +438,11 @@ const updateItem = async () => {
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
<BankAccountAssignInput
|
||||
v-else-if="datapoint.inputType === 'bankaccountassign'"
|
||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||
/>
|
||||
<Tiptap
|
||||
v-else-if="datapoint.inputType === 'editor'"
|
||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||
@@ -527,6 +543,11 @@ const updateItem = async () => {
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
<BankAccountAssignInput
|
||||
v-else-if="datapoint.inputType === 'bankaccountassign'"
|
||||
v-model="item[datapoint.key]"
|
||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||
/>
|
||||
<Tiptap
|
||||
v-else-if="datapoint.inputType === 'editor'"
|
||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||
@@ -652,6 +673,11 @@ const updateItem = async () => {
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
<BankAccountAssignInput
|
||||
v-else-if="datapoint.inputType === 'bankaccountassign'"
|
||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||
/>
|
||||
<Tiptap
|
||||
v-else-if="datapoint.inputType === 'editor'"
|
||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||
@@ -752,6 +778,11 @@ const updateItem = async () => {
|
||||
/>
|
||||
</template>
|
||||
</UPopover>
|
||||
<BankAccountAssignInput
|
||||
v-else-if="datapoint.inputType === 'bankaccountassign'"
|
||||
v-model="item[datapoint.key]"
|
||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||
/>
|
||||
<Tiptap
|
||||
v-else-if="datapoint.inputType === 'editor'"
|
||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||
@@ -788,4 +819,4 @@ td {
|
||||
padding-bottom: 0.15em;
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -69,6 +69,12 @@ const profileStore = useProfileStore()
|
||||
const tempStore = useTempStore()
|
||||
|
||||
const dataType = dataStore.dataTypes[type]
|
||||
const canCreate = computed(() => {
|
||||
if (type === "members") {
|
||||
return has("members-create") || has("customers-create")
|
||||
}
|
||||
return has(`${type}-create`)
|
||||
})
|
||||
|
||||
const selectedColumns = ref(tempStore.columns[type] ? tempStore.columns[type] : dataType.templateColumns.filter(i => !i.disabledInTable))
|
||||
const columns = computed(() => dataType.templateColumns.filter((column) => !column.disabledInTable && selectedColumns.value.find(i => i.key === column.key)))
|
||||
@@ -138,7 +144,7 @@ const filteredRows = computed(() => {
|
||||
/>
|
||||
|
||||
<UButton
|
||||
v-if="platform !== 'mobile' && has(`${type}-create`)/*&& useRole().checkRight(`${type}-create`)*/"
|
||||
v-if="platform !== 'mobile' && canCreate/*&& useRole().checkRight(`${type}-create`)*/"
|
||||
@click="router.push(`/standardEntity/${type}/create`)"
|
||||
class="ml-3"
|
||||
>+ {{dataType.labelSingle}}</UButton>
|
||||
@@ -200,4 +206,4 @@ const filteredRows = computed(() => {
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -69,7 +69,7 @@ const getAvailableQueryStringData = (keys) => {
|
||||
|
||||
if(props.item.customer) {
|
||||
addParam("customer", props.item.customer.id)
|
||||
} else if(type === "customers") {
|
||||
} else if(type === "customers" || type === "members") {
|
||||
addParam("customer", props.item.id)
|
||||
}
|
||||
|
||||
@@ -372,4 +372,4 @@ const changePinned = async () => {
|
||||
<style scoped>
|
||||
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -5,6 +5,13 @@ const { has } = usePermission()
|
||||
|
||||
// Lokaler State für den Taschenrechner
|
||||
const showCalculator = ref(false)
|
||||
const tenantExtraModules = computed(() => {
|
||||
const modules = auth.activeTenantData?.extraModules
|
||||
return Array.isArray(modules) ? modules : []
|
||||
})
|
||||
const showMembersNav = computed(() => {
|
||||
return tenantExtraModules.value.includes("verein") && (has("members") || has("customers"))
|
||||
})
|
||||
|
||||
const links = computed(() => {
|
||||
return [
|
||||
@@ -98,11 +105,16 @@ const links = computed(() => {
|
||||
}
|
||||
]
|
||||
},
|
||||
...(has("customers") || has("vendors") || has("contacts")) ? [{
|
||||
...(has("customers") || has("vendors") || has("contacts") || showMembersNav.value) ? [{
|
||||
label: "Kontakte",
|
||||
defaultOpen: false,
|
||||
icon: "i-heroicons-user-group",
|
||||
children: [
|
||||
...showMembersNav.value ? [{
|
||||
label: "Mitglieder",
|
||||
to: "/standardEntity/members",
|
||||
icon: "i-heroicons-user-group"
|
||||
}] : [],
|
||||
...has("customers") ? [{
|
||||
label: "Kunden",
|
||||
to: "/standardEntity/customers",
|
||||
|
||||
@@ -49,6 +49,12 @@ const tempStore = useTempStore()
|
||||
const type = route.params.type
|
||||
|
||||
const dataType = dataStore.dataTypes[type]
|
||||
const canCreate = computed(() => {
|
||||
if (type === "members") {
|
||||
return has("members-create") || has("customers-create")
|
||||
}
|
||||
return has(`${type}-create`)
|
||||
})
|
||||
|
||||
const selectedColumns = ref(tempStore.columns[type] ? tempStore.columns[type] : dataType.templateColumns.filter(i => !i.disabledInTable))
|
||||
const columns = computed(() => dataType.templateColumns.filter((column) => !column.disabledInTable && selectedColumns.value.find(i => i.key === column.key)))
|
||||
@@ -240,7 +246,7 @@ const handleFilterChange = async (action,column) => {
|
||||
|
||||
<UTooltip :text="`${dataType.labelSingle} erstellen`">
|
||||
<UButton
|
||||
v-if="platform !== 'mobile' && has(`${type}-create`)/*&& useRole().checkRight(`${type}-create`)*/"
|
||||
v-if="platform !== 'mobile' && canCreate/*&& useRole().checkRight(`${type}-create`)*/"
|
||||
@click="router.push(`/standardEntity/${type}/create`)"
|
||||
class="ml-3"
|
||||
>+ {{dataType.labelSingle}}</UButton>
|
||||
|
||||
@@ -43,6 +43,7 @@ import quantity from "~/components/helpRenderings/quantity.vue"
|
||||
import {useFunctions} from "~/composables/useFunctions.js";
|
||||
import signDate from "~/components/columnRenderings/signDate.vue";
|
||||
import sepaDate from "~/components/columnRenderings/sepaDate.vue";
|
||||
import bankAccounts from "~/components/columnRenderings/bankAccounts.vue";
|
||||
|
||||
// @ts-ignore
|
||||
export const useDataStore = defineStore('data', () => {
|
||||
@@ -410,6 +411,14 @@ export const useDataStore = defineStore('data', () => {
|
||||
inputType: "text",
|
||||
inputColumn: "Kontaktdaten"
|
||||
},
|
||||
{
|
||||
key: "infoData.bankAccountIds",
|
||||
label: "Bankkonten",
|
||||
component: bankAccounts,
|
||||
inputType: "bankaccountassign",
|
||||
inputColumn: "Kontaktdaten",
|
||||
disabledInTable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.ustid",
|
||||
label: "USt-Id",
|
||||
@@ -436,6 +445,202 @@ export const useDataStore = defineStore('data', () => {
|
||||
],
|
||||
showTabs: [{label: 'Informationen'},{label: 'Ansprechpartner'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Termine'},{label: 'Verträge'},{label: 'Wiki'}]
|
||||
},
|
||||
members: {
|
||||
isArchivable: true,
|
||||
label: "Mitglieder",
|
||||
labelSingle: "Mitglied",
|
||||
isStandardEntity: true,
|
||||
redirect: true,
|
||||
numberRangeHolder: "customerNumber",
|
||||
historyItemHolder: "customer",
|
||||
sortColumn: "customerNumber",
|
||||
selectWithInformation: "*, projects(*), plants(*), contracts(*), contacts(*), createddocuments(*, statementallocations(*)), files(*), events(*)",
|
||||
filters: [{
|
||||
name: "Archivierte ausblenden",
|
||||
default: true,
|
||||
"filterFunction": function (row) {
|
||||
return !row.archived
|
||||
}
|
||||
}],
|
||||
inputColumns: [
|
||||
"Allgemeines",
|
||||
"Bank & Kontakt"
|
||||
],
|
||||
templateColumns: [
|
||||
{
|
||||
key: 'customerNumber',
|
||||
label: "Mitgliedsnummer",
|
||||
inputIsNumberRange: true,
|
||||
inputType: "text",
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "name",
|
||||
label: "Name",
|
||||
title: true,
|
||||
sortable: true,
|
||||
distinct: true
|
||||
},
|
||||
{
|
||||
key: "salutation",
|
||||
label: "Anrede",
|
||||
inputType: "text",
|
||||
inputChangeFunction: function (row) {
|
||||
row.name = `${row.salutation ? (row.salutation + " ") : ""}${row.title ? (row.title + " ") : ""}${row.firstname ? (row.firstname + " ") : ""}${row.lastname || ""}`.trim();
|
||||
},
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true,
|
||||
distinct: true
|
||||
},
|
||||
{
|
||||
key: "title",
|
||||
label: "Titel",
|
||||
inputType: "text",
|
||||
inputChangeFunction: function (row) {
|
||||
row.name = `${row.salutation ? (row.salutation + " ") : ""}${row.title ? (row.title + " ") : ""}${row.firstname ? (row.firstname + " ") : ""}${row.lastname || ""}`.trim();
|
||||
},
|
||||
inputColumn: "Allgemeines"
|
||||
},
|
||||
{
|
||||
key: "firstname",
|
||||
label: "Vorname",
|
||||
required: true,
|
||||
inputType: "text",
|
||||
inputChangeFunction: function (row) {
|
||||
row.name = `${row.salutation ? (row.salutation + " ") : ""}${row.title ? (row.title + " ") : ""}${row.firstname ? (row.firstname + " ") : ""}${row.lastname || ""}`.trim();
|
||||
},
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "lastname",
|
||||
label: "Nachname",
|
||||
required: true,
|
||||
inputType: "text",
|
||||
inputChangeFunction: function (row) {
|
||||
row.name = `${row.salutation ? (row.salutation + " ") : ""}${row.title ? (row.title + " ") : ""}${row.firstname ? (row.firstname + " ") : ""}${row.lastname || ""}`.trim();
|
||||
},
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "active",
|
||||
label: "Aktiv",
|
||||
component: active,
|
||||
inputType: "bool",
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true,
|
||||
distinct: true
|
||||
},
|
||||
{
|
||||
key: "customPaymentDays",
|
||||
label: "Beitragsintervall in Tagen",
|
||||
inputType: "number",
|
||||
inputColumn: "Allgemeines",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.bankAccountIds",
|
||||
label: "Bankkonten",
|
||||
component: bankAccounts,
|
||||
inputType: "bankaccountassign",
|
||||
required: true,
|
||||
inputColumn: "Bank & Kontakt",
|
||||
disabledInTable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.hasSEPA",
|
||||
label: "SEPA-Mandat vorhanden",
|
||||
inputType: "bool",
|
||||
inputColumn: "Bank & Kontakt",
|
||||
disabledInTable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.sepaSignedAt",
|
||||
label: "SEPA unterschrieben am",
|
||||
inputType: "date",
|
||||
required: true,
|
||||
showFunction: function (item) {
|
||||
return Boolean(item.infoData?.hasSEPA)
|
||||
},
|
||||
inputColumn: "Bank & Kontakt",
|
||||
disabledInTable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.street",
|
||||
label: "Straße + Hausnummer",
|
||||
inputType: "text",
|
||||
disabledInTable: true,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.special",
|
||||
label: "Adresszusatz",
|
||||
inputType: "text",
|
||||
disabledInTable: true,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.zip",
|
||||
label: "Postleitzahl",
|
||||
inputType: "text",
|
||||
inputChangeFunction: async function (row) {
|
||||
const zip = String(row.infoData.zip || "").replace(/\D/g, "")
|
||||
row.infoData.zip = zip
|
||||
if ([4, 5].includes(zip.length)) {
|
||||
const zipData = await useFunctions().useZipCheck(zip)
|
||||
row.infoData.zip = zipData?.zip || row.infoData.zip
|
||||
row.infoData.city = zipData?.short || row.infoData.city
|
||||
}
|
||||
},
|
||||
disabledInTable: true,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.city",
|
||||
label: "Stadt",
|
||||
inputType: "text",
|
||||
disabledInTable: true,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.country",
|
||||
label: "Land",
|
||||
inputType: "select",
|
||||
selectDataType: "countrys",
|
||||
selectOptionAttribute: "name",
|
||||
selectValueAttribute: "name",
|
||||
disabledInTable: true,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "address",
|
||||
label: "Adresse",
|
||||
component: address,
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.tel",
|
||||
label: "Telefon",
|
||||
inputType: "text",
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "infoData.email",
|
||||
label: "E-Mail",
|
||||
inputType: "text",
|
||||
inputColumn: "Bank & Kontakt"
|
||||
},
|
||||
{
|
||||
key: "notes",
|
||||
label: "Notizen",
|
||||
inputType: "textarea",
|
||||
inputColumn: "Allgemeines"
|
||||
},
|
||||
],
|
||||
showTabs: [{label: 'Informationen'},{label: 'Ansprechpartner'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Termine'},{label: 'Verträge'},{label: 'Wiki'}]
|
||||
},
|
||||
contacts: {
|
||||
isArchivable: true,
|
||||
label: "Kontakte",
|
||||
@@ -1455,6 +1660,13 @@ export const useDataStore = defineStore('data', () => {
|
||||
label: "Web",
|
||||
inputType: "text"
|
||||
},
|
||||
{
|
||||
key: "infoData.bankAccountIds",
|
||||
label: "Bankkonten",
|
||||
component: bankAccounts,
|
||||
inputType: "bankaccountassign",
|
||||
disabledInTable: true
|
||||
},
|
||||
{
|
||||
key: "infoData.ustid",
|
||||
label: "USt-Id",
|
||||
@@ -2700,6 +2912,55 @@ export const useDataStore = defineStore('data', () => {
|
||||
bankaccounts: {
|
||||
label: "Bankkonten",
|
||||
labelSingle: "Bankkonto",
|
||||
},
|
||||
entitybankaccounts: {
|
||||
isArchivable: true,
|
||||
label: "Bankverbindungen",
|
||||
labelSingle: "Bankverbindung",
|
||||
isStandardEntity: false,
|
||||
redirect: false,
|
||||
sortColumn: "created_at",
|
||||
filters: [{
|
||||
name: "Archivierte ausblenden",
|
||||
default: true,
|
||||
"filterFunction": function (row) {
|
||||
return !row.archived
|
||||
}
|
||||
}],
|
||||
templateColumns: [
|
||||
{
|
||||
key: "displayLabel",
|
||||
label: "Bankverbindung",
|
||||
title: true,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "iban",
|
||||
label: "IBAN",
|
||||
required: true,
|
||||
inputType: "text",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "bic",
|
||||
label: "BIC",
|
||||
required: true,
|
||||
inputType: "text",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "bankName",
|
||||
label: "Bankinstitut",
|
||||
required: true,
|
||||
inputType: "text",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
key: "description",
|
||||
label: "Beschreibung",
|
||||
inputType: "text",
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user