From 6861e5e754878798a670a02b395524ae490644d0 Mon Sep 17 00:00:00 2001 From: dbastrikin Date: Thu, 19 Mar 2026 23:05:19 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20POST=20/products=20500=20=E2=80=94=20inv?= =?UTF-8?q?alid=20unit=20FK=20on=20unrecognized=20items?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs caused a FK constraint violation on products.unit: 1. RecognizedItem.fromJson fell back to 'шт' (Cyrillic, not a valid units.code) when the AI returned a null unit — changed to 'pcs'. 2. The unit dropdown in RecognitionConfirmScreen displayed units.keys.first for invalid units but never updated item.unit, so the invalid value was still submitted. Added a reconcile step in build() that syncs item.unit to units.keys.first whenever the stored value is not in the valid set. Co-Authored-By: Claude Sonnet 4.6 --- .../features/scan/recognition_confirm_screen.dart | 15 ++++++++++----- client/lib/features/scan/recognition_service.dart | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/client/lib/features/scan/recognition_confirm_screen.dart b/client/lib/features/scan/recognition_confirm_screen.dart index eb7d439..679ae9f 100644 --- a/client/lib/features/scan/recognition_confirm_screen.dart +++ b/client/lib/features/scan/recognition_confirm_screen.dart @@ -248,10 +248,14 @@ class _ItemTileState extends State<_ItemTile> { const SizedBox(width: 8), widget.units.isEmpty ? const SizedBox(width: 48) - : DropdownButton( - value: widget.units.containsKey(widget.item.unit) - ? widget.item.unit - : widget.units.keys.first, + : Builder(builder: (builderContext) { + // Reconcile item.unit with valid server codes so that the + // submitted value matches what the dropdown displays. + if (!widget.units.containsKey(widget.item.unit)) { + widget.item.unit = widget.units.keys.first; + } + return DropdownButton( + value: widget.item.unit, underline: const SizedBox(), items: widget.units.entries .map((e) => DropdownMenuItem(value: e.key, child: Text(e.value))) @@ -262,7 +266,8 @@ class _ItemTileState extends State<_ItemTile> { widget.onChanged(); } }, - ), + ); + }), IconButton( icon: const Icon(Icons.close), onPressed: widget.onDelete, diff --git a/client/lib/features/scan/recognition_service.dart b/client/lib/features/scan/recognition_service.dart index 590bf05..1fdbf0f 100644 --- a/client/lib/features/scan/recognition_service.dart +++ b/client/lib/features/scan/recognition_service.dart @@ -39,7 +39,7 @@ class RecognizedItem { return RecognizedItem( name: json['name'] as String? ?? '', quantity: (json['quantity'] as num?)?.toDouble() ?? 1.0, - unit: json['unit'] as String? ?? 'шт', + unit: json['unit'] as String? ?? 'pcs', category: json['category'] as String? ?? 'other', confidence: (json['confidence'] as num?)?.toDouble() ?? 0.0, mappingId: json['mapping_id'] as String?,