package main import ( "context" "encoding/json" "fmt" "log/slog" "git.k6n.net/mats/go-cart-actor/pkg/flow" "git.k6n.net/mats/go-cart-actor/pkg/order" ) type projectFulfillmentHookParams struct { Integration string `json:"integration,omitempty"` Target string `json:"target,omitempty"` Dropship bool `json:"dropship,omitempty"` } // registerProjectFlowHooks is the project-layer seam for customer-specific flow // integrations. These belong here rather than pkg/order so core order logic // stays generic while deployments can register their own fulfillment tools. func registerProjectFlowHooks(reg *flow.Registry, app *orderedApplier, logger *slog.Logger) { if logger == nil { logger = slog.Default() } reg.HookWithMeta("project_fulfillment_integration", func(ctx context.Context, st *flow.State, info flow.HookInfo, params json.RawMessage) error { var p projectFulfillmentHookParams if len(params) > 0 { if err := json.Unmarshal(params, &p); err != nil { return fmt.Errorf("project_fulfillment_integration: bad params: %w", err) } } if p.Integration == "" { p.Integration = "order-integration" } o, err := app.Get(ctx, st.ID) if err != nil { return err } if len(o.Fulfillments) == 0 { return fmt.Errorf("project_fulfillment_integration: order %s has no fulfillment yet", order.OrderId(st.ID).String()) } last := o.Fulfillments[len(o.Fulfillments)-1] log := st.Logger if log == nil { log = logger } log.Info("project fulfillment integration", "orderId", order.OrderId(st.ID).String(), "orderReference", o.OrderReference, "customerEmail", o.CustomerEmail, "integration", p.Integration, "target", p.Target, "dropship", p.Dropship, "step", info.Step, "phase", info.Phase, "fulfillmentId", last.ID, "carrier", last.Carrier, "trackingNumber", last.TrackingNumber, ) return nil }, flow.CapabilityMeta{ Description: "Project-specific fulfillment integration seam for local or testing adapters.", ExampleParams: json.RawMessage(`{"integration":"dropship-test","target":"erp-sandbox","dropship":true}`), }) }