Skip to content

Commit ab93fe0

Browse files
committed
feat(shopinbit): recover requestDescription and detect travel on restore
1 parent 91dc822 commit ab93fe0

1 file changed

Lines changed: 30 additions & 8 deletions

File tree

lib/services/shopinbit/shopinbit_service.dart

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class ShopInBitService {
136136
final feeTicketNumber = category == ShopInBitCategory.car
137137
? _extractFeeTicketNumber(apiMessages)
138138
: null;
139+
final requestDescription = _extractRequestDescription(apiMessages);
139140

140141
final messages = apiMessages
141142
.map(
@@ -153,7 +154,7 @@ class ShopInBitService {
153154
category: Value(category),
154155
status: Value(mappedStatus),
155156
statusRaw: Value(statusResp.value!.stateRaw),
156-
requestDescription: const Value(""),
157+
requestDescription: Value(requestDescription),
157158
deliveryCountry: const Value(""),
158159
offerProductName: Value(offerProductName),
159160
offerPrice: Value(offerPrice),
@@ -180,22 +181,43 @@ class ShopInBitService {
180181
}
181182
}
182183

183-
// The API does not return service_type for existing tickets, so we infer
184-
// category from the first user message. Stack Wallet's car flow always seeds
185-
// the comment with this exact phrase; travel cannot be distinguished from
186-
// concierge because Stack Wallet sends travel as service_type="concierge" too.
184+
// Infer category from the first user message. The car flow always seeds
185+
// the comment with the "car research fee" line; travel requests built by
186+
// _buildRequestDescription always start with "Arrangement: " followed by
187+
// structured labels. Both are fragile against template changes in the form.
187188
final RegExp _kCarResearchFeeRegex = RegExp(r'car research fee \(#([^)]+)\)');
189+
final RegExp _kTravelArrangementRegex = RegExp(
190+
r'^Arrangement:\s',
191+
multiLine: true,
192+
);
188193

189194
ShopInBitCategory _inferCategoryFromMessages(List<TicketMessage> messages) {
190195
final firstUser = messages.where((m) => !m.fromAgent).firstOrNull;
191196
if (firstUser == null) return ShopInBitCategory.concierge;
192-
return _kCarResearchFeeRegex.hasMatch(firstUser.content)
193-
? ShopInBitCategory.car
194-
: ShopInBitCategory.concierge;
197+
final content = firstUser.content;
198+
if (_kCarResearchFeeRegex.hasMatch(content)) {
199+
return ShopInBitCategory.car;
200+
}
201+
if (_kTravelArrangementRegex.hasMatch(content)) {
202+
return ShopInBitCategory.travel;
203+
}
204+
return ShopInBitCategory.concierge;
195205
}
196206

197207
String? _extractFeeTicketNumber(List<TicketMessage> messages) {
198208
final firstUser = messages.where((m) => !m.fromAgent).firstOrNull;
199209
if (firstUser == null) return null;
200210
return _kCarResearchFeeRegex.firstMatch(firstUser.content)?.group(1);
201211
}
212+
213+
// The original `comment` passed to POST /requests becomes the first user message.
214+
final RegExp _kHtmlTagRegex = RegExp(r'<[^>]+>');
215+
216+
String _extractRequestDescription(List<TicketMessage> messages) {
217+
final firstUser = messages.where((m) => !m.fromAgent).firstOrNull;
218+
if (firstUser == null) return "";
219+
return firstUser.content
220+
.replaceAll(RegExp(r'<br\s*/?>', caseSensitive: false), '\n')
221+
.replaceAll(_kHtmlTagRegex, '')
222+
.trim();
223+
}

0 commit comments

Comments
 (0)