Files
LWLT-AIBOT/control-plane/migrations/013_business_parser_modes.sql

96 lines
4.8 KiB
SQL

CREATE TABLE IF NOT EXISTS business_parser_settings (
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
route_id text NOT NULL,
mode text NOT NULL DEFAULT 'ai',
revision bigint NOT NULL DEFAULT 1,
updated_by uuid REFERENCES users(id) ON DELETE SET NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (organization_id, route_id),
CONSTRAINT business_parser_settings_route_check CHECK (route_id IN (
'team_order_create', 'team_order_batch_create', 'shared_plan_create',
'shared_child_order_create', 'passenger_list_import_independent',
'passenger_list_import_shared_child', 'arrangement_guide_create',
'arrangement_vehicle_create', 'arrangement_hotel_create',
'arrangement_transport_create', 'arrangement_other_create',
'order_update_shared_plan', 'order_update_shared_child',
'order_update_independent', 'arrangement_hotel_update',
'order_cancel', 'order_restore', 'confirmation_export'
)),
CONSTRAINT business_parser_settings_mode_check CHECK (mode IN ('ai', 'shadow', 'auto', 'program')),
CONSTRAINT business_parser_settings_revision_check CHECK (revision >= 1)
);
CREATE INDEX IF NOT EXISTS business_parser_settings_updated_idx
ON business_parser_settings (organization_id, updated_at DESC);
ALTER TABLE tasks
ADD COLUMN IF NOT EXISTS business_route_id text,
ADD COLUMN IF NOT EXISTS input_contract_version text,
ADD COLUMN IF NOT EXISTS parser_mode text NOT NULL DEFAULT 'ai' CHECK (parser_mode IN ('ai', 'shadow', 'auto', 'program')),
ADD COLUMN IF NOT EXISTS parser_config_revision bigint NOT NULL DEFAULT 0 CHECK (parser_config_revision >= 0),
ADD COLUMN IF NOT EXISTS parser_engine_affinity text CHECK (parser_engine_affinity IN ('ai', 'program')),
ADD COLUMN IF NOT EXISTS parser_engine text CHECK (parser_engine IN ('ai', 'program')),
ADD COLUMN IF NOT EXISTS parser_version text,
ADD COLUMN IF NOT EXISTS parser_fallback_reason text,
ADD COLUMN IF NOT EXISTS parser_comparison_status text CHECK (parser_comparison_status IN ('equivalent', 'different', 'not_comparable')),
ADD COLUMN IF NOT EXISTS parser_reparse_count integer NOT NULL DEFAULT 0 CHECK (parser_reparse_count BETWEEN 0 AND 1);
UPDATE tasks
SET parser_mode = 'ai',
parser_config_revision = 0,
parser_engine_affinity = 'ai',
parser_engine = COALESCE(parser_engine, CASE WHEN parse_response IS NOT NULL OR parse_response_ciphertext IS NOT NULL THEN 'ai' END),
parser_version = COALESCE(parser_version, CASE WHEN parse_response IS NOT NULL OR parse_response_ciphertext IS NOT NULL THEN 'legacy-ai' END);
CREATE INDEX IF NOT EXISTS tasks_parser_route_idx
ON tasks (organization_id, business_route_id, parser_mode, created_at DESC);
CREATE TABLE IF NOT EXISTS parse_decisions (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
task_id uuid NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
attempt_no integer NOT NULL,
route_id text,
configured_mode text NOT NULL,
authoritative_engine text NOT NULL,
program_version text,
ai_prompt_version text,
fallback_reason text,
comparison_status text,
program_status text,
ai_status text,
program_error_code text,
ai_error_code text,
program_duration_ms integer,
ai_duration_ms integer,
program_result_hash text,
ai_result_hash text,
program_result_ciphertext text,
ai_result_ciphertext text,
diff_summary jsonb NOT NULL DEFAULT '{}'::jsonb,
review_status text,
reviewed_by uuid REFERENCES users(id) ON DELETE SET NULL,
reviewed_at timestamptz,
review_note_ciphertext text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT parse_decisions_attempt_check CHECK (attempt_no >= 1),
CONSTRAINT parse_decisions_mode_check CHECK (configured_mode IN ('ai', 'shadow', 'auto', 'program')),
CONSTRAINT parse_decisions_engine_check CHECK (authoritative_engine IN ('ai', 'program')),
CONSTRAINT parse_decisions_comparison_check CHECK (comparison_status IS NULL OR comparison_status IN ('equivalent', 'different', 'not_comparable')),
CONSTRAINT parse_decisions_review_check CHECK (review_status IS NULL OR review_status IN ('pending', 'equivalent', 'program_correct', 'ai_correct', 'both_wrong')),
CONSTRAINT parse_decisions_duration_check CHECK (
(program_duration_ms IS NULL OR program_duration_ms >= 0)
AND (ai_duration_ms IS NULL OR ai_duration_ms >= 0)
),
UNIQUE (task_id, attempt_no)
);
CREATE INDEX IF NOT EXISTS parse_decisions_route_stats_idx
ON parse_decisions (organization_id, route_id, created_at DESC);
CREATE INDEX IF NOT EXISTS parse_decisions_review_idx
ON parse_decisions (organization_id, review_status, created_at DESC)
WHERE review_status IS NOT NULL;