const nullableText = { type: ["string", "null"] } export const outgoingAddressSchema = { type: "object", description: "Abweichende Empfängeradresse; Feldnamen entsprechen dem Belegeditor.", properties: { street: nullableText, special: nullableText, zip: nullableText, city: nullableText }, additionalProperties: true, } export const outgoingRowsSchema = { type: "array", description: "Belegpositionen als Objekte. Beträge numerisch in EUR, unit als Einheiten-ID. Mengen und Preise dürfen für Korrekturpositionen negativ sein.", items: { type: "object", properties: { id: { type: "string", format: "uuid", description: "Optionale Positions-ID; wird sonst erzeugt." }, pos: { type: "string", description: "Positionsnummer, z. B. 1.1; wird sonst erzeugt." }, mode: { type: "string", enum: ["free", "normal", "service", "title", "text", "pagebreak"], default: "free" }, text: { type: "string" }, description: { type: "string", description: "Positionsbeschreibung. Ohne Angabe wird sie bei mode=normal/service aus Artikel bzw. Leistung übernommen, ebenso fehlender Name, Einheit, Preis und USt-Satz." }, descriptionText: { type: "string", description: "Veraltet; wird als description übernommen, wenn description fehlt." }, product: { type: "integer", minimum: 1, description: "Artikel-ID bei mode=normal." }, service: { type: "integer", minimum: 1, description: "Leistungs-ID bei mode=service." }, quantity: { type: "number", default: 1 }, unit: { type: "integer", minimum: 1 }, price: { type: "number", description: "Netto-Einzelpreis vor Positionsrabatt." }, inputPrice: { type: "number", description: "Eingegebener Einzelpreis; wird ohne price auch als price verwendet." }, purchasePrice: { type: "number" }, taxPercent: { type: "number", minimum: 0, maximum: 100 }, discountPercent: { type: "number", minimum: 0, maximum: 100, default: 0 }, costCentre: { type: ["string", "null"], format: "uuid", description: "Positionskostenstelle (abweichende Schreibweise zum Belegfeld costcentre)." }, optional: { type: "boolean" }, alternative: { type: "boolean" }, titleLevel: { type: "integer", minimum: 1, maximum: 3 }, linkedEntitys: { type: "array", items: { type: "object", properties: { type: { type: "string" }, subtype: { type: "string" }, id: { type: "integer", minimum: 1 } } }, }, }, // Preserve module-specific position fields used by existing callers. additionalProperties: true, }, } export const outgoingReportSchema = { type: "object", description: "Optionale, vom Aufrufer berechnete Kalkulationswerte. Diese Felder werden gespeichert, nicht durch MCP berechnet.", properties: { totalProductsPurchasePrice: { type: "number" }, totalProductsFromServicesPurchasePrice: { type: "number" }, totalMargin: { type: "number" }, totalHoursSellingPrice: { type: "number" }, totalHoursFromServices: { type: "object", properties: { total: { type: "number" }, totalPurchasePrice: { type: "number" }, byName: { type: "object", additionalProperties: { type: "number" } }, }, }, }, additionalProperties: true, }