Initial commit - Black Canyon Tickets whitelabel platform

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-08 12:31:31 -06:00
commit 997c129383
139 changed files with 60476 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
-- Add printed tickets support
-- This migration adds support for printed tickets with barcodes
-- Create printed_tickets table
CREATE TABLE printed_tickets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
barcode_number TEXT NOT NULL UNIQUE,
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
ticket_type_id UUID NOT NULL REFERENCES ticket_types(id) ON DELETE CASCADE,
organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
status TEXT NOT NULL DEFAULT 'valid' CHECK (status IN ('valid', 'used', 'invalid')),
batch_number TEXT,
notes TEXT,
issued_by UUID REFERENCES users(id),
checked_in_at TIMESTAMP WITH TIME ZONE,
scanned_by UUID REFERENCES users(id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create scan_attempts table for audit logging
CREATE TABLE scan_attempts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
barcode_number TEXT NOT NULL,
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
scanned_by UUID REFERENCES users(id),
result TEXT NOT NULL CHECK (result IN ('SUCCESS', 'INVALID_BARCODE', 'WRONG_EVENT', 'ALREADY_USED', 'NOT_VALID')),
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Add indexes for performance
CREATE INDEX idx_printed_tickets_barcode ON printed_tickets(barcode_number);
CREATE INDEX idx_printed_tickets_event_id ON printed_tickets(event_id);
CREATE INDEX idx_printed_tickets_org_id ON printed_tickets(organization_id);
CREATE INDEX idx_scan_attempts_barcode ON scan_attempts(barcode_number);
CREATE INDEX idx_scan_attempts_event_id ON scan_attempts(event_id);
CREATE INDEX idx_scan_attempts_created_at ON scan_attempts(created_at);
-- Add RLS policies for multi-tenant security
ALTER TABLE printed_tickets ENABLE ROW LEVEL SECURITY;
ALTER TABLE scan_attempts ENABLE ROW LEVEL SECURITY;
-- Policies for printed_tickets
CREATE POLICY "Users can view printed tickets in their organization" ON printed_tickets
FOR SELECT USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id = printed_tickets.organization_id
)
);
CREATE POLICY "Users can insert printed tickets in their organization" ON printed_tickets
FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id = printed_tickets.organization_id
)
);
CREATE POLICY "Users can update printed tickets in their organization" ON printed_tickets
FOR UPDATE USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id = printed_tickets.organization_id
)
);
-- Policies for scan_attempts
CREATE POLICY "Users can view scan attempts in their organization" ON scan_attempts
FOR SELECT USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id = (
SELECT organization_id FROM events WHERE events.id = scan_attempts.event_id
)
)
);
CREATE POLICY "Users can insert scan attempts in their organization" ON scan_attempts
FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id = (
SELECT organization_id FROM events WHERE events.id = scan_attempts.event_id
)
)
);
-- Admin override policies (for users with admin privileges)
CREATE POLICY "Admin can view all printed tickets" ON printed_tickets
FOR SELECT USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id IS NULL
)
);
CREATE POLICY "Admin can manage all printed tickets" ON printed_tickets
FOR ALL USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id IS NULL
)
);
CREATE POLICY "Admin can view all scan attempts" ON scan_attempts
FOR SELECT USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = auth.uid()
AND users.organization_id IS NULL
)
);
-- Create function to automatically set organization_id when inserting printed tickets
CREATE OR REPLACE FUNCTION set_printed_ticket_organization_id()
RETURNS TRIGGER AS $$
BEGIN
-- Set organization_id from the event
NEW.organization_id = (
SELECT organization_id
FROM events
WHERE id = NEW.event_id
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger to automatically set organization_id
CREATE TRIGGER set_printed_ticket_organization_id_trigger
BEFORE INSERT ON printed_tickets
FOR EACH ROW
EXECUTE FUNCTION set_printed_ticket_organization_id();
-- Create function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_printed_ticket_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger to update updated_at
CREATE TRIGGER update_printed_ticket_updated_at_trigger
BEFORE UPDATE ON printed_tickets
FOR EACH ROW
EXECUTE FUNCTION update_printed_ticket_updated_at();