Includes SQL migrations, Prisma models, dashboard CRUD, registration status workflow, and website OpenAPI updates for workshop listing and signup. Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
3.7 KiB
SQL
89 lines
3.7 KiB
SQL
-- Workshops module (rich text + image gallery + customer registration)
|
|
|
|
ALTER TYPE media_entity_type ADD VALUE IF NOT EXISTS 'workshop';
|
|
|
|
CREATE TABLE workshops (
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
business_id BIGINT NOT NULL,
|
|
author_id BIGINT,
|
|
title VARCHAR(255) NOT NULL,
|
|
title_fa VARCHAR(255),
|
|
title_en VARCHAR(255),
|
|
slug VARCHAR(255) NOT NULL,
|
|
excerpt TEXT,
|
|
content JSONB NOT NULL DEFAULT '{}',
|
|
status content_status NOT NULL DEFAULT 'draft',
|
|
featured_media_id BIGINT,
|
|
published_at TIMESTAMPTZ,
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT workshops_business_slug_unique UNIQUE (business_id, slug),
|
|
CONSTRAINT workshops_business_id_fkey
|
|
FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE,
|
|
CONSTRAINT workshops_author_id_fkey
|
|
FOREIGN KEY (author_id) REFERENCES users (id) ON DELETE SET NULL,
|
|
CONSTRAINT workshops_featured_media_id_fkey
|
|
FOREIGN KEY (featured_media_id) REFERENCES media (id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE INDEX idx_workshops_business_id ON workshops (business_id);
|
|
CREATE INDEX idx_workshops_business_status ON workshops (business_id, status);
|
|
CREATE INDEX idx_workshops_business_published ON workshops (business_id, published_at DESC);
|
|
CREATE INDEX idx_workshops_author_id ON workshops (author_id);
|
|
|
|
CREATE TRIGGER workshops_set_updated_at
|
|
BEFORE UPDATE ON workshops
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION set_updated_at();
|
|
|
|
CREATE TABLE workshop_registrations (
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
business_id BIGINT NOT NULL,
|
|
workshop_id BIGINT NOT NULL,
|
|
user_id BIGINT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT workshop_registrations_workshop_user_unique UNIQUE (workshop_id, user_id),
|
|
CONSTRAINT workshop_registrations_business_id_fkey
|
|
FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE,
|
|
CONSTRAINT workshop_registrations_workshop_id_fkey
|
|
FOREIGN KEY (workshop_id) REFERENCES workshops (id) ON DELETE CASCADE,
|
|
CONSTRAINT workshop_registrations_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX idx_workshop_registrations_business_id ON workshop_registrations (business_id);
|
|
CREATE INDEX idx_workshop_registrations_workshop_id ON workshop_registrations (workshop_id);
|
|
CREATE INDEX idx_workshop_registrations_user_id ON workshop_registrations (user_id);
|
|
|
|
INSERT INTO permissions (name, slug, group_name, description) VALUES
|
|
('View workshops', 'workshops.read', 'workshops', 'View workshops'),
|
|
('Create workshops', 'workshops.create', 'workshops', 'Create workshops'),
|
|
('Update workshops', 'workshops.update', 'workshops', 'Edit workshops'),
|
|
('Delete workshops', 'workshops.delete', 'workshops', 'Delete workshops'),
|
|
('Publish workshops', 'workshops.publish', 'workshops', 'Publish and unpublish workshops')
|
|
ON CONFLICT (slug) DO NOTHING;
|
|
|
|
INSERT INTO role_permissions (role_id, permission_id)
|
|
SELECT r.id, p.id
|
|
FROM roles r
|
|
JOIN permissions p ON p.slug LIKE 'workshops.%'
|
|
WHERE r.slug IN ('business_owner', 'owner', 'admin')
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
INSERT INTO role_permissions (role_id, permission_id)
|
|
SELECT r.id, p.id
|
|
FROM roles r
|
|
JOIN permissions p ON p.slug IN ('workshops.read', 'workshops.create', 'workshops.update', 'workshops.publish')
|
|
WHERE r.slug = 'editor'
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
INSERT INTO role_permissions (role_id, permission_id)
|
|
SELECT r.id, p.id
|
|
FROM roles r
|
|
JOIN permissions p ON p.slug = 'workshops.read'
|
|
WHERE r.slug = 'viewer'
|
|
ON CONFLICT DO NOTHING;
|