/** * CM-5: interest assignment is gated behind the per-port `assignment_enabled` * setting. When off (the default), createInterest must NOT auto-assign an owner * even when a `default_new_interest_owner` is configured. When on, the existing * tier-2 (port default-owner) auto-assign fires. An explicit `assignedTo` from * the caller (tier 1) is always honored regardless of the toggle. */ import { describe, it, expect, beforeAll, afterEach } from 'vitest'; import { eq } from 'drizzle-orm'; import { db } from '@/lib/db'; import { systemSettings } from '@/lib/db/schema/system'; import { userProfiles } from '@/lib/db/schema/users'; // interests.assigned_to FKs to user_profiles(user_id); the owner must exist. const OWNER = 'cm5-default-owner'; describe('interests.service - assignment_enabled gate (CM-5)', () => { let createInterest: typeof import('@/lib/services/interests.service').createInterest; let makePort: typeof import('../helpers/factories').makePort; let makeClient: typeof import('../helpers/factories').makeClient; let makeAuditMeta: typeof import('../helpers/factories').makeAuditMeta; beforeAll(async () => { const svc = await import('@/lib/services/interests.service'); createInterest = svc.createInterest; const factories = await import('../helpers/factories'); makePort = factories.makePort; makeClient = factories.makeClient; makeAuditMeta = factories.makeAuditMeta; // Idempotent owner profile - left in place (created interests reference it, // so we never delete it in teardown). await db .insert(userProfiles) .values({ userId: OWNER, displayName: 'CM5 Default Owner' }) .onConflictDoNothing(); }); afterEach(async () => { await db.delete(systemSettings).where(eq(systemSettings.key, 'assignment_enabled')); await db.delete(systemSettings).where(eq(systemSettings.key, 'default_new_interest_owner')); }); async function setSetting(portId: string, key: string, value: unknown) { await db.insert(systemSettings).values({ key, portId, value: value as never }); } it('does NOT auto-assign the port default owner when assignment is disabled (default)', async () => { const port = await makePort(); const client = await makeClient({ portId: port.id }); // A default owner IS configured, but the feature is OFF - the guard must // skip tier-2 entirely and leave the interest unassigned. await setSetting(port.id, 'default_new_interest_owner', { userId: OWNER }); const interest = await createInterest( port.id, { clientId: client.id, pipelineStage: 'enquiry', tagIds: [], reminderEnabled: false }, makeAuditMeta({ portId: port.id }), ); expect(interest.assignedTo).toBeNull(); }); it('auto-assigns the port default owner when assignment is enabled', async () => { const port = await makePort(); const client = await makeClient({ portId: port.id }); await setSetting(port.id, 'assignment_enabled', true); await setSetting(port.id, 'default_new_interest_owner', { userId: OWNER }); const interest = await createInterest( port.id, { clientId: client.id, pipelineStage: 'enquiry', tagIds: [], reminderEnabled: false }, makeAuditMeta({ portId: port.id }), ); expect(interest.assignedTo).toBe(OWNER); }); it('always honors an explicit assignedTo regardless of the toggle', async () => { const port = await makePort(); const client = await makeClient({ portId: port.id }); // Feature off, but the caller explicitly picked an owner - tier 1 wins. const interest = await createInterest( port.id, { clientId: client.id, assignedTo: OWNER, pipelineStage: 'enquiry', tagIds: [], reminderEnabled: false, }, makeAuditMeta({ portId: port.id }), ); expect(interest.assignedTo).toBe(OWNER); }); });