From 8e0166c68a90ce9fbd4cda33f300be31aa1a5792 Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Mon, 11 May 2026 21:18:06 +0200 Subject: [PATCH] feat: Improve category ID handling with dynamic parsing in inventory screens --- db/seeds/seed_all.sql | 16 +++++++++++++++- .../presentation/create_inventory_screen.dart | 13 +++++++------ .../presentation/inventory_category_helpers.dart | 12 ++++++++++-- .../presentation/inventory_edit_screen.dart | 13 +++++++------ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/db/seeds/seed_all.sql b/db/seeds/seed_all.sql index 0257882e..b6ebdb66 100644 --- a/db/seeds/seed_all.sql +++ b/db/seeds/seed_all.sql @@ -455,7 +455,21 @@ INSERT INTO `Category` (`name`, `parentId`) INSERT INTO `Category` (`name`, `parentId`) SELECT 'Kryddor', c2.id FROM `Category` c1 JOIN `Category` c2 ON c2.parentId = c1.id AND c2.name = 'Kryddor & smaksättare' - WHERE c1.name = 'Skafferi' AND c1.parentId IS NULL; + WHERE c1.name = 'Skafferi' + AND c1.parentId IS NULL + AND NOT EXISTS ( + SELECT 1 FROM `Category` existing + WHERE existing.parentId = c2.id AND existing.name = 'Kryddor' + ); +INSERT INTO `Category` (`name`, `parentId`) + SELECT 'Salt', c2.id FROM `Category` c1 + JOIN `Category` c2 ON c2.parentId = c1.id AND c2.name = 'Kryddor & smaksättare' + WHERE c1.name = 'Skafferi' + AND c1.parentId IS NULL + AND NOT EXISTS ( + SELECT 1 FROM `Category` existing + WHERE existing.parentId = c2.id AND existing.name = 'Salt' + ); INSERT INTO `Category` (`name`, `parentId`) SELECT 'Övriga smaksättare', c2.id FROM `Category` c1 JOIN `Category` c2 ON c2.parentId = c1.id AND c2.name = 'Kryddor & smaksättare' diff --git a/flutter/lib/features/inventory/presentation/create_inventory_screen.dart b/flutter/lib/features/inventory/presentation/create_inventory_screen.dart index e2690d9e..88e14b87 100644 --- a/flutter/lib/features/inventory/presentation/create_inventory_screen.dart +++ b/flutter/lib/features/inventory/presentation/create_inventory_screen.dart @@ -130,7 +130,7 @@ class _CreateInventoryScreenState Map? _selectedProduct() { if (_selectedProductId == null) return null; for (final product in _products) { - if ((product['id'] as num).toInt() == _selectedProductId) { + if (tryParseDynamicInt(product['id']) == _selectedProductId) { return product; } } @@ -150,7 +150,7 @@ class _CreateInventoryScreenState : _products .where( (p) => productInSelectedBranch( - productCategoryId: (p['categoryId'] as num?)?.toInt(), + productCategoryId: tryParseDynamicInt(p['categoryId']), selectedCategoryIds: selectedCategoryIds, ), ) @@ -165,11 +165,12 @@ class _CreateInventoryScreenState final sorted = _sortedProductsCache.sort(withSelected); return sorted + .where((p) => tryParseDynamicInt(p['id']) != null) .map( (p) => ( - id: (p['id'] as num).toInt(), + id: tryParseDynamicInt(p['id'])!, name: (p['canonicalName'] ?? p['name'] ?? '').toString(), - categoryId: (p['categoryId'] as num?)?.toInt(), + categoryId: tryParseDynamicInt(p['categoryId']), ), ) .toList(); @@ -186,7 +187,7 @@ class _CreateInventoryScreenState _selectedCategoryId = selected.id; final selectedCategoryIds = _selectedCategoryBranchIds(); final current = _selectedProduct(); - final currentCategoryId = (current?['categoryId'] as num?)?.toInt(); + final currentCategoryId = tryParseDynamicInt(current?['categoryId']); if (!productInSelectedBranch( productCategoryId: currentCategoryId, selectedCategoryIds: selectedCategoryIds, @@ -328,7 +329,7 @@ class _CreateInventoryScreenState _selectedCategoryId = int.tryParse(value); final selectedCategoryIds = _selectedCategoryBranchIds(); final current = _selectedProduct(); - final currentCategoryId = (current?['categoryId'] as num?)?.toInt(); + final currentCategoryId = tryParseDynamicInt(current?['categoryId']); if (!productInSelectedBranch( productCategoryId: currentCategoryId, selectedCategoryIds: selectedCategoryIds, diff --git a/flutter/lib/features/inventory/presentation/inventory_category_helpers.dart b/flutter/lib/features/inventory/presentation/inventory_category_helpers.dart index b4ec9f16..7163f00d 100644 --- a/flutter/lib/features/inventory/presentation/inventory_category_helpers.dart +++ b/flutter/lib/features/inventory/presentation/inventory_category_helpers.dart @@ -1,5 +1,13 @@ import '../../admin/domain/admin_category_node.dart'; +int? tryParseDynamicInt(dynamic value) { + if (value == null) return null; + if (value is int) return value; + if (value is num) return value.toInt(); + if (value is String) return int.tryParse(value.trim()); + return null; +} + class InventoryCategoryBranchIndex { final Map> _descendantsById; @@ -62,8 +70,8 @@ class InventorySortedProductsCache { String _buildKey(List> products) { final b = StringBuffer('${products.length}|'); for (final p in products) { - final id = (p['id'] as num?)?.toInt() ?? -1; - final categoryId = (p['categoryId'] as num?)?.toInt() ?? -1; + final id = tryParseDynamicInt(p['id']) ?? -1; + final categoryId = tryParseDynamicInt(p['categoryId']) ?? -1; final name = (p['canonicalName'] ?? p['name'] ?? '').toString(); b ..write(id) diff --git a/flutter/lib/features/inventory/presentation/inventory_edit_screen.dart b/flutter/lib/features/inventory/presentation/inventory_edit_screen.dart index b7e8c9e8..1243b44b 100644 --- a/flutter/lib/features/inventory/presentation/inventory_edit_screen.dart +++ b/flutter/lib/features/inventory/presentation/inventory_edit_screen.dart @@ -152,7 +152,7 @@ class _InventoryEditScreenState extends ConsumerState { Map? _selectedProduct() { if (_selectedProductId == null) return null; for (final product in _products) { - if ((product['id'] as num).toInt() == _selectedProductId) { + if (tryParseDynamicInt(product['id']) == _selectedProductId) { return product; } } @@ -172,7 +172,7 @@ class _InventoryEditScreenState extends ConsumerState { : _products .where( (p) => productInSelectedBranch( - productCategoryId: (p['categoryId'] as num?)?.toInt(), + productCategoryId: tryParseDynamicInt(p['categoryId']), selectedCategoryIds: selectedCategoryIds, ), ) @@ -186,11 +186,12 @@ class _InventoryEditScreenState extends ConsumerState { final sorted = _sortedProductsCache.sort(withSelected); return sorted + .where((p) => tryParseDynamicInt(p['id']) != null) .map( (p) => ( - id: (p['id'] as num).toInt(), + id: tryParseDynamicInt(p['id'])!, name: (p['canonicalName'] ?? p['name'] ?? '').toString(), - categoryId: (p['categoryId'] as num?)?.toInt(), + categoryId: tryParseDynamicInt(p['categoryId']), ), ) .toList(); @@ -207,7 +208,7 @@ class _InventoryEditScreenState extends ConsumerState { _selectedCategoryId = selected.id; final selectedCategoryIds = _selectedCategoryBranchIds(); final current = _selectedProduct(); - final currentCategoryId = (current?['categoryId'] as num?)?.toInt(); + final currentCategoryId = tryParseDynamicInt(current?['categoryId']); if (!productInSelectedBranch( productCategoryId: currentCategoryId, selectedCategoryIds: selectedCategoryIds, @@ -320,7 +321,7 @@ class _InventoryEditScreenState extends ConsumerState { _selectedCategoryId = int.tryParse(value); final selectedCategoryIds = _selectedCategoryBranchIds(); final current = _selectedProduct(); - final currentCategoryId = (current?['categoryId'] as num?)?.toInt(); + final currentCategoryId = tryParseDynamicInt(current?['categoryId']); if (!productInSelectedBranch( productCategoryId: currentCategoryId, selectedCategoryIds: selectedCategoryIds,