Browse Source

fix clases and secciones

Matthew Trejo 4 months ago
parent
commit
1d7a9b638d

+ 2 - 0
drizzle/0002_silky_micromax.sql

@@ -0,0 +1,2 @@
+ALTER TABLE "classes" ADD COLUMN "period_id" uuid;--> statement-breakpoint
+ALTER TABLE "classes" ADD CONSTRAINT "classes_period_id_periods_id_fk" FOREIGN KEY ("period_id") REFERENCES "public"."periods"("id") ON DELETE no action ON UPDATE no action;

+ 3 - 0
drizzle/0003_round_jackal.sql

@@ -0,0 +1,3 @@
+ALTER TABLE "sections" DROP CONSTRAINT "sections_period_id_periods_id_fk";
+--> statement-breakpoint
+ALTER TABLE "sections" DROP COLUMN "period_id";

+ 771 - 0
drizzle/meta/0002_snapshot.json

@@ -0,0 +1,771 @@
+{
+  "id": "689081c0-94c4-4c90-a1ee-ccdce86fbe77",
+  "prevId": "a52e7c22-a395-4c42-b9eb-2093435413bb",
+  "version": "7",
+  "dialect": "postgresql",
+  "tables": {
+    "public.attendance": {
+      "name": "attendance",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "student_id": {
+          "name": "student_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "teacher_id": {
+          "name": "teacher_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "partial_id": {
+          "name": "partial_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "date": {
+          "name": "date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "status": {
+          "name": "status",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "reason": {
+          "name": "reason",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "attendance_student_id_users_id_fk": {
+          "name": "attendance_student_id_users_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "users",
+          "columnsFrom": [
+            "student_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_class_id_classes_id_fk": {
+          "name": "attendance_class_id_classes_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_section_id_sections_id_fk": {
+          "name": "attendance_section_id_sections_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_teacher_id_users_id_fk": {
+          "name": "attendance_teacher_id_users_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "users",
+          "columnsFrom": [
+            "teacher_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_partial_id_partials_id_fk": {
+          "name": "attendance_partial_id_partials_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "partials",
+          "columnsFrom": [
+            "partial_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.classes": {
+      "name": "classes",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "code": {
+          "name": "code",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "credits": {
+          "name": "credits",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "period_id": {
+          "name": "period_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "classes_period_id_periods_id_fk": {
+          "name": "classes_period_id_periods_id_fk",
+          "tableFrom": "classes",
+          "tableTo": "periods",
+          "columnsFrom": [
+            "period_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "classes_code_unique": {
+          "name": "classes_code_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "code"
+          ]
+        }
+      },
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.partials": {
+      "name": "partials",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "period_id": {
+          "name": "period_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "start_date": {
+          "name": "start_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "end_date": {
+          "name": "end_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "partials_period_id_periods_id_fk": {
+          "name": "partials_period_id_periods_id_fk",
+          "tableFrom": "partials",
+          "tableTo": "periods",
+          "columnsFrom": [
+            "period_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.periods": {
+      "name": "periods",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "start_date": {
+          "name": "start_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "end_date": {
+          "name": "end_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.sections": {
+      "name": "sections",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "period_id": {
+          "name": "period_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "max_students": {
+          "name": "max_students",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "sections_class_id_classes_id_fk": {
+          "name": "sections_class_id_classes_id_fk",
+          "tableFrom": "sections",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "sections_period_id_periods_id_fk": {
+          "name": "sections_period_id_periods_id_fk",
+          "tableFrom": "sections",
+          "tableTo": "periods",
+          "columnsFrom": [
+            "period_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.student_enrollments": {
+      "name": "student_enrollments",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "student_id": {
+          "name": "student_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "student_enrollments_student_id_users_id_fk": {
+          "name": "student_enrollments_student_id_users_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "users",
+          "columnsFrom": [
+            "student_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "student_enrollments_class_id_classes_id_fk": {
+          "name": "student_enrollments_class_id_classes_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "student_enrollments_section_id_sections_id_fk": {
+          "name": "student_enrollments_section_id_sections_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.teacher_assignments": {
+      "name": "teacher_assignments",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "teacher_id": {
+          "name": "teacher_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "teacher_assignments_teacher_id_users_id_fk": {
+          "name": "teacher_assignments_teacher_id_users_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "users",
+          "columnsFrom": [
+            "teacher_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "teacher_assignments_class_id_classes_id_fk": {
+          "name": "teacher_assignments_class_id_classes_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "teacher_assignments_section_id_sections_id_fk": {
+          "name": "teacher_assignments_section_id_sections_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.users": {
+      "name": "users",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "email": {
+          "name": "email",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "password": {
+          "name": "password",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "first_name": {
+          "name": "first_name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "last_name": {
+          "name": "last_name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "cedula": {
+          "name": "cedula",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "phone": {
+          "name": "phone",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "role": {
+          "name": "role",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "admission_number": {
+          "name": "admission_number",
+          "type": "varchar(50)",
+          "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": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "users_email_unique": {
+          "name": "users_email_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "email"
+          ]
+        },
+        "users_cedula_unique": {
+          "name": "users_cedula_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "cedula"
+          ]
+        }
+      },
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    }
+  },
+  "enums": {},
+  "schemas": {},
+  "sequences": {},
+  "roles": {},
+  "policies": {},
+  "views": {},
+  "_meta": {
+    "columns": {},
+    "schemas": {},
+    "tables": {}
+  }
+}

+ 752 - 0
drizzle/meta/0003_snapshot.json

@@ -0,0 +1,752 @@
+{
+  "id": "6f4da49b-981a-4f9a-b990-14d457ea2111",
+  "prevId": "689081c0-94c4-4c90-a1ee-ccdce86fbe77",
+  "version": "7",
+  "dialect": "postgresql",
+  "tables": {
+    "public.attendance": {
+      "name": "attendance",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "student_id": {
+          "name": "student_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "teacher_id": {
+          "name": "teacher_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "partial_id": {
+          "name": "partial_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "date": {
+          "name": "date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "status": {
+          "name": "status",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "reason": {
+          "name": "reason",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "attendance_student_id_users_id_fk": {
+          "name": "attendance_student_id_users_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "users",
+          "columnsFrom": [
+            "student_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_class_id_classes_id_fk": {
+          "name": "attendance_class_id_classes_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_section_id_sections_id_fk": {
+          "name": "attendance_section_id_sections_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_teacher_id_users_id_fk": {
+          "name": "attendance_teacher_id_users_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "users",
+          "columnsFrom": [
+            "teacher_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "attendance_partial_id_partials_id_fk": {
+          "name": "attendance_partial_id_partials_id_fk",
+          "tableFrom": "attendance",
+          "tableTo": "partials",
+          "columnsFrom": [
+            "partial_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.classes": {
+      "name": "classes",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "code": {
+          "name": "code",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "credits": {
+          "name": "credits",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "period_id": {
+          "name": "period_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "classes_period_id_periods_id_fk": {
+          "name": "classes_period_id_periods_id_fk",
+          "tableFrom": "classes",
+          "tableTo": "periods",
+          "columnsFrom": [
+            "period_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "classes_code_unique": {
+          "name": "classes_code_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "code"
+          ]
+        }
+      },
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.partials": {
+      "name": "partials",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "period_id": {
+          "name": "period_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "start_date": {
+          "name": "start_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "end_date": {
+          "name": "end_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "partials_period_id_periods_id_fk": {
+          "name": "partials_period_id_periods_id_fk",
+          "tableFrom": "partials",
+          "tableTo": "periods",
+          "columnsFrom": [
+            "period_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.periods": {
+      "name": "periods",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "start_date": {
+          "name": "start_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "end_date": {
+          "name": "end_date",
+          "type": "date",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.sections": {
+      "name": "sections",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "max_students": {
+          "name": "max_students",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "sections_class_id_classes_id_fk": {
+          "name": "sections_class_id_classes_id_fk",
+          "tableFrom": "sections",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.student_enrollments": {
+      "name": "student_enrollments",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "student_id": {
+          "name": "student_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "student_enrollments_student_id_users_id_fk": {
+          "name": "student_enrollments_student_id_users_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "users",
+          "columnsFrom": [
+            "student_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "student_enrollments_class_id_classes_id_fk": {
+          "name": "student_enrollments_class_id_classes_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "student_enrollments_section_id_sections_id_fk": {
+          "name": "student_enrollments_section_id_sections_id_fk",
+          "tableFrom": "student_enrollments",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.teacher_assignments": {
+      "name": "teacher_assignments",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "teacher_id": {
+          "name": "teacher_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "class_id": {
+          "name": "class_id",
+          "type": "uuid",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "section_id": {
+          "name": "section_id",
+          "type": "uuid",
+          "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": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "teacher_assignments_teacher_id_users_id_fk": {
+          "name": "teacher_assignments_teacher_id_users_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "users",
+          "columnsFrom": [
+            "teacher_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "teacher_assignments_class_id_classes_id_fk": {
+          "name": "teacher_assignments_class_id_classes_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "classes",
+          "columnsFrom": [
+            "class_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        },
+        "teacher_assignments_section_id_sections_id_fk": {
+          "name": "teacher_assignments_section_id_sections_id_fk",
+          "tableFrom": "teacher_assignments",
+          "tableTo": "sections",
+          "columnsFrom": [
+            "section_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.users": {
+      "name": "users",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "uuid",
+          "primaryKey": true,
+          "notNull": true,
+          "default": "gen_random_uuid()"
+        },
+        "email": {
+          "name": "email",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "password": {
+          "name": "password",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "first_name": {
+          "name": "first_name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "last_name": {
+          "name": "last_name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "cedula": {
+          "name": "cedula",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "phone": {
+          "name": "phone",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "role": {
+          "name": "role",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "admission_number": {
+          "name": "admission_number",
+          "type": "varchar(50)",
+          "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": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "users_email_unique": {
+          "name": "users_email_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "email"
+          ]
+        },
+        "users_cedula_unique": {
+          "name": "users_cedula_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "cedula"
+          ]
+        }
+      },
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    }
+  },
+  "enums": {},
+  "schemas": {},
+  "sequences": {},
+  "roles": {},
+  "policies": {},
+  "views": {},
+  "_meta": {
+    "columns": {},
+    "schemas": {},
+    "tables": {}
+  }
+}

+ 14 - 0
drizzle/meta/_journal.json

@@ -15,6 +15,20 @@
       "when": 1755504262104,
       "tag": "0001_normal_juggernaut",
       "breakpoints": true
+    },
+    {
+      "idx": 2,
+      "version": "7",
+      "when": 1755508119734,
+      "tag": "0002_silky_micromax",
+      "breakpoints": true
+    },
+    {
+      "idx": 3,
+      "version": "7",
+      "when": 1755508696025,
+      "tag": "0003_round_jackal",
+      "breakpoints": true
     }
   ]
 }

+ 64 - 6
src/app/admin/classes/page.tsx

@@ -10,12 +10,22 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
 import { Trash2, Edit, Plus, BookOpen } from 'lucide-react';
 import { DashboardLayout } from '@/components/dashboard-layout';
 
+interface Period {
+  id: string;
+  name: string;
+  startDate: string;
+  endDate: string;
+  isActive: boolean;
+}
+
 interface Class {
   id: string;
   name: string;
   code: string;
   credits: number;
   description?: string;
+  periodId?: string;
+  period?: Period;
   isActive: boolean;
   createdAt: string;
 }
@@ -25,15 +35,18 @@ interface FormData {
   code: string;
   credits: string;
   description: string;
+  periodId: string;
 }
 
 export default function ClassesPage() {
   const [classes, setClasses] = useState<Class[]>([]);
+  const [periods, setPeriods] = useState<Period[]>([]);
   const [formData, setFormData] = useState<FormData>({
     name: '',
     code: '',
     credits: '',
-    description: ''
+    description: '',
+    periodId: ''
   });
   const [editingId, setEditingId] = useState<string | null>(null);
   const [error, setError] = useState('');
@@ -42,6 +55,7 @@ export default function ClassesPage() {
 
   useEffect(() => {
     fetchClasses();
+    fetchPeriods();
   }, []);
 
   const fetchClasses = async () => {
@@ -56,6 +70,18 @@ export default function ClassesPage() {
     }
   };
 
+  const fetchPeriods = async () => {
+    try {
+      const response = await fetch('/api/admin/periods');
+      if (response.ok) {
+        const data = await response.json();
+        setPeriods(data.filter((period: Period) => period.isActive));
+      }
+    } catch (error) {
+      console.error('Error fetching periods:', error);
+    }
+  };
+
   const handleSubmit = async (e: React.FormEvent) => {
     e.preventDefault();
     setLoading(true);
@@ -70,6 +96,12 @@ export default function ClassesPage() {
         return;
       }
 
+      if (!formData.periodId) {
+        setError('Debe seleccionar un período académico');
+        setLoading(false);
+        return;
+      }
+
       const url = editingId ? `/api/admin/classes/${editingId}` : '/api/admin/classes';
       const method = editingId ? 'PUT' : 'POST';
 
@@ -82,13 +114,14 @@ export default function ClassesPage() {
           name: formData.name,
           code: formData.code,
           credits,
-          description: formData.description || undefined
+          description: formData.description || undefined,
+          periodId: formData.periodId
         }),
       });
 
       if (response.ok) {
         setSuccess(editingId ? 'Clase actualizada exitosamente' : 'Clase creada exitosamente');
-        setFormData({ name: '', code: '', credits: '', description: '' });
+        setFormData({ name: '', code: '', credits: '', description: '', periodId: '' });
         setEditingId(null);
         fetchClasses();
       } else {
@@ -107,7 +140,8 @@ export default function ClassesPage() {
       name: classItem.name,
       code: classItem.code,
       credits: classItem.credits.toString(),
-      description: classItem.description || ''
+      description: classItem.description || '',
+      periodId: classItem.periodId || ''
     });
     setEditingId(classItem.id);
     setError('');
@@ -137,7 +171,7 @@ export default function ClassesPage() {
   };
 
   const handleCancel = () => {
-    setFormData({ name: '', code: '', credits: '', description: '' });
+    setFormData({ name: '', code: '', credits: '', description: '', periodId: '' });
     setEditingId(null);
     setError('');
     setSuccess('');
@@ -204,6 +238,25 @@ export default function ClassesPage() {
                 />
               </div>
 
+              <div>
+                <Label htmlFor="periodId">Período Académico</Label>
+                <Select
+                  value={formData.periodId}
+                  onValueChange={(value) => setFormData({ ...formData, periodId: value })}
+                >
+                  <SelectTrigger>
+                    <SelectValue placeholder="Seleccionar período" />
+                  </SelectTrigger>
+                  <SelectContent>
+                    {periods.map((period) => (
+                      <SelectItem key={period.id} value={period.id}>
+                        {period.name}
+                      </SelectItem>
+                    ))}
+                  </SelectContent>
+                </Select>
+              </div>
+
               <div>
                 <Label htmlFor="description">Descripción (Opcional)</Label>
                 <Input
@@ -257,7 +310,7 @@ export default function ClassesPage() {
                     className="flex items-center justify-between p-3 border rounded-lg hover:bg-gray-50"
                   >
                     <div className="flex-1">
-                      <div className="flex items-center gap-2">
+                      <div className="flex items-center gap-2 flex-wrap">
                         <h3 className="font-medium">{classItem.name}</h3>
                         <span className="text-sm bg-blue-100 text-blue-800 px-2 py-1 rounded">
                           {classItem.code}
@@ -265,6 +318,11 @@ export default function ClassesPage() {
                         <span className="text-sm bg-gray-100 text-gray-800 px-2 py-1 rounded">
                           {classItem.credits} créditos
                         </span>
+                        {classItem.period && (
+                          <span className="text-sm bg-green-100 text-green-800 px-2 py-1 rounded">
+                            {classItem.period.name}
+                          </span>
+                        )}
                       </div>
                       {classItem.description && (
                         <p className="text-sm text-gray-600 mt-1">{classItem.description}</p>

+ 5 - 38
src/app/admin/sections/page.tsx

@@ -16,7 +16,6 @@ interface Section {
   classId: string;
   className: string;
   classCode: string;
-  periodId: string;
   periodName: string;
   maxStudents: number;
   isActive: boolean;
@@ -27,6 +26,7 @@ interface Class {
   id: string;
   name: string;
   code: string;
+  periodId?: string;
   isActive?: boolean;
 }
 
@@ -39,7 +39,6 @@ interface Period {
 interface FormData {
   name: string;
   classId: string;
-  periodId: string;
   maxStudents: string;
 }
 
@@ -50,7 +49,6 @@ export default function SectionsPage() {
   const [formData, setFormData] = useState<FormData>({
     name: '',
     classId: '',
-    periodId: '',
     maxStudents: ''
   });
   const [editingId, setEditingId] = useState<string | null>(null);
@@ -61,7 +59,6 @@ export default function SectionsPage() {
   useEffect(() => {
     fetchSections();
     fetchClasses();
-    fetchPeriods();
   }, []);
 
   const fetchSections = async () => {
@@ -88,17 +85,7 @@ export default function SectionsPage() {
     }
   };
 
-  const fetchPeriods = async () => {
-    try {
-      const response = await fetch('/api/admin/periods');
-      if (response.ok) {
-        const data = await response.json();
-        setPeriods(data.filter((p: Period) => p.isActive !== false));
-      }
-    } catch (error) {
-      console.error('Error fetching periods:', error);
-    }
-  };
+
 
   const handleSubmit = async (e: React.FormEvent) => {
     e.preventDefault();
@@ -125,14 +112,13 @@ export default function SectionsPage() {
         body: JSON.stringify({
           name: formData.name,
           classId: formData.classId,
-          periodId: formData.periodId,
           maxStudents
         }),
       });
 
       if (response.ok) {
         setSuccess(editingId ? 'Sección actualizada exitosamente' : 'Sección creada exitosamente');
-        setFormData({ name: '', classId: '', periodId: '', maxStudents: '' });
+        setFormData({ name: '', classId: '', maxStudents: '' });
         setEditingId(null);
         fetchSections();
       } else {
@@ -150,7 +136,6 @@ export default function SectionsPage() {
     setFormData({
       name: section.name,
       classId: section.classId,
-      periodId: section.periodId,
       maxStudents: section.maxStudents.toString()
     });
     setEditingId(section.id);
@@ -181,7 +166,7 @@ export default function SectionsPage() {
   };
 
   const handleCancel = () => {
-    setFormData({ name: '', classId: '', periodId: '', maxStudents: '' });
+    setFormData({ name: '', classId: '', maxStudents: '' });
     setEditingId(null);
     setError('');
     setSuccess('');
@@ -243,25 +228,7 @@ export default function SectionsPage() {
                 </Select>
               </div>
 
-              <div>
-                <Label htmlFor="periodId">Período Académico</Label>
-                <Select
-                  value={formData.periodId}
-                  onValueChange={(value) => setFormData({ ...formData, periodId: value })}
-                  required
-                >
-                  <SelectTrigger>
-                    <SelectValue placeholder="Seleccionar período" />
-                  </SelectTrigger>
-                  <SelectContent>
-                    {periods.map((period) => (
-                      <SelectItem key={period.id} value={period.id}>
-                        {period.name}
-                      </SelectItem>
-                    ))}
-                  </SelectContent>
-                </Select>
-              </div>
+
 
               <div>
                 <Label htmlFor="maxStudents">Máximo de Estudiantes</Label>

+ 5 - 3
src/app/api/admin/classes/[id]/route.ts

@@ -20,12 +20,12 @@ export async function PUT(request: NextRequest, context: RouteContext) {
     }
 
     const { id } = await context.params;
-    const { name, code, credits, description } = await request.json();
+    const { name, code, credits, description, periodId } = await request.json();
 
     // Validaciones
-    if (!name || !code || !credits) {
+    if (!name || !code || !credits || !periodId) {
       return NextResponse.json(
-        { error: 'Nombre, código y créditos son requeridos' },
+        { error: 'Nombre, código, créditos y período académico son requeridos' },
         { status: 400 }
       );
     }
@@ -76,6 +76,7 @@ export async function PUT(request: NextRequest, context: RouteContext) {
         code,
         credits,
         description: description || null,
+        periodId,
         updatedAt: new Date(),
       })
       .where(eq(classes.id, id))
@@ -85,6 +86,7 @@ export async function PUT(request: NextRequest, context: RouteContext) {
         code: classes.code,
         credits: classes.credits,
         description: classes.description,
+        periodId: classes.periodId,
         isActive: classes.isActive,
         updatedAt: classes.updatedAt,
       });

+ 15 - 4
src/app/api/admin/classes/route.ts

@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
 import { getServerSession } from 'next-auth';
 import { authOptions } from '@/lib/auth';
 import { db } from '@/lib/db';
-import { classes, eq } from '@/lib/db/schema';
+import { classes, periods, eq } from '@/lib/db/schema';
 
 export async function GET() {
   try {
@@ -22,10 +22,19 @@ export async function GET() {
         code: classes.code,
         credits: classes.credits,
         description: classes.description,
+        periodId: classes.periodId,
         isActive: classes.isActive,
         createdAt: classes.createdAt,
+        period: {
+          id: periods.id,
+          name: periods.name,
+          startDate: periods.startDate,
+          endDate: periods.endDate,
+          isActive: periods.isActive,
+        },
       })
       .from(classes)
+      .leftJoin(periods, eq(classes.periodId, periods.id))
       .orderBy(classes.name);
 
     return NextResponse.json(allClasses);
@@ -49,12 +58,12 @@ export async function POST(request: NextRequest) {
       );
     }
 
-    const { name, code, credits, description } = await request.json();
+    const { name, code, credits, description, periodId } = await request.json();
 
     // Validaciones
-    if (!name || !code || !credits) {
+    if (!name || !code || !credits || !periodId) {
       return NextResponse.json(
-        { error: 'Nombre, código y créditos son requeridos' },
+        { error: 'Nombre, código, créditos y período académico son requeridos' },
         { status: 400 }
       );
     }
@@ -88,6 +97,7 @@ export async function POST(request: NextRequest) {
         code,
         credits,
         description: description || null,
+        periodId,
         isActive: true,
       })
       .returning({
@@ -96,6 +106,7 @@ export async function POST(request: NextRequest) {
         code: classes.code,
         credits: classes.credits,
         description: classes.description,
+        periodId: classes.periodId,
         isActive: classes.isActive,
         createdAt: classes.createdAt,
       });

+ 7 - 7
src/app/api/admin/periods/[id]/route.ts

@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
 import { getServerSession } from 'next-auth';
 import { authOptions } from '@/lib/auth';
 import { db } from '@/lib/db';
-import { periods, sections, partials } from '@/lib/db/schema';
+import { periods, sections, partials, classes } from '@/lib/db/schema';
 import { eq, and } from 'drizzle-orm';
 
 // PUT - Actualizar período académico
@@ -132,16 +132,16 @@ export async function DELETE(
       );
     }
 
-    // Verificar si el período tiene secciones asociadas (las secciones están vinculadas a períodos)
-    const associatedSections = await db
+    // Verificar si el período tiene clases asociadas
+    const associatedClasses = await db
       .select()
-      .from(sections)
-      .where(eq(sections.periodId, id))
+      .from(classes)
+      .where(eq(classes.periodId, id))
       .limit(1);
 
-    if (associatedSections.length > 0) {
+    if (associatedClasses.length > 0) {
       return NextResponse.json(
-        { error: 'No se puede eliminar el período porque tiene secciones asociadas' },
+        { error: 'No se puede eliminar el período porque tiene clases asociadas' },
         { status: 400 }
       );
     }

+ 4 - 21
src/app/api/admin/sections/[id]/route.ts

@@ -20,10 +20,10 @@ export async function PUT(request: NextRequest, context: RouteContext) {
     }
 
     const { id } = await context.params;
-    const { name, classId, periodId, maxStudents } = await request.json();
+    const { name, classId, maxStudents } = await request.json();
 
     // Validaciones
-    if (!name || !classId || !periodId || !maxStudents) {
+    if (!name || !classId || !maxStudents) {
       return NextResponse.json(
         { error: 'Todos los campos son requeridos' },
         { status: 400 }
@@ -65,35 +65,20 @@ export async function PUT(request: NextRequest, context: RouteContext) {
       );
     }
 
-    // Verificar si el período existe
-    const existingPeriod = await db
-      .select()
-      .from(periods)
-      .where(eq(periods.id, periodId))
-      .limit(1);
-
-    if (existingPeriod.length === 0) {
-      return NextResponse.json(
-        { error: 'El período seleccionado no existe' },
-        { status: 400 }
-      );
-    }
-
-    // Verificar si ya existe otra sección con el mismo nombre para la misma clase y período
+    // Verificar si ya existe otra sección con el mismo nombre para la misma clase
     const duplicateSection = await db
       .select()
       .from(sections)
       .where(and(
         eq(sections.name, name),
         eq(sections.classId, classId),
-        eq(sections.periodId, periodId),
         ne(sections.id, id)
       ))
       .limit(1);
 
     if (duplicateSection.length > 0) {
       return NextResponse.json(
-        { error: 'Ya existe otra sección con este nombre para la misma clase y período' },
+        { error: 'Ya existe otra sección con este nombre para la misma clase' },
         { status: 400 }
       );
     }
@@ -117,7 +102,6 @@ export async function PUT(request: NextRequest, context: RouteContext) {
       .set({
         name,
         classId,
-        periodId,
         maxStudents,
         updatedAt: new Date(),
       })
@@ -126,7 +110,6 @@ export async function PUT(request: NextRequest, context: RouteContext) {
         id: sections.id,
         name: sections.name,
         classId: sections.classId,
-        periodId: sections.periodId,
         maxStudents: sections.maxStudents,
         isActive: sections.isActive,
         updatedAt: sections.updatedAt,

+ 6 - 24
src/app/api/admin/sections/route.ts

@@ -22,7 +22,6 @@ export async function GET() {
         classId: sections.classId,
         className: classes.name,
         classCode: classes.code,
-        periodId: sections.periodId,
         periodName: periods.name,
         maxStudents: sections.maxStudents,
         isActive: sections.isActive,
@@ -30,7 +29,7 @@ export async function GET() {
       })
       .from(sections)
       .leftJoin(classes, eq(sections.classId, classes.id))
-      .leftJoin(periods, eq(sections.periodId, periods.id))
+      .leftJoin(periods, eq(classes.periodId, periods.id))
       .orderBy(classes.code, sections.name);
 
     return NextResponse.json(allSections);
@@ -54,10 +53,10 @@ export async function POST(request: NextRequest) {
       );
     }
 
-    const { name, classId, periodId, maxStudents } = await request.json();
+    const { name, classId, maxStudents } = await request.json();
 
     // Validaciones
-    if (!name || !classId || !periodId || !maxStudents) {
+    if (!name || !classId || !maxStudents) {
       return NextResponse.json(
         { error: 'Todos los campos son requeridos' },
         { status: 400 }
@@ -85,34 +84,19 @@ export async function POST(request: NextRequest) {
       );
     }
 
-    // Verificar si el período existe
-    const existingPeriod = await db
-      .select()
-      .from(periods)
-      .where(eq(periods.id, periodId))
-      .limit(1);
-
-    if (existingPeriod.length === 0) {
-      return NextResponse.json(
-        { error: 'El período seleccionado no existe' },
-        { status: 400 }
-      );
-    }
-
-    // Verificar si ya existe una sección con el mismo nombre para la misma clase y período
+    // Verificar si ya existe una sección con el mismo nombre para la misma clase
     const existingSection = await db
       .select()
       .from(sections)
       .where(and(
         eq(sections.name, name),
-        eq(sections.classId, classId),
-        eq(sections.periodId, periodId)
+        eq(sections.classId, classId)
       ))
       .limit(1);
 
     if (existingSection.length > 0) {
       return NextResponse.json(
-        { error: 'Ya existe una sección con este nombre para la misma clase y período' },
+        { error: 'Ya existe una sección con este nombre para la misma clase' },
         { status: 400 }
       );
     }
@@ -123,7 +107,6 @@ export async function POST(request: NextRequest) {
       .values({
         name,
         classId,
-        periodId,
         maxStudents,
         isActive: true,
       })
@@ -131,7 +114,6 @@ export async function POST(request: NextRequest) {
         id: sections.id,
         name: sections.name,
         classId: sections.classId,
-        periodId: sections.periodId,
         maxStudents: sections.maxStudents,
         isActive: sections.isActive,
         createdAt: sections.createdAt,

+ 1 - 1
src/app/api/teacher/sections/route.ts

@@ -33,7 +33,7 @@ export async function GET(request: NextRequest) {
       .from(teacherAssignments)
       .innerJoin(sections, eq(teacherAssignments.sectionId, sections.id))
       .innerJoin(classes, eq(sections.classId, classes.id))
-      .innerJoin(periods, eq(sections.periodId, periods.id))
+      .innerJoin(periods, eq(classes.periodId, periods.id))
       .where(eq(teacherAssignments.teacherId, teacherId))
 
     // Get student count for each section

+ 1 - 1
src/app/teacher/dashboard/page.tsx

@@ -79,7 +79,7 @@ async function getAssignedSections(teacherId: string): Promise<AssignedSection[]
     .from(teacherAssignments)
     .innerJoin(sections, eq(teacherAssignments.sectionId, sections.id))
     .innerJoin(classes, eq(sections.classId, classes.id))
-    .innerJoin(periods, eq(sections.periodId, periods.id))
+    .innerJoin(periods, eq(classes.periodId, periods.id))
     .where(eq(teacherAssignments.teacherId, teacherId))
 
   // Get student count for each section

+ 1 - 1
src/app/teacher/page.tsx

@@ -79,7 +79,7 @@ async function getAssignedSections(teacherId: string): Promise<AssignedSection[]
     .from(teacherAssignments)
     .innerJoin(sections, eq(teacherAssignments.sectionId, sections.id))
     .innerJoin(classes, eq(sections.classId, classes.id))
-    .innerJoin(periods, eq(sections.periodId, periods.id))
+    .innerJoin(periods, eq(classes.periodId, periods.id))
     .where(eq(teacherAssignments.teacherId, teacherId))
 
   // Get student count for each section

+ 7 - 7
src/lib/db/schema.ts

@@ -51,6 +51,7 @@ export const classes = pgTable('classes', {
   code: varchar('code', { length: 20 }).notNull().unique(),
   credits: integer('credits').notNull(),
   description: text('description'),
+  periodId: uuid('period_id').references(() => periods.id),
   isActive: boolean('is_active').default(true),
   createdAt: timestamp('created_at').defaultNow(),
   updatedAt: timestamp('updated_at').defaultNow(),
@@ -61,7 +62,6 @@ export const sections = pgTable('sections', {
   id: uuid('id').defaultRandom().primaryKey(),
   name: varchar('name', { length: 50 }).notNull(),
   classId: uuid('class_id').references(() => classes.id),
-  periodId: uuid('period_id').references(() => periods.id),
   maxStudents: integer('max_students').notNull(),
   isActive: boolean('is_active').default(true),
   createdAt: timestamp('created_at').defaultNow(),
@@ -112,7 +112,7 @@ export const usersRelations = relations(users, ({ many }) => ({
 
 export const periodsRelations = relations(periods, ({ many }) => ({
   partials: many(partials),
-  classes: many(classes),
+  sections: many(sections),
 }));
 
 export const partialsRelations = relations(partials, ({ one }) => ({
@@ -122,7 +122,11 @@ export const partialsRelations = relations(partials, ({ one }) => ({
   }),
 }));
 
-export const classesRelations = relations(classes, ({ many }) => ({
+export const classesRelations = relations(classes, ({ one, many }) => ({
+  period: one(periods, {
+    fields: [classes.periodId],
+    references: [periods.id],
+  }),
   sections: many(sections),
   teacherAssignments: many(teacherAssignments),
   studentEnrollments: many(studentEnrollments),
@@ -134,10 +138,6 @@ export const sectionsRelations = relations(sections, ({ one, many }) => ({
     fields: [sections.classId],
     references: [classes.id],
   }),
-  period: one(periods, {
-    fields: [sections.periodId],
-    references: [periods.id],
-  }),
   teacherAssignments: many(teacherAssignments),
   studentEnrollments: many(studentEnrollments),
   attendance: many(attendance),

+ 0 - 3
src/lib/db/seed.ts

@@ -60,21 +60,18 @@ export async function seedDatabase() {
     const [section1A] = await db.insert(sections).values({
       name: 'A',
       classId: class1.id,
-      periodId: period.id,
       maxStudents: 30,
     }).returning();
 
     const [section1B] = await db.insert(sections).values({
       name: 'B',
       classId: class1.id,
-      periodId: period.id,
       maxStudents: 25,
     }).returning();
 
     const [section2A] = await db.insert(sections).values({
       name: 'A',
       classId: class2.id,
-      periodId: period.id,
       maxStudents: 35,
     }).returning();