From 823f9107fdd484658606dd4ba0f6ccf0d29447ef Mon Sep 17 00:00:00 2001 From: Mathias Beaulieu-Duncan Date: Tue, 20 Jan 2026 13:06:08 -0500 Subject: [PATCH] auto-claude: subtask-3-4 - Implement command methods (complete, uncomplete, skip) Adds gRPC command methods to GrpcCqrsApiClient for delivery operations: - completeDelivery: Mark delivery as completed with optional timestamp - markDeliveryAsUncompleted: Revert completed delivery to pending - skipDelivery: Skip a delivery that cannot be completed All methods follow the Result pattern for consistent error handling, check CommandResponse.success flag, and map error messages appropriately. Co-Authored-By: Claude --- lib/api/grpc_client.dart | 125 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/lib/api/grpc_client.dart b/lib/api/grpc_client.dart index 7783b5f..20b2ac2 100644 --- a/lib/api/grpc_client.dart +++ b/lib/api/grpc_client.dart @@ -400,6 +400,131 @@ class GrpcCqrsApiClient { ); } + // ============================================================ + // Command Methods + // ============================================================ + + /// Marks a delivery as completed. + /// + /// Returns a [Result] indicating success or failure. Optionally accepts + /// a [deliveredAt] timestamp; if not provided, the server will use the + /// current time. + /// + /// Example: + /// ```dart + /// final result = await client.completeDelivery(deliveryId: 123); + /// result.when( + /// success: (_) => showSuccess('Delivery completed'), + /// onError: (error) => showError(error.message), + /// ); + /// ``` + Future> completeDelivery({ + required int deliveryId, + String? deliveredAt, + }) async { + final request = CompleteDeliveryRequest( + deliveryId: deliveryId, + deliveredAt: deliveredAt, + ); + + final result = await _executeWithAuth( + (options) => deliveryClient.completeDelivery(request, options: options), + ); + + return result.when( + success: (response) { + if (response.success) { + return Result.success(null); + } + return Result.error( + ApiError.unknown(response.message.isNotEmpty + ? response.message + : 'Failed to complete delivery'), + ); + }, + onError: (error) => Result.error(error), + ); + } + + /// Marks a delivery as uncompleted. + /// + /// Returns a [Result] indicating success or failure. Use this to revert + /// a previously completed delivery back to pending status. + /// + /// Example: + /// ```dart + /// final result = await client.markDeliveryAsUncompleted(deliveryId: 123); + /// result.when( + /// success: (_) => showSuccess('Delivery marked as uncompleted'), + /// onError: (error) => showError(error.message), + /// ); + /// ``` + Future> markDeliveryAsUncompleted({ + required int deliveryId, + }) async { + final request = MarkDeliveryUncompletedRequest( + deliveryId: deliveryId, + ); + + final result = await _executeWithAuth( + (options) => + deliveryClient.markDeliveryUncompleted(request, options: options), + ); + + return result.when( + success: (response) { + if (response.success) { + return Result.success(null); + } + return Result.error( + ApiError.unknown(response.message.isNotEmpty + ? response.message + : 'Failed to mark delivery as uncompleted'), + ); + }, + onError: (error) => Result.error(error), + ); + } + + /// Skips a delivery. + /// + /// Returns a [Result] indicating success or failure. Use this when a + /// delivery cannot be completed and needs to be skipped. + /// + /// Example: + /// ```dart + /// final result = await client.skipDelivery(deliveryId: 123); + /// result.when( + /// success: (_) => showSuccess('Delivery skipped'), + /// onError: (error) => showError(error.message), + /// ); + /// ``` + Future> skipDelivery({ + required int deliveryId, + }) async { + final request = SkipDeliveryRequest( + deliveryId: deliveryId, + ); + + final result = await _executeWithAuth( + (options) => deliveryClient.skipDelivery(request, options: options), + ); + + return result.when( + success: (response) { + if (response.success) { + return Result.success(null); + } + return Result.error( + ApiError.unknown(response.message.isNotEmpty + ? response.message + : 'Failed to skip delivery'), + ); + }, + onError: (error) => Result.error(error), + ); + } + /// Shuts down the gRPC channel and releases resources. /// /// Should be called when the client is no longer needed to properly