Files
commerce/thirdparty/shipwire/api/tracking.go
zeekay 1943f1c093 Hanzo Commerce
Multi-tenant commerce and billing: orders, subscriptions, invoices, plans,
usage metering and a credit ledger. One Go binary. MIT OR Apache-2.0.

Claude-Session: https://claude.ai/code/session_01SAtaDFm8VDiWrhYHNNtxMw
2026-09-23 21:52:16 -07:00

101 lines
3.0 KiB
Go

package api
import (
"fmt"
"strconv"
"github.com/zap-proto/zip"
"github.com/hanzoai/commerce/datastore"
"github.com/hanzoai/commerce/log"
"github.com/hanzoai/commerce/middleware"
"github.com/hanzoai/commerce/models/order"
"github.com/hanzoai/commerce/models/organization"
"github.com/hanzoai/commerce/models/types/fulfillment"
"github.com/hanzoai/commerce/thirdparty/shipwire"
. "github.com/hanzoai/commerce/thirdparty/shipwire/types"
)
func convertTracking(t Tracking) fulfillment.Tracking {
trk := fulfillment.Tracking{}
trk.Number = t.Tracking
trk.ExternalId = strconv.Itoa(t.ID)
trk.Url = t.Url
trk.Carrier = t.Carrier
trk.Summary = t.Summary
trk.FirstScanRegion = t.FirstScanRegion
trk.FirstScanPostalCode = t.FirstScanPostalCode
trk.FirstScanCountry = t.FirstScanCountry
trk.DeliveryCity = t.DeliveryCity
trk.DeliveryRegion = t.DeliveryRegion
trk.DeliveryPostalCode = t.DeliveryPostalCode
trk.DeliveryCountry = t.DeliveryCountry
trk.CreatedAt = t.TrackedDate.Time
trk.DeliveredAt = t.DeliveredDate.Time
trk.FirstScanAt = t.FirstScanDate.Time
trk.LabelCreatedAt = t.LabelCreatedDate.Time
trk.SummaryAt = t.SummaryDate.Time
return trk
}
func getOrderFromShipwire(c *zip.Ctx, org *organization.Organization, ord *order.Order, id int) error {
client := shipwire.New(c, org.Shipwire.Username, org.Shipwire.Password)
o, res, err := client.GetOrder(id)
if res.Status < 300 && err != nil {
// Try using order number
log.Info("Looking up order via order number: %s", o.OrderNo, c)
return ord.GetById(o.OrderNo)
}
log.Warn("Failed to fetch Shipwire order", c)
return fmt.Errorf("No matching order found for Shipwire order %d", id)
}
func getOrderForTracking(c *zip.Ctx, t Tracking) (*order.Order, error) {
org := middleware.GetOrganization(c)
db := datastore.New(org.Namespaced(c.Context()))
ord := order.New(db)
log.Info("Looking up order using OrderExternalID", c)
id := t.OrderExternalID
err := ord.GetById(id)
if err != nil {
log.Info("Fetching Shipwire order to lookup order by order number", c)
err = getOrderFromShipwire(c, org, ord, t.OrderID)
}
return ord, nil
}
func updateOrderTracking(ord *order.Order, t Tracking) {
// Check if we know about this tracking object already
for i, trk := range ord.Fulfillment.Trackings {
if trk.ExternalId == strconv.Itoa(t.ID) {
log.Info("Found existing tracking object, updating")
ord.Fulfillment.Trackings[i] = convertTracking(t)
return
}
}
// New tracking information, append
log.Info("New tracking information")
ord.Fulfillment.Trackings = append(ord.Fulfillment.Trackings, convertTracking(t))
}
func updateTracking(c *zip.Ctx, topic string, t Tracking) {
log.Info("Fetching order associated with tracking %s", t.ID, c)
ord, err := getOrderForTracking(c, t)
if err != nil {
log.Warn("Unable to find order for tracking '%s': %v", t.ID, err, c)
return
}
log.Info("Found order: %s, updating tracking", ord.Id(), c)
updateOrderTracking(ord, t)
log.Info("Saving order", c)
ord.MustPut()
}