269 lines
11 KiB
C#
269 lines
11 KiB
C#
using line_gestao_api.Models;
|
|
using line_gestao_api.Services;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace line_gestao_api.Data;
|
|
|
|
public class AppDbContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>
|
|
{
|
|
private readonly ITenantProvider _tenantProvider;
|
|
|
|
public AppDbContext(DbContextOptions<AppDbContext> options, ITenantProvider tenantProvider) : base(options)
|
|
{
|
|
_tenantProvider = tenantProvider;
|
|
}
|
|
|
|
public DbSet<Tenant> Tenants => Set<Tenant>();
|
|
|
|
// ✅ tabela para espelhar a planilha (GERAL)
|
|
public DbSet<MobileLine> MobileLines => Set<MobileLine>();
|
|
|
|
// ✅ tabela para espelhar a aba MUREG
|
|
public DbSet<MuregLine> MuregLines => Set<MuregLine>();
|
|
|
|
// ✅ tabela para espelhar o FATURAMENTO (PF/PJ)
|
|
public DbSet<BillingClient> BillingClients => Set<BillingClient>();
|
|
|
|
// ✅ tabela DADOS DOS USUÁRIOS
|
|
public DbSet<UserData> UserDatas => Set<UserData>();
|
|
|
|
// ✅ tabela VIGÊNCIA
|
|
public DbSet<VigenciaLine> VigenciaLines => Set<VigenciaLine>();
|
|
|
|
// ✅ tabela TROCA DE NÚMERO
|
|
public DbSet<TrocaNumeroLine> TrocaNumeroLines => Set<TrocaNumeroLine>();
|
|
|
|
// ✅ tabela CHIPS VIRGENS
|
|
public DbSet<ChipVirgemLine> ChipVirgemLines => Set<ChipVirgemLine>();
|
|
|
|
// ✅ tabela CONTROLE DE RECEBIDOS
|
|
public DbSet<ControleRecebidoLine> ControleRecebidoLines => Set<ControleRecebidoLine>();
|
|
|
|
// ✅ tabela NOTIFICAÇÕES
|
|
public DbSet<Notification> Notifications => Set<Notification>();
|
|
|
|
// ✅ tabela RESUMO
|
|
public DbSet<ResumoMacrophonyPlan> ResumoMacrophonyPlans => Set<ResumoMacrophonyPlan>();
|
|
public DbSet<ResumoMacrophonyTotal> ResumoMacrophonyTotals => Set<ResumoMacrophonyTotal>();
|
|
public DbSet<ResumoVivoLineResumo> ResumoVivoLineResumos => Set<ResumoVivoLineResumo>();
|
|
public DbSet<ResumoVivoLineTotal> ResumoVivoLineTotals => Set<ResumoVivoLineTotal>();
|
|
public DbSet<ResumoClienteEspecial> ResumoClienteEspeciais => Set<ResumoClienteEspecial>();
|
|
public DbSet<ResumoPlanoContratoResumo> ResumoPlanoContratoResumos => Set<ResumoPlanoContratoResumo>();
|
|
public DbSet<ResumoPlanoContratoTotal> ResumoPlanoContratoTotals => Set<ResumoPlanoContratoTotal>();
|
|
public DbSet<ResumoLineTotais> ResumoLineTotais => Set<ResumoLineTotais>();
|
|
public DbSet<ResumoReservaLine> ResumoReservaLines => Set<ResumoReservaLine>();
|
|
public DbSet<ResumoReservaTotal> ResumoReservaTotals => Set<ResumoReservaTotal>();
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
// =========================
|
|
// ✅ USER (Identity)
|
|
// =========================
|
|
modelBuilder.Entity<ApplicationUser>(e =>
|
|
{
|
|
e.Property(x => x.Name).HasMaxLength(120);
|
|
e.HasIndex(x => new { x.TenantId, x.NormalizedEmail })
|
|
.IsUnique();
|
|
});
|
|
|
|
// =========================
|
|
// ✅ GERAL (MobileLine)
|
|
// =========================
|
|
modelBuilder.Entity<MobileLine>(e =>
|
|
{
|
|
// Mantém UNIQUE por Linha por tenant (se Linha puder ser null no banco, Postgres aceita múltiplos nulls)
|
|
e.HasIndex(x => new { x.TenantId, x.Linha }).IsUnique();
|
|
|
|
// performance
|
|
e.HasIndex(x => x.Chip);
|
|
e.HasIndex(x => x.Cliente);
|
|
e.HasIndex(x => x.Usuario);
|
|
e.HasIndex(x => x.Skil);
|
|
e.HasIndex(x => x.Status);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ MUREG (FK para MobileLines)
|
|
// =========================
|
|
modelBuilder.Entity<MuregLine>(e =>
|
|
{
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.ICCID);
|
|
e.HasIndex(x => x.LinhaAntiga);
|
|
e.HasIndex(x => x.LinhaNova);
|
|
e.HasIndex(x => x.TenantId);
|
|
|
|
// FK + index
|
|
e.HasIndex(x => x.MobileLineId);
|
|
|
|
e.HasOne(x => x.MobileLine)
|
|
.WithMany(m => m.Muregs)
|
|
.HasForeignKey(x => x.MobileLineId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ FATURAMENTO (BillingClient)
|
|
// =========================
|
|
modelBuilder.Entity<BillingClient>(e =>
|
|
{
|
|
// ⚠️ só mantenha se seu banco realmente usa esse nome
|
|
e.ToTable("billing_clients");
|
|
|
|
e.HasKey(x => x.Id);
|
|
|
|
e.Property(x => x.Tipo).HasMaxLength(2);
|
|
e.Property(x => x.Cliente).HasMaxLength(255);
|
|
|
|
e.HasIndex(x => x.Tipo);
|
|
e.HasIndex(x => x.Cliente);
|
|
e.HasIndex(x => new { x.Tipo, x.Cliente });
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ DADOS DOS USUÁRIOS (UserData)
|
|
// ✅ (SEM "Nome" pq não existe no model)
|
|
// =========================
|
|
modelBuilder.Entity<UserData>(e =>
|
|
{
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.Cliente);
|
|
e.HasIndex(x => x.Linha);
|
|
e.HasIndex(x => x.Cpf);
|
|
e.HasIndex(x => x.Email);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ VIGÊNCIA
|
|
// =========================
|
|
modelBuilder.Entity<VigenciaLine>(e =>
|
|
{
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.Cliente);
|
|
e.HasIndex(x => x.Linha);
|
|
e.HasIndex(x => x.DtTerminoFidelizacao);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ TROCA NÚMERO
|
|
// =========================
|
|
modelBuilder.Entity<TrocaNumeroLine>(e =>
|
|
{
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.LinhaAntiga);
|
|
e.HasIndex(x => x.LinhaNova);
|
|
e.HasIndex(x => x.ICCID);
|
|
e.HasIndex(x => x.DataTroca);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ CHIPS VIRGENS
|
|
// =========================
|
|
modelBuilder.Entity<ChipVirgemLine>(e =>
|
|
{
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.NumeroDoChip);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ CONTROLE DE RECEBIDOS
|
|
// =========================
|
|
modelBuilder.Entity<ControleRecebidoLine>(e =>
|
|
{
|
|
e.HasIndex(x => x.Ano);
|
|
e.HasIndex(x => x.Item);
|
|
e.HasIndex(x => x.NotaFiscal);
|
|
e.HasIndex(x => x.Chip);
|
|
e.HasIndex(x => x.Serial);
|
|
e.HasIndex(x => x.NumeroDaLinha);
|
|
e.HasIndex(x => x.DataDaNf);
|
|
e.HasIndex(x => x.DataDoRecebimento);
|
|
e.HasIndex(x => x.TenantId);
|
|
});
|
|
|
|
// =========================
|
|
// ✅ NOTIFICAÇÕES
|
|
// =========================
|
|
modelBuilder.Entity<Notification>(e =>
|
|
{
|
|
e.HasIndex(x => x.DedupKey).IsUnique();
|
|
e.HasIndex(x => x.UserId);
|
|
e.HasIndex(x => x.Cliente);
|
|
e.HasIndex(x => x.Lida);
|
|
e.HasIndex(x => x.Data);
|
|
e.HasIndex(x => x.VigenciaLineId);
|
|
e.HasIndex(x => x.TenantId);
|
|
|
|
e.HasOne(x => x.User)
|
|
.WithMany()
|
|
.HasForeignKey(x => x.UserId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
e.HasOne(x => x.VigenciaLine)
|
|
.WithMany()
|
|
.HasForeignKey(x => x.VigenciaLineId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
});
|
|
|
|
modelBuilder.Entity<MobileLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<MuregLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<BillingClient>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<UserData>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<VigenciaLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<TrocaNumeroLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ChipVirgemLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ControleRecebidoLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<Notification>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoMacrophonyPlan>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoMacrophonyTotal>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoVivoLineResumo>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoVivoLineTotal>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoClienteEspecial>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoPlanoContratoResumo>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoPlanoContratoTotal>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoLineTotais>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoReservaLine>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ResumoReservaTotal>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
modelBuilder.Entity<ApplicationUser>().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId);
|
|
}
|
|
|
|
public override int SaveChanges()
|
|
{
|
|
ApplyTenantIds();
|
|
return base.SaveChanges();
|
|
}
|
|
|
|
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
ApplyTenantIds();
|
|
return base.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
private void ApplyTenantIds()
|
|
{
|
|
if (_tenantProvider.TenantId == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var tenantId = _tenantProvider.TenantId.Value;
|
|
foreach (var entry in ChangeTracker.Entries<ITenantEntity>().Where(e => e.State == EntityState.Added))
|
|
{
|
|
if (entry.Entity.TenantId == Guid.Empty)
|
|
{
|
|
entry.Entity.TenantId = tenantId;
|
|
}
|
|
}
|
|
}
|
|
}
|