// ignore_for_file: invalid_use_of_protected_member part of '../../registration_page.dart'; extension _RegistrationAttachmentPart on _RegistrationPageState { /// Handle FJ- attachment scan: pick category, then register location. Future _handleAttachmentScan(String zongpaiNo) async { if (_crossPaichaPending) { _triggerDoubleVibration(); return; } final baseUrl = await _baseUrl(); if (baseUrl == null || !mounted) return; // 1. Fetch categories (cache in the page state) final catResult = await _apiService.fetchAttachmentCategories( baseUrl: baseUrl, ); if (!catResult.success || !mounted) { _feedbackService.trigger(FeedbackEvent.scanInvalid); _showStatusOverride( catResult.errorMessage ?? '加载附件类型失败', StatusDotColor.red, const Duration(seconds: 2), ); return; } final categories = catResult.categories; // 2. Pick category (single choice) final picked = await showAttachmentCategoryPicker( context: context, categories: categories, ); if (picked == null || !mounted) return; // 3. Now treat this zongpai as "scanned" with the picked category // For the registration flow: append scanned zongpai (for location binding) // and store category context for the submit path _feedbackService.trigger(FeedbackEvent.scanValid); setState(() { if (_mode == RegistrationMode.multiCode) { if (!_zongpaiNos.contains(zongpaiNo)) { _zongpaiNos.add(zongpaiNo); } } else { if (_zongpaiNos.isEmpty) { _zongpaiNos.add(zongpaiNo); } else { _zongpaiNos[0] = zongpaiNo; } } // Store the last-scanned attachment category for submit _pendingAttachmentCategory = picked.id; _clearStatusOverride(); }); // 4. Refresh the overview (the zongpai is now a product scan for display, // attachment status will be shown via a separate banner/tag) final shouldRefresh = _overviewZongpaiNo != zongpaiNo; if (shouldRefresh) { _loadOverview(zongpaiNo); } } /// Handle a product scan with attachment-config integration. /// Called from the existing _handleZongpaiScan when a product code is scanned. Future _checkAndConfigureAttachment(String zongpaiNo) async { final baseUrl = await _baseUrl(); if (baseUrl == null || !mounted) return; // Fetch attachment status for this zongpai final status = await _apiService.fetchAttachmentStatus( baseUrl: baseUrl, zongpaiNo: zongpaiNo, ); if (!mounted) return; if (!status.success) { // Network error or other — defer to product scan flow without blocking return; } if (status.determination == 'none') { // Already determined none — nothing to configure return; } if (status.determination == 'undetermined' || status.determination == 'has') { // Fetch categories for the dialog final catResult = await _apiService.fetchAttachmentCategories( baseUrl: baseUrl, ); if (!catResult.success || !mounted) return; // Fetch ERP quantity for default expected_qty final overview = _overview; final erpQty = overview?.success == true ? overview!.items .where((i) => i.zongpaiNo == zongpaiNo) .fold(0, (sum, i) => sum + i.quantity) : 0; final result = await showAttachmentConfigDialog( context: context, zongpaiNo: zongpaiNo, categories: catResult.categories, prefillItems: status.items, erpQuantity: erpQty > 0 ? erpQty : 1, ); if (result == null || !mounted) return; // Submit config final configResult = await _apiService.putAttachmentConfig( baseUrl: baseUrl, zongpaiNo: zongpaiNo, determination: result.determination, items: result.items, ); if (!mounted) return; if (!configResult.success) { _feedbackService.trigger(FeedbackEvent.submitFailure); _showStatusOverride( configResult.errorMessage ?? '配置失败', StatusDotColor.red, const Duration(seconds: 2), ); } } } /// Submit attachment location for the given zongpai. Future _submitAttachmentLocation( String baseUrl, String zongpaiNo, int categoryId, ) async { final result = await _apiService.registerAttachmentLocation( baseUrl: baseUrl, zongpaiNo: zongpaiNo, categoryId: categoryId, locationCode: _locationCode!, ); if (!mounted) return false; if (result.success) { return true; } else if (result.isDuplicate) { _feedbackService.trigger(FeedbackEvent.duplicateError); if (result.conflictInfo != null) { final msg = '附件 $zongpaiNo 已上架至 ${result.conflictInfo!['location_code']}'; _showStatusOverride( msg, StatusDotColor.red, const Duration(seconds: 2), ); } return false; } else if (result.isAlreadyOffShelf) { _feedbackService.trigger(FeedbackEvent.submitFailure); _showStatusOverride( result.errorMessage ?? '该附件已下架至转运区域,不可重新上架', StatusDotColor.red, const Duration(seconds: 2), ); return false; } else { final isNetwork = result.errorMessage == '网络异常,请检查网络连接'; _feedbackService.trigger( isNetwork ? FeedbackEvent.networkError : FeedbackEvent.submitFailure, ); _showStatusOverride( result.errorMessage ?? '提交失败', isNetwork ? StatusDotColor.yellow : StatusDotColor.red, const Duration(seconds: 2), ); return false; } } }