initial commit

This commit is contained in:
2026-07-21 13:52:43 +07:00
commit f0e6f38940
881 changed files with 66309 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Firebase;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Infrastructure.Authentication.Keycloak;
using Indotalent.Infrastructure.Database;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;
namespace Indotalent.Infrastructure.Authentication;
public static class DI
{
public static IServiceCollection AddAuthenticationService(this IServiceCollection services, IConfiguration configuration)
{
//Identity
services.AddScoped<IdentityService>();
services.AddHttpContextAccessor();
services.AddCascadingAuthenticationState();
services.Configure<JwtSettingsModel>(configuration.GetSection("JwtSettings"));
services.AddScoped<TokenProvider>();
var identitySettings = configuration.GetSection("IdentitySettings").Get<IdentitySettingsModel>() ?? new IdentitySettingsModel();
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireDigit = identitySettings.Password.RequireDigit;
options.Password.RequiredLength = identitySettings.Password.RequiredLength;
options.Password.RequireNonAlphanumeric = identitySettings.Password.RequireNonAlphanumeric;
options.Password.RequireUppercase = identitySettings.Password.RequireUppercase;
options.Password.RequireLowercase = identitySettings.Password.RequireLowercase;
options.SignIn.RequireConfirmedAccount = identitySettings.SignIn.RequireConfirmedAccount;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders()
.AddClaimsPrincipalFactory<CustomClaimsPrincipalFactory>();
services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ApplicationScheme;
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
var jwtSettings = configuration.GetSection("JwtSettings").Get<JwtSettingsModel>();
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings?.Issuer,
ValidAudience = jwtSettings?.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings?.Key ?? "PRAGMATIC_FIX_KEY_MIN_32_CHARS_LONG_2026"))
};
});
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = identitySettings.Cookies.LoginPath;
options.LogoutPath = identitySettings.Cookies.LogoutPath;
options.AccessDeniedPath = identitySettings.Cookies.AccessDeniedPath;
options.Cookie.Name = identitySettings.Cookies.Name;
options.ExpireTimeSpan = TimeSpan.FromDays(identitySettings.Cookies.ExpireDays);
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
});
//Firebase
services.AddScoped<FirebaseService>();
//Keycloak
services.AddScoped<KeycloakService>();
return services;
}
}
@@ -0,0 +1,13 @@
using Indotalent.Infrastructure.Authentication.Identity;
using Microsoft.Extensions.Options;
namespace Indotalent.Infrastructure.Authentication.Firebase;
public class FirebaseService(IOptions<IdentitySettingsModel> options)
{
private readonly IdentitySettingsModel _settings = options.Value;
public IdentitySettingsModel GetConfiguration() => _settings;
public FirebaseSettingsModel GetDefaultAdmin() => _settings.SsoFirebase;
}
@@ -0,0 +1,13 @@
namespace Indotalent.Infrastructure.Authentication.Firebase;
public class FirebaseSettingsModel
{
public bool IsUsed { get; set; }
public bool OpenForPublic { get; set; }
public string ApiKey { get; set; } = string.Empty;
public string AuthDomain { get; set; } = string.Empty;
public string ProjectId { get; set; } = string.Empty;
public string StorageBucket { get; set; } = string.Empty;
public string MessagingSenderId { get; set; } = string.Empty;
public string AppId { get; set; } = string.Empty;
}
@@ -0,0 +1,10 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class CookieSettings
{
public string Name { get; set; } = string.Empty;
public string LoginPath { get; set; } = string.Empty;
public string LogoutPath { get; set; } = string.Empty;
public string AccessDeniedPath { get; set; } = string.Empty;
public int ExpireDays { get; set; }
}
@@ -0,0 +1,26 @@
using Indotalent.Data.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Security.Claims;
namespace Indotalent.Infrastructure.Authentication.Identity;
public class CustomClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
{
public CustomClaimsPrincipalFactory(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{
}
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
var identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FullName ?? string.Empty));
return identity;
}
}
@@ -0,0 +1,8 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class DefaultAdminSettings
{
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string FullName { get; set; } = string.Empty;
}
@@ -0,0 +1,16 @@
using Indotalent.Data.Entities;
namespace Indotalent.Infrastructure.Authentication.Identity;
public static class DefaultUserConfig
{
public static ApplicationUser GetAdminUser(DefaultAdminSettings settings) => new()
{
FullName = settings.FullName,
UserName = settings.Email,
Email = settings.Email,
EmailConfirmed = true,
CreatedAt = DateTime.Now,
IsActive = true
};
}
@@ -0,0 +1,56 @@
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Identity;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
internal sealed class IdentityRevalidatingAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly TokenProvider _tokenProvider;
public IdentityRevalidatingAuthenticationStateProvider(
ILoggerFactory loggerFactory,
IServiceScopeFactory scopeFactory,
IHttpContextAccessor httpContextAccessor,
TokenProvider tokenProvider)
: base(loggerFactory)
{
_scopeFactory = scopeFactory;
_httpContextAccessor = httpContextAccessor;
_tokenProvider = tokenProvider;
var context = httpContextAccessor.HttpContext;
if (context != null)
{
var token = context.Request.Cookies["X-Auth-Token"];
var refreshToken = context.Request.Cookies["X-Refresh-Token"];
if (!string.IsNullOrEmpty(token))
{
_tokenProvider.Token = token;
}
if (!string.IsNullOrEmpty(refreshToken))
{
_tokenProvider.RefreshToken = refreshToken;
}
}
}
protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);
protected override async Task<bool> ValidateAuthenticationStateAsync(
AuthenticationState authenticationState, CancellationToken cancellationToken)
{
await using var scopeAsync = _scopeFactory.CreateAsyncScope();
var userManager = scopeAsync.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
return await ValidateSecurityStampAsync(userManager, authenticationState.User);
}
private async Task<bool> ValidateSecurityStampAsync(UserManager<ApplicationUser> userManager, ClaimsPrincipal principal)
{
var user = await userManager.GetUserAsync(principal);
return user != null;
}
}
@@ -0,0 +1,24 @@
using Indotalent.Infrastructure.Authentication.Firebase;
using Indotalent.Infrastructure.Authentication.Keycloak;
using Microsoft.Extensions.Options;
namespace Indotalent.Infrastructure.Authentication.Identity;
public class IdentityService(IOptions<IdentitySettingsModel> options)
{
private readonly IdentitySettingsModel _settings = options.Value;
public IdentitySettingsModel GetConfiguration() => _settings;
public DefaultAdminSettings GetDefaultAdmin() => _settings.DefaultAdmin;
public PasswordSettings GetPasswordPolicy() => _settings.Password;
public CookieSettings GetCookieSettings() => _settings.Cookies;
public SignInSettings GetSignInSettings() => _settings.SignIn;
public FirebaseSettingsModel GetFirebaseSettings() => _settings.SsoFirebase;
public KeycloakSettingsModel GetKeycloakSettings() => _settings.SsoKeycloak;
}
@@ -0,0 +1,14 @@
using Indotalent.Infrastructure.Authentication.Firebase;
using Indotalent.Infrastructure.Authentication.Keycloak;
namespace Indotalent.Infrastructure.Authentication.Identity;
public class IdentitySettingsModel
{
public PasswordSettings Password { get; set; } = new();
public CookieSettings Cookies { get; set; } = new();
public DefaultAdminSettings DefaultAdmin { get; set; } = new();
public SignInSettings SignIn { get; set; } = new();
public FirebaseSettingsModel SsoFirebase { get; set; } = new();
public KeycloakSettingsModel SsoKeycloak { get; set; } = new();
}
@@ -0,0 +1,9 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class JwtSettingsModel
{
public string Key { get; set; } = string.Empty;
public string Issuer { get; set; } = string.Empty;
public string Audience { get; set; } = string.Empty;
public int DurationInMinutes { get; set; }
}
@@ -0,0 +1,11 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class PasswordSettings
{
public bool RequireDigit { get; set; }
public int RequiredLength { get; set; }
public bool RequireNonAlphanumeric { get; set; }
public bool RequireUppercase { get; set; }
public bool RequireLowercase { get; set; }
public int RequiredUniqueChars { get; set; }
}
@@ -0,0 +1,6 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class SignInSettings
{
public bool RequireConfirmedAccount { get; set; }
}
@@ -0,0 +1,7 @@
namespace Indotalent.Infrastructure.Authentication.Identity;
public class TokenProvider
{
public string? Token { get; set; }
public string? RefreshToken { get; set; }
}
@@ -0,0 +1,13 @@
using Indotalent.Infrastructure.Authentication.Identity;
using Microsoft.Extensions.Options;
namespace Indotalent.Infrastructure.Authentication.Keycloak;
public class KeycloakService(IOptions<IdentitySettingsModel> options)
{
private readonly IdentitySettingsModel _settings = options.Value;
public IdentitySettingsModel GetConfiguration() => _settings;
public KeycloakSettingsModel GetPasswordPolicy() => _settings.SsoKeycloak;
}
@@ -0,0 +1,11 @@
namespace Indotalent.Infrastructure.Authentication.Keycloak;
public class KeycloakSettingsModel
{
public bool IsUsed { get; set; }
public string Authority { get; set; } = string.Empty;
public string ClientId { get; set; } = string.Empty;
public string ClientSecret { get; set; } = string.Empty;
public string RequireHttpsMetadata { get; set; } = string.Empty;
}
@@ -0,0 +1,10 @@
namespace Indotalent.Infrastructure.Authorization.Identity;
public static class ApplicationRoles
{
public const string Admin = "Admin";
public const string Member = "Member";
public const string Guest = "Guest";
public static IReadOnlyList<string> AllRoles => new[] { Admin, Member, Guest };
}
@@ -0,0 +1,94 @@
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
using System.Collections.Concurrent;
namespace Indotalent.Infrastructure.AutoNumberGenerator;
public class AutoNumberGeneratorService
{
private readonly AppDbContext _context;
private static readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new();
public AutoNumberGeneratorService(AppDbContext context)
{
_context = context;
}
public async Task<string> GenerateNextNumberAsync(
string entityName,
string prefixTemplate,
string? suffixTemplate = null,
int paddingLength = 4,
bool useYear = true,
bool useMonth = false,
CancellationToken cancellationToken = default)
{
var now = DateTime.UtcNow;
int? year = useYear ? now.Year : null;
int? month = useMonth ? now.Month : null;
var lockKey = $"{entityName}_{year}_{month}";
var semaphore = _locks.GetOrAdd(lockKey, _ => new SemaphoreSlim(1, 1));
await semaphore.WaitAsync(cancellationToken);
try
{
var sequence = await _context.AutoNumberSequence
.FirstOrDefaultAsync(ns =>
ns.EntityName == entityName &&
ns.Year == year &&
ns.Month == month,
cancellationToken);
if (sequence == null)
{
sequence = new AutoNumberSequence
{
EntityName = entityName,
Year = year,
Month = month,
CurrentSequence = 0,
PrefixTemplate = prefixTemplate,
SuffixTemplate = suffixTemplate,
PaddingLength = paddingLength
};
_context.AutoNumberSequence.Add(sequence);
}
sequence.CurrentSequence = (sequence.CurrentSequence ?? 0) + 1;
var formattedNumber = BuildFormattedNumber(sequence, now);
await _context.SaveChangesAsync(cancellationToken);
return formattedNumber;
}
finally
{
semaphore.Release();
if (semaphore.CurrentCount == 1) _locks.TryRemove(lockKey, out _);
}
}
private string BuildFormattedNumber(AutoNumberSequence sequence, DateTime now)
{
string ProcessTemplate(string? template)
{
if (string.IsNullOrEmpty(template)) return "";
return template
.Replace("{EntityName}", sequence.EntityName)
.Replace("{Year}", now.Year.ToString())
.Replace("{Year2}", now.ToString("yy"))
.Replace("{Month}", now.Month.ToString("D2"));
}
var prefix = ProcessTemplate(sequence.PrefixTemplate);
var suffix = ProcessTemplate(sequence.SuffixTemplate);
var padding = sequence.PaddingLength ?? 4;
var paddedSequence = (sequence.CurrentSequence ?? 1).ToString($"D{padding}");
return $"{prefix}{paddedSequence}{suffix}";
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace Indotalent.Infrastructure.AutoNumberGenerator;
public static class DI
{
public static IServiceCollection AddAutoNumberGeneratorService(this IServiceCollection services)
{
services.AddScoped<AutoNumberGeneratorService>();
return services;
}
}
@@ -0,0 +1,12 @@
namespace Indotalent.Infrastructure.AutoNumberGenerator;
public interface IAutoNumberGenerator
{
string? EntityName { get; set; }
int? Year { get; set; }
int? Month { get; set; }
long? CurrentSequence { get; set; }
string? PrefixTemplate { get; set; }
string? SuffixTemplate { get; set; }
int? PaddingLength { get; set; }
}
@@ -0,0 +1,10 @@
using Microsoft.Extensions.Options;
namespace Indotalent.Infrastructure.BackgroundJob;
public class BackgroundJobService(IOptions<BackgroundJobSettingsModel> options)
{
private readonly BackgroundJobSettingsModel _settings = options.Value;
public BackgroundJobSettingsModel GetConfiguration() => _settings;
}
@@ -0,0 +1,10 @@
using Indotalent.Infrastructure.BackgroundJob.Hangfire;
using Indotalent.Infrastructure.BackgroundJob.Quartz;
namespace Indotalent.Infrastructure.BackgroundJob;
public class BackgroundJobSettingsModel
{
public HangfireSettingsModel Hangfire { get; set; } = new();
public QuartzSettingsModel Quartz { get; set; } = new();
}
+11
View File
@@ -0,0 +1,11 @@
namespace Indotalent.Infrastructure.BackgroundJob;
public static class DI
{
public static IServiceCollection AddBackgroundJobService(this IServiceCollection services)
{
services.AddScoped<BackgroundJobService>();
return services;
}
}
@@ -0,0 +1,8 @@
namespace Indotalent.Infrastructure.BackgroundJob.Hangfire;
public class HangfireSettingsModel
{
public bool IsUsed { get; set; }
public string ConnectionString { get; set; } = string.Empty;
public string DashboardPath { get; set; } = "/hangfire";
}
@@ -0,0 +1,7 @@
namespace Indotalent.Infrastructure.BackgroundJob.Quartz;
public class QuartzSettingsModel
{
public bool IsUsed { get; set; }
public string TablePrefix { get; set; } = "QRTZ_";
}
+43
View File
@@ -0,0 +1,43 @@
using Indotalent.Infrastructure.Authentication;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Infrastructure.AutoNumberGenerator;
using Indotalent.Infrastructure.BackgroundJob;
using Indotalent.Infrastructure.Database;
using Indotalent.Infrastructure.Email;
using Indotalent.Infrastructure.File;
using Indotalent.Infrastructure.Logging;
using Indotalent.Infrastructure.OData;
namespace Indotalent.Infrastructure;
public static class DI
{
public static IServiceCollection AddInfrastructureDI(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<DatabaseSettingsModel>(configuration.GetSection("DatabaseSettings"));
services.Configure<BackgroundJobSettingsModel>(configuration.GetSection("BackgroundJobSettings"));
services.Configure<EmailSettingsModel>(configuration.GetSection("EmailSettings"));
services.Configure<FileStorageSettingsModel>(configuration.GetSection("FileStorageSettings"));
services.Configure<LoggerSettingsModel>(configuration.GetSection("LoggerSettings"));
services.Configure<IdentitySettingsModel>(configuration.GetSection("IdentitySettings"));
services.AddLoggingService();
services.AddDatabaseService(configuration);
services.AddBackgroundJobService();
services.AddEmailService(configuration);
services.AddFileService();
services.AddAuthenticationService(configuration);
services.AddAutoNumberGeneratorService();
services.AddODataService();
return services;
}
}
+206
View File
@@ -0,0 +1,206 @@
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<PaymentMethod> PaymentMethod { get; set; } = default!;
public DbSet<Booking> Booking { get; set; } = default!;
public DbSet<BookingGroup> BookingGroup { get; set; } = default!;
public DbSet<BookingResource> BookingResource { get; set; } = default!;
public DbSet<Bill> Bill { get; set; } = default!;
public DbSet<PaymentDisburse> PaymentDisburse { get; set; } = default!;
public DbSet<Invoice> Invoice { get; set; } = default!;
public DbSet<PaymentReceive> PaymentReceive { get; set; } = default!;
public DbSet<ProductGroup> ProductGroup { get; set; } = default!;
public DbSet<PurchaseOrder> PurchaseOrder { get; set; } = default!;
public DbSet<PurchaseOrderItem> PurchaseOrderItem { get; set; } = default!;
public DbSet<Patient> Patient { get; set; } = default!;
public DbSet<PatientCategory> PatientCategory { get; set; } = default!;
public DbSet<PatientContact> PatientContact { get; set; } = default!;
public DbSet<PatientGroup> PatientGroup { get; set; } = default!;
public DbSet<Product> Product { get; set; } = default!;
public DbSet<SalesOrderGroup> SalesOrderGroup { get; set; } = default!;
public DbSet<SalesOrderCategory> SalesOrderCategory { get; set; } = default!;
public DbSet<SalesOrder> SalesOrder { get; set; } = default!;
public DbSet<SalesOrderItem> SalesOrderItem { get; set; } = default!;
public DbSet<Todo> Todo { get; set; } = default!;
public DbSet<TodoItem> TodoItem { get; set; } = default!;
public DbSet<UnitMeasure> UnitMeasure { get; set; } = default!;
public DbSet<Vendor> Vendor { get; set; } = default!;
public DbSet<VendorCategory> VendorCategory { get; set; } = default!;
public DbSet<VendorContact> VendorContact { get; set; } = default!;
public DbSet<VendorGroup> VendorGroup { get; set; } = default!;
public DbSet<Warehouse> Warehouse { get; set; } = default!;
public DbSet<InventoryTransaction> InventoryTransaction { get; set; } = default!;
public DbSet<Employee> Employee { get; set; } = default!;
public DbSet<EmployeeCategory> EmployeeCategory { get; set; } = default!;
public DbSet<EmployeeGroup> EmployeeGroup { get; set; } = default!;
public DbSet<MedicalRecordCategory> MedicalRecordCategory { get; set; } = default!;
public DbSet<MedicalRecordGroup> MedicalRecordGroup { get; set; } = default!;
public DbSet<MedicalRecord> MedicalRecord { 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);
}
}
@@ -0,0 +1,24 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Utils;
namespace Indotalent.Infrastructure.Database;
public static class AppDbContextExtensions
{
public static void CalculateInvenTrans(this AppDbContext context, InventoryTransaction transaction)
{
InventoryTransactionHelper.CalculateInvenTrans(context, transaction);
}
public static double GetStock(this AppDbContext context, string? warehouseId, string? productId, string? currentId = null)
{
return InventoryTransactionHelper.GetStock(context, warehouseId, productId, currentId);
}
public static void RecalculatePurchaseOrder(this AppDbContext context, string purchaseOrderId)
{
PurchaseOrderHelper.Recalculate(context, purchaseOrderId);
}
public static void RecalculateSalesOrder(this AppDbContext context, string salesOrderId)
{
SalesOrderHelper.Recalculate(context, salesOrderId);
}
}
+53
View File
@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database;
public static class DI
{
public static IServiceCollection AddDatabaseService(this IServiceCollection services, IConfiguration configuration)
{
var dbSettings = configuration.GetSection("DatabaseSettings").Get<DatabaseSettingsModel>();
if (dbSettings?.MsSQL?.IsUsed == true)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
dbSettings.MsSQL.ConnectionString,
sqlOptions =>
{
sqlOptions.CommandTimeout(dbSettings.MsSQL.TimeoutInSeconds);
}
)
);
}
else if (dbSettings?.PostgreSQL?.IsUsed == true)
{
services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(
dbSettings.PostgreSQL.ConnectionString,
npgsqlOptions =>
{
npgsqlOptions.CommandTimeout(dbSettings.PostgreSQL.TimeoutInSeconds);
}
)
);
}
else if (dbSettings?.MySQL?.IsUsed == true)
{
services.AddDbContext<AppDbContext>(options =>
options.UseMySQL(
dbSettings.MySQL.ConnectionString,
mySqlOptions =>
{
mySqlOptions.CommandTimeout(dbSettings.MySQL.TimeoutInSeconds);
mySqlOptions.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName);
}
)
);
}
services.AddScoped<DatabaseService>();
return services;
}
}
@@ -0,0 +1,8 @@
namespace Indotalent.Infrastructure.Database;
public class DatabaseProviderModel
{
public bool IsUsed { get; set; }
public string ConnectionString { get; set; } = string.Empty;
public int TimeoutInSeconds { get; set; }
}
+138
View File
@@ -0,0 +1,138 @@
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Infrastructure.Authorization.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database;
public static class DatabaseSeeder
{
public static async Task SeedAsync(IServiceProvider serviceProvider)
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var context = serviceProvider.GetRequiredService<AppDbContext>();
await SeedIdentityAsync(roleManager, userManager, configuration);
await SeedCurrenciesAsync(context);
await SeedCompanyAsync(context);
await SeedTaxAsync(context);
await SeedSystemWarehouseAsync(context);
await DatabaseSeederDemo.SeedAsync(serviceProvider);
}
private static async Task SeedIdentityAsync(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager, IConfiguration configuration)
{
var adminSettings = configuration.GetSection("IdentitySettings:DefaultAdmin").Get<DefaultAdminSettings>();
if (adminSettings == null) return;
foreach (var roleName in ApplicationRoles.AllRoles)
{
if (!await roleManager.RoleExistsAsync(roleName))
{
await roleManager.CreateAsync(new IdentityRole(roleName));
}
}
var existingUser = await userManager.FindByEmailAsync(adminSettings.Email);
if (existingUser == null)
{
var defaultAdmin = DefaultUserConfig.GetAdminUser(adminSettings);
var createAdmin = await userManager.CreateAsync(defaultAdmin, adminSettings.Password);
if (createAdmin.Succeeded)
{
await userManager.AddToRolesAsync(defaultAdmin, ApplicationRoles.AllRoles);
}
}
}
private static async Task SeedCurrenciesAsync(AppDbContext context)
{
if (await context.Set<Currency>().AnyAsync()) return;
var currencies = new List<Currency>
{
new() { Name = "US Dollar", Code = "USD", Symbol = "$", Description = "United States official currency", CountryOwner = "United States" },
new() { Name = "Euro", Code = "EUR", Symbol = "€", Description = "Eurozone member states currency", CountryOwner = "European Union" },
new() { Name = "British Pound", Code = "GBP", Symbol = "£", Description = "Official currency of the UK", CountryOwner = "United Kingdom" },
new() { Name = "Indonesian Rupiah", Code = "IDR", Symbol = "Rp", Description = "Official currency of Indonesia", CountryOwner = "Indonesia" }
};
await context.Set<Currency>().AddRangeAsync(currencies);
await context.SaveChangesAsync();
}
private static async Task SeedCompanyAsync(AppDbContext context)
{
if (await context.Set<Company>().AnyAsync()) return;
var usdCurrency = await context.Set<Currency>().FirstOrDefaultAsync(x => x.Code == "USD");
if (usdCurrency == null) return;
var companies = new List<Company>
{
new()
{
Name = "Acme Global Solutions Inc.",
Description = "A leading provider of enterprise-grade cloud software solutions.",
IsDefault = true,
CurrencyId = usdCurrency.Id,
TaxIdentification = "EIN 12-3456789",
BusinessLicense = "LC-987654321",
StreetAddress = "One World Trade Center, Suite 85",
City = "New York",
StateProvince = "NY",
ZipCode = "10007",
Phone = "+1 212 555 0198",
Email = "hr@acmeglobal.com",
SocialMediaLinkedIn = "linkedin.com/company/acme-global",
CompanyLogo = "/images/logos/acme-logo.png",
OtherInformation1 = "Corporate Headquarters",
OtherInformation2 = "Technology & SaaS",
OtherInformation3 = "Fortune 500 Candidate"
}
};
await context.Set<Company>().AddRangeAsync(companies);
await context.SaveChangesAsync();
}
private static async Task SeedTaxAsync(AppDbContext context)
{
if (await context.Set<Tax>().AnyAsync()) return;
var taxes = new List<Tax>
{
new Tax { Code = "NOTAX", Name = "NOTAX", PercentageValue = 0 },
new Tax { Code = "T10", Name = "T10", PercentageValue = 10 },
new Tax { Code = "T15", Name = "T15", PercentageValue = 15 },
new Tax { Code = "T20", Name = "T20", PercentageValue = 20 },
};
await context.Set<Tax>().AddRangeAsync(taxes);
await context.SaveChangesAsync();
}
private static async Task SeedSystemWarehouseAsync(AppDbContext context)
{
if (await context.Set<Warehouse>().AnyAsync(x => x.SystemWarehouse == true)) return;
var warehouses = new List<Warehouse>
{
new Warehouse { Name = "Customer", SystemWarehouse = true },
new Warehouse { Name = "Vendor", SystemWarehouse = true },
new Warehouse { Name = "Transfer", SystemWarehouse = true },
new Warehouse { Name = "Adjustment", SystemWarehouse = true },
new Warehouse { Name = "StockCount", SystemWarehouse = true },
new Warehouse { Name = "Scrapping", SystemWarehouse = true }
};
await context.Set<Warehouse>().AddRangeAsync(warehouses);
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,68 @@
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Database.Demo;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Indotalent.Infrastructure.Database;
public static class DatabaseSeederDemo
{
public static async Task SeedAsync(IServiceProvider serviceProvider)
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var context = serviceProvider.GetRequiredService<AppDbContext>();
// 1. Master Data (Must be first)
await UserSeeder.GenerateDataAsync(userManager, context, configuration);
await UnitMeasureSeeder.GenerateDataAsync(context);
await WarehouseSeeder.GenerateDataAsync(context);
await PaymentMethodSeeder.GenerateDataAsync(context);
await EmployeeGroupSeeder.GenerateDataAsync(context);
await EmployeeCategorySeeder.GenerateDataAsync(context);
await EmployeeSeeder.GenerateDataAsync(context);
await SalesOrderGroupSeeder.GenerateDataAsync(context);
await SalesOrderCategorySeeder.GenerateDataAsync(context);
await MedicalRecordGroupSeeder.GenerateDataAsync(context);
await MedicalRecordCategorySeeder.GenerateDataAsync(context);
// 2. Customer & Vendor Related
await PatientCategorySeeder.GenerateDataAsync(context);
await PatientGroupSeeder.GenerateDataAsync(context);
await PatientSeeder.GenerateDataAsync(context);
await PatientContactSeeder.GenerateDataAsync(context);
await VendorCategorySeeder.GenerateDataAsync(context);
await VendorGroupSeeder.GenerateDataAsync(context);
await VendorSeeder.GenerateDataAsync(context);
await VendorContactSeeder.GenerateDataAsync(context);
// 3. Product Related
await ProductGroupSeeder.GenerateDataAsync(context);
await ProductSeeder.GenerateDataAsync(context);
// 4. Sales Related
await SalesOrderSeeder.GenerateDataAsync(context);
// 5. Purchase Related
await PurchaseOrderSeeder.GenerateDataAsync(context);
// 6. Inventory Operations
// 7. Finance & Project Related
await InvoiceSeeder.GenerateDataAsync(context);
await PaymentReceiveSeeder.GenerateDataAsync(context);
await BillSeeder.GenerateDataAsync(context);
await PaymentDisburseSeeder.GenerateDataAsync(context);
await BookingGroupSeeder.GenerateDataAsync(context);
await BookingResourceSeeder.GenerateDataAsync(context);
await BookingSeeder.GenerateDataAsync(context);
// 8. Medical Record Related
await MedicalRecordSeeder.GenerateDataAsync(context);
}
}
@@ -0,0 +1,18 @@
using Microsoft.Extensions.Options;
namespace Indotalent.Infrastructure.Database;
public class DatabaseService(IOptions<DatabaseSettingsModel> options)
{
private readonly DatabaseSettingsModel _settings = options.Value;
public DatabaseSettingsModel GetConfiguration() => _settings;
public DatabaseProviderModel GetActiveProvider()
{
if (_settings.MsSQL.IsUsed) return _settings.MsSQL;
if (_settings.MySQL.IsUsed) return _settings.MySQL;
if (_settings.PostgreSQL.IsUsed) return _settings.PostgreSQL;
return new DatabaseProviderModel();
}
}
@@ -0,0 +1,8 @@
namespace Indotalent.Infrastructure.Database;
public class DatabaseSettingsModel
{
public DatabaseProviderModel MsSQL { get; set; } = new();
public DatabaseProviderModel MySQL { get; set; } = new();
public DatabaseProviderModel PostgreSQL { get; set; } = new();
}
+104
View File
@@ -0,0 +1,104 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class BillSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Bill.AnyAsync()) return;
var random = new Random();
var entityName = nameof(Bill);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedPurchaseOrders = await context.PurchaseOrder
.Where(po => po.OrderStatus == PurchaseOrderStatus.Confirmed)
.Select(po => po.Id)
.ToListAsync();
if (!confirmedPurchaseOrders.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] billDates = GetRandomDays(date.Year, date.Month, 5);
foreach (var billDate in billDates)
{
if (confirmedPurchaseOrders.Count == 0) break;
var status = GetRandomStatus(random);
var purchaseOrderId = GetRandomAndRemove(confirmedPurchaseOrders, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var bill = new Bill
{
AutoNumber = autoNo,
BillDate = billDate,
BillStatus = status,
Description = $"Bill for {billDate:MMMM yyyy}",
PurchaseOrderId = purchaseOrderId
};
await context.Bill.AddAsync(bill);
}
}
await context.SaveChangesAsync();
}
private static BillStatus GetRandomStatus(Random random)
{
var statuses = new[]
{
BillStatus.Draft,
BillStatus.Cancelled,
BillStatus.Confirmed
};
var weights = new[] { 1, 1, 4 };
int totalWeight = weights.Sum();
int randomNumber = random.Next(0, totalWeight);
for (int i = 0; i < statuses.Length; i++)
{
if (randomNumber < weights[i]) return statuses[i];
randomNumber -= weights[i];
}
return BillStatus.Confirmed;
}
private static string GetRandomAndRemove(List<string> list, Random random)
{
int index = random.Next(list.Count);
string value = list[index];
list.RemoveAt(index);
return value;
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class BookingGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.BookingGroup.AnyAsync()) return;
var bookingGroups = new List<BookingGroup>
{
new BookingGroup { Name = "General Practice Consultations" },
new BookingGroup { Name = "Specialist Consultations" },
new BookingGroup { Name = "Dental Care & Procedures" },
new BookingGroup { Name = "Laboratory & Blood Testing" },
new BookingGroup { Name = "Radiology & Diagnostic Imaging" },
new BookingGroup { Name = "Physical Therapy & Rehabilitation" },
new BookingGroup { Name = "Maternal & Women's Health" },
new BookingGroup { Name = "Pediatric Care & Immunizations" },
new BookingGroup { Name = "Minor Surgical Procedures" },
new BookingGroup { Name = "Health Screening & Medical Checkups" }
};
foreach (var bookingGroup in bookingGroups)
{
await context.BookingGroup.AddAsync(bookingGroup);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,161 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class BookingResourceSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.BookingResource.AnyAsync()) return;
var groups = await context.BookingGroup.ToListAsync();
var resources = new List<BookingResource>();
foreach (var group in groups)
{
if (group.Name == "General Practice Consultations")
{
resources.Add(new BookingResource { Name = "GP Consultation Room 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "GP Consultation Room 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "GP Consultation Room 3", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "GP Consultation Room 4", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Walk-in Clinic Room A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Walk-in Clinic Room B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Telemedicine Booth 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Telemedicine Booth 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Triage Station 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Triage Station 2", BookingGroupId = group.Id });
}
if (group.Name == "Specialist Consultations")
{
resources.Add(new BookingResource { Name = "Cardiology Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dermatology Exam Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Orthopedic Consult Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Neurology Exam Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Gastroenterology Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "ENT Examination Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Psychiatry Consult Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Ophthalmology Exam Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Endocrinology Office", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Specialist VIP Suite", BookingGroupId = group.Id });
}
if (group.Name == "Dental Care & Procedures")
{
resources.Add(new BookingResource { Name = "Dental Chair 1 - General", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dental Chair 2 - General", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dental Chair 3 - Hygiene", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dental Chair 4 - Hygiene", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Orthodontic Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Pediatric Dental Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Oral Surgery Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Endodontic Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dental X-Ray Booth", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Cosmetic Dental Suite", BookingGroupId = group.Id });
}
if (group.Name == "Laboratory & Blood Testing")
{
resources.Add(new BookingResource { Name = "Phlebotomy Station 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Phlebotomy Station 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Phlebotomy Station 3", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Phlebotomy Station 4", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Private Draw Room A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Private Draw Room B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Specimen Collection Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Urinalysis Restroom 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Urinalysis Restroom 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Rapid Testing Bay", BookingGroupId = group.Id });
}
if (group.Name == "Radiology & Diagnostic Imaging")
{
resources.Add(new BookingResource { Name = "X-Ray Room A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "X-Ray Room B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Ultrasound Room 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Ultrasound Room 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "MRI Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "CT Scan Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Mammography Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Bone Density Scan Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Echocardiogram Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Fluoroscopy Bay", BookingGroupId = group.Id });
}
if (group.Name == "Physical Therapy & Rehabilitation")
{
resources.Add(new BookingResource { Name = "PT Treatment Room 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "PT Treatment Room 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "PT Treatment Room 3", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Manual Therapy Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Rehab Gym Area", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Gait Analysis Walkway", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Ultrasound Therapy Bay", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "TENS & Stim Station", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Pediatric PT Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Sports Rehab Zone", BookingGroupId = group.Id });
}
if (group.Name == "Maternal & Women's Health")
{
resources.Add(new BookingResource { Name = "OBGYN Exam Room 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "OBGYN Exam Room 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "OBGYN Exam Room 3", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Fetal Monitoring Bay A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Fetal Monitoring Bay B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Lactation Consulting Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Family Planning Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Women's Wellness Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Maternity Triage", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Colposcopy Room", BookingGroupId = group.Id });
}
if (group.Name == "Pediatric Care & Immunizations")
{
resources.Add(new BookingResource { Name = "Pediatric Exam Room A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Pediatric Exam Room B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Pediatric Exam Room C", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Well-Baby Checkup Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Immunization Station 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Immunization Station 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Pediatric Triage Bay", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Adolescent Care Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Nebulizer Station", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Child Development Room", BookingGroupId = group.Id });
}
if (group.Name == "Minor Surgical Procedures")
{
resources.Add(new BookingResource { Name = "Minor Procedure Room 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Minor Procedure Room 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Outpatient Surgery Suite", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Suture & Laceration Bay", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Dermatology Procedure Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Cryotherapy Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Laser Treatment Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Prep & Recovery Bed 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Prep & Recovery Bed 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Prep & Recovery Bed 3", BookingGroupId = group.Id });
}
if (group.Name == "Health Screening & Medical Checkups")
{
resources.Add(new BookingResource { Name = "Executive Checkup Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Basic Screening Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Biometric Station 1", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Biometric Station 2", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Vision Testing Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Audiology Booth", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "ECG & Treadmill Room", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Vitals Station A", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Vitals Station B", BookingGroupId = group.Id });
resources.Add(new BookingResource { Name = "Consultation Finalization Room", BookingGroupId = group.Id });
}
}
await context.BookingResource.AddRangeAsync(resources);
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,95 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class BookingSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Booking.AnyAsync()) return;
var random = new Random();
var bookingStatusValues = Enum.GetValues(typeof(BookingStatus)).Cast<BookingStatus>().ToList();
var entityName = nameof(Booking);
var dateEnd = DateTime.Now;
var dateStart = dateEnd.AddMonths(-12);
var bookingResources = await context.BookingResource
.Select(x => x.Id)
.ToListAsync();
var locations = await context.Warehouse
.Where(x => x.SystemWarehouse == false)
.Select(x => x.Name)
.ToListAsync();
if (!bookingResources.Any() || !locations.Any()) return;
var subjects = new string[]
{
"General Medical Checkup",
"Specialist Follow-up",
"Routine Dental Cleaning",
"Blood Extraction & Lab Test",
"X-Ray / Diagnostic Imaging",
"Physical Therapy Session",
"Annual Vaccination",
"Pediatric Well-Baby Visit",
"Obstetric Ultrasound",
"Cardiology ECG Check",
"Dermatology Consultation",
"Orthopedic Assessment",
"Minor Surgical Procedure",
"Telemedicine Consultation",
"Pre-Employment Medical Exam"
};
for (DateTime date = dateStart; date < dateEnd; date = date.AddMonths(1))
{
DateTime[] transactionDates = GenerateRandomDays(date.Year, date.Month, 25);
foreach (DateTime transDate in transactionDates)
{
int hourStart = random.Next(8, 18);
DateTime startTime = transDate.Date.AddHours(hourStart);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var booking = new Booking
{
Subject = $"{subjects[random.Next(subjects.Length)]} - {autoNo}",
AutoNumber = autoNo,
StartTime = startTime,
EndTime = startTime.AddHours(random.Next(1, 3)),
BookingResourceId = GetRandomValue(bookingResources, random),
Status = bookingStatusValues[random.Next(bookingStatusValues.Count)],
Location = GetRandomValue(locations, random)
};
await context.Booking.AddAsync(booking);
}
}
await context.SaveChangesAsync();
}
private static DateTime[] GenerateRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
return Enumerable.Range(1, count)
.Select(_ => new DateTime(year, month, random.Next(1, daysInMonthCount + 1)))
.ToArray();
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
}
@@ -0,0 +1,28 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class EmployeeCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.EmployeeCategory.AnyAsync()) return;
var employeeCategories = new List<EmployeeCategory>
{
new EmployeeCategory { Name = "Medical & Clinical Professionals" },
new EmployeeCategory { Name = "Nursing & Clinical Support" },
new EmployeeCategory { Name = "Allied Health & Diagnostics" },
new EmployeeCategory { Name = "Administrative & Management" },
new EmployeeCategory { Name = "Operations & Facility Support" }
};
foreach (var category in employeeCategories)
{
await context.EmployeeCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class EmployeeGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.EmployeeGroup.AnyAsync()) return;
var employeeGroups = new List<EmployeeGroup>
{
new EmployeeGroup { Name = "Medical Doctors & Specialists" },
new EmployeeGroup { Name = "Registered Nurses & Care Staff" },
new EmployeeGroup { Name = "Pharmacy & Dispensing Team" },
new EmployeeGroup { Name = "Laboratory & Diagnostic Technicians" },
new EmployeeGroup { Name = "Radiology & Imaging Technicians" },
new EmployeeGroup { Name = "Dental & Allied Health Professionals" },
new EmployeeGroup { Name = "Patient Reception & Front Desk" },
new EmployeeGroup { Name = "Medical Billing & Insurance" },
new EmployeeGroup { Name = "Clinic Administration & Management" },
new EmployeeGroup { Name = "Facility Maintenance & Security" }
};
foreach (var group in employeeGroups)
{
await context.EmployeeGroup.AddAsync(group);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,91 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class EmployeeSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Employee.AnyAsync()) return;
var categories = await context.EmployeeCategory.ToListAsync();
var groups = await context.EmployeeGroup.ToListAsync();
if (!categories.Any() || !groups.Any()) return;
var streets = new string[] { "Main St", "Broadway", "Oak Avenue", "Maple Drive", "Park Avenue", "Washington Blvd", "Lakeview Dr", "Sunset Blvd" };
var cities = new string[] { "New York", "Los Angeles", "Chicago", "Miami", "Seattle" };
var states = new string[] { "NY", "CA", "IL", "FL", "WA" };
var zipCodes = new string[] { "10001", "90210", "60601", "33101", "98101" };
var random = new Random();
var entityName = nameof(Employee);
var employeeData = new List<(string Name, string Title, string GroupName, string CategoryName, decimal Commission)>
{
("Dr. Robert Sterling", "Chief Medical Officer", "Medical Doctors & Specialists", "Medical & Clinical Professionals", 0.00m),
("Dr. Jennifer Adams", "General Practitioner", "Medical Doctors & Specialists", "Medical & Clinical Professionals", 0.15m),
("Dr. David Miller", "Orthopedic Surgeon", "Medical Doctors & Specialists", "Medical & Clinical Professionals", 0.20m),
("Sarah Mitchell", "Head Nurse", "Registered Nurses & Care Staff", "Nursing & Clinical Support", 0.00m),
("Jessica Taylor", "ER Triage Nurse", "Registered Nurses & Care Staff", "Nursing & Clinical Support", 0.00m),
("Michael Vance", "Senior Pharmacist", "Pharmacy & Dispensing Team", "Allied Health & Diagnostics", 0.00m),
("Amanda Williams", "Pharmacy Technician", "Pharmacy & Dispensing Team", "Allied Health & Diagnostics", 0.00m),
("Christopher Moore", "Lead Phlebotomist", "Laboratory & Diagnostic Technicians", "Allied Health & Diagnostics", 0.00m),
("Kevin Anderson", "Clinical Lab Scientist", "Laboratory & Diagnostic Technicians", "Allied Health & Diagnostics", 0.00m),
("Samantha White", "MRI Technologist", "Radiology & Imaging Technicians", "Allied Health & Diagnostics", 0.00m),
("Dr. Ashley Johnson", "Chief Dentist", "Dental & Allied Health Professionals", "Medical & Clinical Professionals", 0.15m),
("Matthew Davis", "Dental Hygienist", "Dental & Allied Health Professionals", "Allied Health & Diagnostics", 0.05m),
("Lauren Martinez", "Receptionist Lead", "Patient Reception & Front Desk", "Administrative & Management", 0.00m),
("Jonathan Wilson", "Admissions Coordinator", "Patient Reception & Front Desk", "Administrative & Management", 0.00m),
("Stephanie Rodriguez", "Billing Specialist", "Medical Billing & Insurance", "Administrative & Management", 0.00m),
("Nicholas Thomas", "Insurance Coordinator", "Medical Billing & Insurance", "Administrative & Management", 0.00m),
("Jason Hernandez", "Clinic Administrator", "Clinic Administration & Management", "Administrative & Management", 0.00m),
("Olivia Jackson", "HR Manager", "Clinic Administration & Management", "Administrative & Management", 0.00m),
("Alexander Smith", "Facility Supervisor", "Facility Maintenance & Security", "Operations & Facility Support", 0.00m),
("Elizabeth Brown", "Security Lead", "Facility Maintenance & Security", "Operations & Facility Support", 0.00m)
};
foreach (var data in employeeData)
{
var group = groups.FirstOrDefault(x => x.Name == data.GroupName);
var category = categories.FirstOrDefault(x => x.Name == data.CategoryName);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"EMP-{{Year}}-"
);
var emailPrefix = data.Name.Replace("Dr. ", "").Replace(" ", ".").ToLower();
var employee = new Employee
{
Name = data.Name,
AutoNumber = autoNo,
EmployeeNumber = $"ID-{random.Next(1000, 9999)}",
JobTitle = data.Title,
CommissionRate = data.Commission,
EmployeeGroupId = group?.Id,
EmployeeCategoryId = category?.Id,
Street = $"{random.Next(100, 999)} {GetRandomString(streets, random)}",
City = GetRandomString(cities, random),
State = GetRandomString(states, random),
ZipCode = GetRandomString(zipCodes, random),
Country = "United States",
PhoneNumber = $"+1-{random.Next(200, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
EmailAddress = $"{emailPrefix}@med-clinic.us",
Description = $"Professional {data.Title} based in the {data.CategoryName} division."
};
await context.Employee.AddAsync(employee);
}
await context.SaveChangesAsync();
}
private static string GetRandomString(string[] array, Random random)
{
return array[random.Next(array.Length)];
}
}
@@ -0,0 +1,99 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class InvoiceSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Invoice.AnyAsync()) return;
var random = new Random();
var entityName = nameof(Invoice);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedSalesOrders = await context.SalesOrder
.Where(so => so.OrderStatus == SalesOrderStatus.Confirmed)
.Select(so => so.Id)
.ToListAsync();
if (!confirmedSalesOrders.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] invoiceDates = GetRandomDays(date.Year, date.Month, 5);
foreach (var invoiceDate in invoiceDates)
{
if (confirmedSalesOrders.Count == 0) break;
var status = GetRandomStatus(random);
var salesOrderId = GetRandomAndRemove(confirmedSalesOrders, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var invoice = new Invoice
{
AutoNumber = autoNo,
InvoiceDate = invoiceDate,
InvoiceStatus = status,
Description = $"Invoice for {invoiceDate:MMMM yyyy}",
SalesOrderId = salesOrderId
};
await context.Invoice.AddAsync(invoice);
}
}
await context.SaveChangesAsync();
}
private static InvoiceStatus GetRandomStatus(Random random)
{
var statuses = new[] { InvoiceStatus.Draft, InvoiceStatus.Cancelled, InvoiceStatus.Confirmed };
var weights = new[] { 1, 1, 4 };
int totalWeight = weights.Sum();
int randomNumber = random.Next(0, totalWeight);
for (int i = 0; i < statuses.Length; i++)
{
if (randomNumber < weights[i]) return statuses[i];
randomNumber -= weights[i];
}
return InvoiceStatus.Confirmed;
}
private static string GetRandomAndRemove(List<string> list, Random random)
{
int index = random.Next(list.Count);
string value = list[index];
list.RemoveAt(index);
return value;
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class MedicalRecordCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.MedicalRecordCategory.AnyAsync()) return;
var medicalCategories = new List<MedicalRecordCategory>
{
new MedicalRecordCategory { Name = "Initial Consultation" },
new MedicalRecordCategory { Name = "Follow-up Visit" },
new MedicalRecordCategory { Name = "Annual Physical Examination" },
new MedicalRecordCategory { Name = "Urgent Care Visit" },
new MedicalRecordCategory { Name = "Emergency Department Visit" },
new MedicalRecordCategory { Name = "Telehealth Consultation" },
new MedicalRecordCategory { Name = "Specialist Referral Evaluation" },
new MedicalRecordCategory { Name = "Pre-Employment Medical Exam" },
new MedicalRecordCategory { Name = "Diagnostic Results Review" },
new MedicalRecordCategory { Name = "Chronic Care Management" }
};
foreach (var category in medicalCategories)
{
await context.MedicalRecordCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,35 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class MedicalRecordGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.MedicalRecordGroup.AnyAsync()) return;
var medicalGroups = new List<MedicalRecordGroup>
{
new MedicalRecordGroup { Name = "Family Medicine" },
new MedicalRecordGroup { Name = "Internal Medicine" },
new MedicalRecordGroup { Name = "Pediatrics" },
new MedicalRecordGroup { Name = "Obstetrics & Gynecology (OB/GYN)" },
new MedicalRecordGroup { Name = "Cardiology" },
new MedicalRecordGroup { Name = "Dermatology" },
new MedicalRecordGroup { Name = "Dentistry & Oral Health" },
new MedicalRecordGroup { Name = "Emergency Medicine" },
new MedicalRecordGroup { Name = "Urgent Care" },
new MedicalRecordGroup { Name = "Physical Therapy & Rehab" },
new MedicalRecordGroup { Name = "Psychiatry & Behavioral Health" },
new MedicalRecordGroup { Name = "Occupational Health" }
};
foreach (var group in medicalGroups)
{
await context.MedicalRecordGroup.AddAsync(group);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,116 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class MedicalRecordSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.MedicalRecord.AnyAsync()) return;
var random = new Random();
var entityName = nameof(MedicalRecord);
var patients = await context.Patient.ToListAsync();
var doctors = await context.Employee
.Where(x => x.Name!.StartsWith("Dr.") || x.JobTitle!.Contains("Practitioner") || x.JobTitle!.Contains("Surgeon"))
.ToListAsync();
var groups = await context.MedicalRecordGroup.ToListAsync();
var categories = await context.MedicalRecordCategory.ToListAsync();
if (!patients.Any() || !doctors.Any() || !groups.Any() || !categories.Any()) return;
var soapSamples = new List<(string S, string O, string A, string P)>
{
(
"Patient reports persistent lower back pain for 2 weeks, exacerbated by morning activity.",
"Tenderness noted in the lumbar spine region, decreased range of motion during trunk flexion.",
"Lumbago with sciatica (ICD-10 M54.5).",
"Start NSAID regimen, referral to Physical Therapy twice weekly, and activity modification."
),
(
"Dry cough and low-grade fever for 72 hours. Patient denies dyspnea or chest pain.",
"Lungs clear to auscultation bilaterally. Pharynx mildly erythematous. Temp 100.8 F.",
"Acute Upper Respiratory Infection (ICD-10 J06.9).",
"Rest, increased fluid intake, and over-the-counter antipyretics as needed."
),
(
"Routine dental evaluation. Patient reports sensitivity to cold stimuli on lower left quadrant.",
"Localized enamel wear on tooth #19. Gingival tissue appears within normal limits.",
"Dentin hypersensitivity (ICD-10 K03.8).",
"Applied fluoride varnish. Recommended use of potassium nitrate toothpaste."
),
(
"Follow-up for essential hypertension. Patient reports compliance with medication, no headaches.",
"S1, S2 audible, regular rate and rhythm. No peripheral edema noted.",
"Essential Hypertension (ICD-10 I10).",
"Continue current antihypertensive therapy. Reinforce DASH diet and low sodium intake."
),
(
"Urgent care visit: inverted right ankle while running this morning.",
"Edema and ecchymosis over the lateral malleolus. Guarded weight-bearing due to pain.",
"Ankle sprain, grade 1 (ICD-10 S93.4).",
"Follow RICE protocol (Rest, Ice, Compression, Elevation). Applied ACE bandage."
)
};
var dateFinish = DateTime.Now;
var dateStart = dateFinish.AddMonths(-12);
foreach (var patient in patients)
{
int recordsPerPatient = random.Next(1, 4);
for (int i = 0; i < recordsPerPatient; i++)
{
var randomDays = random.Next(0, (dateFinish - dateStart).Days);
var recordDate = dateStart.AddDays(randomDays);
var doctor = doctors[random.Next(doctors.Count)];
var soap = soapSamples[random.Next(soapSamples.Count)];
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"MR/{{Year}}/{{Month}}/"
);
var tempF = Math.Round(97.0 + (random.NextDouble() * 3.5), 1);
var heightInches = random.Next(60, 76);
var feet = heightInches / 12;
var inches = heightInches % 12;
var medicalRecord = new MedicalRecord
{
AutoNumber = autoNo,
RecordDate = recordDate,
PatientId = patient.Id,
EmployeeId = doctor.Id,
MedicalRecordGroupId = groups[random.Next(groups.Count)].Id,
MedicalRecordCategoryId = categories[random.Next(categories.Count)].Id,
Subjective = soap.S,
Objective = soap.O,
Assessment = soap.A,
Planning = soap.P,
BloodPressure = $"{random.Next(110, 135)}/{random.Next(70, 88)} mmHg",
Temperature = $"{tempF} F",
HeartRate = $"{random.Next(60, 100)} bpm",
Weight = $"{random.Next(120, 230)} lbs",
Height = $"{feet}'{inches}\"",
Description = $"Clinical encounter documentation for {patient.Name}",
Status = random.Next(1, 10) > 2 ? MedicalRecordStatus.Completed : MedicalRecordStatus.Examining
};
await context.MedicalRecord.AddAsync(medicalRecord);
}
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PatientCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PatientCategory.AnyAsync()) return;
var patientCategories = new List<PatientCategory>
{
new PatientCategory { Name = "New Patient" },
new PatientCategory { Name = "Returning / Existing Patient" },
new PatientCategory { Name = "Walk-in Patient" },
new PatientCategory { Name = "Referred Patient" },
new PatientCategory { Name = "Emergency / Urgent Care" },
new PatientCategory { Name = "Regular Outpatient" },
new PatientCategory { Name = "Day Care / Observation" },
new PatientCategory { Name = "Telemedicine Patient" },
new PatientCategory { Name = "Home Care Patient" },
new PatientCategory { Name = "Routine Medical Checkup" }
};
foreach (var category in patientCategories)
{
await context.PatientCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,81 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PatientContactSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PatientContact.AnyAsync()) return;
var firstNames = new string[]
{
"James", "Mary", "Robert", "Patricia", "John", "Jennifer",
"Michael", "Linda", "David", "Elizabeth", "William", "Barbara",
"Richard", "Susan", "Joseph", "Jessica", "Thomas", "Sarah",
"Charles", "Karen"
};
var lastNames = new string[]
{
"Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia",
"Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez",
"Gonzalez", "Wilson", "Anderson", "Thomas", "Taylor", "Moore",
"Jackson", "Martin"
};
var relationships = new string[]
{
"Spouse", "Father", "Mother", "Sibling", "Child",
"Emergency Contact", "Next of Kin", "Legal Guardian",
"Primary Caregiver", "Partner", "Aunt", "Uncle",
"Grandparent", "Cousin", "Friend"
};
var emailDomains = new string[] { "gmail.com", "outlook.com", "yahoo.com", "icloud.com", "hotmail.com" };
var patientIds = await context.Patient.Select(x => x.Id).ToListAsync();
var random = new Random();
var entityName = nameof(PatientContact);
foreach (var patientId in patientIds)
{
for (int i = 0; i < 2; i++)
{
var firstName = GetRandomString(firstNames, random);
var lastName = GetRandomString(lastNames, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var contact = new PatientContact
{
Name = $"{firstName} {lastName}",
AutoNumber = autoNo,
PatientId = patientId,
Title = GetRandomString(relationships, random),
EmailAddress = $"{firstName.ToLower()}.{lastName.ToLower()}@{GetRandomString(emailDomains, random)}",
PhoneNumber = GenerateRandomPhoneNumber(random)
};
await context.PatientContact.AddAsync(contact);
}
}
await context.SaveChangesAsync();
}
private static string GetRandomString(string[] array, Random random)
{
return array[random.Next(array.Length)];
}
private static string GenerateRandomPhoneNumber(Random random)
{
return $"+1-{random.Next(200, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}";
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PatientGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PatientGroup.AnyAsync()) return;
var patientGroups = new List<PatientGroup>
{
new PatientGroup { Name = "Self-Pay / General Patients" },
new PatientGroup { Name = "Private Health Insurance" },
new PatientGroup { Name = "Government Insurance / BPJS" },
new PatientGroup { Name = "Corporate Partner Employees" },
new PatientGroup { Name = "Pediatric & Child Care" },
new PatientGroup { Name = "Maternity & Women's Health" },
new PatientGroup { Name = "Geriatric & Senior Care" },
new PatientGroup { Name = "Chronic Disease Management" },
new PatientGroup { Name = "External Clinic Referrals" },
new PatientGroup { Name = "VIP / Premium Care Members" }
};
foreach (var group in patientGroups)
{
await context.PatientGroup.AddAsync(group);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,82 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PatientSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Patient.AnyAsync()) return;
var groups = await context.PatientGroup.Select(x => x.Id).ToArrayAsync();
var categories = await context.PatientCategory.Select(x => x.Id).ToArrayAsync();
var cities = new string[] { "New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia", "Miami", "Seattle", "Austin", "Denver" };
var streets = new string[] { "Maple Street", "Oak Avenue", "Pine Lane", "Cedar Road", "Elm Street", "Washington Blvd", "Lakeview Drive", "Meadow Lane", "Park Avenue", "Sunset Blvd" };
var states = new string[] { "NY", "CA", "IL", "TX", "AZ", "PA", "FL", "WA", "CO", "MA" };
var zipCodes = new string[] { "10001", "90210", "60601", "77001", "85001", "19101", "33101", "98101", "73301", "80201" };
var phoneNumbers = new string[] { "212-555-0101", "310-555-0102", "312-555-0103", "713-555-0104", "602-555-0105", "305-555-0106" };
var emailDomains = new string[] { "gmail.com", "outlook.com", "icloud.com", "yahoo.com", "hotmail.com" };
var random = new Random();
var entityName = nameof(Patient);
var patients = new List<Patient>
{
new Patient { Name = "James Anderson" },
new Patient { Name = "Maria Garcia" },
new Patient { Name = "Robert Smith" },
new Patient { Name = "Linda Johnson" },
new Patient { Name = "Michael Williams" },
new Patient { Name = "Sarah Davis" },
new Patient { Name = "David Miller" },
new Patient { Name = "Jessica Wilson" },
new Patient { Name = "John Taylor" },
new Patient { Name = "Karen Moore" },
new Patient { Name = "Richard Anderson" },
new Patient { Name = "Nancy Thomas" },
new Patient { Name = "Charles Jackson" },
new Patient { Name = "Lisa White" },
new Patient { Name = "Joseph Harris" },
new Patient { Name = "Margaret Martin" },
new Patient { Name = "Thomas Thompson" },
new Patient { Name = "Sandra Garcia" },
new Patient { Name = "Christopher Martinez" },
new Patient { Name = "Betty Robinson" }
};
foreach (var patient in patients)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
patient.AutoNumber = autoNo;
patient.PatientGroupId = GetRandomValue(groups, random);
patient.PatientCategoryId = GetRandomValue(categories, random);
patient.City = GetRandomString(cities, random);
patient.Street = GetRandomString(streets, random);
patient.State = GetRandomString(states, random);
patient.ZipCode = GetRandomString(zipCodes, random);
patient.PhoneNumber = GetRandomString(phoneNumbers, random);
patient.EmailAddress = $"{patient.Name?.Replace(" ", ".").ToLower()}@{GetRandomString(emailDomains, random)}";
await context.Patient.AddAsync(patient);
}
await context.SaveChangesAsync();
}
private static T GetRandomValue<T>(T[] array, Random random)
{
return array[random.Next(array.Length)];
}
private static string GetRandomString(string[] array, Random random)
{
return array[random.Next(array.Length)];
}
}
@@ -0,0 +1,117 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PaymentDisburseSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PaymentDisburse.AnyAsync()) return;
var random = new Random();
var entityName = nameof(PaymentDisburse);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedBills = await context.Bill
.Include(b => b.PurchaseOrder)
.Where(b => b.BillStatus == BillStatus.Confirmed)
.ToListAsync();
var paymentMethods = await context.PaymentMethod
.Select(pm => pm.Id)
.ToListAsync();
if (!paymentMethods.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] paymentDates = GetRandomDays(date.Year, date.Month, 4);
foreach (var paymentDate in paymentDates)
{
if (confirmedBills.Count == 0) break;
var status = GetRandomStatus(random);
var bill = GetRandomAndRemove(confirmedBills, random);
var paymentMethodId = GetRandomValue(paymentMethods, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var paymentDisburse = new PaymentDisburse
{
AutoNumber = autoNo,
Description = $"Payment Disbursed on {paymentDate:MMMM yyyy}",
PaymentDate = paymentDate,
PaymentMethodId = paymentMethodId,
PaymentAmount = bill.PurchaseOrder?.AfterTaxAmount,
Status = status,
BillId = bill.Id
};
await context.PaymentDisburse.AddAsync(paymentDisburse);
}
}
await context.SaveChangesAsync();
}
private static PaymentDisburseStatus GetRandomStatus(Random random)
{
var statuses = new[]
{
PaymentDisburseStatus.Draft,
PaymentDisburseStatus.Cancelled,
PaymentDisburseStatus.Confirmed,
PaymentDisburseStatus.Archived
};
var weights = new[] { 1, 1, 4, 1 };
int totalWeight = weights.Sum();
int randomNumber = random.Next(0, totalWeight);
for (int i = 0; i < statuses.Length; i++)
{
if (randomNumber < weights[i]) return statuses[i];
randomNumber -= weights[i];
}
return PaymentDisburseStatus.Confirmed;
}
private static T GetRandomAndRemove<T>(List<T> list, Random random)
{
int index = random.Next(list.Count);
T value = list[index];
list.RemoveAt(index);
return value;
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,28 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PaymentMethodSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PaymentMethod.AnyAsync()) return;
var paymentMethods = new List<PaymentMethod>
{
new PaymentMethod { Name = "Credit Card" },
new PaymentMethod { Name = "Debit Card" },
new PaymentMethod { Name = "Bank Transfer" },
new PaymentMethod { Name = "PayPal" },
new PaymentMethod { Name = "Cash" }
};
foreach (var paymentMethod in paymentMethods)
{
await context.PaymentMethod.AddAsync(paymentMethod);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,117 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PaymentReceiveSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PaymentReceive.AnyAsync()) return;
var random = new Random();
var entityName = nameof(PaymentReceive);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedInvoices = await context.Invoice
.Include(i => i.SalesOrder)
.Where(i => i.InvoiceStatus == InvoiceStatus.Confirmed && i.SalesOrder != null)
.ToListAsync();
var paymentMethods = await context.PaymentMethod
.Select(pm => pm.Id)
.ToListAsync();
if (!paymentMethods.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] paymentDates = GetRandomDays(date.Year, date.Month, 4);
foreach (var paymentDate in paymentDates)
{
if (confirmedInvoices.Count == 0) break;
var status = GetRandomStatus(random);
var invoice = GetRandomAndRemove(confirmedInvoices, random);
var paymentMethodId = GetRandomValue(paymentMethods, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var paymentReceive = new PaymentReceive
{
AutoNumber = autoNo,
Description = $"Payment Received on {paymentDate:MMMM yyyy}",
PaymentDate = paymentDate,
PaymentMethodId = paymentMethodId,
PaymentAmount = invoice?.SalesOrder?.AfterTaxAmount,
Status = status,
InvoiceId = invoice?.Id
};
await context.PaymentReceive.AddAsync(paymentReceive);
}
}
await context.SaveChangesAsync();
}
private static PaymentReceiveStatus GetRandomStatus(Random random)
{
var statuses = new[]
{
PaymentReceiveStatus.Draft,
PaymentReceiveStatus.Cancelled,
PaymentReceiveStatus.Confirmed,
PaymentReceiveStatus.Archived
};
var weights = new[] { 1, 1, 4, 1 };
int totalWeight = weights.Sum();
int randomNumber = random.Next(0, totalWeight);
for (int i = 0; i < statuses.Length; i++)
{
if (randomNumber < weights[i]) return statuses[i];
randomNumber -= weights[i];
}
return PaymentReceiveStatus.Confirmed;
}
private static T GetRandomAndRemove<T>(List<T> list, Random random)
{
int index = random.Next(list.Count);
T value = list[index];
list.RemoveAt(index);
return value;
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,43 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class ProductGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.ProductGroup.AnyAsync()) return;
var productGroups = new List<ProductGroup>
{
new ProductGroup { Name = "Prescription Medications" },
new ProductGroup { Name = "Over-the-Counter (OTC) Drugs" },
new ProductGroup { Name = "Vaccines & Immunizations" },
new ProductGroup { Name = "Medical & Surgical Supplies" },
new ProductGroup { Name = "Diagnostic Instruments" },
new ProductGroup { Name = "Laboratory Reagents" },
new ProductGroup { Name = "Personal Protective Equipment (PPE)" },
new ProductGroup { Name = "Wound Care & Dressings" },
new ProductGroup { Name = "Dental Supplies" },
new ProductGroup { Name = "IV Fluids & Solutions" },
new ProductGroup { Name = "General Consultations" },
new ProductGroup { Name = "Specialist Consultations" },
new ProductGroup { Name = "Laboratory Tests & Profiles" },
new ProductGroup { Name = "Radiology & Imaging" },
new ProductGroup { Name = "Minor Surgical Procedures" },
new ProductGroup { Name = "Dental Procedures" },
new ProductGroup { Name = "Physical Therapy & Rehab" },
new ProductGroup { Name = "Emergency Care Services" },
new ProductGroup { Name = "Maternal & Child Health" },
new ProductGroup { Name = "Medical Checkup Packages" }
};
foreach (var productGroup in productGroups)
{
await context.ProductGroup.AddAsync(productGroup);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,264 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class ProductSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Product.AnyAsync()) return;
var productGroups = await context.ProductGroup.ToListAsync();
var measureId = await context.UnitMeasure
.Where(x => x.Name == "unit")
.Select(x => x.Id)
.FirstOrDefaultAsync();
if (string.IsNullOrEmpty(measureId)) return;
var groupMapping = productGroups
.Where(pg => !string.IsNullOrEmpty(pg.Name) && !string.IsNullOrEmpty(pg.Id))
.ToDictionary(pg => pg.Name!, pg => pg.Id!);
var entityName = nameof(Product);
var products = new List<Product>();
products.Add(new Product { Name = "Amoxicillin 500mg", UnitPrice = 15m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Metformin 500mg", UnitPrice = 12m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Lisinopril 10mg", UnitPrice = 18m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Atorvastatin 20mg", UnitPrice = 25m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Levothyroxine 50mcg", UnitPrice = 20m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Azithromycin 250mg", UnitPrice = 30m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Omeprazole 20mg", UnitPrice = 22m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Amlodipine 5mg", UnitPrice = 16m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Sertraline 50mg", UnitPrice = 28m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Losartan 50mg", UnitPrice = 19m, ProductGroupId = groupMapping["Prescription Medications"] });
products.Add(new Product { Name = "Paracetamol 500mg", UnitPrice = 5m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Ibuprofen 400mg", UnitPrice = 8m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Cetirizine 10mg", UnitPrice = 10m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Loratadine 10mg", UnitPrice = 11m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Aspirin 81mg", UnitPrice = 7m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Loperamide 2mg", UnitPrice = 9m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Diphenhydramine 25mg", UnitPrice = 8m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Guaifenesin Syrup 200ml", UnitPrice = 15m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Antacid Tablets", UnitPrice = 6m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Hydrocortisone Cream 1%", UnitPrice = 12m, ProductGroupId = groupMapping["Over-the-Counter (OTC) Drugs"] });
products.Add(new Product { Name = "Influenza Vaccine", UnitPrice = 35m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Hepatitis B Vaccine", UnitPrice = 45m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Tetanus Toxoid", UnitPrice = 25m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "HPV Vaccine", UnitPrice = 150m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "MMR Vaccine", UnitPrice = 65m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Pneumococcal Vaccine", UnitPrice = 85m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Varicella Vaccine", UnitPrice = 75m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "COVID-19 Booster", UnitPrice = 40m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Rabies Vaccine", UnitPrice = 120m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Typhoid Vaccine", UnitPrice = 55m, ProductGroupId = groupMapping["Vaccines & Immunizations"] });
products.Add(new Product { Name = "Sterile Syringes 5ml", UnitPrice = 2m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Surgical Scalpel Blades", UnitPrice = 5m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Suture Needles Size 3-0", UnitPrice = 12m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Medical Tourniquet", UnitPrice = 8m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Catheters 14FG", UnitPrice = 15m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Surgical Scissors", UnitPrice = 25m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Tissue Forceps", UnitPrice = 20m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Endotracheal Tubes", UnitPrice = 30m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Oxygen Masks Adult", UnitPrice = 10m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Surgical Tape", UnitPrice = 4m, ProductGroupId = groupMapping["Medical & Surgical Supplies"] });
products.Add(new Product { Name = "Digital Sphygmomanometer", UnitPrice = 85m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Medical Stethoscope", UnitPrice = 120m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Infrared Thermometer", UnitPrice = 45m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Pulse Oximeter", UnitPrice = 35m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Diagnostic Otoscope", UnitPrice = 150m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Ophthalmoscope", UnitPrice = 200m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Tuning Fork Set", UnitPrice = 40m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Neurological Reflex Hammer", UnitPrice = 15m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "ECG Electrodes 50pcs", UnitPrice = 25m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Glucometer Kit", UnitPrice = 60m, ProductGroupId = groupMapping["Diagnostic Instruments"] });
products.Add(new Product { Name = "Blood Grouping Reagents", UnitPrice = 45m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Glucose Test Strips 50s", UnitPrice = 25m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Urine Test Strips 10-Param", UnitPrice = 20m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Cholesterol Reagent Kit", UnitPrice = 55m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Hematology Stain", UnitPrice = 35m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Pregnancy Test Cassettes", UnitPrice = 15m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "CRP Latex Agglutination Kit", UnitPrice = 40m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "HbA1c Reagent", UnitPrice = 65m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "HIV Rapid Test Kits", UnitPrice = 50m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "Malaria Antigen Rapid Test", UnitPrice = 30m, ProductGroupId = groupMapping["Laboratory Reagents"] });
products.Add(new Product { Name = "N95 Respirator Masks", UnitPrice = 25m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Surgical Masks 3-Ply Box", UnitPrice = 10m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Nitrile Examination Gloves", UnitPrice = 15m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Latex Surgical Gloves", UnitPrice = 18m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Medical Face Shields", UnitPrice = 8m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Disposable Isolation Gowns", UnitPrice = 20m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Surgical Bouffant Caps", UnitPrice = 5m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Shoe Covers Box", UnitPrice = 12m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Protective Safety Goggles", UnitPrice = 15m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Biohazard Protective Suits", UnitPrice = 45m, ProductGroupId = groupMapping["Personal Protective Equipment (PPE)"] });
products.Add(new Product { Name = "Sterile Gauze Pads 4x4", UnitPrice = 6m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Cotton Wool Roll 500g", UnitPrice = 8m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Crepe Bandage 4 inch", UnitPrice = 5m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Fabric Adhesive Bandages", UnitPrice = 4m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Povidone-Iodine Solution", UnitPrice = 12m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Hydrogen Peroxide 3%", UnitPrice = 7m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Silver Sulfadiazine Cream", UnitPrice = 18m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Transparent Film Dressing", UnitPrice = 25m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Hydrocolloid Dressing", UnitPrice = 30m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Medical Plaster Cast Roll", UnitPrice = 15m, ProductGroupId = groupMapping["Wound Care & Dressings"] });
products.Add(new Product { Name = "Disposable Dental Mirror", UnitPrice = 15m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Dental Explorer Probes", UnitPrice = 22m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Alginate Impression Material", UnitPrice = 35m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Composite Resin Syringe", UnitPrice = 45m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Sterile Dental Needles", UnitPrice = 18m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Local Anesthetic Carpules", UnitPrice = 55m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Saliva Ejectors 100pcs", UnitPrice = 12m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Waterproof Dental Bibs", UnitPrice = 20m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Fluoride Varnish 50pk", UnitPrice = 75m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Orthodontic Metal Brackets", UnitPrice = 120m, ProductGroupId = groupMapping["Dental Supplies"] });
products.Add(new Product { Name = "Normal Saline 0.9% 500ml", UnitPrice = 3m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Lactated Ringer's Solution", UnitPrice = 4m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Dextrose 5% Water 500ml", UnitPrice = 3.5m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Dextrose 5% in Normal Saline", UnitPrice = 4.5m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Hartmann's Solution 500ml", UnitPrice = 5m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Sterile Water for Injection", UnitPrice = 2m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Mannitol 20% Infusion", UnitPrice = 12m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Potassium Chloride Injection", UnitPrice = 8m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Calcium Gluconate 10%", UnitPrice = 10m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Amino Acid Solution 500ml", UnitPrice = 25m, ProductGroupId = groupMapping["IV Fluids & Solutions"] });
products.Add(new Product { Name = "Initial GP Consultation", UnitPrice = 50m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Follow-up Visit", UnitPrice = 35m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Telemedicine Consultation", UnitPrice = 40m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Walk-in Clinic Visit", UnitPrice = 45m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Medical Certificate Issuance", UnitPrice = 20m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Prescription Refill Visit", UnitPrice = 25m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Preventive Health Advice", UnitPrice = 55m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Chronic Disease Management", UnitPrice = 65m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Nutritional Advice Session", UnitPrice = 60m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Travel Medicine Consultation", UnitPrice = 45m, Physical = false, ProductGroupId = groupMapping["General Consultations"] });
products.Add(new Product { Name = "Cardiology Consultation", UnitPrice = 150m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Dermatology Assessment", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Orthopedic Evaluation", UnitPrice = 140m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Neurologist Visit", UnitPrice = 180m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Pediatrician Consultation", UnitPrice = 100m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "OBGYN Consultation", UnitPrice = 130m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Gastroenterology Assessment", UnitPrice = 160m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "ENT Specialist Visit", UnitPrice = 110m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Psychiatric Evaluation", UnitPrice = 175m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Ophthalmologist Consultation", UnitPrice = 125m, Physical = false, ProductGroupId = groupMapping["Specialist Consultations"] });
products.Add(new Product { Name = "Complete Blood Count (CBC)", UnitPrice = 25m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Comprehensive Metabolic Panel", UnitPrice = 45m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Lipid Profile Test", UnitPrice = 30m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Thyroid Function Test", UnitPrice = 55m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Liver Function Test", UnitPrice = 40m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Fasting Blood Sugar", UnitPrice = 15m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Routine Urinalysis", UnitPrice = 20m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Vitamin D Level Test", UnitPrice = 65m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Prostate Specific Antigen", UnitPrice = 50m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Pap Smear Analysis", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Laboratory Tests & Profiles"] });
products.Add(new Product { Name = "Chest X-Ray 2 Views", UnitPrice = 65m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Abdominal Ultrasound", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Pelvic Ultrasound", UnitPrice = 110m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "MRI Brain w/o Contrast", UnitPrice = 550m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "CT Scan Abdomen", UnitPrice = 450m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "DEXA Bone Density Scan", UnitPrice = 150m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Screening Mammogram", UnitPrice = 175m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "2D Echocardiogram", UnitPrice = 250m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Venous Doppler Ultrasound", UnitPrice = 195m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Dental Panoramic X-Ray", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Radiology & Imaging"] });
products.Add(new Product { Name = "Laceration Repair Complex", UnitPrice = 150m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Mole Excision & Biopsy", UnitPrice = 180m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Ingrown Toenail Removal", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Abscess Incision & Drainage", UnitPrice = 140m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Sebaceous Cyst Removal", UnitPrice = 200m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Wart Cryotherapy Session", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Joint Aspiration Injection", UnitPrice = 165m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Foreign Body Removal", UnitPrice = 130m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Diagnostic Skin Biopsy", UnitPrice = 110m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Suture Removal Visit", UnitPrice = 45m, Physical = false, ProductGroupId = groupMapping["Minor Surgical Procedures"] });
products.Add(new Product { Name = "Routine Dental Cleaning", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Simple Tooth Extraction", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Composite Dental Filling", UnitPrice = 150m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Root Canal Treatment", UnitPrice = 650m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Porcelain Crown Prep", UnitPrice = 850m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Professional Teeth Whitening", UnitPrice = 250m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Fluoride Varnish Treatment", UnitPrice = 50m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Partial Denture Fitting", UnitPrice = 450m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Orthodontic Adjustment", UnitPrice = 95m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Periodontal Deep Scaling", UnitPrice = 220m, Physical = false, ProductGroupId = groupMapping["Dental Procedures"] });
products.Add(new Product { Name = "Initial PT Assessment", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Post-Op Rehab Session", UnitPrice = 95m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Sports Injury Therapy", UnitPrice = 110m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Postural Correction Program", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Ultrasound Therapy Session", UnitPrice = 65m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "TENS Therapy Treatment", UnitPrice = 55m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Neurological Gait Training", UnitPrice = 130m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Manual Therapy & Massage", UnitPrice = 90m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Pediatric Physiotherapy", UnitPrice = 115m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "Stroke Rehab Session", UnitPrice = 140m, Physical = false, ProductGroupId = groupMapping["Physical Therapy & Rehab"] });
products.Add(new Product { Name = "ER Triage & Assessment", UnitPrice = 250m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Emergency Resuscitation", UnitPrice = 1500m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Major Trauma Care", UnitPrice = 2500m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Acute Burn Management", UnitPrice = 350m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Fracture Reduction & Splint", UnitPrice = 450m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Acute Asthma Nebulization", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Gastric Lavage Washout", UnitPrice = 280m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Anaphylaxis IV Treatment", UnitPrice = 300m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Emergency Blood Transfusion", UnitPrice = 650m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Cardiac Arrest Protocol", UnitPrice = 2000m, Physical = false, ProductGroupId = groupMapping["Emergency Care Services"] });
products.Add(new Product { Name = "Antenatal Checkup Visit", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Postnatal Care Consultation", UnitPrice = 95m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Well-Baby Examination", UnitPrice = 75m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Childhood Immunization Visit", UnitPrice = 45m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Lactation Consulting", UnitPrice = 110m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Pediatric Growth Monitoring", UnitPrice = 60m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Neonatal Jaundice Screen", UnitPrice = 55m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Gestational Diabetes Screen", UnitPrice = 65m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Fetal Heart Monitoring CTG", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Family Planning Consult", UnitPrice = 50m, Physical = false, ProductGroupId = groupMapping["Maternal & Child Health"] });
products.Add(new Product { Name = "Basic Health Screening", UnitPrice = 150m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Comprehensive Exec Checkup", UnitPrice = 450m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Pre-Employment Medical Exam", UnitPrice = 120m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Cardiac Wellness Package", UnitPrice = 350m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Diabetic Care Package", UnitPrice = 220m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Women's Health Checkup", UnitPrice = 280m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Men's Health Screening", UnitPrice = 250m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Senior Citizen Health Pack", UnitPrice = 300m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Student Health Clearance", UnitPrice = 85m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
products.Add(new Product { Name = "Premarital Screening Test", UnitPrice = 180m, Physical = false, ProductGroupId = groupMapping["Medical Checkup Packages"] });
foreach (var product in products)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
product.AutoNumber = autoNo;
product.UnitMeasureId = measureId;
product.Physical ??= true;
await context.Product.AddAsync(product);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,112 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PurchaseOrderSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PurchaseOrder.AnyAsync()) return;
var random = new Random();
var entityName = nameof(PurchaseOrder);
var vendors = await context.Vendor.Select(x => x.Id).ToListAsync();
var taxes = await context.Tax.Select(x => x.Id).ToListAsync();
var products = await context.Product.ToListAsync();
if (!vendors.Any() || !taxes.Any() || !products.Any()) return;
var allStatusValues = Enum.GetValues(typeof(PurchaseOrderStatus))
.Cast<PurchaseOrderStatus>()
.ToList();
var nonConfirmedStatusValues = allStatusValues
.Where(x => x != PurchaseOrderStatus.Confirmed)
.ToList();
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] transactionDates = GetRandomDays(date.Year, date.Month, 6);
foreach (DateTime transDate in transactionDates)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
PurchaseOrderStatus selectedStatus;
int probability = random.Next(1, 101);
if (probability <= 90)
{
selectedStatus = PurchaseOrderStatus.Confirmed;
}
else
{
selectedStatus = nonConfirmedStatusValues[random.Next(nonConfirmedStatusValues.Count)];
}
var purchaseOrder = new PurchaseOrder
{
AutoNumber = autoNo,
OrderDate = transDate,
OrderStatus = selectedStatus,
VendorId = GetRandomValue(vendors, random),
TaxId = GetRandomValue(taxes, random),
};
await context.PurchaseOrder.AddAsync(purchaseOrder);
int numberOfProducts = random.Next(3, 6);
for (int i = 0; i < numberOfProducts; i++)
{
var product = products[random.Next(products.Count)];
var quantity = random.Next(20, 50);
var purchaseOrderItem = new PurchaseOrderItem
{
PurchaseOrderId = purchaseOrder.Id,
ProductId = product.Id,
Summary = product.AutoNumber,
UnitPrice = product.UnitPrice,
Quantity = (double)quantity,
Total = product.UnitPrice * (decimal)quantity
};
await context.PurchaseOrderItem.AddAsync(purchaseOrderItem);
}
await context.SaveChangesAsync();
context.RecalculatePurchaseOrder(purchaseOrder.Id);
await context.SaveChangesAsync();
}
}
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,29 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class SalesOrderCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.SalesOrderCategory.AnyAsync()) return;
var salesOrderCategories = new List<SalesOrderCategory>
{
new SalesOrderCategory { Name = "Self-Pay / Out-of-Pocket" },
new SalesOrderCategory { Name = "Private Health Insurance" },
new SalesOrderCategory { Name = "Government Insurance" },
new SalesOrderCategory { Name = "Corporate Partner / B2B" },
new SalesOrderCategory { Name = "Employee Benefit" },
new SalesOrderCategory { Name = "Charity / Pro-Bono" }
};
foreach (var category in salesOrderCategories)
{
await context.SalesOrderCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,30 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class SalesOrderGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.SalesOrderGroup.AnyAsync()) return;
var salesOrderGroups = new List<SalesOrderGroup>
{
new SalesOrderGroup { Name = "Inpatient" },
new SalesOrderGroup { Name = "Outpatient" },
new SalesOrderGroup { Name = "Emergency Care" },
new SalesOrderGroup { Name = "Telemedicine" },
new SalesOrderGroup { Name = "Medical Check-Up" },
new SalesOrderGroup { Name = "Home Care Services" },
new SalesOrderGroup { Name = "Day Care / Day Surgery" }
};
foreach (var group in salesOrderGroups)
{
await context.SalesOrderGroup.AddAsync(group);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,114 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class SalesOrderSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.SalesOrder.AnyAsync()) return;
var random = new Random();
var entityName = nameof(SalesOrder);
var customers = await context.Patient.Select(x => x.Id).ToListAsync();
var employees = await context.Employee.Select(x => x.Id).ToListAsync();
var taxes = await context.Tax.Select(x => x.Id).ToListAsync();
var products = await context.Product.ToListAsync();
var orderGroups = await context.SalesOrderGroup.Select(x => x.Id).ToListAsync();
var orderCategories = await context.SalesOrderCategory.Select(x => x.Id).ToListAsync();
if (!customers.Any() || !employees.Any() || !taxes.Any() || !products.Any() || !orderGroups.Any() || !orderCategories.Any()) return;
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] transactionDates = GetRandomDays(date.Year, date.Month, 6);
foreach (DateTime transDate in transactionDates)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var salesOrder = new SalesOrder
{
AutoNumber = autoNo,
OrderDate = transDate,
OrderStatus = GetHighProbabilityStatus(random),
CustomerId = GetRandomValue(customers, random),
EmployeeId = GetRandomValue(employees, random),
TaxId = GetRandomValue(taxes, random),
SalesOrderGroupId = GetRandomValue(orderGroups, random),
SalesOrderCategoryId = GetRandomValue(orderCategories, random)
};
await context.SalesOrder.AddAsync(salesOrder);
int numberOfProducts = random.Next(3, 6);
for (int i = 0; i < numberOfProducts; i++)
{
var qty = (double)random.Next(2, 5);
var product = products[random.Next(products.Count)];
var salesOrderItem = new SalesOrderItem
{
SalesOrderId = salesOrder.Id,
ProductId = product.Id,
Summary = product.AutoNumber,
UnitPrice = product.UnitPrice,
Quantity = qty,
Total = (product.UnitPrice ?? 0m) * (decimal)qty
};
await context.SalesOrderItem.AddAsync(salesOrderItem);
}
await context.SaveChangesAsync();
context.RecalculateSalesOrder(salesOrder.Id);
await context.SaveChangesAsync();
}
}
}
private static SalesOrderStatus GetHighProbabilityStatus(Random random)
{
int probability = random.Next(1, 101);
if (probability <= 90)
{
return SalesOrderStatus.Confirmed;
}
else
{
var otherStatuses = new[] { SalesOrderStatus.Draft, SalesOrderStatus.Cancelled, SalesOrderStatus.Archived };
return otherStatuses[random.Next(otherStatuses.Length)];
}
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
private static DateTime[] GetRandomDays(int year, int month, int count)
{
var random = new Random();
int daysInMonthCount = DateTime.DaysInMonth(year, month);
var daysInMonth = Enumerable.Range(1, daysInMonthCount).ToList();
var selectedDays = new List<int>();
for (int i = 0; i < count && daysInMonth.Count > 0; i++)
{
int day = daysInMonth[random.Next(daysInMonth.Count)];
selectedDays.Add(day);
daysInMonth.Remove(day);
}
return selectedDays.Select(day => new DateTime(year, month, day)).ToArray();
}
}
@@ -0,0 +1,29 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class UnitMeasureSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.UnitMeasure.AnyAsync()) return;
var unitMeasures = new List<UnitMeasure>
{
new UnitMeasure { Name = "m" },
new UnitMeasure { Name = "kg" },
new UnitMeasure { Name = "hour" },
new UnitMeasure { Name = "unit" },
new UnitMeasure { Name = "pcs" },
new UnitMeasure { Name = "package" }
};
foreach (var unitMeasure in unitMeasures)
{
await context.UnitMeasure.AddAsync(unitMeasure);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,54 @@
using DocumentFormat.OpenXml.InkML;
using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Infrastructure.Authorization.Identity;
using Microsoft.AspNetCore.Identity;
namespace Indotalent.Infrastructure.Database.Demo;
public static class UserSeeder
{
public static async Task GenerateDataAsync(UserManager<ApplicationUser> userManager, AppDbContext context, IConfiguration configuration)
{
var adminSettings = configuration.GetSection("IdentitySettings:DefaultAdmin").Get<DefaultAdminSettings>();
if (adminSettings == null) return;
if (context.Users.Where(x => x.Email != adminSettings.Email).Any()) return;
var userNames = new List<string>
{
"Alex", "Taylor", "Jordan", "Morgan", "Riley",
"Casey", "Peyton", "Cameron", "Jamie", "Drew",
"Dakota", "Avery", "Quinn", "Harper", "Rowan",
"Emerson", "Finley", "Skyler", "Charlie", "Sage"
};
var defaultPassword = "123456";
var domain = "@example.com";
var role = ApplicationRoles.Member;
foreach (var name in userNames)
{
var email = $"{name.ToLower()}{domain}";
if (await userManager.FindByEmailAsync(email) == null)
{
var applicationUser = new ApplicationUser
{
UserName = email,
Email = email,
FullName = name,
EmailConfirmed = true
};
var result = await userManager.CreateAsync(applicationUser, defaultPassword);
if (result.Succeeded)
{
await userManager.AddToRoleAsync(applicationUser, role);
}
}
}
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class VendorCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.VendorCategory.AnyAsync()) return;
var vendorCategories = new List<VendorCategory>
{
new VendorCategory { Name = "Principal Manufacturer" },
new VendorCategory { Name = "Authorized Medical Distributor" },
new VendorCategory { Name = "Local Pharmacy Partner" },
new VendorCategory { Name = "Clinical Service Provider" },
new VendorCategory { Name = "General Wholesale Supplier" },
new VendorCategory { Name = "Emergency Medical Supplier" },
new VendorCategory { Name = "Maintenance & Support Vendor" },
new VendorCategory { Name = "Government Health Agency" },
new VendorCategory { Name = "Contracted Service Provider" },
new VendorCategory { Name = "Outsourced Diagnostic Center" }
};
foreach (var category in vendorCategories)
{
await context.VendorCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,75 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class VendorContactSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.VendorContact.AnyAsync()) return;
var firstNames = new string[]
{
"James", "Mary", "Robert", "Patricia", "John", "Jennifer",
"Michael", "Linda", "David", "Elizabeth", "William", "Barbara",
"Richard", "Susan", "Joseph", "Jessica", "Thomas", "Sarah",
"Charles", "Karen"
};
var lastNames = new string[]
{
"Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia",
"Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez",
"Gonzalez", "Wilson", "Anderson", "Thomas", "Taylor", "Moore",
"Jackson", "Martin"
};
var jobTitles = new string[]
{
"Pharma Account Executive", "Medical Equipment Specialist", "Clinical Support Representative", "Healthcare Supply Chain Manager",
"Biomedical Engineer Consultant", "Laboratory Products Manager", "Medical Devices Sales Director", "Healthcare Procurement Specialist",
"Consumables Account Manager", "Surgical Supplies Coordinator", "Pharmacy Relations Manager", "Diagnostic Tech Lead",
"Dental Products Representative", "Radiology Equipment Consultant", "Hospitality & Linens Coordinator", "Medical IT Solutions Architect",
"Healthcare Logistics Director", "Regulatory Compliance Manager", "Infection Control Product Lead", "Emergency Supplies Account Exec"
};
var vendorIds = await context.Vendor.Select(x => x.Id).ToListAsync();
var random = new Random();
var entityName = nameof(VendorContact);
foreach (var vendorId in vendorIds)
{
for (int i = 0; i < 3; i++)
{
var firstName = GetRandomString(firstNames, random);
var lastName = GetRandomString(lastNames, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var contact = new VendorContact
{
Name = $"{firstName} {lastName}",
AutoNumber = autoNo,
VendorId = vendorId,
JobTitle = GetRandomString(jobTitles, random),
EmailAddress = $"{firstName.ToLower()}.{lastName.ToLower()}@med-supplier.example.com",
PhoneNumber = $"+1-{random.Next(200, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}"
};
await context.VendorContact.AddAsync(contact);
}
}
await context.SaveChangesAsync();
}
private static string GetRandomString(string[] array, Random random)
{
return array[random.Next(array.Length)];
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class VendorGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.VendorGroup.AnyAsync()) return;
var vendorGroups = new List<VendorGroup>
{
new VendorGroup { Name = "Pharmaceuticals & Medications" },
new VendorGroup { Name = "Medical Equipment & Instruments" },
new VendorGroup { Name = "Laboratory Supplies & Reagents" },
new VendorGroup { Name = "Consumables & Disposables" },
new VendorGroup { Name = "Medical Waste Management" },
new VendorGroup { Name = "Uniforms & Medical Linens" },
new VendorGroup { Name = "Cleaning & Hygiene Supplies" },
new VendorGroup { Name = "Facility Maintenance Services" },
new VendorGroup { Name = "IT & Software Services" },
new VendorGroup { Name = "Office & Administrative Supplies" }
};
foreach (var group in vendorGroups)
{
await context.VendorGroup.AddAsync(group);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,82 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class VendorSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Vendor.AnyAsync()) return;
var groups = await context.VendorGroup.Select(x => x.Id).ToArrayAsync();
var categories = await context.VendorCategory.Select(x => x.Id).ToArrayAsync();
var cities = new string[] { "New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia", "Miami", "San Francisco", "Seattle", "Austin" };
var streets = new string[] { "Medical Center Blvd", "Healthway Drive", "Innovation Road", "Science Park Ave", "Clinical Way", "Wellness Blvd", "Recovery Street", "Research Lane", "Care Avenue", "Pharma Street" };
var states = new string[] { "NY", "CA", "IL", "TX", "AZ", "PA", "FL", "GA", "WA", "MA" };
var zipCodes = new string[] { "10001", "90210", "60601", "77001", "85001", "19101", "33101", "94102", "98101", "73301" };
var phoneNumbers = new string[] { "212-555-0199", "310-555-0188", "312-555-0177", "713-555-0166", "602-555-0155", "305-555-0144" };
var emails = new string[] { "sales@med-supply.com", "info@pharmadistribution.net", "contact@healthequip.com", "support@biotechlabs.us", "wholesale@medinstruments.com" };
var random = new Random();
var entityName = nameof(Vendor);
var vendors = new List<Vendor>
{
new Vendor { Name = "MediTech Solutions" },
new Vendor { Name = "Global Pharma Network" },
new Vendor { Name = "CarePlus Medical Supplies" },
new Vendor { Name = "Apex Health Instruments" },
new Vendor { Name = "LifeLine Diagnostic Labs" },
new Vendor { Name = "SterileMed Consumables" },
new Vendor { Name = "NovaCare Equipment" },
new Vendor { Name = "HealthGuard Systems" },
new Vendor { Name = "BioGenix Pharmaceuticals" },
new Vendor { Name = "Prime Medical Devices" },
new Vendor { Name = "VitalSign Technologies" },
new Vendor { Name = "Surgical Precision Inc." },
new Vendor { Name = "ClinicCore Furniture" },
new Vendor { Name = "MedTex Linens & Uniforms" },
new Vendor { Name = "Aura Medical Software" },
new Vendor { Name = "SafeWaste Management" },
new Vendor { Name = "ProHealth Dental Supplies" },
new Vendor { Name = "ClearView Radiology Tech" },
new Vendor { Name = "SanitizePro Chemicals" },
new Vendor { Name = "FirstAid Emergency Kits" }
};
foreach (var vendor in vendors)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
vendor.AutoNumber = autoNo;
vendor.VendorGroupId = GetRandomValue(groups, random);
vendor.VendorCategoryId = GetRandomValue(categories, random);
vendor.City = GetRandomString(cities, random);
vendor.Street = GetRandomString(streets, random);
vendor.State = GetRandomString(states, random);
vendor.ZipCode = GetRandomString(zipCodes, random);
vendor.PhoneNumber = GetRandomString(phoneNumbers, random);
vendor.EmailAddress = GetRandomString(emails, random);
await context.Vendor.AddAsync(vendor);
}
await context.SaveChangesAsync();
}
private static T GetRandomValue<T>(T[] array, Random random)
{
return array[random.Next(array.Length)];
}
private static string GetRandomString(string[] array, Random random)
{
return array[random.Next(array.Length)];
}
}
@@ -0,0 +1,33 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class WarehouseSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Warehouse.Where(x => x.SystemWarehouse == false).AnyAsync()) return;
var warehouses = new List<Warehouse>
{
new Warehouse { Name = "Main Pharmacy" },
new Warehouse { Name = "Central Supply Room" },
new Warehouse { Name = "Laboratory" },
new Warehouse { Name = "Emergency Room Storage" },
new Warehouse { Name = "General Practice Room" },
new Warehouse { Name = "Dental Clinic Storage" },
new Warehouse { Name = "Radiology Department" },
new Warehouse { Name = "Pediatrics Ward" },
new Warehouse { Name = "Surgical Suite Storage" },
new Warehouse { Name = "Maternity Ward" }
};
foreach (var warehouse in warehouses)
{
await context.Warehouse.AddAsync(warehouse);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,68 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class ApplicationUserConfiguration : IEntityTypeConfiguration<ApplicationUser>
{
public void Configure(EntityTypeBuilder<ApplicationUser> builder)
{
builder.Property(e => e.FullName).HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.SsoIdFirebase).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdKeycloak).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdAzure).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdAws).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdOther1).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdOther2).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SsoIdOther3).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.AvatarFile).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.RefreshToken).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.FirstName).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.LastName).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.ShortBio).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.JobTitle).HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.StreetAddress)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.City)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.StateProvince)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ZipCode)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Country)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.SocialMediaLinkedIn)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaX)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaFacebook)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaInstagram)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaTikTok)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation1)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation2)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation3)
.HasMaxLength(GlobalConsts.StringLengthMedium);
}
}
@@ -0,0 +1,25 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class AutoNumberSequenceConfiguration : IEntityTypeConfiguration<AutoNumberSequence>
{
public void Configure(EntityTypeBuilder<AutoNumberSequence> builder)
{
builder.Property(e => e.EntityName)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PrefixTemplate)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.SuffixTemplate)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.HasIndex(e => new { e.EntityName, e.Year, e.Month })
.IsUnique();
}
}
@@ -0,0 +1,30 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class BillConfiguration : IEntityTypeConfiguration<Bill>
{
public void Configure(EntityTypeBuilder<Bill> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PurchaseOrderId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.PurchaseOrder)
.WithMany()
.HasForeignKey(e => e.PurchaseOrderId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.BillDate);
builder.HasIndex(e => e.PurchaseOrderId);
}
}
@@ -0,0 +1,53 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class BookingConfiguration : IEntityTypeConfiguration<Booking>
{
public void Configure(EntityTypeBuilder<Booking> builder)
{
builder.Property(e => e.Subject)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.StartTimezone)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EndTimezone)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Location)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.RecurrenceRule)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.RecurrenceID)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.FollowingID)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.RecurrenceException)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.BookingResourceId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.BookingResource)
.WithMany()
.HasForeignKey(e => e.BookingResourceId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.BookingResourceId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class BookingGroupConfiguration : IEntityTypeConfiguration<BookingGroup>
{
public void Configure(EntityTypeBuilder<BookingGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,29 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class BookingResourceConfiguration : IEntityTypeConfiguration<BookingResource>
{
public void Configure(EntityTypeBuilder<BookingResource> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.BookingGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.BookingGroup)
.WithMany()
.HasForeignKey(e => e.BookingGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.BookingGroupId);
}
}
@@ -0,0 +1,87 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class CompanyConfiguration : IEntityTypeConfiguration<Company>
{
public void Configure(EntityTypeBuilder<Company> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.CurrencyId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Currency)
.WithMany()
.HasForeignKey(e => e.CurrencyId)
.OnDelete(DeleteBehavior.NoAction);
builder.Property(e => e.TaxIdentification)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.BusinessLicense)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.CompanyLogo)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.StreetAddress)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.City)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.StateProvince)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ZipCode)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Phone)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Email)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.SocialMediaLinkedIn)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaX)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaFacebook)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaInstagram)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SocialMediaTikTok)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation1)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation2)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.OtherInformation3)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.Email);
builder.HasIndex(e => e.CurrencyId);
}
}
@@ -0,0 +1,36 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class CurrencyConfiguration : IEntityTypeConfiguration<Currency>
{
public void Configure(EntityTypeBuilder<Currency> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Code)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Symbol)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.CountryOwner)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.Code).IsUnique();
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class EmployeeCategoryConfiguration : IEntityTypeConfiguration<EmployeeCategory>
{
public void Configure(EntityTypeBuilder<EmployeeCategory> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,94 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
{
public void Configure(EntityTypeBuilder<Employee> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.JobTitle)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmployeeNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.Street)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.City)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.State)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ZipCode)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Country)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PhoneNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.FaxNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmailAddress)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Website)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.WhatsApp)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.LinkedIn)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Facebook)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Instagram)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.TwitterX)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.TikTok)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmployeeGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.EmployeeCategoryId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.EmployeeGroup)
.WithMany()
.HasForeignKey(e => e.EmployeeGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.EmployeeCategory)
.WithMany()
.HasForeignKey(e => e.EmployeeCategoryId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.EmployeeNumber).IsUnique();
builder.HasIndex(e => e.EmployeeGroupId);
builder.HasIndex(e => e.EmployeeCategoryId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class EmployeeGroupConfiguration : IEntityTypeConfiguration<EmployeeGroup>
{
public void Configure(EntityTypeBuilder<EmployeeGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,64 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class InventoryTransactionConfiguration : IEntityTypeConfiguration<InventoryTransaction>
{
public void Configure(EntityTypeBuilder<InventoryTransaction> builder)
{
builder.Property(e => e.ModuleId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ModuleName)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ModuleCode)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ModuleNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.WarehouseId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ProductId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.WarehouseFromId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.WarehouseToId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Warehouse)
.WithMany()
.HasForeignKey(e => e.WarehouseId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Product)
.WithMany()
.HasForeignKey(e => e.ProductId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.WarehouseFrom)
.WithMany()
.HasForeignKey(e => e.WarehouseFromId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.WarehouseTo)
.WithMany()
.HasForeignKey(e => e.WarehouseToId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.MovementDate);
builder.HasIndex(e => e.WarehouseId);
builder.HasIndex(e => e.ProductId);
}
}
@@ -0,0 +1,30 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class InvoiceConfiguration : IEntityTypeConfiguration<Invoice>
{
public void Configure(EntityTypeBuilder<Invoice> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SalesOrderId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.SalesOrder)
.WithMany()
.HasForeignKey(e => e.SalesOrderId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.InvoiceDate);
builder.HasIndex(e => e.SalesOrderId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class MedicalRecordCategoryConfiguration : IEntityTypeConfiguration<MedicalRecordCategory>
{
public void Configure(EntityTypeBuilder<MedicalRecordCategory> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,83 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class MedicalRecordConfiguration : IEntityTypeConfiguration<MedicalRecord>
{
public void Configure(EntityTypeBuilder<MedicalRecord> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Subjective)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Objective)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Assessment)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Planning)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.BloodPressure)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Temperature)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.HeartRate)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Weight)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Height)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PatientId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.EmployeeId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.MedicalRecordGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.MedicalRecordCategoryId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Patient)
.WithMany()
.HasForeignKey(e => e.PatientId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Employee)
.WithMany()
.HasForeignKey(e => e.EmployeeId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.MedicalRecordGroup)
.WithMany()
.HasForeignKey(e => e.MedicalRecordGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.MedicalRecordCategory)
.WithMany()
.HasForeignKey(e => e.MedicalRecordCategoryId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.RecordDate);
builder.HasIndex(e => e.PatientId);
builder.HasIndex(e => e.EmployeeId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class MedicalRecordGroupConfiguration : IEntityTypeConfiguration<MedicalRecordGroup>
{
public void Configure(EntityTypeBuilder<MedicalRecordGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PatientCategoryConfiguration : IEntityTypeConfiguration<PatientCategory>
{
public void Configure(EntityTypeBuilder<PatientCategory> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,87 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PatientConfiguration : IEntityTypeConfiguration<Patient>
{
public void Configure(EntityTypeBuilder<Patient> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.Street)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.City)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.State)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.ZipCode)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Country)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PhoneNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.FaxNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmailAddress)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Website)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.WhatsApp)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.LinkedIn)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Facebook)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Instagram)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.TwitterX)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.TikTok)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PatientGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.PatientCategoryId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.PatientGroup)
.WithMany()
.HasForeignKey(e => e.PatientGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.PatientCategory)
.WithMany()
.HasForeignKey(e => e.PatientCategoryId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.PatientGroupId);
builder.HasIndex(e => e.PatientCategoryId);
}
}
@@ -0,0 +1,42 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PatientContactConfiguration : IEntityTypeConfiguration<PatientContact>
{
public void Configure(EntityTypeBuilder<PatientContact> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Title)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PhoneNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmailAddress)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PatientId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Patient)
.WithMany(e => e.PatientContactList)
.HasForeignKey(e => e.PatientId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.PatientId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PatientGroupConfiguration : IEntityTypeConfiguration<PatientGroup>
{
public void Configure(EntityTypeBuilder<PatientGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,39 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PaymentDisburseConfiguration : IEntityTypeConfiguration<PaymentDisburse>
{
public void Configure(EntityTypeBuilder<PaymentDisburse> builder)
{
builder.Property(e => e.BillId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PaymentMethodId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Bill)
.WithMany()
.HasForeignKey(e => e.BillId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.PaymentMethod)
.WithMany()
.HasForeignKey(e => e.PaymentMethodId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.BillId);
builder.HasIndex(e => e.PaymentMethodId);
builder.HasIndex(e => e.PaymentDate);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PaymentMethodConfiguration : IEntityTypeConfiguration<PaymentMethod>
{
public void Configure(EntityTypeBuilder<PaymentMethod> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,39 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PaymentReceiveConfiguration : IEntityTypeConfiguration<PaymentReceive>
{
public void Configure(EntityTypeBuilder<PaymentReceive> builder)
{
builder.Property(e => e.InvoiceId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PaymentMethodId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Invoice)
.WithMany()
.HasForeignKey(e => e.InvoiceId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.PaymentMethod)
.WithMany()
.HasForeignKey(e => e.PaymentMethodId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.InvoiceId);
builder.HasIndex(e => e.PaymentMethodId);
builder.HasIndex(e => e.PaymentDate);
}
}
@@ -0,0 +1,42 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.UnitMeasureId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ProductGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.UnitMeasure)
.WithMany()
.HasForeignKey(e => e.UnitMeasureId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.ProductGroup)
.WithMany()
.HasForeignKey(e => e.ProductGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.UnitMeasureId);
builder.HasIndex(e => e.ProductGroupId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class ProductGroupConfiguration : IEntityTypeConfiguration<ProductGroup>
{
public void Configure(EntityTypeBuilder<ProductGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,44 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PurchaseOrderConfiguration : IEntityTypeConfiguration<PurchaseOrder>
{
public void Configure(EntityTypeBuilder<PurchaseOrder> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.VendorId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.TaxId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Vendor)
.WithMany()
.HasForeignKey(e => e.VendorId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Tax)
.WithMany()
.HasForeignKey(e => e.TaxId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasMany(e => e.PurchaseOrderItemList)
.WithOne(e => e.PurchaseOrder)
.HasForeignKey(e => e.PurchaseOrderId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.OrderDate);
builder.HasIndex(e => e.VendorId);
builder.HasIndex(e => e.TaxId);
}
}
@@ -0,0 +1,34 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class PurchaseOrderItemConfiguration : IEntityTypeConfiguration<PurchaseOrderItem>
{
public void Configure(EntityTypeBuilder<PurchaseOrderItem> builder)
{
builder.Property(e => e.PurchaseOrderId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ProductId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.Summary)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.HasOne(e => e.PurchaseOrder)
.WithMany(e => e.PurchaseOrderItemList)
.HasForeignKey(e => e.PurchaseOrderId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(e => e.Product)
.WithMany()
.HasForeignKey(e => e.ProductId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.PurchaseOrderId);
builder.HasIndex(e => e.ProductId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class SalesOrderCategoryConfiguration : IEntityTypeConfiguration<SalesOrderCategory>
{
public void Configure(EntityTypeBuilder<SalesOrderCategory> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,66 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class SalesOrderConfiguration : IEntityTypeConfiguration<SalesOrder>
{
public void Configure(EntityTypeBuilder<SalesOrder> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.CustomerId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.TaxId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.SalesOrderGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.SalesOrderCategoryId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Customer)
.WithMany()
.HasForeignKey(e => e.CustomerId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Employee)
.WithMany()
.HasForeignKey(e => e.EmployeeId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Tax)
.WithMany()
.HasForeignKey(e => e.TaxId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.SalesOrderGroup)
.WithMany()
.HasForeignKey(e => e.SalesOrderGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.SalesOrderCategory)
.WithMany()
.HasForeignKey(e => e.SalesOrderCategoryId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasMany(e => e.SalesOrderItemList)
.WithOne(e => e.SalesOrder)
.HasForeignKey(e => e.SalesOrderId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.OrderDate);
builder.HasIndex(e => e.CustomerId);
builder.HasIndex(e => e.TaxId);
builder.HasIndex(e => e.EmployeeId);
}
}
@@ -0,0 +1,20 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class SalesOrderGroupConfiguration : IEntityTypeConfiguration<SalesOrderGroup>
{
public void Configure(EntityTypeBuilder<SalesOrderGroup> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,34 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class SalesOrderItemConfiguration : IEntityTypeConfiguration<SalesOrderItem>
{
public void Configure(EntityTypeBuilder<SalesOrderItem> builder)
{
builder.Property(e => e.SalesOrderId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ProductId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.Summary)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.HasOne(e => e.SalesOrder)
.WithMany(e => e.SalesOrderItemList)
.HasForeignKey(e => e.SalesOrderId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(e => e.Product)
.WithMany()
.HasForeignKey(e => e.ProductId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.SalesOrderId);
builder.HasIndex(e => e.ProductId);
}
}
@@ -0,0 +1,39 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class LogConfiguration : IEntityTypeConfiguration<SerilogLogs>
{
public void Configure(EntityTypeBuilder<SerilogLogs> builder)
{
builder.ToTable("SerilogLogs");
builder.HasKey(e => e.Id);
builder.Property(e => e.Message)
.HasMaxLength(2000);
builder.Property(e => e.Level)
.HasMaxLength(128);
builder.Property(e => e.TimeStamp)
.IsRequired();
builder.Property(e => e.Exception)
.HasColumnType("nvarchar(max)");
builder.Property(e => e.Properties)
.HasColumnType("nvarchar(max)");
builder.Property(e => e.MessageTemplate)
.HasMaxLength(2000);
builder.Property(e => e.LogEvent)
.HasColumnType("nvarchar(max)");
builder.HasIndex(e => e.TimeStamp)
.HasDatabaseName("IX_SerilogLogs_TimeStamp");
}
}
@@ -0,0 +1,36 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class TaxConfiguration : IEntityTypeConfiguration<Tax>
{
public void Configure(EntityTypeBuilder<Tax> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Code)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.PercentageValue)
.HasColumnType("decimal(18,2)");
builder.Property(e => e.Category)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.Code).IsUnique();
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,25 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class TodoConfiguration : IEntityTypeConfiguration<Todo>
{
public void Configure(EntityTypeBuilder<Todo> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.HasMany(e => e.TodoItemList)
.WithOne(e => e.Todo)
.HasForeignKey(e => e.TodoId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
}
}
@@ -0,0 +1,29 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class TodoItemConfiguration : IEntityTypeConfiguration<TodoItem>
{
public void Configure(EntityTypeBuilder<TodoItem> builder)
{
builder.Property(e => e.Name)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.TodoId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Todo)
.WithMany(e => e.TodoItemList)
.HasForeignKey(e => e.TodoId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.TodoId);
}
}

Some files were not shown because too many files have changed in this diff Show More