parseInventoryWebhookEvent function

InventoryWebhookEvent? parseInventoryWebhookEvent(
  1. Object? rawBody
)

Liest eine Zustellung als typisiertes Ereignis. Vorher die Signatur pruefen (verifyInventoryWebhookSignature).

  • rawBody: der Rumpf als String oder als Bytes (List<int>).
  • Ein Ereignis, das diese Paketversion nicht kennt (eines einer spaeteren Stufe), ergibt null: mit 2xx antworten und uebergehen.
  • reservation.expired|released|redeemed tragen die Reservierung wie getReservation, mit dem Status nach dem Vorgang (seit 10.4).
  • variant_group.created|updated tragen die Gruppe wie getVariantGroup (seit 10.5); den Stand nur uebernehmen, wenn data.updatedAt neuer ist.
  • Ein Rumpf, der keine Huelle ist, oder eine Bruchzahl in einer Menge wirft KasseneckValidationError (kind: response).

Entdoppeln auf event.id; Stand statt Aenderung: einen gespeicherten Bestand nur ueberschreiben, wenn data.sequence groesser ist.

Implementation

InventoryWebhookEvent? parseInventoryWebhookEvent(Object? rawBody) {
  final String text;
  if (rawBody is String) {
    text = rawBody;
  } else if (rawBody is List<int>) {
    // Wie TextDecoder im JS-Zwilling: kaputte Folgen werden ersetzt, das JSON
    // entscheidet dann.
    text = utf8.decode(rawBody, allowMalformed: true);
  } else {
    throw _kaputt('Rumpf ist weder Text noch Bytes');
  }
  final Object? roh;
  try {
    roh = jsonDecode(text);
  } on FormatException {
    throw _kaputt('Rumpf ist kein JSON');
  }
  final e = objekt(roh);
  if (e == null) throw _kaputt('Rumpf ist kein Ereignis (kein Objekt)');
  final id = e['id'];
  final type = e['type'];
  final accountId = e['accountId'];
  if (id is! String || id.isEmpty || type is! String || type.isEmpty) throw _kaputt('Ereignis ohne id oder type');
  final createdAt = ganzzahlVon(e['createdAt']);
  if (createdAt == null) throw _kaputt('Ereignis ohne createdAt');
  if (accountId is! String || accountId.isEmpty) throw _kaputt('Ereignis ohne accountId');
  if (!inventoryWebhookEvents.contains(type)) return null;
  final data = e['data'];
  if (objekt(data) == null) throw _kaputt('Ereignis ohne data');
  const ort = Ort(_parseName, 'data');
  // Nur ein ausdrueckliches `true` ist eine Probe; im Zweifel der Ernstfall.
  final test = e['test'] == true;
  return switch (type) {
    'stock.changed' => InventoryStockChangedEvent(
        id: id, createdAt: createdAt, accountId: accountId, test: test, data: bestandGeaendert(ort, data)),
    'stock.below_minimum' => InventoryStockBelowMinimumEvent(
        id: id, createdAt: createdAt, accountId: accountId, test: test, data: unterMindestbestand(ort, data)),
    'reservation.expired' || 'reservation.released' || 'reservation.redeemed' => InventoryReservationEvent(
        id: id, type: type, createdAt: createdAt, accountId: accountId, test: test, data: reservierung(ort, data)),
    'variant_group.created' || 'variant_group.updated' => InventoryVariantGroupEvent(
        id: id, type: type, createdAt: createdAt, accountId: accountId, test: test, data: variantengruppe(ort, data)),
    _ => InventoryArticleEvent(
        id: id, type: type, createdAt: createdAt, accountId: accountId, test: test, data: artikel(ort, data)),
  };
}