initial commit

This commit is contained in:
2026-07-21 14:28:43 +07:00
commit 01107db6fd
995 changed files with 75124 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;
}
}
+210
View File
@@ -0,0 +1,210 @@
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<GoodsReceive> GoodsReceive { get; set; } = default!;
public DbSet<Bill> Bill { get; set; } = default!;
public DbSet<PaymentDisburse> PaymentDisburse { get; set; } = default!;
public DbSet<DeliveryOrder> DeliveryOrder { get; set; } = default!;
public DbSet<Invoice> Invoice { get; set; } = default!;
public DbSet<PaymentReceive> PaymentReceive { get; set; } = default!;
public DbSet<DebitNote> DebitNote { get; set; } = default!;
public DbSet<CreditNote> CreditNote { get; set; } = default!;
public DbSet<ProductGroup> ProductGroup { get; set; } = default!;
public DbSet<ProgramManager> ProgramManager { get; set; } = default!;
public DbSet<ProgramManagerResource> ProgramManagerResource { get; set; } = default!;
public DbSet<PurchaseOrder> PurchaseOrder { get; set; } = default!;
public DbSet<PurchaseOrderItem> PurchaseOrderItem { get; set; } = default!;
public DbSet<PurchaseRequisition> PurchaseRequisition { get; set; } = default!;
public DbSet<PurchaseRequisitionItem> PurchaseRequisitionItem { get; set; } = default!;
public DbSet<PurchaseReturn> PurchaseReturn { get; set; } = default!;
public DbSet<Customer> Customer { get; set; } = default!;
public DbSet<CustomerCategory> CustomerCategory { get; set; } = default!;
public DbSet<CustomerContact> CustomerContact { get; set; } = default!;
public DbSet<CustomerGroup> CustomerGroup { get; set; } = default!;
public DbSet<Product> Product { get; set; } = default!;
public DbSet<SalesOrder> SalesOrder { get; set; } = default!;
public DbSet<SalesOrderItem> SalesOrderItem { get; set; } = default!;
public DbSet<SalesQuotation> SalesQuotation { get; set; } = default!;
public DbSet<SalesQuotationItem> SalesQuotationItem { get; set; } = default!;
public DbSet<SalesReturn> SalesReturn { 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 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,32 @@
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 RecalculatePurchaseRequisition(this AppDbContext context, string requisitionId)
{
PurchaseRequisitionHelper.Recalculate(context, requisitionId);
}
public static void RecalculateSalesOrder(this AppDbContext context, string salesOrderId)
{
SalesOrderHelper.Recalculate(context, salesOrderId);
}
public static void RecalculateSalesQuotation(this AppDbContext context, string quotationId)
{
SalesQuotationHelper.Recalculate(context, quotationId);
}
}
+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,67 @@
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);
// 2. Customer & Vendor Related
await CustomerCategorySeeder.GenerateDataAsync(context);
await CustomerGroupSeeder.GenerateDataAsync(context);
await CustomerSeeder.GenerateDataAsync(context);
await CustomerContactSeeder.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 SalesQuotationSeeder.GenerateDataAsync(context);
await SalesOrderSeeder.GenerateDataAsync(context);
// 5. Purchase Related
await PurchaseRequisitionSeeder.GenerateDataAsync(context);
await PurchaseOrderSeeder.GenerateDataAsync(context);
// 6. Inventory Operations
await DeliveryOrderSeeder.GenerateDataAsync(context);
await SalesReturnSeeder.GenerateDataAsync(context);
await GoodsReceiveSeeder.GenerateDataAsync(context);
await PurchaseReturnSeeder.GenerateDataAsync(context);
// 7. Finance & Project Related
await InvoiceSeeder.GenerateDataAsync(context);
await CreditNoteSeeder.GenerateDataAsync(context);
await PaymentReceiveSeeder.GenerateDataAsync(context);
await BillSeeder.GenerateDataAsync(context);
await DebitNoteSeeder.GenerateDataAsync(context);
await PaymentDisburseSeeder.GenerateDataAsync(context);
await BookingGroupSeeder.GenerateDataAsync(context);
await BookingResourceSeeder.GenerateDataAsync(context);
await BookingSeeder.GenerateDataAsync(context);
await ProgramManagerResourceSeeder.GenerateDataAsync(context);
await ProgramManagerSeeder.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,26 @@
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 = "Vehicle" },
new BookingGroup { Name = "Room" },
new BookingGroup { Name = "Electronic" }
};
foreach (var bookingGroup in bookingGroups)
{
await context.BookingGroup.AddAsync(bookingGroup);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,71 @@
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 vehicleGroup = await context.BookingGroup.Where(x => x.Name == "Vehicle").SingleOrDefaultAsync();
if (vehicleGroup != null)
{
var vehicleResources = new List<BookingResource>
{
new BookingResource { Name = "Audi 01", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "Audi 02", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "Audi 03", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "BMW 01", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "BMW 02", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "BMW 03", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "Lexus 01", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "Lexus 02", BookingGroupId = vehicleGroup.Id },
new BookingResource { Name = "Lexus 03", BookingGroupId = vehicleGroup.Id }
};
await context.BookingResource.AddRangeAsync(vehicleResources);
}
var roomGroup = await context.BookingGroup.Where(x => x.Name == "Room").SingleOrDefaultAsync();
if (roomGroup != null)
{
var roomResources = new List<BookingResource>
{
new BookingResource { Name = "Room One", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Room Two", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Room Three", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Conference One", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Conference Two", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Conference Three", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Studio One", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Studio Two", BookingGroupId = roomGroup.Id },
new BookingResource { Name = "Studio Three", BookingGroupId = roomGroup.Id }
};
await context.BookingResource.AddRangeAsync(roomResources);
}
var electronicGroup = await context.BookingGroup.Where(x => x.Name == "Electronic").SingleOrDefaultAsync();
if (electronicGroup != null)
{
var electronicResources = new List<BookingResource>
{
new BookingResource { Name = "Epson Projector", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Sony Projector", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Bose Speaker", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "JBL Speaker", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Microsoft Webcam", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Logitech Webcam", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Google Chromecast", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Apple TV", BookingGroupId = electronicGroup.Id },
new BookingResource { Name = "Samsung Monitor 49", BookingGroupId = electronicGroup.Id }
};
await context.BookingResource.AddRangeAsync(electronicResources);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,85 @@
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.AddMonths(6);
var dateStart = dateEnd.AddMonths(-6);
var bookingResources = await context.BookingResource
.Select(x => x.Id)
.ToListAsync();
if (!bookingResources.Any()) return;
var dummyLocations = new List<string>
{
"123 Main St, New York",
"456 Elm St, Los Angeles",
"789 Pine St, Chicago",
"101 Maple St, Houston",
"202 Oak St, Phoenix",
"303 Birch St, Philadelphia",
"404 Cedar St, San Antonio",
"505 Walnut St, San Diego",
"606 Aspen St, Dallas",
"707 Spruce St, San Jose"
};
for (DateTime date = dateStart; date < dateEnd; date = date.AddMonths(1))
{
DateTime[] transactionDates = GenerateRandomDays(date.Year, date.Month, 12);
foreach (DateTime transDate in transactionDates)
{
TimeSpan randomTime = TimeSpan.FromHours(random.Next(8, 12));
DateTime startTime = transDate.Date.Add(randomTime);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var booking = new Booking
{
Subject = autoNo,
AutoNumber = autoNo,
StartTime = startTime,
EndTime = startTime.AddHours(random.Next(2, 12)),
BookingResourceId = GetRandomValue(bookingResources, random),
Status = bookingStatusValues[random.Next(bookingStatusValues.Count)],
Location = GetRandomValue(dummyLocations, 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,99 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class CreditNoteSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.CreditNote.AnyAsync()) return;
var random = new Random();
var entityName = nameof(CreditNote);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedSalesReturns = await context.SalesReturn
.Where(sr => sr.Status == SalesReturnStatus.Confirmed)
.Select(sr => sr.Id)
.ToListAsync();
if (!confirmedSalesReturns.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] creditNoteDates = GetRandomDays(date.Year, date.Month, 3);
foreach (var creditNoteDate in creditNoteDates)
{
if (confirmedSalesReturns.Count == 0) break;
var status = GetRandomStatus(random);
var salesReturnId = GetRandomAndRemove(confirmedSalesReturns, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var creditNote = new CreditNote
{
AutoNumber = autoNo,
CreditNoteDate = creditNoteDate,
CreditNoteStatus = status,
Description = $"Credit Note for {creditNoteDate:MMMM yyyy}",
SalesReturnId = salesReturnId
};
await context.CreditNote.AddAsync(creditNote);
}
}
await context.SaveChangesAsync();
}
private static CreditNoteStatus GetRandomStatus(Random random)
{
var statuses = new[] { CreditNoteStatus.Draft, CreditNoteStatus.Cancelled, CreditNoteStatus.Confirmed, CreditNoteStatus.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 CreditNoteStatus.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,28 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class CustomerCategorySeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.CustomerCategory.AnyAsync()) return;
var customerCategories = new List<CustomerCategory>
{
new CustomerCategory { Name = "Enterprise" },
new CustomerCategory { Name = "Medium" },
new CustomerCategory { Name = "Small" },
new CustomerCategory { Name = "Startup" },
new CustomerCategory { Name = "Micro" }
};
foreach (var category in customerCategories)
{
await context.CustomerCategory.AddAsync(category);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,80 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class CustomerContactSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.CustomerContact.AnyAsync()) return;
var firstNames = new string[]
{
"Adam", "Sarah", "Michael", "Emily", "David", "Jessica",
"Kevin", "Samantha", "Jason", "Olivia", "Matthew", "Ashley",
"Christopher", "Jennifer", "Nicholas", "Amanda", "Alexander",
"Stephanie", "Jonathan", "Lauren"
};
var lastNames = new string[]
{
"Johnson", "Williams", "Brown", "Jones", "Miller", "Davis",
"Garcia", "Rodriguez", "Wilson", "Martinez", "Anderson", "Taylor",
"Thomas", "Hernandez", "Moore", "Martin", "Jackson", "Thompson",
"White", "Lopez"
};
var jobTitles = new string[]
{
"Chief Executive Officer", "Data Scientist", "Product Manager", "Business Development Executive",
"IT Consultant", "Social Media Specialist", "Research Analyst", "Content Writer",
"Operations Manager", "Financial Planner", "Software Developer", "Customer Success Manager",
"Marketing Coordinator", "Quality Assurance Tester", "HR Specialist", "Event Coordinator",
"Account Executive", "Network Administrator", "Sales Manager", "Legal Assistant"
};
var customerIds = await context.Customer.Select(x => x.Id).ToListAsync();
var random = new Random();
var entityName = nameof(CustomerContact);
foreach (var customerId in customerIds)
{
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 CustomerContact
{
Name = $"{firstName} {lastName}",
AutoNumber = autoNo,
CustomerId = customerId,
JobTitle = GetRandomString(jobTitles, random),
EmailAddress = $"{firstName.ToLower()}.{lastName.ToLower()}@gmail.com",
PhoneNumber = GenerateRandomPhoneNumber(random)
};
await context.CustomerContact.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(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}";
}
}
@@ -0,0 +1,29 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class CustomerGroupSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.CustomerGroup.AnyAsync()) return;
var customerGroups = new List<CustomerGroup>
{
new CustomerGroup { Name = "Corporate" },
new CustomerGroup { Name = "Government" },
new CustomerGroup { Name = "Foundation" },
new CustomerGroup { Name = "Military" },
new CustomerGroup { Name = "Education" },
new CustomerGroup { Name = "Hospitality" }
};
foreach (var group in customerGroups)
{
await context.CustomerGroup.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 CustomerSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.Customer.AnyAsync()) return;
var groups = await context.CustomerGroup.Select(x => x.Id).ToArrayAsync();
var categories = await context.CustomerCategory.Select(x => x.Id).ToArrayAsync();
var cities = new string[] { "New York", "Los Angeles", "San Francisco", "Chicago" };
var streets = new string[] { "Main St", "Broadway", "Market St", "Elm St" };
var states = new string[] { "NY", "CA", "IL", "TX" };
var zipCodes = new string[] { "10001", "90001", "94101", "60601" };
var phoneNumbers = new string[] { "555-1234", "555-5678", "555-8765", "555-4321" };
var emailDomains = new string[] { "example.com", "demo.com", "test.com", "sample.com" };
var random = new Random();
var entityName = nameof(Customer);
var customers = new List<Customer>
{
new Customer { Name = "Citadel LLC" },
new Customer { Name = "Ironclad LLC" },
new Customer { Name = "Armada LLC" },
new Customer { Name = "Shield LLC" },
new Customer { Name = "Alpha LLC" },
new Customer { Name = "Capitol LLC" },
new Customer { Name = "Federal LLC" },
new Customer { Name = "Statewide LLC" },
new Customer { Name = "Harmony LLC" },
new Customer { Name = "Hope LLC" },
new Customer { Name = "Unity LLC" },
new Customer { Name = "Prosperity LLC" },
new Customer { Name = "Global LLC" },
new Customer { Name = "Sunset LLC" },
new Customer { Name = "Luxe LLC" },
new Customer { Name = "Serenity LLC" },
new Customer { Name = "Oasis LLC" },
new Customer { Name = "Grandeur LLC" },
new Customer { Name = "Bright LLC" },
new Customer { Name = "Stellar LLC" }
};
foreach (var customer in customers)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
customer.AutoNumber = autoNo;
customer.CustomerGroupId = GetRandomValue(groups, random);
customer.CustomerCategoryId = GetRandomValue(categories, random);
customer.City = GetRandomString(cities, random);
customer.Street = GetRandomString(streets, random);
customer.State = GetRandomString(states, random);
customer.ZipCode = GetRandomString(zipCodes, random);
customer.PhoneNumber = GetRandomString(phoneNumbers, random);
customer.EmailAddress = $"{customer.Name?.Split(' ')[0].ToLower()}@{GetRandomString(emailDomains, random)}";
await context.Customer.AddAsync(customer);
}
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,99 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class DebitNoteSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.DebitNote.AnyAsync()) return;
var random = new Random();
var entityName = nameof(DebitNote);
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-12).Year, dateFinish.AddMonths(-12).Month, 1);
var confirmedPurchaseReturns = await context.PurchaseReturn
.Where(pr => pr.Status == PurchaseReturnStatus.Confirmed)
.Select(pr => pr.Id)
.ToListAsync();
if (!confirmedPurchaseReturns.Any()) return;
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] debitNoteDates = GetRandomDays(date.Year, date.Month, 3);
foreach (var debitNoteDate in debitNoteDates)
{
if (confirmedPurchaseReturns.Count == 0) break;
var status = GetRandomStatus(random);
var purchaseReturnId = GetRandomAndRemove(confirmedPurchaseReturns, random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var debitNote = new DebitNote
{
AutoNumber = autoNo,
DebitNoteDate = debitNoteDate,
DebitNoteStatus = status,
Description = $"Debit Note for {debitNoteDate:MMMM yyyy}",
PurchaseReturnId = purchaseReturnId
};
await context.DebitNote.AddAsync(debitNote);
}
}
await context.SaveChangesAsync();
}
private static DebitNoteStatus GetRandomStatus(Random random)
{
var statuses = new[] { DebitNoteStatus.Draft, DebitNoteStatus.Cancelled, DebitNoteStatus.Confirmed, DebitNoteStatus.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 DebitNoteStatus.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,86 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
using Indotalent.Shared.Utils;
namespace Indotalent.Infrastructure.Database.Demo;
public static class DeliveryOrderSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.DeliveryOrder.AnyAsync()) return;
var random = new Random();
var deliveryOrderStatusValues = Enum.GetValues(typeof(DeliveryOrderStatus)).Cast<DeliveryOrderStatus>().ToList();
var doEntityName = nameof(DeliveryOrder);
var ivtEntityName = nameof(InventoryTransaction);
var salesOrders = await context.SalesOrder
.Where(x => x.OrderStatus >= SalesOrderStatus.Confirmed)
.ToListAsync();
var warehouses = await context.Warehouse
.Where(x => x.SystemWarehouse == false)
.Select(x => x.Id)
.ToListAsync();
if (!warehouses.Any()) return;
foreach (var salesOrder in salesOrders)
{
var autoNoDO = await context.GenerateAutoNumberAsync(
entityName: doEntityName,
prefixTemplate: $"{doEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var deliveryOrder = new DeliveryOrder
{
AutoNumber = autoNoDO,
DeliveryDate = salesOrder.OrderDate?.AddDays(random.Next(1, 5)),
Status = deliveryOrderStatusValues[random.Next(deliveryOrderStatusValues.Count)],
SalesOrderId = salesOrder.Id,
};
await context.DeliveryOrder.AddAsync(deliveryOrder);
var items = await context.SalesOrderItem
.Include(x => x.Product)
.Where(x => x.SalesOrderId == salesOrder.Id && x.Product!.Physical == true)
.ToListAsync();
foreach (var item in items)
{
var autoNoIVT = await context.GenerateAutoNumberAsync(
entityName: ivtEntityName,
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var inventoryTransaction = new InventoryTransaction
{
ModuleId = deliveryOrder.Id,
ModuleName = doEntityName,
ModuleCode = "DO",
ModuleNumber = deliveryOrder.AutoNumber,
MovementDate = deliveryOrder.DeliveryDate!.Value,
Status = (InventoryTransactionStatus)deliveryOrder.Status,
AutoNumber = autoNoIVT,
WarehouseId = GetRandomValue(warehouses, random),
ProductId = item.ProductId,
Movement = item.Quantity!.Value
};
context.CalculateInvenTrans(inventoryTransaction);
await context.InventoryTransaction.AddAsync(inventoryTransaction);
}
await context.SaveChangesAsync();
}
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
}
@@ -0,0 +1,85 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class GoodsReceiveSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.GoodsReceive.AnyAsync()) return;
var random = new Random();
var goodsReceiveStatusValues = Enum.GetValues(typeof(GoodsReceiveStatus)).Cast<GoodsReceiveStatus>().ToList();
var grEntityName = nameof(GoodsReceive);
var ivtEntityName = nameof(InventoryTransaction);
var purchaseOrders = await context.PurchaseOrder
.Where(x => x.OrderStatus >= PurchaseOrderStatus.Confirmed)
.ToListAsync();
var warehouses = await context.Warehouse
.Where(x => x.SystemWarehouse == false)
.Select(x => x.Id)
.ToListAsync();
if (!warehouses.Any()) return;
foreach (var purchaseOrder in purchaseOrders)
{
var autoNoGR = await context.GenerateAutoNumberAsync(
entityName: grEntityName,
prefixTemplate: $"{grEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var goodsReceive = new GoodsReceive
{
AutoNumber = autoNoGR,
ReceiveDate = purchaseOrder.OrderDate?.AddDays(random.Next(1, 5)),
Status = goodsReceiveStatusValues[random.Next(goodsReceiveStatusValues.Count)],
PurchaseOrderId = purchaseOrder.Id,
};
await context.GoodsReceive.AddAsync(goodsReceive);
var items = await context.PurchaseOrderItem
.Include(x => x.Product)
.Where(x => x.PurchaseOrderId == purchaseOrder.Id && x.Product!.Physical == true)
.ToListAsync();
foreach (var item in items)
{
var autoNoIVT = await context.GenerateAutoNumberAsync(
entityName: ivtEntityName,
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var inventoryTransaction = new InventoryTransaction
{
ModuleId = goodsReceive.Id,
ModuleName = grEntityName,
ModuleCode = "GR",
ModuleNumber = goodsReceive.AutoNumber,
MovementDate = goodsReceive.ReceiveDate!.Value,
Status = (InventoryTransactionStatus)goodsReceive.Status,
AutoNumber = autoNoIVT,
WarehouseId = GetRandomValue(warehouses, random),
ProductId = item.ProductId,
Movement = item.Quantity!.Value
};
context.CalculateInvenTrans(inventoryTransaction);
await context.InventoryTransaction.AddAsync(inventoryTransaction);
}
await context.SaveChangesAsync();
}
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
}
@@ -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,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,29 @@
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 = "Hardware" },
new ProductGroup { Name = "Networking" },
new ProductGroup { Name = "Storage" },
new ProductGroup { Name = "Device" },
new ProductGroup { Name = "Software" },
new ProductGroup { Name = "Service" }
};
foreach (var productGroup in productGroups)
{
await context.ProductGroup.AddAsync(productGroup);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,76 @@
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>
{
// Hardware - Gunakan akhiran 'm' untuk decimal literal
new Product { Name = "Dell Servers", UnitPrice = 5000m, ProductGroupId = groupMapping["Hardware"] },
new Product { Name = "Dell Desktop Computers", UnitPrice = 2000m, ProductGroupId = groupMapping["Hardware"] },
new Product { Name = "Dell Laptops", UnitPrice = 3000m, ProductGroupId = groupMapping["Hardware"] },
// Networking
new Product { Name = "Network Cables", UnitPrice = 100m, ProductGroupId = groupMapping["Networking"] },
new Product { Name = "Routers and Switches", UnitPrice = 1000m, ProductGroupId = groupMapping["Networking"] },
new Product { Name = "Antennas and Signal Boosters", UnitPrice = 2000m, ProductGroupId = groupMapping["Networking"] },
new Product { Name = "Wifii", UnitPrice = 1000m, ProductGroupId = groupMapping["Networking"] },
// Storage
new Product { Name = "HDD 500", UnitPrice = 500m, ProductGroupId = groupMapping["Storage"] },
new Product { Name = "HDD 1T", UnitPrice = 800m, ProductGroupId = groupMapping["Storage"] },
new Product { Name = "SSD 500", UnitPrice = 1000m, ProductGroupId = groupMapping["Storage"] },
new Product { Name = "SSD 1T", UnitPrice = 1500m, ProductGroupId = groupMapping["Storage"] },
// Device
new Product { Name = "Dell Keyboard", UnitPrice = 700m, ProductGroupId = groupMapping["Device"] },
new Product { Name = "Dell Mouse", UnitPrice = 500m, ProductGroupId = groupMapping["Device"] },
new Product { Name = "Dell Monitor 27inch", UnitPrice = 1000m, ProductGroupId = groupMapping["Device"] },
new Product { Name = "Dell Monitor 32inch", UnitPrice = 1500m, ProductGroupId = groupMapping["Device"] },
new Product { Name = "Dell Webcams", UnitPrice = 500m, ProductGroupId = groupMapping["Device"] },
// Software
new Product { Name = "D365 License", UnitPrice = 800m, Physical = false, ProductGroupId = groupMapping["Software"] },
// Service
new Product { Name = "IT Security", UnitPrice = 500m, Physical = false, ProductGroupId = groupMapping["Service"] },
new Product { Name = "Discount", UnitPrice = -10m, Physical = false, ProductGroupId = groupMapping["Service"] }
};
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,28 @@
using Indotalent.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class ProgramManagerResourceSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.ProgramManagerResource.AnyAsync()) return;
var programResources = new List<ProgramManagerResource>
{
new ProgramManagerResource { Name = "Information Technology" },
new ProgramManagerResource { Name = "Human Resource" },
new ProgramManagerResource { Name = "Operations" },
new ProgramManagerResource { Name = "Sales Marketing" },
new ProgramManagerResource { Name = "Finance Accounting" }
};
foreach (var programResource in programResources)
{
await context.ProgramManagerResource.AddAsync(programResource);
}
await context.SaveChangesAsync();
}
}
@@ -0,0 +1,75 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class ProgramManagerSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.ProgramManager.AnyAsync()) return;
var random = new Random();
var entityName = nameof(ProgramManager);
var programManagerResources = await context.ProgramManagerResource.Select(x => x.Id).ToListAsync();
if (!programManagerResources.Any()) return;
var statusValues = Enum.GetValues(typeof(ProgramManagerStatus)).Cast<ProgramManagerStatus>().ToList();
var priorityValues = Enum.GetValues(typeof(ProgramManagerPriority)).Cast<ProgramManagerPriority>().ToList();
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-6).Year, dateFinish.AddMonths(-6).Month, 1);
for (DateTime date = dateStart; date < dateFinish; date = date.AddMonths(1))
{
DateTime[] transactionDates = GetRandomDays(date.Year, date.Month, 12);
foreach (DateTime transDate in transactionDates)
{
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var programManager = new ProgramManager
{
Title = autoNo,
AutoNumber = autoNo,
Summary = $"Lorem Ipsum Dolor Sit Amet Program - #{Guid.NewGuid().ToString().Substring(0, 5)}",
ProgramManagerResourceId = GetRandomValue(programManagerResources, random),
Status = statusValues[random.Next(statusValues.Count)],
Priority = priorityValues[random.Next(priorityValues.Count)]
};
await context.ProgramManager.AddAsync(programManager);
}
}
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,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,117 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PurchaseRequisitionSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PurchaseRequisition.AnyAsync()) return;
var random = new Random();
var entityName = nameof(PurchaseRequisition);
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 dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
{
DateTime[] requisitionDates = GetRandomDays(date.Year, date.Month, 4);
foreach (var requisitionDate in requisitionDates)
{
var status = GetRandomStatus(random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var purchaseRequisition = new PurchaseRequisition
{
AutoNumber = autoNo,
RequisitionDate = requisitionDate,
RequisitionStatus = status,
Description = $"Requisition for {requisitionDate:MMMM yyyy}",
VendorId = GetRandomValue(vendors, random),
TaxId = GetRandomValue(taxes, random),
};
await context.PurchaseRequisition.AddAsync(purchaseRequisition);
int numberOfItems = random.Next(2, 5);
for (int i = 0; i < numberOfItems; i++)
{
var qty = (double)random.Next(2, 5);
var product = products[random.Next(products.Count)];
var purchaseRequisitionItem = new PurchaseRequisitionItem
{
PurchaseRequisitionId = purchaseRequisition.Id,
ProductId = product.Id,
Summary = product.AutoNumber,
UnitPrice = product.UnitPrice,
Quantity = qty,
Total = (product.UnitPrice ?? 0m) * (decimal)qty
};
await context.PurchaseRequisitionItem.AddAsync(purchaseRequisitionItem);
}
await context.SaveChangesAsync();
context.RecalculatePurchaseRequisition(purchaseRequisition.Id);
await context.SaveChangesAsync();
}
}
}
private static PurchaseRequisitionStatus GetRandomStatus(Random random)
{
var statuses = new[] {
PurchaseRequisitionStatus.Draft,
PurchaseRequisitionStatus.Cancelled,
PurchaseRequisitionStatus.Confirmed,
PurchaseRequisitionStatus.Ordered
};
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 PurchaseRequisitionStatus.Confirmed;
}
private static string GetRandomValue(List<string> 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,87 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class PurchaseReturnSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.PurchaseReturn.AnyAsync()) return;
var random = new Random();
var purchaseReturnStatusValues = Enum.GetValues(typeof(PurchaseReturnStatus)).Cast<PurchaseReturnStatus>().ToList();
var prnEntityName = nameof(PurchaseReturn);
var grEntityName = nameof(GoodsReceive);
var ivtEntityName = nameof(InventoryTransaction);
var goodsReceives = await context.GoodsReceive
.Where(x => x.Status >= GoodsReceiveStatus.Confirmed)
.ToListAsync();
var warehouses = await context.Warehouse
.Where(x => x.SystemWarehouse == false)
.Select(x => x.Id)
.ToListAsync();
if (!warehouses.Any()) return;
foreach (var goodsReceive in goodsReceives)
{
bool skip = random.Next(2) == 0;
if (skip) continue;
var autoNoPRN = await context.GenerateAutoNumberAsync(
entityName: prnEntityName,
prefixTemplate: $"{prnEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var purchaseReturn = new PurchaseReturn
{
AutoNumber = autoNoPRN,
ReturnDate = goodsReceive.ReceiveDate?.AddDays(random.Next(1, 5)),
Status = purchaseReturnStatusValues[random.Next(purchaseReturnStatusValues.Count)],
GoodsReceiveId = goodsReceive.Id,
};
await context.PurchaseReturn.AddAsync(purchaseReturn);
var items = await context.InventoryTransaction
.Where(x => x.ModuleId == goodsReceive.Id && x.ModuleName == grEntityName)
.ToListAsync();
foreach (var item in items)
{
var autoNoIVT = await context.GenerateAutoNumberAsync(
entityName: ivtEntityName,
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var inventoryTransaction = new InventoryTransaction
{
ModuleId = purchaseReturn.Id,
ModuleName = prnEntityName,
ModuleCode = "PRN",
ModuleNumber = purchaseReturn.AutoNumber,
MovementDate = purchaseReturn.ReturnDate!.Value,
Status = (InventoryTransactionStatus)purchaseReturn.Status,
AutoNumber = autoNoIVT,
WarehouseId = GetRandomValue(warehouses, random),
ProductId = item.ProductId,
Movement = item.Movement
};
context.CalculateInvenTrans(inventoryTransaction);
await context.InventoryTransaction.AddAsync(inventoryTransaction);
}
await context.SaveChangesAsync();
}
}
private static T GetRandomValue<T>(List<T> list, Random random)
{
return list[random.Next(list.Count)];
}
}
@@ -0,0 +1,107 @@
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.Customer.Select(x => x.Id).ToListAsync();
var taxes = await context.Tax.Select(x => x.Id).ToListAsync();
var products = await context.Product.ToListAsync();
if (!customers.Any() || !taxes.Any() || !products.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),
TaxId = GetRandomValue(taxes, 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,117 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class SalesQuotationSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.SalesQuotation.AnyAsync()) return;
var random = new Random();
var entityName = nameof(SalesQuotation);
var customers = await context.Customer.Select(x => x.Id).ToListAsync();
var taxes = await context.Tax.Select(x => x.Id).ToListAsync();
var products = await context.Product.ToListAsync();
if (!customers.Any() || !taxes.Any() || !products.Any()) return;
var dateFinish = DateTime.Now;
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
{
DateTime[] quotationDates = GetRandomDays(date.Year, date.Month, 4);
foreach (var quotationDate in quotationDates)
{
var status = GetRandomStatus(random);
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var salesQuotation = new SalesQuotation
{
AutoNumber = autoNo,
QuotationDate = quotationDate,
QuotationStatus = status,
Description = $"Quotation for {quotationDate:MMMM yyyy}",
CustomerId = GetRandomValue(customers, random),
TaxId = GetRandomValue(taxes, random),
};
await context.SalesQuotation.AddAsync(salesQuotation);
int numberOfItems = random.Next(2, 5);
for (int i = 0; i < numberOfItems; i++)
{
var qty = (double)random.Next(2, 5);
var product = products[random.Next(products.Count)];
var salesQuotationItem = new SalesQuotationItem
{
SalesQuotationId = salesQuotation.Id,
ProductId = product.Id,
Summary = product.AutoNumber,
UnitPrice = product.UnitPrice,
Quantity = qty,
Total = (product.UnitPrice ?? 0m) * (decimal)qty
};
await context.SalesQuotationItem.AddAsync(salesQuotationItem);
}
await context.SaveChangesAsync();
context.RecalculateSalesQuotation(salesQuotation.Id);
await context.SaveChangesAsync();
}
}
}
private static SalesQuotationStatus GetRandomStatus(Random random)
{
var statuses = new[] {
SalesQuotationStatus.Draft,
SalesQuotationStatus.Cancelled,
SalesQuotationStatus.Confirmed,
SalesQuotationStatus.Ordered
};
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 SalesQuotationStatus.Confirmed;
}
private static string GetRandomValue(List<string> 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,104 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Entities;
using Indotalent.Data.Enums;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Infrastructure.Database.Demo;
public static class SalesReturnSeeder
{
public static async Task GenerateDataAsync(AppDbContext context)
{
if (await context.SalesReturn.AnyAsync()) return;
var random = new Random();
var entityName = nameof(SalesReturn);
var deliveryOrderEntityName = nameof(DeliveryOrder);
var ivtEntityName = nameof(InventoryTransaction);
var deliveryOrders = await context.DeliveryOrder
.Where(x => x.Status >= DeliveryOrderStatus.Confirmed)
.ToListAsync();
var warehouses = await context.Warehouse
.Where(x => x.SystemWarehouse == false)
.Select(x => x.Id)
.ToListAsync();
if (!warehouses.Any()) return;
foreach (var deliveryOrder in deliveryOrders)
{
bool skip = random.Next(2) == 0;
if (skip) continue;
var autoNo = await context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var salesReturn = new SalesReturn
{
AutoNumber = autoNo,
ReturnDate = deliveryOrder.DeliveryDate?.AddDays(random.Next(1, 5)),
Status = GetRandomStatus(random),
DeliveryOrderId = deliveryOrder.Id,
};
await context.SalesReturn.AddAsync(salesReturn);
var items = await context.InventoryTransaction
.Where(x => x.ModuleId == deliveryOrder.Id && x.ModuleName == deliveryOrderEntityName)
.ToListAsync();
foreach (var item in items)
{
var autoNoIVT = await context.GenerateAutoNumberAsync(
entityName: ivtEntityName,
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
);
var inventoryTransaction = new InventoryTransaction
{
ModuleId = salesReturn.Id,
ModuleName = entityName,
ModuleCode = "SRN",
ModuleNumber = salesReturn.AutoNumber,
MovementDate = salesReturn.ReturnDate!.Value,
Status = (InventoryTransactionStatus)salesReturn.Status,
AutoNumber = autoNoIVT,
WarehouseId = GetRandomValue(warehouses, random),
ProductId = item.ProductId,
Movement = item.Movement
};
context.CalculateInvenTrans(inventoryTransaction);
await context.InventoryTransaction.AddAsync(inventoryTransaction);
}
await context.SaveChangesAsync();
}
}
private static SalesReturnStatus GetRandomStatus(Random random)
{
var statuses = new[] { SalesReturnStatus.Draft, SalesReturnStatus.Cancelled, SalesReturnStatus.Confirmed, SalesReturnStatus.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 SalesReturnStatus.Confirmed;
}
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 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" }
};
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,29 @@
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 = "Large" },
new VendorCategory { Name = "Medium" },
new VendorCategory { Name = "Small" },
new VendorCategory { Name = "Specialty" },
new VendorCategory { Name = "Local" },
new VendorCategory { Name = "Global" }
};
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[]
{
"Adam", "Sarah", "Michael", "Emily", "David", "Jessica",
"Kevin", "Samantha", "Jason", "Olivia", "Matthew", "Ashley",
"Christopher", "Jennifer", "Nicholas", "Amanda", "Alexander",
"Stephanie", "Jonathan", "Lauren"
};
var lastNames = new string[]
{
"Johnson", "Williams", "Brown", "Jones", "Miller", "Davis",
"Garcia", "Rodriguez", "Wilson", "Martinez", "Anderson", "Taylor",
"Thomas", "Hernandez", "Moore", "Martin", "Jackson", "Thompson",
"White", "Lopez"
};
var jobTitles = new string[]
{
"Chief Executive Officer", "Data Scientist", "Product Manager", "Business Development Executive",
"IT Consultant", "Social Media Specialist", "Research Analyst", "Content Writer",
"Operations Manager", "Financial Planner", "Software Developer", "Vendor Success Manager",
"Marketing Coordinator", "Quality Assurance Tester", "HR Specialist", "Event Coordinator",
"Account Executive", "Network Administrator", "Sales Manager", "Legal Assistant"
};
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()}@gmail.com",
PhoneNumber = $"+1-{random.Next(100, 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,28 @@
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 = "Manufacture" },
new VendorGroup { Name = "Supplier" },
new VendorGroup { Name = "Service Provider" },
new VendorGroup { Name = "Distributor" },
new VendorGroup { Name = "Freelancer" }
};
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", "San Francisco", "Chicago" };
var streets = new string[] { "Main Street", "Broadway", "Elm Street", "Maple Avenue" };
var states = new string[] { "NY", "CA", "IL", "TX" };
var zipCodes = new string[] { "10001", "90001", "60601", "73301" };
var phoneNumbers = new string[] { "123-456-7890", "987-654-3210", "555-123-4567", "111-222-3333" };
var emails = new string[] { "vendor1@example.com", "vendor2@example.com", "vendor3@example.com", "vendor4@example.com" };
var random = new Random();
var entityName = nameof(Vendor);
var vendors = new List<Vendor>
{
new Vendor { Name = "Quantum Industries" },
new Vendor { Name = "Apex Ventures" },
new Vendor { Name = "Horizon Enterprises" },
new Vendor { Name = "Nova Innovations" },
new Vendor { Name = "Phoenix Holdings" },
new Vendor { Name = "Titan Group" },
new Vendor { Name = "Zenith Corporation" },
new Vendor { Name = "Prime Solutions" },
new Vendor { Name = "Cascade Enterprises" },
new Vendor { Name = "Aurora Holdings" },
new Vendor { Name = "Vanguard Industries" },
new Vendor { Name = "Empyrean Ventures" },
new Vendor { Name = "Genesis Corporation" },
new Vendor { Name = "Equinox Enterprises" },
new Vendor { Name = "Summit Holdings" },
new Vendor { Name = "Sovereign Solutions" },
new Vendor { Name = "Spectrum Corporation" },
new Vendor { Name = "Elysium Enterprises" },
new Vendor { Name = "Infinity Holdings" },
new Vendor { Name = "Momentum Ventures" }
};
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,27 @@
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 = "New York" },
new Warehouse { Name = "San Francisco" },
new Warehouse { Name = "Chicago" },
new Warehouse { Name = "Los Angeles" }
};
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,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 CreditNoteConfiguration : IEntityTypeConfiguration<CreditNote>
{
public void Configure(EntityTypeBuilder<CreditNote> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.SalesReturnId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.SalesReturn)
.WithMany()
.HasForeignKey(e => e.SalesReturnId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.CreditNoteDate);
builder.HasIndex(e => e.SalesReturnId);
}
}
@@ -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 CustomerCategoryConfiguration : IEntityTypeConfiguration<CustomerCategory>
{
public void Configure(EntityTypeBuilder<CustomerCategory> 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 CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> 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.CustomerGroupId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.CustomerCategoryId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.CustomerGroup)
.WithMany()
.HasForeignKey(e => e.CustomerGroupId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.CustomerCategory)
.WithMany()
.HasForeignKey(e => e.CustomerCategoryId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.CustomerGroupId);
builder.HasIndex(e => e.CustomerCategoryId);
}
}
@@ -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 CustomerContactConfiguration : IEntityTypeConfiguration<CustomerContact>
{
public void Configure(EntityTypeBuilder<CustomerContact> 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.PhoneNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.EmailAddress)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.CustomerId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.Customer)
.WithMany(e => e.CustomerContactList)
.HasForeignKey(e => e.CustomerId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Name);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.CustomerId);
}
}
@@ -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 CustomerGroupConfiguration : IEntityTypeConfiguration<CustomerGroup>
{
public void Configure(EntityTypeBuilder<CustomerGroup> 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,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 DebitNoteConfiguration : IEntityTypeConfiguration<DebitNote>
{
public void Configure(EntityTypeBuilder<DebitNote> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.PurchaseReturnId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.PurchaseReturn)
.WithMany()
.HasForeignKey(e => e.PurchaseReturnId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.DebitNoteDate);
builder.HasIndex(e => e.PurchaseReturnId);
}
}
@@ -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 DeliveryOrderConfiguration : IEntityTypeConfiguration<DeliveryOrder>
{
public void Configure(EntityTypeBuilder<DeliveryOrder> 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.DeliveryDate);
builder.HasIndex(e => e.SalesOrderId);
}
}
@@ -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 GoodsReceiveConfiguration : IEntityTypeConfiguration<GoodsReceive>
{
public void Configure(EntityTypeBuilder<GoodsReceive> 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.ReceiveDate);
builder.HasIndex(e => e.PurchaseOrderId);
}
}
@@ -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,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,33 @@
using Indotalent.Data.Entities;
using Indotalent.Shared.Consts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
public class ProgramManagerConfiguration : IEntityTypeConfiguration<ProgramManager>
{
public void Configure(EntityTypeBuilder<ProgramManager> builder)
{
builder.Property(e => e.Title)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Summary)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.ProgramManagerResourceId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.ProgramManagerResource)
.WithMany()
.HasForeignKey(e => e.ProgramManagerResourceId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.Title);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.ProgramManagerResourceId);
}
}
@@ -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 ProgramManagerResourceConfiguration : IEntityTypeConfiguration<ProgramManagerResource>
{
public void Configure(EntityTypeBuilder<ProgramManagerResource> 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,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 PurchaseRequisitionConfiguration : IEntityTypeConfiguration<PurchaseRequisition>
{
public void Configure(EntityTypeBuilder<PurchaseRequisition> 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.PurchaseRequisitionItemList)
.WithOne(e => e.PurchaseRequisition)
.HasForeignKey(e => e.PurchaseRequisitionId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.RequisitionDate);
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 PurchaseRequisitionItemConfiguration : IEntityTypeConfiguration<PurchaseRequisitionItem>
{
public void Configure(EntityTypeBuilder<PurchaseRequisitionItem> builder)
{
builder.Property(e => e.PurchaseRequisitionId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.ProductId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.Property(e => e.Summary)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.HasOne(e => e.PurchaseRequisition)
.WithMany(e => e.PurchaseRequisitionItemList)
.HasForeignKey(e => e.PurchaseRequisitionId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(e => e.Product)
.WithMany()
.HasForeignKey(e => e.ProductId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.PurchaseRequisitionId);
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 PurchaseReturnConfiguration : IEntityTypeConfiguration<PurchaseReturn>
{
public void Configure(EntityTypeBuilder<PurchaseReturn> builder)
{
builder.Property(e => e.AutoNumber)
.HasMaxLength(GlobalConsts.StringLengthShort);
builder.Property(e => e.Description)
.HasMaxLength(GlobalConsts.StringLengthMedium);
builder.Property(e => e.GoodsReceiveId)
.HasMaxLength(GlobalConsts.StringLengthId);
builder.HasOne(e => e.GoodsReceive)
.WithMany()
.HasForeignKey(e => e.GoodsReceiveId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.ReturnDate);
builder.HasIndex(e => e.GoodsReceiveId);
}
}
@@ -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 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.HasOne(e => e.Customer)
.WithMany()
.HasForeignKey(e => e.CustomerId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Tax)
.WithMany()
.HasForeignKey(e => e.TaxId)
.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);
}
}
@@ -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,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 SalesQuotationConfiguration : IEntityTypeConfiguration<SalesQuotation>
{
public void Configure(EntityTypeBuilder<SalesQuotation> 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.HasOne(e => e.Customer)
.WithMany()
.HasForeignKey(e => e.CustomerId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(e => e.Tax)
.WithMany()
.HasForeignKey(e => e.TaxId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasMany(e => e.SalesQuotationItemList)
.WithOne(e => e.SalesQuotation)
.HasForeignKey(e => e.SalesQuotationId)
.OnDelete(DeleteBehavior.NoAction);
builder.HasIndex(e => e.AutoNumber).IsUnique();
builder.HasIndex(e => e.QuotationDate);
builder.HasIndex(e => e.CustomerId);
builder.HasIndex(e => e.TaxId);
}
}

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