fix: ensure ticket gets stored on car invoice polling ticket created/found
What changed, and why it matters
This commit fixes a data-handling bug in a car-research invoice payment screen. Previously, when the app polled the server for invoice status and discovered a newly created support ticket, it did not save that ticket to the local database. The patch adds logic to fetch the full ticket details from the server and store a minimal local record so the rest of the app can see and update it later. There is no indication this is a security vulnerability; it appears to be a functional bug fix.
Treat as a normal functional bug fix. Review for code quality and null-safety (e.g., invoiceStatus.realTicketNumber! could crash if the API omits it), but no security response is indicated based on the supplied materials.
Security signals we found
No security-relevant keywords in commit title or message
No input sanitization or boundary changes
No authentication/authorization logic changes
No cryptographic or secret-handling changes
Functional data-persistence bug fix only
Evidence from the diff
In lib/pages/shopinbit/shopinbit_car_research_payment_view.dart, _pollStatus() now checks the invoice-status response for realTicketId. If present and not already in the local Drift database, it calls getTicketFull() and inserts a bare-minimum ShopInBitTicketsCompanion row inside a transaction. The change prevents a missing local ticket record during the polling flow. No input validation, cryptographic, authorization, or network-trust changes are visible in the diff.
Changed components
lib/pages/shopinbit/shopinbit_car_research_payment_view.dartShopInBit car research payment polling flowShopInBitTicketsDao local databaseInspect captured patch +61 / −7
diff --git a/lib/pages/shopinbit/shopinbit_car_research_payment_view.dart b/lib/pages/shopinbit/shopinbit_car_research_payment_view.dart
index 4232d43..1978f3e 100644
--- a/lib/pages/shopinbit/shopinbit_car_research_payment_view.dart
+++ b/lib/pages/shopinbit/shopinbit_car_research_payment_view.dart
@@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../app_config.dart';
+import '../../db/drift/shared_db/shared_database.dart';
import '../../notifications/show_flush_bar.dart';
import '../../providers/global/shopin_bit_service_provider.dart';
import '../../providers/providers.dart';
@@ -312,13 +313,12 @@ class _ShopInBitCarResearchPaymentViewState
/// the periodic driver can back off instead of polling at full rate.
Future<bool> _pollStatus() async {
try {
- final resp = await ref
- .read(pShopinBitService)
- .client
- .getCarResearchInvoiceStatus(
- widget.invoice.btcpayInvoice,
- customerKey: widget.customerKey,
- );
+ final service = ref.read(pShopinBitService);
+
+ final resp = await service.client.getCarResearchInvoiceStatus(
+ widget.invoice.btcpayInvoice,
+ customerKey: widget.customerKey,
+ );
if (resp.hasError || resp.value == null) {
if (mounted) {
unawaited(
@@ -332,6 +332,60 @@ class _ShopInBitCarResearchPaymentViewState
}
return false;
}
+
+ final apiTicketId = resp.value!.realTicketId;
+ if (apiTicketId != null) {
+ // we may not have the ticket in the db yet. Lets check
+ final ticket = await service.db.shopInBitTicketsDao.getByApiId(
+ apiTicketId,
+ );
+
+ // not found, so lets fix that
+ if (ticket == null) {
+ final invoiceStatus = resp.value!;
+
+ final response = await service.client.getTicketFull(
+ apiTicketId,
+ customerKey: invoiceStatus.externalCustomerKey,
+ );
+
+ if (response.hasError || response.value == null) {
+ Logging.instance.e(
+ "$runtimeType get full ticket for car failed",
+ error: response.exception,
+ stackTrace: .current,
+ );
+ } else {
+ final fullTicket = response.value!;
+
+ // TODO: clean this up a bit some day but for now...
+ await service.db.transaction(() async {
+ // get ticket again to ensure this is an atomic insert operation
+ // in the db transaction
+ final ticket = await service.db.shopInBitTicketsDao.getByApiId(
+ apiTicketId,
+ );
+
+ if (ticket == null) {
+ // insert bare minimum - will be updated automatically later
+ await service.db.shopInBitTicketsDao.insertTicket(
+ ShopInBitTicketsCompanion.insert(
+ apiTicketId: apiTicketId,
+ customerKey: invoiceStatus.externalCustomerKey,
+ ticketNumber: invoiceStatus.realTicketNumber!,
+ category: .car,
+ requestDescription: fullTicket.productName ?? "",
+ deliveryCountry: fullTicket.deliveryCountry,
+ status: .pending,
+ statusRaw: "NEW",
+ ),
+ );
+ }
+ });
+ }
+ }
+ }
+
if (!mounted) return true;
Logging.instance.i(
"CarResearch status response (payment_view): ${resp.value}",
Why this scored 16/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.