194 lines
7.1 KiB
C#
194 lines
7.1 KiB
C#
using Indotalent.ConfigBackEnd.Extensions;
|
|
using Indotalent.ConfigBackEnd.Interfaces;
|
|
using Indotalent.Data.Abstracts;
|
|
using Indotalent.Data.Entities;
|
|
using Indotalent.Data.Interfaces;
|
|
using Indotalent.Infrastructure.AutoNumberGenerator;
|
|
using Indotalent.Shared.Consts;
|
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Indotalent.Infrastructure.Database;
|
|
|
|
public class AppDbContext : IdentityDbContext<ApplicationUser>
|
|
{
|
|
private readonly IServiceScopeFactory _scopeFactory;
|
|
private readonly ICurrentUserService _currentUserService;
|
|
|
|
public AppDbContext(
|
|
DbContextOptions<AppDbContext> options,
|
|
IServiceScopeFactory scopeFactory,
|
|
ICurrentUserService currentUserService) : base(options)
|
|
{
|
|
_scopeFactory = scopeFactory;
|
|
_currentUserService = currentUserService;
|
|
}
|
|
|
|
public DbSet<AutoNumberSequence> AutoNumberSequence { get; set; } = default!;
|
|
public DbSet<Currency> Currency { get; set; } = default!;
|
|
public DbSet<Company> Company { get; set; } = default!;
|
|
public DbSet<Tax> Tax { get; set; } = default!;
|
|
public DbSet<Branch> Branch { get; set; } = default!;
|
|
public DbSet<Department> Department { get; set; } = default!;
|
|
public DbSet<Designation> Designation { get; set; } = default!;
|
|
public DbSet<Employee> Employee { get; set; } = default!;
|
|
public DbSet<LeaveCategory> LeaveCategory { get; set; } = default!;
|
|
public DbSet<LeaveRequest> LeaveRequest { get; set; } = default!;
|
|
public DbSet<LeaveBalance> LeaveBalance { get; set; } = default!;
|
|
public DbSet<Evaluation> Evaluation { get; set; } = default!;
|
|
public DbSet<Appraisal> Appraisal { get; set; } = default!;
|
|
public DbSet<Promotion> Promotion { get; set; } = default!;
|
|
public DbSet<Transfer> Transfer { get; set; } = default!;
|
|
public DbSet<Income> Income { get; set; } = default!;
|
|
public DbSet<Deduction> Deduction { get; set; } = default!;
|
|
public DbSet<Grade> Grade { get; set; } = default!;
|
|
public DbSet<EmployeeIncome> EmployeeIncome { get; set; } = default!;
|
|
public DbSet<EmployeeDeduction> EmployeeDeduction { get; set; } = default!;
|
|
public DbSet<PayrollProcess> PayrollProcess { get; set; } = default!;
|
|
public DbSet<PayrollDetail> PayrollDetail { get; set; } = default!;
|
|
public DbSet<PayrollComponent> PayrollComponent { get; set; } = default!;
|
|
|
|
public override int SaveChanges()
|
|
{
|
|
ApplySoftDelete();
|
|
ApplyAudit(_currentUserService.UserId ?? string.Empty);
|
|
return base.SaveChanges();
|
|
}
|
|
|
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
ChangeTracker.DetectChanges();
|
|
ApplySoftDelete();
|
|
ApplyAudit(_currentUserService.UserId ?? string.Empty);
|
|
await ApplyAutoNumber(cancellationToken);
|
|
return await base.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
private void ApplySoftDelete()
|
|
{
|
|
var entries = ChangeTracker.Entries<IHasIsDeleted>()
|
|
.Where(e => e.State == EntityState.Deleted);
|
|
|
|
foreach (var entry in entries)
|
|
{
|
|
entry.State = EntityState.Modified;
|
|
entry.Entity.IsDeleted = true;
|
|
}
|
|
}
|
|
|
|
private void ApplyAudit(string userId)
|
|
{
|
|
var entries = ChangeTracker.Entries<IHasAudit>()
|
|
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
|
|
.ToList();
|
|
|
|
foreach (var entry in entries)
|
|
{
|
|
var now = DateTimeOffset.UtcNow;
|
|
var auditEntity = entry.Entity;
|
|
|
|
if (entry.State == EntityState.Added)
|
|
{
|
|
auditEntity.CreatedAt = now;
|
|
auditEntity.CreatedBy = userId;
|
|
}
|
|
else
|
|
{
|
|
entry.Property(nameof(IHasAudit.CreatedAt)).IsModified = false;
|
|
entry.Property(nameof(IHasAudit.CreatedBy)).IsModified = false;
|
|
}
|
|
|
|
auditEntity.UpdatedAt = now;
|
|
auditEntity.UpdatedBy = userId;
|
|
}
|
|
}
|
|
|
|
private async Task ApplyAutoNumber(CancellationToken ct)
|
|
{
|
|
var entries = ChangeTracker
|
|
.Entries<IHasAutoNumber>()
|
|
.Where(e => e.State == EntityState.Added && string.IsNullOrEmpty(e.Entity.AutoNumber))
|
|
.ToList();
|
|
|
|
if (!entries.Any()) return;
|
|
|
|
using var scope = _scopeFactory.CreateScope();
|
|
var generator = scope.ServiceProvider.GetRequiredService<AutoNumberGeneratorService>();
|
|
|
|
foreach (var entry in entries)
|
|
{
|
|
var entityName = entry.Entity.GetType().Name;
|
|
var shortName = entityName.ToShortNameConsonant(3);
|
|
|
|
entry.Entity.AutoNumber = await generator.GenerateNextNumberAsync(
|
|
entityName: entityName,
|
|
prefixTemplate: $"{shortName}/{{Year}}/",
|
|
paddingLength: 4,
|
|
cancellationToken: ct
|
|
);
|
|
}
|
|
}
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
if (Database.ProviderName?.Contains("MySql") == true)
|
|
{
|
|
foreach (var entity in modelBuilder.Model.GetEntityTypes())
|
|
{
|
|
if (entity.GetTableName()!.StartsWith("AspNet"))
|
|
{
|
|
foreach (var property in entity.GetProperties().Where(p => p.ClrType == typeof(string)))
|
|
{
|
|
property.SetMaxLength(191);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
|
{
|
|
var type = entityType.ClrType;
|
|
|
|
if (typeof(BaseEntity).IsAssignableFrom(type))
|
|
{
|
|
modelBuilder.Entity(type)
|
|
.Property("Id")
|
|
.HasMaxLength(GlobalConsts.StringLengthId)
|
|
.IsFixedLength();
|
|
}
|
|
|
|
if (typeof(IHasAudit).IsAssignableFrom(type))
|
|
{
|
|
modelBuilder.Entity(type)
|
|
.Property(nameof(IHasAudit.CreatedBy))
|
|
.HasMaxLength(GlobalConsts.StringLengthShort);
|
|
|
|
modelBuilder.Entity(type)
|
|
.Property(nameof(IHasAudit.UpdatedBy))
|
|
.HasMaxLength(GlobalConsts.StringLengthShort);
|
|
}
|
|
|
|
if (typeof(IHasIsDeleted).IsAssignableFrom(type))
|
|
{
|
|
modelBuilder.Entity(type).HasQueryFilter(GetNotDeletedOnlyFilter(type));
|
|
}
|
|
|
|
}
|
|
|
|
modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
|
|
}
|
|
|
|
private static System.Linq.Expressions.LambdaExpression GetNotDeletedOnlyFilter(Type type)
|
|
{
|
|
var parameter = System.Linq.Expressions.Expression.Parameter(type, "e");
|
|
var property = System.Linq.Expressions.Expression.Property(parameter, nameof(IHasIsDeleted.IsDeleted));
|
|
var falseConstant = System.Linq.Expressions.Expression.Constant(false);
|
|
var comparison = System.Linq.Expressions.Expression.Equal(property, falseConstant);
|
|
return System.Linq.Expressions.Expression.Lambda(comparison, parameter);
|
|
}
|
|
}
|
|
|
|
|