add some new features
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../helper/input_validators.dart';
|
||||
import '../helper/abfall_berechnung.dart';
|
||||
import '../models/bauteil_model.dart';
|
||||
import '../models/kauf_filament_model.dart';
|
||||
import '../helper/storage_keys.dart';
|
||||
import '../models/abfall_model.dart';
|
||||
import '../services/get_storage_services.dart';
|
||||
|
||||
class AbfallController extends GetxController {
|
||||
final storage = Get.find<GetStorageService>();
|
||||
final abfaelle = <AbfallModel>[].obs;
|
||||
final datumZeit = DateTime.now().obs;
|
||||
final editingId = RxnString();
|
||||
final isSaving = false.obs;
|
||||
final message = RxnString();
|
||||
final hasError = false.obs;
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final scrollController = ScrollController();
|
||||
final kilopreisController = TextEditingController();
|
||||
final gewichtController = TextEditingController();
|
||||
final kostenController = TextEditingController();
|
||||
|
||||
double get summeAbfall =>
|
||||
abfaelle.fold(0, (sum, entry) => sum + entry.gewichtGramm);
|
||||
double get summeKosten =>
|
||||
abfaelle.fold(0, (sum, entry) => sum + entry.kosten);
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
loadAbfaelle();
|
||||
}
|
||||
|
||||
void loadAbfaelle() {
|
||||
final entries = storage
|
||||
.getModelList(StorageKeys.abfaelle)
|
||||
.map(AbfallModel.fromJson)
|
||||
.toList();
|
||||
final filamente = storage
|
||||
.getModelList(StorageKeys.filamente)
|
||||
.map(KaufFilamentModel.fromJson)
|
||||
.toList();
|
||||
for (final bauteil
|
||||
in storage
|
||||
.getModelList(StorageKeys.bauteile)
|
||||
.map(BauteilModel.fromJson)) {
|
||||
if (bauteil.abfallGramm <= 0) continue;
|
||||
final kosten =
|
||||
bauteil.abfallKosten ?? AbfallBerechnung.kosten(bauteil, filamente);
|
||||
entries.add(
|
||||
AbfallModel(
|
||||
abfallId: 'bauteil:${bauteil.bauteilId}',
|
||||
bauteilId: bauteil.bauteilId,
|
||||
bauteilName: bauteil.name,
|
||||
datumZeit: bauteil.erstelltAm,
|
||||
gewichtGramm: bauteil.abfallGramm,
|
||||
kosten: kosten ?? 0,
|
||||
kostenUnbekannt: kosten == null,
|
||||
kostenNachtraeglich: bauteil.abfallKosten == null && kosten != null,
|
||||
),
|
||||
);
|
||||
}
|
||||
entries.sort((a, b) => b.datumZeit.compareTo(a.datumZeit));
|
||||
abfaelle.assignAll(entries);
|
||||
}
|
||||
|
||||
void berechneKosten(String _) {
|
||||
final kilopreis = InputValidators.number(kilopreisController.text);
|
||||
final gewicht = InputValidators.number(gewichtController.text);
|
||||
if (kilopreis == null ||
|
||||
!kilopreis.isFinite ||
|
||||
kilopreis < 0 ||
|
||||
gewicht == null ||
|
||||
!gewicht.isFinite ||
|
||||
gewicht <= 0) {
|
||||
return;
|
||||
}
|
||||
final kosten = gewicht / 1000 * kilopreis;
|
||||
if (!kosten.isFinite) return;
|
||||
kostenController.text = kosten.toStringAsFixed(2).replaceAll('.', ',');
|
||||
}
|
||||
|
||||
void setDatum(DateTime date) {
|
||||
final current = datumZeit.value;
|
||||
datumZeit.value = DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
current.hour,
|
||||
current.minute,
|
||||
);
|
||||
}
|
||||
|
||||
void setUhrzeit(TimeOfDay time) {
|
||||
final current = datumZeit.value;
|
||||
datumZeit.value = DateTime(
|
||||
current.year,
|
||||
current.month,
|
||||
current.day,
|
||||
time.hour,
|
||||
time.minute,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _commit(List<AbfallModel> entries) async {
|
||||
await storage.saveModelList(
|
||||
StorageKeys.abfaelle,
|
||||
entries.map((entry) => entry.toJson()).toList(),
|
||||
);
|
||||
loadAbfaelle();
|
||||
}
|
||||
|
||||
Future<void> saveAbfall() async {
|
||||
if (isSaving.value) return;
|
||||
message.value = null;
|
||||
if (!(formKey.currentState?.validate() ?? false)) return;
|
||||
isSaving.value = true;
|
||||
try {
|
||||
final entries = storage
|
||||
.getModelList(StorageKeys.abfaelle)
|
||||
.map(AbfallModel.fromJson)
|
||||
.toList();
|
||||
final id = editingId.value;
|
||||
if (id != null && !entries.any((entry) => entry.abfallId == id)) {
|
||||
throw StateError('Eintrag nicht gefunden');
|
||||
}
|
||||
final entry = AbfallModel(
|
||||
abfallId: id ?? const Uuid().v4(),
|
||||
datumZeit: datumZeit.value,
|
||||
gewichtGramm: InputValidators.number(gewichtController.text)!,
|
||||
kosten: InputValidators.number(kostenController.text)!,
|
||||
);
|
||||
await _commit([
|
||||
...entries.where((item) => item.abfallId != entry.abfallId),
|
||||
entry,
|
||||
]);
|
||||
resetForm();
|
||||
hasError.value = false;
|
||||
message.value = 'Abfall gespeichert.';
|
||||
} catch (_) {
|
||||
hasError.value = true;
|
||||
message.value = 'Speichern fehlgeschlagen. Bitte erneut versuchen.';
|
||||
} finally {
|
||||
isSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> editAbfall(AbfallModel entry) async {
|
||||
if (isSaving.value || entry.ausBauteil) return;
|
||||
message.value = null;
|
||||
editingId.value = entry.abfallId;
|
||||
datumZeit.value = entry.datumZeit;
|
||||
gewichtController.text = entry.gewichtGramm.toString().replaceAll('.', ',');
|
||||
kostenController.text = entry.kosten.toString().replaceAll('.', ',');
|
||||
if (scrollController.hasClients) {
|
||||
await scrollController.animateTo(
|
||||
0,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteAbfall(String id) async {
|
||||
if (isSaving.value ||
|
||||
abfaelle.any((item) => item.abfallId == id && item.ausBauteil)) {
|
||||
return;
|
||||
}
|
||||
isSaving.value = true;
|
||||
try {
|
||||
final entries = storage
|
||||
.getModelList(StorageKeys.abfaelle)
|
||||
.map(AbfallModel.fromJson)
|
||||
.where((entry) => entry.abfallId != id)
|
||||
.toList();
|
||||
await _commit(entries);
|
||||
if (editingId.value == id) resetForm();
|
||||
hasError.value = false;
|
||||
message.value = 'Abfall gelöscht.';
|
||||
} catch (_) {
|
||||
hasError.value = true;
|
||||
message.value = 'Löschen fehlgeschlagen. Bitte erneut versuchen.';
|
||||
} finally {
|
||||
isSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void resetForm() {
|
||||
final kilopreis = kilopreisController.text;
|
||||
formKey.currentState?.reset();
|
||||
kilopreisController.text = kilopreis;
|
||||
editingId.value = null;
|
||||
datumZeit.value = DateTime.now();
|
||||
gewichtController.clear();
|
||||
kostenController.clear();
|
||||
message.value = null;
|
||||
hasError.value = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
scrollController.dispose();
|
||||
kilopreisController.dispose();
|
||||
gewichtController.dispose();
|
||||
kostenController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../helper/storage_keys.dart';
|
||||
import '../models/bauteil_auswertung_model.dart';
|
||||
import '../models/bauteil_model.dart';
|
||||
import '../services/get_storage_services.dart';
|
||||
|
||||
class BauteilAuswertungController extends GetxController {
|
||||
final storage = Get.find<GetStorageService>();
|
||||
final bauteile = <BauteilModel>[].obs;
|
||||
final zeitraum = BauteilZeitraum.monat.obs;
|
||||
final scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
final entries = storage
|
||||
.getModelList(StorageKeys.bauteile)
|
||||
.map(BauteilModel.fromJson)
|
||||
.toList();
|
||||
entries.sort((a, b) {
|
||||
final datum = b.erstelltAm.compareTo(a.erstelltAm);
|
||||
return datum == 0 ? a.bauteilId.compareTo(b.bauteilId) : datum;
|
||||
});
|
||||
bauteile.assignAll(entries);
|
||||
}
|
||||
|
||||
double get gesamtsumme => BauteilAuswertungsGruppe.summeFuer(bauteile);
|
||||
int get ohnePreis => bauteile
|
||||
.where((item) => !BauteilAuswertungsGruppe.preisBekannt(item))
|
||||
.length;
|
||||
|
||||
List<BauteilAuswertungsGruppe> get gruppen {
|
||||
final auswahl = zeitraum.value;
|
||||
final gruppiert = <DateTime, List<BauteilModel>>{};
|
||||
for (final bauteil in bauteile) {
|
||||
final datum = bauteil.erstelltAm.toLocal();
|
||||
final beginn = switch (auswahl) {
|
||||
BauteilZeitraum.jahr => DateTime(datum.year),
|
||||
BauteilZeitraum.monat => DateTime(datum.year, datum.month),
|
||||
BauteilZeitraum.tag => DateTime(datum.year, datum.month, datum.day),
|
||||
};
|
||||
gruppiert.putIfAbsent(beginn, () => []).add(bauteil);
|
||||
}
|
||||
final zeitpunkte = gruppiert.keys.toList()..sort((a, b) => b.compareTo(a));
|
||||
return zeitpunkte
|
||||
.map(
|
||||
(beginn) => BauteilAuswertungsGruppe(
|
||||
beginn: beginn,
|
||||
bauteile: List.unmodifiable(gruppiert[beginn]!),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
String gruppenTitel(DateTime beginn) => switch (zeitraum.value) {
|
||||
BauteilZeitraum.jahr => 'Jahr ${beginn.year}',
|
||||
BauteilZeitraum.monat => 'Monat ${DateFormat('MM.yyyy').format(beginn)}',
|
||||
BauteilZeitraum.tag => DateFormat('dd.MM.yyyy').format(beginn),
|
||||
};
|
||||
|
||||
void waehleZeitraum(BauteilZeitraum auswahl) {
|
||||
if (auswahl == zeitraum.value) return;
|
||||
if (scrollController.hasClients) scrollController.jumpTo(0);
|
||||
zeitraum.value = auswahl;
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
scrollController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import 'package:get/get.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../helper/display_formats.dart';
|
||||
import '../helper/bauteil_preis_berechnung.dart';
|
||||
import '../helper/filament_bestand.dart';
|
||||
import '../helper/input_validators.dart';
|
||||
import '../helper/storage_keys.dart';
|
||||
@@ -15,12 +16,14 @@ import '../models/kauf_filament_model.dart';
|
||||
import '../services/bauteil_photo_service.dart';
|
||||
import '../services/get_storage_services.dart';
|
||||
import 'home_controller.dart';
|
||||
import 'abfall_controller.dart';
|
||||
|
||||
class BauteilController extends GetxController {
|
||||
BauteilController({BauteilPhotoService? photoService})
|
||||
: photoService = photoService ?? BauteilPhotoService();
|
||||
|
||||
static const storageKey = StorageKeys.bauteile;
|
||||
static const double standardAufschlagProzent = 50;
|
||||
final storage = Get.find<GetStorageService>();
|
||||
final BauteilPhotoService photoService;
|
||||
final formKey = GlobalKey<FormState>();
|
||||
@@ -32,6 +35,12 @@ class BauteilController extends GetxController {
|
||||
final gewichtController = TextEditingController();
|
||||
final abfallController = TextEditingController(text: '0');
|
||||
final gesamtpreisController = TextEditingController();
|
||||
final aufschlagController = TextEditingController(
|
||||
text: standardAufschlagProzent.toStringAsFixed(0),
|
||||
);
|
||||
final preisDetails = Rxn<BauteilPreis>();
|
||||
bool _preisPausiert = false;
|
||||
BauteilModel? _bearbeitetesBauteil;
|
||||
final _verbrauchControllers = <String, TextEditingController>{};
|
||||
final filamente = <KaufFilamentModel>[].obs;
|
||||
final profile = <AnwendungModel>[].obs;
|
||||
@@ -60,13 +69,20 @@ class BauteilController extends GetxController {
|
||||
);
|
||||
bauteile.assignAll(_loadBauteile());
|
||||
bauteile.sort((a, b) => b.erstelltAm.compareTo(a.erstelltAm));
|
||||
gewichtController.addListener(berechnePreis);
|
||||
abfallController.addListener(berechnePreis);
|
||||
aufschlagController.addListener(berechnePreis);
|
||||
}
|
||||
|
||||
List<BauteilModel> _loadBauteile() =>
|
||||
storage.getModelList(storageKey).map(BauteilModel.fromJson).toList();
|
||||
|
||||
TextEditingController verbrauchController(String id) =>
|
||||
_verbrauchControllers.putIfAbsent(id, () => TextEditingController());
|
||||
_verbrauchControllers.putIfAbsent(id, () {
|
||||
final field = TextEditingController();
|
||||
field.addListener(berechnePreis);
|
||||
return field;
|
||||
});
|
||||
|
||||
List<AnwendungModel> profilesFor(String filamentId) =>
|
||||
profile.where((item) => item.filamentId == filamentId).toList()
|
||||
@@ -78,6 +94,15 @@ class BauteilController extends GetxController {
|
||||
return '${item.marke} · ${item.material} · ${item.farbe}';
|
||||
}
|
||||
|
||||
double? restgewichtGramm(String id) {
|
||||
final startgewicht = filamente
|
||||
.firstWhereOrNull((item) => item.filamentId == id)
|
||||
?.gewichtGramm;
|
||||
if (startgewicht == null) return null;
|
||||
final verbrauch = FilamentBestand.verbrauch(bauteile);
|
||||
return startgewicht - (verbrauch[id] ?? 0);
|
||||
}
|
||||
|
||||
double? verfuegbarGramm(String id) {
|
||||
final start = filamente
|
||||
.firstWhereOrNull((item) => item.filamentId == id)
|
||||
@@ -97,6 +122,42 @@ class BauteilController extends GetxController {
|
||||
} else {
|
||||
selectedFilamente.remove(id);
|
||||
}
|
||||
berechnePreis();
|
||||
}
|
||||
|
||||
String? pruefeFilamentVorrat() {
|
||||
if (selectedFilamente.isEmpty) return null;
|
||||
final gewicht = InputValidators.number(gewichtController.text);
|
||||
final abfall = abfallController.text.trim().isEmpty
|
||||
? 0.0
|
||||
: InputValidators.number(abfallController.text);
|
||||
if (gewicht == null ||
|
||||
!gewicht.isFinite ||
|
||||
gewicht <= 0 ||
|
||||
abfall == null ||
|
||||
!abfall.isFinite ||
|
||||
abfall < 0) {
|
||||
return null;
|
||||
}
|
||||
final bedarf = gewicht + abfall;
|
||||
if (!bedarf.isFinite) return null;
|
||||
var verfuegbar = 0.0;
|
||||
for (final id in selectedFilamente.keys) {
|
||||
final rest = verfuegbarGramm(id);
|
||||
if (rest == null || !rest.isFinite) {
|
||||
return 'Die Restmenge einer ausgewählten Rolle ist unbekannt. Bitte das Startgewicht und den bisherigen Verbrauch prüfen.';
|
||||
}
|
||||
verfuegbar += rest > 0 ? rest : 0;
|
||||
}
|
||||
if (bedarf - verfuegbar <= 0.000001) return null;
|
||||
final rollen = selectedFilamente.length == 1
|
||||
? 'der ausgewählten Rolle'
|
||||
: 'der ausgewählten Rollen zusammen';
|
||||
return 'Die Restmenge $rollen reicht nicht aus.\n\n'
|
||||
'Benötigt (inklusive Abfall): ${DisplayFormats.number(bedarf)} g\n'
|
||||
'Verfügbar: ${DisplayFormats.number(verfuegbar)} g\n'
|
||||
'Es fehlen: ${DisplayFormats.number(bedarf - verfuegbar)} g\n\n'
|
||||
'Füge eine weitere Rolle hinzu oder wähle eine andere Rolle aus.';
|
||||
}
|
||||
|
||||
void selectProfile(String filamentId, String? anwendungId) {
|
||||
@@ -190,8 +251,60 @@ class BauteilController extends GetxController {
|
||||
if (Get.isRegistered<HomeController>()) {
|
||||
Get.find<HomeController>().loadVerbrauch();
|
||||
}
|
||||
if (Get.isRegistered<AbfallController>()) {
|
||||
Get.find<AbfallController>().loadAbfaelle();
|
||||
}
|
||||
}
|
||||
|
||||
void berechnePreis() {
|
||||
if (_preisPausiert || _closed) return;
|
||||
final gewicht = InputValidators.number(gewichtController.text);
|
||||
final abfall = InputValidators.number(abfallController.text);
|
||||
final aufschlag = InputValidators.number(aufschlagController.text);
|
||||
BauteilPreis? preis;
|
||||
if (gewicht != null && abfall != null && aufschlag != null) {
|
||||
final entry = BauteilModel(
|
||||
bauteilId: editingId.value ?? '',
|
||||
erstelltAm: DateTime.now(),
|
||||
name: '',
|
||||
verwendung: '',
|
||||
druckdauerMinuten: 1,
|
||||
gewichtGramm: gewicht,
|
||||
abfallGramm: abfall,
|
||||
filamente: selectedFilamente.keys
|
||||
.map(
|
||||
(id) => BauteilFilamentModel(
|
||||
filamentId: id,
|
||||
verbrauchGramm:
|
||||
InputValidators.number(_verbrauchControllers[id]?.text) ??
|
||||
0,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
preis = BauteilPreisBerechnung.berechne(
|
||||
entry,
|
||||
filamente,
|
||||
aufschlag,
|
||||
previous: _bearbeitetesBauteil,
|
||||
);
|
||||
}
|
||||
preisDetails.value = preis;
|
||||
gesamtpreisController.text = preis == null
|
||||
? ''
|
||||
: preis.gesamtpreis.toStringAsFixed(2).replaceAll('.', ',');
|
||||
}
|
||||
|
||||
BauteilPreis? _kalkulation(
|
||||
BauteilModel entry,
|
||||
double aufschlag, {
|
||||
BauteilModel? previous,
|
||||
}) => BauteilPreisBerechnung.berechne(
|
||||
entry,
|
||||
storage.getModelList(StorageKeys.filamente).map(KaufFilamentModel.fromJson),
|
||||
aufschlag,
|
||||
previous: previous,
|
||||
);
|
||||
Future<void> saveBauteil() async {
|
||||
if (isSaving.value || isPickingPhoto.value) return;
|
||||
message.value = null;
|
||||
@@ -225,7 +338,7 @@ class BauteilController extends GetxController {
|
||||
druckdauerMinuten: duration,
|
||||
gewichtGramm: InputValidators.number(gewichtController.text)!,
|
||||
abfallGramm: InputValidators.number(abfallController.text)!,
|
||||
gesamtpreis: InputValidators.number(gesamtpreisController.text),
|
||||
aufschlagProzent: InputValidators.number(aufschlagController.text),
|
||||
fotoBase64: foto.value == null ? null : base64Encode(foto.value!),
|
||||
filamente: selectedFilamente.entries
|
||||
.map(
|
||||
@@ -246,13 +359,32 @@ class BauteilController extends GetxController {
|
||||
_error(error);
|
||||
return;
|
||||
}
|
||||
final preis = _kalkulation(
|
||||
entry,
|
||||
entry.aufschlagProzent!,
|
||||
previous: previous,
|
||||
);
|
||||
if (preis == null) {
|
||||
_error(
|
||||
'Preis nicht berechenbar. Bitte Verbrauch, Einkaufspreis und Startgewicht der Rollen sowie den Aufschlag prüfen.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final gespeichert = entry.copyWith(
|
||||
bauteilId: entry.bauteilId,
|
||||
erstelltAm: entry.erstelltAm,
|
||||
abfallKosten: preis.abfallKosten,
|
||||
materialKosten: preis.materialKosten,
|
||||
aufschlagProzent: preis.aufschlagProzent,
|
||||
gesamtpreis: preis.gesamtpreis,
|
||||
);
|
||||
await _commit([
|
||||
...existing.where((item) => item.bauteilId != entry.bauteilId),
|
||||
entry,
|
||||
gespeichert,
|
||||
]);
|
||||
resetForm();
|
||||
hasError.value = false;
|
||||
message.value = 'Bauteil und Filamentverbrauch gespeichert.';
|
||||
message.value = 'Bauteil, Filamentverbrauch und Abfall gespeichert.';
|
||||
} catch (_) {
|
||||
_error('Speichern fehlgeschlagen. Bitte erneut versuchen.');
|
||||
} finally {
|
||||
@@ -263,6 +395,8 @@ class BauteilController extends GetxController {
|
||||
Future<void> editBauteil(BauteilModel entry) async {
|
||||
if (isSaving.value || isPickingPhoto.value) return;
|
||||
resetForm();
|
||||
_preisPausiert = true;
|
||||
_bearbeitetesBauteil = entry;
|
||||
message.value = null;
|
||||
nameController.text = entry.name;
|
||||
verwendungController.text = entry.verwendung;
|
||||
@@ -279,7 +413,13 @@ class BauteilController extends GetxController {
|
||||
: '';
|
||||
selectedFilamente[item.filamentId] = item.anwendungId;
|
||||
}
|
||||
aufschlagController.text =
|
||||
(entry.aufschlagProzent ?? standardAufschlagProzent)
|
||||
.toString()
|
||||
.replaceAll('.', ',');
|
||||
editingId.value = entry.bauteilId;
|
||||
_preisPausiert = false;
|
||||
berechnePreis();
|
||||
await scrollToForm();
|
||||
}
|
||||
|
||||
@@ -298,7 +438,27 @@ class BauteilController extends GetxController {
|
||||
await scrollToForm();
|
||||
return;
|
||||
}
|
||||
await _commit([...existing, copy]);
|
||||
final preis = _kalkulation(
|
||||
copy,
|
||||
copy.aufschlagProzent ?? standardAufschlagProzent,
|
||||
);
|
||||
if (preis == null) {
|
||||
_error(
|
||||
'Abfallkosten nicht berechenbar. Bitte Einkaufspreis und Startgewicht der verwendeten Rollen prüfen.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
await _commit([
|
||||
...existing,
|
||||
copy.copyWith(
|
||||
bauteilId: copy.bauteilId,
|
||||
erstelltAm: copy.erstelltAm,
|
||||
abfallKosten: preis.abfallKosten,
|
||||
materialKosten: preis.materialKosten,
|
||||
aufschlagProzent: preis.aufschlagProzent,
|
||||
gesamtpreis: preis.gesamtpreis,
|
||||
),
|
||||
]);
|
||||
hasError.value = false;
|
||||
message.value = 'Bauteil dupliziert und Verbrauch erneut gebucht.';
|
||||
} catch (_) {
|
||||
@@ -338,6 +498,8 @@ class BauteilController extends GetxController {
|
||||
}
|
||||
|
||||
void resetForm() {
|
||||
_preisPausiert = true;
|
||||
_bearbeitetesBauteil = null;
|
||||
formKey.currentState?.reset();
|
||||
editingId.value = null;
|
||||
nameController.clear();
|
||||
@@ -352,6 +514,9 @@ class BauteilController extends GetxController {
|
||||
controller.clear();
|
||||
}
|
||||
foto.value = null;
|
||||
aufschlagController.text = standardAufschlagProzent.toStringAsFixed(0);
|
||||
preisDetails.value = null;
|
||||
_preisPausiert = false;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -365,6 +530,7 @@ class BauteilController extends GetxController {
|
||||
gewichtController.dispose();
|
||||
abfallController.dispose();
|
||||
gesamtpreisController.dispose();
|
||||
aufschlagController.dispose();
|
||||
for (final controller in _verbrauchControllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import '../models/backup_model.dart';
|
||||
import '../services/backup_file_service.dart';
|
||||
import '../services/get_storage_services.dart';
|
||||
import 'home_controller.dart';
|
||||
import 'abfall_controller.dart';
|
||||
|
||||
class ExportController extends GetxController {
|
||||
ExportController({BackupFileService? fileService})
|
||||
@@ -76,6 +77,9 @@ class ExportController extends GetxController {
|
||||
home.loadMaterialien();
|
||||
home.resetForm();
|
||||
}
|
||||
if (Get.isRegistered<AbfallController>()) {
|
||||
Get.find<AbfallController>().loadAbfaelle();
|
||||
}
|
||||
pendingBackup.value = null;
|
||||
hasError.value = false;
|
||||
message.value = 'Alle Daten wurden importiert.';
|
||||
|
||||
@@ -54,6 +54,7 @@ class HomeController extends GetxController {
|
||||
final preisController = TextEditingController();
|
||||
final markeController = TextEditingController();
|
||||
final gewichtController = TextEditingController();
|
||||
final bruttoGewichtController = TextEditingController();
|
||||
final materialController = TextEditingController(text: 'PLA');
|
||||
|
||||
final kaufdatum = DateTime.now().obs;
|
||||
@@ -163,6 +164,18 @@ class HomeController extends GetxController {
|
||||
);
|
||||
}
|
||||
|
||||
String? validateBruttogewicht(String? value) {
|
||||
if ((value ?? '').trim().isEmpty) return null;
|
||||
final error = InputValidators.positive(value);
|
||||
if (error != null) return error;
|
||||
final brutto = InputValidators.number(value)!;
|
||||
final netto = InputValidators.number(gewichtController.text);
|
||||
if (netto != null && netto.isFinite && brutto < netto) {
|
||||
return 'Bruttogewicht muss mindestens dem Nettogewicht entsprechen.';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> saveFilament() async {
|
||||
if (!formKey.currentState!.validate()) return;
|
||||
|
||||
@@ -186,7 +199,7 @@ class HomeController extends GetxController {
|
||||
gewicht < bereitsVerbraucht) {
|
||||
Get.snackbar(
|
||||
'Ungültiges Gewicht',
|
||||
'Das Startgewicht muss positiv sein und mindestens dem bereits gebuchten Verbrauch entsprechen.',
|
||||
'Das Nettostartgewicht muss positiv sein und mindestens dem bereits gebuchten Verbrauch entsprechen.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -202,6 +215,7 @@ class HomeController extends GetxController {
|
||||
preis: preis,
|
||||
farbe: farbeController.text.trim(),
|
||||
gewicht: gewicht.toString(),
|
||||
bruttoGewichtGramm: InputValidators.number(bruttoGewichtController.text),
|
||||
);
|
||||
|
||||
if (editingId.value == null) {
|
||||
@@ -231,6 +245,8 @@ class HomeController extends GetxController {
|
||||
haendlerController.text = filament.haendler;
|
||||
selectMaterial(filament.material);
|
||||
preisController.text = filament.preis.toStringAsFixed(2);
|
||||
bruttoGewichtController.text =
|
||||
filament.bruttoGewichtGramm?.toString().replaceAll('.', ',') ?? '';
|
||||
farbeController.text = filament.farbe;
|
||||
gewichtController.text = filament.gewichtGramm == null
|
||||
? filament.gewicht
|
||||
@@ -272,6 +288,7 @@ class HomeController extends GetxController {
|
||||
selectMaterial(materialien.firstOrNull ?? '');
|
||||
materialMessage.value = null;
|
||||
gewichtController.clear();
|
||||
bruttoGewichtController.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -283,6 +300,7 @@ class HomeController extends GetxController {
|
||||
farbeController.dispose();
|
||||
preisController.dispose();
|
||||
gewichtController.dispose();
|
||||
bruttoGewichtController.dispose();
|
||||
materialController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user