getDriverName() !== 'pgsql') { throw new RuntimeException('InvestMoz requires PostgreSQL with PostGIS. Use the isolated pgsql test environment.'); } DB::statement(<<<'SQL' CREATE TABLE public.projects ( id uuid DEFAULT gen_random_uuid() NOT NULL, source_system text NOT NULL DEFAULT 'investmoz', external_id text, version_no integer NOT NULL DEFAULT 1, data_classification text NOT NULL DEFAULT 'internal', correlation_id uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz, code text NOT NULL, name text NOT NULL, status text NOT NULL, description text, budget_amount numeric(20,2), budget_currency char(3), start_date date, end_date date, metadata jsonb NOT NULL DEFAULT '{}'::jsonb, CONSTRAINT imz_projects_pk PRIMARY KEY (id), CONSTRAINT imz_projects_check_01 CHECK (version_no > 0), CONSTRAINT imz_projects_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')), CONSTRAINT imz_projects_check_03 CHECK (status IN ('draft','planned','active','suspended','completed','cancelled')), CONSTRAINT imz_projects_check_04 CHECK (budget_amount IS NULL OR budget_amount >= 0), CONSTRAINT imz_projects_check_05 CHECK (end_date IS NULL OR start_date IS NULL OR end_date >= start_date), CONSTRAINT imz_projects_check_06 CHECK ((budget_amount IS NULL) = (budget_currency IS NULL)), CONSTRAINT imz_projects_check_07 CHECK (budget_currency IS NULL OR budget_currency ~ '^[A-Z]{3}$') ); SQL); DB::statement(<<<'SQL' CREATE TABLE public.project_locations ( id uuid DEFAULT gen_random_uuid() NOT NULL, source_system text NOT NULL DEFAULT 'investmoz', external_id text, version_no integer NOT NULL DEFAULT 1, data_classification text NOT NULL DEFAULT 'internal', correlation_id uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz, project_id uuid NOT NULL CONSTRAINT imz_project_locations_project_id_fk REFERENCES public.projects(id) ON DELETE CASCADE ON UPDATE CASCADE, geo_location_id uuid NOT NULL CONSTRAINT imz_project_locations_geo_location_id_fk REFERENCES public.geo_locations(id) ON DELETE RESTRICT ON UPDATE CASCADE, role text NOT NULL, CONSTRAINT imz_project_locations_pk PRIMARY KEY (id), CONSTRAINT imz_project_locations_check_01 CHECK (version_no > 0), CONSTRAINT imz_project_locations_check_02 CHECK (data_classification IN ('public','internal','confidential','restricted')), CONSTRAINT imz_project_locations_check_03 CHECK (role IN ('primary','secondary','impact')) ); SQL); } public function down(): void { if (DB::connection()->getDriverName() !== 'pgsql') { throw new RuntimeException('InvestMoz rollback requires PostgreSQL.'); } DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_project_id_fk RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_geo_location_id_fk RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_pk RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_01 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_02 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.project_locations DROP CONSTRAINT IF EXISTS imz_project_locations_check_03 RESTRICT; SQL); DB::statement(<<<'SQL' DROP TABLE IF EXISTS public.project_locations RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_pk RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_01 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_02 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_03 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_04 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_05 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_06 RESTRICT; SQL); DB::statement(<<<'SQL' ALTER TABLE IF EXISTS public.projects DROP CONSTRAINT IF EXISTS imz_projects_check_07 RESTRICT; SQL); DB::statement(<<<'SQL' DROP TABLE IF EXISTS public.projects RESTRICT; SQL); } };