Zum Hauptinhalt springen

12. Order-Service

Greifen Sie über client.order() zu. Der gesamte Lebenszyklus eines Arbeitsauftrags (Work Order) von Erstellung → Start → Stopp/Fortsetzung → Abschluss wird über eine ISA-88-basierte Zustandsmaschine verwaltet.

11.1 Status des Arbeitsauftrags (ISA-88-basiert)​

CREATE → WAIT ──start()──► START ──pause()──► PAUSED
│ │
│ resume()
│ │
▼ ▼
END ◄──end()──── START
│
└─ (또는) ──abort()──► ABORTED
Status (status)BedeutungTransitionsmethodeISA-95 Status (isa95_state)
WAITWartend (Initialzustand nach Erstellung)Ergebnis von create()Ready
STARTIn Arbeitstart(), resume()Running
PAUSEDPausiertpause()Held
ENDNormal abgeschlossenend()Completed
ABORTEDAbnormal beendetabort()Aborted

status entspricht exakt dem gespeicherten Wert und umfasst nur diese fünf Zustände. Ein Arbeitsauftrag, der vor dem Start storniert wurde, ist kein neuer Status, sondern ABORTED + abort_code=CANCELLED. Arbeitsauftragszeilen (/order·Liste·/order/query), Leistungsdokumente und plantpulse.order.*-Events ergänzen hier den ISA-95 Part 4 Status des Arbeitsauftrags isa95_state — die Zuordnung erfolgt über die obige Tabelle, und alle Pfade liefern denselben Wert.

Aufrufe, die eine nicht zulässige Zustandsänderung bewirken (z. B. erneuter Aufruf von start() im Status START), führen dazu, dass der Server eine Antwort OK + data.success=false sendet; V5-Methoden geben false zurück.

11.2 Methodenübersicht​

CRUD​

MethodeRückgabetypHTTPEndpunkt
create(OrderRequestV5)OrderResponseV5 oder nullPOST/api/v5/order
update(order_id, OrderRequestV5)OrderResponseV5 oder nullPUT/api/v5/order/{id}
delete(order_id)booleanDELETE/api/v5/order/{id}
get(order_id)OrderResponseV5 oder nullGET/api/v5/order/{id}
list()List<OrderResponseV5>GET/api/v5/order
exists(order_id)booleanGET/api/v5/order/{id}/exists

Lebenszyklus (Alle geben boolean zurück)​

MethodeHTTPEndpunkt
start(order_id)POST/api/v5/order/{id}/start
end(order_id)POST/api/v5/order/{id}/end
pause(order_id)POST/api/v5/order/{id}/pause
resume(order_id)POST/api/v5/order/{id}/resume
abort(order_id)POST/api/v5/order/{id}/abort

11.3 OrderRequestV5 / OrderResponseV5​

FeldTypBeschreibung
order_idStringArbeitsauftrags-ID (PK)
order_nameStringName des Arbeitsauftrags — Pflichtfeld, darf nicht leer sein (422 order.name.required). Name des B2MML JobOrder
descriptionStringBeschreibung
site_idStringZugehörige Site
asset_idStringZielanlage (Equipment)
customer_idStringKunde (Optional)
product_idStringZu produzierendes Produkt
employee_idStringZuständiger Mitarbeiter (Optional)
planned_quantityQuantityGeplante Menge — ISA-95 / B2MML QuantityValueType. Siehe 11.5 Menge
time_per_unit_in_mslongStandardzeit pro Einheit
planned_start_timestamplongGeplanter Startzeitpunkt (Millisekunden)
planned_end_timestamplongGeplanter Endzeitpunkt (Millisekunden)
external_idStringArbeitsauftragsnummer des externen Systems (MES·ERP, bis 100 Zeichen). Wird als Paar mit external_system identifiziert — 11.6
external_systemStringName des externen Systems, das den Arbeitsauftrag erstellt hat (bis 50 Zeichen) — zweite Hälfte des externen Identifikationspaares
customer_po_idStringKundenbestellnummer (PO) für diesen Arbeitsauftrag (Optional)
statusString(Nur Antwort) Aktueller Status — Gespeicherte Werte WAIT·START·PAUSED·END·ABORTED
isa95_stateString(Nur Antwort) ISA-95 Status des Arbeitsauftrags — Ready·Running·Held·Completed·Aborted (11.1)
Name geändert im November 2026 — keine Aliase

