Files
Sven CarstensenandClaude Fable 5 ac4266079a Task-Typnummern neu zugeordnet und benutzerdefinierte Typen via effectiveType unterstuetzt
- TourTask: base_type-Feld und effectiveType-Getter ergaenzt; benutzerdefinierte
  Typen (>= 1000) aus dem Workflow-Editor werden auf ihren Basis-Typ abgebildet,
  bei Altdaten ohne base_type wird der Basis-Typ aus den Eigenschaften abgeleitet
- TaskListPage: alle Typ-Switches auf effectiveType und die neuen Typnummern
  umgestellt (u.a. Ankunft 1->3, Fotos 3->4, Bestaetigung 6->12, Listen 12-14->13-15)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 14:29:22 +02:00

207 lines
5.8 KiB
Dart

class TourTask {
/// Untergrenze der im Workflow-Editor vergebenen Typnummern für
/// benutzerdefinierte Typen.
static const int customTypeStart = 1000;
late int sId;
late int type;
/// Typnummer des Basis-Typs bei benutzerdefinierten Typen
/// (>= [customTypeStart]) aus dem Workflow-Editor. `null` bei
/// Standard-Typen und bei Altdaten ohne Angabe.
int? baseType;
late String topic;
bool? opt;
bool? reenter;
int? min;
int? max;
int? maxLen;
bool? rt;
bool? track;
String? txt;
int? taskArrival;
int? taskFinWork;
List<TourEntry>? entries;
/// Auswahloptionen eines Status-Tasks (Typ 11).
List<TourChoice>? choices;
/// Eingabefelder einer Text-/Zahlen-Liste (Typ 13/14).
List<TourField>? fields;
TourTask();
/// Der für Darstellung und Validierung maßgebliche Typ: Standard-Typen
/// unverändert; benutzerdefinierte Typen (>= [customTypeStart]) werden auf
/// ihren Basis-Typ abgebildet. Fehlt {@code base_type} (Altdaten), wird der
/// Basis-Typ aus den typprägenden Eigenschaften abgeleitet.
int get effectiveType {
if (type < customTypeStart) {
return type;
}
if (baseType != null) {
return baseType!;
}
if (choices != null && choices!.isNotEmpty) return 11; // Statusauswahl
if (entries != null && entries!.isNotEmpty) return 15; // Checkbox-Liste
if (fields != null && fields!.isNotEmpty) return 13; // Text-Liste
if (min != null || max != null) return 4; // Fotos
if (maxLen != null) return 8; // Texteingabe (Bemerkung)
if (track != null) return 3; // Ankunft melden
return 12; // Bestätigung per Checkbox
}
factory TourTask.fromJson(Map<String, dynamic> json) {
final task = TourTask();
task.sId = json['s_id'] as int;
task.type = json['type'] as int;
task.baseType = json['base_type'] as int?;
task.topic = json['topic'] as String;
task.opt = json['opt'] as bool? ?? false;
task.reenter = json['reenter'] as bool? ?? false;
task.min = json['min'] as int?;
task.max = json['max'] as int?;
task.maxLen = json['max_len'] as int?;
task.rt = json['rt'] as bool?;
task.track = json['track'] as bool?;
task.txt = json['txt'] as String?;
task.taskArrival = json['task_arrival'] as int?;
task.taskFinWork = json['task_fin_work'] as int?;
task.entries = json['entries'] != null
? (json['entries'] as List<dynamic>)
.map((e) => TourEntry.fromJson(e as Map<String, dynamic>))
.toList()
: null;
task.choices = json['choices'] != null
? (json['choices'] as List<dynamic>)
.map((e) => TourChoice.fromJson(e as Map<String, dynamic>))
.toList()
: null;
task.fields = json['fields'] != null
? (json['fields'] as List<dynamic>)
.map((e) => TourField.fromJson(e as Map<String, dynamic>))
.toList()
: null;
return task;
}
Map<String, dynamic> toJson() {
return {
's_id': sId,
'type': type,
if (baseType != null) 'base_type': baseType,
'topic': topic,
'opt': opt,
'reenter': reenter,
'min': min,
'max': max,
'max_len': maxLen,
'rt': rt,
'track': track,
'txt': txt,
'task_arrival': taskArrival,
'task_fin_work': taskFinWork,
'entries': entries?.map((e) => e.toJson()).toList(),
'choices': choices?.map((e) => e.toJson()).toList(),
'fields': fields?.map((e) => e.toJson()).toList(),
};
}
}
class TourEntry {
late int code;
late String text;
late bool queryRemark;
/// Pflicht-Kennzeichen aus dem Workflow-Editor (Checkbox-Liste, Typ 15).
/// `null`, wenn das JSON keine Angabe enthält (Altdaten).
bool? required;
TourEntry();
factory TourEntry.fromJson(Map<String, dynamic> json) {
final entry = TourEntry();
entry.code = json['code'] as int;
entry.text = json['text'] as String;
entry.queryRemark = json['query_remark'] as bool? ?? false;
entry.required = json['required'] as bool?;
return entry;
}
Map<String, dynamic> toJson() {
return {
'code': code,
'text': text,
'query_remark': queryRemark,
if (required != null) 'required': required,
};
}
}
/// Eine Auswahloption eines Status-Tasks (Typ 11). Entspricht {@code Choice}
/// im App-JSON (txt, ret, term, quest, action, price).
class TourChoice {
late String txt;
late int ret;
bool? term;
String? quest;
String? action;
String? price;
TourChoice();
factory TourChoice.fromJson(Map<String, dynamic> json) {
final choice = TourChoice();
choice.txt = json['txt'] as String? ?? '';
choice.ret = json['ret'] as int? ?? 0;
choice.term = json['term'] as bool?;
choice.quest = json['quest'] as String?;
choice.action = json['action'] as String?;
choice.price = json['price'] as String?;
return choice;
}
Map<String, dynamic> toJson() {
return {
'txt': txt,
'ret': ret,
'term': term,
'quest': quest,
'action': action,
'price': price,
};
}
/// Ob nach Auswahl dieser Option eine zusätzliche Bemerkung erfragt wird.
bool get requiresRemark => (quest != null && quest!.trim().isNotEmpty);
}
/// Ein Eingabefeld einer Text-/Zahlen-Liste (Typ 13/14).
class TourField {
String? title;
String? placeholder;
/// Pflicht-Kennzeichen aus dem Workflow-Editor. `null`, wenn das JSON
/// keine Angabe enthält (Altdaten).
bool? required;
TourField();
factory TourField.fromJson(Map<String, dynamic> json) {
final field = TourField();
field.title = json['title'] as String?;
field.placeholder = json['placeholder'] as String?;
field.required = json['required'] as bool?;
return field;
}
Map<String, dynamic> toJson() {
return {
'title': title,
'placeholder': placeholder,
if (required != null) 'required': required,
};
}
}