production
This commit is contained in:
@@ -67,7 +67,7 @@ extension RouteOrderSourceX on RouteOrderSource {
|
||||
/// What the rider is told the list is ordered by. Short, because it sits
|
||||
/// under a heading and not in a paragraph.
|
||||
String get label => switch (this) {
|
||||
RouteOrderSource.adminSequence => 'Hub route',
|
||||
RouteOrderSource.adminSequence => 'Assigned route',
|
||||
RouteOrderSource.bookedTime => 'By booked time',
|
||||
RouteOrderSource.backendOrder => 'As assigned',
|
||||
RouteOrderSource.proximity => 'Nearest first',
|
||||
@@ -76,7 +76,8 @@ extension RouteOrderSourceX on RouteOrderSource {
|
||||
/// The longer form, for a place with room to explain — and specifically to
|
||||
/// keep the app from implying the hub planned an order it did not.
|
||||
String get explanation => switch (this) {
|
||||
RouteOrderSource.adminSequence => 'Ordered by the route your hub assigned.',
|
||||
RouteOrderSource.adminSequence =>
|
||||
'Ordered by the route your office assigned.',
|
||||
RouteOrderSource.bookedTime =>
|
||||
'No route assigned — ordered by booked time.',
|
||||
RouteOrderSource.backendOrder =>
|
||||
@@ -122,9 +123,43 @@ abstract final class RouteOrder {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Field names that have carried the moment the route was solved.
|
||||
static const List<String> sequencedAtKeys = [
|
||||
'sequencedat',
|
||||
'sequencedAt',
|
||||
'sequenced_at',
|
||||
'routesequencedat',
|
||||
];
|
||||
|
||||
/// True when this stop carries a solve timestamp.
|
||||
///
|
||||
/// ── The authority signal, confirmed by the backend ──
|
||||
///
|
||||
/// `sequencedat` is what says a route exists: **non-null → follow `step`
|
||||
/// exactly; null → no route was assigned, use a fallback.** Sequencing is
|
||||
/// automatic on every assignment — there is no operator action to wait for —
|
||||
/// so `step: 0` with a null stamp means one of exactly three things: the
|
||||
/// rider has fewer than two active stops, a stop is missing coordinates, or
|
||||
/// the row predates the fix. None of those is a route to follow.
|
||||
static bool isSequenced(Map<String, dynamic> stop) {
|
||||
for (final key in sequencedAtKeys) {
|
||||
final raw = stop[key];
|
||||
if (raw == null) continue;
|
||||
if (raw.toString().trim().isEmpty) continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// True when the hub has solved an order for at least one of these stops.
|
||||
///
|
||||
/// The stamp is the authority and a positive `step` is accepted alongside
|
||||
/// it: a deployment that populates one without the other is still telling
|
||||
/// the app it has a route, and refusing to follow a numbered sequence
|
||||
/// because its timestamp is missing would be reading the contract against
|
||||
/// the rider. Either is enough; neither means no route.
|
||||
static bool hasAdminSequence(Iterable<Map<String, dynamic>> stops) =>
|
||||
stops.any((s) => sequenceOf(s) > 0);
|
||||
stops.any((s) => isSequenced(s) || sequenceOf(s) > 0);
|
||||
|
||||
/// Puts [stops] in the order they are to be worked, and says which rule it
|
||||
/// used.
|
||||
|
||||
Reference in New Issue
Block a user