Once an order is packaged and marked LISTO, the seller’s next responsibility is to assign a courier (mensajero) and monitor the delivery to completion. SansiStore models each delivery as a separate Firestore document in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProcesosAgilesUMSS/sansistore/llms.txt
Use this file to discover all available pages before exploring further.
deliveries collection, linked to the originating order. The seller portal provides dedicated pages for incidents, failure reasons, and decisions on non-delivered orders.
Delivery Assignment Flow
Order Reaches LISTO Status
After
markOrderReady updates the order to LISTO, it appears on /seller/ready-orders. The ReadyOrdersPanel component lists all such orders filtered by sellerId.Seller Opens the Assign Messenger Modal
Clicking an order card opens
AssignMessengerModal. The modal calls useGetMessengers to load all registered couriers from Firestore and shows their availability status (isAvailable: boolean).If all couriers are busy (
isAvailable: false), the modal displays a warning: “Todos los mensajeros están ocupados en este momento.” The confirm button remains disabled until an available courier is selected.Confirm Courier Assignment
The seller selects an available courier and clicks Confirmar asignación. This triggers The transaction is atomic — if the order document does not exist or the write fails, neither document is modified.
useAssignOrdersToDelivery.assingToDelivery(orderId, courierId), which calls assignCourierToDelivery in a single Firestore transaction.Courier Picks Up and Delivers
The courier app moves the delivery through
picked_up → in_transit → delivered. On a successful delivery the order reaches ENTREGADO or PAGADO. On failure or non-delivery it lands in NO ENTREGADO.Courier Reassignment (if needed)
If a delivery stalls in The
PENDIENTE-ASIGNACION, the seller can reassign using reassignCourierToDelivery. This function updates the existing delivery document’s courierId and resets its assignedAt timestamp, while updating the order back to ASIGNADO.useRessignOrdersToDelivery hook wraps this service and is used by ReassignModal.Deliveries Firestore Schema
Each document in thedeliveries collection contains:
| Field | Type | Description |
|---|---|---|
orderId | string | Reference to the parent order |
courierId | string | UID of the assigned courier |
status | string | assigned → picked_up → in_transit → delivered / failed / reprogrammed |
deliveryCode | string | Human-readable code, e.g. DEL-LX3K9F |
attemptNumber | number | Increments on reassignment or reprogramming |
incidentReason | string | null | Free-text incident logged by courier |
evidenceUrl | string | null | URL to photographic evidence |
failureReason | string | null | Structured failure category |
amountCollected | number | null | Cash collected on delivery (BOB) |
customerConfirmed | boolean | Whether the buyer confirmed reception |
customerConfirmedAt | Timestamp | null | When the buyer confirmed |
pickedUpAt | Timestamp | null | When courier picked up the package |
inTransitAt | Timestamp | null | When courier departed |
deliveredAt | Timestamp | null | Successful delivery timestamp |
failedAt | Timestamp | null | Failure timestamp |
reprogrammedAt | Timestamp | null | When delivery was rescheduled |
assignedAt | Timestamp | When courier was assigned |
createdAt | Timestamp | Document creation time |
updatedAt | Timestamp | Last modification time |
Incidents Page
The/seller/incidents page (IncidentsPanel) lets the seller log and review delivery problems in real time. An incident is a note attached to a delivery explaining why it could not be completed as expected — for example, a blocked road or an inaccessible building.
Incident fields stored in the order
Incident fields stored in the order
When an incident is recorded, the order document is updated with:
incidentReason(string) — the human-readable incident descriptionincidentNotes(string | null) — optional extended notes
OrderDetailsModal and on the individual order detail page at /seller/orders/[id].Failure Reasons Page
The/seller/failure-reasons page is powered by the useDeliveryFailureReasons hook. It combines:
ordersAwaitingReason— rejected orders (RECHAZADO) that have no seller-registered failure reason yet and no customer return reasonregisteredReasons— seller-submitted records from thedeliveryFailurescollectioncustomerReturnReasons— buyer-submitted return requests from thereturnscollection
Registering a Failure Reason
The seller picks a structured reason from theDELIVERY_FAILURE_REASON_OPTIONS list and optionally adds a description:
registerDeliveryFailureReason validates that:
- The order exists and belongs to the authenticated seller
- The order is in
RECHAZADOstatus - No reason has already been registered for this order
- No customer return has been filed for this order
deliveryFailures/{orderId} and updates the order with deliveryFailureReason, deliveryFailureDescription, deliveryFailureRegisteredAt, and deliveryFailureRegisteredBy.
Failed Orders — Seller Decision
Orders inNO ENTREGADO status surface on /seller/failed-orders. The FailedOrdersPanel uses useFailedOrderDecision (which calls restartFailedOrder or cancelFailedOrder) to resolve each case.
- Restart Order
- Cancel Order
Restarting returns the order to
RESERVADO so the seller can re-package and re-assign a courier. If stockRestored is true (inventory was already freed), the service re-reserves the items before updating the order:Undelivered Orders — Seller Decision
/seller/undelivered-orders shows the same NO ENTREGADO queue but is managed by useUndeliveredOrderDecision, which calls restartUndeliveredOrder or cancelUndeliveredOrder from undeliveredOrderDecisionService.ts. The logic is identical to the failed-order flow — restart re-reserves stock when needed, and cancel releases it. Both hooks expose loadingAction, successAction, and error for optimistic UI feedback.
Both
FailedOrdersPanel and UndeliveredOrdersPanel display an incidentReason badge when the field is populated, giving the seller immediate context before making the restart or cancel decision.