Workroom Tracking & Auto-Ship
Overview
The Workroom Tracking system enables Malet Owners to inject carrier shipping information during Murchase fulfillment. When a tracking number is provided via the advanceWorkroom mutation, the platform automatically:
- Writes tracking fields to the associated Order document
- Transitions the Murchase status from
PROCESSINGโSHIPPED - Triggers shipping notification alerts to the Visitor (email + push)
This document covers the end-to-end data flow, the DTO surface, and frontend integration patterns.
Data Flow
sequenceDiagram
participant MO as Malet Owner (Deck)
participant FE as Frontend
participant GW as Hive Gateway
participant WS as WorkroomService
participant OS as OrderService
participant AL as AlertsClient
MO->>FE: Fill tracking form
FE->>GW: advanceWorkroom(input)
GW->>WS: advanceWorkroom(input, userId)
WS->>WS: Advance workroom step
WS->>OS: propagateTrackingToOrder(orderId, input)
OS->>OS: $set trackingNumber, trackingUrl, estimatedDeliveryDate
OS->>OS: Auto-transition PROCESSING โ SHIPPED
OS->>AL: Emit ORDER_STATUS_CHANGED (SHIPPED)
AL-->>MO: Push notification
AL-->>MO: Email notification (vertical-branded)
WS-->>FE: Updated Workroom
FE-->>MO: Success banner
Backend DTO
`AdvanceWorkroomInput`
The input DTO for the advanceWorkroom mutation accepts three optional tracking fields alongside the required workroomId:
input AdvanceWorkroomInput {
workroomId: ID!
note: String
trackingNumber: String
trackingUrl: String
estimatedDeliveryDate: DateTime
}
| Field | Type | Validation | Description |
|---|---|---|---|
workroomId |
ID! |
Required, non-empty | Workroom being advanced |
note |
String |
Optional | Seller note for the step |
trackingNumber |
String |
Optional | Carrier tracking number (e.g., UPS, FedEx, USPS) |
trackingUrl |
String |
Optional, @IsUrl() |
Direct tracking link from carrier |
estimatedDeliveryDate |
DateTime |
Optional, @IsDate() |
ISO 8601 estimated delivery date |
Order Model Fields
The Order entity stores tracking data at the document level:
@prop()
trackingNumber?: string;
@prop()
trackingUrl?: string;
@prop()
estimatedDeliveryDate?: Date;
Tracking Propagation Logic
The WorkroomService.propagateTrackingToOrder() method handles the write-through from the Workroom mutation to the Order document:
private async propagateTrackingToOrder(
orderId: string,
input: AdvanceWorkroomInput,
): Promise<void> {
const { trackingNumber, trackingUrl, estimatedDeliveryDate } = input;
// Only propagate if at least one tracking field is present
if (!trackingNumber && !trackingUrl && !estimatedDeliveryDate) return;
const order = await this.orderService.findById(orderId);
if (!order) return; // Graceful degradation โ log warning
// Atomic update for tracking fields
await this.orderModel.findByIdAndUpdate(orderId, {
$set: { trackingNumber, trackingUrl, estimatedDeliveryDate, updatedAt: new Date() }
});
// Auto-transition to SHIPPED if tracking number present + order is PROCESSING
if (trackingNumber && order.status === OrderStatus.PROCESSING) {
await this.orderService.updateStatus(orderId, OrderStatus.SHIPPED);
}
}
Key Design Decisions
- Atomic
$set: Tracking fields are written viafindByIdAndUpdateto avoid MongooseVersionErrorunder concurrency - Conditional transition: Auto-SHIPPED only fires when the order is in
PROCESSINGโ prevents double-transitions fromPENDINGorPAYMENT_AUTHORIZED - Graceful degradation: If the order is not found (!order), the method logs a warning and returns โ it never throws, ensuring the workroom advance itself succeeds
Frontend Integration
TypeScript Interface
// src/lib/queries/workroom.ts
export interface AdvanceWorkroomInput {
workroomId: string;
note?: string;
trackingNumber?: string;
trackingUrl?: string;
estimatedDeliveryDate?: string; // ISO 8601
}
Tracking Form Location
The tracking form lives on the seller's Murchase detail page at:
ngwenya-deck/src/routes/[malet]/manage/orders/[id]/+page.svelte
Visibility Condition
The form renders only when:
let showTrackingForm = $derived(
workroom.status !== WorkroomStatus.COMPLETED &&
workroom.status !== WorkroomStatus.CANCELLED &&
(order.status === OrderStatus.PROCESSING || order.status === OrderStatus.PAYMENT_AUTHORIZED)
);
Mutation Call
const input: AdvanceWorkroomInput = {
workroomId: workroom.id,
note: 'Tracking information added',
trackingNumber: trackingNumber.trim(),
};
if (trackingUrl.trim()) input.trackingUrl = trackingUrl.trim();
if (estimatedDeliveryDate) {
input.estimatedDeliveryDate = new Date(estimatedDeliveryDate).toISOString();
}
const res = await client.request<AdvanceWorkroomResponse>(
ADVANCE_WORKROOM,
{ input, userId: user.id }
);
Test IDs
| Element | data-testid |
|---|---|
| Tracking form container | tracking-form |
| Tracking number input | tracking-number-input |
| Tracking URL input | tracking-url-input |
| Estimated delivery input | tracking-date-input |
| Submit button | submit-tracking-btn |
| Success banner | tracking-success |
Test Coverage
Backend Unit Tests (WorkroomService)
| Test | Assertion |
|---|---|
| Propagate tracking to order | $set with all 3 fields + auto-SHIPPED |
| No propagation without tracking fields | findById not called |
| No auto-SHIPPED if order not PROCESSING | Tracking written, no status change |
| Order not found โ graceful handling | No throw, no crash |
Backend E2E Tests
| Suite | Coverage |
|---|---|
workroom.e2e-spec.ts |
Step advancement lifecycle |
checkout-smoke.e2e-spec.ts |
Cart โ Order โ Workroom + tracking |
Related
- Murchases & Grouping โ Murchase entity, status lifecycle, and grouping system
- Alerts Resilience โ How shipping notifications are dispatched via the Alerts pipeline
- The Deck Operations โ Malet Owner workspace guide