SEPA-Mandate in Verträge und Ausgangsrechnungen einbauen #183

This commit is contained in:
2026-05-15 18:13:29 +02:00
parent d522cbb49d
commit 9592e2b062
2 changed files with 90 additions and 37 deletions

View File

@@ -224,6 +224,33 @@ const availableSepaMandates = computed(() => {
})
})
const getSelectedSepaMandate = () => {
return availableSepaMandates.value.find((mandate) => mandate.id === itemInfo.value.outgoingsepamandate) || null
}
const mapContractPaymentType = (paymentType) => {
if (paymentType === "Einzug") return "direct-debit"
if (paymentType === "Überweisung") return "transfer"
return null
}
const applyContractPaymentData = () => {
const selectedContract = contracts.value.find((contract) => contract.id === itemInfo.value.contract)
if (!selectedContract) return
const mappedPaymentType = mapContractPaymentType(selectedContract.paymentType)
if (mappedPaymentType) {
itemInfo.value.payment_type = mappedPaymentType
}
const contractMandateId = selectedContract.outgoingsepamandate?.id || selectedContract.outgoingsepamandate
if (mappedPaymentType === "direct-debit" && contractMandateId) {
itemInfo.value.outgoingsepamandate = contractMandateId
} else if (mappedPaymentType === "transfer") {
itemInfo.value.outgoingsepamandate = null
}
}
const applyDefaultSepaMandate = () => {
if (itemInfo.value.payment_type !== "direct-debit") {
itemInfo.value.outgoingsepamandate = null
@@ -246,6 +273,11 @@ const applyDefaultSepaMandate = () => {
itemInfo.value.outgoingsepamandate = defaultMandate?.id || null
}
watch(
() => itemInfo.value.contract,
() => applyContractPaymentData()
)
watch(
() => [itemInfo.value.customer, itemInfo.value.contract, itemInfo.value.payment_type, outgoingsepamandates.value.length],
() => applyDefaultSepaMandate()
@@ -2268,6 +2300,24 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
class="w-full"
/>
</UFormField>
<UFormField
class="min-w-0 flex-1"
label="Individueller Aufschlag:"
>
<UInput
type="number"
step="0.01"
v-model="itemInfo.customSurchargePercentage"
@change="updateCustomSurcharge"
class="w-full"
>
<template #trailing>
<span class="text-gray-500 dark:text-gray-400 text-xs">%</span>
</template>
</UInput>
</UFormField>
</InputGroup>
<InputGroup class="w-full items-start flex-wrap md:flex-nowrap">
<UFormField
class="min-w-0 flex-1"
label="Zahlungsart:"
@@ -2289,39 +2339,38 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
class="min-w-0 flex-1"
label="SEPA-Mandat:"
>
<USelectMenu
v-model="itemInfo.outgoingsepamandate"
value-key="id"
label-key="reference"
:items="availableSepaMandates"
:search-input="{ placeholder: 'Suche...' }"
:filter-fields="['reference', 'status']"
class="w-full"
:disabled="!itemInfo.customer"
>
<template #default>
{{ itemInfo.outgoingsepamandate ? availableSepaMandates.find(i => i.id === itemInfo.outgoingsepamandate)?.reference : "Kein Mandat ausgewählt" }}
</template>
<template #item="{ item: mandate }">
{{ mandate.reference }} - {{ mandate.bankaccount?.displayLabel || "Bankverbindung" }}
</template>
</USelectMenu>
</UFormField>
<UFormField
class="min-w-0 flex-1"
label="Individueller Aufschlag:"
>
<UInput
type="number"
step="0.01"
v-model="itemInfo.customSurchargePercentage"
@change="updateCustomSurcharge"
class="w-full"
>
<template #trailing>
<span class="text-gray-500 dark:text-gray-400 text-xs">%</span>
</template>
</UInput>
<InputGroup>
<USelectMenu
v-model="itemInfo.outgoingsepamandate"
value-key="id"
label-key="reference"
:items="availableSepaMandates"
:search-input="{ placeholder: 'Suche...' }"
:filter-fields="['reference', 'status']"
class="w-full"
:disabled="!itemInfo.customer"
>
<template #default>
{{ getSelectedSepaMandate()?.reference || "Kein Mandat ausgewählt" }}
</template>
<template #item="{ item: mandate }">
{{ mandate.reference }} - {{ mandate.bankaccount?.displayLabel || "Bankverbindung" }}
</template>
</USelectMenu>
<UButton
variant="outline"
color="error"
v-if="itemInfo.outgoingsepamandate"
icon="i-heroicons-x-mark"
@click="itemInfo.outgoingsepamandate = null"
/>
<EntityModalButtons
type="outgoingsepamandates"
:id="itemInfo.outgoingsepamandate"
:create-query="{customer: itemInfo.customer}"
@return-data="(data) => itemInfo.outgoingsepamandate = data.id"
/>
</InputGroup>
</UFormField>
</InputGroup>
<UFormField
@@ -2438,7 +2487,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
>
<InputGroup>
<USelectMenu
:items="contracts.filter(i => i.customer?.id === itemInfo.customer && (itemInfo.plant ? itemInfo.plant === i.plant : true))"
:items="contracts.filter(i => (i.customer?.id || i.customer) === itemInfo.customer && (itemInfo.plant ? itemInfo.plant === i.plant : true))"
v-model="itemInfo.contract"
value-key="id"
label-key="name"
@@ -2463,7 +2512,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
@click="itemInfo.contract = null"
/>
<EntityModalButtons
type="projects"
type="contracts"
:id="itemInfo.contract"
:create-query="{customer: itemInfo.customer}"
@return-data="(data) => itemInfo.contract = data.id"