Zum Inhalt

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:

  1. Preis dieser Leistung für diesen Gerätetyp
  2. Preis dieser Leistung für die Preiskategorie, in der der Gerätetyp liegt
  3. 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

docker exec calserver-api-v2 php artisan price-classes:derive

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:

  1. create_config mit standard_article → liefert die uID des Artikels.
  2. create_config mit service_price und service_id = dieser uID.

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