more flow
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s
Build and Publish / BuildAndDeployArm64 (push) Failing after 5s

This commit is contained in:
2026-07-01 12:13:38 +02:00
parent 83986e7a35
commit 4a37cb479c
8 changed files with 85 additions and 9 deletions
+33 -3
View File
@@ -63,7 +63,7 @@ const PlaceOrderVar = "placeOrder"
// RegisterFlowActions registers the order lifecycle actions on reg, driving the
// grain through app and taking payment via provider. Compose with
// flow.RegisterBuiltinHooks(reg) to get the "log"/"webhook" hooks too.
func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvider) {
func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvider, prefCheckers ...EmailPreferenceChecker) {
reg.ActionWithMeta("place_order", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
po, ok := st.Vars[PlaceOrderVar].(*messages.PlaceOrder)
if !ok || po == nil {
@@ -243,7 +243,11 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
ExampleParams: json.RawMessage(`{"carrier":"dropshipper","trackingNumber":"TRACK-123","trackingUri":"https://tracking.example/TRACK-123","lines":[{"reference":"l1","quantity":1}]}`),
})
registerPredicates(reg, app)
var checker EmailPreferenceChecker
if len(prefCheckers) > 0 {
checker = prefCheckers[0]
}
registerPredicates(reg, app, checker)
}
// registerPredicates adds the order gating predicates a step can reference via
@@ -251,7 +255,7 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
// at the moment the step is reached (e.g. only fire a receipt hook once the
// order is captured). Predicates take no params (the engine's When is a bare
// name), so each is a fixed, composable boolean.
func registerPredicates(reg *flow.Registry, app Applier) {
func registerPredicates(reg *flow.Registry, app Applier, prefChecker EmailPreferenceChecker) {
get := func(ctx context.Context, st *flow.State) (*OrderGrain, error) { return app.Get(ctx, st.ID) }
reg.PredicateWithMeta("has_customer_email", func(ctx context.Context, st *flow.State) (bool, error) {
@@ -289,4 +293,30 @@ func registerPredicates(reg *flow.Registry, app Applier) {
}
return o.CapturedAmount-o.RefundedAmount > 0, nil
}, flow.CapabilityMeta{Description: "Run only when captured amount remains to refund."})
// Email consent predicates — gate marketing or order steps when the customer
// has opted out in their profile email preferences.
if prefChecker != nil {
reg.PredicateWithMeta("has_marketing_consent", func(ctx context.Context, st *flow.State) (bool, error) {
o, err := get(ctx, st)
if err != nil {
return false, err
}
if o.CustomerEmail == "" {
return false, nil // no email address -> no consent
}
return prefChecker.Allowed(ctx, o.CustomerEmail, "marketing"), nil
}, flow.CapabilityMeta{Description: "Run only when the customer has consented to marketing emails."})
reg.PredicateWithMeta("has_order_email_consent", func(ctx context.Context, st *flow.State) (bool, error) {
o, err := get(ctx, st)
if err != nil {
return false, err
}
if o.CustomerEmail == "" {
return false, nil // no email address -> cannot receive order emails
}
return prefChecker.Allowed(ctx, o.CustomerEmail, "order"), nil
}, flow.CapabilityMeta{Description: "Run only when the customer has consented to order transactional emails."})
}
}