mirror of
https://github.com/marcogll/AnchorOS.git
synced 2026-03-15 13:24:27 +00:00
feat: Add kiosk management, artist selection, and schedule management
- Add KiosksManagement component with full CRUD for kiosks - Add ScheduleManagement for staff schedules with break reminders - Update booking flow to allow artist selection by customers - Add staff_services API for assigning services to artists - Update staff management UI with service assignment dialog - Add auto-break reminder when schedule >= 8 hours - Update availability API to filter artists by service - Add kiosk management to Aperture dashboard - Clean up ralphy artifacts and logs
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
-- ============================================
|
||||
-- ADD ANCHOR 23 MENU STRUCTURE
|
||||
-- Date: 20260120
|
||||
-- Description: Add columns to support complex service structure from Anchor 23 menu
|
||||
-- ============================================
|
||||
|
||||
-- Add new columns for complex service structure
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS subtitle VARCHAR(200);
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS price_type VARCHAR(20) DEFAULT 'fixed';
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS duration_min INTEGER;
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS duration_max INTEGER;
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS requires_prerequisite BOOLEAN DEFAULT false;
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS prerequisite_details JSONB;
|
||||
ALTER TABLE services ADD COLUMN IF NOT EXISTS membership_benefits JSONB;
|
||||
|
||||
-- Update existing duration_minutes to duration_max for backward compatibility
|
||||
-- This ensures existing services still work while new services can use ranges
|
||||
UPDATE services SET duration_max = duration_minutes WHERE duration_max IS NULL AND duration_minutes IS NOT NULL;
|
||||
|
||||
-- Add check constraints for new fields
|
||||
ALTER TABLE services ADD CONSTRAINT IF NOT EXISTS check_price_type
|
||||
CHECK (price_type IN ('fixed', 'starting_at'));
|
||||
|
||||
ALTER TABLE services ADD CONSTRAINT IF NOT EXISTS check_duration_range
|
||||
CHECK (duration_min IS NULL OR duration_max IS NULL OR duration_min <= duration_max);
|
||||
|
||||
ALTER TABLE services ADD CONSTRAINT IF NOT EXISTS check_duration_not_null
|
||||
CHECK (
|
||||
(duration_min IS NOT NULL AND duration_max IS NOT NULL) OR
|
||||
(duration_min IS NULL AND duration_max IS NOT NULL)
|
||||
);
|
||||
|
||||
-- Add comments for documentation
|
||||
COMMENT ON COLUMN services.subtitle IS 'Optional subtitle displayed under service name';
|
||||
COMMENT ON COLUMN services.price_type IS 'fixed or starting_at pricing type';
|
||||
COMMENT ON COLUMN services.duration_min IS 'Minimum duration in minutes for ranged services';
|
||||
COMMENT ON COLUMN services.duration_max IS 'Maximum duration in minutes for ranged services';
|
||||
COMMENT ON COLUMN services.requires_prerequisite IS 'Whether service requires prerequisite service';
|
||||
COMMENT ON COLUMN services.prerequisite_details IS 'JSON details about prerequisite requirements';
|
||||
COMMENT ON COLUMN services.membership_benefits IS 'JSON details about member-specific benefits';
|
||||
@@ -0,0 +1,85 @@
|
||||
-- ============================================
|
||||
-- FIX: Correct function calls in check_staff_availability
|
||||
-- Date: 2026-01-21
|
||||
-- Description: Fix parameter issues in check_staff_availability function calls
|
||||
-- ============================================
|
||||
|
||||
-- Drop and recreate check_staff_availability with correct function calls
|
||||
DROP FUNCTION IF EXISTS check_staff_availability(UUID, TIMESTAMPTZ, TIMESTAMPTZ, UUID) CASCADE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_staff_availability(
|
||||
p_staff_id UUID,
|
||||
p_start_time_utc TIMESTAMPTZ,
|
||||
p_end_time_utc TIMESTAMPTZ,
|
||||
p_exclude_booking_id UUID DEFAULT NULL
|
||||
)
|
||||
RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
v_staff RECORD;
|
||||
v_location_timezone TEXT;
|
||||
v_has_work_conflict BOOLEAN := false;
|
||||
v_has_booking_conflict BOOLEAN := false;
|
||||
v_has_calendar_conflict BOOLEAN := false;
|
||||
v_has_block_conflict BOOLEAN := false;
|
||||
BEGIN
|
||||
-- 1. Check if staff exists and is active
|
||||
SELECT s.*, l.timezone INTO v_staff, v_location_timezone
|
||||
FROM staff s
|
||||
JOIN locations l ON s.location_id = l.id
|
||||
WHERE s.id = p_staff_id;
|
||||
|
||||
IF NOT FOUND OR NOT v_staff.is_active OR NOT v_staff.is_available_for_booking THEN
|
||||
RETURN false;
|
||||
END IF;
|
||||
|
||||
-- 2. Check work hours and days (with correct parameters)
|
||||
v_has_work_conflict := NOT check_staff_work_hours(p_staff_id, p_start_time_utc, p_end_time_utc, v_location_timezone);
|
||||
IF v_has_work_conflict THEN
|
||||
RETURN false;
|
||||
END IF;
|
||||
|
||||
-- 3. Check existing bookings conflict
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM bookings b
|
||||
WHERE b.staff_id = p_staff_id
|
||||
AND b.status != 'cancelled'
|
||||
AND b.start_time_utc < p_end_time_utc
|
||||
AND b.end_time_utc > p_start_time_utc
|
||||
AND (p_exclude_booking_id IS NULL OR b.id != p_exclude_booking_id)
|
||||
) INTO v_has_booking_conflict;
|
||||
|
||||
IF v_has_booking_conflict THEN
|
||||
RETURN false;
|
||||
END IF;
|
||||
|
||||
-- 4. Check manual blocks conflict
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM staff_availability sa
|
||||
WHERE sa.staff_id = p_staff_id
|
||||
AND sa.date = p_start_time_utc::DATE
|
||||
AND sa.is_available = false
|
||||
AND (p_start_time_utc::TIME >= sa.start_time AND p_start_time_utc::TIME < sa.end_time
|
||||
OR p_end_time_utc::TIME > sa.start_time AND p_end_time_utc::TIME <= sa.end_time
|
||||
OR p_start_time_utc::TIME <= sa.start_time AND p_end_time_utc::TIME >= sa.end_time)
|
||||
) INTO v_has_block_conflict;
|
||||
|
||||
IF v_has_block_conflict THEN
|
||||
RETURN false;
|
||||
END IF;
|
||||
|
||||
-- 5. Check Google Calendar blocking events conflict
|
||||
v_has_calendar_conflict := NOT check_calendar_blocking(p_staff_id, p_start_time_utc, p_end_time_utc, p_exclude_booking_id);
|
||||
|
||||
IF v_has_calendar_conflict THEN
|
||||
RETURN false;
|
||||
END IF;
|
||||
|
||||
-- All checks passed - staff is available
|
||||
RETURN true;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- Grant execute permission
|
||||
GRANT EXECUTE ON FUNCTION check_staff_availability TO authenticated, anon, service_role;
|
||||
|
||||
COMMENT ON FUNCTION check_staff_availability IS 'Enhanced availability check including work hours, bookings, manual blocks, and Google Calendar sync with corrected function calls';
|
||||
@@ -0,0 +1,75 @@
|
||||
-- ============================================
|
||||
-- STAFF SERVICES MANAGEMENT
|
||||
-- Date: 2026-01-21
|
||||
-- Description: Add staff_services table and proficiency system
|
||||
-- ============================================
|
||||
|
||||
-- Create staff_services table
|
||||
CREATE TABLE staff_services (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
staff_id UUID NOT NULL REFERENCES staff(id) ON DELETE CASCADE,
|
||||
service_id UUID NOT NULL REFERENCES services(id) ON DELETE CASCADE,
|
||||
proficiency_level INTEGER CHECK (proficiency_level >= 1 AND proficiency_level <= 5) DEFAULT 3,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(staff_id, service_id)
|
||||
);
|
||||
|
||||
-- Add indexes for performance
|
||||
CREATE INDEX idx_staff_services_staff_id ON staff_services(staff_id);
|
||||
CREATE INDEX idx_staff_services_service_id ON staff_services(service_id);
|
||||
CREATE INDEX idx_staff_services_active ON staff_services(is_active);
|
||||
|
||||
-- Add RLS policies
|
||||
ALTER TABLE staff_services ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Staff can view their own services
|
||||
CREATE POLICY "Staff can view own services"
|
||||
ON staff_services
|
||||
FOR SELECT
|
||||
USING (
|
||||
auth.uid()::text = (
|
||||
SELECT user_id::text FROM staff WHERE id = staff_id
|
||||
)
|
||||
);
|
||||
|
||||
-- Policy: Managers and admins can view all staff services
|
||||
CREATE POLICY "Managers and admins can view all staff services"
|
||||
ON staff_services
|
||||
FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM staff s
|
||||
WHERE s.user_id::text = auth.uid()::text
|
||||
AND s.role IN ('manager', 'admin')
|
||||
)
|
||||
);
|
||||
|
||||
-- Policy: Managers and admins can manage staff services
|
||||
CREATE POLICY "Managers and admins can manage staff services"
|
||||
ON staff_services
|
||||
FOR ALL
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM staff s
|
||||
WHERE s.user_id::text = auth.uid()::text
|
||||
AND s.role IN ('manager', 'admin')
|
||||
)
|
||||
);
|
||||
|
||||
-- Add audit columns to bookings for tracking auto-assignment and invitations
|
||||
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS invitation_code_used TEXT;
|
||||
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS auto_assigned BOOLEAN DEFAULT false;
|
||||
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS assigned_by UUID REFERENCES staff(id);
|
||||
|
||||
-- Create indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_bookings_invitation_code ON bookings(invitation_code_used);
|
||||
CREATE INDEX IF NOT EXISTS idx_bookings_auto_assigned ON bookings(auto_assigned);
|
||||
|
||||
-- Grant permissions
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON staff_services TO authenticated;
|
||||
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO authenticated;
|
||||
|
||||
COMMENT ON TABLE staff_services IS 'Tracks which services each staff member can perform and their proficiency level';
|
||||
COMMENT ON COLUMN staff_services.proficiency_level IS '1=Beginner, 2=Intermediate, 3=Competent, 4=Proficient, 5=Expert';
|
||||
Reference in New Issue
Block a user