@open-mercato/core 0.4.2-canary-15e78de280 → 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/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/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/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/lib/seeds.js +3 -15
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- 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/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/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/setup.ts +108 -0
- package/src/modules/staff/setup.ts +27 -0
- package/src/modules/workflows/lib/seeds.ts +4 -16
- package/src/modules/workflows/migrations/Migration20251207131955.ts +77 -143
- package/src/modules/workflows/setup.ts +15 -0
|
@@ -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
|
}
|
|
@@ -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
|
|
@@ -4,13 +4,8 @@ import type { AwilixContainer } from 'awilix'
|
|
|
4
4
|
import { Role, RoleAcl } from '@open-mercato/core/modules/auth/data/entities'
|
|
5
5
|
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
6
6
|
import { reindexModules } from '@open-mercato/core/modules/configs/lib/reindex-helpers'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { seedExampleCurrencies } from '@open-mercato/core/modules/currencies/lib/seeds'
|
|
10
|
-
import { seedExampleWorkflows } from '@open-mercato/core/modules/workflows/lib/seeds'
|
|
11
|
-
import { seedPlannerAvailabilityRuleSetDefaults, seedPlannerUnavailabilityReasons } from '@open-mercato/core/modules/planner/lib/seeds'
|
|
12
|
-
import { seedResourcesAddressTypes, seedResourcesCapacityUnits, seedResourcesResourceExamples } from '@open-mercato/core/modules/resources/lib/seeds'
|
|
13
|
-
import { seedStaffTeamExamples } from '@open-mercato/core/modules/staff/lib/seeds'
|
|
7
|
+
// Optional module imports are loaded dynamically inside each upgrade action
|
|
8
|
+
// so the app does not crash when a module is disabled.
|
|
14
9
|
import { collectCrudCacheStats, purgeCrudCacheSegment } from '@open-mercato/shared/lib/crud/cache-stats'
|
|
15
10
|
import { isCrudCacheEnabled, resolveCrudCache } from '@open-mercato/shared/lib/crud/cache'
|
|
16
11
|
import * as semver from 'semver'
|
|
@@ -91,7 +86,9 @@ async function ensureVectorSearchEncryptionMap(
|
|
|
91
86
|
return true
|
|
92
87
|
}
|
|
93
88
|
|
|
94
|
-
export type UpgradeActionContext =
|
|
89
|
+
export type UpgradeActionContext = {
|
|
90
|
+
tenantId: string
|
|
91
|
+
organizationId: string
|
|
95
92
|
container: AwilixContainer
|
|
96
93
|
em: EntityManager
|
|
97
94
|
}
|
|
@@ -155,6 +152,14 @@ export const upgradeActions: UpgradeActionDefinition[] = [
|
|
|
155
152
|
successKey: 'upgrades.v034.success',
|
|
156
153
|
loadingKey: 'upgrades.v034.loading',
|
|
157
154
|
async run({ container, em, tenantId, organizationId }) {
|
|
155
|
+
let installExampleCatalogData: typeof import('@open-mercato/core/modules/catalog/lib/seeds')['installExampleCatalogData'] | undefined
|
|
156
|
+
try {
|
|
157
|
+
const catalogSeeds = await import('@open-mercato/core/modules/catalog/lib/seeds')
|
|
158
|
+
installExampleCatalogData = catalogSeeds.installExampleCatalogData
|
|
159
|
+
} catch {
|
|
160
|
+
console.warn('[upgrade-actions] catalog module not available, skipping catalog example data')
|
|
161
|
+
return
|
|
162
|
+
}
|
|
158
163
|
await installExampleCatalogData(container, { tenantId, organizationId }, em)
|
|
159
164
|
const vectorService = resolveVectorService(container)
|
|
160
165
|
await reindexModules(em, ['catalog'], { tenantId, organizationId, vectorService })
|
|
@@ -214,8 +219,16 @@ export const upgradeActions: UpgradeActionDefinition[] = [
|
|
|
214
219
|
successKey: 'upgrades.v036.success',
|
|
215
220
|
loadingKey: 'upgrades.v036.loading',
|
|
216
221
|
async run({ container, em, tenantId, organizationId }) {
|
|
222
|
+
let seedSalesExamples: typeof import('@open-mercato/core/modules/sales/seed/examples')['seedSalesExamples'] | undefined
|
|
223
|
+
try {
|
|
224
|
+
const salesSeeds = await import('@open-mercato/core/modules/sales/seed/examples')
|
|
225
|
+
seedSalesExamples = salesSeeds.seedSalesExamples
|
|
226
|
+
} catch {
|
|
227
|
+
console.warn('[upgrade-actions] sales module not available, skipping sales example data')
|
|
228
|
+
return
|
|
229
|
+
}
|
|
217
230
|
await em.transactional(async (tem) => {
|
|
218
|
-
await seedSalesExamples(tem, container, { tenantId, organizationId })
|
|
231
|
+
await seedSalesExamples!(tem, container, { tenantId, organizationId })
|
|
219
232
|
})
|
|
220
233
|
const vectorService = resolveVectorService(container)
|
|
221
234
|
await reindexModules(em, ['sales', 'catalog'], { tenantId, organizationId, vectorService })
|
|
@@ -262,9 +275,26 @@ export const upgradeActions: UpgradeActionDefinition[] = [
|
|
|
262
275
|
async run({ container, em, tenantId, organizationId }) {
|
|
263
276
|
const normalizedTenantId = tenantId.trim()
|
|
264
277
|
const scope = { tenantId, organizationId }
|
|
278
|
+
|
|
279
|
+
let seedExampleCurrencies: typeof import('@open-mercato/core/modules/currencies/lib/seeds')['seedExampleCurrencies'] | undefined
|
|
280
|
+
try {
|
|
281
|
+
const currenciesSeeds = await import('@open-mercato/core/modules/currencies/lib/seeds')
|
|
282
|
+
seedExampleCurrencies = currenciesSeeds.seedExampleCurrencies
|
|
283
|
+
} catch {
|
|
284
|
+
console.warn('[upgrade-actions] currencies module not available, skipping currency seeding')
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let seedExampleWorkflows: typeof import('@open-mercato/core/modules/workflows/lib/seeds')['seedExampleWorkflows'] | undefined
|
|
288
|
+
try {
|
|
289
|
+
const workflowsSeeds = await import('@open-mercato/core/modules/workflows/lib/seeds')
|
|
290
|
+
seedExampleWorkflows = workflowsSeeds.seedExampleWorkflows
|
|
291
|
+
} catch {
|
|
292
|
+
console.warn('[upgrade-actions] workflows module not available, skipping workflow seeding')
|
|
293
|
+
}
|
|
294
|
+
|
|
265
295
|
await em.transactional(async (tem) => {
|
|
266
|
-
await seedExampleCurrencies(tem, scope)
|
|
267
|
-
await seedExampleWorkflows(tem, scope)
|
|
296
|
+
if (seedExampleCurrencies) await seedExampleCurrencies(tem, scope)
|
|
297
|
+
if (seedExampleWorkflows) await seedExampleWorkflows(tem, scope)
|
|
268
298
|
|
|
269
299
|
const adminRole = await tem.findOne(Role, { name: 'admin', tenantId: normalizedTenantId, deletedAt: null })
|
|
270
300
|
if (!adminRole) return
|
|
@@ -315,13 +345,44 @@ export const upgradeActions: UpgradeActionDefinition[] = [
|
|
|
315
345
|
async run({ container, em, tenantId, organizationId }) {
|
|
316
346
|
const normalizedTenantId = tenantId.trim()
|
|
317
347
|
const scope = { tenantId, organizationId }
|
|
348
|
+
|
|
349
|
+
let seedPlannerAvailabilityRuleSetDefaults: typeof import('@open-mercato/core/modules/planner/lib/seeds')['seedPlannerAvailabilityRuleSetDefaults'] | undefined
|
|
350
|
+
let seedPlannerUnavailabilityReasons: typeof import('@open-mercato/core/modules/planner/lib/seeds')['seedPlannerUnavailabilityReasons'] | undefined
|
|
351
|
+
try {
|
|
352
|
+
const plannerSeeds = await import('@open-mercato/core/modules/planner/lib/seeds')
|
|
353
|
+
seedPlannerAvailabilityRuleSetDefaults = plannerSeeds.seedPlannerAvailabilityRuleSetDefaults
|
|
354
|
+
seedPlannerUnavailabilityReasons = plannerSeeds.seedPlannerUnavailabilityReasons
|
|
355
|
+
} catch {
|
|
356
|
+
console.warn('[upgrade-actions] planner module not available, skipping planner seeding')
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let seedStaffTeamExamples: typeof import('@open-mercato/core/modules/staff/lib/seeds')['seedStaffTeamExamples'] | undefined
|
|
360
|
+
try {
|
|
361
|
+
const staffSeeds = await import('@open-mercato/core/modules/staff/lib/seeds')
|
|
362
|
+
seedStaffTeamExamples = staffSeeds.seedStaffTeamExamples
|
|
363
|
+
} catch {
|
|
364
|
+
console.warn('[upgrade-actions] staff module not available, skipping staff seeding')
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
let seedResourcesAddressTypes: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesAddressTypes'] | undefined
|
|
368
|
+
let seedResourcesCapacityUnits: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesCapacityUnits'] | undefined
|
|
369
|
+
let seedResourcesResourceExamples: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesResourceExamples'] | undefined
|
|
370
|
+
try {
|
|
371
|
+
const resourcesSeeds = await import('@open-mercato/core/modules/resources/lib/seeds')
|
|
372
|
+
seedResourcesAddressTypes = resourcesSeeds.seedResourcesAddressTypes
|
|
373
|
+
seedResourcesCapacityUnits = resourcesSeeds.seedResourcesCapacityUnits
|
|
374
|
+
seedResourcesResourceExamples = resourcesSeeds.seedResourcesResourceExamples
|
|
375
|
+
} catch {
|
|
376
|
+
console.warn('[upgrade-actions] resources module not available, skipping resources seeding')
|
|
377
|
+
}
|
|
378
|
+
|
|
318
379
|
await em.transactional(async (tem) => {
|
|
319
|
-
await seedPlannerAvailabilityRuleSetDefaults(tem, scope)
|
|
320
|
-
await seedPlannerUnavailabilityReasons(tem, scope)
|
|
321
|
-
await seedStaffTeamExamples(tem, scope)
|
|
322
|
-
await seedResourcesCapacityUnits(tem, scope)
|
|
323
|
-
await seedResourcesAddressTypes(tem, scope)
|
|
324
|
-
await seedResourcesResourceExamples(tem, scope)
|
|
380
|
+
if (seedPlannerAvailabilityRuleSetDefaults) await seedPlannerAvailabilityRuleSetDefaults(tem, scope)
|
|
381
|
+
if (seedPlannerUnavailabilityReasons) await seedPlannerUnavailabilityReasons(tem, scope)
|
|
382
|
+
if (seedStaffTeamExamples) await seedStaffTeamExamples(tem, scope)
|
|
383
|
+
if (seedResourcesCapacityUnits) await seedResourcesCapacityUnits(tem, scope)
|
|
384
|
+
if (seedResourcesAddressTypes) await seedResourcesAddressTypes(tem, scope)
|
|
385
|
+
if (seedResourcesResourceExamples) await seedResourcesResourceExamples(tem, scope)
|
|
325
386
|
|
|
326
387
|
const adminRole = await tem.findOne(Role, { name: 'admin', tenantId: normalizedTenantId, deletedAt: null })
|
|
327
388
|
if (!adminRole) return
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
admin: [
|
|
6
|
+
'configs.system_status.view',
|
|
7
|
+
'configs.cache.view',
|
|
8
|
+
'configs.cache.manage',
|
|
9
|
+
'configs.manage',
|
|
10
|
+
],
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default setup
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
import { seedExampleCurrencies } from './lib/seeds'
|
|
3
|
+
|
|
4
|
+
export const setup: ModuleSetupConfig = {
|
|
5
|
+
seedDefaults: async (ctx) => {
|
|
6
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
7
|
+
await seedExampleCurrencies(ctx.em, scope)
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
defaultRoleFeatures: {
|
|
11
|
+
admin: ['currencies.*'],
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default setup
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
import { seedCustomerDictionaries, seedCurrencyDictionary, seedCustomerExamples } from './cli'
|
|
3
|
+
|
|
4
|
+
export const setup: ModuleSetupConfig = {
|
|
5
|
+
seedDefaults: async (ctx) => {
|
|
6
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
7
|
+
await seedCustomerDictionaries(ctx.em, scope)
|
|
8
|
+
await seedCurrencyDictionary(ctx.em, scope)
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
seedExamples: async (ctx) => {
|
|
12
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
13
|
+
await seedCustomerExamples(ctx.em, ctx.container, scope)
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
defaultRoleFeatures: {
|
|
17
|
+
admin: [
|
|
18
|
+
'customers.*',
|
|
19
|
+
'customers.people.view',
|
|
20
|
+
'customers.people.manage',
|
|
21
|
+
'customers.companies.view',
|
|
22
|
+
'customers.companies.manage',
|
|
23
|
+
'customers.deals.view',
|
|
24
|
+
'customers.deals.manage',
|
|
25
|
+
],
|
|
26
|
+
employee: [
|
|
27
|
+
'customers.*',
|
|
28
|
+
'customers.people.view',
|
|
29
|
+
'customers.people.manage',
|
|
30
|
+
'customers.companies.view',
|
|
31
|
+
'customers.companies.manage',
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default setup
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
admin: ['dashboards.*', 'dashboards.admin.assign-widgets', 'analytics.view'],
|
|
6
|
+
employee: ['dashboards.view', 'dashboards.configure', 'analytics.view'],
|
|
7
|
+
},
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default setup
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
admin: ['dictionaries.view', 'dictionaries.manage'],
|
|
6
|
+
employee: ['dictionaries.view'],
|
|
7
|
+
},
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default setup
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
superadmin: ['directory.tenants.*'],
|
|
6
|
+
admin: ['directory.organizations.view', 'directory.organizations.manage'],
|
|
7
|
+
},
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default setup
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
admin: ['perspectives.use', 'perspectives.role_defaults'],
|
|
6
|
+
employee: ['perspectives.use'],
|
|
7
|
+
},
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default setup
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
import { seedPlannerUnavailabilityReasons, seedPlannerAvailabilityRuleSetDefaults } from './lib/seeds'
|
|
3
|
+
|
|
4
|
+
export const setup: ModuleSetupConfig = {
|
|
5
|
+
seedDefaults: async (ctx) => {
|
|
6
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
7
|
+
await seedPlannerUnavailabilityReasons(ctx.em, scope)
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
seedExamples: async (ctx) => {
|
|
11
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
12
|
+
await seedPlannerAvailabilityRuleSetDefaults(ctx.em, scope)
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
defaultRoleFeatures: {
|
|
16
|
+
admin: ['planner.*'],
|
|
17
|
+
employee: ['planner.view'],
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default setup
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
import { seedResourcesAddressTypes, seedResourcesCapacityUnits, seedResourcesResourceExamples } from './lib/seeds'
|
|
3
|
+
|
|
4
|
+
export const setup: ModuleSetupConfig = {
|
|
5
|
+
seedDefaults: async (ctx) => {
|
|
6
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
7
|
+
await seedResourcesAddressTypes(ctx.em, scope)
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
seedExamples: async (ctx) => {
|
|
11
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
12
|
+
await seedResourcesCapacityUnits(ctx.em, scope)
|
|
13
|
+
await seedResourcesResourceExamples(ctx.em, scope)
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
defaultRoleFeatures: {
|
|
17
|
+
admin: ['resources.*'],
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default setup
|