KI-AGENT: Dropdown zum Einfügen von Dokumentpositionen ergänzt

This commit is contained in:
2026-07-15 10:15:11 +02:00
parent 31ef408b66
commit 1711f975bb

View File

@@ -826,21 +826,18 @@ const getRowAmountUndiscounted = (row) => {
return String(Number(Number(row.quantity) * Number(row.price)).toFixed(2)).replace('.', ',') return String(Number(Number(row.quantity) * Number(row.price)).toFixed(2)).replace('.', ',')
} }
const addPosition = (mode) => { const positionAddOptions = [
{ mode: 'service', label: 'Leistung', icon: 'i-heroicons-wrench-screwdriver' },
let lastId = 0 { mode: 'normal', label: 'Artikel', icon: 'i-heroicons-cube' },
itemInfo.value.rows.forEach(row => { { mode: 'free', label: 'Freie Position', icon: 'i-heroicons-pencil-square' },
if (row.id > lastId) lastId = row.id { mode: 'pagebreak', label: 'Seitenumbruch', icon: 'i-heroicons-document-minus' },
}) { mode: 'title', label: 'Titel', icon: 'i-heroicons-bars-3-bottom-left' },
{ mode: 'text', label: 'Text', icon: 'i-heroicons-document-text' }
let taxPercentage = 19 ]
if (['13b UStG', '19 UStG', '12.3 UStG'].includes(itemInfo.value.taxType)) {
taxPercentage = 0
}
const createPositionRow = (mode, taxPercentage) => {
if (mode === 'free') { if (mode === 'free') {
let rowData = { const rowData = {
id: uuidv4(), id: uuidv4(),
mode: "free", mode: "free",
text: "", text: "",
@@ -855,10 +852,11 @@ const addPosition = (mode) => {
linkedEntitys: [] linkedEntitys: []
} }
itemInfo.value.rows.push({...rowData, ...auth.activeTenantData.extraModules.includes("agriculture") ? {agriculture: {}} : {}}) return {...rowData, ...auth.activeTenantData.extraModules.includes("agriculture") ? {agriculture: {}} : {}}
}
} else if (mode === 'normal') { if (mode === 'normal') {
itemInfo.value.rows.push({ return {
id: uuidv4(), id: uuidv4(),
mode: "normal", mode: "normal",
quantity: 1, quantity: 1,
@@ -869,9 +867,11 @@ const addPosition = (mode) => {
unit: 1, unit: 1,
costCentre: itemInfo.value.costcentre, costCentre: itemInfo.value.costcentre,
linkedEntitys: [] linkedEntitys: []
}) }
} else if (mode === 'service') { }
let rowData = {
if (mode === 'service') {
const rowData = {
id: uuidv4(), id: uuidv4(),
mode: "service", mode: "service",
quantity: 1, quantity: 1,
@@ -884,26 +884,63 @@ const addPosition = (mode) => {
linkedEntitys: [] linkedEntitys: []
} }
//Push Agriculture Holder only if Module is activated return {...rowData, ...auth.activeTenantData.extraModules.includes("agriculture") ? {agriculture: {}} : {}}
itemInfo.value.rows.push({...rowData, ...auth.activeTenantData.extraModules.includes("agriculture") ? {agriculture: {}} : {}}) }
} else if (mode === "pagebreak") {
itemInfo.value.rows.push({ if (mode === "pagebreak") {
return {
id: uuidv4(), id: uuidv4(),
mode: "pagebreak", mode: "pagebreak",
linkedEntitys: [] linkedEntitys: []
}) }
} else if (mode === "title") { }
itemInfo.value.rows.push({
if (mode === "title") {
return {
id: uuidv4(), id: uuidv4(),
mode: "title", mode: "title",
linkedEntitys: [] linkedEntitys: []
}) }
} else if (mode === "text") { }
itemInfo.value.rows.push({
if (mode === "text") {
return {
id: uuidv4(), id: uuidv4(),
mode: "text", mode: "text",
linkedEntitys: [] linkedEntitys: []
}) }
}
return null
}
const getPositionAddMenuItems = (row) => [
positionAddOptions.map(option => ({
...option,
onSelect: () => addPosition(option.mode, row?.id)
}))
]
const getFullWidthPositionColspan = () => deliveryNoteLikeDocumentTypes.includes(itemInfo.value.type) ? 5 : 8
const getTitlePositionColspan = () => deliveryNoteLikeDocumentTypes.includes(itemInfo.value.type) ? 4 : 7
const addPosition = (mode, afterRowId = null) => {
let taxPercentage = 19
if (['13b UStG', '19 UStG', '12.3 UStG'].includes(itemInfo.value.taxType)) {
taxPercentage = 0
}
const newRow = createPositionRow(mode, taxPercentage)
if (!newRow) return
const insertAfterIndex = afterRowId ? itemInfo.value.rows.findIndex(row => row.id === afterRowId) : -1
if (insertAfterIndex >= 0) {
itemInfo.value.rows.splice(insertAfterIndex + 1, 0, newRow)
} else {
itemInfo.value.rows.push(newRow)
} }
setPosNumbers() setPosNumbers()
@@ -2797,6 +2834,8 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
<th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Rabatt</th>--> <th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Rabatt</th>-->
<th class="pl-2"></th> <th class="pl-2"></th>
<th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Gesamt</th> <th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Gesamt</th>
<th class="pl-2"></th>
<th class="pl-2"></th>
</tr> </tr>
</thead> </thead>
<draggable <draggable
@@ -2817,13 +2856,13 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
</td> </td>
<td <td
v-if="row.mode === 'pagebreak'" v-if="row.mode === 'pagebreak'"
colspan="8" :colspan="getFullWidthPositionColspan()"
> >
<USeparator/> <USeparator/>
</td> </td>
<td <td
v-if="row.mode === 'text'" v-if="row.mode === 'text'"
colspan="8" :colspan="getFullWidthPositionColspan()"
> >
<!-- <UInput <!-- <UInput
v-model="row.text" v-model="row.text"
@@ -3430,7 +3469,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
</td> </td>
<td <td
v-if="row.mode === 'title'" v-if="row.mode === 'title'"
colspan="7" :colspan="getTitlePositionColspan()"
> >
<UInput <UInput
:disabled="itemInfo.type === 'cancellationInvoices'" :disabled="itemInfo.type === 'cancellationInvoices'"
@@ -3439,6 +3478,19 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
class="w-full" class="w-full"
/> />
</td> </td>
<td>
<UDropdownMenu
:items="getPositionAddMenuItems(row)"
:content="{ align: 'end' }"
>
<UButton
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
variant="ghost"
color="primary"
icon="i-heroicons-plus"
/>
</UDropdownMenu>
</td>
<td> <td>
<UButton <UButton
:disabled="itemInfo.type === 'cancellationInvoices'" :disabled="itemInfo.type === 'cancellationInvoices'"
@@ -3462,46 +3514,13 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
<InputGroup> <InputGroup>
<UButton <UButton
@click="addPosition('service')" v-for="option in positionAddOptions"
:key="option.mode"
@click="addPosition(option.mode)"
class="mt-3" class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)" :disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
> >
+ Leistung + {{ option.label }}
</UButton>
<UButton
@click="addPosition('normal')"
class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
>
+ Artikel
</UButton>
<UButton
@click="addPosition('free')"
class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
>
+ Freie Position
</UButton>
<UButton
@click="addPosition('pagebreak')"
class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
>
+ Seitenumbruch
</UButton>
<UButton
@click="addPosition('title')"
class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
>
+ Titel
</UButton>
<UButton
@click="addPosition('text')"
class="mt-3"
:disabled="['advanceInvoices','cancellationInvoices'].includes(itemInfo.type)"
>
+ Text
</UButton> </UButton>
</InputGroup> </InputGroup>