using Microsoft.EntityFrameworkCore; using HelpDesk.Models.Entities; namespace HelpDesk.Data; public class HelpDeskDbContext : DbContext { public HelpDeskDbContext(DbContextOptions options) : base(options) { } public DbSet Users => Set(); public DbSet Tickets => Set(); public DbSet TicketComments => Set(); public DbSet Groups => Set(); public DbSet SLAPolicies => Set(); public DbSet KnowledgeBaseArticles => Set(); public DbSet KnowledgeBaseCategories => Set(); public DbSet ActivityLogs => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // ── User ────────────────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("users"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.FirstName).HasColumnName("first_name").HasMaxLength(100).IsRequired(); entity.Property(e => e.LastName).HasColumnName("last_name").HasMaxLength(100).IsRequired(); entity.Property(e => e.Email).HasColumnName("email").HasMaxLength(256).IsRequired(); entity.Property(e => e.PasswordHash).HasColumnName("password_hash").HasMaxLength(500).IsRequired(); entity.Property(e => e.Role).HasColumnName("role").HasMaxLength(50).IsRequired(); entity.Property(e => e.IsActive).HasColumnName("is_active"); entity.Property(e => e.PhoneNumber).HasColumnName("phone_number").HasMaxLength(50); entity.Property(e => e.AvatarUrl).HasColumnName("avatar_url").HasMaxLength(500); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); entity.Property(e => e.UpdatedAt).HasColumnName("updated_at"); entity.HasIndex(e => e.Email).IsUnique().HasDatabaseName("ix_users_email"); }); // ── Ticket ──────────────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("tickets"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Title).HasColumnName("title").HasMaxLength(200).IsRequired(); entity.Property(e => e.Description).HasColumnName("description").IsRequired(); entity.Property(e => e.Status).HasColumnName("status").HasMaxLength(50).IsRequired(); entity.Property(e => e.Priority).HasColumnName("priority").HasMaxLength(50).IsRequired(); entity.Property(e => e.TicketNumber).HasColumnName("ticket_number").HasMaxLength(50).IsRequired(); entity.Property(e => e.RequesterId).HasColumnName("requester_id"); entity.Property(e => e.AssigneeId).HasColumnName("assignee_id"); entity.Property(e => e.GroupId).HasColumnName("group_id"); entity.Property(e => e.SlaPolicyId).HasColumnName("sla_policy_id"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); entity.Property(e => e.UpdatedAt).HasColumnName("updated_at"); entity.Property(e => e.ResolvedAt).HasColumnName("resolved_at"); entity.Property(e => e.ClosedAt).HasColumnName("closed_at"); entity.HasIndex(e => e.TicketNumber).IsUnique().HasDatabaseName("ix_tickets_ticket_number"); // Cascade delete: Ticket -> TicketComment entity.HasMany(e => e.Comments) .WithOne(c => c.Ticket) .HasForeignKey(c => c.TicketId) .OnDelete(DeleteBehavior.Cascade); // Restrict: User FK references (Requester) entity.HasOne(e => e.Requester) .WithMany(u => u.RequestedTickets) .HasForeignKey(e => e.RequesterId) .OnDelete(DeleteBehavior.Restrict); // Restrict: User FK references (Assignee) entity.HasOne(e => e.Assignee) .WithMany(u => u.AssignedTickets) .HasForeignKey(e => e.AssigneeId) .OnDelete(DeleteBehavior.Restrict); entity.HasOne(e => e.Group) .WithMany(g => g.Tickets) .HasForeignKey(e => e.GroupId) .OnDelete(DeleteBehavior.SetNull); entity.HasOne(e => e.SlaPolicy) .WithMany(s => s.Tickets) .HasForeignKey(e => e.SlaPolicyId) .OnDelete(DeleteBehavior.SetNull); }); // ── TicketComment ───────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("ticket_comments"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.TicketId).HasColumnName("ticket_id"); entity.Property(e => e.UserId).HasColumnName("user_id"); entity.Property(e => e.Content).HasColumnName("content").IsRequired(); entity.Property(e => e.IsInternal).HasColumnName("is_internal"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); // Restrict: User FK reference entity.HasOne(e => e.User) .WithMany(u => u.Comments) .HasForeignKey(e => e.UserId) .OnDelete(DeleteBehavior.Restrict); }); // ── Group ───────────────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("groups"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Name).HasColumnName("name").HasMaxLength(100).IsRequired(); entity.Property(e => e.Description).HasColumnName("description").HasMaxLength(500); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); }); // ── SLAPolicy ───────────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("sla_policies"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Name).HasColumnName("name").HasMaxLength(100).IsRequired(); entity.Property(e => e.Description).HasColumnName("description").HasMaxLength(500); entity.Property(e => e.ResponseTimeHours).HasColumnName("response_time_hours"); entity.Property(e => e.ResolutionTimeHours).HasColumnName("resolution_time_hours"); entity.Property(e => e.IsActive).HasColumnName("is_active"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); }); // ── KnowledgeBaseArticle ────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("knowledge_base_articles"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Title).HasColumnName("title").HasMaxLength(200).IsRequired(); entity.Property(e => e.Content).HasColumnName("content").IsRequired(); entity.Property(e => e.CategoryId).HasColumnName("category_id"); entity.Property(e => e.AuthorId).HasColumnName("author_id"); entity.Property(e => e.IsPublished).HasColumnName("is_published"); entity.Property(e => e.ViewCount).HasColumnName("view_count"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); entity.Property(e => e.UpdatedAt).HasColumnName("updated_at"); entity.HasOne(e => e.Category) .WithMany(c => c.Articles) .HasForeignKey(e => e.CategoryId) .OnDelete(DeleteBehavior.Restrict); entity.HasOne(e => e.Author) .WithMany(u => u.Articles) .HasForeignKey(e => e.AuthorId) .OnDelete(DeleteBehavior.Restrict); }); // ── KnowledgeBaseCategory ───────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("knowledge_base_categories"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Name).HasColumnName("name").HasMaxLength(100).IsRequired(); entity.Property(e => e.Description).HasColumnName("description").HasMaxLength(500); entity.Property(e => e.SortOrder).HasColumnName("sort_order"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); }); // ── ActivityLog ─────────────────────────────────────── modelBuilder.Entity(entity => { entity.ToTable("activity_logs"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.UserId).HasColumnName("user_id"); entity.Property(e => e.EntityType).HasColumnName("entity_type").HasMaxLength(100).IsRequired(); entity.Property(e => e.EntityId).HasColumnName("entity_id"); entity.Property(e => e.Action).HasColumnName("action").HasMaxLength(100).IsRequired(); entity.Property(e => e.Details).HasColumnName("details"); entity.Property(e => e.CreatedAt).HasColumnName("created_at"); entity.HasOne(e => e.User) .WithMany(u => u.ActivityLogs) .HasForeignKey(e => e.UserId) .OnDelete(DeleteBehavior.Restrict); }); // ── Seed Data ───────────────────────────────────────── SeedData(modelBuilder); } private static void SeedData(ModelBuilder modelBuilder) { var adminId = Guid.Parse("a0000000-0000-0000-0000-000000000001"); var generalGroupId = Guid.Parse("b0000000-0000-0000-0000-000000000001"); var ventasGroupId = Guid.Parse("b0000000-0000-0000-0000-000000000002"); var desarrolloGroupId = Guid.Parse("b0000000-0000-0000-0000-000000000003"); var standardSlaId = Guid.Parse("c0000000-0000-0000-0000-000000000001"); var premiumSlaId = Guid.Parse("c0000000-0000-0000-0000-000000000002"); var generalCategoryId = Guid.Parse("d0000000-0000-0000-0000-000000000001"); var faqCategoryId = Guid.Parse("d0000000-0000-0000-0000-000000000002"); var tutorialsCategoryId = Guid.Parse("d0000000-0000-0000-0000-000000000003"); // SuperAdmin user modelBuilder.Entity().HasData(new User { Id = adminId, FirstName = "Super", LastName = "Admin", Email = "admin@helpdesk.local", // BCrypt hash for "Admin123!" PasswordHash = "$2a$11$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy", Role = HelpDesk.Models.Enums.UserRole.SuperAdmin, IsActive = true, PhoneNumber = "+1-555-0100", CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc), UpdatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }); // Default groups modelBuilder.Entity().HasData( new Group { Id = generalGroupId, Name = "Soporte General", Description = "Grupo de soporte técnico general", CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }, new Group { Id = ventasGroupId, Name = "Ventas", Description = "Grupo de soporte de ventas", CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }, new Group { Id = desarrolloGroupId, Name = "Desarrollo", Description = "Grupo de desarrollo de software", CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) } ); // SLA policies modelBuilder.Entity().HasData( new SLAPolicy { Id = standardSlaId, Name = "Estándar", Description = "Política estándar: respuesta en 4 horas, resolución en 24 horas", ResponseTimeHours = 4, ResolutionTimeHours = 24, IsActive = true, CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }, new SLAPolicy { Id = premiumSlaId, Name = "Premium", Description = "Política premium: respuesta en 1 hora, resolución en 8 horas", ResponseTimeHours = 1, ResolutionTimeHours = 8, IsActive = true, CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) } ); // Knowledge base categories modelBuilder.Entity().HasData( new KnowledgeBaseCategory { Id = generalCategoryId, Name = "General", Description = "Artículos generales de ayuda", SortOrder = 1, CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }, new KnowledgeBaseCategory { Id = faqCategoryId, Name = "Preguntas Frecuentes", Description = "Preguntas frecuentes y respuestas", SortOrder = 2, CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) }, new KnowledgeBaseCategory { Id = tutorialsCategoryId, Name = "Tutoriales", Description = "Guías y tutoriales paso a paso", SortOrder = 3, CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) } ); } }