feat(tasks): add request parsing for generate-and-assign core module

This commit is contained in:
lorentz 2026-07-18 10:12:47 +00:00
parent d8aaea33e6
commit 64f8b71603
2 changed files with 85 additions and 0 deletions

View file

@ -0,0 +1,47 @@
import { parseGenerateAndAssignTarget, GenerateAndAssignError } from '../generate-and-assign-core'
describe('parseGenerateAndAssignTarget', () => {
it('parses advocate+designation mode', () => {
const { target, dryRun } = parseGenerateAndAssignTarget({
advocateId: 'adv-1',
designationId: 'des-1',
})
expect(target).toEqual({ mode: 'advocate-designation', advocateId: 'adv-1', designationId: 'des-1' })
expect(dryRun).toBe(false)
})
it('parses client mode', () => {
const { target, dryRun } = parseGenerateAndAssignTarget({ clientId: 'client-1', dryRun: true })
expect(target).toEqual({ mode: 'client', clientId: 'client-1' })
expect(dryRun).toBe(true)
})
it('defaults dryRun to false when omitted', () => {
const { dryRun } = parseGenerateAndAssignTarget({ clientId: 'client-1' })
expect(dryRun).toBe(false)
})
it('throws when both modes are provided', () => {
expect(() =>
parseGenerateAndAssignTarget({ advocateId: 'a', designationId: 'd', clientId: 'c' })
).toThrow(GenerateAndAssignError)
})
it('throws when neither mode is provided', () => {
expect(() => parseGenerateAndAssignTarget({})).toThrow(GenerateAndAssignError)
})
it('throws when advocateId is given without designationId', () => {
expect(() => parseGenerateAndAssignTarget({ advocateId: 'a' })).toThrow(GenerateAndAssignError)
})
it('sets a 400 status on validation errors', () => {
try {
parseGenerateAndAssignTarget({})
fail('expected throw')
} catch (err) {
expect(err).toBeInstanceOf(GenerateAndAssignError)
expect((err as GenerateAndAssignError).status).toBe(400)
}
})
})

View file

@ -0,0 +1,38 @@
export class GenerateAndAssignError extends Error {
status: number
constructor(message: string, status: number) {
super(message)
this.status = status
}
}
export type GenerateTarget =
| { mode: 'advocate-designation'; advocateId: string; designationId: string }
| { mode: 'client'; clientId: string }
/**
* Parses and validates a generate-and-assign request body. Exactly one of
* (advocateId + designationId) or clientId must be present.
*/
export function parseGenerateAndAssignTarget(body: any): { target: GenerateTarget; dryRun: boolean } {
const dryRun = body?.dryRun === true
const hasAdvocateDesignation = !!body?.advocateId && !!body?.designationId
const hasClient = !!body?.clientId
if (hasAdvocateDesignation && hasClient) {
throw new GenerateAndAssignError(
'Provide either advocateId+designationId or clientId, not both',
400
)
}
if (hasClient) {
return { target: { mode: 'client', clientId: body.clientId }, dryRun }
}
if (hasAdvocateDesignation) {
return {
target: { mode: 'advocate-designation', advocateId: body.advocateId, designationId: body.designationId },
dryRun,
}
}
throw new GenerateAndAssignError('advocateId and designationId, or clientId, are required', 400)
}