Major additions: - Territory manager system with application workflow - Custom pricing and page builder with Craft.js - Enhanced Stripe Connect onboarding - CodeReadr QR scanning integration - Kiosk mode for venue sales - Super admin dashboard and analytics - MCP integration for AI-powered operations Infrastructure improvements: - Centralized API client and routing system - Enhanced authentication with organization context - Comprehensive theme management system - Advanced event management with custom tabs - Performance monitoring and accessibility features Database schema updates: - Territory management tables - Custom pages and pricing structures - Kiosk PIN system - Enhanced organization profiles - CodeReadr integration tables 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
186 lines
6.3 KiB
PL/PgSQL
186 lines
6.3 KiB
PL/PgSQL
-- CodeREADr Integration Tables
|
|
|
|
-- Table to store CodeREADr configuration for each event
|
|
CREATE TABLE codereadr_configs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
|
organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
|
|
-- CodeREADr API entities
|
|
database_id TEXT NOT NULL,
|
|
service_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
|
|
-- Readable names for reference
|
|
database_name TEXT NOT NULL,
|
|
service_name TEXT NOT NULL,
|
|
user_name TEXT NOT NULL,
|
|
|
|
-- Status and metadata
|
|
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'error')),
|
|
last_sync_at TIMESTAMP WITH TIME ZONE,
|
|
total_scans INTEGER DEFAULT 0,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
|
|
-- Unique constraint to prevent multiple configs per event
|
|
UNIQUE(event_id, organization_id)
|
|
);
|
|
|
|
-- Table to store synchronized scans from CodeREADr
|
|
CREATE TABLE codereadr_scans (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
codereadr_scan_id TEXT NOT NULL UNIQUE, -- CodeREADr's scan ID
|
|
|
|
-- Event and service references
|
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
|
service_id TEXT NOT NULL,
|
|
|
|
-- Scan data
|
|
ticket_uuid TEXT NOT NULL,
|
|
scan_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
response TEXT, -- CodeREADr response data
|
|
device_id TEXT,
|
|
location JSONB, -- {latitude, longitude} if available
|
|
|
|
-- Sync metadata
|
|
synced_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
webhook_processed BOOLEAN DEFAULT false,
|
|
ticket_updated BOOLEAN DEFAULT false,
|
|
error_message TEXT,
|
|
|
|
-- Index for quick lookups
|
|
INDEX idx_codereadr_scans_event_id (event_id),
|
|
INDEX idx_codereadr_scans_ticket_uuid (ticket_uuid),
|
|
INDEX idx_codereadr_scans_timestamp (scan_timestamp),
|
|
INDEX idx_codereadr_scans_service_id (service_id)
|
|
);
|
|
|
|
-- Add scan_method column to existing tickets table to track how ticket was scanned
|
|
ALTER TABLE tickets ADD COLUMN IF NOT EXISTS scan_method TEXT DEFAULT 'manual' CHECK (scan_method IN ('manual', 'qr', 'codereadr', 'api'));
|
|
|
|
-- Add scan_method column to existing scan_attempts table
|
|
ALTER TABLE scan_attempts ADD COLUMN IF NOT EXISTS scan_method TEXT DEFAULT 'manual' CHECK (scan_method IN ('manual', 'qr', 'codereadr', 'api'));
|
|
|
|
-- Update existing scan attempts to have a scan_method
|
|
UPDATE scan_attempts SET scan_method = 'qr' WHERE scan_method IS NULL;
|
|
UPDATE tickets SET scan_method = 'qr' WHERE scan_method IS NULL AND checked_in = true;
|
|
|
|
-- Add RLS policies for codereadr_configs table
|
|
ALTER TABLE codereadr_configs ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Users can only access configs for their organization
|
|
CREATE POLICY "Users can view codereadr_configs for their organization" ON codereadr_configs
|
|
FOR SELECT USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can insert codereadr_configs for their organization" ON codereadr_configs
|
|
FOR INSERT WITH CHECK (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can update codereadr_configs for their organization" ON codereadr_configs
|
|
FOR UPDATE USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can delete codereadr_configs for their organization" ON codereadr_configs
|
|
FOR DELETE USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Admin bypass for codereadr_configs
|
|
CREATE POLICY "Admins can manage all codereadr_configs" ON codereadr_configs
|
|
FOR ALL USING (
|
|
EXISTS (
|
|
SELECT 1 FROM users
|
|
WHERE id = auth.uid()
|
|
AND role = 'admin'
|
|
)
|
|
);
|
|
|
|
-- Add RLS policies for codereadr_scans table
|
|
ALTER TABLE codereadr_scans ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Users can only access scans for events in their organization
|
|
CREATE POLICY "Users can view codereadr_scans for their organization" ON codereadr_scans
|
|
FOR SELECT USING (
|
|
event_id IN (
|
|
SELECT e.id FROM events e
|
|
JOIN users u ON e.organization_id = u.organization_id
|
|
WHERE u.id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can insert codereadr_scans for their organization" ON codereadr_scans
|
|
FOR INSERT WITH CHECK (
|
|
event_id IN (
|
|
SELECT e.id FROM events e
|
|
JOIN users u ON e.organization_id = u.organization_id
|
|
WHERE u.id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Admin bypass for codereadr_scans
|
|
CREATE POLICY "Admins can manage all codereadr_scans" ON codereadr_scans
|
|
FOR ALL USING (
|
|
EXISTS (
|
|
SELECT 1 FROM users
|
|
WHERE id = auth.uid()
|
|
AND role = 'admin'
|
|
)
|
|
);
|
|
|
|
-- Add indexes for better performance
|
|
CREATE INDEX IF NOT EXISTS idx_codereadr_configs_event_id ON codereadr_configs(event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_codereadr_configs_organization_id ON codereadr_configs(organization_id);
|
|
CREATE INDEX IF NOT EXISTS idx_codereadr_configs_status ON codereadr_configs(status);
|
|
|
|
-- Add function to automatically update updated_at timestamp
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
-- Add trigger for codereadr_configs updated_at
|
|
CREATE TRIGGER update_codereadr_configs_updated_at
|
|
BEFORE UPDATE ON codereadr_configs
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Add useful views for reporting
|
|
CREATE VIEW codereadr_scan_summary AS
|
|
SELECT
|
|
c.event_id,
|
|
c.organization_id,
|
|
c.database_name,
|
|
c.service_name,
|
|
c.status,
|
|
c.last_sync_at,
|
|
COUNT(s.id) as total_scans,
|
|
COUNT(CASE WHEN s.ticket_updated = true THEN 1 END) as successful_checkins,
|
|
COUNT(CASE WHEN s.webhook_processed = true THEN 1 END) as webhook_scans,
|
|
MAX(s.scan_timestamp) as latest_scan_time
|
|
FROM codereadr_configs c
|
|
LEFT JOIN codereadr_scans s ON c.event_id = s.event_id
|
|
GROUP BY c.event_id, c.organization_id, c.database_name, c.service_name, c.status, c.last_sync_at;
|
|
|
|
-- Add RLS to the view
|
|
ALTER VIEW codereadr_scan_summary SET (security_invoker = true);
|
|
|
|
COMMENT ON TABLE codereadr_configs IS 'Configuration for CodeREADr integration per event';
|
|
COMMENT ON TABLE codereadr_scans IS 'Synchronized scan records from CodeREADr';
|
|
COMMENT ON VIEW codereadr_scan_summary IS 'Summary view of CodeREADr scan statistics per event'; |