schema.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { pgTable, text, timestamp, integer, boolean, uuid, varchar, date } from 'drizzle-orm/pg-core';
  2. import { relations } from 'drizzle-orm';
  3. import { eq, and, ne } from 'drizzle-orm';
  4. // Re-export drizzle operators for convenience
  5. export { eq, and, ne };
  6. // Tabla de usuarios (administradores, docentes, estudiantes)
  7. export const users = pgTable('users', {
  8. id: uuid('id').defaultRandom().primaryKey(),
  9. email: varchar('email', { length: 255 }).notNull().unique(),
  10. password: text('password').notNull(),
  11. firstName: varchar('first_name', { length: 100 }).notNull(),
  12. lastName: varchar('last_name', { length: 100 }).notNull(),
  13. cedula: varchar('cedula', { length: 20 }).notNull().unique(),
  14. phone: varchar('phone', { length: 20 }),
  15. role: varchar('role', { length: 20 }).notNull(), // 'admin', 'teacher', 'student'
  16. admissionNumber: varchar('admission_number', { length: 50 }), // Solo para estudiantes
  17. isActive: boolean('is_active').default(true),
  18. createdAt: timestamp('created_at').defaultNow(),
  19. updatedAt: timestamp('updated_at').defaultNow(),
  20. });
  21. // Tabla de periodos
  22. export const periods = pgTable('periods', {
  23. id: uuid('id').defaultRandom().primaryKey(),
  24. name: varchar('name', { length: 100 }).notNull(),
  25. startDate: date('start_date').notNull(),
  26. endDate: date('end_date').notNull(),
  27. isActive: boolean('is_active').default(true),
  28. createdAt: timestamp('created_at').defaultNow(),
  29. updatedAt: timestamp('updated_at').defaultNow(),
  30. });
  31. // Tabla de parciales
  32. export const partials = pgTable('partials', {
  33. id: uuid('id').defaultRandom().primaryKey(),
  34. name: varchar('name', { length: 100 }).notNull(),
  35. periodId: uuid('period_id').references(() => periods.id),
  36. startDate: date('start_date').notNull(),
  37. endDate: date('end_date').notNull(),
  38. isActive: boolean('is_active').default(true),
  39. createdAt: timestamp('created_at').defaultNow(),
  40. updatedAt: timestamp('updated_at').defaultNow(),
  41. });
  42. // Tabla de clases/materias
  43. export const classes = pgTable('classes', {
  44. id: uuid('id').defaultRandom().primaryKey(),
  45. name: varchar('name', { length: 100 }).notNull(),
  46. code: varchar('code', { length: 20 }).notNull().unique(),
  47. credits: integer('credits').notNull(),
  48. description: text('description'),
  49. periodId: uuid('period_id').references(() => periods.id),
  50. isActive: boolean('is_active').default(true),
  51. createdAt: timestamp('created_at').defaultNow(),
  52. updatedAt: timestamp('updated_at').defaultNow(),
  53. });
  54. // Tabla de paralelos/secciones
  55. export const sections = pgTable('sections', {
  56. id: uuid('id').defaultRandom().primaryKey(),
  57. name: varchar('name', { length: 50 }).notNull(),
  58. classId: uuid('class_id').references(() => classes.id),
  59. maxStudents: integer('max_students').notNull(),
  60. isActive: boolean('is_active').default(true),
  61. createdAt: timestamp('created_at').defaultNow(),
  62. updatedAt: timestamp('updated_at').defaultNow(),
  63. });
  64. // Tabla de asignaciones de docentes a clases/secciones
  65. export const teacherAssignments = pgTable('teacher_assignments', {
  66. id: uuid('id').defaultRandom().primaryKey(),
  67. teacherId: uuid('teacher_id').references(() => users.id),
  68. classId: uuid('class_id').references(() => classes.id),
  69. sectionId: uuid('section_id').references(() => sections.id),
  70. isActive: boolean('is_active').default(true),
  71. createdAt: timestamp('created_at').defaultNow(),
  72. });
  73. // Tabla de inscripciones de estudiantes
  74. export const studentEnrollments = pgTable('student_enrollments', {
  75. id: uuid('id').defaultRandom().primaryKey(),
  76. studentId: uuid('student_id').references(() => users.id),
  77. classId: uuid('class_id').references(() => classes.id),
  78. sectionId: uuid('section_id').references(() => sections.id),
  79. isActive: boolean('is_active').default(true),
  80. createdAt: timestamp('created_at').defaultNow(),
  81. });
  82. // Tabla de asistencia
  83. export const attendance = pgTable('attendance', {
  84. id: uuid('id').defaultRandom().primaryKey(),
  85. studentId: uuid('student_id').references(() => users.id),
  86. classId: uuid('class_id').references(() => classes.id),
  87. sectionId: uuid('section_id').references(() => sections.id),
  88. teacherId: uuid('teacher_id').references(() => users.id),
  89. partialId: uuid('partial_id').references(() => partials.id),
  90. date: date('date').notNull(),
  91. status: varchar('status', { length: 20 }).notNull(), // 'present', 'absent', 'justified'
  92. reason: text('reason'), // Motivo de falta o justificación
  93. createdAt: timestamp('created_at').defaultNow(),
  94. });
  95. // Relaciones
  96. export const usersRelations = relations(users, ({ many }) => ({
  97. teacherAssignments: many(teacherAssignments),
  98. studentEnrollments: many(studentEnrollments),
  99. attendanceAsStudent: many(attendance, { relationName: 'studentAttendance' }),
  100. attendanceAsTeacher: many(attendance, { relationName: 'teacherAttendance' }),
  101. }));
  102. export const periodsRelations = relations(periods, ({ many }) => ({
  103. partials: many(partials),
  104. sections: many(sections),
  105. }));
  106. export const partialsRelations = relations(partials, ({ one }) => ({
  107. period: one(periods, {
  108. fields: [partials.periodId],
  109. references: [periods.id],
  110. }),
  111. }));
  112. export const classesRelations = relations(classes, ({ one, many }) => ({
  113. period: one(periods, {
  114. fields: [classes.periodId],
  115. references: [periods.id],
  116. }),
  117. sections: many(sections),
  118. teacherAssignments: many(teacherAssignments),
  119. studentEnrollments: many(studentEnrollments),
  120. attendance: many(attendance),
  121. }));
  122. export const sectionsRelations = relations(sections, ({ one, many }) => ({
  123. class: one(classes, {
  124. fields: [sections.classId],
  125. references: [classes.id],
  126. }),
  127. teacherAssignments: many(teacherAssignments),
  128. studentEnrollments: many(studentEnrollments),
  129. attendance: many(attendance),
  130. }));
  131. export const teacherAssignmentsRelations = relations(teacherAssignments, ({ one }) => ({
  132. teacher: one(users, {
  133. fields: [teacherAssignments.teacherId],
  134. references: [users.id],
  135. }),
  136. class: one(classes, {
  137. fields: [teacherAssignments.classId],
  138. references: [classes.id],
  139. }),
  140. section: one(sections, {
  141. fields: [teacherAssignments.sectionId],
  142. references: [sections.id],
  143. }),
  144. }));
  145. export const studentEnrollmentsRelations = relations(studentEnrollments, ({ one }) => ({
  146. student: one(users, {
  147. fields: [studentEnrollments.studentId],
  148. references: [users.id],
  149. }),
  150. class: one(classes, {
  151. fields: [studentEnrollments.classId],
  152. references: [classes.id],
  153. }),
  154. section: one(sections, {
  155. fields: [studentEnrollments.sectionId],
  156. references: [sections.id],
  157. }),
  158. }));
  159. export const attendanceRelations = relations(attendance, ({ one }) => ({
  160. student: one(users, {
  161. fields: [attendance.studentId],
  162. references: [users.id],
  163. relationName: 'studentAttendance',
  164. }),
  165. teacher: one(users, {
  166. fields: [attendance.teacherId],
  167. references: [users.id],
  168. relationName: 'teacherAttendance',
  169. }),
  170. class: one(classes, {
  171. fields: [attendance.classId],
  172. references: [classes.id],
  173. }),
  174. section: one(sections, {
  175. fields: [attendance.sectionId],
  176. references: [sections.id],
  177. }),
  178. partial: one(partials, {
  179. fields: [attendance.partialId],
  180. references: [partials.id],
  181. }),
  182. }));