title → order_name, fix_start_timestamp·fix_end_timestamp → planned_start_timestamp·planned_end_timestamp, external_order_id → external_id, external_po_id → customer_po_id. Alte Namen werden weder in Anfragen gelesen noch in Antworten ausgegeben — Upgrade-Notes.

11.4 Anwendungsbeispiele​

Erstellung eines Arbeitsauftrags​

import plantpulse.api.v5.dto.Quantity;
import plantpulse.api.v5.dto.request.OrderRequestV5;
import plantpulse.api.v5.dto.response.OrderResponseV5;

OrderRequestV5 req = new OrderRequestV5();
req.setOrder_id("ORDER_000001");
req.setOrder_name("5월 14일 1교대 생산");
req.setDescription("PROD_A001 500개 생산");
req.setSite_id("SITE_DJ");
req.setAsset_id("ASSET_DJ_M_0001");
req.setProduct_id("PROD_A001");
req.setCustomer_id("CUST_001");
req.setEmployee_id("EMP_E12345");
req.setPlanned_quantity(Quantity.of("500", "EA")); // 값은 10진 «문자열», 단위는 UN/ECE Rec 20 코드
req.setTime_per_unit_in_ms(5_000);

long now = System.currentTimeMillis();
req.setPlanned_start_timestamp(now);
req.setPlanned_end_timestamp(now + 4 * 3600_000L);
req.setExternal_id("MES-2026-0514-001");
req.setExternal_system("MES");

OrderResponseV5 created = client.order().create(req);

Standard-Lebenszyklus​

String orderId = "ORDER_000001";

// WAIT → START
if (!client.order().start(orderId)) {
System.err.println("시작 실패 — planned_start_timestamp가 미래이거나 이미 진행중");
return;
}

// 잠시 후 — 일시중지
client.order().pause(orderId);

// 재개
client.order().resume(orderId);

// 정상 종료
client.order().end(orderId);

Abnormaler Abschluss​

// abort 는 별도 인자 없이 호출. 상세 사유는 update() 로 description/notes 에 기록.
if (!client.order().abort("ORDER_000001")) {
System.err.println("중단 실패");
}

Einzelabfrage / Existenzprüfung​

OrderResponseV5 o = client.order().get("ORDER_000001");
if (o != null) {
System.out.println("상태: " + o.getStatus());
Quantity planned = o.getPlanned_quantity(); // {quantity_string, data_type, unit_of_measure}
System.out.println("계획: " + planned.getQuantity_string() + " " + planned.getUnit_of_measure());
java.math.BigDecimal value = planned.toBigDecimal(); // 계산은 BigDecimal 로 — double 로 바꾸지 않는다
}

boolean exists = client.order().exists("ORDER_000001");

Gesamte Liste​

import java.util.List;

List<OrderResponseV5> all = client.order().list();
for (OrderResponseV5 o : all) {
System.out.printf("[%s] %s — %s%n",
o.getStatus(), o.getOrder_id(), o.getOrder_name());
}

Nur laufende Arbeitsaufträge (Client-seitige Filterung)​

import java.util.stream.Collectors;

List<OrderResponseV5> active = client.order().list().stream()
.filter(o -> "START".equals(o.getStatus())
|| "PAUSE".equals(o.getStatus()))
.collect(Collectors.toList());

Arbeitsaufträge nach Anlage​

String assetId = "ASSET_DJ_M_0001";
List<OrderResponseV5> assetOrders = client.order().list().stream()
.filter(o -> assetId.equals(o.getAsset_id()))
.collect(Collectors.toList());

Statistiken nach Status​

import java.util.Map;

Map<String, Long> byStatus = client.order().list().stream()
.collect(Collectors.groupingBy(
OrderResponseV5::getStatus,
Collectors.counting()));

byStatus.forEach((status, count) ->
System.out.printf("%s: %d건%n", status, count));

Bearbeiten / Löschen​

