[Feature] Merchant webhooks, nearest-driver assignment, driver earnings, and proof-of-delivery gating - #178
Merged
Merged
Conversation
Merchants can register HTTPS endpoints per delivery-lifecycle event; every delivery status transition now fires a signed (HMAC-SHA256), retried (exponential backoff via a cron sweep) POST to each subscribed endpoint, persisted through WebhookSubscription/WebhookDeliveryAttempt so retries survive a process restart. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assigns the nearest available driver to a funded delivery using the existing DriverLocation 2dsphere index, expanding the search radius on a miss. Race conditions are handled with an atomic per-driver claim (findOneAndUpdate on isAvailable) plus a per-delivery Redis lock, so concurrent assignment attempts cannot double-book a driver or a delivery. A cron sweep auto-assigns unassigned funded deliveries on a schedule, and a manual admin endpoint (POST /deliveries/:id/assign-nearest-driver) covers on-demand retries. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GET /api/v1/drivers/:id/earnings aggregates a driver's earnings by day/week/month, sourced from resolved (released) Escrow documents joined to their delivery's driverId rather than derived from Delivery fields. Accessible by the driver themselves or an admin. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Drivers must upload a delivery image (stored via the existing S3/local storage driver abstraction) before a delivery can transition to completed or its escrow can be released. The image reference lives on the Delivery document; both the completion transition (delivery.service.ts) and the escrow release endpoint (escrow.service.ts) now assert proof exists first. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
@Dannyorji Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Collaborator
|
Thank you for contributing to the project |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Webhook dispatch system (
src/services/webhookService.ts): merchants register HTTPSendpoints (
WebhookSubscription) that receive a signed (HMAC-SHA256), retried POST on everydelivery status transition. Attempts are persisted (
WebhookDeliveryAttempt) so retriessurvive a restart; a cron sweep (
jobs/webhookRetryJob.ts) drives exponential-backoff retriesup to
WEBHOOK_MAX_RETRIES. CRUD endpoints live underPOST/GET/PATCH/DELETE /api/v1/webhooks(merchant/admin only), including secret rotation.
Nearest-driver assignment (
src/services/assignmentService.ts): finds and assigns thenearest available driver to a funded delivery using the existing
DriverLocation2dsphereindex, expanding the search radius on a miss (up to
ASSIGNMENT_RADIUS_EXPANSION_STEPS).Race conditions are handled with an atomic per-driver claim (
findOneAndUpdateonisAvailable) plus a per-delivery Redis lock, so concurrent attempts can't double-book adriver or a delivery. A cron sweep auto-assigns unassigned funded deliveries; a manual admin
endpoint (
POST /api/v1/deliveries/:id/assign-nearest-driver) covers on-demand retries.Driver earnings ledger (
GET /api/v1/drivers/:id/earnings): aggregates a driver'searnings by day/week/month from resolved (
released)Escrowdocuments joined to theirdelivery's
driverId, rather than deriving amounts from theDeliveryrecord. Accessible bythe driver themselves or an admin.
Proof of delivery gating: drivers must upload a completion photo
(
POST /api/v1/deliveries/:id/proof-of-delivery, stored via the existing S3/local storagedriver abstraction) before a delivery can transition to
completedor its escrow can bereleased. The image reference is stored on the
Deliverydocument; both the completiontransition (
delivery.service.ts) and the escrow release flow (escrow.service.ts) nowassert proof exists first.
Notes
expansion/cron, and proof-of-delivery upload limits — see
src/config/env.ts.src/routes/index.tswhile wiring up the newrouters.
Closes #127
Closes #128
Closes #130
Closes #133