import { jsonb, text, timestamp, integer, serial } from "drizzle-orm/pg-core"; import { knoxSchema } from "./employee"; import { approvalLogs } from "./approvals"; import { users } from "@/db/schema/users"; /** * Pending Actions 테이블 * * 결재가 필요한 액션들을 보류(pending) 상태로 저장하고, * 결재 승인 후 실제 비즈니스 로직을 실행하는 워크플로우를 관리 * * 워크플로우: * 1. 사용자 요청 → pendingAction 생성 (status: 'pending') * 2. Knox 결재 상신 → approvalLog와 연결 * 3. [폴링으로 결재 상태 감지] * 4. 결재 승인 → status: 'approved' → 액션 실행 * 5. 실행 완료 → status: 'executed' */ export const pendingActions = knoxSchema.table("pending_actions", { // 기본 정보 id: serial("id").primaryKey(), // 결재 연결 (approvalLogs의 apInfId와 논리적으로 연결) // 주의: FK 제약 조건을 사용하지 않음 // 이유: pending_actions는 Knox 상신 전에 생성되지만, // approval_logs는 Knox와 동기화되어 나중에 생성되므로 // FK 제약이 있으면 Saga Pattern의 순서(DB → Knox)를 지킬 수 없음 apInfId: text("ap_inf_id").notNull(), // 액션 정보 actionType: text("action_type").notNull(), // 예: 'vendor_investigation_request', 'purchase_order_request' actionPayload: jsonb("action_payload").notNull(), // 실행에 필요한 모든 파라미터 저장 // 상태 관리 // pending: 결재 대기 중 // approved: 결재 승인됨 (실행 대기) // executed: 실행 완료 // failed: 실행 실패 // rejected: 결재 반려됨 // cancelled: 결재 취소됨 status: text("status").notNull().default("pending"), // 실행 결과 (옵션) executionResult: jsonb("execution_result"), // 실행 결과 저장 (성공/실패 정보) errorMessage: text("error_message"), // 실패 시 에러 메시지 // 실행 시간 executedAt: timestamp("executed_at"), // 실제 액션이 실행된 시간 // 생성자 정보 createdBy: integer("created_by") .notNull() .references(() => users.id, { onDelete: "set null" }), // 타임스탬프 createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), });