feat: Improve category ID handling with dynamic parsing in inventory screens
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-11 21:18:06 +02:00
parent 3e0af925d5
commit 8e0166c68a
4 changed files with 39 additions and 15 deletions
+15 -1
View File
@@ -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'
@@ -130,7 +130,7 @@ class _CreateInventoryScreenState
Map<String, dynamic>? _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,
@@ -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<int, Set<int>> _descendantsById;
@@ -62,8 +70,8 @@ class InventorySortedProductsCache {
String _buildKey(List<Map<String, dynamic>> 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)
@@ -152,7 +152,7 @@ class _InventoryEditScreenState extends ConsumerState<InventoryEditScreen> {
Map<String, dynamic>? _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<InventoryEditScreen> {
: _products
.where(
(p) => productInSelectedBranch(
productCategoryId: (p['categoryId'] as num?)?.toInt(),
productCategoryId: tryParseDynamicInt(p['categoryId']),
selectedCategoryIds: selectedCategoryIds,
),
)
@@ -186,11 +186,12 @@ class _InventoryEditScreenState extends ConsumerState<InventoryEditScreen> {
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<InventoryEditScreen> {
_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<InventoryEditScreen> {
_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,