CREATE TABLE IF NOT EXISTS accounts ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, email VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, full_name VARCHAR(255) NOT NULL DEFAULT 'Unknown', first_name VARCHAR(255) NOT NULL DEFAULT 'FirstName', last_name VARCHAR(255) NOT NULL DEFAULT 'LastName', phone VARCHAR(255), city VARCHAR(255), organization_form VARCHAR(255), organization_name VARCHAR(255), organization_short VARCHAR(255), inn VARCHAR(255), personal_inn VARCHAR(255), is_active BOOLEAN NOT NULL DEFAULT TRUE, is_verified BOOLEAN NOT NULL DEFAULT FALSE, role VARCHAR(255) NOT NULL DEFAULT 'user' ); CREATE INDEX IF NOT EXISTS idx_accounts_deleted_at ON accounts(deleted_at); CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_email ON accounts(email); CREATE TABLE IF NOT EXISTS update_histories ( id BIGSERIAL PRIMARY KEY, model_id BIGINT, model_type VARCHAR(255), timestamp TIMESTAMPTZ, updated_by BIGINT ); CREATE INDEX IF NOT EXISTS idx_update_histories_updated_by ON update_histories(updated_by); CREATE TABLE IF NOT EXISTS objects ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, owner_id BIGINT, title VARCHAR(255) DEFAULT '', short_name VARCHAR(255) NOT NULL, long_name VARCHAR(255), type VARCHAR(255), price DECIMAL DEFAULT 0, price_period VARCHAR(255) DEFAULT 'per_unit', phone VARCHAR(255), email VARCHAR(255), site VARCHAR(255), short_description VARCHAR(255), description VARCHAR(255), address VARCHAR(255), latitude DECIMAL, longitude DECIMAL, is_active BOOLEAN DEFAULT TRUE, is_verified BOOLEAN DEFAULT FALSE, status VARCHAR(255) DEFAULT 'active', view_count BIGINT DEFAULT 0, feedback_count BIGINT DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_objects_deleted_at ON objects(deleted_at); CREATE INDEX IF NOT EXISTS idx_objects_is_active ON objects(is_active); CREATE TABLE IF NOT EXISTS object_images ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, object_id BIGINT NOT NULL, url VARCHAR(255) NOT NULL, is_primary BOOLEAN DEFAULT FALSE, sort_order BIGINT DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_object_images_deleted_at ON object_images(deleted_at); CREATE INDEX IF NOT EXISTS idx_object_images_object_id ON object_images(object_id); CREATE TABLE IF NOT EXISTS amenities ( id BIGSERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, category VARCHAR(255), icon VARCHAR(255), description VARCHAR(255) ); CREATE UNIQUE INDEX IF NOT EXISTS idx_amenities_name ON amenities(name); CREATE TABLE IF NOT EXISTS object_amenities ( object_id BIGINT NOT NULL, amenity_id BIGINT NOT NULL, PRIMARY KEY (object_id, amenity_id) ); CREATE TABLE IF NOT EXISTS ratings ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, owner_id BIGINT, object_id BIGINT, platform VARCHAR(255), average_score DECIMAL, total_votes BIGINT DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_ratings_deleted_at ON ratings(deleted_at); CREATE TABLE IF NOT EXISTS vote_breakdowns ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, rating_id BIGINT, score_1 BIGINT DEFAULT 0, score_2 BIGINT DEFAULT 0, score_3 BIGINT DEFAULT 0, score_4 BIGINT DEFAULT 0, score_5 BIGINT DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_vote_breakdowns_deleted_at ON vote_breakdowns(deleted_at); CREATE TABLE IF NOT EXISTS rating_votes ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, platform VARCHAR(255), target_id BIGINT, voter_id BIGINT, score BIGINT ); CREATE INDEX IF NOT EXISTS idx_rating_votes_deleted_at ON rating_votes(deleted_at); CREATE TABLE IF NOT EXISTS feedbacks ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, owner_id BIGINT NOT NULL, object_id BIGINT NOT NULL, platform VARCHAR(255), score BIGINT, comment_count BIGINT DEFAULT 0, text VARCHAR(255) ); CREATE INDEX IF NOT EXISTS idx_feedbacks_deleted_at ON feedbacks(deleted_at); CREATE INDEX IF NOT EXISTS idx_feedbacks_owner_id ON feedbacks(owner_id); CREATE INDEX IF NOT EXISTS idx_feedbacks_object_id ON feedbacks(object_id); CREATE TABLE IF NOT EXISTS comments ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, author_id BIGINT NOT NULL, feedback_id BIGINT NOT NULL, text VARCHAR(255) NOT NULL, parent_id BIGINT, is_edited BOOLEAN DEFAULT FALSE, is_verified BOOLEAN DEFAULT FALSE ); CREATE INDEX IF NOT EXISTS idx_comments_deleted_at ON comments(deleted_at); CREATE INDEX IF NOT EXISTS idx_comments_author_id ON comments(author_id); CREATE INDEX IF NOT EXISTS idx_comments_feedback_id ON comments(feedback_id); CREATE INDEX IF NOT EXISTS idx_comments_parent_id ON comments(parent_id); CREATE TABLE IF NOT EXISTS appeals ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, author_id BIGINT, type VARCHAR(255) NOT NULL, status VARCHAR(255) NOT NULL DEFAULT 'new', priority VARCHAR(255) NOT NULL DEFAULT 'medium', title VARCHAR(255) NOT NULL, message TEXT NOT NULL, attachments TEXT[], contact_name VARCHAR(255), contact_email VARCHAR(255), contact_phone VARCHAR(255), object_id BIGINT, feedback_id BIGINT, comment_id BIGINT, ip_address VARCHAR(255), user_agent VARCHAR(255), assigned_to_id BIGINT, resolved_at TIMESTAMPTZ, resolved_by BIGINT, resolution VARCHAR(255), category VARCHAR(255), labels TEXT[], custom_data JSONB ); CREATE INDEX IF NOT EXISTS idx_appeals_deleted_at ON appeals(deleted_at); CREATE INDEX IF NOT EXISTS idx_appeals_author_id ON appeals(author_id); CREATE INDEX IF NOT EXISTS idx_appeals_type ON appeals(type); CREATE INDEX IF NOT EXISTS idx_appeals_status ON appeals(status); CREATE INDEX IF NOT EXISTS idx_appeals_priority ON appeals(priority); CREATE INDEX IF NOT EXISTS idx_appeals_object_id ON appeals(object_id); CREATE INDEX IF NOT EXISTS idx_appeals_feedback_id ON appeals(feedback_id); CREATE INDEX IF NOT EXISTS idx_appeals_comment_id ON appeals(comment_id); CREATE INDEX IF NOT EXISTS idx_appeals_assigned_to_id ON appeals(assigned_to_id); CREATE TABLE IF NOT EXISTS appeal_histories ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, appeal_id BIGINT NOT NULL, user_id BIGINT, old_status VARCHAR(255), new_status VARCHAR(255), comment VARCHAR(255) ); CREATE INDEX IF NOT EXISTS idx_appeal_histories_deleted_at ON appeal_histories(deleted_at); CREATE INDEX IF NOT EXISTS idx_appeal_histories_appeal_id ON appeal_histories(appeal_id); CREATE TABLE IF NOT EXISTS password_resets ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, account_id BIGINT NOT NULL, token VARCHAR(255) NOT NULL, expires_at TIMESTAMPTZ NOT NULL, used BOOLEAN DEFAULT FALSE ); CREATE INDEX IF NOT EXISTS idx_password_resets_deleted_at ON password_resets(deleted_at); CREATE INDEX IF NOT EXISTS idx_password_resets_account_id ON password_resets(account_id); CREATE UNIQUE INDEX IF NOT EXISTS idx_password_resets_token ON password_resets(token);