call method
Einen Endpunkt rufen. params kommt zur Kasse dazu; null-Werte fallen
weg, damit das Backend „nicht gesetzt" nicht als ausdrückliche Angabe
missversteht.
timeout überschreibt die Vorgabe für diesen einen Aufruf – der Abschluss
eines Belegs darf länger warten als eine Belegliste.
Fehler tragen outcome: bei ErrorOutcome.unknown nie wiederholen,
sondern nachlesen (siehe v3Post).
Implementation
Future<Map<String, dynamic>> call(
String name, {
Map<String, dynamic> params = const {},
Duration? timeout,
}) async {
// Beides frisch — siehe Klassenkommentar.
final token = await idToken();
final sitzung = await sessionId();
if (token == null || token.isEmpty) {
throw KasseneckValidationError(name, 'idToken lieferte kein Token', 'request');
}
if (sitzung == null || sitzung.isEmpty) {
throw KasseneckValidationError(name, 'sessionId lieferte keine Sitzung', 'request');
}
final nutzlast = <String, dynamic>{'cashregisterId': cashregisterId};
params.forEach((schluessel, wert) {
if (wert != null) nutzlast[schluessel] = wert;
});
// Ausserhalb des Sendens: ein nicht serialisierbarer Parameter ist ein
// Programmierfehler und keine Netzstoerung. Sonst haette ihn der
// Sammelfang als `network` gemeldet — ein Fehler, der nie am Netz lag,
// saehe aus wie einer, nach dem ein Beleg entstanden sein koennte.
final String rumpf = jsonEncode({'params': nutzlast});
// Zeitlimit getrennt vom Netzfehler: die Anfrage war draussen, ueber
// `createReceipt` kann der Beleg laengst signiert sein. Nur der Typ der
// Ursache, nie die Meldung: die kann eine Adresse tragen.
final antwort = await v3Post(
_http,
functionName: name,
basis: baseUrl,
name: name,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
'register-session': sitzung,
},
kasseneck: _kopf,
body: rumpf,
timeout: timeout ?? _timeout,
);
final huelle = readEnvelope(name, antwort);
if (huelle['status'] == 'success') {
// Fehlendes `data` ist erlaubt — nicht jeder Aufruf hat eine Nutzlast.
// Ein `data`, das da ist und **kein Objekt** ist (Array, Zahl, Text), ist
// dagegen kaputt und darf nicht als leeres Objekt durchgehen: aus dem
// wurde weiter oben ein voller Standardsatz Einstellungen, und der
// Bildschirm meldete „der Betrieb hat nichts eingestellt". Dieselbe
// Grenze wie bei den Listen: leer ist etwas anderes als kaputt.
return envelopeData(name, huelle, antwort.statusCode);
}
throw envelopeError(name, huelle);
}