// 수정 (계획 시간 연장)
OrderRequestV5 update = new OrderRequestV5();
update.setOrder_id("ORDER_000001");
update.setOrder_name("5월 14일 1교대 생산 (연장)");
// ... 모든 필드 다시 세팅 ...
update.setPlanned_end_timestamp(System.currentTimeMillis() + 8 * 3600_000L);
client.order().update("ORDER_000001", update);

// 삭제 (취소 처리)
client.order().delete("ORDER_000001");

11.5 Menge — ISA-95 Quantity​

Die Menge eines Arbeitsauftrags (geplant, produziert, Gutteile, Ausschuss, Nacharbeit ...) ist kein einzelner Zahlenwert, sondern ein Objekt, das Wert und Einheit enthält. Die Struktur entspricht 1:1 den QuantityValueType von ISA-95(IEC 62264) / B2MML V0700.

Geltungsbereich dieses Abschnitts

Basis sind V5 API (OpenAPI info.version 5.0), Mengenvereinbarung 2026-10-30, Namenswave 2026-10-31 und Platform-Version November 2026 (server-web 974891b4). Events folgen dem Schema plantpulse.order.*·plantpulse.calendar.* Major 2, plantpulse.kpi.oee.finalized Major 1; DB nutzt Flyway V99·V100·V103 und Core-Migration V12V16·V21V23 — Upgrade-Notes.

[
{ "quantity_string": "1250.5", "data_type": "decimal", "unit_of_measure": "KGM" },
{ "quantity_string": "1200", "data_type": "integer", "unit_of_measure": "EA" }
]
FeldB2MMLTypRegel
quantity_stringQuantityStringstringExakte Dezimaldarstellung — Exponentialdarstellung verboten, Dezimaltrennzeichen ist ., bis zu vier Dezimalstellen. Zähleinheiten müssen Ganzzahlen sein
data_typeDataTypestringinteger (Zähleinheit) oder decimal (Sonstige). Wird vom Server basierend auf der Einheit festgelegt — kann in der Anfrage weggelassen werden; wenn angegeben, muss es zur Einheit passen
unit_of_measureUnitOfMeasurestringUN/ECE Recommendation 20 Common Code — siehe folgende Liste
Warum ist der Wert ein String?

B2MML definiert dies als QuantityString. Zudem lesen die meisten JSON-Parser Zahlen als Double, was zu Präzisionsverlusten bei Dezimalzahlen führt. Verwenden Sie im SDK Quantity.toBigDecimal() zum Lesen und Berechnen. Bei der Erstellung einer Anfrage nutzen Sie Quantity.of("1250.5", "KGM") — wenn data_type leer bleibt, füllt der Server dies automatisch aus.

Einheiten — Zulassungsliste (UN/ECE Rec 20)​

CodeBedeutungdata_typeBildschirmsymbol
EAeach — StückzählungintegerEA
H87pieceintegerpc
C62one (unit)integerunit
BXbox — Anzahl Boxenintegerbox
SETset — Anzahl Sätze/Kitsintegerset
KGMkilogramdecimalkg
GRMgramdecimalg
TNEtonnedecimalt
LTRlitredecimalL
MLTmillilitredecimalmL
MTQcubic metredecimalm³
MTRmetredecimalm
MTKsquare metredecimalm²
  • Es sind insgesamt 13 Einheiten zulässig; die Zähleinheiten sind EA·H87·C62·BX·SET. Codes außerhalb dieser Liste werden abgelehnt (quantity.unit_invalid). Die Codes werden exakt (inklusive Groß-/Kleinschreibung) verglichen — ea, KG, PCS sind keine zulässigen Codes.
  • Wenn ein Code empfangen wird, der kein Bildschirmsymbol hat (z. B. Altdaten), wird der Code selbst angezeigt.
  • Einheitenumrechnungen werden nicht durchgeführt (dies ist Aufgabe des MES). Mengen mit unterschiedlichen Einheiten werden nicht addiert.
  • Bildschirmsymbole sind sprachunabhängig — auch in koreanischen Oberflächen wird «개» nicht verwendet, sondern EA. Symbole werden immer angehängt (auch bei Stückzahlen).

Feldbezeichnungen — ISO 22400​

Die Feldbezeichnungen folgen der Terminologie von ISA-95 und ISO 22000-2 (KPI-Gegenstück zu IEC 62264). Alte Namen erscheinen nicht mehr in Antworten (keine Kompatibilitätsfelder).

