mirror of
https://github.com/hanzoai/commerce.git
synced 2026-10-30 15:08:42 +00:00
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
101 lines
3.0 KiB
Go
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()
|
|
}
|