diff --git a/src/defaultSkills/drafts.SKILL b/src/defaultSkills/drafts.SKILL index e5285cc..922d072 100644 --- a/src/defaultSkills/drafts.SKILL +++ b/src/defaultSkills/drafts.SKILL @@ -1,14 +1,13 @@ -VFS Drafts: Collaborative Quote, Order, and Delivery Editing +VFS Drafts: Collaborative Quote and Order Editing # Overview The virtual directory `drafts/` in VFS allows the LLM agent and the frontend user to collaborate in real time on in-progress commercial documents. Drafts are stateful forms maintained in the frontend application and synchronized with the backend. -There are three virtual draft files: +There are two virtual draft files: 1. `drafts/quote` : Sales Quote / Angebot (Customer sales proposal) 2. `drafts/order` : Sales Order / Auftrag & Bestellung (Customer order confirmation) -3. `drafts/delivery` : Goods Inbound / Wareneingang & Lieferschein (Supplier delivery receipt) --- @@ -31,7 +30,7 @@ Every draft file contains a root object with a `manifest` property conforming to "properties": { "kind": { "type": "string", - "enum": ["quote", "order", "delivery"], + "enum": ["quote", "order"], "description": "Document type" }, "mode": { @@ -50,7 +49,7 @@ Every draft file contains a root object with a `manifest` property conforming to }, "partyId": { "type": ["integer", "null"], - "description": "Customer entity.id for quotes/orders; supplier.id for deliveries" + "description": "Customer entity.id for quotes and orders" }, "number": { "type": ["string", "null"], @@ -381,157 +380,3 @@ Used for customer order confirmations and sales orders (Aufträge & Bestellungen } } ``` - ---- - -## 4. Goods Inbound Delivery Draft (`drafts/delivery`) - -Used for inbound delivery receipts from suppliers (Wareneingang & Lieferscheine). - -### Complete Delivery JSON Schema -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DeliveryDraft", - "type": "object", - "required": ["manifest"], - "properties": { - "manifest": { - "type": "object", - "required": ["kind", "mode", "lines"], - "properties": { - "kind": { "type": "string", "const": "delivery" }, - "mode": { "type": "string", "enum": ["create", "edit"] }, - "id": { "type": ["integer", "null"] }, - "date": { - "type": ["string", "null"], - "format": "date", - "description": "Delivery arrival / receipt date (Lieferdatum, YYYY-MM-DD)" - }, - "partyId": { - "type": ["integer", "null"], - "description": "Supplier ID (supplier.id / entity_id)" - }, - "number": { - "type": ["string", "null"], - "description": "Delivery manifest number (allocated by system sequence upon creation)" - }, - "externalNumber": { - "type": ["string", "null"], - "description": "Supplier delivery slip number (Lieferschein-Nr. des Lieferanten)" - }, - "comment": { - "type": ["string", "null"], - "description": "Warehouse receipt remarks or gate notes" - }, - "lines": { - "type": "array", - "items": { - "type": "object", - "required": ["name", "amount", "net", "taxrate"], - "properties": { - "pos": { - "type": "integer", - "minimum": 1, - "description": "Position line number (1, 2, 3...)" - }, - "sku": { - "type": ["string", "null"], - "description": "Article SKU (internal SKU or matched supplier SKU)" - }, - "name": { - "type": "string", - "description": "Delivered article name" - }, - "amount": { - "type": "number", - "exclusiveMinimum": 0, - "description": "Delivered quantity received into warehouse" - }, - "pu": { - "type": "number", - "minimum": 1, - "default": 1, - "description": "Packaging unit / VPE (default 1)" - }, - "net": { - "type": "number", - "minimum": 0, - "description": "Purchase cost net per unit in EUR (EK netto)" - }, - "gross": { - "type": ["number", "null"], - "description": "Purchase cost gross per unit in EUR (EK brutto)" - }, - "taxrate": { - "type": "number", - "minimum": 0, - "description": "Input tax percentage (e.g. 19 or 7)" - }, - "rebate": { - "type": "number", - "minimum": 0, - "maximum": 100, - "default": 0, - "description": "Supplier discount percentage" - }, - "unit": { - "type": ["string", "null"], - "description": "Unit of measurement" - }, - "comment": { - "type": ["string", "null"], - "description": "Batch number, lot, condition, or storage bin note" - } - } - } - } - } - } - } -} -``` - -### Complete Delivery Example -```json -{ - "manifest": { - "kind": "delivery", - "mode": "create", - "id": null, - "date": "2026-10-14", - "partyId": 12, - "number": null, - "externalNumber": "LS-SUP-99412", - "comment": "Ware unbeschädigt auf Palette 3 angeliefert.", - "lines": [ - { - "pos": 1, - "sku": "42001257", - "name": "1 Pot 8L System inkl. 47L Wasserfass", - "amount": 20, - "pu": 1, - "net": 38.50, - "gross": 45.82, - "taxrate": 19, - "rebate": 0, - "unit": "Stück", - "comment": "Palette A-04" - }, - { - "pos": 2, - "sku": "42000009", - "name": "Autopot Easy2Grow Erweiterungsset 2Pot", - "amount": 50, - "pu": 1, - "net": 24.00, - "gross": 28.56, - "taxrate": 19, - "rebate": 3, - "unit": "Stück", - "comment": "Karton 1 bis 5" - } - ] - } -} -``` diff --git a/src/defaultSkills/process-incoming-product-and-invoices.SKILL b/src/defaultSkills/process-incoming-product-and-invoices.SKILL new file mode 100644 index 0000000..3a2c08a --- /dev/null +++ b/src/defaultSkills/process-incoming-product-and-invoices.SKILL @@ -0,0 +1,305 @@ +Process Incoming Product and Invoices: Extraction & Delivery Drafts + +# Overview + +This skill guides the automated and interactive processing of inbound supplier documents (invoices / *Rechnungen* and delivery notes / *Lieferscheine*). +It covers: +1. **Document Data Extraction**: Extracting structured metadata, packaging units (VPE), units of measurement, line items, and notes from document text/images via the `output_manifest` tool. +2. **Goods Inbound Delivery Draft (`drafts/delivery`)**: Storing and maintaining the inbound receipt in the virtual file system (`drafts/delivery`) for real-time collaboration with the user in the UI. + +--- + +# 1. Document Extraction Rules & Prompt Logic + +When reading or processing an invoice or delivery note, follow these core rules: + +## General Extraction Rules +- **Document Type (`manifestType`)**: `"rechnung"` or `"lieferschein"`. For `"lieferschein"`, prices (`eknetto`) and taxes (`mwst`) must be `null`. +- **Exclude Non-Product Lines**: Exclude freight, shipping, postage, pallet charges, packaging disposal fees, and handling surcharges. Only include physical inventory products. +- **Line Items**: Extract `position`, `count`, `vpe` (default: 1), `unit`, `articleName`, `liefArtNr`, `mwst` (7, 19, or null), and `eknetto` per piece in euro cents (or null). +- **Supplier Matching**: Match the supplier against known company suppliers to identify `lieferant_id` and `lieferantName`. For unknown suppliers, extract `lieferantName` as string and set `lieferant_id` to `null`. +- **Notes Strictly in German**: Record all notes, ambiguities, packaging assumptions, or excluded line details in German. These notes assist a human reviewer in double-checking results. +- **Delta / Batching Updates**: The `output_manifest` tool consists of three optional components: `basedata`, `notes`, and `items`. Only include a component when it carries genuinely new or changed data; omit unchanged components. + - Include `basedata` ONLY when at least one field is currently null/empty or value actually changes. + - Include `items` ONLY when new product line items are being added. + - Include `notes` ONLY when there is a genuinely new noteworthy detail. + +## VPE (Verpackungseinheit) Logic +VPE represents the number of individually sellable units inside a bulk item. If not explicitly split for individual sale, default to 1. +- `"20 Boxen á 10 Stück"` -> `vpe = 20`. +- `"10 Gläser á 100 Filter"` -> `vpe = 10` (the 10 glasses are sold individually). +- `"100 Stück"` -> `vpe = 1` (sold as one bulk pack). +- Typical sellable VPEs are containers like *Beutel*, *Gläser*, *Boxen*, *Hefte*, not loose sub-components. +- In `"Y Hefte á X Blatt"` the VPE is NOT X, but `Y`. +- A "Display" represents a VPE: `"20er Display"` means `vpe = 20`. +- `eknetto` is the price of one full VPE. + +## Unit (ME) Rules +- The unit (ME) must ALWAYS refer to the individual sellable item (e.g. `Stk.`, `Beutel`, `Flasche`, `Box`, `Set`). It must **NEVER** be `"VE"` or `"VPE"`. +- A packaging size like `"VE100"` means the bulk pack contains 100 individual items: set `vpe = 100` and `unit = "Stk."` (or the relevant individual unit). +- Example: `"Einhängesiebe Stahl, VE100"` -> `vpe = 100`, `unit = "Stk."`, `count = 1` (one bulk pack of 100 sieves). + +--- + +# 2. Extraction Tool Specification (`output_manifest`) + +The extraction engine outputs structured findings via the `output_manifest` tool call. + +```json +{ + "name": "output_manifest", + "description": "Stores extracted invoice/delivery-note data: header metadata (basedata), notes, and product line items. Each component is strictly optional — only include the ones that carry new data.", + "strict": false, + "parameters": { + "type": "object", + "additionalProperties": false, + "required": [], + "properties": { + "basedata": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "date": { "type": ["string", "null"], "description": "Document date (ISO 8601, YYYY-MM-DD)" }, + "lieferant_id": { "type": ["number", "null"], "description": "Lieferant ID if matched, else null" }, + "lieferantName": { "type": "string", "description": "Supplier name" }, + "manifestNr": { "type": ["string", "null"], "description": "Lieferscheinnummer or Rechnungsnummer" }, + "manifestType": { + "anyOf": [ + { "type": "string", "enum": ["rechnung", "lieferschein"] }, + { "type": "null" } + ], + "description": "Document type" + } + } + }, + { "type": "null" } + ], + "description": "Header/metadata. Only include fields that are currently missing or changed." + }, + "notes": { + "anyOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "null" } + ], + "description": "New noteworthy details (in German), for a human to double-check the result." + }, + "items": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "numberOfItemsToAdd": { "type": "number", "description": "Number of NEW line items being added in this call." }, + "items": { + "type": "array", + "description": "Invoice/delivery product line items", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["position", "count", "vpe", "unit", "articleName", "liefArtNr", "mwst", "eknetto"], + "properties": { + "position": { "type": "number", "description": "Position number" }, + "count": { "type": "number", "description": "Quantity (Menge)" }, + "vpe": { "type": "number", "description": "Packaging unit size (VPE). Default: 1." }, + "unit": { "type": "string", "description": "Unit of the individual sellable item. NEVER 'VE' or 'VPE'." }, + "articleName": { "type": "string", "description": "Article name" }, + "liefArtNr": { "type": "string", "description": "Supplier article number" }, + "mwst": { + "anyOf": [{ "type": "string", "enum": ["7", "19"] }, { "type": "null" }], + "description": "VAT rate percentage; null if delivery note or missing" + }, + "eknetto": { "type": ["number", "null"], "description": "Net purchase price per VPE in euro cents; null if missing" } + } + } + } + } + }, + { "type": "null" } + ], + "description": "New product line items." + } + } + } +} +``` + +--- + +# 3. Goods Inbound Delivery Draft (`drafts/delivery`) + +Inbound deliveries are staged and edited as drafts in the virtual file system under `drafts/delivery`. +This allows the agent and frontend user to review, correct, and finalize stock receipts and purchase costs before committing them into the inventory ledger. + +## Field Mapping from Extracted Manifest to Delivery Draft +- **`date`**: Document date (`YYYY-MM-DD`). +- **`partyId`**: Supplier ID (`lieferant_id` / `entity.id`). +- **`externalNumber`**: Supplier delivery slip number or invoice number (`manifestNr`). +- **`comment`**: Human-readable notes, inspection remarks, storage location, or extraction caveats. +- **`lines`**: + - `pos`: 1-based position line number. + - `sku`: Internal article SKU or matched supplier SKU (`liefArtNr`). + - `name`: Delivered product name (`articleName`). + - `amount`: Quantity delivered (`count`). + - `pu`: Packaging unit size (`vpe`, default `1`). + - `net`: Purchase cost net per unit in EUR (`eknetto / 100`, or `0` for delivery notes without prices). + - `gross`: Purchase cost gross per unit in EUR (`net * (1 + taxrate/100)`). + - `taxrate`: Input tax rate percentage (`19`, `7`, or `0`). + - `rebate`: Supplier discount percentage (default `0`). + - `unit`: Individual sellable unit (e.g. `Stück`, `Beutel`, `Flasche`). + - `comment`: Specific batch, lot, or packaging comment. + +--- + +## Delivery Draft JSON Schema + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "DeliveryDraft", + "type": "object", + "required": ["manifest"], + "properties": { + "manifest": { + "type": "object", + "required": ["kind", "mode", "lines"], + "properties": { + "kind": { "type": "string", "const": "delivery" }, + "mode": { "type": "string", "enum": ["create", "edit"] }, + "id": { "type": ["integer", "null"] }, + "date": { + "type": ["string", "null"], + "format": "date", + "description": "Delivery arrival / receipt date (Lieferdatum, YYYY-MM-DD)" + }, + "partyId": { + "type": ["integer", "null"], + "description": "Supplier ID (supplier.id / entity_id)" + }, + "number": { + "type": ["string", "null"], + "description": "Delivery manifest number (allocated by system sequence upon creation)" + }, + "externalNumber": { + "type": ["string", "null"], + "description": "Supplier delivery slip number (Lieferschein-Nr. des Lieferanten)" + }, + "comment": { + "type": ["string", "null"], + "description": "Warehouse receipt remarks or gate notes" + }, + "lines": { + "type": "array", + "items": { + "type": "object", + "required": ["name", "amount", "net", "taxrate"], + "properties": { + "pos": { + "type": "integer", + "minimum": 1, + "description": "Position line number (1, 2, 3...)" + }, + "sku": { + "type": ["string", "null"], + "description": "Article SKU (internal SKU or matched supplier SKU)" + }, + "name": { + "type": "string", + "description": "Delivered article name" + }, + "amount": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Delivered quantity received into warehouse" + }, + "pu": { + "type": "number", + "minimum": 1, + "default": 1, + "description": "Packaging unit / VPE (default 1)" + }, + "net": { + "type": "number", + "minimum": 0, + "description": "Purchase cost net per unit in EUR (EK netto)" + }, + "gross": { + "type": ["number", "null"], + "description": "Purchase cost gross per unit in EUR (EK brutto)" + }, + "taxrate": { + "type": "number", + "minimum": 0, + "description": "Input tax percentage (e.g. 19 or 7)" + }, + "rebate": { + "type": "number", + "minimum": 0, + "maximum": 100, + "default": 0, + "description": "Supplier discount percentage" + }, + "unit": { + "type": ["string", "null"], + "description": "Unit of measurement" + }, + "comment": { + "type": ["string", "null"], + "description": "Batch number, lot, condition, or storage bin note" + } + } + } + } + } + } + } +} +``` + +--- + +## Delivery Draft Complete Example + +```json +{ + "manifest": { + "kind": "delivery", + "mode": "create", + "id": null, + "date": "2026-10-14", + "partyId": 12, + "number": null, + "externalNumber": "LS-SUP-99412", + "comment": "Ware unbeschädigt auf Palette 3 angeliefert.", + "lines": [ + { + "pos": 1, + "sku": "42001257", + "name": "1 Pot 8L System inkl. 47L Wasserfass", + "amount": 20, + "pu": 1, + "net": 38.50, + "gross": 45.82, + "taxrate": 19, + "rebate": 0, + "unit": "Stück", + "comment": "Palette A-04" + }, + { + "pos": 2, + "sku": "42000009", + "name": "Autopot Easy2Grow Erweiterungsset 2Pot", + "amount": 50, + "pu": 1, + "net": 24.00, + "gross": 28.56, + "taxrate": 19, + "rebate": 3, + "unit": "Stück", + "comment": "Karton 1 bis 5" + } + ] + } +} +```