saveDevice method
Einstellungen dieses Geräts schreiben (Recht layout). shortcuts nur
als ganze Karte aller bekannten Aktionen (posSettingsChanges liefert
sie bei jeder Tastenänderung); sie wird vorab auf Doppelbelegung geprüft.
Implementation
Future<PosDeviceSettings> saveDevice(Map<String, dynamic> patch) async {
const name = Aufrufe.setMyRegisterDeviceSettings;
if (deviceId.trim().isEmpty) {
throw const KasseneckValidationError(name, 'deviceId fehlt', 'request');
}
// Die optionale Lade getrennt: `null` heisst hier „Zuordnung entfernen“ und
// geht hinaus, waehrend `_pruefeTeil` Nullwerte als „nicht geaendert“ faellt.
final mitLade = patch.containsKey('drawerId');
final lade = patch['drawerId'];
if (mitLade && lade != null && !isPosOptionalId(lade)) {
throw const KasseneckValidationError(
name, 'device.drawerId: keine Kennung (1-64 Zeichen aus A-Z a-z 0-9 _ -, oder null zum Entfernen)', 'request');
}
final gesendet = mitLade && patch.length == 1
? <String, dynamic>{}
: _pruefeTeil(name, 'device', {...patch}..remove('drawerId'), const PosDeviceSettings().toJson(), posDeviceValues);
if (mitLade) gesendet['drawerId'] = lade;
if (gesendet.containsKey('shortcuts')) {
final karte = gesendet['shortcuts'];
if (karte is! Map) {
throw const KasseneckValidationError(name, 'device.shortcuts: keine Tastenkarte', 'request');
}
final tasten = <String, Object?>{};
for (final e in karte.entries) {
if (e.value == null) continue;
final aktion = e.key.toString();
if (!posShortcutActions.contains(aktion)) {
throw KasseneckValidationError(name, 'device.shortcuts.$aktion: unbekannte Aktion', 'request');
}
tasten[aktion] = e.value;
}
// Nur die ganze Karte: der Server prüft Doppelbelegungen nur in der
// gesendeten Karte, eine halbe (`{cash: ['Mod+K']}`) ließe eine
// Doppelbelegung mit einer gespeicherten Taste durch.
final fehlt = posShortcutActions.where((a) => !tasten.containsKey(a)).toList();
if (fehlt.isNotEmpty) {
throw KasseneckValidationError(
name,
'device.shortcuts: ganze Karte senden (posSettingsChanges), es fehlen ${fehlt.join(', ')}',
'request');
}
// Doppelbelegung in der ganzen Karte, also in der ganzen Belegung.
final konflikt = posShortcutConflict(tasten);
if (konflikt != null) {
throw KasseneckValidationError(
name,
'device.shortcuts.${konflikt.action}: Taste ${konflikt.key} schon belegt (${konflikt.heldBy})',
'request');
}
gesendet['shortcuts'] = tasten;
}
final daten = await transport.call(name, params: {'deviceId': deviceId, 'device': gesendet});
return PosDeviceSettings.fromJson(_stand(name, daten, 'device'));
}