diff --git a/config/database.yml b/config/database.yml
index a253baef9..ff86a8993 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -3,6 +3,7 @@ default: &default
pool: 5
timeout: 5000
host: <%= ENV['DATABASE_HOST'] || 'localhost' %>
+ port: <%= ENV['DATABASE_PORT'] || 5432 %>
username: <%= ENV['DATABASE_USER'] || 'tracker' %>
password: <%= ENV['DATABASE_PASSWORD'] || 'tracker' %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 9dc1b2a63..e701535b3 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -357,6 +357,10 @@ en:
health_insurance: Health Insurance
health_issues: Health Issues
hiv_tested: HIV Tested
+ no_students_found: "No Students found"
+ no_groups_found: "No Groups found"
+ no_chapters_found: "No Chapters found"
+ no_organizations_found: "No Organizations found"
confirm: Confirm
import: Import
@@ -451,7 +455,6 @@ en:
one: MLID
other: MLID
-
errors:
messages:
extension_whitelist_error: File is not an image
diff --git a/db/structure.sql b/db/structure.sql
index 9d53667dd..addd1f06a 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -24,20 +24,6 @@ CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public;
COMMENT ON EXTENSION btree_gist IS 'support for indexing common datatypes in GiST';
---
--- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: -
---
-
-CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public;
-
-
---
--- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: -
---
-
-COMMENT ON EXTENSION pg_stat_statements IS 'track execution statistics of all SQL statements executed';
-
-
--
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
--
@@ -249,8 +235,8 @@ SET default_table_access_method = heap;
CREATE TABLE public.ar_internal_metadata (
key character varying NOT NULL,
value character varying,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
+ created_at timestamp(6) without time zone NOT NULL,
+ updated_at timestamp(6) without time zone NOT NULL
);
@@ -273,6 +259,7 @@ CREATE TABLE public.assignments (
--
CREATE SEQUENCE public.assignments_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -309,6 +296,7 @@ CREATE TABLE public.authentication_tokens (
--
CREATE SEQUENCE public.authentication_tokens_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -364,6 +352,7 @@ CREATE TABLE public.chapters (
--
CREATE SEQUENCE public.chapters_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -395,7 +384,7 @@ CREATE TABLE public.deleted_lessons (
--
CREATE TABLE public.enrollments (
- id uuid DEFAULT public.gen_random_uuid() NOT NULL,
+ id uuid DEFAULT gen_random_uuid() NOT NULL,
student_id bigint NOT NULL,
group_id bigint NOT NULL,
active_since date NOT NULL,
@@ -425,6 +414,7 @@ CREATE TABLE public.grade_descriptors (
--
CREATE SEQUENCE public.grade_descriptors_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -461,6 +451,7 @@ CREATE TABLE public.grades (
--
CREATE SEQUENCE public.grades_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -534,6 +525,7 @@ CREATE TABLE public.groups (
--
CREATE SEQUENCE public.groups_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -562,27 +554,6 @@ SELECT
NULL::integer AS subject_id;
---
--- Name: lesson_table_rows; Type: VIEW; Schema: public; Owner: -
---
-
-CREATE VIEW public.lesson_table_rows AS
-SELECT
- NULL::integer AS group_id,
- NULL::date AS date,
- NULL::timestamp without time zone AS created_at,
- NULL::timestamp without time zone AS updated_at,
- NULL::integer AS subject_id,
- NULL::timestamp without time zone AS deleted_at,
- NULL::uuid AS id,
- NULL::character varying AS group_name,
- NULL::character varying AS chapter_name,
- NULL::character varying AS subject_name,
- NULL::bigint AS group_student_count,
- NULL::bigint AS graded_student_count,
- NULL::numeric AS average_mark;
-
-
--
-- Name: lessons; Type: TABLE; Schema: public; Owner: -
--
@@ -674,8 +645,8 @@ CREATE TABLE public.roles (
name character varying,
resource_type character varying,
resource_id integer,
- created_at timestamp without time zone,
- updated_at timestamp without time zone
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
);
@@ -804,6 +775,7 @@ CREATE TABLE public.organizations (
--
CREATE SEQUENCE public.organizations_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -840,6 +812,7 @@ SELECT
--
CREATE SEQUENCE public.roles_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -883,6 +856,7 @@ CREATE TABLE public.skills (
--
CREATE SEQUENCE public.skills_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -946,6 +920,7 @@ CREATE TABLE public.student_images (
--
CREATE SEQUENCE public.student_images_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1104,6 +1079,7 @@ CREATE TABLE public.student_tags (
--
CREATE SEQUENCE public.students_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1138,6 +1114,7 @@ SELECT
--
CREATE SEQUENCE public.subjects_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1157,7 +1134,7 @@ ALTER SEQUENCE public.subjects_id_seq OWNED BY public.subjects.id;
--
CREATE TABLE public.tags (
- id uuid DEFAULT public.gen_random_uuid() NOT NULL,
+ id uuid DEFAULT gen_random_uuid() NOT NULL,
tag_name character varying NOT NULL,
organization_id bigint NOT NULL,
shared boolean NOT NULL,
@@ -1171,6 +1148,7 @@ CREATE TABLE public.tags (
--
CREATE SEQUENCE public.users_id_seq
+ AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1510,20 +1488,6 @@ CREATE INDEX index_chapters_on_organization_id ON public.chapters USING btree (o
CREATE INDEX index_deleted_lessons_on_group_id ON public.deleted_lessons USING btree (group_id);
---
--- Name: index_deleted_lessons_on_lesson_id; Type: INDEX; Schema: public; Owner: -
---
-
-CREATE UNIQUE INDEX index_deleted_lessons_on_lesson_id ON public.deleted_lessons USING btree (lesson_id);
-
-
---
--- Name: index_deleted_lessons_on_subject_id; Type: INDEX; Schema: public; Owner: -
---
-
-CREATE INDEX index_deleted_lessons_on_subject_id ON public.deleted_lessons USING btree (subject_id);
-
-
--
-- Name: index_enrollments_on_group_dates_and_student; Type: INDEX; Schema: public; Owner: -
--
@@ -1601,6 +1565,13 @@ CREATE INDEX index_lessons_on_group_id ON public.lessons USING btree (group_id);
CREATE UNIQUE INDEX index_lessons_on_group_id_and_subject_id_and_date ON public.lessons USING btree (group_id, subject_id, date) WHERE (deleted_at IS NULL);
+--
+-- Name: index_lessons_on_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE UNIQUE INDEX index_lessons_on_id ON public.lessons USING btree (id);
+
+
--
-- Name: index_lessons_on_subject_id; Type: INDEX; Schema: public; Owner: -
--
@@ -1622,6 +1593,13 @@ CREATE INDEX index_roles_on_name ON public.roles USING btree (name);
CREATE INDEX index_roles_on_name_and_resource_type_and_resource_id ON public.roles USING btree (name, resource_type, resource_id);
+--
+-- Name: index_roles_on_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_roles_on_resource_type_and_resource_id ON public.roles USING btree (resource_type, resource_id);
+
+
--
-- Name: index_skills_on_organization_id; Type: INDEX; Schema: public; Owner: -
--
@@ -1699,6 +1677,20 @@ CREATE INDEX index_tags_on_organization_id ON public.tags USING btree (organizat
CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);
+--
+-- Name: index_users_roles_on_role_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_users_roles_on_role_id ON public.users_roles USING btree (role_id);
+
+
+--
+-- Name: index_users_roles_on_user_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_users_roles_on_user_id ON public.users_roles USING btree (user_id);
+
+
--
-- Name: index_users_roles_on_user_id_and_role_id; Type: INDEX; Schema: public; Owner: -
--
@@ -1706,6 +1698,95 @@ CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);
CREATE INDEX index_users_roles_on_user_id_and_role_id ON public.users_roles USING btree (user_id, role_id);
+--
+-- Name: chapter_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+--
+
+CREATE OR REPLACE VIEW public.chapter_summaries AS
+ SELECT c.id,
+ c.chapter_name,
+ c.mlid AS chapter_mlid,
+ o.mlid AS organization_mlid,
+ concat(o.mlid, '-', c.mlid) AS full_mlid,
+ c.organization_id,
+ o.organization_name,
+ c.deleted_at,
+ (count(DISTINCT
+ CASE
+ WHEN (g.deleted_at IS NULL) THEN g.id
+ ELSE NULL::integer
+ END))::integer AS group_count,
+ (count(DISTINCT
+ CASE
+ WHEN ((en.active_since <= CURRENT_DATE) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= CURRENT_DATE)) AND (s.deleted_at IS NULL)) THEN s.id
+ ELSE NULL::integer
+ END))::integer AS student_count,
+ c.created_at,
+ c.updated_at
+ FROM ((((public.chapters c
+ LEFT JOIN public.groups g ON ((g.chapter_id = c.id)))
+ LEFT JOIN public.enrollments en ON ((en.group_id = g.id)))
+ LEFT JOIN public.students s ON ((s.id = en.student_id)))
+ LEFT JOIN public.organizations o ON ((c.organization_id = o.id)))
+ GROUP BY c.id, o.id;
+
+
+--
+-- Name: group_lesson_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+--
+
+CREATE OR REPLACE VIEW public.group_lesson_summaries AS
+ SELECT slu.lesson_id,
+ slu.lesson_date,
+ gr.id AS group_id,
+ gr.chapter_id,
+ slu.subject_id,
+ concat(gr.group_name, ' - ', c.chapter_name) AS group_chapter_name,
+ (round(avg(slu.average_mark), 2))::double precision AS average_mark,
+ (sum(slu.grade_count))::bigint AS grade_count,
+ (round((((sum(
+ CASE
+ WHEN (slu.grade_count = 0) THEN 0
+ ELSE 1
+ END))::numeric / (count(slu.*))::numeric) * (100)::numeric), 2))::double precision AS attendance
+ FROM ((public.student_lesson_summaries slu
+ JOIN public.groups gr ON ((slu.group_id = gr.id)))
+ JOIN public.chapters c ON ((gr.chapter_id = c.id)))
+ WHERE (slu.deleted_at IS NULL)
+ GROUP BY slu.lesson_id, gr.id, c.id, slu.subject_id, slu.lesson_date
+ ORDER BY slu.lesson_date;
+
+
+--
+-- Name: group_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+--
+
+CREATE OR REPLACE VIEW public.group_summaries AS
+ SELECT g.id,
+ g.group_name,
+ g.deleted_at,
+ g.created_at,
+ g.chapter_id,
+ c.chapter_name,
+ o.id AS organization_id,
+ o.mlid AS organization_mlid,
+ c.mlid AS chapter_mlid,
+ g.mlid,
+ concat(o.mlid, '-', c.mlid, '-', g.mlid) AS full_mlid,
+ o.organization_name,
+ sum(
+ CASE
+ WHEN ((en.active_since <= CURRENT_DATE) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= CURRENT_DATE)) AND (s.deleted_at IS NULL)) THEN 1
+ ELSE 0
+ END) AS student_count
+ FROM ((((public.groups g
+ LEFT JOIN public.enrollments en ON ((g.id = en.group_id)))
+ LEFT JOIN public.students s ON ((s.id = en.student_id)))
+ LEFT JOIN public.chapters c ON ((g.chapter_id = c.id)))
+ LEFT JOIN public.organizations o ON ((c.organization_id = o.id)))
+ GROUP BY g.id, c.id, o.id;
+
+
--
-- Name: lesson_skill_summaries _RETURN; Type: RULE; Schema: public; Owner: -
--
@@ -1725,6 +1806,40 @@ CREATE OR REPLACE VIEW public.lesson_skill_summaries AS
GROUP BY l.id, sk.id, su.id;
+--
+-- Name: organization_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+--
+
+CREATE OR REPLACE VIEW public.organization_summaries AS
+ SELECT o.id,
+ o.organization_name,
+ o.mlid AS organization_mlid,
+ (count(DISTINCT
+ CASE
+ WHEN ((c.id IS NOT NULL) AND (c.deleted_at IS NULL)) THEN c.id
+ ELSE NULL::integer
+ END))::integer AS chapter_count,
+ (count(DISTINCT
+ CASE
+ WHEN ((g.id IS NOT NULL) AND (g.deleted_at IS NULL)) THEN g.id
+ ELSE NULL::integer
+ END))::integer AS group_count,
+ (count(DISTINCT
+ CASE
+ WHEN ((s.id IS NOT NULL) AND (s.deleted_at IS NULL)) THEN s.id
+ ELSE NULL::integer
+ END))::integer AS student_count,
+ o.country,
+ o.updated_at,
+ o.created_at,
+ o.deleted_at
+ FROM (((public.organizations o
+ LEFT JOIN public.chapters c ON ((c.organization_id = o.id)))
+ LEFT JOIN public.groups g ON ((g.chapter_id = c.id)))
+ LEFT JOIN public.students s ON ((s.organization_id = o.id)))
+ GROUP BY o.id;
+
+
--
-- Name: performance_per_group_per_skill_per_lessons _RETURN; Type: RULE; Schema: public; Owner: -
--
@@ -1750,26 +1865,22 @@ CREATE OR REPLACE VIEW public.performance_per_group_per_skill_per_lessons AS
--
--- Name: subject_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+-- Name: student_analytics_summaries _RETURN; Type: RULE; Schema: public; Owner: -
--
-CREATE OR REPLACE VIEW public.subject_summaries AS
- SELECT su.id,
- su.subject_name,
- su.organization_id,
- sum(
- CASE
- WHEN (a.deleted_at IS NOT NULL) THEN 0
- ELSE 1
- END) AS skill_count,
- su.created_at,
- su.updated_at,
- su.deleted_at
- FROM ((public.subjects su
- LEFT JOIN public.assignments a ON ((su.id = a.subject_id)))
- LEFT JOIN public.skills sk ON ((sk.id = a.skill_id)))
- WHERE (sk.deleted_at IS NULL)
- GROUP BY su.id;
+CREATE OR REPLACE VIEW public.student_analytics_summaries AS
+ SELECT s.id,
+ s.organization_id,
+ s.first_name,
+ s.last_name,
+ s.old_group_id,
+ COALESCE(array_agg(en.group_id) FILTER (WHERE (en.group_id IS NOT NULL)), '{}'::bigint[]) AS enrolled_group_ids
+ FROM ((public.students s
+ JOIN public.organizations o ON ((s.organization_id = o.id)))
+ JOIN public.enrollments en ON ((s.id = en.student_id)))
+ WHERE (s.deleted_at IS NULL)
+ GROUP BY s.id, s.first_name, s.last_name
+ ORDER BY s.last_name, s.first_name;
--
@@ -1793,30 +1904,32 @@ CREATE OR REPLACE VIEW public.student_averages AS
JOIN public.lessons l ON (((l.id = g.lesson_id) AND (l.subject_id = su.id))))
GROUP BY s.id, su.id, sk.skill_name;
+
--
--- Name: group_lesson_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+-- Name: student_lesson_details _RETURN; Type: RULE; Schema: public; Owner: -
--
-CREATE OR REPLACE VIEW public.group_lesson_summaries AS
- SELECT slu.lesson_id,
- slu.lesson_date,
- gr.id AS group_id,
- gr.chapter_id,
- slu.subject_id,
- concat(gr.group_name, ' - ', c.chapter_name) AS group_chapter_name,
- (round(avg(slu.average_mark), 2))::double precision AS average_mark,
- (sum(slu.grade_count))::bigint AS grade_count,
- (round((((sum(
- CASE
- WHEN (slu.grade_count = 0) THEN 0
- ELSE 1
- END))::numeric / (count(slu.*))::numeric) * (100)::numeric), 2))::double precision AS attendance
- FROM ((public.student_lesson_summaries slu
- JOIN public.groups gr ON ((slu.group_id = gr.id)))
- JOIN public.chapters c ON ((gr.chapter_id = c.id)))
- WHERE (slu.deleted_at IS NULL)
- GROUP BY slu.lesson_id, gr.id, c.id, slu.subject_id, slu.lesson_date
- ORDER BY slu.lesson_date;
+CREATE OR REPLACE VIEW public.student_lesson_details AS
+ SELECT s.id AS student_id,
+ s.first_name,
+ s.last_name,
+ s.deleted_at AS student_deleted_at,
+ l.id AS lesson_id,
+ l.date,
+ l.deleted_at AS lesson_deleted_at,
+ l.subject_id,
+ round(avg(g.mark), 2) AS average_mark,
+ count(g.mark) AS grade_count,
+ COALESCE(jsonb_object_agg(g.skill_id, jsonb_build_object('mark', g.mark, 'grade_descriptor_id', g.grade_descriptor_id, 'skill_name', sk.skill_name)) FILTER (WHERE (sk.skill_name IS NOT NULL)), '{}'::jsonb) AS skill_marks
+ FROM ((((public.students s
+ JOIN public.enrollments en ON ((s.id = en.student_id)))
+ JOIN public.lessons l ON ((en.group_id = l.group_id)))
+ LEFT JOIN public.grades g ON (((g.student_id = s.id) AND (g.lesson_id = l.id) AND (g.deleted_at IS NULL))))
+ LEFT JOIN public.skills sk ON ((sk.id = g.skill_id)))
+ WHERE ((en.active_since <= l.date) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= l.date)))
+ GROUP BY s.id, l.id
+ ORDER BY l.subject_id;
+
--
-- Name: student_lesson_summaries _RETURN; Type: RULE; Schema: public; Owner: -
@@ -1873,146 +1986,26 @@ CREATE OR REPLACE VIEW public.student_tag_table_rows AS
--
--- Name: group_summaries _RETURN; Type: RULE; Schema: public; Owner: -
+-- Name: subject_summaries _RETURN; Type: RULE; Schema: public; Owner: -
--
-CREATE OR REPLACE VIEW public.group_summaries AS
- SELECT g.id,
- g.group_name,
- g.deleted_at,
- g.created_at,
- g.chapter_id,
- c.chapter_name,
- o.id AS organization_id,
- o.mlid AS organization_mlid,
- c.mlid AS chapter_mlid,
- g.mlid,
- concat(o.mlid, '-', c.mlid, '-', g.mlid) AS full_mlid,
- o.organization_name,
+CREATE OR REPLACE VIEW public.subject_summaries AS
+ SELECT su.id,
+ su.subject_name,
+ su.organization_id,
sum(
CASE
- WHEN ((en.active_since <= CURRENT_DATE) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= CURRENT_DATE)) AND (s.deleted_at IS NULL)) THEN 1
- ELSE 0
- END) AS student_count
- FROM ((((public.groups g
- LEFT JOIN public.enrollments en ON ((g.id = en.group_id)))
- LEFT JOIN public.students s ON ((s.id = en.student_id)))
- LEFT JOIN public.chapters c ON ((g.chapter_id = c.id)))
- LEFT JOIN public.organizations o ON ((c.organization_id = o.id)))
- GROUP BY g.id, c.id, o.id;
-
-
---
--- Name: student_lesson_details _RETURN; Type: RULE; Schema: public; Owner: -
---
-
-CREATE OR REPLACE VIEW public.student_lesson_details AS
- SELECT s.id AS student_id,
- s.first_name,
- s.last_name,
- s.deleted_at AS student_deleted_at,
- l.id AS lesson_id,
- l.date,
- l.deleted_at AS lesson_deleted_at,
- l.subject_id,
- round(avg(g.mark), 2) AS average_mark,
- count(g.mark) AS grade_count,
- COALESCE(jsonb_object_agg(g.skill_id, jsonb_build_object('mark', g.mark, 'grade_descriptor_id', g.grade_descriptor_id, 'skill_name', sk.skill_name)) FILTER (WHERE (sk.skill_name IS NOT NULL)), '{}'::jsonb) AS skill_marks
- FROM ((((public.students s
- JOIN public.enrollments en ON ((s.id = en.student_id)))
- JOIN public.lessons l ON ((en.group_id = l.group_id)))
- LEFT JOIN public.grades g ON (((g.student_id = s.id) AND (g.lesson_id = l.id) AND (g.deleted_at IS NULL))))
- LEFT JOIN public.skills sk ON ((sk.id = g.skill_id)))
- WHERE ((en.active_since <= l.date) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= l.date)))
- GROUP BY s.id, l.id
- ORDER BY l.subject_id;
-
-
---
--- Name: student_analytics_summaries _RETURN; Type: RULE; Schema: public; Owner: -
---
-
-CREATE OR REPLACE VIEW public.student_analytics_summaries AS
- SELECT s.id,
- s.organization_id,
- s.first_name,
- s.last_name,
- s.old_group_id,
- COALESCE(array_agg(en.group_id) FILTER (WHERE (en.group_id IS NOT NULL)), '{}'::bigint[]) AS enrolled_group_ids
- FROM ((public.students s
- JOIN public.organizations o ON ((s.organization_id = o.id)))
- JOIN public.enrollments en ON ((s.id = en.student_id)))
- WHERE (s.deleted_at IS NULL)
- GROUP BY s.id, s.first_name, s.last_name
- ORDER BY s.last_name, s.first_name;
-
-
---
--- Name: chapter_summaries _RETURN; Type: RULE; Schema: public; Owner: -
---
-
-CREATE OR REPLACE VIEW public.chapter_summaries AS
- SELECT c.id,
- c.chapter_name,
- c.mlid AS chapter_mlid,
- o.mlid AS organization_mlid,
- concat(o.mlid, '-', c.mlid) AS full_mlid,
- c.organization_id,
- o.organization_name,
- c.deleted_at,
- (count(DISTINCT
- CASE
- WHEN (g.deleted_at IS NULL) THEN g.id
- ELSE NULL::integer
- END))::integer AS group_count,
- (count(DISTINCT
- CASE
- WHEN ((en.active_since <= CURRENT_DATE) AND ((en.inactive_since IS NULL) OR (en.inactive_since >= CURRENT_DATE)) AND (s.deleted_at IS NULL)) THEN s.id
- ELSE NULL::integer
- END))::integer AS student_count,
- c.created_at,
- c.updated_at
- FROM ((((public.chapters c
- LEFT JOIN public.groups g ON ((g.chapter_id = c.id)))
- LEFT JOIN public.enrollments en ON ((en.group_id = g.id)))
- LEFT JOIN public.students s ON ((s.id = en.student_id)))
- LEFT JOIN public.organizations o ON ((c.organization_id = o.id)))
- GROUP BY c.id, o.id;
-
---
--- Name: organization_summaries _RETURN; Type: RULE; Schema: public; Owner: -
---
-
-CREATE OR REPLACE VIEW public.organization_summaries AS
- SELECT o.id,
- o.organization_name,
- o.mlid AS organization_mlid,
- (count(DISTINCT
- CASE
- WHEN ((c.id IS NOT NULL) AND (c.deleted_at IS NULL)) THEN c.id
- ELSE NULL::integer
- END))::integer AS chapter_count,
- (count(DISTINCT
- CASE
- WHEN ((g.id IS NOT NULL) AND (g.deleted_at IS NULL)) THEN g.id
- ELSE NULL::integer
- END))::integer AS group_count,
- (count(DISTINCT
- CASE
- WHEN ((c.id IS NOT NULL) AND (c.deleted_at IS NULL)) THEN c.student_count
- ELSE 0
- WHEN ((s.id IS NOT NULL) AND (s.deleted_at IS NULL)) THEN s.id
- ELSE NULL::integer
- END))::integer AS student_count,
- o.country,
- o.updated_at,
- o.created_at,
- o.deleted_at
- FROM (((public.organizations o
- LEFT JOIN public.chapters c ON ((c.organization_id = o.id)))
- LEFT JOIN public.groups g ON ((g.chapter_id = c.id)))
- LEFT JOIN public.students s ON ((s.organization_id = o.id)))
- GROUP BY o.id;
+ WHEN (a.deleted_at IS NOT NULL) THEN 0
+ ELSE 1
+ END) AS skill_count,
+ su.created_at,
+ su.updated_at,
+ su.deleted_at
+ FROM ((public.subjects su
+ LEFT JOIN public.assignments a ON ((su.id = a.subject_id)))
+ LEFT JOIN public.skills sk ON ((sk.id = a.skill_id)))
+ WHERE (sk.deleted_at IS NULL)
+ GROUP BY su.id;
--
diff --git a/spec/components/table_components/table_spec.rb b/spec/components/table_components/table_spec.rb
new file mode 100644
index 000000000..2f52d85c0
--- /dev/null
+++ b/spec/components/table_components/table_spec.rb
@@ -0,0 +1,44 @@
+require 'rails_helper'
+
+# Minimal stub to test TableComponents::Table in isolation without policy concerns
+class StubTableRow < ViewComponent::Base
+ with_collection_parameter :item
+
+ def self.columns(**_)
+ [{ column_name: 'Name' }]
+ end
+
+ def initialize(item:, **_)
+ @item = item
+ super()
+ end
+
+ erb_template '
<%= @item %>
'
+end
+
+RSpec.describe TableComponents::Table, type: :component do
+ let(:row_component) { StubTableRow }
+
+ context 'when rows is empty' do
+ it 'renders the empty message when the empty_message option is provided' do
+ render_inline(described_class.new(rows: [], row_component: row_component, options: { empty_message: 'No items found' }))
+
+ expect(page).to have_text('No items found')
+ end
+
+ it 'does not render an empty message when no empty_message option is provided' do
+ render_inline(described_class.new(rows: [], row_component: row_component))
+
+ expect(page).not_to have_css('[style*="grid-column: 1/-1"]')
+ end
+ end
+
+ context 'when rows is not empty' do
+ it 'does not render the empty message' do
+ render_inline(described_class.new(rows: ['Alice'], row_component: row_component, options: { empty_message: 'No items found' }))
+
+ expect(page).not_to have_text('No items found')
+ expect(page).to have_css('.stub-row', text: 'Alice')
+ end
+ end
+end