BedeutungFeld (Quantity)Altes FeldGrundlage
Geplante Mengeplanned_quantitytarget_units + unitISA-95 MaterialRequirement.Quantity · ISO 22400 POQ
Produktionsmengeproduced_quantitytotal_production_countISO 22400 PQ
Gutteilmengegood_quantitytotal_good_count · good_countISO 22400 GQ
Ausschussmengescrap_quantitytotal_bad_count · bad_count — Bedeutung wurde eingegrenzt: Altes Feld war Gesamtausschuss, neues Feld nur physischer AusschussISO 22400 SQ
Nacharbeitsmengerework_quantity(Keines — neues Feld)ISO 22400 RQ
Geplant außerhalb Gutteil / Ausschussgood_quantity_out_of_plan / scrap_quantity_out_of_planout_of_plan_good_count / out_of_plan_bad_count
Gemessene Gutteile / Ausschuss (PLC)measured_good_quantity / measured_scrap_quantitymeasured_good_count / measured_bad_count
Korrektur +/-good_quantity_delta / scrap_quantity_deltagood_delta / bad_delta
Korrektureingabewertentered_good_quantity / entered_scrap_quantityentered_good / entered_bad
Prüfmengeinspected_quantityinspected_count
Summe Prüfausschussinspected_scrap_quantityinspected_bad_count
Ausschussaufzeichnung nach Verwertungscrap_quantity / rework_quantityscrap_count / rework_countISO 22400 SQ / RQ

Geänderte Antworten: /order, /order/query(include=oee), /order/{id}/oee, /order/{id}/quantity (inkl. Revisionshistorie), /defects, /order/performance, /kpi/oee/history, /asset/{id}/status, MCP-Arbeitsauftragswerkzeug, Produktionsereignis OEE_CALCULATED.

  • Die Felder planned_quantity·good_quantity·scrap_quantity von /asset/{id}/status werden in der Einheit des laufenden Arbeitsauftrags ausgegeben. Wenn kein Arbeitsauftrag läuft, ist der Wert null.
  • Verhältnisfelder (total_good_rate, production_rate, Verfügbarkeit·Leistung·Qualität·OEE) sind dimensionslos und daher einfache Zahlen.
  • In /asset/{id}/status gibt es ebenfalls rework_quantity (Nacharbeit des laufenden Arbeitsauftrags).
  • PLC-Zähleraufzeichnungen (good_quantity·scrap_quantity von GET /api/v5/kpi/oee/count) und Ursachenausschuss in MCP get_asset_kpi (scrap_quantity) sind Quantity-Werte in der Einheit des Arbeitsauftrags zu diesem Zeitpunkt. Da Zähler Ganzzahlen verwenden, gilt Count 1 = 1 Einheit des Arbeitsauftrags — ein Ganzzahlzähler an einem kg-Arbeitsauftrag zählt nur in 1-kg-Schritten. Dezimalwerte werden nicht über Zähler, sondern über Mengenkorrekturen oder Leistungseingaben erfasst.

Ausschuss und Nacharbeit — «Ausschuss» als Summe​

Gemäß ISO 22400 wird Ausschuss in physischen Ausschuss (SQ) und Nacharbeit (RQ) unterteilt.

  • Ausschuss = physischer Ausschuss + Nacharbeit, Produktion = Gutteile + physischer Ausschuss + Nacharbeit (produced_quantity = good_quantity + scrap_quantity + rework_quantity).
  • scrap_quantity bezieht sich nur auf physischen Ausschuss. Vom PLC gezählte Fehler werden, da die Verwertung unbekannt ist, als physischer Ausschuss gezählt. Nacharbeit entsteht nur aus Fehleraufzeichnungen mit der Verwertung REWORK.
  • Die Qualitätsrate (Q) ist Gutteile ÷ Produktion, daher mindert auch Nacharbeit die Qualität — sie wird lediglich getrennt aufgeführt, der OEE-Wert bleibt unverändert.
  • In der Benutzeroberfläche wird diese Unterscheidung textlich eingehalten: Stellen, die nur physischen Ausschuss angeben (Spalte Produktionshistorie, Feld Mengenkorrektur), werden als «Ausschuss» bezeichnet. Stellen, die die Summe anzeigen, heißen «Ausschuss», wobei bei vorhandener Nacharbeit Details wie «14 kg (Ausschuss 12,75 · Nacharbeit 1,25)» angehängt werden — Produktionsmanagement — Menge und Einheit.
  • Wenn eine Integration eine «Ausschusssumme» benötigt, addieren Sie scrap_quantity + rework_quantity als Dezimalzahlen innerhalb derselben Einheit. Lesen Sie scrap_quantity nicht allein als Ausschusssumme.

