feat(mcp): manage master data and cost centre hierarchies
This commit is contained in:
@@ -24,15 +24,25 @@ const adminPermissions = [
|
||||
"mcp.tokens.write",
|
||||
"staff.time.read_all",
|
||||
"masterdata.customers.read",
|
||||
"masterdata.customers.write",
|
||||
"masterdata.vendors.read",
|
||||
"masterdata.vendors.write",
|
||||
"masterdata.contacts.read",
|
||||
"masterdata.contacts.write",
|
||||
"masterdata.products.read",
|
||||
"masterdata.products.write",
|
||||
"masterdata.services.read",
|
||||
"masterdata.services.write",
|
||||
"masterdata.cost_centres.read",
|
||||
"masterdata.cost_centres.write",
|
||||
"masterdata.branches.read",
|
||||
"masterdata.branches.write",
|
||||
"masterdata.teams.read",
|
||||
"masterdata.teams.write",
|
||||
"masterdata.vehicles.read",
|
||||
"masterdata.vehicles.write",
|
||||
"masterdata.inventory_items.read",
|
||||
"masterdata.inventory_items.write",
|
||||
"masterdata.units.read",
|
||||
"accounting.outgoing_documents.read",
|
||||
"accounting.outgoing_documents.write",
|
||||
|
||||
56
backend/src/modules/cost-centre-hierarchy.service.ts
Normal file
56
backend/src/modules/cost-centre-hierarchy.service.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { FastifyInstance } from "fastify"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { costcentres } from "../../db/schema"
|
||||
|
||||
export async function validateCostCentreParent(
|
||||
server: FastifyInstance,
|
||||
tenantId: number,
|
||||
costCentreId: string | null,
|
||||
parentCostcentreId: string | null
|
||||
) {
|
||||
if (!parentCostcentreId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const hierarchyRows = await server.db
|
||||
.select({
|
||||
id: costcentres.id,
|
||||
parentCostcentre: costcentres.parentCostcentre,
|
||||
})
|
||||
.from(costcentres)
|
||||
.where(eq(costcentres.tenant, tenantId))
|
||||
|
||||
const hierarchyMap = new Map(
|
||||
hierarchyRows.map((row) => [row.id, row.parentCostcentre || null])
|
||||
)
|
||||
|
||||
if (!hierarchyMap.has(parentCostcentreId)) {
|
||||
return "Die übergeordnete Kostenstelle wurde nicht gefunden."
|
||||
}
|
||||
|
||||
if (costCentreId && parentCostcentreId === costCentreId) {
|
||||
return "Eine Kostenstelle kann nicht sich selbst als übergeordnete Kostenstelle haben."
|
||||
}
|
||||
|
||||
if (!costCentreId) {
|
||||
return null
|
||||
}
|
||||
|
||||
let currentParentId: string | null = parentCostcentreId
|
||||
const visited = new Set<string>()
|
||||
|
||||
while (currentParentId) {
|
||||
if (currentParentId === costCentreId) {
|
||||
return "Die ausgewählte übergeordnete Kostenstelle würde einen Zyklus erzeugen."
|
||||
}
|
||||
|
||||
if (visited.has(currentParentId)) {
|
||||
break
|
||||
}
|
||||
|
||||
visited.add(currentParentId)
|
||||
currentParentId = hierarchyMap.get(currentParentId) || null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user