CREATE TYPE "AttendanceCorrectionKind" AS ENUM ('missed_punch', 'out', 'overtime'); CREATE TYPE "AttendanceCorrectionStatus" AS ENUM ('reviewing', 'approved', 'rejected', 'cancelled'); CREATE TABLE "wecom_checkin_sync_runs" ( "id" UUID NOT NULL, "start_date" DATE NOT NULL, "end_date" DATE NOT NULL, "status" VARCHAR(24) NOT NULL DEFAULT 'running', "employee_count" INTEGER NOT NULL DEFAULT 0, "record_count" INTEGER NOT NULL DEFAULT 0, "error_code" VARCHAR(80), "error_message" TEXT, "triggered_by" UUID, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "wecom_checkin_sync_runs_pkey" PRIMARY KEY ("id") ); CREATE TABLE "wecom_checkin_records" ( "id" UUID NOT NULL, "sync_run_id" UUID NOT NULL, "employee_id" UUID NOT NULL, "external_user_id" VARCHAR(128) NOT NULL, "checkin_time" TIMESTAMP(3) NOT NULL, "checkin_date" DATE NOT NULL, "checkin_type" VARCHAR(40) NOT NULL, "exception_type" VARCHAR(80), "source_type" VARCHAR(40), "result" VARCHAR(80), "raw_hash" VARCHAR(64) NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "wecom_checkin_records_pkey" PRIMARY KEY ("id") ); CREATE TABLE "attendance_corrections" ( "id" UUID NOT NULL, "owner_id" UUID NOT NULL, "department_id" UUID, "kind" "AttendanceCorrectionKind" NOT NULL, "status" "AttendanceCorrectionStatus" NOT NULL DEFAULT 'reviewing', "work_date" DATE NOT NULL, "start_at" TIMESTAMP(3), "end_at" TIMESTAMP(3), "missed_punch_at" TIMESTAMP(3), "reason" TEXT NOT NULL, "location_summary" TEXT, "compensation_policy" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "created_by" UUID, "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_by" UUID, CONSTRAINT "attendance_corrections_pkey" PRIMARY KEY ("id") ); ALTER TABLE "workflow_instances" ADD COLUMN "attendance_correction_id" UUID; CREATE UNIQUE INDEX "wecom_checkin_records_user_time_type_ux" ON "wecom_checkin_records"("external_user_id", "checkin_time", "checkin_type"); CREATE INDEX "idx_wecom_checkin_sync_runs_status_created" ON "wecom_checkin_sync_runs"("status", "created_at"); CREATE INDEX "idx_wecom_checkin_sync_runs_range" ON "wecom_checkin_sync_runs"("start_date", "end_date"); CREATE INDEX "idx_wecom_checkin_sync_runs_triggered_by" ON "wecom_checkin_sync_runs"("triggered_by"); CREATE INDEX "idx_wecom_checkin_records_employee_date" ON "wecom_checkin_records"("employee_id", "checkin_date"); CREATE INDEX "idx_wecom_checkin_records_sync_run" ON "wecom_checkin_records"("sync_run_id"); CREATE INDEX "idx_attendance_corrections_owner_date" ON "attendance_corrections"("owner_id", "work_date"); CREATE INDEX "idx_attendance_corrections_department_status" ON "attendance_corrections"("department_id", "status"); CREATE INDEX "idx_attendance_corrections_status_updated" ON "attendance_corrections"("status", "updated_at"); CREATE INDEX "workflow_instances_attendance_correction_id_idx" ON "workflow_instances"("attendance_correction_id"); ALTER TABLE "wecom_checkin_sync_runs" ADD CONSTRAINT "wecom_checkin_sync_runs_triggered_by_fkey" FOREIGN KEY ("triggered_by") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "wecom_checkin_records" ADD CONSTRAINT "wecom_checkin_records_sync_run_id_fkey" FOREIGN KEY ("sync_run_id") REFERENCES "wecom_checkin_sync_runs"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "wecom_checkin_records" ADD CONSTRAINT "wecom_checkin_records_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "attendance_corrections" ADD CONSTRAINT "attendance_corrections_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "attendance_corrections" ADD CONSTRAINT "attendance_corrections_department_id_fkey" FOREIGN KEY ("department_id") REFERENCES "departments"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "workflow_instances" ADD CONSTRAINT "workflow_instances_attendance_correction_id_fkey" FOREIGN KEY ("attendance_correction_id") REFERENCES "attendance_corrections"("id") ON DELETE CASCADE ON UPDATE CASCADE; INSERT INTO "feature_flags" ( "id", "flag_key", "override_mode", "rollout_type", "department_ids", "note", "version", "created_at", "updated_at" ) VALUES ( '9902678f-58af-4326-b2ce-04690a0b5fa9'::uuid, 'attendance_unified_v1', 'force_off', 'global', '[]'::jsonb, 'bootstrap default: force_off', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP ) ON CONFLICT ("flag_key") DO NOTHING; INSERT INTO "workflow_definitions" ( "id", "name", "entity_type", "definition_json", "version", "is_active", "created_at", "created_by" ) VALUES ( '113c2ac4-a58b-470b-bd46-c9a3cdc34e97'::uuid, '考勤修正审批流程(V1)', 'attendance_correction', '{"steps":[{"id":"attendance_correction_approval_manager","name":"直属经理审批","type":"approval","assignee_rule":{"type":"department_manager"}}]}'::jsonb, 1, true, CURRENT_TIMESTAMP, NULL ) ON CONFLICT ("entity_type", "version") DO UPDATE SET "name" = EXCLUDED."name", "definition_json" = EXCLUDED."definition_json", "is_active" = true;