import 'package:hl_lieferservice/dto/article.dart'; import 'component.dart'; class Article { Article({ required this.name, required this.articleNumber, required this.amount, required this.internalId, required this.price, required this.tax, required this.scannable, required this.scannedAmount, required this.scannedRemovedAmount, required this.isParent, this.components = const [], this.scannedDate, this.removeNoteId, this.warehouseNr, this.warehouseName, }); final String name; final String articleNumber; final int internalId; final bool isParent; final List components; final String? warehouseNr; final String? warehouseName; int amount; double price; double tax; bool scannable; DateTime? scannedDate; String? removeNoteId; int scannedAmount; int scannedRemovedAmount; double getGrossPrice() { return price * amount * ((100 + tax) / 100); } double getGrossPriceScanned() { return price * scannedAmount * ((100 + tax) / 100); } /// Whether this article is fully scanned. /// /// For parent articles (Stückliste): delegates to components — all must be /// individually scanned. For regular articles: the classic amount check. bool get isFullyScanned { if (isParent && components.isNotEmpty) { return components.every((c) => c.isFullyScanned); } return scannedAmount + scannedRemovedAmount >= amount; } /// Find a component by its article number, or `null` if none matches. Component? findComponent(String articleNumber) { for (final c in components) { if (c.articleNumber == articleNumber) return c; } return null; } /// Whether this article *or* any of its components carries [articleNumber]. bool hasArticleNumber(String articleNumber) { if (this.articleNumber == articleNumber) return true; return components.any((c) => c.articleNumber == articleNumber); } bool unscanned() { if (isParent && components.isNotEmpty) { return components.every((c) => c.scannedAmount == 0); } return scannedAmount == 0; } int getScannedAmount() { return scannedAmount; } factory Article.fromDTO(ArticleDTO dto) { return Article( name: dto.name, scannedAmount: int.parse( dto.scannedAmount != "" ? dto.scannedAmount : "0", ), scannedRemovedAmount: int.tryParse(dto.scannedRemovedAmount) ?? 0, removeNoteId: dto.removeNoteId, internalId: int.parse(dto.internalId), articleNumber: dto.articleNr, amount: int.parse(dto.quantity == "" ? "0" : dto.quantity), price: double.parse(dto.price == "" ? "0.0" : dto.price), scannable: dto.scannable, tax: double.parse(dto.taxRate == "" ? "19" : dto.taxRate), isParent: dto.isParent, components: dto.components?.map(Component.fromDTO).toList() ?? [], warehouseNr: dto.warehouseNr?.isEmpty ?? true ? null : dto.warehouseNr, warehouseName: dto.warehouseName?.isEmpty ?? true ? null : dto.warehouseName, ); } }