CREATE TABLE IF NOT EXISTS organizations ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name varchar(128) NOT NULL, code varchar(64) NOT NULL, description text, status varchar(16) NOT NULL DEFAULT 'active', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS idx_organizations_code ON organizations (code); CREATE TABLE IF NOT EXISTS organization_members ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), organization_id uuid NOT NULL, user_id uuid NOT NULL, role varchar(16) NOT NULL DEFAULT 'member', created_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS idx_org_members_org_user ON organization_members (organization_id, user_id); CREATE INDEX IF NOT EXISTS idx_org_members_user_id ON organization_members (user_id); ALTER TABLE rooms ADD COLUMN IF NOT EXISTS org_id uuid; CREATE INDEX IF NOT EXISTS idx_rooms_org_id ON rooms (org_id); INSERT INTO organizations (name, code, description, status) SELECT '默认组织', 'default', '系统升级时创建的默认组织,用于兼容历史数据', 'active' WHERE NOT EXISTS (SELECT 1 FROM organizations WHERE code = 'default'); UPDATE rooms SET org_id = (SELECT id FROM organizations WHERE code = 'default') WHERE org_id IS NULL; INSERT INTO organization_members (organization_id, user_id, role) SELECT o.id, u.id, 'member' FROM organizations o, users u WHERE o.code = 'default' AND NOT EXISTS ( SELECT 1 FROM organization_members om WHERE om.organization_id = o.id AND om.user_id = u.id ); CREATE TABLE IF NOT EXISTS device_maintenance_records ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), device_id uuid NOT NULL, kind varchar(16) NOT NULL, title varchar(128) NOT NULL, scheduled_at timestamptz, performed_at timestamptz, performer_id uuid, result text, firmware_from varchar(64), firmware_to varchar(64), cost_amount double precision, cost_unit varchar(16), note text, created_by uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_device_maintenance_device_id ON device_maintenance_records (device_id, created_at); CREATE INDEX IF NOT EXISTS idx_device_maintenance_kind ON device_maintenance_records (kind); CREATE TABLE IF NOT EXISTS production_loss_records ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), room_id uuid, batch_id uuid, record_date timestamptz NOT NULL, death_count integer, culled_count integer, yield_kg double precision, loss_kg double precision, cost_type varchar(32), cost_amount double precision, note text, created_by uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_production_loss_room_date ON production_loss_records (room_id, record_date); CREATE INDEX IF NOT EXISTS idx_production_loss_batch_date ON production_loss_records (batch_id, record_date); CREATE TABLE IF NOT EXISTS case_studies ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), title varchar(128) NOT NULL, disease varchar(64) NOT NULL, source_consultation_id uuid, source_disease_event_id uuid, source_room_id uuid, region varchar(64), case_date timestamptz, summary text, desensitized_payload jsonb NOT NULL DEFAULT '{}'::jsonb, status varchar(16) NOT NULL DEFAULT 'draft', review_note text, reviewer_id uuid, reviewed_at timestamptz, published_at timestamptz, created_by uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_case_studies_disease ON case_studies (disease); CREATE INDEX IF NOT EXISTS idx_case_studies_status ON case_studies (status); CREATE INDEX IF NOT EXISTS idx_case_studies_source_consultation ON case_studies (source_consultation_id); CREATE TABLE IF NOT EXISTS laboratory_results ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), trace_record_id uuid, disease_event_id uuid, sample_id uuid, room_id uuid, batch_id uuid, lab_name varchar(128) NOT NULL, report_no varchar(64) NOT NULL, test_type varchar(32) NOT NULL, result_type varchar(16) NOT NULL, pathogen varchar(128), genotype varchar(128), method varchar(128), sample_no varchar(64), sample_type varchar(32), findings text, report_url varchar(512), tested_at timestamptz, concluded_at timestamptz, created_by uuid, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_laboratory_results_trace_record ON laboratory_results (trace_record_id); CREATE INDEX IF NOT EXISTS idx_laboratory_results_disease_event ON laboratory_results (disease_event_id); CREATE INDEX IF NOT EXISTS idx_laboratory_results_room_date ON laboratory_results (room_id, tested_at); ALTER TABLE rearing_records ADD COLUMN IF NOT EXISTS death_count integer, ADD COLUMN IF NOT EXISTS culled_count integer;