From 74cda26093ebfffdb073f5b483cf4c04ede3e050 Mon Sep 17 00:00:00 2001 From: Maria Sauer <mcs22@inf.ufpr.br> Date: Mon, 21 Oct 2024 10:49:12 -0300 Subject: [PATCH] Issue #33: Create resource/educational stage relation table --- .../0000_lyrical_silver_samurai.sql | 366 ---- src/db/migrations/meta/0000_snapshot.json | 1624 ----------------- src/db/migrations/meta/_journal.json | 1 + .../repo/resource-educational-stages.repo.ts | 157 ++ src/db/schema/educational-stages.schema.ts | 5 +- src/db/schema/index.ts | 2 + .../resource-educational-stages.schema.ts | 42 + src/db/schema/resource.schema.ts | 4 +- src/db/seed.ts | 1 + src/db/seeds/index.ts | 1 + .../seeds/resource-educational-stages.seed.ts | 25 + src/index.ts | 8 +- .../resource-educational-stages.route.ts | 155 ++ .../resource-educational-stages.service.ts | 35 + 14 files changed, 430 insertions(+), 1996 deletions(-) delete mode 100644 src/db/migrations/0000_lyrical_silver_samurai.sql delete mode 100644 src/db/migrations/meta/0000_snapshot.json create mode 100644 src/db/repo/resource-educational-stages.repo.ts create mode 100644 src/db/schema/resource-educational-stages.schema.ts create mode 100644 src/db/seeds/resource-educational-stages.seed.ts create mode 100644 src/routes/resource-educational-stages.route.ts create mode 100644 src/services/resource-educational-stages.service.ts diff --git a/src/db/migrations/0000_lyrical_silver_samurai.sql b/src/db/migrations/0000_lyrical_silver_samurai.sql deleted file mode 100644 index 4102cb1..0000000 --- a/src/db/migrations/0000_lyrical_silver_samurai.sql +++ /dev/null @@ -1,366 +0,0 @@ -CREATE TABLE IF NOT EXISTS "collection_likes" ( - "user_id" integer NOT NULL, - "collection" integer NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "collection_resources" ( - "collection_id" integer NOT NULL, - "resource_id" integer NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "collection_stats" ( - "id" serial PRIMARY KEY NOT NULL, - "collection_id" bigint NOT NULL, - "views" bigint DEFAULT 0, - "downloads" bigint DEFAULT 0, - "likes" bigint DEFAULT 0, - "shares" bigint DEFAULT 0, - "score" bigint DEFAULT 0, - "follows" bigint DEFAULT 0, - CONSTRAINT "collection_stats_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "collection" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(255), - "description" text, - "is_private" boolean, - "is_active" boolean DEFAULT true, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp, - "deleted_at" timestamp, - "thumbnail" varchar(255), - CONSTRAINT "collection_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "complaint" ( - "id" serial PRIMARY KEY NOT NULL, - "state" integer DEFAULT 0 NOT NULL, - "description" text NOT NULL, - "evaluatedUser" integer NOT NULL, - "resource_id" integer, - "collection_id" integer, - "user_id" integer, - "evaluated_at" timestamp, - "created_at" timestamp DEFAULT now() NOT NULL, - "q1" boolean, - "q2" boolean, - "q3" boolean, - "q4" boolean -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "educational_stages" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar NOT NULL, - CONSTRAINT "educational_stages_id_unique" UNIQUE("id"), - CONSTRAINT "educational_stages_name_unique" UNIQUE("name") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "follows" ( - "id" serial PRIMARY KEY NOT NULL, - "user_id" integer NOT NULL, - "follower_id" integer NOT NULL, - CONSTRAINT "follows_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "institution" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(255) NOT NULL, - "uf" varchar(2), - "city" varchar(255), - "cep" varchar(10), - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL, - CONSTRAINT "institution_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "language" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar NOT NULL, - "code" varchar NOT NULL, - CONSTRAINT "language_id_unique" UNIQUE("id"), - CONSTRAINT "language_name_unique" UNIQUE("name"), - CONSTRAINT "language_code_unique" UNIQUE("code") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "licenses" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar NOT NULL, - "description" varchar NOT NULL, - "url" varchar NOT NULL, - CONSTRAINT "licenses_id_unique" UNIQUE("id"), - CONSTRAINT "licenses_name_unique" UNIQUE("name") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "object_types" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(255) NOT NULL, - CONSTRAINT "object_types_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "reset_ticket" ( - "id" serial PRIMARY KEY NOT NULL, - "user_id" integer NOT NULL, - "token_hash" varchar(255) NOT NULL, - "expiration_date" timestamp NOT NULL, - "token_used" boolean DEFAULT false NOT NULL, - "valid_token" boolean DEFAULT true NOT NULL, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL, - CONSTRAINT "reset_ticket_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "resource_languages" ( - "resource_id" integer NOT NULL, - "language_id" integer NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "resource_subjects" ( - "resource_id" integer NOT NULL, - "subject_id" integer NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "resource" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(256) NOT NULL, - "author" varchar(256) NOT NULL, - "description" varchar(256), - "bucket_key" varchar(256), - "link" varchar(256), - "thumbnail" varchar(256) NOT NULL, - "active" boolean DEFAULT false NOT NULL, - "published_at" timestamp, - "submited_at" timestamp, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp, - "deleted_at" timestamp, - CONSTRAINT "resource_id_unique" UNIQUE("id"), - CONSTRAINT "resource_bucket_key_unique" UNIQUE("bucket_key") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "role" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(255) NOT NULL, - "description" text, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL, - CONSTRAINT "role_id_unique" UNIQUE("id"), - CONSTRAINT "role_name_unique" UNIQUE("name") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "stats_resources" ( - "id" serial PRIMARY KEY NOT NULL, - "resource_id" bigint NOT NULL, - "views" bigint DEFAULT 0 NOT NULL, - "downloads" bigint DEFAULT 0 NOT NULL, - "shares" bigint DEFAULT 0 NOT NULL, - "score" bigint DEFAULT 0 NOT NULL, - CONSTRAINT "stats_resources_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "subjects" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar NOT NULL, - CONSTRAINT "subjects_id_unique" UNIQUE("id"), - CONSTRAINT "subjects_name_unique" UNIQUE("name") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "submission" ( - "id" serial PRIMARY KEY NOT NULL, - "is_accepted" boolean DEFAULT false NOT NULL, - "justification" text, - "resource_id" integer NOT NULL, - "submitter_id" integer NOT NULL, - "curator_id" integer NOT NULL, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp, - "answered_at" timestamp, - "q1" boolean, - "q2" boolean, - "q3" boolean, - "q4" boolean -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "user_institution" ( - "id" serial PRIMARY KEY NOT NULL, - "user_id" integer NOT NULL, - "institution_id" integer NOT NULL, - CONSTRAINT "user_institution_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "user_role" ( - "id" serial PRIMARY KEY NOT NULL, - "user_id" integer NOT NULL, - "role_id" integer NOT NULL, - CONSTRAINT "user_role_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "user_stats" ( - "id" serial PRIMARY KEY NOT NULL, - "user_id" integer NOT NULL, - "score" integer DEFAULT 0 NOT NULL, - "likes" integer DEFAULT 0 NOT NULL, - "likes_received" integer DEFAULT 0 NOT NULL, - "follows" integer DEFAULT 0 NOT NULL, - "followers" integer DEFAULT 0 NOT NULL, - "collections" integer DEFAULT 0 NOT NULL, - "submitted_resources" integer DEFAULT 0 NOT NULL, - "approved_resources" integer DEFAULT 0 NOT NULL, - "reviewed_resources" integer DEFAULT 0 NOT NULL, - "comments" integer DEFAULT 0 NOT NULL, - CONSTRAINT "user_stats_id_unique" UNIQUE("id") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "user" ( - "id" serial PRIMARY KEY NOT NULL, - "name" varchar(255) NOT NULL, - "username" varchar(255) NOT NULL, - "password" varchar(255) NOT NULL, - "email" varchar(255) NOT NULL, - "description" text DEFAULT 'sem descrição', - "institution" text DEFAULT 'sem instituição', - "birthday" timestamp NOT NULL, - "cpf" varchar(255) NOT NULL, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL, - "confirmed_at" timestamp, - "confirmation_sent_at" timestamp, - "deleted_at" timestamp, - "reactivated_at" timestamp, - "active" boolean DEFAULT true, - CONSTRAINT "user_id_unique" UNIQUE("id"), - CONSTRAINT "user_username_unique" UNIQUE("username"), - CONSTRAINT "user_email_unique" UNIQUE("email") -); ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "collection_likes" ADD CONSTRAINT "collection_likes_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "collection_likes" ADD CONSTRAINT "collection_likes_collection_collection_id_fk" FOREIGN KEY ("collection") REFERENCES "public"."collection"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "collection_resources" ADD CONSTRAINT "collection_resources_collection_id_collection_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."collection"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "collection_resources" ADD CONSTRAINT "collection_resources_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "collection_stats" ADD CONSTRAINT "collection_stats_collection_id_collection_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."collection"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "complaint" ADD CONSTRAINT "complaint_evaluatedUser_user_id_fk" FOREIGN KEY ("evaluatedUser") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "follows" ADD CONSTRAINT "follows_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "follows" ADD CONSTRAINT "follows_follower_id_user_id_fk" FOREIGN KEY ("follower_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "reset_ticket" ADD CONSTRAINT "reset_ticket_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "resource_languages" ADD CONSTRAINT "resource_languages_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "resource_languages" ADD CONSTRAINT "resource_languages_language_id_language_id_fk" FOREIGN KEY ("language_id") REFERENCES "public"."language"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "resource_subjects" ADD CONSTRAINT "resource_subjects_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "resource_subjects" ADD CONSTRAINT "resource_subjects_subject_id_subjects_id_fk" FOREIGN KEY ("subject_id") REFERENCES "public"."subjects"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "stats_resources" ADD CONSTRAINT "stats_resources_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "submission" ADD CONSTRAINT "submission_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "submission" ADD CONSTRAINT "submission_submitter_id_user_id_fk" FOREIGN KEY ("submitter_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "submission" ADD CONSTRAINT "submission_curator_id_user_id_fk" FOREIGN KEY ("curator_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "user_institution" ADD CONSTRAINT "user_institution_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "user_institution" ADD CONSTRAINT "user_institution_institution_id_institution_id_fk" FOREIGN KEY ("institution_id") REFERENCES "public"."institution"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "user_role" ADD CONSTRAINT "user_role_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "user_role" ADD CONSTRAINT "user_role_role_id_role_id_fk" FOREIGN KEY ("role_id") REFERENCES "public"."role"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "user_stats" ADD CONSTRAINT "user_stats_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; diff --git a/src/db/migrations/meta/0000_snapshot.json b/src/db/migrations/meta/0000_snapshot.json deleted file mode 100644 index 2b98099..0000000 --- a/src/db/migrations/meta/0000_snapshot.json +++ /dev/null @@ -1,1624 +0,0 @@ -{ - "id": "6288d454-cfb1-4aff-983d-6781c24fe1eb", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.collection_likes": { - "name": "collection_likes", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "collection": { - "name": "collection", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "collection_likes_user_id_user_id_fk": { - "name": "collection_likes_user_id_user_id_fk", - "tableFrom": "collection_likes", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_likes_collection_collection_id_fk": { - "name": "collection_likes_collection_collection_id_fk", - "tableFrom": "collection_likes", - "tableTo": "collection", - "columnsFrom": [ - "collection" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.collection_resources": { - "name": "collection_resources", - "schema": "", - "columns": { - "collection_id": { - "name": "collection_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "collection_resources_collection_id_collection_id_fk": { - "name": "collection_resources_collection_id_collection_id_fk", - "tableFrom": "collection_resources", - "tableTo": "collection", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_resources_resource_id_resource_id_fk": { - "name": "collection_resources_resource_id_resource_id_fk", - "tableFrom": "collection_resources", - "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.collection_stats": { - "name": "collection_stats", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "collection_id": { - "name": "collection_id", - "type": "bigint", - "primaryKey": false, - "notNull": true - }, - "views": { - "name": "views", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "downloads": { - "name": "downloads", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "likes": { - "name": "likes", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "shares": { - "name": "shares", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "score": { - "name": "score", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "follows": { - "name": "follows", - "type": "bigint", - "primaryKey": false, - "notNull": false, - "default": 0 - } - }, - "indexes": {}, - "foreignKeys": { - "collection_stats_collection_id_collection_id_fk": { - "name": "collection_stats_collection_id_collection_id_fk", - "tableFrom": "collection_stats", - "tableTo": "collection", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_stats_id_unique": { - "name": "collection_stats_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.collection": { - "name": "collection", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_private": { - "name": "is_private", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "thumbnail": { - "name": "thumbnail", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_id_unique": { - "name": "collection_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.complaint": { - "name": "complaint", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "state": { - "name": "state", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "evaluatedUser": { - "name": "evaluatedUser", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "evaluated_at": { - "name": "evaluated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "q1": { - "name": "q1", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q2": { - "name": "q2", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q3": { - "name": "q3", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q4": { - "name": "q4", - "type": "boolean", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "complaint_evaluatedUser_user_id_fk": { - "name": "complaint_evaluatedUser_user_id_fk", - "tableFrom": "complaint", - "tableTo": "user", - "columnsFrom": [ - "evaluatedUser" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.educational_stages": { - "name": "educational_stages", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "educational_stages_id_unique": { - "name": "educational_stages_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "educational_stages_name_unique": { - "name": "educational_stages_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.follows": { - "name": "follows", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "follower_id": { - "name": "follower_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "follows_user_id_user_id_fk": { - "name": "follows_user_id_user_id_fk", - "tableFrom": "follows", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "follows_follower_id_user_id_fk": { - "name": "follows_follower_id_user_id_fk", - "tableFrom": "follows", - "tableTo": "user", - "columnsFrom": [ - "follower_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "follows_id_unique": { - "name": "follows_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.institution": { - "name": "institution", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "uf": { - "name": "uf", - "type": "varchar(2)", - "primaryKey": false, - "notNull": false - }, - "city": { - "name": "city", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "cep": { - "name": "cep", - "type": "varchar(10)", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "institution_id_unique": { - "name": "institution_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.language": { - "name": "language", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "language_id_unique": { - "name": "language_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "language_name_unique": { - "name": "language_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - }, - "language_code_unique": { - "name": "language_code_unique", - "nullsNotDistinct": false, - "columns": [ - "code" - ] - } - } - }, - "public.licenses": { - "name": "licenses", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "url": { - "name": "url", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "licenses_id_unique": { - "name": "licenses_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "licenses_name_unique": { - "name": "licenses_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.object_types": { - "name": "object_types", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "object_types_id_unique": { - "name": "object_types_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.reset_ticket": { - "name": "reset_ticket", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "token_hash": { - "name": "token_hash", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "expiration_date": { - "name": "expiration_date", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "token_used": { - "name": "token_used", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "valid_token": { - "name": "valid_token", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "reset_ticket_user_id_user_id_fk": { - "name": "reset_ticket_user_id_user_id_fk", - "tableFrom": "reset_ticket", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "reset_ticket_id_unique": { - "name": "reset_ticket_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.resource_languages": { - "name": "resource_languages", - "schema": "", - "columns": { - "resource_id": { - "name": "resource_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "language_id": { - "name": "language_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "resource_languages_resource_id_resource_id_fk": { - "name": "resource_languages_resource_id_resource_id_fk", - "tableFrom": "resource_languages", - "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "resource_languages_language_id_language_id_fk": { - "name": "resource_languages_language_id_language_id_fk", - "tableFrom": "resource_languages", - "tableTo": "language", - "columnsFrom": [ - "language_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.resource_subjects": { - "name": "resource_subjects", - "schema": "", - "columns": { - "resource_id": { - "name": "resource_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "subject_id": { - "name": "subject_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "resource_subjects_resource_id_resource_id_fk": { - "name": "resource_subjects_resource_id_resource_id_fk", - "tableFrom": "resource_subjects", - "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "resource_subjects_subject_id_subjects_id_fk": { - "name": "resource_subjects_subject_id_subjects_id_fk", - "tableFrom": "resource_subjects", - "tableTo": "subjects", - "columnsFrom": [ - "subject_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.resource": { - "name": "resource", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(256)", - "primaryKey": false, - "notNull": true - }, - "author": { - "name": "author", - "type": "varchar(256)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "bucket_key": { - "name": "bucket_key", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "link": { - "name": "link", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "thumbnail": { - "name": "thumbnail", - "type": "varchar(256)", - "primaryKey": false, - "notNull": true - }, - "active": { - "name": "active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "published_at": { - "name": "published_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "submited_at": { - "name": "submited_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "resource_id_unique": { - "name": "resource_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "resource_bucket_key_unique": { - "name": "resource_bucket_key_unique", - "nullsNotDistinct": false, - "columns": [ - "bucket_key" - ] - } - } - }, - "public.role": { - "name": "role", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "role_id_unique": { - "name": "role_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "role_name_unique": { - "name": "role_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.stats_resources": { - "name": "stats_resources", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "bigint", - "primaryKey": false, - "notNull": true - }, - "views": { - "name": "views", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "downloads": { - "name": "downloads", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "shares": { - "name": "shares", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "score": { - "name": "score", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - } - }, - "indexes": {}, - "foreignKeys": { - "stats_resources_resource_id_resource_id_fk": { - "name": "stats_resources_resource_id_resource_id_fk", - "tableFrom": "stats_resources", - "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "stats_resources_id_unique": { - "name": "stats_resources_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.subjects": { - "name": "subjects", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subjects_id_unique": { - "name": "subjects_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "subjects_name_unique": { - "name": "subjects_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.submission": { - "name": "submission", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "is_accepted": { - "name": "is_accepted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "justification": { - "name": "justification", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "resource_id": { - "name": "resource_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "submitter_id": { - "name": "submitter_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "curator_id": { - "name": "curator_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "answered_at": { - "name": "answered_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "q1": { - "name": "q1", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q2": { - "name": "q2", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q3": { - "name": "q3", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "q4": { - "name": "q4", - "type": "boolean", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "submission_resource_id_resource_id_fk": { - "name": "submission_resource_id_resource_id_fk", - "tableFrom": "submission", - "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "submission_submitter_id_user_id_fk": { - "name": "submission_submitter_id_user_id_fk", - "tableFrom": "submission", - "tableTo": "user", - "columnsFrom": [ - "submitter_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "submission_curator_id_user_id_fk": { - "name": "submission_curator_id_user_id_fk", - "tableFrom": "submission", - "tableTo": "user", - "columnsFrom": [ - "curator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.user_institution": { - "name": "user_institution", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "institution_id": { - "name": "institution_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "user_institution_user_id_user_id_fk": { - "name": "user_institution_user_id_user_id_fk", - "tableFrom": "user_institution", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_institution_institution_id_institution_id_fk": { - "name": "user_institution_institution_id_institution_id_fk", - "tableFrom": "user_institution", - "tableTo": "institution", - "columnsFrom": [ - "institution_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_institution_id_unique": { - "name": "user_institution_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.user_role": { - "name": "user_role", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "user_role_user_id_user_id_fk": { - "name": "user_role_user_id_user_id_fk", - "tableFrom": "user_role", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_role_role_id_role_id_fk": { - "name": "user_role_role_id_role_id_fk", - "tableFrom": "user_role", - "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_role_id_unique": { - "name": "user_role_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.user_stats": { - "name": "user_stats", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "score": { - "name": "score", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "likes": { - "name": "likes", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "likes_received": { - "name": "likes_received", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "follows": { - "name": "follows", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "followers": { - "name": "followers", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "collections": { - "name": "collections", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "submitted_resources": { - "name": "submitted_resources", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "approved_resources": { - "name": "approved_resources", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "reviewed_resources": { - "name": "reviewed_resources", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "comments": { - "name": "comments", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - } - }, - "indexes": {}, - "foreignKeys": { - "user_stats_user_id_user_id_fk": { - "name": "user_stats_user_id_user_id_fk", - "tableFrom": "user_stats", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_stats_id_unique": { - "name": "user_stats_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - } - }, - "public.user": { - "name": "user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "username": { - "name": "username", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "password": { - "name": "password", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'sem descrição'" - }, - "institution": { - "name": "institution", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'sem instituição'" - }, - "birthday": { - "name": "birthday", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "cpf": { - "name": "cpf", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "confirmed_at": { - "name": "confirmed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "confirmation_sent_at": { - "name": "confirmation_sent_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "reactivated_at": { - "name": "reactivated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "active": { - "name": "active", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_id_unique": { - "name": "user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - }, - "user_username_unique": { - "name": "user_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - } - }, - "enums": {}, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json index cb78270..255a328 100644 --- a/src/db/migrations/meta/_journal.json +++ b/src/db/migrations/meta/_journal.json @@ -16,5 +16,6 @@ "tag": "0001_eager_living_lightning", "breakpoints": true } + ] } \ No newline at end of file diff --git a/src/db/repo/resource-educational-stages.repo.ts b/src/db/repo/resource-educational-stages.repo.ts new file mode 100644 index 0000000..27169f7 --- /dev/null +++ b/src/db/repo/resource-educational-stages.repo.ts @@ -0,0 +1,157 @@ +import { Service } from "typedi"; +import db from ".."; +import type { ResourceModel } from "../schema/resource.schema"; +import type { EducationalStagesModel } from "../schema/educational-stages.schema"; +import resourceEducationalStagesTable from "../schema/resource-educational-stages.schema"; +import { and, eq, inArray } from "drizzle-orm"; +import educationalStageTable from "../schema/educational-stages.schema"; +import resourceTable from "../schema/resource.schema"; + + + +@Service() +export class resourceEducationalStages { + + async associateResourceWithEducationalStages(resourceId: ResourceModel['id'], educationalStageIds: EducationalStagesModel['id'][]): Promise<void> { + try { + const existingAssociations = await db + .select({ + educational_stage_id: resourceEducationalStagesTable.educational_stage_id + }) + .from(resourceEducationalStagesTable) + .where(eq(resourceEducationalStagesTable.resource_id, resourceId)) + .execute(); + + const existingEducationalStageIds = existingAssociations.map(row => row.educational_stage_id); + const newEducationalStageIds = educationalStageIds.filter(educationalStageId => !existingEducationalStageIds.includes(educationalStageId)); + + if (newEducationalStageIds.length > 0) { + const valuesToInsert = newEducationalStageIds.map(educationalStageId => ({ + resource_id: resourceId, + educational_stage_id: educationalStageId + })); + + await db + .insert(resourceEducationalStagesTable) + .values(valuesToInsert) + .onConflictDoNothing() + .execute(); + + console.log(`Resource ${resourceId} associated with new educational stages: ${newEducationalStageIds.join(", ")}`); + } else { + console.log(`No new educational stages to associate for resource ${resourceId}`); + } + } catch (error) { + console.error("Error associating resource with educational stages:", error); + } + } + + + + async getEducationalStagesByResource(resourceId: ResourceModel['id']): Promise<EducationalStagesModel[]> { + try { + const educationalStages = await db + .select() + .from(resourceEducationalStagesTable) + .innerJoin(educationalStageTable, eq(resourceEducationalStagesTable.educational_stage_id, educationalStageTable.id)) + .where(eq(resourceEducationalStagesTable.resource_id, resourceId)) + .execute(); + + return educationalStages.map(row => row.educational_stages); + } catch (error) { + console.error("Error getting educational stages by resource:", error); + return []; + } + } + + async removeEducationalStageFromResource(resourceId: ResourceModel['id'], educationalStageId: EducationalStagesModel['id']): Promise<void> { + try { + await db + .delete(resourceEducationalStagesTable) + .where( + and( + eq(resourceEducationalStagesTable.resource_id, resourceId), + eq(resourceEducationalStagesTable.educational_stage_id, educationalStageId) + ) + ) + .execute(); + + console.log(`Educational stage ${educationalStageId} removed from resource ${resourceId}`); + } catch (error) { + console.error("Error removing educational stage from resource:", error); + } + } + + + async isAssociationExists(resourceId: ResourceModel['id'], educationalStageId: EducationalStagesModel['id']): Promise<boolean> { + try { + const result = await db + .select() + .from(resourceEducationalStagesTable) + .where( + and( + eq(resourceEducationalStagesTable.resource_id, resourceId), + eq(resourceEducationalStagesTable.educational_stage_id, educationalStageId) + ) + ) + .execute(); + + return result.length > 0; + } catch (error) { + console.error("Error checking if educational stage is associated with resource:", error); + return false; + } + } + + async getResourcesByEducationalStage(educationalStageId: EducationalStagesModel['id']): Promise<ResourceModel[]> { + try { + const resources = await db + .select() + .from(resourceEducationalStagesTable) + .innerJoin(resourceTable, eq(resourceEducationalStagesTable.resource_id, resourceTable.id)) + .where(eq(resourceEducationalStagesTable.educational_stage_id, educationalStageId)) + .execute(); + + return resources.map(row => row.resource); + } catch (error) { + console.error("Error getting resources by educational stage:", error); + return []; + } + } + + + async updateResourceEducationalStages(resourceId: ResourceModel['id'], newEducationalStageIds: EducationalStagesModel['id'][]): Promise<void> { + const existingAssociations = await db + .select({ + educational_stage_id: resourceEducationalStagesTable.educational_stage_id + }) + .from(resourceEducationalStagesTable) + .where(eq(resourceEducationalStagesTable.resource_id, resourceId)) + .execute(); + + const existingEducationalStageIds = existingAssociations.map(row => row.educational_stage_id); + const educationalStageToAdd = newEducationalStageIds.filter(educationalStageId => !existingEducationalStageIds.includes(educationalStageId)); + const educationalStageToRemove = existingEducationalStageIds.filter(educationalStageId => !newEducationalStageIds.includes(educationalStageId)); + + if (educationalStageToAdd.length > 0) { + const valuesToInsert = educationalStageToAdd.map(educationalStageId => ({ + resource_id: resourceId, + educational_stage_id: educationalStageId + })); + + await db.insert(resourceEducationalStagesTable).values(valuesToInsert).execute(); + } + + if (educationalStageToRemove.length > 0) { + await db + .delete(resourceEducationalStagesTable) + .where( + and( + eq(resourceEducationalStagesTable.resource_id, resourceId), + inArray(resourceEducationalStagesTable.educational_stage_id, educationalStageToRemove) + ) + ) + .execute(); + } + } +} \ No newline at end of file diff --git a/src/db/schema/educational-stages.schema.ts b/src/db/schema/educational-stages.schema.ts index ad9dd3a..e68d2a5 100644 --- a/src/db/schema/educational-stages.schema.ts +++ b/src/db/schema/educational-stages.schema.ts @@ -1,3 +1,4 @@ +import { relations } from "drizzle-orm"; import { pgTable, serial, varchar } from "drizzle-orm/pg-core"; import { createInsertSchema, createSelectSchema } from "drizzle-zod"; import type { z } from 'zod' @@ -8,7 +9,9 @@ const educationalStageTable = pgTable('educational_stages', { name: varchar('name').unique().notNull(), }) - +export const educationalStagesRelations = relations(educationalStageTable, ({many}) => ({ + resourceEducationalStages: many(educationalStageTable) +})) const educationalStagesModelSchema = createSelectSchema(educationalStageTable) const educationalStagesDtoSchema = educationalStagesModelSchema.omit({}) diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index 8671809..d0bbac5 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -25,6 +25,7 @@ import collectionResourcesTable from '../relations/collection-resources.relation import institutionTable from './institutions.schema' import userInstitutionRelationTable from '../relations/user-institution.relation' import resourceLikesTable from '../relations/resource-likes.relation' +import resourceEducationalStagesTable from './resource-educational-stages.schema' export { userTable, @@ -52,6 +53,7 @@ export { institutionTable, userInstitutionRelationTable, resourceLikesTable, + resourceEducationalStagesTable } export const tables = [ diff --git a/src/db/schema/resource-educational-stages.schema.ts b/src/db/schema/resource-educational-stages.schema.ts new file mode 100644 index 0000000..e8a7930 --- /dev/null +++ b/src/db/schema/resource-educational-stages.schema.ts @@ -0,0 +1,42 @@ +import { integer, pgTable } from "drizzle-orm/pg-core"; +import resourceTable from "./resource.schema"; +import educationalStageTable from "./educational-stages.schema"; +import { relations } from "drizzle-orm"; +import { createSelectSchema } from "drizzle-zod"; +import type { z } from "zod"; + + +const resourceEducationalStagesTable = pgTable('resource_educational_stages', { + resource_id: integer('resource_id').notNull().references(() => resourceTable.id, { onDelete: 'cascade' }), + educational_stage_id: integer('educational_stage_id').notNull().references(() => educationalStageTable.id, { onDelete: 'cascade' }) +}) + +export const resourceEducationalStagesRelations = relations(resourceEducationalStagesTable, ({ one }) => ({ + resource: one(resourceTable, { + fields: [resourceEducationalStagesTable.resource_id], + references: [resourceTable.id] + }), + educationalStage: one(educationalStageTable, { + fields: [resourceEducationalStagesTable.educational_stage_id], + references: [educationalStageTable.id] + }) +})) + +const resourceEducationalStagesModelSchema = createSelectSchema(resourceEducationalStagesTable) +const resourceEducationalStagesDtoSchema = resourceEducationalStagesModelSchema.omit({}) +const resourceEducationalStagesInputSchema = createSelectSchema(resourceEducationalStagesTable) +const resourceEducationalStagesUpdateSchema = resourceEducationalStagesInputSchema + +export type ResourceEducationalStagesModel = z.infer<typeof resourceEducationalStagesModelSchema> +export type ResourceEducationalStagesDto = z.infer<typeof resourceEducationalStagesDtoSchema> +export type ResourceEducationalStagesInput = z.infer<typeof resourceEducationalStagesInputSchema> +export type ResourceEducationalStagesUpdate = z.infer<typeof resourceEducationalStagesUpdateSchema> + +export const resourceEducationalStagesSchema = { + model: resourceEducationalStagesModelSchema, + dto: resourceEducationalStagesDtoSchema, + input: resourceEducationalStagesInputSchema, + update: resourceEducationalStagesUpdateSchema, +} + +export default resourceEducationalStagesTable \ No newline at end of file diff --git a/src/db/schema/resource.schema.ts b/src/db/schema/resource.schema.ts index d6fa308..1971ee5 100644 --- a/src/db/schema/resource.schema.ts +++ b/src/db/schema/resource.schema.ts @@ -10,6 +10,7 @@ import { createInsertSchema, createSelectSchema } from 'drizzle-zod' import type { z } from 'zod' import resourceLanguagesTable from './resource-languages.schema' import resourceSubjectsTable from './resource-subjects.schema' +import resourceEducationalStagesTable from './resource-educational-stages.schema' //por padrao active é false, só é true quando o recurso é aprovado const resourceTable = pgTable('resource', { @@ -33,7 +34,8 @@ const resourceTable = pgTable('resource', { export const resourceRelations = relations(resourceTable, ({ many }) => ({ resourceLanguages: many(resourceLanguagesTable), - resourceSubjects: many(resourceSubjectsTable) + resourceSubjects: many(resourceSubjectsTable), + resourceEducatinalStages: many(resourceEducationalStagesTable) }) ) diff --git a/src/db/seed.ts b/src/db/seed.ts index d43389f..c456c9f 100644 --- a/src/db/seed.ts +++ b/src/db/seed.ts @@ -43,5 +43,6 @@ await seeds.collectionResourcesSeed(db) await seeds.resourceSubjectsSeed(db) await seeds.userInstitutionSeed(db) await seeds.resourceLikesSeed(db) +await seeds.resourceEducationalStagesSeed(db) await connection.end() diff --git a/src/db/seeds/index.ts b/src/db/seeds/index.ts index cf31993..f683802 100644 --- a/src/db/seeds/index.ts +++ b/src/db/seeds/index.ts @@ -20,3 +20,4 @@ export { default as resourceSubjectsSeed } from './resource-subjects.seed' export { default as institutionSeed } from './institutions.seed' export { default as userInstitutionSeed } from './user-institution.seed' export { default as resourceLikesSeed } from './resource-likes.seed' +export { default as resourceEducationalStagesSeed } from './resource-educational-stages.seed' diff --git a/src/db/seeds/resource-educational-stages.seed.ts b/src/db/seeds/resource-educational-stages.seed.ts new file mode 100644 index 0000000..29e03d9 --- /dev/null +++ b/src/db/seeds/resource-educational-stages.seed.ts @@ -0,0 +1,25 @@ +import type db from ".."; +import resourceEducationalStagesTable, { type ResourceEducationalStagesInput } from "../schema/resource-educational-stages.schema"; + +export default async function seed(db: db) { + await db.insert(resourceEducationalStagesTable).values(resourceEducationalStagesData); +} + +const resourceEducationalStagesData: ResourceEducationalStagesInput[] = [ + { + resource_id: 1, + educational_stage_id: 1 + }, + { + resource_id: 1, + educational_stage_id: 2 + }, + { + resource_id: 2, + educational_stage_id: 1 + }, + { + resource_id: 2, + educational_stage_id: 3 + } +]; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 632a998..f0cd40b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,12 +29,10 @@ import { userRoleRouter } from './routes/user-role.route' import { collectionLikesRoutes, publicCollectionLikesRoutes } from './routes/collection-likes.route' import { institutionRouter } from './routes/institution.route' import { collectionResourcesRoutes, publicCollectionResourcesRoutes } from './routes/collection-resources.route' -<<<<<<< HEAD import { publicResourceSubjectsRouter, resourceSubjectsRouter } from './routes/resource-subjects.route' import { userInstitutionRouter } from './routes/user-institution.route' -======= import { publicResourceLikesRoutes, resourceLikesRoutes } from './routes/resource-likes.route' ->>>>>>> 04db82e (para não perder) +import { publicResourceEducationalStagesRouter, resourceEducationalStagesRouter } from './routes/resource-educational-stages.route' const app = new Hono() @@ -71,7 +69,7 @@ app.get('/', (c) => c.json({ message: 'sv running on /api' })) //rotas que não precisam de token app -.basePath('/public') + .basePath('/public') .route('/auth', authRouter) .route('/signup', signUpRouter) .route('/reset-password', passRouter) @@ -88,6 +86,7 @@ app .route('/collectionLikes', publicCollectionLikesRoutes) .route('/collectionResources', publicCollectionResourcesRoutes) .route('/resourceSubjects', publicResourceSubjectsRouter) + .route('/resourceEducationalStages', publicResourceEducationalStagesRouter) .route('/resourceLikes', publicResourceLikesRoutes) //rotas que precisam de token @@ -115,6 +114,7 @@ app .route('/collectionResources', collectionResourcesRoutes) .route('/resourceSubjects', resourceSubjectsRouter) .route('/user-institutions', userInstitutionRouter) + .route('/resourceEducationalStages', resourceEducationalStagesRouter) .route('/resourceLikes', resourceLikesRoutes) export default app diff --git a/src/routes/resource-educational-stages.route.ts b/src/routes/resource-educational-stages.route.ts new file mode 100644 index 0000000..7570899 --- /dev/null +++ b/src/routes/resource-educational-stages.route.ts @@ -0,0 +1,155 @@ +import { ResourceEducationalStagesService } from "@/services/resource-educational-stages.service"; +import Container from "typedi"; +import { z } from "zod"; +import { honoWithJwt } from ".."; +import { createApexError, HttpStatus } from "@/services/error.service"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; + +const associateSchema = z.object({ + resourceId: z.number(), + educationalStageIds: z.array(z.number()), +}); + +const service = Container.get(ResourceEducationalStagesService); + +export const resourceEducationalStagesRouter = honoWithJwt() + + .post( + '/associate', + zValidator('json', associateSchema), + async (c) => { + try { + const { resourceId, educationalStageIds } = await c.req.valid('json'); + await service.associateResourceWithEducationalStages(resourceId, educationalStageIds); + return c.json({ message: 'Educational stages associated successfully' }, HttpStatus.OK); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to associate educational stages', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) + + .post( + '/:resourceId/delete/educationalStage/:educationalStageId', + async (c) => { + try { + const resourceId = +c.req.param('resourceId'); + const educationalStageId = +c.req.param('educationalStageId'); + await service.removeEducationalStageFromResource(resourceId, educationalStageId); + return c.json({ message: 'Educational stage removed successfully' }, HttpStatus.OK); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to remove educational stage', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) + + .post( + '/update/educationalStages', + zValidator('json', associateSchema), + async (c) => { + try { + const { resourceId, educationalStageIds } = await c.req.valid('json'); + await service.updateResourceEducationalStages(resourceId, educationalStageIds); + return c.json({ message: 'Educational stages updated successfully' }, HttpStatus.OK); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to update educational stages', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) + + +export const publicResourceEducationalStagesRouter = new Hono() + + .get( + '/:resourceId/educationalStages', + async (c) => { + try { + const resourceId = +c.req.param('resourceId'); + const educationalStages = await service.getEducationalStagesByResource(resourceId); + return c.json(educationalStages); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to get educational stages', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) + + .get( + '/:resourceId/educationalStages/:educationalStageId/exists', + async (c) => { + try { + const resourceId = +c.req.param('resourceId'); + const educationalStageId = +c.req.param('educationalStageId'); + const exists = await service.isAssociationExists(resourceId, educationalStageId); + return c.json({ exists }); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to check association', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) + + .get( + '/educationalStage/:educationalStageId/resources', + async (c) => { + try { + const educationalStageId = +c.req.param('educationalStageId'); + const resources = await service.getResourcesByEducationalStage(educationalStageId); + return c.json(resources); + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'Failed to get resources', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'Check the input and try again', + }), + HttpStatus.BAD_REQUEST + ); + } + } + ) \ No newline at end of file diff --git a/src/services/resource-educational-stages.service.ts b/src/services/resource-educational-stages.service.ts new file mode 100644 index 0000000..37dd70c --- /dev/null +++ b/src/services/resource-educational-stages.service.ts @@ -0,0 +1,35 @@ +import { resourceEducationalStages } from "@/db/repo/resource-educational-stages.repo"; +import type { EducationalStagesModel } from "@/db/schema/educational-stages.schema"; +import type { ResourceModel } from "@/db/schema/resource.schema"; +import { Inject, Service } from "typedi"; + +@Service() +export class ResourceEducationalStagesService { + @Inject() + private readonly repo: resourceEducationalStages; + + async associateResourceWithEducationalStages(resourceId: ResourceModel['id'], educationalStages: EducationalStagesModel['id'][]): Promise<void> { + await this.repo.associateResourceWithEducationalStages(resourceId, educationalStages); + } + + async getEducationalStagesByResource(resourceId: ResourceModel['id']): Promise<EducationalStagesModel[]> { + return await this.repo.getEducationalStagesByResource(resourceId); + } + + async removeEducationalStageFromResource(resourceId: ResourceModel['id'], educationalStageId: EducationalStagesModel['id']): Promise<void> { + await this.repo.removeEducationalStageFromResource(resourceId, educationalStageId); + } + + async isAssociationExists(resourceId: ResourceModel['id'], educationalStageId: EducationalStagesModel['id']): Promise<boolean> { + return await this.repo.isAssociationExists(resourceId, educationalStageId); + } + + async getResourcesByEducationalStage(educationalStageId: EducationalStagesModel['id']): Promise<ResourceModel[]> { + return await this.repo.getResourcesByEducationalStage(educationalStageId); + } + + async updateResourceEducationalStages(resourceId: ResourceModel['id'], newEducationalStageIds: EducationalStagesModel['id'][]): Promise<void> { + await this.repo.updateResourceEducationalStages(resourceId, newEducationalStageIds); + } + +} \ No newline at end of file -- GitLab