🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
157 lines
5.0 KiB
PL/PgSQL
157 lines
5.0 KiB
PL/PgSQL
-- 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(); |