|
| 1 | +import { z } from 'zod'; |
| 2 | +import { SnakeCaseIdentifierSchema } from '../shared/identifiers.zod'; |
| 3 | + |
| 4 | +/** |
| 5 | + * Approval Step Approver Type |
| 6 | + */ |
| 7 | +export const ApproverType = z.enum([ |
| 8 | + 'user', // Specific user(s) |
| 9 | + 'role', // Users with specific role |
| 10 | + 'manager', // Submitter's manager |
| 11 | + 'field', // User ID defined in a record field |
| 12 | + 'queue' // Data ownership queue |
| 13 | +]); |
| 14 | + |
| 15 | +/** |
| 16 | + * Approval Action Type |
| 17 | + * Actions to execute on transition |
| 18 | + */ |
| 19 | +export const ApprovalActionType = z.enum([ |
| 20 | + 'field_update', |
| 21 | + 'email_alert', |
| 22 | + 'webhook', |
| 23 | + 'script' |
| 24 | +]); |
| 25 | + |
| 26 | +/** |
| 27 | + * definition of an action to perform |
| 28 | + */ |
| 29 | +export const ApprovalActionSchema = z.object({ |
| 30 | + type: ApprovalActionType, |
| 31 | + name: z.string().describe('Action name'), |
| 32 | + config: z.record(z.any()).describe('Action configuration') |
| 33 | +}); |
| 34 | + |
| 35 | +/** |
| 36 | + * Approval Process Step |
| 37 | + */ |
| 38 | +export const ApprovalStepSchema = z.object({ |
| 39 | + name: SnakeCaseIdentifierSchema.describe('Step machine name'), |
| 40 | + label: z.string().describe('Step display label'), |
| 41 | + description: z.string().optional(), |
| 42 | + |
| 43 | + /** Entry criteria for this step */ |
| 44 | + entryCriteria: z.string().optional().describe('Formula expression to enter this step'), |
| 45 | + |
| 46 | + /** Who can approve */ |
| 47 | + approvers: z.array(z.object({ |
| 48 | + type: ApproverType, |
| 49 | + value: z.string().describe('User ID, Role Name, or Field Name') |
| 50 | + })).min(1).describe('List of allowed approvers'), |
| 51 | + |
| 52 | + /** Approval Logic */ |
| 53 | + behavior: z.enum(['first_response', 'unanimous']).default('first_response') |
| 54 | + .describe('How to handle multiple approvers'), |
| 55 | + |
| 56 | + /** Rejection behavior */ |
| 57 | + rejectionBehavior: z.enum(['reject_process', 'back_to_previous']) |
| 58 | + .default('reject_process').describe('What happens if rejected'), |
| 59 | + |
| 60 | + /** Actions */ |
| 61 | + onApprove: z.array(ApprovalActionSchema).optional().describe('Actions on step approval'), |
| 62 | + onReject: z.array(ApprovalActionSchema).optional().describe('Actions on step rejection'), |
| 63 | +}); |
| 64 | + |
| 65 | +/** |
| 66 | + * Approval Process Protocol |
| 67 | + * |
| 68 | + * Defines a complex review and approval cycle for a record. |
| 69 | + * Manages state locking, notifications, and transition logic. |
| 70 | + */ |
| 71 | +export const ApprovalProcessSchema = z.object({ |
| 72 | + name: SnakeCaseIdentifierSchema.describe('Unique process name'), |
| 73 | + label: z.string().describe('Human readable label'), |
| 74 | + object: z.string().describe('Target Object Name'), |
| 75 | + |
| 76 | + active: z.boolean().default(false), |
| 77 | + description: z.string().optional(), |
| 78 | + |
| 79 | + /** Entry Criteria for the entire process */ |
| 80 | + entryCriteria: z.string().optional().describe('Formula to allow submission'), |
| 81 | + |
| 82 | + /** Record Locking */ |
| 83 | + lockRecord: z.boolean().default(true).describe('Lock record from editing during approval'), |
| 84 | + |
| 85 | + /** Steps */ |
| 86 | + steps: z.array(ApprovalStepSchema).min(1).describe('Sequence of approval steps'), |
| 87 | + |
| 88 | + /** Global Actions */ |
| 89 | + onSubmit: z.array(ApprovalActionSchema).optional().describe('Actions on initial submission'), |
| 90 | + onFinalApprove: z.array(ApprovalActionSchema).optional().describe('Actions on final approval'), |
| 91 | + onFinalReject: z.array(ApprovalActionSchema).optional().describe('Actions on final rejection'), |
| 92 | + onRecall: z.array(ApprovalActionSchema).optional().describe('Actions on recall'), |
| 93 | +}); |
| 94 | + |
| 95 | +export const ApprovalProcess = Object.assign(ApprovalProcessSchema, { |
| 96 | + create: <T extends z.input<typeof ApprovalProcessSchema>>(config: T) => config, |
| 97 | +}); |
| 98 | + |
| 99 | +export type ApprovalProcess = z.infer<typeof ApprovalProcessSchema>; |
| 100 | +export type ApprovalStep = z.infer<typeof ApprovalStepSchema>; |
0 commit comments