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