- Create gbp_audits table with all required fields: - completeness_score (0-100) - fields_status and recommendations (JSONB) - Individual field flags (has_name, has_phone, etc.) - Photo and review metrics - Google Place integration fields - Audit metadata (source, version, errors) - Add indexes for company_id, audit_date, and score - Add update trigger for updated_at timestamp - Create views: v_company_gbp_overview, v_gbp_audit_history - Include GRANT statements for nordabiz_app user Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
217 lines
7.5 KiB
PL/PgSQL
217 lines
7.5 KiB
PL/PgSQL
-- ============================================================
|
|
-- NordaBiz - Migration: Google Business Profile (GBP) Audit Tables
|
|
-- ============================================================
|
|
-- Created: 2026-01-08
|
|
-- Description:
|
|
-- - Creates gbp_audits table for storing GBP completeness audit results
|
|
-- - Tracks field-by-field status with JSONB for flexibility
|
|
-- - Stores AI-generated recommendations
|
|
-- - Includes indexes and helpful views
|
|
--
|
|
-- Usage:
|
|
-- PostgreSQL: psql -h localhost -U nordabiz_app -d nordabiz -f add_gbp_audit.sql
|
|
-- SQLite: Not fully supported (JSONB columns)
|
|
-- ============================================================
|
|
|
|
-- ============================================================
|
|
-- 1. MAIN GBP_AUDITS TABLE
|
|
-- ============================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gbp_audits (
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
-- Company reference
|
|
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
|
|
-- Audit timestamp
|
|
audit_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
-- Completeness scoring (0-100)
|
|
completeness_score INTEGER,
|
|
|
|
-- Field-by-field status tracking (JSONB)
|
|
-- Example: {"name": {"status": "complete", "value": "Company Name"}, "phone": {"status": "missing"}, ...}
|
|
fields_status JSONB,
|
|
|
|
-- AI-generated recommendations (JSONB)
|
|
-- Example: [{"priority": "high", "field": "description", "recommendation": "Add a detailed business description..."}, ...]
|
|
recommendations JSONB,
|
|
|
|
-- Individual field completion flags
|
|
has_name BOOLEAN DEFAULT FALSE,
|
|
has_address BOOLEAN DEFAULT FALSE,
|
|
has_phone BOOLEAN DEFAULT FALSE,
|
|
has_website BOOLEAN DEFAULT FALSE,
|
|
has_hours BOOLEAN DEFAULT FALSE,
|
|
has_categories BOOLEAN DEFAULT FALSE,
|
|
has_photos BOOLEAN DEFAULT FALSE,
|
|
has_description BOOLEAN DEFAULT FALSE,
|
|
has_services BOOLEAN DEFAULT FALSE,
|
|
has_reviews BOOLEAN DEFAULT FALSE,
|
|
|
|
-- Photo metrics
|
|
photo_count INTEGER DEFAULT 0,
|
|
logo_present BOOLEAN DEFAULT FALSE,
|
|
cover_photo_present BOOLEAN DEFAULT FALSE,
|
|
|
|
-- Review metrics
|
|
review_count INTEGER DEFAULT 0,
|
|
average_rating NUMERIC(2, 1),
|
|
|
|
-- Google Place integration
|
|
google_place_id VARCHAR(100),
|
|
google_maps_url VARCHAR(500),
|
|
|
|
-- Audit metadata
|
|
audit_source VARCHAR(50) DEFAULT 'manual', -- manual, automated, api
|
|
audit_version VARCHAR(20) DEFAULT '1.0',
|
|
audit_errors TEXT,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
COMMENT ON TABLE gbp_audits IS 'Google Business Profile completeness audit results';
|
|
COMMENT ON COLUMN gbp_audits.completeness_score IS 'Overall GBP completeness score 0-100';
|
|
COMMENT ON COLUMN gbp_audits.fields_status IS 'Field-by-field status with values as JSON';
|
|
COMMENT ON COLUMN gbp_audits.recommendations IS 'AI-generated improvement recommendations as JSON array';
|
|
COMMENT ON COLUMN gbp_audits.audit_source IS 'How audit was triggered: manual, automated, api';
|
|
COMMENT ON COLUMN gbp_audits.google_place_id IS 'Google Places API place_id for verification';
|
|
COMMENT ON COLUMN gbp_audits.google_maps_url IS 'Direct link to Google Maps listing';
|
|
|
|
-- ============================================================
|
|
-- 2. INDEXES FOR PERFORMANCE
|
|
-- ============================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gbp_audits_company ON gbp_audits(company_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gbp_audits_date ON gbp_audits(audit_date);
|
|
CREATE INDEX IF NOT EXISTS idx_gbp_audits_score ON gbp_audits(completeness_score);
|
|
CREATE INDEX IF NOT EXISTS idx_gbp_audits_company_date ON gbp_audits(company_id, audit_date DESC);
|
|
|
|
-- ============================================================
|
|
-- 3. UPDATE TRIGGER FOR updated_at
|
|
-- ============================================================
|
|
|
|
CREATE OR REPLACE FUNCTION gbp_audits_update_timestamp()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gbp_audits_update ON gbp_audits;
|
|
CREATE TRIGGER trigger_gbp_audits_update
|
|
BEFORE UPDATE ON gbp_audits
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION gbp_audits_update_timestamp();
|
|
|
|
-- ============================================================
|
|
-- 4. GBP AUDIT OVERVIEW VIEW
|
|
-- ============================================================
|
|
|
|
CREATE OR REPLACE VIEW v_company_gbp_overview AS
|
|
SELECT
|
|
c.id,
|
|
c.name,
|
|
c.slug,
|
|
c.website,
|
|
cat.name as category_name,
|
|
ga.completeness_score,
|
|
ga.has_name,
|
|
ga.has_address,
|
|
ga.has_phone,
|
|
ga.has_website,
|
|
ga.has_hours,
|
|
ga.has_categories,
|
|
ga.has_photos,
|
|
ga.has_description,
|
|
ga.has_services,
|
|
ga.has_reviews,
|
|
ga.photo_count,
|
|
ga.review_count,
|
|
ga.average_rating,
|
|
ga.google_place_id,
|
|
ga.audit_date,
|
|
ga.audit_source,
|
|
-- Score category
|
|
CASE
|
|
WHEN ga.completeness_score >= 90 THEN 'excellent'
|
|
WHEN ga.completeness_score >= 70 THEN 'good'
|
|
WHEN ga.completeness_score >= 50 THEN 'needs_work'
|
|
WHEN ga.completeness_score IS NOT NULL THEN 'poor'
|
|
ELSE 'not_audited'
|
|
END as score_category
|
|
FROM companies c
|
|
LEFT JOIN categories cat ON c.category_id = cat.id
|
|
LEFT JOIN LATERAL (
|
|
SELECT * FROM gbp_audits
|
|
WHERE company_id = c.id
|
|
ORDER BY audit_date DESC
|
|
LIMIT 1
|
|
) ga ON TRUE
|
|
ORDER BY ga.completeness_score DESC NULLS LAST;
|
|
|
|
COMMENT ON VIEW v_company_gbp_overview IS 'Latest GBP audit results per company for dashboard';
|
|
|
|
-- ============================================================
|
|
-- 5. GBP AUDIT HISTORY VIEW
|
|
-- ============================================================
|
|
|
|
CREATE OR REPLACE VIEW v_gbp_audit_history AS
|
|
SELECT
|
|
ga.id as audit_id,
|
|
c.id as company_id,
|
|
c.name as company_name,
|
|
c.slug as company_slug,
|
|
ga.completeness_score,
|
|
ga.audit_date,
|
|
ga.audit_source,
|
|
ga.audit_version,
|
|
-- Previous score for comparison
|
|
LAG(ga.completeness_score) OVER (
|
|
PARTITION BY ga.company_id
|
|
ORDER BY ga.audit_date
|
|
) as previous_score,
|
|
-- Score change
|
|
ga.completeness_score - LAG(ga.completeness_score) OVER (
|
|
PARTITION BY ga.company_id
|
|
ORDER BY ga.audit_date
|
|
) as score_change
|
|
FROM gbp_audits ga
|
|
JOIN companies c ON ga.company_id = c.id
|
|
ORDER BY ga.audit_date DESC;
|
|
|
|
COMMENT ON VIEW v_gbp_audit_history IS 'GBP audit history with score trend tracking';
|
|
|
|
-- ============================================================
|
|
-- 6. GRANTS FOR APPLICATION USER
|
|
-- ============================================================
|
|
|
|
-- Grant permissions on table
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE gbp_audits TO nordabiz_app;
|
|
|
|
-- Grant permissions on sequence
|
|
GRANT USAGE, SELECT ON SEQUENCE gbp_audits_id_seq TO nordabiz_app;
|
|
|
|
-- Grant permissions on views
|
|
GRANT SELECT ON v_company_gbp_overview TO nordabiz_app;
|
|
GRANT SELECT ON v_gbp_audit_history TO nordabiz_app;
|
|
|
|
-- ============================================================
|
|
-- MIGRATION COMPLETE
|
|
-- ============================================================
|
|
|
|
-- Verify migration (PostgreSQL only)
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE 'GBP Audit migration completed successfully!';
|
|
RAISE NOTICE 'Created:';
|
|
RAISE NOTICE ' - Table: gbp_audits';
|
|
RAISE NOTICE ' - Indexes: company_id, audit_date, completeness_score, company_date';
|
|
RAISE NOTICE ' - Trigger: updated_at auto-update';
|
|
RAISE NOTICE ' - Views: v_company_gbp_overview, v_gbp_audit_history';
|
|
RAISE NOTICE ' - Grants: nordabiz_app permissions';
|
|
END $$;
|