@open-mercato/core 0.4.2-canary-ed15f2e753 → 0.4.2-canary-f075c3eb92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/entities.ids.generated.js +0 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_keys/setup.js +11 -0
- package/dist/modules/api_keys/setup.js.map +7 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js +1 -1
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/lib/assignmentDetails.js +31 -17
- package/dist/modules/attachments/lib/assignmentDetails.js.map +2 -2
- package/dist/modules/attachments/lib/partitions.js +3 -3
- package/dist/modules/attachments/lib/partitions.js.map +2 -2
- package/dist/modules/attachments/setup.js +11 -0
- package/dist/modules/attachments/setup.js.map +7 -0
- package/dist/modules/audit_logs/setup.js +12 -0
- package/dist/modules/audit_logs/setup.js.map +7 -0
- package/dist/modules/auth/lib/setup-app.js +29 -159
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/setup.js +11 -0
- package/dist/modules/auth/setup.js.map +7 -0
- package/dist/modules/business_rules/data/validators.js +0 -34
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +1 -21
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +1 -182
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/setup.js +11 -0
- package/dist/modules/business_rules/setup.js.map +7 -0
- package/dist/modules/catalog/setup.js +22 -0
- package/dist/modules/catalog/setup.js.map +7 -0
- package/dist/modules/configs/lib/upgrade-actions.js +65 -15
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/configs/setup.js +16 -0
- package/dist/modules/configs/setup.js.map +7 -0
- package/dist/modules/currencies/setup.js +16 -0
- package/dist/modules/currencies/setup.js.map +7 -0
- package/dist/modules/customers/setup.js +36 -0
- package/dist/modules/customers/setup.js.map +7 -0
- package/dist/modules/dashboards/setup.js +12 -0
- package/dist/modules/dashboards/setup.js.map +7 -0
- package/dist/modules/dictionaries/setup.js +12 -0
- package/dist/modules/dictionaries/setup.js.map +7 -0
- package/dist/modules/directory/setup.js +12 -0
- package/dist/modules/directory/setup.js.map +7 -0
- package/dist/modules/entities/setup.js +11 -0
- package/dist/modules/entities/setup.js.map +7 -0
- package/dist/modules/feature_toggles/setup.js +11 -0
- package/dist/modules/feature_toggles/setup.js.map +7 -0
- package/dist/modules/perspectives/setup.js +12 -0
- package/dist/modules/perspectives/setup.js.map +7 -0
- package/dist/modules/planner/setup.js +21 -0
- package/dist/modules/planner/setup.js.map +7 -0
- package/dist/modules/query_index/setup.js +11 -0
- package/dist/modules/query_index/setup.js.map +7 -0
- package/dist/modules/resources/setup.js +21 -0
- package/dist/modules/resources/setup.js.map +7 -0
- package/dist/modules/sales/acl.js +0 -1
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +0 -12
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -62
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +0 -3
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/setup.js +99 -0
- package/dist/modules/sales/setup.js.map +7 -0
- package/dist/modules/staff/setup.js +27 -0
- package/dist/modules/staff/setup.js.map +7 -0
- package/dist/modules/workflows/acl.js +0 -2
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +6 -18
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +1 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -9
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +15 -24
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +132 -150
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +6 -5
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +3 -81
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/data/entities.js +1 -64
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +0 -115
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/dist/modules/workflows/lib/activity-executor.js +13 -75
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +2 -71
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +7 -36
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +23 -33
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +45 -157
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/dist/modules/workflows/migrations/Migration20251207131955.js +76 -72
- package/dist/modules/workflows/migrations/Migration20251207131955.js.map +2 -2
- package/dist/modules/workflows/setup.js +16 -0
- package/dist/modules/workflows/setup.js.map +7 -0
- package/generated/entities.ids.generated.ts +0 -1
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/__tests__/module-decoupling.test.ts +356 -0
- package/src/modules/api_keys/setup.ts +9 -0
- package/src/modules/attachments/components/AttachmentLibrary.tsx +2 -2
- package/src/modules/attachments/lib/assignmentDetails.ts +32 -16
- package/src/modules/attachments/lib/partitions.ts +3 -3
- package/src/modules/attachments/setup.ts +9 -0
- package/src/modules/audit_logs/setup.ts +10 -0
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +30 -0
- package/src/modules/auth/lib/setup-app.ts +40 -177
- package/src/modules/auth/setup.ts +9 -0
- package/src/modules/business_rules/data/validators.ts +0 -40
- package/src/modules/business_rules/index.ts +0 -25
- package/src/modules/business_rules/lib/rule-engine.ts +1 -281
- package/src/modules/business_rules/setup.ts +9 -0
- package/src/modules/catalog/setup.ts +22 -0
- package/src/modules/configs/lib/upgrade-actions.ts +78 -17
- package/src/modules/configs/setup.ts +14 -0
- package/src/modules/currencies/setup.ts +15 -0
- package/src/modules/customers/setup.ts +36 -0
- package/src/modules/dashboards/setup.ts +10 -0
- package/src/modules/dictionaries/setup.ts +10 -0
- package/src/modules/directory/setup.ts +10 -0
- package/src/modules/entities/setup.ts +9 -0
- package/src/modules/feature_toggles/setup.ts +9 -0
- package/src/modules/perspectives/setup.ts +10 -0
- package/src/modules/planner/setup.ts +21 -0
- package/src/modules/query_index/setup.ts +9 -0
- package/src/modules/resources/setup.ts +21 -0
- package/src/modules/sales/acl.ts +0 -1
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +0 -16
- package/src/modules/sales/commands/documents.ts +1 -74
- package/src/modules/sales/lib/dictionaries.ts +0 -3
- package/src/modules/sales/setup.ts +108 -0
- package/src/modules/staff/setup.ts +27 -0
- package/src/modules/workflows/acl.ts +0 -2
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +2 -5
- package/src/modules/workflows/api/instances/route.ts +7 -21
- package/src/modules/workflows/api/tasks/route.ts +1 -7
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -21
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +6 -5
- package/src/modules/workflows/cli.ts +0 -111
- package/src/modules/workflows/data/entities.ts +0 -124
- package/src/modules/workflows/data/validators.ts +0 -138
- package/src/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/src/modules/workflows/i18n/en.json +0 -71
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +36 -43
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +90 -170
- package/src/modules/workflows/lib/activity-executor.ts +16 -129
- package/src/modules/workflows/lib/graph-utils.ts +2 -117
- package/src/modules/workflows/lib/seeds.ts +12 -50
- package/src/modules/workflows/lib/start-validator.ts +28 -38
- package/src/modules/workflows/lib/transition-handler.ts +55 -208
- package/src/modules/workflows/migrations/Migration20251207131955.ts +77 -143
- package/src/modules/workflows/setup.ts +15 -0
- package/dist/generated/entities/workflow_event_trigger/index.js +0 -33
- package/dist/generated/entities/workflow_event_trigger/index.js.map +0 -7
- package/dist/modules/auth/events.js +0 -30
- package/dist/modules/auth/events.js.map +0 -7
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +0 -145
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +0 -7
- package/dist/modules/catalog/events.js +0 -34
- package/dist/modules/catalog/events.js.map +0 -7
- package/dist/modules/customers/events.js +0 -49
- package/dist/modules/customers/events.js.map +0 -7
- package/dist/modules/directory/events.js +0 -23
- package/dist/modules/directory/events.js.map +0 -7
- package/dist/modules/sales/events.js +0 -63
- package/dist/modules/sales/events.js.map +0 -7
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +0 -25
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +0 -7
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +0 -481
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/components/EventTriggersEditor.js +0 -553
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/events.js +0 -38
- package/dist/modules/workflows/events.js.map +0 -7
- package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/dist/modules/workflows/lib/event-trigger-service.js +0 -308
- package/dist/modules/workflows/lib/event-trigger-service.js.map +0 -7
- package/dist/modules/workflows/migrations/Migration20260123143500.js +0 -36
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +0 -7
- package/dist/modules/workflows/subscribers/event-trigger.js +0 -78
- package/dist/modules/workflows/subscribers/event-trigger.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +0 -323
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +0 -17
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +0 -7
- package/dist/modules/workflows/widgets/injection-table.js +0 -19
- package/dist/modules/workflows/widgets/injection-table.js.map +0 -7
- package/generated/entities/workflow_event_trigger/index.ts +0 -15
- package/src/modules/auth/events.ts +0 -39
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +0 -163
- package/src/modules/catalog/events.ts +0 -45
- package/src/modules/customers/events.ts +0 -63
- package/src/modules/directory/events.ts +0 -31
- package/src/modules/sales/events.ts +0 -82
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +0 -28
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +0 -581
- package/src/modules/workflows/components/EventTriggersEditor.tsx +0 -664
- package/src/modules/workflows/events.ts +0 -49
- package/src/modules/workflows/examples/order-approval-definition.json +0 -257
- package/src/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/src/modules/workflows/lib/event-trigger-service.ts +0 -557
- package/src/modules/workflows/migrations/Migration20260123143500.ts +0 -38
- package/src/modules/workflows/subscribers/event-trigger.ts +0 -109
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +0 -446
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +0 -16
- package/src/modules/workflows/widgets/injection-table.ts +0 -21
|
@@ -4,12 +4,8 @@ import { Role, RoleAcl, User, UserRole } from '@open-mercato/core/modules/auth/d
|
|
|
4
4
|
import { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'
|
|
5
5
|
import { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'
|
|
6
6
|
import { normalizeTenantId } from './tenantAccess'
|
|
7
|
-
import { SalesSettings, SalesDocumentSequence } from '@open-mercato/core/modules/sales/data/entities'
|
|
8
|
-
import {
|
|
9
|
-
DEFAULT_ORDER_NUMBER_FORMAT,
|
|
10
|
-
DEFAULT_QUOTE_NUMBER_FORMAT,
|
|
11
|
-
} from '@open-mercato/core/modules/sales/lib/documentNumberTokens'
|
|
12
7
|
import { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'
|
|
8
|
+
import type { Module } from '@open-mercato/shared/modules/registry'
|
|
13
9
|
import { isEncryptionDebugEnabled, isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'
|
|
14
10
|
import { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'
|
|
15
11
|
import { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'
|
|
@@ -95,6 +91,8 @@ export type SetupInitialTenantOptions = {
|
|
|
95
91
|
failIfUserExists?: boolean
|
|
96
92
|
primaryUserRoles?: string[]
|
|
97
93
|
includeSuperadminRole?: boolean
|
|
94
|
+
/** Optional list of enabled modules. When provided, module setup hooks are called. */
|
|
95
|
+
modules?: Module[]
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
export type SetupInitialTenantResult = {
|
|
@@ -321,9 +319,16 @@ export async function setupInitialTenant(
|
|
|
321
319
|
await rebuildHierarchyForTenant(em, tenantId)
|
|
322
320
|
}
|
|
323
321
|
|
|
324
|
-
|
|
322
|
+
const resolvedModules = options.modules ?? tryGetModules()
|
|
323
|
+
await ensureDefaultRoleAcls(em, tenantId, resolvedModules, { includeSuperadminRole })
|
|
325
324
|
await deactivateDemoSuperAdminIfSelfOnboardingEnabled(em)
|
|
326
|
-
|
|
325
|
+
|
|
326
|
+
// Call module onTenantCreated hooks
|
|
327
|
+
for (const mod of resolvedModules) {
|
|
328
|
+
if (mod.setup?.onTenantCreated) {
|
|
329
|
+
await mod.setup.onTenantCreated({ em, tenantId, organizationId })
|
|
330
|
+
}
|
|
331
|
+
}
|
|
327
332
|
|
|
328
333
|
return {
|
|
329
334
|
tenantId,
|
|
@@ -349,6 +354,7 @@ async function resolvePasswordHash(input: PrimaryUserInput): Promise<string | nu
|
|
|
349
354
|
async function ensureDefaultRoleAcls(
|
|
350
355
|
em: EntityManager,
|
|
351
356
|
tenantId: string,
|
|
357
|
+
modules: Module[],
|
|
352
358
|
options: { includeSuperadminRole?: boolean } = {},
|
|
353
359
|
) {
|
|
354
360
|
const includeSuperadminRole = options.includeSuperadminRole ?? true
|
|
@@ -357,84 +363,27 @@ async function ensureDefaultRoleAcls(
|
|
|
357
363
|
const adminRole = await findRoleByName(em, 'admin', roleTenantId)
|
|
358
364
|
const employeeRole = await findRoleByName(em, 'employee', roleTenantId)
|
|
359
365
|
|
|
366
|
+
// Merge features from all enabled modules' setup configs
|
|
367
|
+
const superadminFeatures: string[] = []
|
|
368
|
+
const adminFeatures: string[] = []
|
|
369
|
+
const employeeFeatures: string[] = []
|
|
370
|
+
|
|
371
|
+
for (const mod of modules) {
|
|
372
|
+
const roleFeatures = mod.setup?.defaultRoleFeatures
|
|
373
|
+
if (!roleFeatures) continue
|
|
374
|
+
if (roleFeatures.superadmin) superadminFeatures.push(...roleFeatures.superadmin)
|
|
375
|
+
if (roleFeatures.admin) adminFeatures.push(...roleFeatures.admin)
|
|
376
|
+
if (roleFeatures.employee) employeeFeatures.push(...roleFeatures.employee)
|
|
377
|
+
}
|
|
378
|
+
|
|
360
379
|
if (includeSuperadminRole && superadminRole) {
|
|
361
|
-
await ensureRoleAclFor(em, superadminRole, tenantId,
|
|
380
|
+
await ensureRoleAclFor(em, superadminRole, tenantId, superadminFeatures, { isSuperAdmin: true })
|
|
362
381
|
}
|
|
363
382
|
if (adminRole) {
|
|
364
|
-
|
|
365
|
-
'auth.*',
|
|
366
|
-
'entities.*',
|
|
367
|
-
'attachments.*',
|
|
368
|
-
'attachments.view',
|
|
369
|
-
'attachments.manage',
|
|
370
|
-
'query_index.*',
|
|
371
|
-
'search.*',
|
|
372
|
-
'vector.*',
|
|
373
|
-
'feature_toggles.*',
|
|
374
|
-
'configs.system_status.view',
|
|
375
|
-
'configs.cache.view',
|
|
376
|
-
'configs.cache.manage',
|
|
377
|
-
'configs.manage',
|
|
378
|
-
'catalog.*',
|
|
379
|
-
'catalog.variants.manage',
|
|
380
|
-
'catalog.pricing.manage',
|
|
381
|
-
'sales.*',
|
|
382
|
-
'audit_logs.*',
|
|
383
|
-
'directory.organizations.view',
|
|
384
|
-
'directory.organizations.manage',
|
|
385
|
-
'customers.*',
|
|
386
|
-
'customers.people.view',
|
|
387
|
-
'customers.people.manage',
|
|
388
|
-
'customers.companies.view',
|
|
389
|
-
'customers.companies.manage',
|
|
390
|
-
'customers.deals.view',
|
|
391
|
-
'customers.deals.manage',
|
|
392
|
-
'dictionaries.view',
|
|
393
|
-
'dictionaries.manage',
|
|
394
|
-
'example.*',
|
|
395
|
-
'dashboards.*',
|
|
396
|
-
'dashboards.admin.assign-widgets',
|
|
397
|
-
'analytics.view',
|
|
398
|
-
'api_keys.*',
|
|
399
|
-
'perspectives.use',
|
|
400
|
-
'perspectives.role_defaults',
|
|
401
|
-
'business_rules.*',
|
|
402
|
-
'workflows.*',
|
|
403
|
-
'currencies.*',
|
|
404
|
-
'staff.*',
|
|
405
|
-
'staff.leave_requests.manage',
|
|
406
|
-
'resources.*',
|
|
407
|
-
'planner.*',
|
|
408
|
-
]
|
|
409
|
-
await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures, { remove: ['directory.organizations.*', 'directory.tenants.*'] })
|
|
383
|
+
await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures)
|
|
410
384
|
}
|
|
411
385
|
if (employeeRole) {
|
|
412
|
-
await ensureRoleAclFor(em, employeeRole, tenantId,
|
|
413
|
-
'customers.*',
|
|
414
|
-
'customers.people.view',
|
|
415
|
-
'customers.people.manage',
|
|
416
|
-
'customers.companies.view',
|
|
417
|
-
'customers.companies.manage',
|
|
418
|
-
'vector.*',
|
|
419
|
-
'catalog.*',
|
|
420
|
-
'catalog.variants.manage',
|
|
421
|
-
'catalog.pricing.manage',
|
|
422
|
-
'sales.*',
|
|
423
|
-
'dictionaries.view',
|
|
424
|
-
'example.*',
|
|
425
|
-
'example.widgets.*',
|
|
426
|
-
'dashboards.view',
|
|
427
|
-
'dashboards.configure',
|
|
428
|
-
'analytics.view',
|
|
429
|
-
'audit_logs.undo_self',
|
|
430
|
-
'perspectives.use',
|
|
431
|
-
'staff.leave_requests.send',
|
|
432
|
-
'staff.my_availability.view',
|
|
433
|
-
'staff.my_availability.manage',
|
|
434
|
-
'staff.my_leave_requests.view',
|
|
435
|
-
'staff.my_leave_requests.send',
|
|
436
|
-
'planner.view',
|
|
437
|
-
])
|
|
386
|
+
await ensureRoleAclFor(em, employeeRole, tenantId, employeeFeatures)
|
|
438
387
|
}
|
|
439
388
|
}
|
|
440
389
|
|
|
@@ -443,7 +392,7 @@ async function ensureRoleAclFor(
|
|
|
443
392
|
role: Role,
|
|
444
393
|
tenantId: string,
|
|
445
394
|
features: string[],
|
|
446
|
-
options: { isSuperAdmin?: boolean
|
|
395
|
+
options: { isSuperAdmin?: boolean } = {},
|
|
447
396
|
) {
|
|
448
397
|
const existing = await em.findOne(RoleAcl, { role, tenantId })
|
|
449
398
|
if (!existing) {
|
|
@@ -459,24 +408,10 @@ async function ensureRoleAclFor(
|
|
|
459
408
|
}
|
|
460
409
|
const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []
|
|
461
410
|
const merged = Array.from(new Set([...currentFeatures, ...features]))
|
|
462
|
-
const removeSet = new Set(options.remove ?? [])
|
|
463
|
-
const sanitized =
|
|
464
|
-
removeSet.size
|
|
465
|
-
? merged.filter((value) => {
|
|
466
|
-
if (removeSet.has(value)) return false
|
|
467
|
-
for (const entry of removeSet) {
|
|
468
|
-
if (entry.endsWith('.*')) {
|
|
469
|
-
const prefix = entry.slice(0, -1) // keep trailing dot
|
|
470
|
-
if (value === entry || value.startsWith(prefix)) return false
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return true
|
|
474
|
-
})
|
|
475
|
-
: merged
|
|
476
411
|
const changed =
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (changed) existing.featuresJson =
|
|
412
|
+
merged.length !== currentFeatures.length ||
|
|
413
|
+
merged.some((value, index) => value !== currentFeatures[index])
|
|
414
|
+
if (changed) existing.featuresJson = merged
|
|
480
415
|
if (options.isSuperAdmin && !existing.isSuperAdmin) {
|
|
481
416
|
existing.isSuperAdmin = true
|
|
482
417
|
}
|
|
@@ -507,84 +442,12 @@ async function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em: EntityManager
|
|
|
507
442
|
}
|
|
508
443
|
}
|
|
509
444
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
tenantId: scope.tenantId,
|
|
518
|
-
organizationId: scope.organizationId,
|
|
519
|
-
}) ??
|
|
520
|
-
(em as any).findOne?.(SalesSettings, {
|
|
521
|
-
tenantId: scope.tenantId,
|
|
522
|
-
organizationId: scope.organizationId,
|
|
523
|
-
})
|
|
524
|
-
|
|
525
|
-
const exists = await findSettings()
|
|
526
|
-
if (!exists) {
|
|
527
|
-
const settings =
|
|
528
|
-
repo?.create?.({
|
|
529
|
-
tenantId: scope.tenantId,
|
|
530
|
-
organizationId: scope.organizationId,
|
|
531
|
-
orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,
|
|
532
|
-
quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,
|
|
533
|
-
createdAt: new Date(),
|
|
534
|
-
updatedAt: new Date(),
|
|
535
|
-
}) ??
|
|
536
|
-
(em as any).create?.(SalesSettings, {
|
|
537
|
-
tenantId: scope.tenantId,
|
|
538
|
-
organizationId: scope.organizationId,
|
|
539
|
-
orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,
|
|
540
|
-
quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,
|
|
541
|
-
createdAt: new Date(),
|
|
542
|
-
updatedAt: new Date(),
|
|
543
|
-
})
|
|
544
|
-
if (settings && (em as any).persist) {
|
|
545
|
-
em.persist(settings)
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const sequenceRepo = (em as any).getRepository?.(SalesDocumentSequence)
|
|
550
|
-
const kinds: Array<'order' | 'quote'> = ['order', 'quote']
|
|
551
|
-
for (const kind of kinds) {
|
|
552
|
-
const seq =
|
|
553
|
-
sequenceRepo?.findOne({
|
|
554
|
-
tenantId: scope.tenantId,
|
|
555
|
-
organizationId: scope.organizationId,
|
|
556
|
-
documentKind: kind,
|
|
557
|
-
}) ??
|
|
558
|
-
(em as any).findOne?.(SalesDocumentSequence, {
|
|
559
|
-
tenantId: scope.tenantId,
|
|
560
|
-
organizationId: scope.organizationId,
|
|
561
|
-
documentKind: kind,
|
|
562
|
-
})
|
|
563
|
-
if (!seq) {
|
|
564
|
-
const entry =
|
|
565
|
-
sequenceRepo?.create?.({
|
|
566
|
-
tenantId: scope.tenantId,
|
|
567
|
-
organizationId: scope.organizationId,
|
|
568
|
-
documentKind: kind,
|
|
569
|
-
currentValue: 0,
|
|
570
|
-
createdAt: new Date(),
|
|
571
|
-
updatedAt: new Date(),
|
|
572
|
-
}) ??
|
|
573
|
-
(em as any).create?.(SalesDocumentSequence, {
|
|
574
|
-
tenantId: scope.tenantId,
|
|
575
|
-
organizationId: scope.organizationId,
|
|
576
|
-
documentKind: kind,
|
|
577
|
-
currentValue: 0,
|
|
578
|
-
createdAt: new Date(),
|
|
579
|
-
updatedAt: new Date(),
|
|
580
|
-
})
|
|
581
|
-
if (entry && (em as any).persist) {
|
|
582
|
-
em.persist(entry)
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if ((em as any).flush) {
|
|
588
|
-
await em.flush()
|
|
445
|
+
/** Try to get modules from runtime registry; returns empty array if not yet registered. */
|
|
446
|
+
function tryGetModules(): Module[] {
|
|
447
|
+
try {
|
|
448
|
+
const { getModules } = require('@open-mercato/shared/lib/modules/registry')
|
|
449
|
+
return getModules()
|
|
450
|
+
} catch {
|
|
451
|
+
return []
|
|
589
452
|
}
|
|
590
453
|
}
|
|
@@ -287,43 +287,3 @@ export const ruleDiscoveryOptionsSchema = z.object({
|
|
|
287
287
|
})
|
|
288
288
|
|
|
289
289
|
export type RuleDiscoveryOptionsInput = z.infer<typeof ruleDiscoveryOptionsSchema>
|
|
290
|
-
|
|
291
|
-
// Direct Rule Execution Context Schema (for executing a specific rule by ID)
|
|
292
|
-
export const directRuleExecutionContextSchema = z.object({
|
|
293
|
-
ruleId: z.uuid('ruleId must be a valid UUID'),
|
|
294
|
-
data: z.any(),
|
|
295
|
-
user: z.looseObject({
|
|
296
|
-
id: z.string().optional(),
|
|
297
|
-
email: z.string().optional(),
|
|
298
|
-
role: z.string().optional(),
|
|
299
|
-
}).optional(),
|
|
300
|
-
tenantId: z.uuid('tenantId must be a valid UUID'),
|
|
301
|
-
organizationId: z.uuid('organizationId must be a valid UUID'),
|
|
302
|
-
executedBy: z.string().optional(),
|
|
303
|
-
dryRun: z.boolean().optional(),
|
|
304
|
-
entityType: z.string().optional(),
|
|
305
|
-
entityId: z.string().optional(),
|
|
306
|
-
eventType: z.string().optional(),
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
export type DirectRuleExecutionContextInput = z.infer<typeof directRuleExecutionContextSchema>
|
|
310
|
-
|
|
311
|
-
// Rule ID Execution Context Schema (for executing a specific rule by its string rule_id identifier)
|
|
312
|
-
export const ruleIdExecutionContextSchema = z.object({
|
|
313
|
-
ruleId: z.string().min(1, 'ruleId must be a non-empty string').max(50),
|
|
314
|
-
data: z.any(),
|
|
315
|
-
user: z.looseObject({
|
|
316
|
-
id: z.string().optional(),
|
|
317
|
-
email: z.string().optional(),
|
|
318
|
-
role: z.string().optional(),
|
|
319
|
-
}).optional(),
|
|
320
|
-
tenantId: z.uuid('tenantId must be a valid UUID'),
|
|
321
|
-
organizationId: z.uuid('organizationId must be a valid UUID'),
|
|
322
|
-
executedBy: z.string().optional(),
|
|
323
|
-
dryRun: z.boolean().optional(),
|
|
324
|
-
entityType: z.string().optional(),
|
|
325
|
-
entityId: z.string().optional(),
|
|
326
|
-
eventType: z.string().optional(),
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
export type RuleIdExecutionContextInput = z.infer<typeof ruleIdExecutionContextSchema>
|
|
@@ -8,28 +8,3 @@ export const metadata: ModuleInfo = {
|
|
|
8
8
|
author: 'Patryk Lewczuk',
|
|
9
9
|
license: 'Proprietary',
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
// Export rule engine types and functions for programmatic usage
|
|
13
|
-
export {
|
|
14
|
-
executeRules,
|
|
15
|
-
executeRuleById,
|
|
16
|
-
executeRuleByRuleId,
|
|
17
|
-
executeSingleRule,
|
|
18
|
-
findApplicableRules,
|
|
19
|
-
logRuleExecution,
|
|
20
|
-
type RuleEngineContext,
|
|
21
|
-
type RuleEngineResult,
|
|
22
|
-
type RuleExecutionResult,
|
|
23
|
-
type RuleDiscoveryOptions,
|
|
24
|
-
type DirectRuleExecutionContext,
|
|
25
|
-
type DirectRuleExecutionResult,
|
|
26
|
-
type RuleIdExecutionContext,
|
|
27
|
-
} from './lib/rule-engine'
|
|
28
|
-
|
|
29
|
-
// Export validator schemas
|
|
30
|
-
export {
|
|
31
|
-
directRuleExecutionContextSchema,
|
|
32
|
-
ruleIdExecutionContextSchema,
|
|
33
|
-
type DirectRuleExecutionContextInput,
|
|
34
|
-
type RuleIdExecutionContextInput,
|
|
35
|
-
} from './data/validators'
|
|
@@ -4,7 +4,7 @@ import * as ruleEvaluator from './rule-evaluator'
|
|
|
4
4
|
import * as actionExecutor from './action-executor'
|
|
5
5
|
import type { RuleEvaluationContext } from './rule-evaluator'
|
|
6
6
|
import type { ActionContext, ActionExecutionOutcome } from './action-executor'
|
|
7
|
-
import { ruleEngineContextSchema, ruleDiscoveryOptionsSchema
|
|
7
|
+
import { ruleEngineContextSchema, ruleDiscoveryOptionsSchema } from '../data/validators'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Constants
|
|
@@ -85,65 +85,6 @@ export interface RuleDiscoveryOptions {
|
|
|
85
85
|
ruleType?: RuleType
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
/**
|
|
89
|
-
* Direct rule execution context (for executing a specific rule by ID)
|
|
90
|
-
*/
|
|
91
|
-
export interface DirectRuleExecutionContext {
|
|
92
|
-
ruleId: string // Database UUID of the rule
|
|
93
|
-
data: any
|
|
94
|
-
user?: {
|
|
95
|
-
id?: string
|
|
96
|
-
email?: string
|
|
97
|
-
role?: string
|
|
98
|
-
[key: string]: any
|
|
99
|
-
}
|
|
100
|
-
tenantId: string
|
|
101
|
-
organizationId: string
|
|
102
|
-
executedBy?: string
|
|
103
|
-
dryRun?: boolean
|
|
104
|
-
// Optional for logging (falls back to rule's entityType)
|
|
105
|
-
entityType?: string
|
|
106
|
-
entityId?: string
|
|
107
|
-
eventType?: string
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Direct rule execution result
|
|
112
|
-
*/
|
|
113
|
-
export interface DirectRuleExecutionResult {
|
|
114
|
-
success: boolean
|
|
115
|
-
ruleId: string
|
|
116
|
-
ruleName: string
|
|
117
|
-
conditionResult: boolean
|
|
118
|
-
actionsExecuted: ActionExecutionOutcome | null
|
|
119
|
-
executionTime: number
|
|
120
|
-
error?: string
|
|
121
|
-
logId?: string
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Context for executing a rule by its string rule_id identifier
|
|
126
|
-
* Unlike DirectRuleExecutionContext which uses database UUID,
|
|
127
|
-
* this uses the string identifier (e.g., "workflow_checkout_inventory_available")
|
|
128
|
-
*/
|
|
129
|
-
export interface RuleIdExecutionContext {
|
|
130
|
-
ruleId: string // String identifier (e.g., "workflow_checkout_inventory_available")
|
|
131
|
-
data: any
|
|
132
|
-
user?: {
|
|
133
|
-
id?: string
|
|
134
|
-
email?: string
|
|
135
|
-
role?: string
|
|
136
|
-
[key: string]: any
|
|
137
|
-
}
|
|
138
|
-
tenantId: string
|
|
139
|
-
organizationId: string
|
|
140
|
-
executedBy?: string
|
|
141
|
-
dryRun?: boolean
|
|
142
|
-
entityType?: string
|
|
143
|
-
entityId?: string
|
|
144
|
-
eventType?: string
|
|
145
|
-
}
|
|
146
|
-
|
|
147
88
|
/**
|
|
148
89
|
* Execute a function with a timeout
|
|
149
90
|
*/
|
|
@@ -463,227 +404,6 @@ export async function findApplicableRules(
|
|
|
463
404
|
})
|
|
464
405
|
}
|
|
465
406
|
|
|
466
|
-
/**
|
|
467
|
-
* Execute a specific rule by its database UUID
|
|
468
|
-
* This bypasses the entityType/eventType discovery mechanism and directly executes the rule
|
|
469
|
-
*/
|
|
470
|
-
export async function executeRuleById(
|
|
471
|
-
em: EntityManager,
|
|
472
|
-
context: DirectRuleExecutionContext
|
|
473
|
-
): Promise<DirectRuleExecutionResult> {
|
|
474
|
-
const startTime = Date.now()
|
|
475
|
-
|
|
476
|
-
// Validate input
|
|
477
|
-
const validation = directRuleExecutionContextSchema.safeParse(context)
|
|
478
|
-
if (!validation.success) {
|
|
479
|
-
const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)
|
|
480
|
-
return {
|
|
481
|
-
success: false,
|
|
482
|
-
ruleId: context.ruleId,
|
|
483
|
-
ruleName: 'Unknown',
|
|
484
|
-
conditionResult: false,
|
|
485
|
-
actionsExecuted: null,
|
|
486
|
-
executionTime: Date.now() - startTime,
|
|
487
|
-
error: `Validation failed: ${validationErrors.join(', ')}`,
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// Fetch rule by ID with tenant/org validation
|
|
492
|
-
const rule = await em.findOne(BusinessRule, {
|
|
493
|
-
id: context.ruleId,
|
|
494
|
-
tenantId: context.tenantId,
|
|
495
|
-
organizationId: context.organizationId,
|
|
496
|
-
deletedAt: null,
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
if (!rule) {
|
|
500
|
-
return {
|
|
501
|
-
success: false,
|
|
502
|
-
ruleId: context.ruleId,
|
|
503
|
-
ruleName: 'Unknown',
|
|
504
|
-
conditionResult: false,
|
|
505
|
-
actionsExecuted: null,
|
|
506
|
-
executionTime: Date.now() - startTime,
|
|
507
|
-
error: 'Rule not found',
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
if (!rule.enabled) {
|
|
512
|
-
return {
|
|
513
|
-
success: false,
|
|
514
|
-
ruleId: rule.ruleId,
|
|
515
|
-
ruleName: rule.ruleName,
|
|
516
|
-
conditionResult: false,
|
|
517
|
-
actionsExecuted: null,
|
|
518
|
-
executionTime: Date.now() - startTime,
|
|
519
|
-
error: 'Rule is disabled',
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Check effective date range
|
|
524
|
-
const now = new Date()
|
|
525
|
-
if (rule.effectiveFrom && rule.effectiveFrom > now) {
|
|
526
|
-
return {
|
|
527
|
-
success: false,
|
|
528
|
-
ruleId: rule.ruleId,
|
|
529
|
-
ruleName: rule.ruleName,
|
|
530
|
-
conditionResult: false,
|
|
531
|
-
actionsExecuted: null,
|
|
532
|
-
executionTime: Date.now() - startTime,
|
|
533
|
-
error: `Rule is not yet effective (starts ${rule.effectiveFrom.toISOString()})`,
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
if (rule.effectiveTo && rule.effectiveTo < now) {
|
|
537
|
-
return {
|
|
538
|
-
success: false,
|
|
539
|
-
ruleId: rule.ruleId,
|
|
540
|
-
ruleName: rule.ruleName,
|
|
541
|
-
conditionResult: false,
|
|
542
|
-
actionsExecuted: null,
|
|
543
|
-
executionTime: Date.now() - startTime,
|
|
544
|
-
error: `Rule has expired (ended ${rule.effectiveTo.toISOString()})`,
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// Build RuleEngineContext (use provided entityType or fall back to rule's)
|
|
549
|
-
const engineContext: RuleEngineContext = {
|
|
550
|
-
entityType: context.entityType || rule.entityType,
|
|
551
|
-
entityId: context.entityId,
|
|
552
|
-
eventType: context.eventType || rule.eventType || undefined,
|
|
553
|
-
data: context.data,
|
|
554
|
-
user: context.user,
|
|
555
|
-
tenantId: context.tenantId,
|
|
556
|
-
organizationId: context.organizationId,
|
|
557
|
-
executedBy: context.executedBy,
|
|
558
|
-
dryRun: context.dryRun,
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Execute via existing executeSingleRule
|
|
562
|
-
const result = await executeSingleRule(em, rule, engineContext)
|
|
563
|
-
|
|
564
|
-
return {
|
|
565
|
-
success: !result.error,
|
|
566
|
-
ruleId: rule.ruleId,
|
|
567
|
-
ruleName: rule.ruleName,
|
|
568
|
-
conditionResult: result.conditionResult,
|
|
569
|
-
actionsExecuted: result.actionsExecuted,
|
|
570
|
-
executionTime: result.executionTime,
|
|
571
|
-
error: result.error,
|
|
572
|
-
logId: result.logId,
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
/**
|
|
577
|
-
* Execute a rule by its string rule_id identifier
|
|
578
|
-
* Looks up rule by rule_id (string column) + tenant_id (unique constraint)
|
|
579
|
-
* This is useful for workflow conditions that reference rules by their string identifiers
|
|
580
|
-
*/
|
|
581
|
-
export async function executeRuleByRuleId(
|
|
582
|
-
em: EntityManager,
|
|
583
|
-
context: RuleIdExecutionContext
|
|
584
|
-
): Promise<DirectRuleExecutionResult> {
|
|
585
|
-
const startTime = Date.now()
|
|
586
|
-
|
|
587
|
-
// Validate input
|
|
588
|
-
const validation = ruleIdExecutionContextSchema.safeParse(context)
|
|
589
|
-
if (!validation.success) {
|
|
590
|
-
const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)
|
|
591
|
-
return {
|
|
592
|
-
success: false,
|
|
593
|
-
ruleId: context.ruleId || 'unknown',
|
|
594
|
-
ruleName: 'Unknown',
|
|
595
|
-
conditionResult: false,
|
|
596
|
-
actionsExecuted: null,
|
|
597
|
-
executionTime: Date.now() - startTime,
|
|
598
|
-
error: `Validation failed: ${validationErrors.join(', ')}`,
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// Fetch rule by rule_id (string identifier) + tenant/org
|
|
603
|
-
const rule = await em.findOne(BusinessRule, {
|
|
604
|
-
ruleId: context.ruleId, // String identifier column
|
|
605
|
-
tenantId: context.tenantId,
|
|
606
|
-
organizationId: context.organizationId,
|
|
607
|
-
deletedAt: null,
|
|
608
|
-
})
|
|
609
|
-
|
|
610
|
-
if (!rule) {
|
|
611
|
-
return {
|
|
612
|
-
success: false,
|
|
613
|
-
ruleId: context.ruleId,
|
|
614
|
-
ruleName: 'Unknown',
|
|
615
|
-
conditionResult: false,
|
|
616
|
-
actionsExecuted: null,
|
|
617
|
-
executionTime: Date.now() - startTime,
|
|
618
|
-
error: 'Rule not found',
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
if (!rule.enabled) {
|
|
623
|
-
return {
|
|
624
|
-
success: false,
|
|
625
|
-
ruleId: rule.ruleId,
|
|
626
|
-
ruleName: rule.ruleName,
|
|
627
|
-
conditionResult: false,
|
|
628
|
-
actionsExecuted: null,
|
|
629
|
-
executionTime: Date.now() - startTime,
|
|
630
|
-
error: 'Rule is disabled',
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// Check effective date range
|
|
635
|
-
const now = new Date()
|
|
636
|
-
if (rule.effectiveFrom && rule.effectiveFrom > now) {
|
|
637
|
-
return {
|
|
638
|
-
success: false,
|
|
639
|
-
ruleId: rule.ruleId,
|
|
640
|
-
ruleName: rule.ruleName,
|
|
641
|
-
conditionResult: false,
|
|
642
|
-
actionsExecuted: null,
|
|
643
|
-
executionTime: Date.now() - startTime,
|
|
644
|
-
error: `Rule is not yet effective (starts ${rule.effectiveFrom.toISOString()})`,
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
if (rule.effectiveTo && rule.effectiveTo < now) {
|
|
648
|
-
return {
|
|
649
|
-
success: false,
|
|
650
|
-
ruleId: rule.ruleId,
|
|
651
|
-
ruleName: rule.ruleName,
|
|
652
|
-
conditionResult: false,
|
|
653
|
-
actionsExecuted: null,
|
|
654
|
-
executionTime: Date.now() - startTime,
|
|
655
|
-
error: `Rule has expired (ended ${rule.effectiveTo.toISOString()})`,
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// Build RuleEngineContext (use provided entityType or fall back to rule's)
|
|
660
|
-
const engineContext: RuleEngineContext = {
|
|
661
|
-
entityType: context.entityType || rule.entityType,
|
|
662
|
-
entityId: context.entityId,
|
|
663
|
-
eventType: context.eventType || rule.eventType || undefined,
|
|
664
|
-
data: context.data,
|
|
665
|
-
user: context.user,
|
|
666
|
-
tenantId: context.tenantId,
|
|
667
|
-
organizationId: context.organizationId,
|
|
668
|
-
executedBy: context.executedBy,
|
|
669
|
-
dryRun: context.dryRun,
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
// Execute via existing executeSingleRule
|
|
673
|
-
const result = await executeSingleRule(em, rule, engineContext)
|
|
674
|
-
|
|
675
|
-
return {
|
|
676
|
-
success: !result.error,
|
|
677
|
-
ruleId: rule.ruleId,
|
|
678
|
-
ruleName: rule.ruleName,
|
|
679
|
-
conditionResult: result.conditionResult,
|
|
680
|
-
actionsExecuted: result.actionsExecuted,
|
|
681
|
-
executionTime: result.executionTime,
|
|
682
|
-
error: result.error,
|
|
683
|
-
logId: result.logId,
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
407
|
/**
|
|
688
408
|
* Sensitive field patterns to exclude from logs
|
|
689
409
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
import { seedCatalogUnits, seedCatalogPriceKinds, seedCatalogExamplesForScope } from './lib/seeds'
|
|
3
|
+
|
|
4
|
+
export const setup: ModuleSetupConfig = {
|
|
5
|
+
seedDefaults: async (ctx) => {
|
|
6
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
7
|
+
await seedCatalogUnits(ctx.em, scope)
|
|
8
|
+
await seedCatalogPriceKinds(ctx.em, scope)
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
seedExamples: async (ctx) => {
|
|
12
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
13
|
+
await seedCatalogExamplesForScope(ctx.em, ctx.container, scope)
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
defaultRoleFeatures: {
|
|
17
|
+
admin: ['catalog.*', 'catalog.variants.manage', 'catalog.pricing.manage'],
|
|
18
|
+
employee: ['catalog.*', 'catalog.variants.manage', 'catalog.pricing.manage'],
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default setup
|