Zuweisung der Mengen zu den Feldern — Zählertabelle​

Quelle (Speicherung)V5-Feld / Event-FeldErfasste Menge
PLC-Zählerhauptbuch tm_kpi_oee_countgood_quantity · scrap_quantity von /kpi/oee/countPLC-gemessene Inkremente für Gutteile/Ausschuss. Da Verwertung unbekannt: Ausschuss = physischer Ausschuss (SQ)
Arbeitsauftrags-OEE-Zeile mm_order_oee.total_production_countproduced_quantity · Event pq/pq_quantityProduktion (PQ) = Gutteile + physischer Ausschuss + Nacharbeit
mm_order_oee.total_good_countgood_quantity · gq/gq_quantityGutteile (GQ)
mm_order_oee.total_bad_count − total_rework_countscrap_quantity · sq/sq_quantityphysischer Ausschuss (SQ). total_bad_count selbst (Ausschusssumme) wird nicht über die Leitung übertragen
mm_order_oee.total_rework_countrework_quantity · rq/rq_quantityNacharbeit (RQ)
mm_order_oee.out_of_plan_good_count / out_of_plan_bad_countgood_quantity_out_of_plan / scrap_quantity_out_of_plan · gq_out_of_plan/sq_out_of_plan(+_quantity)Während geplanter Stillstände produzierte Menge — enthalten in obigen Gutteilen/Ausschuss, wird bei Effizienzberechnung abgezogen
Mengenkorrektur mm_order_quantity_correctionmeasured_*_quantity · good_quantity_delta/scrap_quantity_delta · (Historie) entered_*_quantity von /order/{id}/quantityPLC-Messwert, Korrektur +/- , REPLACE-Eingabewert. Das Ausschussfeld enthält nur physischen Ausschuss
Fehleraufzeichnung mm_defect_record (Verwertung SCRAP/REWORK)quantity·inspected_quantity von /defects, Leistungsdokument defects.scrap_quantity / rework_quantity / inspected_scrap_quantityphysischer Ausschuss/Nacharbeit nach Verwertung, Summe Prüfausschuss (SCRAP + REWORK)
mm_order.planned_quantityplanned_quantity · Event planned_quantityGeplant (POQ)

Anfrageregeln und Ablehnung​

Mengen, die in Leistungs-, Korrektur- oder Fehleraufzeichnungen eingetragen werden, müssen die gleiche Einheit wie der Arbeitsauftrag planned_quantity haben. Der Server führt keine Umrechnung durch und lehnt die Anfrage ab. Die Ablehnung von Wert/Einheit erfolgt über 422 E1002 (nicht 400). In der Antwort (application/problem+json) gibt code den Wert E1002 an, und das Feld reason enthält den folgenden Fehlercode. Da detail ein in der Sprache des Aufrufers verfasster Satz ist, führen Sie Verzweigungen über reason durch.

FehlercodeZeitpunkt
quantity.unit_mismatchEine andere Einheit als die des Arbeitsauftrags wurde gesendet
quantity.not_integerEin Dezimalwert für eine Zähleinheit (EA·H87·C62·BX·SET) wurde gesendet
quantity.unit_invalidEinheit fehlt oder liegt außerhalb der 13 zulässigen Einheiten
quantity.formatquantity_string ist kein Dezimal-String (Exponentialdarstellung·führende Null·Zeichen +·Zahlentyp) oder data_type passt nicht zur Einheit
quantity.scaleMehr als vier Dezimalstellen
quantity.negativeNegativer Wert (nur Korrektur +/- Felder akzeptieren negative Werte)
quantity.rangeAbsolutwert ≥ 10¹⁴ — außerhalb des Speicherbereichs von numeric(18,4)
  • Wenn statt eines Objekts ein einfacher Wert (z. B. Zahl 500) in einem Mengenfeld angegeben wird oder Schlüssel außerhalb von quantity_string·data_type·unit_of_measure verwendet werden, erfolgt eine Antwort 400 E1000 (Formatfehler).
  • Die geplante Menge eines Arbeitsauftrags muss größer als 0 sein.

