feat: Implement hub and role matching for order creation and remove payment, savings, and export sections from the billing page.

This commit is contained in:
Achintha Isuru
2026-02-27 21:32:12 -05:00
parent 95175536a0
commit bba4054143
4 changed files with 159 additions and 131 deletions

View File

@@ -382,29 +382,82 @@ class ClientCreateOrderRepositoryImpl
);
final RapidOrderParsedData data = response.parsed;
// Fetch Business ID
final String businessId = await _service.getBusinessId();
// 1. Hub Matching
final OperationResult<
dc.ListTeamHubsByOwnerIdData,
dc.ListTeamHubsByOwnerIdVariables
>
hubResult = await _service.connector
.listTeamHubsByOwnerId(ownerId: businessId)
.execute();
final List<dc.ListTeamHubsByOwnerIdTeamHubs> hubs = hubResult.data.teamHubs;
final dc.ListTeamHubsByOwnerIdTeamHubs? bestHub = _findBestHub(
hubs,
data.locationHint,
);
// 2. Roles Matching
// We fetch vendors to get the first one as a context for role matching.
final OperationResult<dc.ListVendorsData, void> vendorResult =
await _service.connector.listVendors().execute();
final List<dc.ListVendorsVendors> vendors = vendorResult.data.vendors;
String? selectedVendorId;
List<dc.ListRolesByVendorIdRoles> availableRoles =
<dc.ListRolesByVendorIdRoles>[];
if (vendors.isNotEmpty) {
selectedVendorId = vendors.first.id;
final OperationResult<
dc.ListRolesByVendorIdData,
dc.ListRolesByVendorIdVariables
>
roleResult = await _service.connector
.listRolesByVendorId(vendorId: selectedVendorId)
.execute();
availableRoles = roleResult.data.roles;
}
final DateTime startAt =
DateTime.tryParse(data.startAt ?? '') ?? DateTime.now();
final DateTime endAt =
DateTime.tryParse(data.endAt ?? '') ??
startAt.add(const Duration(hours: 8));
final String startTimeStr = DateFormat('hh:mm a').format(startAt);
final String endTimeStr = DateFormat('hh:mm a').format(endAt);
final String startTimeStr = DateFormat('hh:mm a').format(startAt.toLocal());
final String endTimeStr = DateFormat('hh:mm a').format(endAt.toLocal());
return domain.OneTimeOrder(
date: startAt,
location: data.locationHint ?? '',
location: bestHub?.hubName ?? data.locationHint ?? '',
eventName: data.notes ?? '',
hub: data.locationHint != null
vendorId: selectedVendorId,
hub: bestHub != null
? domain.OneTimeOrderHubDetails(
id: '',
name: data.locationHint!,
address: '',
id: bestHub.id,
name: bestHub.hubName,
address: bestHub.address,
placeId: bestHub.placeId,
latitude: bestHub.latitude ?? 0,
longitude: bestHub.longitude ?? 0,
city: bestHub.city,
state: bestHub.state,
street: bestHub.street,
country: bestHub.country,
zipCode: bestHub.zipCode,
)
: null,
positions: data.positions.map((RapidOrderPosition p) {
final dc.ListRolesByVendorIdRoles? matchedRole = _findBestRole(
availableRoles,
p.role,
);
return domain.OneTimeOrderPosition(
role: p.role,
role: matchedRole?.id ?? p.role,
count: p.count,
startTime: startTimeStr,
endTime: endTimeStr,
@@ -656,4 +709,85 @@ class ClientCreateOrderRepositoryImpl
}
return domain.OrderType.oneTime;
}
dc.ListTeamHubsByOwnerIdTeamHubs? _findBestHub(
List<dc.ListTeamHubsByOwnerIdTeamHubs> hubs,
String? hint,
) {
if (hint == null || hint.isEmpty || hubs.isEmpty) return null;
final String normalizedHint = hint.toLowerCase();
dc.ListTeamHubsByOwnerIdTeamHubs? bestMatch;
double highestScore = -1;
for (final dc.ListTeamHubsByOwnerIdTeamHubs hub in hubs) {
final String name = hub.hubName.toLowerCase();
final String address = hub.address.toLowerCase();
double score = 0;
if (name == normalizedHint || address == normalizedHint) {
score = 100;
} else if (name.contains(normalizedHint) ||
address.contains(normalizedHint)) {
score = 80;
} else if (normalizedHint.contains(name) ||
normalizedHint.contains(address)) {
score = 60;
} else {
final List<String> hintWords = normalizedHint.split(RegExp(r'\s+'));
final List<String> hubWords = ('$name $address').split(RegExp(r'\s+'));
int overlap = 0;
for (final String word in hintWords) {
if (word.length > 2 && hubWords.contains(word)) overlap++;
}
score = overlap * 10.0;
}
if (score > highestScore) {
highestScore = score;
bestMatch = hub;
}
}
return (highestScore >= 10) ? bestMatch : null;
}
dc.ListRolesByVendorIdRoles? _findBestRole(
List<dc.ListRolesByVendorIdRoles> roles,
String? hint,
) {
if (hint == null || hint.isEmpty || roles.isEmpty) return null;
final String normalizedHint = hint.toLowerCase();
dc.ListRolesByVendorIdRoles? bestMatch;
double highestScore = -1;
for (final dc.ListRolesByVendorIdRoles role in roles) {
final String name = role.name.toLowerCase();
double score = 0;
if (name == normalizedHint) {
score = 100;
} else if (name.contains(normalizedHint)) {
score = 80;
} else if (normalizedHint.contains(name)) {
score = 60;
} else {
final List<String> hintWords = normalizedHint.split(RegExp(r'\s+'));
final List<String> roleWords = name.split(RegExp(r'\s+'));
int overlap = 0;
for (final String word in hintWords) {
if (word.length > 2 && roleWords.contains(word)) overlap++;
}
score = overlap * 10.0;
}
if (score > highestScore) {
highestScore = score;
bestMatch = role;
}
}
return (highestScore >= 10) ? bestMatch : null;
}
}