DCC-Export¶
Export von Digitalen Kalibrierscheinen (Digital Calibration Certificates) im calServer v2.
Überblick¶
Der DCC-Export erzeugt XML-basierte Kalibrierscheine nach dem PTB-Standard (Physikalisch-Technische Bundesanstalt). Ein DCC enthält alle relevanten Informationen einer Kalibrierung in einem maschinenlesbaren Format.
PTB DCC-Standard
Das Digital Calibration Certificate (DCC) ist ein internationaler Standard für den digitalen Austausch von Kalibrierergebnissen. Er ermöglicht die automatische Verarbeitung und Validierung von Kalibrierdaten.
API-Endpunkt¶
Der DCC-Export ist über die V2-API verfügbar:
| Parameter | Typ | Beschreibung |
|---|---|---|
ctag |
string |
Eindeutiger Kalibrierungs-Tag (CTAG) |
report_id |
string |
Der angeklickte DCC-Eintrag (siehe Menükonfiguration). Ohne Angabe nimmt der Export den ersten konfigurierten Eintrag. |
include_pdf |
bool |
Erzwingt XML-only, unabhängig von der Konfiguration. Vorgabe: true. |
Antwort: JSON mit DCC-XML-Daten und Metainformationen.
{
"data": {
"type": "dcc",
"attributes": {
"xml": "<?xml version=\"1.0\" ...?>...",
"calibration_id": "CTAG-123",
"generated_at": "2026-03-08T10:00:00Z"
}
}
}
Berechtigung¶
Der Endpunkt erfordert die Berechtigung calibration_view sowie using_API.
Menükonfiguration¶
Der DCC war in V2 ein fest verdrahteter Knopf: „DCC Export" stand im Mehr-Menü jeder Kalibrierung, für jeden, der die Kalibrierung sehen durfte, und welcher Kalibrierschein eingebettet wurde, riet der Server (erster Direktdruck-Bericht, sonst der erste überhaupt). Das ist bei einem Dokument, das ein Labor herausgibt, die falsche Voreinstellung: wer den Schein ausgeben darf und welcher Schein das ist, ist eine Laborentscheidung.
V1 hat das nie anders gemacht — dort hängt der Eintrag
„Berichtsname (DCC XML)" am Report-Paket, das eine
schema/dcc-mapping.json mitbringt (AdminReportSetting::hasDccMapping()),
und erbt damit Platzierung, Reihenfolge und Rollen-/Gruppenkreis vom Bericht.
V2 erzeugt das DCC aus den Kalibrierdaten, es gibt also keine Mapping-Datei zu
erkennen — dieselbe Auskunft kommt jetzt aus der Konfiguration.
Admin → Berichte → Bericht bearbeiten (nur bei Grid calibration):
| Feld | Spalte | Bedeutung |
|---|---|---|
| DCC-Export anbieten | is_dcc |
Der Bericht bekommt zusätzlich den Eintrag „Berichtsname (DCC XML)". |
| Menschenlesbaren Schein einbetten | dcc_include_pdf |
PDF im dcc:document. Aus = reines XML. Vorgabe: an. |
| Einzubettender Schein | dcc_pdf_report_uID |
Welcher Kalibrierschein eingebettet wird. Leer = dieser Bericht selbst. |
Was daraus folgt:
- Wo — der DCC-Eintrag steht direkt unter seinem Bericht, im selben
Kontext (
menu: Detail, Master, Master-Detail) und in derselben Reihenfolge (sort_order). Ein Bericht mitmenu = Masterhat auf der Detailseite keinen DCC-Eintrag, weil er dort selbst keinen hat. - Durch wen —
role_name/group_iddes Berichts gelten unverändert (ReportAccessService). Wer den Bericht nicht sieht, bekommt weder ihn noch sein DCC — auch nicht über einen direkten Aufruf mit dessenreport_id(404). - Welche Repräsentation — der eingebettete Schein ist wählbar. Mehrere
Berichte dürfen
is_dcctragen; dann gibt es mehrere DCC-Einträge, jeder mit seinem eigenen Schein. - Der Feature-Flag
enable_dcc_pluginbleibt der Hauptschalter. Ist er aus, liefertGET /calibrations/{ctag}/reportsis_dcc: falseund es erscheint kein Eintrag — genau wie in V1.
Die Regeln stehen in DccReportSettingResolver, die Eingabeprüfung in
ValidatesDccReportConfig (DCC nur am Kalibrier-Grid, der eingebettete Schein
muss ein aktiver Kalibrierbericht sein und darf nicht der Bericht selbst sein).
Bestandsinstallationen
Die Migration setzt is_dcc auf genau den Bericht, den der Export bisher
schon eingebettet hätte — aber nur, wenn das DCC-Plugin eingeschaltet ist.
Das bisherige Verhalten steht danach als Konfigurationszeile da, statt
weiterhin geraten zu werden. Wer das Plugin erst später einschaltet, muss
den Eintrag einmal setzen; ohne konfigurierten Bericht gibt es keinen
Menüeintrag.
API-Clients
POST /calibrations/{ctag}/dcc ohne report_id funktioniert weiterhin,
auch auf einer Installation ohne konfigurierten Eintrag — dort greift die
alte automatische Auswahl des eingebetteten Scheins.
DCC-XML-Struktur¶
Ein generiertes DCC-XML enthält folgende Hauptbereiche:
<?xml version="1.0" encoding="UTF-8"?>
<dcc:digitalCalibrationCertificate
xmlns:dcc="https://ptb.de/dcc">
<!-- Administrative Daten -->
<dcc:administrativeData>
<dcc:calibrationLaboratory>...</dcc:calibrationLaboratory>
<dcc:coreData>
<dcc:uniqueIdentifier>CTAG-123</dcc:uniqueIdentifier>
<dcc:beginPerformanceDate>2026-01-15</dcc:beginPerformanceDate>
<dcc:endPerformanceDate>2026-01-15</dcc:endPerformanceDate>
</dcc:coreData>
</dcc:administrativeData>
<!-- Messergebnisse -->
<dcc:measurementResults>
<dcc:measurementResult>...</dcc:measurementResult>
</dcc:measurementResults>
</dcc:digitalCalibrationCertificate>
Inhaltsbereiche¶
| Bereich | Quelle | Beschreibung |
|---|---|---|
| Kalibrierlabor | Systemkonfiguration | Name, Adresse, Akkreditierung |
| Kerndaten | tbl_calibration |
CTAG, Datum, Prüfer |
| Prüfmittel | tbl_inventory |
MTAG, Seriennummer, Beschreibung |
| Kunde | tbl_customer |
Auftraggeber |
| Messergebnisse | tbl_test_step |
Einzelne Prüfschritte mit Soll/Ist-Werten |
| Bezugsnormale | tbl_standard_article |
Verwendete Referenznormale |
Datenfluss¶
Calibration (CTAG)
│
├── Inventory (MTAG) ──► Prüfmitteldaten
│
├── Customer (KTAG) ──► Auftraggeberdaten
│
├── TestSteps ──► Messergebnisse
│ │
│ └── Soll-/Ist-Werte, Toleranzen, Einheiten
│
└── StandardArticles ──► Bezugsnormale
│
└── Referenznormale mit Rückführbarkeit
Konfiguration¶
DCC-spezifische Einstellungen werden über die Property-Tabelle gesteuert:
| Property | Beschreibung |
|---|---|
dcc_laboratory_name |
Name des Kalibrierlabors |
dcc_accreditation_number |
Akkreditierungsnummer (DAkkS o.ä.) |
dcc_schema_version |
DCC-Schema-Version (Standard: 3.2.1) |
Validierung
Das generierte XML wird gegen das offizielle PTB-DCC-Schema validiert,
bevor es an den Client zurückgegeben wird. Fehlende Pflichtfelder führen
zu einer 422 Unprocessable Entity-Antwort mit Details zu den fehlenden Daten.
Keine erfundenen Werte¶
Ein Kalibrierschein, der behauptet, das Gerät habe 0 V angezeigt, wo in Wahrheit nichts erfasst wurde, ist schlimmer als gar kein Schein: das Dokument ist schemagültig, die Aussage ist falsch, und keine Prüfsoftware der Welt kann das erkennen. Deshalb gilt im Export durchgehend:
Fehlt eine Angabe, wird sie nicht ersetzt. Je nachdem, was das Schema zulässt, heißt das:
| Fall | Verhalten |
|---|---|
| Messwert oder Referenzwert einer Zeile fehlt | Export wird abgelehnt (422), die betroffenen Zeilen stehen in der Meldung |
| Einheit einer Messzeile fehlt | dito |
| Zeile ohne jeden Zahlenwert (Sichtprüfung, Bemerkung) | keine Messzeile, blockiert nichts, kommt nicht in die Werteliste |
| Messabweichung oder Messunsicherheit fehlt in einer Zeile der Gruppe | die ganze Größe entfällt; eine si:...XMLList hat keine Lücken |
| Land nicht zuordenbar | dcc:countryCode entfällt (das Schema führt die Adressteile als Auswahl) |
| Kontakt ganz ohne Anschrift | ausdrücklicher Vermerk in dcc:further statt eines geratenen Landes |
| Laborname nicht konfiguriert | Export wird abgelehnt (422), mit Verweis auf Admin → Berichtsverwaltung → Berichtseinstellungen → Laborangaben |
Die Vorabprüfung sitzt in DccXmlGeneratorService::missingPrerequisites() und
läuft im Endpunkt, bevor überhaupt XML entsteht.
Die Ablehnung als Arbeitsliste¶
Der Satz in error.detail sagt, was fehlt, aber nicht, wo es steht. „Zeile 3
(Resistance 100 Ohm): angezeigter Messwert fehlt" ist als Fließtext richtig und
als Arbeitsanweisung nutzlos — gesucht werden muss trotzdem selbst. Die 422
trägt deshalb dieselbe Auskunft maschinenlesbar daneben:
{
"error": {
"status": 422,
"title": "DCC Export Incomplete",
"detail": "Für ein gültiges DCC (PTB 3.3.0) fehlt noch: …",
"missing": [
{
"code": "lab_name",
"label": "der Name des Kalibrierlabors",
"fix": "report_variable",
"hint": "Admin → Berichtsverwaltung → Berichtseinstellungen → Laborangaben",
"rows": []
},
{
"code": "results",
"label": "ein vollständiges Wertepaar aus Referenz- und Messwert in 1 Messzeile(n)",
"fix": "results",
"hint": "Zeile 3 (Resistance 100 Ohm): angezeigter Messwert fehlt",
"rows": [
{
"row_number": 3,
"label": "Resistance 100 Ohm",
"reason": "angezeigter Messwert fehlt"
}
]
}
]
}
}
| Feld | Bedeutung |
|---|---|
code |
Stabiler Bezeichner: inventory, customer, calibration_date, lab_name, results |
label |
Klartext, wie er auch im Satz steht |
fix |
Sprungziel: calibration_record (Datensatz bearbeiten), report_variable (Berichtsverwaltung), results (Messwertraster) |
hint |
Ergänzung — Pfad zur Einstellung bzw. Kurzliste der Zeilen (max. 5, dann …) |
rows |
Betroffene Messzeilen, vollständig und nach row_number sortiert |
row_number ist die Nummer aus dem Messwertraster (results.row_num), nicht
die Position in der Liste — nur damit findet man die Zeile wieder, wenn die
Erfassung nicht bei 1 anfängt.
Satz und Liste stammen aus derselben Quelle: missingPrerequisites() rendert
seine Sätze aus genau diesen Einträgen (describeMissing()), sie können also
nicht auseinanderlaufen. Clients, die nur detail lesen, bleiben gültig; das
Frontend zeigt die Ablehnung als stehenden Block (DccIssuePanel) mit einem
Link je Punkt statt als Toast, der nach fünf Sekunden verschwindet, während man
noch sucht. Ein Klick auf eine Messzeile öffnet den Ergebnis-Tab und hebt genau
diese Zeile hervor.
Verhaltensänderung
Installationen ohne gepflegten lab_name bekommen jetzt eine 422 statt
eines Scheins mit dem Platzhalter „Kalibrierlabor" als Aussteller.
Einmalige Konfiguration, danach ist Ruhe.
refTypes¶
refType ist die maschinenlesbare Sprungmarke im DCC — daran findet ein
Empfänger den Messwert, das Normal, die Messabweichung. Die XSD prüft sie
nicht (refTypesType ist eine Liste beliebiger Zeichenketten);
verbindlich ist der refType-Thesaurus des DKD
(digilab.ptb.de/dkd/refType/vocab/). Ein erfundener Bezeichner ist deshalb
kein Schemafehler, sondern totes Gewicht.
Der Export schreibt Marken aus dem basic_-Namensraum (messgrößen-
übergreifend). DccRefTypeTest::DKD_REF_TYPES führt die vollständige Liste mit
Herkunft und Platzierungsregel und schlägt fehl, sobald eine neue dazukommt.
Jede Marke ist gegen den Thesaurus geprüft (Stand 2026-09-03). Ersetzt wurden
dabei basic_recalibration → basic_recalibrationDate, basic_uncertainty →
basic_methodMeasurementUncertainty und gp_method →
basic_calibrationMethod; einen Namensraum gp_ führt der Thesaurus nicht.
Eigene Marken¶
Für zwei Aussagen führt der Thesaurus keinen Begriff: die Messbedingungen als Freitext und die angewandte Prüfvorschrift. Beide tragen einen eigenen Namensraum und werden im Schein selbst erklärt:
| refType | Element | Bedeutung |
|---|---|---|
calServer_measurementConditions |
dcc:usedMethod |
Messbedingungen als Freitext (Report-Variable) |
calServer_measuringProcedure |
dcc:usedMethod |
angewandte Prüfvorschrift samt Version |
dcc:administrativeData/dcc:refTypeDefinitions erklärt jede davon mit
Namensraum und Link. Der Knoten steht nur im Schein, wenn er eine solche Marke
auch trägt — refTypeDefinitionListType verlangt mindestens einen Eintrag.
Ein erfundenes basic_… sähe amtlich aus und wäre keins; eine erklärte eigene
Marke kann ein Empfänger auflösen.
Bewusst unverändert
basic_pressure sitzt an der dcc:influenceCondition, obwohl der
Thesaurus dafür nur ruleQuantity führt (basic_temperature und
basic_humidityRelative daneben auch ruleInfluenceCondition). Welches
Element eine Marke tragen darf, wertet bisher kein Prüfer aus; eine der
drei Bedingungen anders zu schreiben brächte nur Uneinheitlichkeit.
dcc:result trägt bewusst keine Marke: der früher dort stehende
Bezeichner gp_measuredQuantity stand in keinem Namensraum, und die Bedeutung
steckt ohnehin an den dcc:quantity-Elementen darin
(basic_referenceValue, basic_measuredValue, basic_measurementError).
Einheiten: D-SI-Notation¶
Das DCC schreibt Einheiten nicht als mV oder °C, sondern in der
D-SI-Notation der PTB: \milli\volt, \degreecelsius. Die Umsetzung macht
DccXmlGeneratorService::toSiUnit() in dieser Reihenfolge:
- Schreibvarianten —
Ohm,kOhm,uV,degCwerden auf das kanonische Symbol gezogen (Ω,kΩ,µV,°C). Bestandsdaten sind voll davon: der Stammdatenkatalog führtΩ, getippt wurdeOhm. - Zusammengesetzte und festgeschriebene Symbole — Produkte (
Nm→\newton\metre), Quotienten (m/s→\metre\per\second), Exponenten (m³→\metre\tothe{3}) und die Fälle mit fester Schreibweise (°C→\degreecelsius,dB→\decibel). - Stammdatenkatalog —
physical_quantity.dsi_unit, gepflegt unter Admin → Anforderungen → Physikalische Größen (siehe unten). - Basiseinheit ohne Vorsatz —
V→\volt,h→\hour. - Vorsatz + Basiseinheit — jede Kombination aus der
si_prefix-Tabelle und dem Einheitensymbol:mV,kΩ,hPa,daN,µS. Der Vorsatz greift auch auf Katalogeinträge, sofern deren Schreibweise eine einzelne Marke ist. - Sonst der
|-Auslassungsstrich —HRCwird zu|HRC.
Punkt 6 ist der Unterschied zu früher: eine Einheit außerhalb der Liste ging unverändert ins XML und war dort keine gültige D-SI-Zeichenkette. Der Auslassungsstrich ist die vom D-SI dafür vorgesehene Schreibweise — der Wert bleibt lesbar, das Dokument bleibt gültig. Maschinell auswertbar ist eine solche Einheit für die Gegenstelle trotzdem nicht; der Prozedureditor weist beim Erfassen darauf hin.
Drei Regeln des D-SI, die im Code sichtbar sind:
- R10 — Minute, Stunde, Tag, Hektar, mmHg und die Verhältnisgrößen (
%,ppm) vertragen keinen Vorsatz.kmingibt es nicht und wird|kmin. - R11 — das Kilogramm ist die Basiseinheit und heißt
\kilogram, nicht\kilo\gram. - R12 — Dezibel heißt
\decibel, nicht\deci\bel.
Einheiten ohne D-SI-Entsprechung sind bewusst als |-Einheit hinterlegt:
pH (zerfiele sonst in Piko + Henry), dBm (ein Pegel bezogen auf 1 mW, kein
Produkt aus Dezibel und Milliwatt) sowie die Härteskalen HRC, HV, HBW.
Die XSD prüft die Einheit nicht
si:unitType ist in D-SI 2.2.1 ein unbeschränkter xs:string — eine
Schemavalidierung nimmt auch HRC an. Die Grammatik steht in den
D-SI-Regeln. DccUnitNotationTest prüft deshalb jede erzeugbare
Zeichenkette gegen die Regex der PTB-Referenzimplementierung
(tests/Fixtures/dcc-schema/d-si-unit.regex).
Einheiten selbst richtigstellen¶
Die Zuordnung Symbol → D-SI stand früher ausschließlich als Konstante im
Generator. Alles, was die dortigen Tabellen nicht kannten, ging als
|Einheit in den Schein — gültig, aber maschinell wertlos, und ohne Release
nicht zu korrigieren. Dabei kommt die Einheit aus einem Katalog, den das Labor
selbst pflegt.
Deshalb hat physical_quantity die Spalte dsi_unit, editierbar unter
Admin → Anforderungen → Physikalische Größen:
- Leer: der Export leitet die Schreibweise wie bisher aus dem Symbol ab.
- Gesetzt: der Katalogwert gewinnt — auch gegen die eingebaute Tabelle.
- Geprüft wird die Form (
\marke, klein, ohne Leerzeichen, Exponent als\tothe{2},|für Einheiten außerhalb des D-SI), nicht das Vokabular: eine exotische, aber gültige Einheit soll nicht an der Eingabemaske scheitern.
Die Werksvorgabe bringt die Schreibweise für alle rund 50 Katalogeinträge mit
(App\Support\SiUnitCatalog); die Migration trägt sie für Bestandszeilen nach,
ohne selbst gesetzte Werte anzufassen. Die Spalte ist eine reine V2-Änderung —
V2 teilt sich keine Tabellen mehr mit V1 und läuft auch nach dessen Abschaltung
eigenständig weiter.
Verwandte Dokumentation¶
- Datenmodell — Tabellenstruktur für Kalibrierungen
- Feldkonstanten — C23xx Metrologie-Codes