Selegic CRM Docs
ServerDynamic Objects

Hooks & Flows

Pre-flows, post-hooks, relationship hooks, and automation for Dynamic Objects.

Pre-Flows (Automation)

Before a record is written, OperationHandlerService checks for active Flow definitions with PRE_CREATE or PRE_UPDATE triggers:

Use Cases

  • Field defaulting based on other fields
  • Complex validation logic
  • Data normalization

Execution

Pre-flows run in-process using the internal Flow Engine:

const preFlows = await FlowIntegrationService.runPreFlows({
  entity,
  operation: "CREATE",
  data,
  context,
});

Post-Hooks

After successful database operations, standard crudHooks are checked. For Dynamic Objects, hooks are resolved by entity name:

dynamicHooks.register({
  entityMatcher: "Invoice",
  opMatcher: "create",
  stage: "afterSuccess",
  handler: async ({ result, context }) => {
    // Notify external systems
    // Update related records
    // Trigger webhooks
  },
});

Relationship Hooks

When a LOOKUP field is populated, the system checks for cascade behaviors defined in metadata:

Cascade Options

BehaviorDescription
CASCADEDelete related records when parent deleted
RESTRICTPrevent parent deletion if related records exist
SET_NULLSet lookup to NULL on parent delete
NONENo referential action

These are implemented as before hooks that verify foreign key existence.

Hook Context

interface DynamicHookContext {
  entity: string;
  operation: "CREATE" | "UPDATE" | "DELETE";
  params: unknown;
  result?: unknown;
  context: {
    org: string;
    user: User;
    session: Session;
  };
}

Registration

Hooks are registered in hooks.ts or via the factory:

import { registerDynamicHook } from "./factory";

registerDynamicHook(
  { entity: "Invoice", op: "create" },
  {
    before: async (ctx) => {
      // Validate or transform params
      return ctx.params;
    },
    after: async (ctx) => {
      // Side effects
    },
  }
);

On this page