Perioden-KPI — Keine Aggregation bei gemischten Einheiten​

Antworten, die mehrere Arbeitsaufträge zusammenfassen (wie /kpi/period·/kpi/daily), bilden Summen nur dann, wenn alle eine einzige Einheit haben.

Die Summenfelder für Mengen befinden sich in good_count·total_count·in_plan_count innerhalb des Objekts oee von /kpi/period sowie in good_count·bad_count·planned_count von /kpi/daily. Die Gesamtausschusssumme in bad_count von /kpi/daily entspricht Produktion − Gutteile, also Ausschuss (physischer Ausschuss + Nacharbeit).

  • Eine einzige Einheit: Die Summenfelder für Mengen sind wie bisher Zahlen, ergänzt durch die Einheit unit_of_measure.
  • Gemischte Einheiten: Die Summenfelder für Mengen sowie unit_of_measure sind null; stattdessen enthält quantities_by_unit die Gutteil- und Produktionsmengen pro Einheit als Quantity-Objekte.
{
"good_count": null,
"total_count": null,
"in_plan_count": null,
"unit_of_measure": null,
"quantities_by_unit": [
{ "unit_of_measure": "EA",
"good_quantity": { "quantity_string": "2671", "data_type": "integer", "unit_of_measure": "EA" },
"produced_quantity": { "quantity_string": "2700", "data_type": "integer", "unit_of_measure": "EA" } },
{ "unit_of_measure": "KGM",
"good_quantity": { "quantity_string": "1250.5", "data_type": "decimal", "unit_of_measure": "KGM" },
"produced_quantity": { "quantity_string": "1302", "data_type": "decimal", "unit_of_measure": "KGM" } }
]
}

Verhältnisse (Verfügbarkeit·Leistung·Qualität·OEE) sind dimensionslos und werden auch bei gemischten Einheiten normal ausgegeben.

EMS-Wert pro Einheit — Einheit des Nenners​

