Preisliste¶
Die Preisliste ist die Stammdatenquelle für die Preisfindung in Aufträgen. Ein Eintrag gilt immer für die Kombination aus Gerätetyp und Preisgruppe — nicht für einen frei benannten Artikel.
Route: /price · Recht: price_view
Preise mit Gerätetypbezug, Katalogartikel ohne
Leistungen ohne Gerätebezug (Pauschalen, Versand, Dienstleistungen) gehören nicht in die Preisliste, sondern in die Artikelverwaltung als Katalogartikel. Die Preisliste beantwortet ausschließlich die Frage „Was kostet die Bearbeitung dieses Gerätetyps für dieses Kundensegment?".
Die Preisliste pro Preisgruppe (Dokument-Sicht)¶
Route: /price/list · Recht: price_view (Pflege: price_edit)
Neben der Zeilenliste gibt es die menschenlesbare Preisliste — das Dokument, das ein Labor seinem Kunden übergibt, als Seite. Sie zeigt für eine gewählte Preisgruppe und einen Stichtag, was gilt:
- A. Kalibrierpreise — der Preiskategorien-Baum mit den geltenden Beträgen, Typ-Ausnahmen eingerückt darunter. Abgeleitete und geerbte Beträge sind kursiv und im Hinweis benannt.
- B. Zusatzleistungen — Leistungsverrechnungspreise (zusätzlicher Prüfpunkt, Sondermessung), typ-/kategorieabhängige Zeilen darunter.
- C. Standardartikel — Katalogartikel mit Preis (Gerät reinigen, Versand).
Währung und pauschale Konditionen (Zuschläge je Kalibrierart wie „DAkkS +30 %", Staffeln wie „ab 10: −10 %") stehen als Kopf- bzw. Fußnoten in der Liste — wie auf echten Laborlisten.
Gepflegt wird, wo gelesen wird: Ein Klick auf einen Betrag öffnet das Eingabefeld. Geschrieben wird immer die richtige Quellzeile — bei einem Betrag, der nur abgeleitet, geerbt oder der Listenpreis ist, entsteht eine eigene Zeile der gewählten Gruppe, statt fremde Preise mitzuverstellen.
Zweisprachig führen und drucken¶
Dieselbe Liste geht an einen deutschen und an einen ausländischen Kunden. Dafür trägt jede Preiskategorie und jeder Katalogartikel einen zweiten Namen; welche Sprache das ist, steht unter Verwaltung → Einstellungen → Preise → Preisliste („Zweitsprache der Preisliste", Vorgabe Englisch).
Im Kopf der Liste steht dann eine Sprachwahl mit drei Fassungen. Sie gilt für Anzeige, CSV und PDF gleichermaßen — was auf dem Bildschirm steht, steht auch auf dem Papier:
| Fassung | Was die Liste zeigt |
|---|---|
| Deutsch (die Standardsprache) | wie bisher: die gepflegten Namen |
| Englisch (die Zweitsprache) | die Zweitnamen. Fehlt einer, steht dort der gepflegte Name — eine Zeile ohne Bezeichnung wäre ein Betrag ohne Gegenstand |
| Beide | den gepflegten Namen, darunter klein den Zweitnamen |
Gepflegt wird auch hier, wo gelesen wird. In den Fassungen Englisch und Beide ist der Zweitname anklickbar wie ein Betrag; wo noch keiner steht, lädt ein „Englisch ergänzen" dazu ein. So geht man die Liste einmal durch und übersetzt sie, statt sich Kategorienummern zu notieren und sie anschließend in der Kategorieverwaltung zu suchen. Änderbar ist der Zweitname zusätzlich in der Kategoriemaske (Verwaltung → Preiskategorien) und am Katalogartikel.
Steht die Einstellung auf der Standardsprache, gibt es keine zweite: die Sprachwahl verschwindet, und die Liste verhält sich wie vor der Zweisprachigkeit.
Gerätetypen werden nicht übersetzt
„Fluke 87V" heißt in jeder Sprache so. Die Typ-Ausnahmen unter einer Kategorie bleiben deshalb einsprachig, auch in der Fassung Beide.
Eine mitgebrachte Liste bringt ihre Übersetzung mit. Der
Kategorie-Import (price-classes:import bzw. der Upload unter
Verwaltung → Preiskategorien) liest eine zusätzliche Spalte
„Preiskategorie Zweitsprache" (auch „Preiskategorie EN", „Name englisch",
„Zweitname"). Ein zweiter Lauf über dieselbe Datei trägt den Zweitnamen bei
bestehenden Kategorien nach, solange dort noch keiner steht — vorhandene
Übersetzungen und Beträge bleiben unberührt. Vierundvierzig Kategorien zu
übersetzen ist damit ein Upload statt vierundvierzig Klicks.
CSV-Export liefert die Liste sofort übergabefähig — in der Fassung Beide
mit zwei Bezeichnungsspalten, sonst mit einer. Der Dateiname nennt die
Sprache, sobald sie nicht die erste ist. PDF-Export läuft
über eine Berichtsvorlage der Familie „Preisliste" (Verwaltung → Berichte,
Bereich price_list, Datenvertrag price-list) — mit Briefkopf über das
Berichts-Overlay; die Vorlage bekommt den Kategoriebaum, Leistungen,
Standardartikel und Fußnoten als JSON-Datensatz
(GET /price-list/reports/dataset liefert ihn zum Vorlagenbau in Jaspersoft
Studio).
Die Sprachwahl löst dabei der Datensatz auf, nicht die Vorlage: name
trägt bereits die angeforderte Sprache. Deshalb folgt auch eine selbst gebaute
Vorlage der Sprachwahl, ohne von ihr zu wissen. Das mitgelieferte Bündel
PRICE-LIST-JSON-SAMPLE (Datenvertrag 1.1) druckt in der Fassung Beide
zusätzlich den Zweitnamen als zweite Zeile.
Der PDF-Knopf zeigt das Dokument erst in einer Vorschau — ein Papier, das man aus der Hand gibt, sieht man vorher an. Von dort führen zwei Wege: Drucken und Herunterladen. Mehr bietet die Vorschau nicht, und das mit Absicht: DMS-Ablage, Signatur und Versand hängen an einem Datensatz, den eine Preisliste nicht hat.
Ist noch gar nichts bepreist, bietet die Seite die drei
Anfänge an: eigene Liste einspielen (price-classes:import), mit einer
Beispiel-Preisliste starten oder leer beginnen, geführt über die Übersicht.
Die Beispiel-Preisliste¶
Ein Klick, und die Preisstellung steht als vollständiges kleines Beispiel da — nicht als Kategoriebaum allein, sondern mit allen Stufen, die das Modul kennt:
| Stufe | Was angelegt wird |
|---|---|
| Kategoriebaum | fünf Obergruppen mit Untergruppen und Grundpreisen |
| Kundenpreisgruppen | „Händler" −15 %, „Rahmenvertrag" −25 %, abgeleitet |
| Zuschlag je Kalibrierart | „DAkkS" +45 % auf den Grundpreis |
| Zusatzleistung | „Zusätzlicher Messpunkt" 25,00 mit Staffel ab 5 (−10 %) und ab 10 (−20 %) |
| Standardartikel | „Gerät reinigen" — nur, wenn der Katalog leer ist |
Die beiden Kundengruppen bekommen bewusst eine Kondition statt einer eigenen
Preisliste: sie leiten vom gruppenlosen Listenpreis ab. Wer den Listenpreis
ändert, ändert beide mit. Ebenso der Zuschlag: eine Kalibrierart ist ein
Aufschlag, keine zweite Preiszeile je Gerätetyp. Genau diese beiden Muster
sparen später die Arbeit, die price-classes:derive sonst wieder auflösen
muss — deshalb bringt die Vorlage sie mit, statt sie dem Zufall zu überlassen.
Nur für den leeren Anfang, und nie über Vorhandenes
Sobald Preiskategorien oder Preiszeilen existieren, wird die Vorlage weder angeboten noch ausgeführt. Und jeder Teil für sich wird übersprungen, wenn es ihn schon gibt: eine Preisgruppe „Händler" behält ihre Kondition, ein vorhandener Zuschlagssatz bleibt der einzige, ein gefüllter Artikelkatalog bekommt keinen Beispielartikel. Die Meldung nach dem Anlegen nennt, was wirklich entstanden ist.
Alle Beträge tragen die Markierung „Beispielbetrag, bitte anpassen".
Wie ein Preis gefunden wird¶
Der Rechnungskunde bringt seine Preisgruppe mit, das Auftragsdatum den Stichtag. Damit werden drei Stufen der Reihe nach geprüft, und die erste Fundstelle gewinnt:
| Stufe | Wo gesucht wird | Wann sie greift |
|---|---|---|
| 1 | Eigene Preiszeile des Gerätetyps in dieser Preisgruppe | immer zuerst — die speziellste Aussage |
| 2 | Preiskategorie des Gerätetyps, in dieser Preisgruppe | wenn der Typ keine eigene Zeile hat (direkt vor geerbt, feinste Ebene zuerst) |
| 3 | Grundpreis — dieselbe Suche ohne Preisgruppe | wenn die Gruppe nichts Eigenes führt |
Der Grundpreis ist die Zeile ohne Preisgruppe. Er ist der Normalfall, nicht die Ausnahme: die Preisliste wird einmal gepflegt, und jede Preisgruppe, die nichts Abweichendes führt, bekommt genau diesen Betrag. Hat die Gruppe eine Ableitungsregel, rechnet sie ihn um („Händler = Grundpreis minus 15 %"); ohne Regel gilt er unverändert.
Erst wenn auch der Grundpreis fehlt, bleibt die Auftragsposition bei 0,00. Genau diese Lücken macht die Preismatrix sichtbar.
Zwischen zwei Preisgruppen wird nichts vererbt
Der Rückfall geht immer auf den Grundpreis, nie auf den Betrag einer anderen Gruppe. Ein Laufkunde bekommt deshalb nicht versehentlich die Kondition eines Großkunden. Und umgekehrt: eine gepflegte Zeile der Gruppe schlägt den Grundpreis, der Rückfall füllt nur Lücken.
Listenansicht (Reiter „Preiszeilen")¶
Die Zeilenliste unter Verwaltung → Preiszeilen zeigt die einzelnen Preiszeilen: eine je Gerätetyp, Preisgruppe und Gültigkeit. Sie ist zum Nachschlagen, Korrigieren und für Ausnahmen da.
Zum Aufbau einer Preisliste ist sie nicht gedacht
Die Zeilenliste zeigt, was es gibt, nicht was fehlt. Wer eine Preisliste aufbaut, arbeitet in der Preismatrix: Filter „nur Lücken" einschalten, Lücken markieren, per Sammelanlage in einem Zug bepreisen. Wer die Liste liest oder pflegt, wie ein Kunde sie bekommt, nimmt den Reiter Preisliste. Deshalb steht die Matrix in der Werkzeugleiste vorn und die Zeilenliste am Ende.
Die Spalten kommen aus der Feldverwaltung (Tabelle prices) und sind pro
Installation konfigurierbar. Werkseitig vorausgewählt sind die sechs, aus denen
eine Zeile ein Satz wird:
| Spalte | Beschreibung |
|---|---|
| Gerätetyp | Gerätetyp, für den der Preis gilt |
| Preisgruppe | Kundensegment, für das der Preis gilt |
| Kalibrierart | ISO- oder DAkkS-Kalibrierung. Im Normalfall leer — der Regelfall ist ein Zuschlag |
| Preis | Betrag je Einheit |
| Gültig ab / Gültig bis | Gültigkeitszeitraum (leer = unbefristet) |
Die Detailfelder Mindestpreis, Höchstpreis, Selbstkosten, Menge, Einheit, Steuersatz und Rabatt sind weiterhin verfügbar, aber nicht mehr vorausgewählt: sie sind im Bestand meist leer oder 0 und verdrängten sonst die Spalten, die die Zeile zuordenbar machen. Über die Spaltenauswahl im Grid sind sie mit einem Klick wieder da.
Weitere Spalten lassen sich über die Feldverwaltung einblenden; eigene Felder für Preise sind dort ebenfalls anlegbar und werden von der API mitgeliefert.
Filter und Suche¶
- Volltextsuche über den Gerätetyp-Namen
- Filter nach Gerätetyp (
filter[type_id]) und Preisgruppe (filter[category_id]) - Erweiterte Filter und Spaltenauswahl wie in allen Hauptgrids
Zeilenaktionen¶
| Aktion | Recht | Wirkung |
|---|---|---|
| Bearbeiten | price_edit |
Öffnet den Preis im Dialog |
| Duplizieren | price_edit |
Öffnet einen vorbefüllten Dialog für eine Kopie |
| Löschen | price_delete |
Entfernt die Preiszeile |
Mehrfachauswahl erlaubt zusätzlich das Massenlöschen (price_delete) und die
Preisrunde (price_edit).
Preisrunde (Massenanpassung)¶
Eine Preiserhöhung Zeile für Zeile einzugeben ist bei vierstelliger Gerätetypzahl nicht durchzuhalten. Die Preisrunde rechnet denselben Aufschlag auf viele Zeilen auf einmal.
Zwei Einstiege:
- Markierte Zeilen — in der Preisliste Zeilen auswählen, dann Preisrunde. Wirkt genau auf die Auswahl.
- Ganze Preisgruppe — auf der Detailseite einer Preisgruppe unter Mehr → Preisrunde. Wirkt auf alle Preiszeilen der Gruppe, auch die auf späteren Seiten des Grids.
Einstellungen:
| Feld | Bedeutung |
|---|---|
| Art der Anpassung | Prozentual (etwa +3 %) oder fester Betrag (etwa +5,00). Ein negativer Wert senkt den Preis. |
| Runden auf | Rundungsstufe des Ergebnisses (0,01 bis 5,00). Ohne Stufe entstehen Beträge wie 123,63. |
| Betragsspalten | Vorgabe ist nur Preis; Mindestpreis, Höchstpreis und Kosten bleiben unberührt, bis sie ausgewählt werden. |
| Wie der neue Preis gilt | Neue Gültigkeit (Vorgabe) beendet die alte Zeile am Tag vor dem Stichtag und legt eine neue an — was vorher galt, bleibt lesbar. Überschreiben ersetzt die Beträge in der bestehenden Zeile. |
| Gültig ab | Stichtag der neuen Gültigkeit. Pflichtangabe in diesem Modus. |
Vorschau vor Ausführung. Anwenden ist erst anklickbar, wenn ein Probelauf gelaufen ist. Der Probelauf schreibt nichts und liefert dieselben Zahlen wie der echte Lauf: betroffene Zeilen, Summe vorher und nachher, Beispielzeilen und die Gründe für übersprungene Zeilen.
Warum Zeilen übersprungen werden:
| Grund | Bedeutung |
|---|---|
| Betrag bleibt gleich | Etwa 0,00 mit einem Prozentaufschlag — eine neue Zeile dafür wäre Pflegeaufwand ohne Wirkung. |
| Ergebnis wäre negativ | Ein fester Abzug ist größer als der Preis. |
| Gültigkeit ist abgelaufen | Die Zeile endete vor dem Stichtag; eine Nachfolgerin würde sie wiederbeleben. |
| Zeile beginnt später | Die Zeile startet am Stichtag oder danach und kann nicht vorher beendet werden. |
| Schon ein Preis vorhanden | Für Gerätetyp, Preisgruppe, Stichtag und Kalibrierart gibt es bereits eine Zeile. |
Eine übersprungene Zeile bricht die Runde nicht ab; die übrigen werden angepasst. Jede Schreibung landet im Audit-Trail.
Obergrenze: höchstens 5000 Zeilen je Lauf. Darüber meldet der Server die Trefferzahl und schreibt nichts — die Auswahl ist dann einzugrenzen, etwa auf eine Preisgruppe.
Leistungen mit Gerätebezug¶
Eine Preiszeile in der Preisliste heißt immer „Kalibrierung von Gerätetyp X". Für „Reinigung Buchsen Gerät X" oder „Verpackungspauschale Gerät X" gibt es seit AP 10 eine zweite Achse: die Leistung.
Die Leistung ist ein Katalogartikel; bepreist wird sie unter
/api/v2/service-prices je Gerätetyp, Preisgruppe und Zeitraum. Bleibt der
Gerätetyp leer, ist es eine Pauschale, die für jedes Gerät gilt.
Wie gesucht wird — feste Reihenfolge, erste Fundstelle gewinnt:
- Preis dieser Leistung für diesen Gerätetyp
- Preis dieser Leistung für die Preiskategorie, in der der Gerätetyp liegt
- Pauschale dieser Leistung, ohne Gerätebezug
Für die Kalibrierung gilt dieselbe Reihenfolge ohne die dritte Stufe: erst die Preiszeile des Gerätetyps, dann seine Preiskategorie. Eine Pauschale gibt es dort bewusst nicht — „Kalibrierung kostet immer 80 Euro, egal welches Gerät" ist keine Preisliste, sondern deren Abwesenheit.
Die Preisgruppe ist dabei kein eigener Schritt, sondern ein Filter auf allen
Stufen. Der Endpunkt sagt in meta.matched_by mit, welche Stufe getroffen hat
— der Unterschied zwischen einem gepflegten Typpreis und einer eingesprungenen
Pauschale ist sonst nicht zu sehen.
Die Preiskategorie¶
Die Preiskategorie ist der Sammelbehälter der Geräteachse: statt jeden Gerätetyp einzeln zu bepreisen, sortiert man ihn in eine Kategorie und bepreist die. Zwei Wege führen hinein:
- Gerätetyp direkt. Der Regelfall für Geräte, die extern durch einen Dienstleister kalibriert werden — sie haben keine Prozedur.
- Über die Prozedur. Liegt die Standardprozedur eines Gerätetyps in einer Kategorie, erbt der Typ sie. Das ist der eigentliche Hebel: Prozeduren gibt es in der Größenordnung Hunderte, Gerätetypen in der Größenordnung Zehntausende.
Ein Gerätetyp gehört zu höchstens einer Kategorie, eine Prozedur ebenso. Liegen beide in verschiedenen Kategorien, gewinnt die direkte Zuordnung — sonst wäre der Preis mehrdeutig.
Kategorien dürfen ineinander liegen (Fachgebiet → Gattung →
Bereichs-/Genauigkeitsstufe, wie die dreistellige Artikelnummer 100.110.01).
Gesucht wird von der feinsten Ebene aufwärts: Wer nur „Druck" bepreist, bekommt
einen groben Preis für alles darunter; wer bis „Druck 0-10 bar" geht, einen
genauen. Beides ist gültig, und der Übergang kostet nichts.
Nicht dasselbe wie die Preisgruppe
Die Preiskategorie sagt, was bepreist wird (die Geräteseite), die Preisgruppe sagt, für wen (die Kundenseite). Beide stehen senkrecht zueinander: eine Preiszeile trägt in aller Regel beides.
Die Kategorie bepreist beide Achsen
Eine Preiskategorie kann sowohl eine Leistung als auch die Kalibrierung bepreisen. Gepflegt wird beides unter Leistungen: mit gewählter Leistung gilt die Zeile für diese Leistung, mit dem Eintrag „— Kalibrierung (ohne Leistung) —" für die Kalibrierung.
Eine Zeile ohne Leistung braucht zwingend eine Preiskategorie. Ohne beides wäre sie ein Preis für jeden Gerätetyp ohne Unterscheidung — den Fall weist die Maske ab. Der Preis eines einzelnen Gerätetyps steht weiterhin in der Preisliste.
Eine Preiszeile trägt entweder einen Gerätetyp oder eine Preiskategorie. Beides zusammen wäre nicht genauer, sondern mehrdeutig — wer einen einzelnen Typ innerhalb seiner Kategorie abweichend bepreisen will, legt die Typzeile an; die geht der Kategorie ohnehin vor.
Kategorien pflegen¶
Das Werkzeug Preiskategorien unter Verwaltung (/price/classes) listet alle
Kategorien mit Nummer, Name, übergeordneter Ebene und der Zahl ihrer
Mitglieder. Die Spalte Mitglieder ist die wichtigste: eine Kategorie ohne
Mitglieder trägt zwar einen Preis, findet aber nie einen Gerätetyp. Sie sieht
gepflegt aus und wirkt nicht — deshalb steht eine 0 dort farblich hervorgehoben.
Ein Klick auf den Namen öffnet die Kategorie. Dort werden Gerätetypen und Prozeduren zusortiert: erst die Art wählen (Gerätetyp oder Prozedur), dann den Eintrag, dann Zuordnen.
Bei der Art „Gerätetyp" steht daneben die Gerätekategorie als Filter: die fachliche Einordnung des Geräts („Druckmessgeräte"), nicht die Preisgruppe und nicht diese Preiskategorie. Untergeordnete Kategorien zählen mit — wer „Elektrisch" wählt, meint den Ast. Und jede Vorschlagszeile zeigt unter der Typbezeichnung Hersteller und Modell: im Bestand tragen zwei Gerätetypen oft fast denselben Namen und unterscheiden sich erst in der Mitte um eine Skalenteilung. Aus der Bezeichnung allein ist dann nicht zu erkennen, welcher der richtige ist.
Zusortieren hängt um, statt abzuweisen
Liegt der Gerätetyp schon in einer anderen Kategorie, wird er hierher verschoben — „höchstens eine Kategorie" heißt nicht „die erste gewinnt für immer". Die Meldung sagt, ob zugeordnet oder umgehängt wurde. Wer das nicht beabsichtigt hat, sortiert ihn genauso einfach zurück.
Mehrere auf einmal: die Listensuche¶
Der Weg oben ordnet einen Eintrag zu. Nach dem Einlesen einer Preisliste sind es aber dreißig auf einmal — „alle Typen mit Druck im Namen gehören in diese Kategorie" —, und dreißig Suchen mit dreißig Klicks sind dann nicht die Bedienung, sondern das Hindernis. Dafür steht neben Zuordnen der Knopf Listensuche.
Er öffnet dieselbe Suche als Liste: Art, Gerätekategorie und Suchbegriff oben, darunter die Treffer seitenweise mit einem Ankreuzfeld je Zeile. Markiert wird über mehrere Seiten hinweg — die Auswahl übersteht das Umblättern —, und Alle auf dieser Seite markiert die ganze Seite in einem Klick. Am Ende übernimmt ein Knopf alles Markierte in einem Zug.
Die Spalte Liegt in ist der eigentliche Grund für den Dialog:
| Zustand | Bedeutung |
|---|---|
| ohne Kategorie | findet heute über keine Direktzuordnung einen Kategoriepreis |
| andere Kategorie | liegt woanders — das Übernehmen hängt um; darunter steht, woher |
| bereits hier | liegt schon in dieser Kategorie und ist deshalb nicht markierbar |
Über der Tabelle steht in einem Satz, was der Klick tun wird („12 Gerätetypen markiert, 3 davon werden aus anderen Preiskategorien umgehängt"). Das ist die Angabe, die man vor dem Übernehmen braucht: eine Mehrfachauswahl nimmt sonst anderen Kategorien Mitglieder weg, ohne dass es jemand bemerkt. Über den Filter Liegt in lässt sich die Liste auf genau einen dieser Zustände einschränken — „nur, was noch nirgends liegt" ist der übliche erste Lauf.
Der Dialog bleibt nach dem Übernehmen offen und zeigt das Ergebnis sofort in der Liste: auf „alles mit Druck" folgt meistens „und alles mit Manometer".
Ein geerbter Preis zählt hier nicht als Zuordnung
Ein Gerätetyp, der seine Kategorie über seine Standardprozedur erbt, erscheint in dieser Liste als ohne Kategorie — denn eine Direktzuordnung wäre eine echte Änderung und würde die geerbte überstimmen. Die Lückenliste unter Preise → Zusortieren beantwortet die andere, strengere Frage: welche Typen finden über keinen Weg einen Kategoriepreis.
Gelöscht werden kann eine Kategorie nur, solange nichts daran hängt — keine Unterkategorien, keine Mitglieder, keine Preiszeilen. Der Grund steht in der Meldung. Preiszeilen still zu verwaisen wäre der schlimmste Fall: die Preisfindung findet eine unbekannte Kategorie einfach nicht mehr, und der Betrag verschwindet ohne Hinweis.
Über die API geht dasselbe: /api/v2/price-classes, Mitglieder unter
/api/v2/price-classes/{id}/members. GET /api/v2/price-classes/resolve?type_id=…
beantwortet, welche Kategorien für einen Gerätetyp in Frage kommen und in
welcher Reihenfolge. Die Listensuche liest
GET /api/v2/price-classes/{id}/member-candidates
(filter[kind], filter[search], filter[category_id], filter[state]) und
schreibt über POST /api/v2/price-classes/members/bulk.
Kategorien aus der Artikelnummer vorschlagen¶
Wer seine Klassenbildung bereits als Artikelnummer pflegt (100.110.01 im
Zusatzfeld der Preisliste), muss sie nicht abtippen. Der Befehl
liest die Preiszeilen, gruppiert sie nach der Nummer und zeigt: welche Nummern es gibt, wie viele Zeilen und Gerätetypen daran hängen, was übernehmbar wäre. Er schreibt nichts. Das ist der Zweck — ob die Nummern sauber genug sind, zeigt erst der Bericht.
Mit --apply werden die übernehmbaren Gruppen als Preiskategorien angelegt und
ihre Gerätetypen zusortiert. Drei Regeln dabei:
- Eine Nummer an genau einem Gerätetyp wird übersprungen — das ist keine Klassenbildung, sondern eine Nummer.
- Ein Gerätetyp, der schon in einer Kategorie liegt, bleibt dort. Eine stille Umhängung korrigierte eine Zuordnung, die jemand von Hand getroffen hat.
- Ein zweiter Lauf legt nichts doppelt an.
Heißt das Feld anders, hilft --field='Klassennummer'; gesucht wird auch über
die Beschriftung aus dem Feldmanagement.
Beträge kommen nicht mit
Der Lauf legt Kategorien und Mitglieder an, keine Preise, und löscht keine bestehenden Preiszeilen. Was eine Kategorie kostet, wird danach unter Leistungen gepflegt — eine Übernahme, die ungefragt Beträge verschiebt, wäre keine Vorschlagsquelle mehr.
Leistungspreise pflegen¶
Gepflegt wird auf der Artikel-Detailseite (Werkzeug Artikel &
Leistungen unter Verwaltung, /standard-article → Artikel anklicken): oben
die Stammdaten des Katalogartikels samt Standardpreis, darunter die Sektion
Leistungspreise — eine Zeile je Geräteachse × Preisgruppe × Gültigkeit.
Gerätetyp, Preiskategorie und Preisgruppe dürfen leer bleiben und heißen dann
„für alle" — die Liste schreibt das ausdrücklich hin („Pauschale (jeder
Gerätetyp)"), damit ein leeres Feld nicht wie ein Pflegefehler aussieht. Ohne
Preiszeile gilt der Standardpreis der Stammdaten.
Damit gibt es einen Pflegeort statt zwei: bis P4 bepreiste der eigene
Reiter „Leistungen" dieselben Artikel, die die Artikelverwaltung mit einem
eigenen Standardpreis führte — wer einen Reinigungspreis suchte, musste
wissen, welcher Ort gerade zuständig ist. Die alte Adresse /price/services
leitet auf den Katalog um. Die Kategoriezeilen der Kalibrierung (Zeilen ohne
Leistung) werden auf der Detailseite der jeweiligen Preiskategorie
gepflegt — oder direkt in der Preisliste.
Beide Achsen nebeneinander¶
Die Preismatrix hat oben eine Auswahl Leistung. Voreingestellt ist „Kalibrierung (Preisliste)" — das ist die Matrix, die es immer gab. Jede andere Auswahl zeigt dieselbe Aufstellung aus Gerätetypen und Preisgruppen für diese Leistung.
Die Matrix rechnet die volle Zugriffsfolge, nicht nur die Zeilen für den jeweiligen Gerätetyp. Ein hochgestellter Buchstabe sagt, woher der Betrag kommt:
| Zeichen | Herkunft |
|---|---|
| (keins) | Eine Zeile für genau diesen Gerätetyp |
| K | Der Preis der Preiskategorie — gilt für alle ihre Mitglieder. Der Tooltip unterscheidet, ob der Typ selbst in der Kategorie liegt oder sie über seine Standardprozedur erbt |
| P | Die Pauschale der Leistung — gilt für jeden Gerätetyp |
Ohne die Markierung sähe eine Spalte aus lauter gleichen Beträgen wie dreihundert gepflegte Einzelpreise aus, obwohl dort dreihundertmal dieselbe Zeile steht.
Ein Klick auf eine Zelle legt eine Zeile für diesen Gerätetyp an, auch wenn dort gerade eine Pauschale oder ein Kategoriepreis steht. Das ist Absicht: Beide gelten für mehr als diesen einen Typ, und aus der Zelle heraus geändert träfe die Änderung Gerätetypen, die gar nicht auf dem Bildschirm stehen. Nur ein eigener Typpreis wird durch den Klick bearbeitet statt ersetzt.
Der Lückenfilter zählt entsprechend: Ein Gerätetyp, dessen Preis über seine Preiskategorie kommt, ist keine Lücke — auch wenn er keine eigene Zeile hat.
Die Sammelanlage („Lücken markieren") gibt es nur auf der Kalibrierung — sie schreibt in die Preisliste und kennt die Leistungsachse nicht.
Im Auftrag¶
Beim Hinzufügen einer Position vom Typ Standardartikel zeigt der Dialog den gefundenen Leistungspreis für die Preisgruppe des Auftragskunden, samt der Stufe, die getroffen hat. Übernommen wird er per Knopf, nicht automatisch: Die Position trägt bereits den Katalogpreis, und ein stilles Überschreiben würde einen von Hand eingetragenen Sonderpreis verschlucken.
Die Preisinfos einer Katalogposition zeigen dieselbe Liste — vorher stand dort „Standardartikel-Positionen haben keine Typ-Preisliste", was stimmte, solange es nur die Preisliste gab.
Preis prüfen¶
Auf der Preis-Übersicht (/price/overview, erster der drei Reiter)
steht unten das Panel Preis prüfen: Gerätetyp und Kunde eingeben, optional
Kalibrierart und Stichtag — es fragt dieselbe Preisfindung, die auch ein Auftrag
benutzt.
Der Anlass ist meist eine Auftragsposition mit 0,00. Dafür gibt es drei verschiedene Ursachen, die sich sonst nicht unterscheiden lassen:
| Meldung | Bedeutung | Was zu tun ist |
|---|---|---|
| Der Kunde hat keine Preisgruppe | Ohne Gruppe greift bewusst kein Gruppenpreis | Preisgruppe am Kunden zuordnen, nicht in der Preisliste |
| Für diesen Gerätetyp ist kein Preis hinterlegt | Es gibt keine einzige Zeile | Preiszeile anlegen, etwa über die Preismatrix |
| Es gibt Preise, aber keinen in dieser Preisgruppe | Die Zeilen hängen an anderen Gruppen | Zeile für die Gruppe anlegen oder die Gruppe duplizieren |
| Es gibt einen Preis, er gilt am Stichtag aber nicht | Abgelaufen oder noch nicht in Kraft | Enddatum prüfen oder neue Gültigkeit anlegen |
| Es gibt einen gültigen Preis, aber nicht für diese Kalibrierart | Die Zeile trägt eine andere Kalibrierart | Zeile für die Kalibrierart anlegen — oder besser einen Zuschlag definieren |
Zusätzlich steht dort, wie viele Preiszeilen es für den Gerätetyp überhaupt gibt — der Unterschied zwischen „gar keine" und „welche, aber keine passende".
Staffelpreise und Zuschläge¶
Zwei Mechanismen ändern den gefundenen Betrag nachgelagert — welche Zeile gilt, entscheiden weiterhin die Regeln oben:
Staffelpreise hängen an einer Preiszeile (Abschnitt Staffelpreise auf deren Detailseite): ab Menge M gilt ein fester Stückpreis oder ein prozentualer Nachlass. Die höchste erreichte Stufe gewinnt, der feste Stückpreis schlägt den Nachlass. Angewandt wird die Staffel überall dort, wo eine Menge bekannt ist — bei Preise aktualisieren über die Positionsmenge und im Panel Preis prüfen über das Feld Menge.
Zuschläge (Werkzeug Zuschläge unter Verwaltung, /price/surcharges) bepreisen die
Kalibrierart (ISO, DAkkS, …) als Aufschlag statt als eigene Zeile je Gerätetyp:
„DAkkS kostet überall 30 Prozent mehr" ist eine Zeile, „bei Elektrisch und
Temperatur sind es 50" eine zweite mit mehreren Preiskategorien — die
Überschreibung schlägt den globalen Wert. Der Zuschlag greift nur, wenn die
Preisliste keine eigene Zeile für die verlangte Kalibrierart hat; eine gepflegte
Zeile mit Kalibrierart schlägt ihn immer.
Ein Satz, viele Kategorien — eine Zeile
Das Feld Preiskategorien nimmt beliebig viele Einträge. Wer für sechs Kategorien denselben Satz will, wählt sie in einer Zeile aus, statt sechs Zeilen zu pflegen. Die nächste Anpassung ist dann eine Änderung, nicht sechs. Leer heißt weiterhin global: der Zuschlag gilt für alle Gerätetypen.
Ein Gerätetyp muss in einer der gewählten Kategorien liegen, damit die Zeile greift — direkt zugeordnet oder über seine Standardprozedur geerbt. Liegt er in mehreren, entscheidet dieselbe Reihenfolge wie in der Preisfindung: feinste Ebene zuerst, direkt vor geerbt.
Beide rechnen kaufmännisch gerundet auf zwei Nachkommastellen, nie unter 0,00, in der Reihenfolge Ableitung → Zuschlag → Staffel. Das Panel Preis prüfen zeigt jeden Rechenschritt als eigene Zeile der Herkunftskette.
Die Kalibrierart im Auftrag wählen¶
Welche Zeile eine Auftragsposition trifft, hängt an ihrer Kalibrierart — und die steht an der Position, nicht in der Preisliste. Ohne gewählte Kalibrierart gilt bewusst die Zeile ohne Kalibrierart (die Grundzeile), damit nicht die Anlage-Reihenfolge der Preiszeilen entscheidet.
Der typische Fall: eine Preiskategorie führt 189,00 als Grundzeile und 289,00 für DAkkS. Eine Position ohne Kalibrierart steht auf 189,00 — richtig, solange es keine DAkkS-Kalibrierung ist.
So kommt der DAkkS-Preis auf die Position: im Auftrag unter Artikel in der Spalte Kalibrierart den Wert wählen. Die Position wird sofort neu bepreist, und zwar nur diese eine. Die Auswahlwerte sind dieselben, die die Preiszeilen im Feld Kalibrierart anbieten — deshalb passt der Wert immer exakt, und ein Tippfehler kann nicht still auf die Grundzeile zurückfallen.
Was danach passiert, folgt der Kaskade von oben: eine gepflegte Zeile für diese Kalibrierart schlägt alles, sonst greift der Zuschlag auf die Grundzeile, und erst ohne beides bleibt der Grundpreis stehen. Die Meldung nennt den alten und den neuen Betrag; findet die Preisliste nichts, bleibt der Betrag stehen und sagt es auch.
Handgesetzte Beträge werden nicht überschrieben
Trägt die Position einen von Hand eingetragenen Preis, fragt calServer einmal nach: neu bepreisen oder nur die Kalibrierart speichern. Die Kalibrierart wird in beiden Fällen gespeichert — sie ist eine Angabe über die Leistung, nicht nur ein Schalter für den Preis, und sie steht auf dem Beleg.
Der Knopf Preise aktualisieren darüber bleibt der Rundumschlag für den ganzen Auftrag: nach einer Preisrunde alle Positionen nachziehen. Er fasst auch die Zeilen mit ausgehandelten Beträgen an — für eine einzelne Position ist die Auswahl in der Zeile der genauere Weg.
Ohne gepflegte Kalibrierarten zeigt die Spalte den gespeicherten Wert nur an. Die Werte pflegt man im Feldmanagement am Feld Kalibrierart der Preiszeilen; frei eintragen lässt sich die Kalibrierart weiterhin im Bearbeiten-Dialog der Position.
Historie eines Preises¶
Auf der Detailseite eines Preises steht der Abschnitt Historie: wer wann welchen Betrag geändert hat. Auch Preisrunden (Massenanpassung) landen dort, jede Zeile einzeln.
Nicht protokolliert werden die Verwaltungsspalten Geändert am und Geändert von — sie ändern sich bei jeder Schreibung und stünden sonst als Rauschen vor jeder echten Betragsänderung.
Preise am Gerätetyp¶
Die Detailseite eines Gerätetyps hat einen Reiter Preise mit allen Zeilen dieses Typs, je Preisgruppe und Zeitraum. Dieselben Daten wie in der Preisliste, nur andersherum gefragt: nicht „welche Preise gibt es", sondern „was kostet dieser Typ".
Import und Export (CSV-Rundlauf)¶
Bei vierstelliger Gerätetypzahl ist die Preisliste von Hand nicht aufzubauen. Der Rundlauf lautet: exportieren, in Excel bearbeiten, zurückspielen.
Export. Der Knopf Export lädt die vollständige Preisliste als CSV (Semikolon, UTF-8 mit BOM — Excel öffnet sie ohne Zwischenschritt). Die Datei ist zugleich die Importvorlage.
Die Spalten. Feste Reihenfolge, Referenzen als Name statt als UUID:
Gerätetyp;Preisgruppe;Kalibrierart;Gültig ab;Gültig bis;Preis;
Mindestpreis;Höchstpreis;Kosten;Menge;Einheit;Rabatt %;Steuer %
Pflicht sind nur Gerätetyp, Preisgruppe und Preis. Kalibrierart und
Gültig ab dürfen fehlen; dann gilt „nicht gesetzt". Überschriften werden
unabhängig von Groß- und Kleinschreibung erkannt, englische Schreibweisen
(Device Type, Price Group) ebenso. Unbekannte Spalten werden ignoriert,
nicht auf gut Glück zugeordnet.
Beträge und Datumsangaben. Deutsche wie englische Schreibweise werden
gelesen (1.234,50 und 1,234.50). Datumsangaben als 2027-01-01 oder
01.01.2027. 03/04/2027 wird abgelehnt, nicht geraten — je nach Herkunft
wäre das der 3. April oder der 4. März.
Zuordnung über den Namen. Eine Zeile wird über Gerätetyp-Name, Preisgruppen-Name, Kalibrierart und Startdatum adressiert. Gibt es dort schon einen Preis, wird er geändert, sonst wird einer angelegt.
Vorschau vor Übernahme. Übernehmen ist erst anklickbar, wenn ein Probelauf gelaufen ist. Er zeigt je Zeile, was geschehen würde, ohne etwas zu schreiben.
Warum Zeilen nicht übernommen werden:
| Meldung | Bedeutung |
|---|---|
| Gerätetyp unbekannt | Der Name steht nicht im Typenkatalog. Wird gemeldet, nicht angelegt — ein Tippfehler in der Datei soll keinen Zwilling im Katalog erzeugen. |
| Preisgruppe unbekannt | Dasselbe für die Preisgruppe. |
| Name nicht eindeutig | Zwei Einträge, die sich nur in Groß-/Kleinschreibung oder Leerzeichen unterscheiden. Welcher gemeint ist, ist nicht entscheidbar. |
| Datum nicht lesbar | Siehe oben zu den akzeptierten Formaten. |
| Betrag nicht lesbar | Die Meldung nennt die betroffene Spalte. |
| Steht in der Datei schon einmal | Zwei Zeilen adressieren denselben Platz. |
| Gerätetyp oder Preisgruppe fehlt | Eine der beiden Schlüsselspalten ist leer. |
Bestehende Preise ändern. Der Schalter im Dialog. Aus bedeutet: bestehende Zeilen bleiben unangetastet und werden nur gezählt — nützlich, um eine Datei zunächst nur um die fehlenden Zeilen zu ergänzen. Für den Rundlauf muss er an sein.
Preisliste per MCP (KI-Assistenz)¶
Eine per MCP angebundene KI kann eine komplette Preisliste als Kategoriebaum anlegen — etwa einen plausiblen Beispieldatensatz für ein neues Labor, wenn die eingebaute Startvorlage nicht passt oder eine eigene Struktur gewünscht ist:
| Werkzeug | Zweck |
|---|---|
import_price_list |
Preiskategorien samt Beträgen aus strukturierten Zeilen anlegen — mit Hierarchie und Trockenlauf |
create_config (price) |
Einzelne Kalibrierpreise auf der Geräteachse — Abschnitt A |
create_config (service_price) |
Leistungsverrechnungspreise — Abschnitt B |
create_config (standard_article) |
Katalogartikel mit Listenpreis — Abschnitt C |
Der Import läuft durch denselben Prüfpfad wie der Listen-Import beim
Einrichten: wiedererkannt wird über die Nummer (ein zweiter
Lauf verdoppelt nichts), eine unbekannte Preisgruppe wird gemeldet statt
angelegt, und ein vorhandener Betrag bleibt, wie er ist. dry_run liefert den
Plan je Zeile, ohne zu schreiben.
Zusatzleistungen anlegen (Abschnitt B)¶
Abschnitt B und C speisen sich beide aus den Standardartikeln. Was einen
Artikel zur Zusatzleistung macht, ist kein Feld an ihm, sondern eine
service_price-Zeile, die auf ihn zeigt — dieselbe Zeile, die die
Artikel-Detailseite unter Artikel & Leistungen anlegt.
In zwei Schritten:
create_configmitstandard_article→ liefert dieuIDdes Artikels.create_configmitservice_priceundservice_id= dieseruID.
Ein Artikel ohne solche Zeile bleibt Standardartikel (C) und zeigt seinen
Katalogpreis. Wird die letzte service_price-Zeile gelöscht, fällt er dorthin
zurück; der Artikel selbst bleibt erhalten.
Umgekehrt gilt: Wird der Artikel gelöscht, bleibt die Preiszeile stehen und
hat keine Bezeichnung mehr — ihr Name war der des Artikels. Eine solche Zeile
steht in keinem Abschnitt der Liste, weder auf der Seite noch im gedruckten
Dokument: Ein Betrag ohne Gegenstand ist keine Auskunft. Verkaufen ließe sie
sich ohnehin nicht, es gibt keinen Artikel für die Auftragsposition. Die Seite
weist über Abschnitt B darauf hin, wie viele solcher Zeilen es gibt; aufgeräumt
wird, indem der Artikel wieder angelegt oder die Preiszeile gelöscht wird. Eine
neue Zeile auf eine unbekannte service_id weist die API seit 08/2026 mit
422 ab, über REST wie über MCP.
Zwei Felder, die stumm wirken
calibration_type am Artikel ist eine Vorbelegung für die
Auftragsposition, kein Schalter — ein Freitext dort verschiebt nichts.
Und eine service_price-Zeile mit gesetzter complexity erscheint
absichtlich nicht in der Preisliste: die Liste zeigt Grundpreise, die
Kalibrierart ist ein Zuschlag und steht als Fußnote. Für eine Leistung, die
in jeder Preisgruppe gleich kostet, bleibt category_id leer.
describe_config_resource nennt diese Regeln zu jeder Ressource; die
Achsen-Prüfungen (Gerätetyp oder Preiskategorie, nie beides) sind dieselben wie
auf der REST-Route. Die Leistung selbst findet die KI über
lookup mit standard-articles.
Schreibrechte
Das Werkzeug verlangt price_edit und ist zusätzlich über
mcp.writes_enabled sowie den Demo-Modus abgesichert. Ein Trockenlauf
funktioniert auch bei abgeschalteten Schreibzugriffen.
Preismatrix¶
Über den Knopf Preismatrix wechselt die Ansicht auf die Darstellung Gerätetyp × Preisgruppe. Details: Preismatrix.
API-Endpunkte¶
GET /api/v2/prices # Liste (paginiert, filterbar)
GET /api/v2/prices/{id} # Einzelner Preis
GET /api/v2/prices/{id}/audits # Änderungshistorie einer Preiszeile
GET /api/v2/prices/matrix # Matrix Gerätetyp × Preisgruppe
GET /api/v2/prices/lookup # Preisfindung für Typ + Kunde (mit Begründung in meta)
# ?service_id=… fragt die Leistungsachse
GET /api/v2/service-prices # Bepreisung auf der Leistungsachse
POST /api/v2/service-prices # Anlegen
PUT /api/v2/service-prices/{id} # Ändern
DELETE /api/v2/service-prices/{id} # Löschen
POST /api/v2/prices # Anlegen
PUT /api/v2/prices/{id} # Ändern
POST /api/v2/prices/{id}/duplicate # Kopieren
POST /api/v2/prices/bulk-create # Sammelanlage für Matrix-Lücken
POST /api/v2/prices/bulk-adjust # Preisrunde (dry_run unterstützt)
GET /api/v2/prices/export # Preisliste als CSV
POST /api/v2/prices/import-preview # Import einordnen, ohne zu schreiben
POST /api/v2/prices/import # Import ausführen
POST /api/v2/prices/bulk-delete # Massenlöschen
DELETE /api/v2/prices/{id} # Löschen
Berechtigungen¶
| Recht | Erlaubt |
|---|---|
price_view |
Preisliste und Matrix lesen, CSV-Export |
price_edit |
Anlegen, Ändern, Duplizieren, Sammelanlage, Preisrunde, Import |
price_delete |
Löschen und Massenlöschen |