UNPKG

wcz-layout

Version:

305 lines (259 loc) • 9.29 kB
# approval ## Client `import { ... } from "wcz-layout/data/client";` - Query: `approvalsQueryOptions(GetApprovalsSchema)` → `Approval[]` // approvals of the application, optionally filtered; `appName` is sent as `applicationName` `approvalQueryOptions(GetApprovalSchema)` → `Approval` // single approval - Mutation: `createApprovalMutationOptions({ queryClient })` → `mutate(CreateApprovalSchema)` → `Approval` // create a new approval request `approveApprovalMutationOptions({ queryClient })` → `mutate(ApproveApprovalSchema)` → `Approval` // current approver's decision (`"Approved"` / `"Rejected"`) on the active step `resubmitApprovalMutationOptions({ queryClient })` → `mutate(ResubmitApprovalSchema)` → `Approval` // resubmit with new flows (same flow shape as create) `withdrawApprovalMutationOptions({ queryClient })` → `mutate(WithdrawApprovalSchema)` → `void` // withdraw the request `cancelApprovalMutationOptions({ queryClient })` → `mutate(CancelApprovalSchema)` → `void` // cancel the request ## Server `import { ... } from "wcz-layout/data/server";` - Fetch: `getApprovals({ data: GetApprovalsSchema })` → `Approval[]` // approvals of the application, optionally filtered `getApproval({ data: GetApprovalSchema })` → `Approval` // single approval - Mutate: `createApproval({ data: CreateApprovalSchema })` → `Approval` // create a new approval request `approveApproval({ data: ApproveApprovalSchema })` → `Approval` // approve / reject the active step `resubmitApproval({ data: ResubmitApprovalSchema })` → `Approval` // resubmit with new flows `withdrawApproval({ data: WithdrawApprovalSchema })` → `void` // withdraw the request `cancelApproval({ data: CancelApprovalSchema })` → `void` // cancel the request ## Schemas/Models ```ts const ApprovalRequestType = z.enum(["Single", "Batch"]); const ApprovalStatus = z.enum([ "WaitingForApproval", "Approved", "PartiallyApproved", "Rejected", "Withdrawn", "Cancelled", ]); const ApprovalStepResult = z.enum([ "NotAvailable", "FutureApproval", "WaitingForApproval", "Approved", "Rejected", "Skipped", "Withdrawn", "Cancelled", ]); const StepApprovalOrder = z.enum(["Serial", "Parallel", "OneOfThem"]); const ApprovalEmployeeSchema = z.object({ employeeId: z.string().trim().min(1).max(20), name: z.string().trim().min(1).max(50), email: z.email().min(1).max(100), }); const ApprovalProxySchema = z.object({ proxy: ApprovalEmployeeSchema, }); const ApprovalFlowStepSchema = z.object({ id: z.uuid(), order: z.number(), approverRole: z.string().trim().min(1).max(100).default("Approver").optional(), approver: ApprovalEmployeeSchema, actualApprover: ApprovalEmployeeSchema.optional(), proxies: z.array(ApprovalProxySchema), result: ApprovalStepResult.default("NotAvailable").optional(), resultDate: z.date().optional(), resultComment: z.string().trim().max(2000).optional(), }); const ApprovalFlowSchema = z.object({ id: z.uuid(), approvalStage: z.number(), batchSequence: z.number().optional(), approvalSequence: z.number(), stepApprovalOrder: StepApprovalOrder, steps: z.array(ApprovalFlowStepSchema), isActive: z.boolean().default(false).optional(), }); const ApprovalCoRequestorGroupSchema = z.object({ role: z.string().trim().min(1), email: z.email(), }); const ApprovalCoRequestorEmployeeSchema = z.object({ employeeId: z.string().trim().min(1), name: z.string().trim().min(1), email: z.email(), }); const ApprovalCoRequestorPrincipalSchema = z.union([ ApprovalCoRequestorGroupSchema, ApprovalCoRequestorEmployeeSchema, ]); const ApprovalCoRequestorPermissionsSchema = z.object({ withdraw: z.boolean().default(false).optional(), cancel: z.boolean().default(false).optional(), }); const ApprovalCoRequestorSchema = z.object({ id: z.uuid(), principal: ApprovalCoRequestorPrincipalSchema, permissions: ApprovalCoRequestorPermissionsSchema, }); const HqApprovalColSchema = z.object({ title: z.string().optional(), text: z.string().optional(), textColor: z.string().optional(), textSize: z.string().optional(), }); const HqApprovalRowSchema = z.object({ col: z.array(HqApprovalColSchema) }); const HqApprovalSectionSchema = z.object({ row: z.array(HqApprovalRowSchema), title: z.string().optional(), type: z.string().optional(), text: z.string().optional(), }); const HqApprovalPageSchema = z.object({ section: z.array(HqApprovalSectionSchema) }); const HqApprovalSummarySchema = z.object({ page: z.array(HqApprovalPageSchema) }); const HqApprovalFormDataSchema = z.object({ systemId: z.string().optional(), formType: z.string().optional(), formId: z.string().optional(), stepName: z.string().optional(), userId: z.string().optional(), title: z.string().optional(), subject: z.string().optional(), summary: HqApprovalSummarySchema.optional(), messageId: z.string().optional(), attachList: z.string().optional(), chkResult: z.string().optional(), apprSummary: z.string().optional(), approvalComment: z.string().optional(), }); const HqApprovalHeaderSchema = z.object({ serviceId: z.string().optional(), authorizationCode: z.string().optional(), dataCreatedTime: z.string().optional(), characterEnable: z.boolean().default(false).optional(), }); const HqApprovalRequestSchema = z.object({ header: HqApprovalHeaderSchema.optional(), formData: HqApprovalFormDataSchema.optional(), }); const ApprovalSchema = z.object({ id: z.uuid(), number: z.string().trim().min(1).max(30), applicationName: z.string().trim().min(1).max(50), type: ApprovalRequestType.default("Single").optional(), status: ApprovalStatus, created: z.date(), createdBy: ApprovalEmployeeSchema, updated: z.date().optional(), updatedBy: ApprovalEmployeeSchema.optional(), approvalFlows: z.array(ApprovalFlowSchema).min(1), currentApprovers: z.array( ApprovalEmployeeSchema.extend({ proxies: z.array(ApprovalProxySchema) }), ), coRequestors: z.array(ApprovalCoRequestorSchema).optional(), }); const GetApprovalsSchema = z.object({ appName: z.string().min(1).max(255), status: ApprovalStatus.optional(), approverEmployeeId: z.string().min(1).max(20).optional(), stepResult: ApprovalStepResult.optional(), }); const GetApprovalSchema = z.object({ id: z.uuid(), }); const CreateApprovalSchema = ApprovalSchema.pick({ id: true, number: true, applicationName: true, type: true, status: true, approvalFlows: true, }).extend({ emailBody: z.string().trim().min(1), hqApprovalRequest: HqApprovalRequestSchema.optional(), approvalFlows: z .array( ApprovalFlowSchema.pick({ approvalStage: true, batchSequence: true, stepApprovalOrder: true, steps: true, }).extend({ steps: z.array(ApprovalFlowStepSchema.pick({ approverRole: true, approver: true })).min(1), }), ) .min(1), coRequestors: z.array(ApprovalCoRequestorSchema).optional(), }); const ApproveApprovalSchema = z.object({ id: z.uuid(), result: ApprovalStepResult, resultComment: z.string().trim().max(2000).optional(), emailBody: z.string().trim().min(1), }); const ResubmitApprovalSchema = ApprovalSchema.pick({ id: true, approvalFlows: true, }).extend({ emailBody: z.string().trim().min(1), approvalFlows: z .array( ApprovalFlowSchema.pick({ approvalStage: true, batchSequence: true, stepApprovalOrder: true, steps: true, }).extend({ steps: z.array(ApprovalFlowStepSchema.pick({ approverRole: true, approver: true })).min(1), }), ) .min(1), }); const CancelApprovalSchema = z.object({ id: z.uuid(), comment: z.string().trim().min(1).max(2000), emailBody: z.string().trim().min(1), }); const WithdrawApprovalSchema = z.object({ id: z.uuid(), comment: z.string().trim().min(1).max(2000), emailBody: z.string().trim().min(1), }); ``` ## Examples ```ts import { approvalQueryOptions, approvalsQueryOptions, approveApprovalMutationOptions, createApprovalMutationOptions, } from "wcz-layout/data/client"; import { createApproval } from "wcz-layout/data/server"; import { uuidv7 } from "wcz-layout/utils"; const { queryClient } = Route.useRouteContext(); // fetch const { data: approvals = [] } = useQuery( approvalsQueryOptions({ appName: packageJson.name, status: "WaitingForApproval" }), ); const { data: approval } = useQuery(approvalQueryOptions({ id })); // create const { mutate: create } = useMutation(createApprovalMutationOptions({ queryClient })); create({ id: uuidv7(), number: "REQ-0001", applicationName: packageJson.name, status: "WaitingForApproval", emailBody: "<p>Please approve REQ-0001.</p>", approvalFlows: [ { approvalStage: 1, stepApprovalOrder: "Serial", steps: [{ approver: { employeeId, name, email } }], }, ], }); // approve / reject const { mutate: approve } = useMutation(approveApprovalMutationOptions({ queryClient })); approve({ id, result: "Approved", emailBody: "<p>REQ-0001 was approved.</p>" }); // server (inside another server function) const created = await createApproval({ data: { id, number, applicationName, status, emailBody, approvalFlows }, }); ```