Der Nenner in energy_per_unit_kwh·co2_per_unit_kg ist die Gutteilmenge des Arbeitsauftrags, daher wird in der Antwort die entsprechende Einheit unit_of_measure mitgegeben (/order/{id}/ems, /order/ems/*, /order/query?include=ems). Die Anzeige erfolgt in Formaten wie «kWh/EA», «kWh/kg». Bei Aggregationen mehrerer Arbeitsaufträge mit gemischten Einheiten sind der Wert pro Einheit und die Einheit null.

Events​

Da das Event-Schema nur «Anhängen am Ende» zulässt, wurden Felder hinzugefügt, ohne die Typen zu ändern.

EventMengenfeld
plantpulse.order.*planned_quantity(number) + planned_quantity_unit_of_measure(Rec 20 Code)
plantpulse.kpi.oee.finalizedReferenzwerte gq_quantity·sq_quantity·rq_quantity·pq_quantity·gq_out_of_plan_quantity·sq_out_of_plan_quantity(number) + unit_of_measure. sq bezieht sich nur auf physischen Ausschuss, Nacharbeit erfolgt über rq(pq = gq + sq + rq). Ganzzahlfelder gq·sq·rq·pq·... werden nur bei Zähleinheiten befüllt und fehlen bei Dezimaleinheiten — sie werden im nächsten Major-Release entfernt
Produktionsereignis OEE_CALCULATEDgood_quantity·scrap_quantity(nur physischer Ausschuss)·rework_quantity = Quantity-Objekt

11.6 MES-Integration — Leistungsfeed und B2MML-Zuordnung​

Identifikation externer Arbeitsaufträge — (external_system, external_id)-Paar​

Arbeitsaufträge von Kundensystemen (MES·ERP) werden über ein Paar aus dem Namen des ausstellenden Systems und der Nummer innerhalb dieses Systems identifiziert — analog zur externen Identifikation von Mitarbeiter- oder Instandhaltungsaufträgen.

  • Das Paar ist sowohl beim Empfang als auch beim Versand präsent. V5 POST·PUT·PATCH /api/v5/order empfangen external_system (50 Zeichen) und external_id (100 Zeichen); GET /order/{id}·Listen·/order/query und Leistungsdokumente übertragen beide Werte stets (wenn nicht vorhanden, null). Da im Konsolenformular kein Feld external_system existiert, erfolgt die Eingabe über V5.
  • Leere Werte oder Werte, die nur aus Leerzeichen bestehen, werden als null gespeichert. Überschreitungen der Länge oder Steuerzeichen führen zu 422 order.external_ref.invalid.
  • Das Paar ist eindeutig, sofern nicht beide Felder leer sind. Die Zuweisung desselben Paares zu einem zweiten Arbeitsauftrag führt zu 409 order.external.duplicate.
  • PUT ersetzt die gesamte Anfrage — fehlende external_system·external_id werden gelöscht. Für Teiländerungen verwenden Sie PATCH.
  • Arbeitsaufträge, die nur external_id, aber kein external_system besitzen, werden weiterhin akzeptiert, können jedoch nicht über die untenstehende «Suche nach Paar» gefunden werden.
  • Events übertragen ebenfalls das Paar: In plantpulse.order.* (Schema Major 2) übertragen created·updated·startedaborted die Werte external_id·external_system; Transitions-Events (startedaborted) übertragen zusätzlich customer_po_id.
  • Um einen Arbeitsauftrag über das Paar zu lesen, nutzen Sie GET /api/v5/order/by-external/{system}/{external_id} — bei Nichtexistenz 404, bei einer leeren Seite des Paares 422 order.external_ref.invalid. Der Filter in /order/query besteht ebenfalls aus external_id + external_system. Das Senden des alten Parameters external_order_id führt nicht zum Ignorieren, sondern zu einer Ablehnung mit 422.

Pfade des Leistungsfeeds​

HTTPPfadFunktion
GET/api/v5/order/performanceLeistungsfeed — cursor·site_id·limit. Arbeitsaufträge mit geänderter Leistung erhalten einen höheren Wert in performance_revision und erscheinen erneut am Ende des Feeds
GET/api/v5/order/{order_id}/performanceLeistungsdokument eines einzelnen Arbeitsauftrags
GET/api/v5/order/performance/by-external/{external_system}/{external_id}Suche nach Paar — Array (da Paare eindeutig, maximal ein Element), sonst leeres Array
Alte Pfade existieren nicht

/api/v5/order/performance/by-external/{external_order_id} (Nummer ohne System) wurde entfernt. Es gibt keine Kompatibilitätspfade.

Mengenschlüssel im Leistungsdokument​

PositionSchlüssel (alles Quantity)Alter Schlüssel
planplanned_quantitytarget_units
quantitymeasured_good_quantity / measured_scrap_quantitymeasured_good / measured_bad
quantitygood_quantity / scrap_quantitygood / bad
quantity.correctiongood_quantity_delta / scrap_quantity_deltagood_delta / bad_delta
oeegood_quantity / scrap_quantitytotal_good_count / total_bad_count
defectsinspected_scrap_quantity / scrap_quantity / rework_quantityinspected_bad_count / scrap_count / rework_count

quantity.correction_version, progress.expected_now_units·pace_units behalten ihre Namen (bei Dezimaleinheiten sind es Dezimalzahlen).

quantity.scrap_quantity bezieht sich nur auf physischen Ausschuss (PLC-Fehler + Aufzeichnung SCRAP) und ist gleichbedeutend mit defects.scrap_quantity. quantity.rework_quantity hat den gleichen Wert wie defects.rework_quantity. defects.inspected_scrap_quantity umfasst den gesamten Prüfausschuss (SCRAP + REWORK).

Status des Leistungsdokuments — Auswertung von Änderungen​

Ein Leistungsdokument enthält den aktuellen Status eines Arbeitsauftrags; bei jeder Statusänderung erhöht sich die Revisionsnummer.

FeldBedeutung
actual.statusGespeicherter Status WAIT·START·PAUSED·END·ABORTED — 11.1. Stornierung ist ABORTED + actual.abort_code=CANCELLED
actual.isa95_stateISA-95 Status des Arbeitsauftrags Ready·Running·Held·Completed·Aborted
performance_revisionAnzahl der Leistungsänderungen. Erhöht sich bei jeder Änderung um 1; der Feed setzt den Arbeitsauftrag dann ans Ende. 0 markiert einen noch nicht beendeten Arbeitsauftrag — nicht im Feed vorhanden, nur über /order/{id}/performance lesbar
quantity.correction_versionRevisionsnummer der Mengenkorrektur. Ohne Korrektur entspricht dies dem Messwert; erhöht sich bei jeder Korrektur — Historie siehe Revisionsverlauf in /order/{id}/quantity
changed_at · change_causeZeitpunkt der letzten Änderung und deren Ursache — ENDED·QUANTITY(Mengenkorrektur)·STOP_REASON·OEE_FINAL·DEFECT(Fehleraufzeichnung)·PROGRESS·BASELINE

Mengen werden ausschließlich als «Wert + Einheit» übertragen; nicht berechnete Felder werden als null statt 0 ausgegeben. Das MES ersetzt ein Dokument vollständig durch ein neues Dokument mit derselben order_id und einer höheren performance_revision.

B2MML-Zuordnungstabelle​

Ein Leistungsdokument entspricht der Job Response (Segment Response) von ISA-95 Part 4; die darin enthaltenen Mengen entsprechen der Quantity von Material Actual (Produced).

ISA-95 / B2MMLPlantPulse V5Bemerkung
QuantityValueType — QuantityString · DataType · UnitOfMeasureQuantity — quantity_string · data_type · unit_of_measure1:1. Die B2MML-Optionalfelder Key werden nicht verwendet
UnitOfMeasure WertUN/ECE Rec 20 CodeZulassungsliste siehe 11.5
ID des Job Orderexternal_idName des ausstellenden Systems ist external_system — beide bilden ein Paar
Quantity von Job Order · MaterialRequirementplanned_quantityISO 22400 POQ
Name des Job Orderorder_name
StartTime · EndTime des Job Orderplanned_start_timestamp · planned_end_timestampGeplante Zeit. Tatsächliche Zeit ist actual_start_timestamp · actual_end_timestamp
Job ResponseEin Leistungsdokument (/order/{id}/performance)
Quantity von MaterialActual(Produced)produced_quantityISO 22400 PQ
Davon Gutteilegood_quantityISO 22400 GQ
Davon Ausschussscrap_quantityISO 22400 SQ
Davon Nacharbeitdefects.rework_quantityISO 22400 RQ

11.7 Nutzungsszenarien​

Szenario — Automatische Erstellung von Arbeitsaufträgen via MES-Integration​

import java.text.SimpleDateFormat;
import java.util.Date;

SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
String today = df.format(new Date());

// 외부 MES 큐에서 받은 주문을 V5 Order로 변환
for (MesOrder mes : mesQueue) {
OrderRequestV5 req = new OrderRequestV5();
req.setOrder_id("ORDER_" + today + "_" + String.format("%03d", mes.seq));
req.setSite_id("SITE_DJ");
req.setAsset_id(mes.equipId);
req.setProduct_id(mes.productId);
// MES 수량을 그대로 — 단위 환산은 하지 않는다. 단위는 허용 목록(11.5) 안의 Rec 20 코드여야 한다
req.setPlanned_quantity(Quantity.of(mes.qty.toPlainString(), mes.unitCode));
req.setExternal_id(mes.mesOrderId);
req.setExternal_system("MES");
req.setPlanned_start_timestamp(mes.plannedStart);
req.setPlanned_end_timestamp(mes.plannedEnd);
client.order().create(req);
}

Szenario — Helper für sichere Zustandsübergänge​

public static boolean safeStart(APIClient_V5 client, String orderId) {
OrderResponseV5 o = client.order().get(orderId);
if (o == null) {
log.warn("작업지시 없음: " + orderId);
return false;
}
if (!"WAIT".equals(o.getStatus())) {
log.warn("WAIT 상태가 아님: " + o.getStatus());
return false;
}
return client.order().start(orderId);
}

Nächste Schritte​