Ausgangsbelege um Kostenstellenzuordnung erweitern
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
ALTER TABLE "createddocuments" ADD COLUMN "costcentre" uuid;
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "services" ADD COLUMN "costcentre" uuid;
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "createddocuments" ADD CONSTRAINT "createddocuments_costcentre_costcentres_id_fk" FOREIGN KEY ("costcentre") REFERENCES "public"."costcentres"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "services" ADD CONSTRAINT "services_costcentre_costcentres_id_fk" FOREIGN KEY ("costcentre") REFERENCES "public"."costcentres"("id") ON DELETE no action ON UPDATE no action;
|
||||||
@@ -344,6 +344,20 @@
|
|||||||
"when": 1780174800000,
|
"when": 1780174800000,
|
||||||
"tag": "0048_mobile_push_devices",
|
"tag": "0048_mobile_push_devices",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 49,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1780178400000,
|
||||||
|
"tag": "0049_email_cache",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 50,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1780261200000,
|
||||||
|
"tag": "0050_outgoing_document_costcentres",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { plants } from "./plants"
|
|||||||
import { authUsers } from "./auth_users"
|
import { authUsers } from "./auth_users"
|
||||||
import {serialExecutions} from "./serialexecutions";
|
import {serialExecutions} from "./serialexecutions";
|
||||||
import { outgoingsepamandates } from "./outgoingsepamandates"
|
import { outgoingsepamandates } from "./outgoingsepamandates"
|
||||||
|
import { costcentres } from "./costcentres"
|
||||||
|
|
||||||
export const createddocuments = pgTable("createddocuments", {
|
export const createddocuments = pgTable("createddocuments", {
|
||||||
id: bigint("id", { mode: "number" })
|
id: bigint("id", { mode: "number" })
|
||||||
@@ -49,6 +50,8 @@ export const createddocuments = pgTable("createddocuments", {
|
|||||||
() => projects.id
|
() => projects.id
|
||||||
),
|
),
|
||||||
|
|
||||||
|
costcentre: uuid("costcentre").references(() => costcentres.id),
|
||||||
|
|
||||||
documentNumber: text("documentNumber"),
|
documentNumber: text("documentNumber"),
|
||||||
documentDate: text("documentDate"),
|
documentDate: text("documentDate"),
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import { tenants } from "./tenants"
|
import { tenants } from "./tenants"
|
||||||
import { units } from "./units"
|
import { units } from "./units"
|
||||||
import { authUsers } from "./auth_users"
|
import { authUsers } from "./auth_users"
|
||||||
|
import { costcentres } from "./costcentres"
|
||||||
|
|
||||||
export const services = pgTable("services", {
|
export const services = pgTable("services", {
|
||||||
id: bigint("id", { mode: "number" })
|
id: bigint("id", { mode: "number" })
|
||||||
@@ -35,6 +36,8 @@ export const services = pgTable("services", {
|
|||||||
|
|
||||||
unit: bigint("unit", { mode: "number" }).references(() => units.id),
|
unit: bigint("unit", { mode: "number" }).references(() => units.id),
|
||||||
|
|
||||||
|
costcentre: uuid("costcentre").references(() => costcentres.id),
|
||||||
|
|
||||||
serviceNumber: bigint("serviceNumber", { mode: "number" }),
|
serviceNumber: bigint("serviceNumber", { mode: "number" }),
|
||||||
|
|
||||||
tags: jsonb("tags").default([]),
|
tags: jsonb("tags").default([]),
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ const buildOutgoingDocumentPayload = (
|
|||||||
if (args[field] !== undefined) payload[field] = numberArg(args, field)
|
if (args[field] !== undefined) payload[field] = numberArg(args, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.costcentre !== undefined) payload.costcentre = stringArg(args, "costcentre")
|
||||||
|
|
||||||
for (const field of ["paymentDays"] as const) {
|
for (const field of ["paymentDays"] as const) {
|
||||||
if (args[field] !== undefined) payload[field] = numberArg(args, field)
|
if (args[field] !== undefined) payload[field] = numberArg(args, field)
|
||||||
}
|
}
|
||||||
@@ -458,6 +460,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
contact: { type: "number" },
|
contact: { type: "number" },
|
||||||
contract: { type: "number" },
|
contract: { type: "number" },
|
||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
|
costcentre: { type: "string", description: "Kostenstellen-UUID als Belegvorgabe." },
|
||||||
plant: { type: "number" },
|
plant: { type: "number" },
|
||||||
documentDate: { type: "string" },
|
documentDate: { type: "string" },
|
||||||
deliveryDate: { type: "string" },
|
deliveryDate: { type: "string" },
|
||||||
@@ -512,6 +515,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
contact: { type: "number" },
|
contact: { type: "number" },
|
||||||
contract: { type: "number" },
|
contract: { type: "number" },
|
||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
|
costcentre: { type: "string", description: "Kostenstellen-UUID als Belegvorgabe." },
|
||||||
plant: { type: "number" },
|
plant: { type: "number" },
|
||||||
documentDate: { type: "string" },
|
documentDate: { type: "string" },
|
||||||
deliveryDate: { type: "string" },
|
deliveryDate: { type: "string" },
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ async function getSaveData(item: any, tenant: any, firstDate: string, lastDate:
|
|||||||
contract: item.contract,
|
contract: item.contract,
|
||||||
address: item.address,
|
address: item.address,
|
||||||
project: item.project,
|
project: item.project,
|
||||||
|
costcentre: item.costcentre,
|
||||||
documentDate: executionDate,
|
documentDate: executionDate,
|
||||||
deliveryDate: firstDate,
|
deliveryDate: firstDate,
|
||||||
deliveryDateEnd: lastDate,
|
deliveryDateEnd: lastDate,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export const resourceConfig = {
|
|||||||
table: contracts,
|
table: contracts,
|
||||||
searchColumns: ["name", "notes", "contractNumber", "paymentType", "billingInterval", "sepaRef", "bankingName"],
|
searchColumns: ["name", "notes", "contractNumber", "paymentType", "billingInterval", "sepaRef", "bankingName"],
|
||||||
numberRangeHolder: "contractNumber",
|
numberRangeHolder: "contractNumber",
|
||||||
mtoLoad: ["customer", "contracttype", "outgoingsepamandate"],
|
mtoLoad: ["customer", "contracttype", "contact", "outgoingsepamandate"],
|
||||||
},
|
},
|
||||||
outgoingsepamandates: {
|
outgoingsepamandates: {
|
||||||
table: outgoingsepamandates,
|
table: outgoingsepamandates,
|
||||||
@@ -230,7 +230,7 @@ export const resourceConfig = {
|
|||||||
},
|
},
|
||||||
createddocuments: {
|
createddocuments: {
|
||||||
table: createddocuments,
|
table: createddocuments,
|
||||||
mtoLoad: ["customer", "project", "contact", "contract", "plant","letterhead","createddocument", "outgoingsepamandate"],
|
mtoLoad: ["customer", "project", "costcentre", "contact", "contract", "plant","letterhead","createddocument", "outgoingsepamandate"],
|
||||||
mtmLoad: ["statementallocations","files","createddocuments"],
|
mtmLoad: ["statementallocations","files","createddocuments"],
|
||||||
mtmListLoad: ["statementallocations", "files"],
|
mtmListLoad: ["statementallocations", "files"],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const optionsToImport = ref({
|
|||||||
contactPerson: true,
|
contactPerson: true,
|
||||||
plant: true,
|
plant: true,
|
||||||
project:true,
|
project:true,
|
||||||
|
costcentre: true,
|
||||||
description: true,
|
description: true,
|
||||||
startText: false,
|
startText: false,
|
||||||
rows: true,
|
rows: true,
|
||||||
@@ -74,6 +75,7 @@ const mappings = ref({
|
|||||||
contactPerson: "Ansprechpartner Mitarbeiter",
|
contactPerson: "Ansprechpartner Mitarbeiter",
|
||||||
plant: "Objekt",
|
plant: "Objekt",
|
||||||
project: "Projekt",
|
project: "Projekt",
|
||||||
|
costcentre: "Kostenstelle",
|
||||||
description: "Beschreibung",
|
description: "Beschreibung",
|
||||||
startText: "Einleitung",
|
startText: "Einleitung",
|
||||||
rows: "Positionen",
|
rows: "Positionen",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const incomingInvoices = ref([])
|
const incomingInvoices = ref([])
|
||||||
|
const createddocuments = ref([])
|
||||||
const costcentres = ref([])
|
const costcentres = ref([])
|
||||||
const selectedYear = ref(String(dayjs().year()))
|
const selectedYear = ref(String(dayjs().year()))
|
||||||
const selectedMonth = ref("all")
|
const selectedMonth = ref("all")
|
||||||
@@ -98,7 +99,7 @@ const monthItems = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const reportRows = computed(() => {
|
const reportRows = computed(() => {
|
||||||
return incomingInvoices.value.flatMap((invoice) => {
|
const incomingRows = incomingInvoices.value.flatMap((invoice) => {
|
||||||
const invoiceDate = invoice.date ? dayjs(invoice.date) : null
|
const invoiceDate = invoice.date ? dayjs(invoice.date) : null
|
||||||
|
|
||||||
if (invoiceDate && invoiceDate.year().toString() !== selectedYear.value) {
|
if (invoiceDate && invoiceDate.year().toString() !== selectedYear.value) {
|
||||||
@@ -120,7 +121,8 @@ const reportRows = computed(() => {
|
|||||||
const accountCostCentre = costCentreMap.value.get(getCostCentreId(account.costCentre))
|
const accountCostCentre = costCentreMap.value.get(getCostCentreId(account.costCentre))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: `${invoice.id}-${index}`,
|
id: `incoming-${invoice.id}-${index}`,
|
||||||
|
sourceLabel: "Eingangsbeleg",
|
||||||
invoiceId: invoice.id,
|
invoiceId: invoice.id,
|
||||||
reference: invoice.reference || "-",
|
reference: invoice.reference || "-",
|
||||||
date: invoice.date,
|
date: invoice.date,
|
||||||
@@ -135,6 +137,53 @@ const reportRows = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const outgoingRows = createddocuments.value.flatMap((document) => {
|
||||||
|
const documentDate = document.documentDate ? dayjs(document.documentDate) : null
|
||||||
|
|
||||||
|
if (documentDate && documentDate.year().toString() !== selectedYear.value) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (documentDate && selectedMonth.value !== "all" && documentDate.month() + 1 !== Number(selectedMonth.value)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return (document.rows || [])
|
||||||
|
.filter((row) => !["pagebreak", "title", "text"].includes(row.mode))
|
||||||
|
.map((row, index) => {
|
||||||
|
const costCentreId = getCostCentreId(row.costCentre || row.costcentre || document.costcentre)
|
||||||
|
|
||||||
|
if (!relevantCostCentreIds.value.has(costCentreId)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const amountNet = Number((Number(row.quantity || 0) * Number(row.price || 0) * (1 - Number(row.discountPercent || 0) / 100)).toFixed(2))
|
||||||
|
const taxPercent = Number(row.taxPercent || 0)
|
||||||
|
const amountTax = Number((amountNet * (taxPercent / 100)).toFixed(2))
|
||||||
|
const amountGross = Number((amountNet + amountTax).toFixed(2))
|
||||||
|
const accountCostCentre = costCentreMap.value.get(costCentreId)
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: `outgoing-${document.id}-${index}`,
|
||||||
|
sourceLabel: "Ausgangsbeleg",
|
||||||
|
invoiceId: document.id,
|
||||||
|
reference: document.documentNumber || document.title || "-",
|
||||||
|
date: document.documentDate,
|
||||||
|
state: document.state || "-",
|
||||||
|
vendorName: document.customer?.name || "-",
|
||||||
|
accountLabel: "Umsatz",
|
||||||
|
costCentreName: accountCostCentre ? `${accountCostCentre.number} - ${accountCostCentre.name}` : "-",
|
||||||
|
description: row.text || row.description || document.description || "-",
|
||||||
|
amountNet,
|
||||||
|
amountTax,
|
||||||
|
amountGross
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
})
|
||||||
|
|
||||||
|
return [...incomingRows, ...outgoingRows]
|
||||||
})
|
})
|
||||||
|
|
||||||
const totals = computed(() => {
|
const totals = computed(() => {
|
||||||
@@ -147,9 +196,10 @@ const totals = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
{ accessorKey: "sourceLabel", header: "Art" },
|
||||||
{ accessorKey: "reference", header: "Beleg" },
|
{ accessorKey: "reference", header: "Beleg" },
|
||||||
{ accessorKey: "date", header: "Datum" },
|
{ accessorKey: "date", header: "Datum" },
|
||||||
{ accessorKey: "vendorName", header: "Lieferant" },
|
{ accessorKey: "vendorName", header: "Kontakt" },
|
||||||
{ accessorKey: "accountLabel", header: "Konto" },
|
{ accessorKey: "accountLabel", header: "Konto" },
|
||||||
{ accessorKey: "costCentreName", header: "Kostenstelle" },
|
{ accessorKey: "costCentreName", header: "Kostenstelle" },
|
||||||
{ accessorKey: "description", header: "Beschreibung" },
|
{ accessorKey: "description", header: "Beschreibung" },
|
||||||
@@ -163,10 +213,16 @@ const setupPage = async () => {
|
|||||||
|
|
||||||
costcentres.value = await useEntities("costcentres").select("*", null, false, true)
|
costcentres.value = await useEntities("costcentres").select("*", null, false, true)
|
||||||
const invoices = await useEntities("incominginvoices").select("*, vendor(id,name)")
|
const invoices = await useEntities("incominginvoices").select("*, vendor(id,name)")
|
||||||
|
const documents = await useEntities("createddocuments").select("*, customer(id,name)")
|
||||||
|
|
||||||
incomingInvoices.value = invoices.filter((invoice) =>
|
incomingInvoices.value = invoices.filter((invoice) =>
|
||||||
(invoice.accounts || []).some((account) => relevantCostCentreIds.value.has(account.costCentre))
|
(invoice.accounts || []).some((account) => relevantCostCentreIds.value.has(account.costCentre))
|
||||||
)
|
)
|
||||||
|
createddocuments.value = documents.filter((document) =>
|
||||||
|
["invoices", "advanceInvoices", "cancellationInvoices"].includes(document.type)
|
||||||
|
&& document.state === "Gebucht"
|
||||||
|
&& (document.rows || []).some((row) => relevantCostCentreIds.value.has(getCostCentreId(row.costCentre || row.costcentre || document.costcentre)))
|
||||||
|
)
|
||||||
|
|
||||||
const firstYear = yearItems.value[0]?.value
|
const firstYear = yearItems.value[0]?.value
|
||||||
if (firstYear && !yearItems.value.some((item) => item.value === selectedYear.value)) {
|
if (firstYear && !yearItems.value.some((item) => item.value === selectedYear.value)) {
|
||||||
@@ -264,7 +320,7 @@ setupPage()
|
|||||||
<div class="text-right font-medium tabular-nums">{{ currency(row.original.amountGross) }}</div>
|
<div class="text-right font-medium tabular-nums">{{ currency(row.original.amountGross) }}</div>
|
||||||
</template>
|
</template>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<TableEmptyState label="Keine Eingangsbelege mit dieser Kostenstelle oder ihren Unterkostenstellen gefunden" />
|
<TableEmptyState label="Keine Belege mit dieser Kostenstelle oder ihren Unterkostenstellen gefunden" />
|
||||||
</template>
|
</template>
|
||||||
</UTable>
|
</UTable>
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const itemInfo = ref({
|
|||||||
city: null,
|
city: null,
|
||||||
},
|
},
|
||||||
project: null,
|
project: null,
|
||||||
|
costcentre: null,
|
||||||
documentNumber: null,
|
documentNumber: null,
|
||||||
documentNumberTitle: "Rechnungsnummer",
|
documentNumberTitle: "Rechnungsnummer",
|
||||||
documentDate: dayjs(),
|
documentDate: dayjs(),
|
||||||
@@ -83,6 +84,7 @@ const letterheads = ref([])
|
|||||||
const createddocuments = ref([])
|
const createddocuments = ref([])
|
||||||
const projects = ref([])
|
const projects = ref([])
|
||||||
const plants = ref([])
|
const plants = ref([])
|
||||||
|
const costcentres = ref([])
|
||||||
const products = ref([])
|
const products = ref([])
|
||||||
const productcategories = ref([])
|
const productcategories = ref([])
|
||||||
const selectedProductcategorie = ref(null)
|
const selectedProductcategorie = ref(null)
|
||||||
@@ -126,6 +128,10 @@ const getContractNumber = (id) => findById(contracts.value, id)?.contractNumber
|
|||||||
const getLetterheadName = (id) => findById(letterheads.value, id)?.name || "Briefpapier nicht gefunden"
|
const getLetterheadName = (id) => findById(letterheads.value, id)?.name || "Briefpapier nicht gefunden"
|
||||||
const getPlantName = (id) => findById(plants.value, id)?.name || "Objekt nicht gefunden"
|
const getPlantName = (id) => findById(plants.value, id)?.name || "Objekt nicht gefunden"
|
||||||
const getProjectName = (id) => findById(projects.value, id)?.name || "Projekt nicht gefunden"
|
const getProjectName = (id) => findById(projects.value, id)?.name || "Projekt nicht gefunden"
|
||||||
|
const getCostCentreName = (id) => {
|
||||||
|
const costcentre = findById(costcentres.value, id)
|
||||||
|
return costcentre ? [costcentre.number, costcentre.name].filter(Boolean).join(" - ") : "Keine Kostenstelle ausgewählt"
|
||||||
|
}
|
||||||
const getSelectedLetterhead = () => findById(letterheads.value, itemInfo.value.letterhead)
|
const getSelectedLetterhead = () => findById(letterheads.value, itemInfo.value.letterhead)
|
||||||
const normalizeExternalUrl = (value) => {
|
const normalizeExternalUrl = (value) => {
|
||||||
if (!value || typeof value !== "string") return null
|
if (!value || typeof value !== "string") return null
|
||||||
@@ -216,6 +222,7 @@ const setupData = async () => {
|
|||||||
createddocuments.value = await useEntities("createddocuments").select("*")
|
createddocuments.value = await useEntities("createddocuments").select("*")
|
||||||
projects.value = await useEntities("projects").select("*")
|
projects.value = await useEntities("projects").select("*")
|
||||||
plants.value = await useEntities("plants").select("*")
|
plants.value = await useEntities("plants").select("*")
|
||||||
|
costcentres.value = await useEntities("costcentres").select("*")
|
||||||
services.value = await useEntities("services").select("*")
|
services.value = await useEntities("services").select("*")
|
||||||
servicecategories.value = await useEntities("servicecategories").select("*")
|
servicecategories.value = await useEntities("servicecategories").select("*")
|
||||||
products.value = await useEntities("products").select("*")
|
products.value = await useEntities("products").select("*")
|
||||||
@@ -336,6 +343,8 @@ const normalizeCreatedDocumentRow = (row) => {
|
|||||||
return {
|
return {
|
||||||
...normalizedRow,
|
...normalizedRow,
|
||||||
id: normalizedRow.id || uuidv4(),
|
id: normalizedRow.id || uuidv4(),
|
||||||
|
costCentre: normalizedRow.costCentre || normalizedRow.costcentre || null,
|
||||||
|
purchasePrice: Number(normalizedRow.purchasePrice || 0),
|
||||||
linkedEntitys: Array.isArray(normalizedRow.linkedEntitys) ? normalizedRow.linkedEntitys : [],
|
linkedEntitys: Array.isArray(normalizedRow.linkedEntitys) ? normalizedRow.linkedEntitys : [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -554,6 +563,7 @@ const setupPage = async () => {
|
|||||||
if (optionsToImport.contactPerson) itemInfo.value.contactPerson = linkedDocument.contactPerson
|
if (optionsToImport.contactPerson) itemInfo.value.contactPerson = linkedDocument.contactPerson
|
||||||
if (optionsToImport.plant) itemInfo.value.plant = linkedDocument.plant
|
if (optionsToImport.plant) itemInfo.value.plant = linkedDocument.plant
|
||||||
if (optionsToImport.project) itemInfo.value.project = linkedDocument.project
|
if (optionsToImport.project) itemInfo.value.project = linkedDocument.project
|
||||||
|
if (optionsToImport.costcentre) itemInfo.value.costcentre = linkedDocument.costcentre
|
||||||
if (optionsToImport.title) itemInfo.value.title = linkedDocument.title
|
if (optionsToImport.title) itemInfo.value.title = linkedDocument.title
|
||||||
if (optionsToImport.description) itemInfo.value.description = linkedDocument.description
|
if (optionsToImport.description) itemInfo.value.description = linkedDocument.description
|
||||||
if (optionsToImport.startText) itemInfo.value.startText = linkedDocument.startText
|
if (optionsToImport.startText) itemInfo.value.startText = linkedDocument.startText
|
||||||
@@ -580,6 +590,7 @@ const setupPage = async () => {
|
|||||||
itemInfo.value.contactPerson = linkedDocument.contactPerson
|
itemInfo.value.contactPerson = linkedDocument.contactPerson
|
||||||
itemInfo.value.plant = linkedDocument.plant
|
itemInfo.value.plant = linkedDocument.plant
|
||||||
itemInfo.value.project = linkedDocument.project
|
itemInfo.value.project = linkedDocument.project
|
||||||
|
itemInfo.value.costcentre = linkedDocument.costcentre
|
||||||
itemInfo.value.title = linkedDocument.title
|
itemInfo.value.title = linkedDocument.title
|
||||||
itemInfo.value.description = linkedDocument.description
|
itemInfo.value.description = linkedDocument.description
|
||||||
itemInfo.value.startText = linkedDocument.startText
|
itemInfo.value.startText = linkedDocument.startText
|
||||||
@@ -790,6 +801,7 @@ const importPositions = () => {
|
|||||||
price: advanceInvoiceData.value.part,
|
price: advanceInvoiceData.value.part,
|
||||||
taxPercent: 19,
|
taxPercent: 19,
|
||||||
discountPercent: 0,
|
discountPercent: 0,
|
||||||
|
costCentre: itemInfo.value.costcentre,
|
||||||
advanceInvoiceData: advanceInvoiceData.value
|
advanceInvoiceData: advanceInvoiceData.value
|
||||||
})
|
})
|
||||||
setPosNumbers()
|
setPosNumbers()
|
||||||
@@ -828,9 +840,11 @@ const addPosition = (mode) => {
|
|||||||
quantity: 1,
|
quantity: 1,
|
||||||
unit: 1,
|
unit: 1,
|
||||||
inputPrice: 0,
|
inputPrice: 0,
|
||||||
|
purchasePrice: 0,
|
||||||
price: 0,
|
price: 0,
|
||||||
taxPercent: taxPercentage,
|
taxPercent: taxPercentage,
|
||||||
discountPercent: 0,
|
discountPercent: 0,
|
||||||
|
costCentre: itemInfo.value.costcentre,
|
||||||
linkedEntitys: []
|
linkedEntitys: []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,6 +860,7 @@ const addPosition = (mode) => {
|
|||||||
taxPercent: taxPercentage,
|
taxPercent: taxPercentage,
|
||||||
discountPercent: 0,
|
discountPercent: 0,
|
||||||
unit: 1,
|
unit: 1,
|
||||||
|
costCentre: itemInfo.value.costcentre,
|
||||||
linkedEntitys: []
|
linkedEntitys: []
|
||||||
})
|
})
|
||||||
} else if (mode === 'service') {
|
} else if (mode === 'service') {
|
||||||
@@ -858,6 +873,7 @@ const addPosition = (mode) => {
|
|||||||
taxPercent: taxPercentage,
|
taxPercent: taxPercentage,
|
||||||
discountPercent: 0,
|
discountPercent: 0,
|
||||||
unit: 1,
|
unit: 1,
|
||||||
|
costCentre: itemInfo.value.costcentre,
|
||||||
linkedEntitys: []
|
linkedEntitys: []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1167,6 +1183,8 @@ const documentReport = computed(() => {
|
|||||||
let product = products.value.find(i => i.id === row.product)
|
let product = products.value.find(i => i.id === row.product)
|
||||||
|
|
||||||
totalProductsPurchasePrice += (product?.purchase_price || 0) * row.quantity
|
totalProductsPurchasePrice += (product?.purchase_price || 0) * row.quantity
|
||||||
|
} else if (row.mode === "free") {
|
||||||
|
totalProductsPurchasePrice += Number(row.purchasePrice || 0) * Number(row.quantity || 0)
|
||||||
|
|
||||||
} else if (row.service) {
|
} else if (row.service) {
|
||||||
let service = services.value.find(i => i.id === row.service)
|
let service = services.value.find(i => i.id === row.service)
|
||||||
@@ -1577,6 +1595,7 @@ const saveSerialInvoice = async () => {
|
|||||||
contract: normalizeEntityId(itemInfo.value.contract),
|
contract: normalizeEntityId(itemInfo.value.contract),
|
||||||
address: itemInfo.value.address,
|
address: itemInfo.value.address,
|
||||||
project: normalizeEntityId(itemInfo.value.project),
|
project: normalizeEntityId(itemInfo.value.project),
|
||||||
|
costcentre: itemInfo.value.costcentre,
|
||||||
paymentDays: itemInfo.value.paymentDays,
|
paymentDays: itemInfo.value.paymentDays,
|
||||||
payment_type: itemInfo.value.payment_type,
|
payment_type: itemInfo.value.payment_type,
|
||||||
outgoingsepamandate: normalizeEntityId(itemInfo.value.outgoingsepamandate),
|
outgoingsepamandate: normalizeEntityId(itemInfo.value.outgoingsepamandate),
|
||||||
@@ -1660,6 +1679,7 @@ const saveDocument = async (state, resetup = false) => {
|
|||||||
contract: normalizeEntityId(itemInfo.value.contract),
|
contract: normalizeEntityId(itemInfo.value.contract),
|
||||||
address: itemInfo.value.address,
|
address: itemInfo.value.address,
|
||||||
project: normalizeEntityId(itemInfo.value.project),
|
project: normalizeEntityId(itemInfo.value.project),
|
||||||
|
costcentre: itemInfo.value.costcentre,
|
||||||
plant: normalizeEntityId(itemInfo.value.plant),
|
plant: normalizeEntityId(itemInfo.value.plant),
|
||||||
documentNumber: itemInfo.value.documentNumber,
|
documentNumber: itemInfo.value.documentNumber,
|
||||||
documentDate: itemInfo.value.documentDate,
|
documentDate: itemInfo.value.documentDate,
|
||||||
@@ -1820,6 +1840,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
//row.unit = service.unit ? service.unit : services.value.find(i => i.id === row.service).unit
|
//row.unit = service.unit ? service.unit : services.value.find(i => i.id === row.service).unit
|
||||||
row.inputPrice = ((service.sellingPriceComposed.total || service.sellingPrice) ? (service.sellingPriceComposed.total || service.sellingPrice) : (services.value.find(i => i.id === row.service).sellingPriceComposed.total || services.value.find(i => i.id === row.service).sellingPrice))
|
row.inputPrice = ((service.sellingPriceComposed.total || service.sellingPrice) ? (service.sellingPriceComposed.total || service.sellingPrice) : (services.value.find(i => i.id === row.service).sellingPriceComposed.total || services.value.find(i => i.id === row.service).sellingPrice))
|
||||||
row.description = service.description ? service.description : (services.value.find(i => i.id === row.service) ? services.value.find(i => i.id === row.service).description : "")
|
row.description = service.description ? service.description : (services.value.find(i => i.id === row.service) ? services.value.find(i => i.id === row.service).description : "")
|
||||||
|
row.costCentre = service.costcentre || services.value.find(i => i.id === row.service)?.costcentre || itemInfo.value.costcentre
|
||||||
|
|
||||||
if (['13b UStG', '19 UStG'].includes(itemInfo.value.taxType)) {
|
if (['13b UStG', '19 UStG'].includes(itemInfo.value.taxType)) {
|
||||||
row.taxPercent = 0
|
row.taxPercent = 0
|
||||||
@@ -1832,6 +1853,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
console.log("Product Detected")
|
console.log("Product Detected")
|
||||||
row.unit = product.unit ? product.unit : products.value.find(i => i.id === row.product).unit
|
row.unit = product.unit ? product.unit : products.value.find(i => i.id === row.product).unit
|
||||||
row.inputPrice = (product.selling_price ? product.selling_price : products.value.find(i => i.id === row.product).selling_price)
|
row.inputPrice = (product.selling_price ? product.selling_price : products.value.find(i => i.id === row.product).selling_price)
|
||||||
|
row.costCentre = row.costCentre || itemInfo.value.costcentre
|
||||||
//row.price = Number((row.originalPrice * (1 + itemInfo.value.customSurchargePercentage /100)).toFixed(2))
|
//row.price = Number((row.originalPrice * (1 + itemInfo.value.customSurchargePercentage /100)).toFixed(2))
|
||||||
row.description = product.description ? product.description : (products.value.find(i => i.id === row.product) ? products.value.find(i => i.id === row.product).description : "")
|
row.description = product.description ? product.description : (products.value.find(i => i.id === row.product) ? products.value.find(i => i.id === row.product).description : "")
|
||||||
|
|
||||||
@@ -2512,6 +2534,41 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
|
||||||
|
</UFormField>
|
||||||
|
<UFormField
|
||||||
|
label="Kostenstelle:"
|
||||||
|
>
|
||||||
|
<InputGroup>
|
||||||
|
<USelectMenu
|
||||||
|
:items="costcentres"
|
||||||
|
v-model="itemInfo.costcentre"
|
||||||
|
value-key="id"
|
||||||
|
label-key="name"
|
||||||
|
:search-input="{ placeholder: 'Suche...' }"
|
||||||
|
:filter-fields="['name', 'number']"
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
{{ getCostCentreName(itemInfo.costcentre) }}
|
||||||
|
</template>
|
||||||
|
<template #item="{ item: costcentre }">
|
||||||
|
{{ [costcentre.number, costcentre.name].filter(Boolean).join(" - ") }}
|
||||||
|
</template>
|
||||||
|
</USelectMenu>
|
||||||
|
<UButton
|
||||||
|
variant="outline"
|
||||||
|
color="error"
|
||||||
|
v-if="itemInfo.costcentre"
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
@click="itemInfo.costcentre = null"
|
||||||
|
/>
|
||||||
|
<EntityModalButtons
|
||||||
|
type="costcentres"
|
||||||
|
:id="itemInfo.costcentre"
|
||||||
|
@return-data="(data) => itemInfo.costcentre = data.id"
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
|
||||||
</UFormField>
|
</UFormField>
|
||||||
<UFormField
|
<UFormField
|
||||||
label="Vertrag:"
|
label="Vertrag:"
|
||||||
@@ -2727,7 +2784,9 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
<th class="pl-2">Name</th>
|
<th class="pl-2">Name</th>
|
||||||
<th class="pl-2">Menge</th>
|
<th class="pl-2">Menge</th>
|
||||||
<th class="pl-2">Einheit</th>
|
<th class="pl-2">Einheit</th>
|
||||||
|
<th class="pl-2">Kostenstelle</th>
|
||||||
<th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Preis</th>
|
<th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Preis</th>
|
||||||
|
<th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">EK</th>
|
||||||
<!-- <th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Steuer</th>
|
<!-- <th class="pl-2" v-if="!deliveryNoteLikeDocumentTypes.includes(itemInfo.type)">Steuer</th>
|
||||||
<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>
|
||||||
@@ -2752,13 +2811,13 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
v-if="row.mode === 'pagebreak'"
|
v-if="row.mode === 'pagebreak'"
|
||||||
colspan="7"
|
colspan="9"
|
||||||
>
|
>
|
||||||
<USeparator/>
|
<USeparator/>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
v-if="row.mode === 'text'"
|
v-if="row.mode === 'text'"
|
||||||
colspan="7"
|
colspan="9"
|
||||||
>
|
>
|
||||||
<!-- <UInput
|
<!-- <UInput
|
||||||
v-model="row.text"
|
v-model="row.text"
|
||||||
@@ -2972,6 +3031,28 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
</td>
|
</td>
|
||||||
|
<td
|
||||||
|
class="w-full"
|
||||||
|
v-if="!['pagebreak','title','text'].includes(row.mode)"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="row.costCentre"
|
||||||
|
:disabled="itemInfo.type === 'cancellationInvoices'"
|
||||||
|
:items="costcentres"
|
||||||
|
label-key="name"
|
||||||
|
value-key="id"
|
||||||
|
:search-input="{ placeholder: 'Suche...' }"
|
||||||
|
:filter-fields="['name', 'number']"
|
||||||
|
class="w-44"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
<span class="truncate">{{ getCostCentreName(row.costCentre) }}</span>
|
||||||
|
</template>
|
||||||
|
<template #item="{ item: costcentre }">
|
||||||
|
{{ [costcentre.number, costcentre.name].filter(Boolean).join(" - ") }}
|
||||||
|
</template>
|
||||||
|
</USelectMenu>
|
||||||
|
</td>
|
||||||
<td
|
<td
|
||||||
class="w-full"
|
class="w-full"
|
||||||
v-if="!['pagebreak','title','text'].includes(row.mode) && !deliveryNoteLikeDocumentTypes.includes(itemInfo.type)"
|
v-if="!['pagebreak','title','text'].includes(row.mode) && !deliveryNoteLikeDocumentTypes.includes(itemInfo.type)"
|
||||||
@@ -3004,6 +3085,24 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
</template>
|
</template>
|
||||||
</UInput>
|
</UInput>
|
||||||
</td>
|
</td>
|
||||||
|
<td
|
||||||
|
class="w-full"
|
||||||
|
v-if="!['pagebreak','title','text'].includes(row.mode) && !deliveryNoteLikeDocumentTypes.includes(itemInfo.type)"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-if="row.mode === 'free'"
|
||||||
|
v-model="row.purchasePrice"
|
||||||
|
:disabled="itemInfo.type === 'cancellationInvoices'"
|
||||||
|
type="number"
|
||||||
|
step="0.001"
|
||||||
|
class="w-28"
|
||||||
|
>
|
||||||
|
<template #leading>
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
|
||||||
|
</template>
|
||||||
|
</UInput>
|
||||||
|
<span v-else class="text-gray-400">-</span>
|
||||||
|
</td>
|
||||||
<!-- <td
|
<!-- <td
|
||||||
class="w-40"
|
class="w-40"
|
||||||
v-if="!['pagebreak','title','text'].includes(row.mode)&& !deliveryNoteLikeDocumentTypes.includes(itemInfo.type)"
|
v-if="!['pagebreak','title','text'].includes(row.mode)&& !deliveryNoteLikeDocumentTypes.includes(itemInfo.type)"
|
||||||
@@ -3324,7 +3423,7 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
|
|||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
v-if="row.mode === 'title'"
|
v-if="row.mode === 'title'"
|
||||||
colspan="6"
|
colspan="8"
|
||||||
>
|
>
|
||||||
<UInput
|
<UInput
|
||||||
:disabled="itemInfo.type === 'cancellationInvoices'"
|
:disabled="itemInfo.type === 'cancellationInvoices'"
|
||||||
|
|||||||
@@ -2964,7 +2964,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
labelSingle: "Leistung",
|
labelSingle: "Leistung",
|
||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
redirect: true,
|
redirect: true,
|
||||||
selectWithInformation: "*, unit(*)",
|
selectWithInformation: "*, unit(*), costcentre(*)",
|
||||||
historyItemHolder: "service",
|
historyItemHolder: "service",
|
||||||
filters: [{
|
filters: [{
|
||||||
name: "Archivierte ausblenden",
|
name: "Archivierte ausblenden",
|
||||||
@@ -3019,6 +3019,15 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
{label: "0 %", key: 0}]
|
{label: "0 %", key: 0}]
|
||||||
//TODO: Default Value
|
//TODO: Default Value
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "costcentre",
|
||||||
|
label: "Kostenstellen-Vorauswahl",
|
||||||
|
inputType: "select",
|
||||||
|
selectDataType: "costcentres",
|
||||||
|
selectOptionAttribute: "name",
|
||||||
|
selectSearchAttributes: ["name", "number"],
|
||||||
|
component: costcentre
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "servicecategories",
|
key: "servicecategories",
|
||||||
label: "Leistungskategorien",
|
label: "Leistungskategorien",
|
||||||
|
|||||||
Reference in New Issue
Block a user