diff --git a/api/handlers/webhook.go b/api/handlers/webhook.go index 357b669..ba80a57 100644 --- a/api/handlers/webhook.go +++ b/api/handlers/webhook.go @@ -279,7 +279,11 @@ func (h *WebhookHandler) HandleShippo(w http.ResponseWriter, r *http.Request) { if payload.Event != "track_updated" { webhookLog().Info("shippo webhook: ignoring no-tracking event", "event", payload.Event) - w.WriteHeader(http.StatusOK) + writeShippoResponse(w, map[string]any{ + "received": true, + "skipped": "non-tracking event", + "event": payload.Event, + }) return } @@ -288,7 +292,11 @@ func (h *WebhookHandler) HandleShippo(w http.ResponseWriter, r *http.Request) { webhookLog().Warn("shippo webhook: unrecognized status, skipping", "status", payload.Data.TrackingStatus.Status, "tracking_number", payload.Data.TrackingNumber) - w.WriteHeader(http.StatusOK) + writeShippoResponse(w, map[string]any{ + "received": true, + "skipped": "unrecognized status", + "raw_status": payload.Data.TrackingStatus.Status, + }) return } @@ -297,12 +305,21 @@ func (h *WebhookHandler) HandleShippo(w http.ResponseWriter, r *http.Request) { if err := db.Where("tracking_number = ?", payload.Data.TrackingNumber).First(&order).Error; err != nil { webhookLog().Warn("shippo webhook: order not found", "tracking_number", payload.Data.TrackingNumber) - w.WriteHeader(http.StatusOK) + writeShippoResponse(w, map[string]any{ + "received": true, + "skipped": "order not found", + "tracking_number": payload.Data.TrackingNumber, + }) return } if order.TrackingStatusUpdatedAt != nil && !payload.Data.TrackingStatus.StatusDate.After(*order.TrackingStatusUpdatedAt) { - w.WriteHeader(http.StatusOK) + writeShippoResponse(w, map[string]any{ + "received": true, + "skipped": "stale status_date", + "order_id": order.ID, + "current_tracking_status": string(order.TrackingStatus), + }) return } @@ -332,7 +349,15 @@ func (h *WebhookHandler) HandleShippo(w http.ResponseWriter, r *http.Request) { if deliveredTransition { audit.OrderDelivered(order.ID, payload.Data.TrackingNumber) } - w.WriteHeader(http.StatusOK) + writeShippoResponse(w, map[string]any{ + "received": true, + "order_id": order.ID, + "tracking_status": string(newStatus), + "previous_tracking_status": string(previousTrackingStatus), + "lifecycle_status": string(order.Status), + "delivered_transition": deliveredTransition, + "status_details": payload.Data.TrackingStatus.StatusDetails, + }) } func mapShippoStatus(s string) (models.TrackingStatus, bool) { @@ -352,3 +377,9 @@ func mapShippoStatus(s string) (models.TrackingStatus, bool) { } return models.TrackingStatusUnknown, false } + +func writeShippoResponse(w http.ResponseWriter, payload map[string]any) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _ = json.NewEncoder(w).Encode(payload) +} diff --git a/pkg/models/order_display.go b/pkg/models/order_display.go index 2f68c6b..5a21f9e 100644 --- a/pkg/models/order_display.go +++ b/pkg/models/order_display.go @@ -31,16 +31,16 @@ func (order *Order) DisplayState() string { case OrderStatusShipped: switch order.TrackingStatus { case TrackingStatusTransit: - return "Shipped * in transit" + return "In Transit" case TrackingStatusFailure: - return "Shipped * delivery issue" + return "Delivery Issue" case TrackingStatusReturned: - return "Shipped * returned to sender" + return "Returned to Sender" case TrackingStatusDelivered: // Webhook hasn't promoted Status yet, trust tracking return "Delivered" } - return "Shipped" + return "Label Created" case OrderStatusDelivered: return "Delivered" case OrderStatusCancelled: diff --git a/pkg/models/order_display_test.go b/pkg/models/order_display_test.go index 02a75f6..d81d63e 100644 --- a/pkg/models/order_display_test.go +++ b/pkg/models/order_display_test.go @@ -13,10 +13,11 @@ func TestOrderDisplayState(t *testing.T) { {"paid no tracking", Order{Status: OrderStatusPaid}, "Paid * awaiting label", DisplayKindAccent}, {"paid with tracking, no event", Order{Status: OrderStatusPaid, TrackingNumber: "12999"}, "Paid", DisplayKindAccent}, {"Paid pre-transit", Order{Status: OrderStatusPaid, TrackingNumber: "12999", TrackingStatus: TrackingStatusPreTransit}, "Paid * ready to ship", DisplayKindAccent}, - {"shipped no tracking event", Order{Status: OrderStatusShipped}, "Shipped", DisplayKindBrand}, - {"shipped in transit", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusTransit}, "Shipped * in transit", DisplayKindBrand}, - {"shipped failure", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusFailure}, "Shipped * delivery issue", DisplayKindWarning}, - {"shipped returned", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusReturned}, "Shipped * returned to sender", DisplayKindWarning}, + {"shipped no tracking event", Order{Status: OrderStatusShipped}, "Label Created", DisplayKindBrand}, + {"shipped pre-transit", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusPreTransit}, "Label Created", DisplayKindBrand}, + {"shipped in transit", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusTransit}, "In Transit", DisplayKindBrand}, + {"shipped failure", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusFailure}, "Delivery Issue", DisplayKindWarning}, + {"shipped returned", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusReturned}, "Returned to Sender", DisplayKindWarning}, {"shipped tracking-delivered (webhook lag)", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusDelivered}, "Delivered", DisplayKindSuccess}, {"delivered", Order{Status: OrderStatusDelivered}, "Delivered", DisplayKindSuccess}, {"cancelled", Order{Status: OrderStatusCancelled}, "Cancelled", DisplayKindError}, diff --git a/pkg/tui/account_orders.go b/pkg/tui/account_orders.go index 98b8beb..e03162b 100644 --- a/pkg/tui/account_orders.go +++ b/pkg/tui/account_orders.go @@ -104,6 +104,10 @@ func (m Model) buildOrderDetailView(order models.Order, _ int) string { b.WriteString(labelStyle.Render("Status: ")) b.WriteString(m.displayStyle(order.DisplayKind()).Render(order.DisplayState())) b.WriteString("\n") + if order.TrackingStatusDetails != "" { + b.WriteString(dimStyle.Render(" " + order.TrackingStatusDetails)) + b.WriteString("\n") + } b.WriteString(labelStyle.Render("Date: ")) b.WriteString(valueStyle.Render(order.CreatedAt.Format("Jan 02 2006 3:04 PM"))) b.WriteString("\n\n")