db: squash migrations

This commit is contained in:
Rotimi Best
2025-04-19 23:21:43 +01:00
parent 1ab07d8d95
commit d010531ef7
34 changed files with 2603 additions and 3467 deletions
@@ -1,11 +0,0 @@
<script lang="ts">
let count = 0;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
clicks: {count}
</button>
View File
-17
View File
@@ -1,17 +0,0 @@
{
"name": "svelte-ui",
"version": "0.0.0",
"description": "Styles and components for use in svelte websites",
"main": "index.js",
"scripts": {
"lint": "prettier --check --ignore-path=../../.prettierignore .",
"format": "prettier --write --ignore-path=../../.prettierignore ."
},
"devDependencies": {
"eslint-config-custom": "workspace:*",
"svelte": "^3.9.2"
},
"keywords": [],
"author": "",
"license": "MIT"
}
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
alter table "public"."profile" alter column "avatar_url" set default 'https://pgrest.classroomio.com/storage/v1/object/public/avatars/avatar.png'::text;
@@ -1,22 +0,0 @@
drop function if exists "public"."get_courses"(org_id_arg uuid, profile_id_arg uuid);
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.get_courses(org_id_arg uuid, profile_id_arg uuid)
RETURNS TABLE(id uuid, org_id uuid, title character varying, slug character varying, description character varying, logo text, banner_image text, cost bigint, currency character varying, is_published boolean, profile_id uuid, role_id bigint, total_lessons bigint, total_students bigint, progress_rate bigint)
LANGUAGE plpgsql
AS $function$
BEGIN
Return query
select course.id, organization.id AS org_id, course.title, course.slug, course.description, course.logo, course.banner_image, course.cost, course.currency, course.is_published, groupmember.profile_id, groupmember.role_id, (select COUNT(*) from lesson as l where l.course_id = course.id) AS total_lessons, (select COUNT(*) from groupmember as gm where gm.group_id = course.group_id AND gm.role_id = 3) as total_students, (select COUNT(*) from lesson_completion as lc join lesson as l on l.id = lc.lesson_id where l.course_id = course.id and lc.is_complete = true and lc.profile_id = profile_id_arg) AS progress_rate
from course
join "group" on "group".id = course.group_id
join groupmember on groupmember.group_id = course.group_id
join organization on organization.id = "group".organization_id
where course.status = 'ACTIVE' AND organization.id = org_id_arg
-- GROUP BY course.id, groupmember.profile_id
ORDER BY course.created_at DESC;
END;
$function$
;
@@ -1 +0,0 @@
alter table "public"."course" alter column "metadata" set default '{"goals": "", "description": "", "requirements": ""}'::jsonb;
@@ -1,11 +0,0 @@
alter table "public"."community_answer" add column "author_profile_id" uuid;
alter table "public"."community_question" add column "author_profile_id" uuid;
alter table "public"."community_answer" add constraint "community_answer_author_profile_id_fkey" FOREIGN KEY (author_profile_id) REFERENCES profile(id) not valid;
alter table "public"."community_answer" validate constraint "community_answer_author_profile_id_fkey";
alter table "public"."community_question" add constraint "community_question_author_profile_id_fkey" FOREIGN KEY (author_profile_id) REFERENCES profile(id) not valid;
alter table "public"."community_question" validate constraint "community_question_author_profile_id_fkey";
@@ -1,48 +0,0 @@
create table "public"."course_newsfeed" (
"created_at" timestamp with time zone not null default now(),
"author_id" uuid,
"content" text,
"id" uuid not null default gen_random_uuid(),
"course_id" uuid,
"reaction" jsonb default '{"clap": [], "smile": [], "thumbsup": [], "thumbsdown": []}'::jsonb,
"is_pinned" boolean not null default false
);
create table "public"."course_newsfeed_comment" (
"created_at" timestamp with time zone not null default now(),
"author_id" uuid,
"content" text,
"id" bigint generated by default as identity not null,
"course_newsfeed_id" uuid
);
CREATE UNIQUE INDEX course_newsfeed_comment_id_key ON public.course_newsfeed_comment USING btree (id);
CREATE UNIQUE INDEX course_newsfeed_comment_pkey ON public.course_newsfeed_comment USING btree (id);
CREATE UNIQUE INDEX course_newsfeed_pkey ON public.course_newsfeed USING btree (id);
alter table "public"."course_newsfeed" add constraint "course_newsfeed_pkey" PRIMARY KEY using index "course_newsfeed_pkey";
alter table "public"."course_newsfeed_comment" add constraint "course_newsfeed_comment_pkey" PRIMARY KEY using index
"course_newsfeed_comment_pkey";
alter table "public"."course_newsfeed" add constraint "course_newsfeed_author_id_fkey" FOREIGN KEY (author_id) REFERENCES groupmember(id) not valid;
alter table "public"."course_newsfeed" validate constraint "course_newsfeed_author_id_fkey";
alter table "public"."course_newsfeed" add constraint "course_newsfeed_course_id_fkey" FOREIGN KEY (course_id) REFERENCES course(id) not valid;
alter table "public"."course_newsfeed" validate constraint "course_newsfeed_course_id_fkey";
alter table "public"."course_newsfeed_comment" add constraint "course_newsfeed_comment_id_key" UNIQUE using index "course_newsfeed_comment_id_key";
alter table "public"."course_newsfeed_comment" add constraint "course_newsfeed_comment_author_id_fkey" FOREIGN KEY (author_id) REFERENCES groupmember(id) not valid;
alter table "public"."course_newsfeed_comment" validate constraint "course_newsfeed_comment_author_id_fkey";
alter table "public"."course_newsfeed_comment" add constraint "course_newsfeed_comment_course_newsfeed_id_fkey" FOREIGN KEY (course_newsfeed_id) REFERENCES course_newsfeed(id) not valid;
alter table "public"."course_newsfeed_comment" validate constraint "course_newsfeed_comment_course_newsfeed_id_fkey";
@@ -1,20 +0,0 @@
create sequence "public"."test_tenant_id_seq";
create table "public"."test_tenant" (
"id" integer not null default nextval('test_tenant_id_seq'::regclass),
"details" text
);
truncate "public"."community_question" cascade;
alter table "public"."community_question" add column "course_id" uuid not null;
alter sequence "public"."test_tenant_id_seq" owned by "public"."test_tenant"."id";
CREATE UNIQUE INDEX test_tenant_pkey ON public.test_tenant USING btree (id);
alter table "public"."test_tenant" add constraint "test_tenant_pkey" PRIMARY KEY using index "test_tenant_pkey";
alter table "public"."community_question" add constraint "community_question_course_id_fkey" FOREIGN KEY (course_id) REFERENCES course(id) not valid;
alter table "public"."community_question" validate constraint "community_question_course_id_fkey";
@@ -1,6 +0,0 @@
alter table "public"."profile" add column "is_email_verified" boolean default false;
alter table "public"."profile" add column "verified_at" timestamp with time zone;
CREATE UNIQUE INDEX profile_email_key ON public.profile USING btree (email);
alter table "public"."profile" add constraint "profile_email_key" UNIQUE using index "profile_email_key";
@@ -1,13 +0,0 @@
create type "public"."LOCALE" as enum ('en', 'hi', 'fr', 'pt', 'de', 'vi', 'ru', 'es');
create table
public.lesson_language (
id bigint generated by default as identity,
content text null,
lesson_id uuid null default gen_random_uuid (),
locale "LOCALE" default 'en'::"LOCALE",
constraint lesson_language_pkey primary key (id),
constraint public_lesson_language_lesson_id_fkey foreign key (lesson_id) references lesson (id)
) tablespace pg_default;
alter table "public"."profile" add column "locale" "LOCALE" default 'en'::"LOCALE";
@@ -1,26 +0,0 @@
create type "public"."PLAN" as enum ('EARLY_ADOPTER', 'ENTERPRISE', 'BASIC');
create table "public"."organization_plan" (
"id" bigint generated by default as identity not null,
"activated_at" timestamp with time zone not null default now(),
"org_id" uuid,
"plan_name" "PLAN",
"is_active" boolean,
"deactivated_at" timestamp with time zone,
"updated_at" timestamp with time zone default now(),
"payload" jsonb,
"triggered_by" bigint
);
CREATE UNIQUE INDEX organization_plan_pkey ON public.organization_plan USING btree (id);
alter table "public"."organization_plan" add constraint "organization_plan_pkey" PRIMARY KEY using index "organization_plan_pkey";
alter table "public"."organization_plan" add constraint "organization_plan_org_id_fkey" FOREIGN KEY (org_id) REFERENCES organization(id) not valid;
alter table "public"."organization_plan" validate constraint "organization_plan_org_id_fkey";
alter table "public"."organization_plan" add constraint "organization_plan_triggered_by_fkey" FOREIGN KEY (triggered_by) REFERENCES organizationmember(id) not valid;
alter table "public"."organization_plan" validate constraint "organization_plan_triggered_by_fkey";
@@ -1 +0,0 @@
alter table "public"."submission" add column "feedback" text;
@@ -1 +0,0 @@
alter table "public"."organization" add column "customization" json not null default '{"apps":{"poll":true,"comments":true},"course":{"grading":true,"newsfeed":true},"dashboard":{"exercise":true,"community":true,"bannerText":"","bannerImage":""}}'::json;
@@ -1,37 +0,0 @@
create type "public"."COURSE_TYPE" as enum ('SELF_PACED', 'LIVE_CLASS');
alter table "public"."course" add column "type" "COURSE_TYPE" default 'LIVE_CLASS'::"COURSE_TYPE";
drop function if exists "public"."get_courses"(org_id_arg uuid, profile_id_arg uuid);
create
or replace function public.get_courses (org_id_arg uuid, profile_id_arg uuid) returns table (
id uuid,
org_id uuid,
title character varying,
slug character varying,
description character varying,
logo text,
banner_image text,
cost bigint,
currency character varying,
is_published boolean,
profile_id uuid,
role_id bigint,
total_lessons bigint,
total_students bigint,
progress_rate bigint,
type "COURSE_TYPE"
) language plpgsql as $function$
BEGIN
Return query
select course.id, organization.id AS org_id, course.title, course.slug, course.description, course.logo, course.banner_image, course.cost, course.currency, course.is_published, groupmember.profile_id, groupmember.role_id, (select COUNT(*) from lesson as l where l.course_id = course.id) AS total_lessons, (select COUNT(*) from groupmember as gm where gm.group_id = course.group_id AND gm.role_id = 3) as total_students, (select COUNT(*) from lesson_completion as lc join lesson as l on l.id = lc.lesson_id where l.course_id = course.id and lc.is_complete = true and lc.profile_id = profile_id_arg) AS progress_rate, course.type as type
from course
join "group" on "group".id = course.group_id
join groupmember on groupmember.group_id = course.group_id
join organization on organization.id = "group".organization_id
where course.status = 'ACTIVE' AND organization.id = org_id_arg
-- GROUP BY course.id, groupmember.profile_id
ORDER BY course.created_at DESC;
END;
$function$;
@@ -1,31 +0,0 @@
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.get_course_progress(course_id_arg uuid, profile_id_arg uuid)
RETURNS TABLE(lessons_count bigint, lessons_completed bigint, exercises_count bigint, exercises_completed bigint)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
select
count(lesson.id) as lessons_count,
count(lesson_completion.id) as lessons_completed,
count(exercise.id) as exercises_count,
count(submission.id) as exercises_completed
from
course
join "group" on "group".id = course.group_id
join groupmember on groupmember.group_id = course.group_id
join profile on profile.id = groupmember.profile_id
left join lesson on lesson.course_id = course.id
left join lesson_completion on lesson_completion.lesson_id = lesson.id
and lesson_completion.is_complete = true
and lesson_completion.profile_id = profile.id
left join exercise on exercise.lesson_id = lesson.id
left join submission on submission.exercise_id = exercise.id
and submission.submitted_by = groupmember.id
where
course.id = course_id_arg
and profile.id = profile_id_arg;
END;
$function$
;
@@ -1,31 +0,0 @@
drop function if exists "public"."get_courses"(org_id_arg uuid, profile_id_arg uuid);
create
or replace function public.get_courses (org_id_arg uuid, profile_id_arg uuid) returns table (
id uuid,
org_id uuid,
title character varying,
slug character varying,
description character varying,
logo text,
banner_image text,
cost bigint,
currency character varying,
is_published boolean,
total_lessons bigint,
total_students bigint,
progress_rate bigint,
type "COURSE_TYPE",
member_profile_id uuid
) language plpgsql as $function$
BEGIN
Return query
select course.id, organization.id AS org_id, course.title, course.slug, course.description, course.logo, course.banner_image, course.cost, course.currency, course.is_published, (select COUNT(*) from lesson as l where l.course_id = course.id) AS total_lessons, (select COUNT(*) from groupmember as gm where gm.group_id = course.group_id AND gm.role_id = 3) as total_students, (select COUNT(*) from lesson_completion as lc join lesson as l on l.id = lc.lesson_id where l.course_id = course.id and lc.is_complete = true and lc.profile_id = profile_id_arg) AS progress_rate, course.type as type, (select groupmember.profile_id from groupmember where groupmember.group_id = "group".id and groupmember.profile_id = profile_id_arg) as member_profile_id
from course
join "group" on "group".id = course.group_id
join organization on organization.id = "group".organization_id
where course.status = 'ACTIVE' AND organization.id = org_id_arg
-- GROUP BY course.id, groupmember.profile_id
ORDER BY course.created_at DESC;
END;
$function$;
@@ -1,47 +0,0 @@
-- Drop table cause it was never used
drop table if exists public.lesson_progress;
alter table public.exercise
drop constraint exercise_lesson_id_fkey,
add constraint exercise_lesson_id_fkey foreign key (lesson_id) references lesson (id)
on delete cascade;
alter table public.lesson_comment
drop constraint lesson_comment_lesson_id_fkey,
add constraint lesson_comment_lesson_id_fkey foreign key (lesson_id) references lesson (id)
on delete cascade;
alter table public.question
drop constraint question_exercise_id_fkey,
add constraint question_exercise_id_fkey foreign key (exercise_id) references exercise (id)
on delete cascade;
alter table public.option
drop constraint option_question_id_fkey,
add constraint option_question_id_fkey foreign key (question_id) references question (id)
on delete cascade;
alter table public.question_answer
drop constraint question_answer_question_id_fkey,
add constraint question_answer_question_id_fkey foreign key (question_id) references question (id)
on delete cascade;
alter table public.submission
drop constraint submission_exercise_id_fkey,
add constraint submission_exercise_id_fkey foreign key (exercise_id) references exercise (id)
on delete cascade;
alter table public.submission
drop constraint submission_course_id_fkey,
add constraint submission_course_id_fkey foreign key (course_id) references course (id)
on delete cascade;
alter table public.question_answer
drop constraint question_answer_submission_id_fkey,
add constraint question_answer_submission_id_fkey foreign key (submission_id) references submission (id)
on delete cascade;
alter table public.lesson_completion
drop constraint lesson_completion_lesson_id_fkey,
add constraint lesson_completion_lesson_id_fkey foreign key (lesson_id) references lesson (id)
on delete cascade;
@@ -1,25 +0,0 @@
CREATE TABLE lesson_language_history (
id SERIAL PRIMARY KEY,
lesson_language_id INTEGER REFERENCES lesson_language(id),
old_content TEXT,
new_content TEXT,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE FUNCTION update_lesson_language_history()
RETURNS trigger AS $$
BEGIN
IF TG_OP IN ('INSERT', 'UPDATE') THEN
INSERT INTO lesson_language_history (lesson_language_id, old_content, new_content)
VALUES (NEW.id, COALESCE(OLD.content, ''), NEW.content);
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_lesson_language_history_trigger
AFTER INSERT
OR
UPDATE ON lesson_language for each row
EXECUTE PROCEDURE update_lesson_language_history();
@@ -1,7 +0,0 @@
create or replace view "public"."lesson_versions" as SELECT llh.old_content,
llh.new_content,
llh."timestamp",
ll.locale,
ll.lesson_id
FROM (lesson_language_history llh
JOIN lesson_language ll ON ((ll.id = llh.lesson_language_id)));
@@ -1,17 +0,0 @@
CREATE OR REPLACE FUNCTION public.get_explore_courses(org_id_arg uuid, profile_id_arg uuid)
RETURNS TABLE(id uuid, org_id uuid, title character varying, slug character varying, description character varying, logo text, banner_image text, cost bigint, currency character varying, is_published boolean, total_lessons bigint, total_students bigint, progress_rate bigint, type "COURSE_TYPE", other_profile_id uuid)
LANGUAGE plpgsql
AS $function$
BEGIN
Return query
select course.id, organization.id AS org_id, course.title, course.slug, course.description, course.logo, course.banner_image, course.cost, course.currency, course.is_published, (select COUNT(*) from lesson
as l where l.course_id = course.id) AS total_lessons, (select COUNT(*) from groupmember as gm where gm.group_id = course.group_id AND gm.role_id = 3) as total_students, (select COUNT(*) from lesson_completion as lc join lesson as l on l.id = lc.lesson_id where l.course_id = course.id and lc.is_complete = true and lc.profile_id = profile_id_arg) AS progress_rate, course.type as type, (select groupmember.profile_id from groupmember where groupmember.group_id = "group".id and groupmember.profile_id != profile_id_arg
limit 1) as other_profile_id
from course
join "group" on "group".id = course.group_id
join organization on organization.id = "group".organization_id
where course.status = 'ACTIVE' AND course.is_published = true AND organization.id = org_id_arg AND profile_id_arg NOT IN (SELECT groupmember.profile_id FROM groupmember WHERE groupmember.group_id = course.group_id)
ORDER BY course.created_at DESC;
END;
$function$
;
File diff suppressed because it is too large Load Diff
@@ -1,8 +0,0 @@
drop policy "User must be an admin to INSERT" on "public"."organization";
create policy "Enable insert for authenticated users only"
on "public"."organization"
as permissive
for insert
to authenticated
with check (true);
@@ -1,59 +0,0 @@
create policy "User must be an org member to DELETE"
on "public"."lesson_language_history"
as permissive
for delete
to public
using (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = ( SELECT lesson.course_id
FROM lesson
WHERE (lesson.id = ( SELECT lesson_language.lesson_id
FROM lesson_language
WHERE (lesson_language.id = lesson_language_history.lesson_language_id)))
LIMIT 1))
LIMIT 1)));
create policy "User must be an org member to INSERT"
on "public"."lesson_language_history"
as permissive
for insert
to public
with check (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = ( SELECT lesson.course_id
FROM lesson
WHERE (lesson.id = ( SELECT lesson_language.lesson_id
FROM lesson_language
WHERE (lesson_language.id = lesson_language_history.lesson_language_id)))
LIMIT 1))
LIMIT 1)));
create policy "User must be an org member to UPDATE"
on "public"."lesson_language_history"
as permissive
for update
to public
using (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = ( SELECT lesson.course_id
FROM lesson
WHERE (lesson.id = ( SELECT lesson_language.lesson_id
FROM lesson_language
WHERE (lesson_language.id = lesson_language_history.lesson_language_id)))
LIMIT 1))
LIMIT 1)))
with check (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = ( SELECT lesson.course_id
FROM lesson
WHERE (lesson.id = ( SELECT lesson_language.lesson_id
FROM lesson_language
WHERE (lesson_language.id = lesson_language_history.lesson_language_id)))
LIMIT 1))
LIMIT 1)));
@@ -1,145 +0,0 @@
create type "public"."COURSE_VERSION" as enum ('V1', 'V2');
alter table "public"."lesson_language_history" drop constraint "lesson_language_history_lesson_language_id_fkey";
alter table "public"."lesson_language" drop constraint "public_lesson_language_lesson_id_fkey";
create table "public"."lesson_section" (
"id" uuid not null default gen_random_uuid(),
"created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone default now(),
"title" character varying,
"order" bigint default '0'::bigint,
"course_id" uuid
);
alter table "public"."lesson_section" enable row level security;
alter table "public"."course" add column "version" "COURSE_VERSION" not null default 'V1'::"COURSE_VERSION";
alter table "public"."lesson" add column "section_id" uuid;
CREATE UNIQUE INDEX lesson_section_pkey ON public.lesson_section USING btree (id);
alter table "public"."lesson_section" add constraint "lesson_section_pkey" PRIMARY KEY using index "lesson_section_pkey";
alter table "public"."lesson" add constraint "public_lesson_section_id_fkey" FOREIGN KEY (section_id) REFERENCES lesson_section(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."lesson" validate constraint "public_lesson_section_id_fkey";
alter table "public"."lesson_language_history" add constraint "public_lesson_language_history_lesson_language_id_fkey" FOREIGN KEY (lesson_language_id) REFERENCES lesson_language(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."lesson_language_history" validate constraint "public_lesson_language_history_lesson_language_id_fkey";
alter table "public"."lesson_section" add constraint "public_lesson_section_course_id_fkey" FOREIGN KEY (course_id) REFERENCES course(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."lesson_section" validate constraint "public_lesson_section_course_id_fkey";
alter table "public"."lesson_language" add constraint "public_lesson_language_lesson_id_fkey" FOREIGN KEY (lesson_id) REFERENCES lesson(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."lesson_language" validate constraint "public_lesson_language_lesson_id_fkey";
grant delete on table "public"."lesson_section" to "anon";
grant insert on table "public"."lesson_section" to "anon";
grant references on table "public"."lesson_section" to "anon";
grant select on table "public"."lesson_section" to "anon";
grant trigger on table "public"."lesson_section" to "anon";
grant truncate on table "public"."lesson_section" to "anon";
grant update on table "public"."lesson_section" to "anon";
grant delete on table "public"."lesson_section" to "authenticated";
grant insert on table "public"."lesson_section" to "authenticated";
grant references on table "public"."lesson_section" to "authenticated";
grant select on table "public"."lesson_section" to "authenticated";
grant trigger on table "public"."lesson_section" to "authenticated";
grant truncate on table "public"."lesson_section" to "authenticated";
grant update on table "public"."lesson_section" to "authenticated";
grant delete on table "public"."lesson_section" to "service_role";
grant insert on table "public"."lesson_section" to "service_role";
grant references on table "public"."lesson_section" to "service_role";
grant select on table "public"."lesson_section" to "service_role";
grant trigger on table "public"."lesson_section" to "service_role";
grant truncate on table "public"."lesson_section" to "service_role";
grant update on table "public"."lesson_section" to "service_role";
create policy "Enable read access for all users"
on "public"."lesson_section"
as permissive
for select
to public
using (true);
create policy "User must be an org member to DELETE"
on "public"."lesson_section"
as permissive
for delete
to public
using (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = lesson_section.course_id)
LIMIT 1)));
create policy "User must be an org member to INSERT"
on "public"."lesson_section"
as permissive
for insert
to public
with check (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = lesson_section.course_id)
LIMIT 1)));
create policy "User must be an org member to UPDATE"
on "public"."lesson_section"
as permissive
for update
to public
using (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = lesson_section.course_id)
LIMIT 1)))
with check (is_user_in_group_with_role(( SELECT course.group_id
FROM course
WHERE (course.id = lesson_section.course_id)
LIMIT 1)));
CREATE
OR REPLACE FUNCTION convert_course_to_v2 (course_id uuid) RETURNS void AS $$
DECLARE
new_section_id bigint;
BEGIN
UPDATE course
SET version = 'V2'
WHERE id = course_id;
INSERT INTO lesson_section (title, course_id) VALUES ('First Section [edit me]', course_id) RETURNING id INTO new_section_id;
UPDATE lesson
SET section_id = new_section_id
WHERE course_id = course_id;
END;
$$ LANGUAGE plpgsql;
@@ -1,27 +0,0 @@
drop function if exists "public"."convert_course_to_v2"(course_id uuid);
alter table "public"."organization" add column "is_restricted" boolean not null default false;
alter table "public"."profile" add column "is_restricted" boolean not null default false;
set check_function_bodies = off;
CREATE
OR REPLACE FUNCTION convert_course_to_v2 (course_id_arg uuid) RETURNS void AS $$
DECLARE
new_section_id uuid;
BEGIN
UPDATE course
SET version = 'V2'
WHERE id = course_id_arg;
INSERT INTO lesson_section (title, course_id) VALUES ('First Section [edit me]', course_id_arg) RETURNING id INTO new_section_id;
UPDATE lesson
SET section_id = new_section_id
WHERE lesson.course_id = course_id_arg;
END;
$$ LANGUAGE plpgsql;
@@ -1,11 +0,0 @@
alter table "public"."organization" add column "customCode" text;
alter table "public"."organization" add column "customDomain" text;
alter table "public"."organization" add column "favicon" text;
alter table "public"."organization" add column "isCustomDomainVerified" boolean default false;
CREATE UNIQUE INDEX "organization_customDomain_key" ON public.organization USING btree ("customDomain");
alter table "public"."organization" add constraint "organization_customDomain_key" UNIQUE using index "organization_customDomain_key";
@@ -1,8 +0,0 @@
drop policy "User must be an org member to SELECT" on "public"."organization_plan";
create policy "Enable read access for all users"
on "public"."organization_plan"
as permissive
for select
to public
using (true);
@@ -1,125 +0,0 @@
create table "public"."analytics_login_events" (
"id" uuid not null default uuid_generate_v4(),
"user_id" uuid not null,
"logged_in_at" timestamp with time zone default now()
);
alter table "public"."analytics_login_events" enable row level security;
CREATE UNIQUE INDEX analytics_login_events_pkey ON public.analytics_login_events USING btree (id);
CREATE INDEX idx_analytics_login_events_logged_in_at ON public.analytics_login_events USING btree (logged_in_at);
CREATE INDEX idx_analytics_login_events_user_id ON public.analytics_login_events USING btree (user_id);
CREATE UNIQUE INDEX analytics_login_events_user_id_unique ON public.analytics_login_events USING btree (user_id);
alter table "public"."analytics_login_events" add constraint "analytics_login_events_pkey" PRIMARY KEY using index "analytics_login_events_pkey";
alter table "public"."analytics_login_events" add constraint "analytics_login_events_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) not valid;
alter table "public"."analytics_login_events" validate constraint "analytics_login_events_user_id_fkey";
alter table "public"."analytics_login_events" add constraint "analytics_login_events_user_id_unique" UNIQUE using index "analytics_login_events_user_id_unique";
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.insert_login_event_on_user_login()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
IF (NEW.last_sign_in_at IS NOT NULL) THEN
INSERT INTO public.analytics_login_events (logged_in_at, user_id)
VALUES (NEW.last_sign_in_at, NEW.id)
ON CONFLICT (user_id) DO UPDATE
SET logged_in_at = NEW.last_sign_in_at;
END IF;
RETURN NEW;
END;
$function$
;
CREATE TRIGGER insert_login_event_on_user_login_trigger
AFTER UPDATE OF last_sign_in_at ON auth.users
FOR EACH ROW
EXECUTE FUNCTION public.insert_login_event_on_user_login();
CREATE OR REPLACE FUNCTION public.insert_login_event_on_user_session_update()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
IF (NEW.updated_at IS NOT NULL AND NEW.updated_at != OLD.updated_at) THEN
INSERT INTO public.analytics_login_events (logged_in_at, user_id)
VALUES (NEW.updated_at, NEW.user_id)
ON CONFLICT (user_id) DO UPDATE
SET logged_in_at = EXCLUDED.logged_in_at
WHERE analytics_login_events.logged_in_at < EXCLUDED.logged_in_at;
END IF;
RETURN NEW;
END;
$function$
;
CREATE TRIGGER insert_login_event_on_user_session_update_trigger
AFTER UPDATE OF updated_at ON auth.sessions
FOR EACH ROW
EXECUTE FUNCTION public.insert_login_event_on_user_session_update();
grant delete on table "public"."analytics_login_events" to "anon";
grant insert on table "public"."analytics_login_events" to "anon";
grant references on table "public"."analytics_login_events" to "anon";
grant select on table "public"."analytics_login_events" to "anon";
grant trigger on table "public"."analytics_login_events" to "anon";
grant truncate on table "public"."analytics_login_events" to "anon";
grant update on table "public"."analytics_login_events" to "anon";
grant delete on table "public"."analytics_login_events" to "authenticated";
grant insert on table "public"."analytics_login_events" to "authenticated";
grant references on table "public"."analytics_login_events" to "authenticated";
grant select on table "public"."analytics_login_events" to "authenticated";
grant trigger on table "public"."analytics_login_events" to "authenticated";
grant truncate on table "public"."analytics_login_events" to "authenticated";
grant update on table "public"."analytics_login_events" to "authenticated";
grant delete on table "public"."analytics_login_events" to "service_role";
grant insert on table "public"."analytics_login_events" to "service_role";
grant references on table "public"."analytics_login_events" to "service_role";
grant select on table "public"."analytics_login_events" to "service_role";
grant trigger on table "public"."analytics_login_events" to "service_role";
grant truncate on table "public"."analytics_login_events" to "service_role";
grant update on table "public"."analytics_login_events" to "service_role";
create policy "Users can insert their own login events"
on "public"."analytics_login_events"
as permissive
for insert
to authenticated
with check ((auth.uid() = user_id));
CREATE POLICY "Enable delete for users based on user_id"
ON "public"."analytics_login_events"
AS PERMISSIVE FOR DELETE
TO public
USING (auth.uid() = user_id);
@@ -1,18 +0,0 @@
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.check_if_student_completed_exercises(lesson_id_arg uuid, groupmember_id_arg uuid)
RETURNS boolean
LANGUAGE plpgsql
AS $function$
DECLARE
all_exercises_exist boolean;
BEGIN
SELECT COUNT(*) = COUNT(s.id) INTO all_exercises_exist
FROM exercise e
LEFT JOIN submission s ON e.id = s.exercise_id AND s.submitted_by = groupmember_id_arg
WHERE e.lesson_id = lesson_id_arg;
RETURN all_exercises_exist;
END;
$function$
;
@@ -1,80 +0,0 @@
set check_function_bodies = off;
create or replace view "public"."dash_org_stats" as SELECT gp.organization_id AS org_id,
count(DISTINCT course.id) AS no_of_courses,
count(DISTINCT gm.profile_id) AS enrolled_students
FROM ((course
JOIN "group" gp ON ((gp.id = course.group_id)))
LEFT JOIN groupmember gm ON (((gm.group_id = gp.id) AND (gm.role_id = 3))))
WHERE (course.status = 'ACTIVE'::text)
GROUP BY gp.organization_id;
CREATE OR REPLACE FUNCTION public.get_dash_org_recent_enrollments(org_id_arg uuid)
RETURNS TABLE(profile_id uuid, avatar_url text, fullname text, course_id uuid, course_title character varying, enrolled_at timestamp with time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT
p.id,
p.avatar_url,
p.fullname,
course.id,
course.title,
gm.created_at as enrolled_at
FROM
course
JOIN "group" as gp ON gp.id = course.group_id
LEFT JOIN groupmember as gm ON gm.group_id = gp.id AND gm.role_id = 3
JOIN profile as p ON p.id = gm.profile_id
WHERE
course.status = 'ACTIVE'
AND gp.organization_id = org_id_arg
GROUP BY
p.id,
course.id,
course.title,
enrolled_at
ORDER BY
enrolled_at DESC
LIMIT 5;
END;
$function$
;
CREATE OR REPLACE FUNCTION public.get_dash_org_top_courses(org_id_arg uuid)
RETURNS TABLE(course_id uuid, course_title character varying, total_students integer, completion_percentage integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT
course_stats.course_id,
course_stats.course_title,
course_stats.total_students::integer,
CASE
WHEN course_stats.total_students * course_stats.total_lessons = 0 THEN 0
ELSE ROUND((course_stats.completed_lessons::numeric / (course_stats.total_students * course_stats.total_lessons)) * 100)::integer
END as completion_percentage
FROM (
SELECT
c.id as course_id,
c.title as course_title,
COUNT(DISTINCT gm.id) as total_students,
COUNT(DISTINCT l.id) as total_lessons,
COUNT(DISTINCT lc.id) FILTER (WHERE lc.is_complete = true) as completed_lessons
FROM course c
JOIN "group" g ON g.id = c.group_id
LEFT JOIN groupmember gm ON gm.group_id = g.id and gm.role_id = 3
LEFT JOIN lesson l ON l.course_id = c.id
LEFT JOIN lesson_completion lc ON lc.lesson_id = l.id
AND lc.profile_id = gm.profile_id
WHERE c.status = 'ACTIVE' AND g.organization_id = org_id_arg
GROUP BY c.id, c.title
ORDER BY completed_lessons DESC
) as course_stats
LIMIT 5;
END;
$function$
;
File diff suppressed because it is too large Load Diff
@@ -1,7 +0,0 @@
alter table "public"."organization_plan" add column "provider" text default 'lmz'::text;
alter table "public"."organization_plan" add column "subscription_id" text;
CREATE UNIQUE INDEX organization_plan_subscription_id_key ON public.organization_plan USING btree (subscription_id);
alter table "public"."organization_plan" add constraint "organization_plan_subscription_id_key" UNIQUE using index "organization_plan_subscription_id_key";