auto-claude: subtask-3-3 - Implement getDeliveries query method

This commit is contained in:
Mathias Beaulieu-Duncan 2026-01-20 13:04:25 -05:00
parent 66d337315b
commit 7c1832dd4f
2 changed files with 116 additions and 3 deletions

View File

@ -3,7 +3,7 @@
"spec": "002-migrate-api-routes-from-http-to-grpc", "spec": "002-migrate-api-routes-from-http-to-grpc",
"state": "building", "state": "building",
"subtasks": { "subtasks": {
"completed": 4, "completed": 6,
"total": 13, "total": 13,
"in_progress": 1, "in_progress": 1,
"failed": 0 "failed": 0
@ -18,8 +18,8 @@
"max": 1 "max": 1
}, },
"session": { "session": {
"number": 5, "number": 7,
"started_at": "2026-01-20T12:45:59.858836" "started_at": "2026-01-20T12:45:59.858836"
}, },
"last_update": "2026-01-20T12:58:25.218168" "last_update": "2026-01-20T13:03:21.219002"
} }

View File

@ -3,7 +3,12 @@ import 'dart:async';
import 'package:grpc/grpc.dart'; import 'package:grpc/grpc.dart';
import '../generated/delivery_service.pbgrpc.dart'; import '../generated/delivery_service.pbgrpc.dart';
import '../models/delivery.dart';
import '../models/delivery_address.dart';
import '../models/delivery_contact.dart';
import '../models/delivery_order.dart';
import '../models/delivery_route.dart'; import '../models/delivery_route.dart';
import '../models/user_info.dart';
import '../services/auth_service.dart'; import '../services/auth_service.dart';
import 'grpc_config.dart'; import 'grpc_config.dart';
import 'types.dart'; import 'types.dart';
@ -287,6 +292,114 @@ class GrpcCqrsApiClient {
); );
} }
/// Gets deliveries for a specific route fragment.
///
/// Returns a [Result] containing a list of [Delivery] objects for the
/// specified [routeFragmentId]. Maps the gRPC [DeliveriesResponse] to
/// domain models.
///
/// Example:
/// ```dart
/// final result = await client.getDeliveries(routeFragmentId: 123);
/// result.when(
/// success: (deliveries) => displayDeliveries(deliveries),
/// onError: (error) => showError(error.message),
/// );
/// ```
Future<Result<List<Delivery>>> getDeliveries({
required int routeFragmentId,
}) async {
final request = GetDeliveriesRequest(routeFragmentId: routeFragmentId);
final result = await _executeWithAuth<DeliveriesResponse>(
(options) => deliveryClient.getDeliveries(request, options: options),
);
return result.when(
success: (response) {
final deliveries =
response.deliveries.map(_mapDeliveryProto).toList();
return Result.success(deliveries);
},
onError: (error) => Result.error(error),
);
}
/// Maps a [DeliveryProto] to a [Delivery] domain model.
Delivery _mapDeliveryProto(DeliveryProto proto) {
return Delivery(
id: proto.id,
routeFragmentId: proto.routeFragmentId,
deliveryIndex: proto.deliveryIndex,
orders: proto.orders.map(_mapDeliveryOrderProto).toList(),
deliveredBy:
proto.hasDeliveredBy() ? _mapUserInfoProto(proto.deliveredBy) : null,
deliveryAddress: proto.hasDeliveryAddress()
? _mapDeliveryAddressProto(proto.deliveryAddress)
: null,
deliveredAt: proto.hasDeliveredAt() ? proto.deliveredAt : null,
skippedAt: proto.hasSkippedAt() ? proto.skippedAt : null,
createdAt: proto.createdAt,
updatedAt: proto.hasUpdatedAt() ? proto.updatedAt : null,
delivered: proto.delivered,
hasBeenSkipped: proto.hasBeenSkipped,
isSkipped: proto.isSkipped,
name: proto.name,
);
}
/// Maps a [DeliveryAddressProto] to a [DeliveryAddress] domain model.
DeliveryAddress _mapDeliveryAddressProto(DeliveryAddressProto proto) {
return DeliveryAddress(
id: proto.id,
line1: proto.hasLine1() ? proto.line1 : null,
line2: proto.hasLine2() ? proto.line2 : null,
postalCode: proto.hasPostalCode() ? proto.postalCode : null,
city: proto.hasCity() ? proto.city : null,
subdivision: proto.hasSubdivision() ? proto.subdivision : null,
countryCode: proto.hasCountryCode() ? proto.countryCode : null,
latitude: proto.hasLatitude() ? proto.latitude : null,
longitude: proto.hasLongitude() ? proto.longitude : null,
formattedAddress:
proto.hasFormattedAddress() ? proto.formattedAddress : null,
);
}
/// Maps a [DeliveryOrderProto] to a [DeliveryOrder] domain model.
DeliveryOrder _mapDeliveryOrderProto(DeliveryOrderProto proto) {
return DeliveryOrder(
id: proto.id,
isNewCustomer: proto.isNewCustomer,
note: proto.hasNote() ? proto.note : null,
totalAmount: proto.totalAmount,
totalPaid: proto.hasTotalPaid() ? proto.totalPaid : null,
totalItems: proto.hasTotalItems() ? proto.totalItems : null,
contacts: proto.contacts.map(_mapDeliveryContactProto).toList(),
contact:
proto.hasContact() ? _mapDeliveryContactProto(proto.contact) : null,
);
}
/// Maps a [DeliveryContactProto] to a [DeliveryContact] domain model.
DeliveryContact _mapDeliveryContactProto(DeliveryContactProto proto) {
return DeliveryContact(
firstName: proto.firstName,
lastName: proto.hasLastName() ? proto.lastName : null,
fullName: proto.fullName,
phoneNumber: proto.hasPhoneNumber() ? proto.phoneNumber : null,
);
}
/// Maps a [UserInfoProto] to a [UserInfo] domain model.
UserInfo _mapUserInfoProto(UserInfoProto proto) {
return UserInfo(
id: proto.id,
firstName: proto.firstName,
lastName: proto.hasLastName() ? proto.lastName : null,
fullName: proto.fullName,
);
}
/// Shuts down the gRPC channel and releases resources. /// Shuts down the gRPC channel and releases resources.
/// ///
/// Should be called when the client is no longer needed to properly /// Should be called when the client is no longer needed to properly