initial commit
This commit is contained in:
@@ -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
|
||||
};
|
||||
}
|
||||
+56
@@ -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}";
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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_";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
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<Campaign> Campaign { get; set; } = default!;
|
||||
public DbSet<Lead> Lead { get; set; } = default!;
|
||||
public DbSet<LeadContact> LeadContact { get; set; } = default!;
|
||||
public DbSet<LeadActivity> LeadActivity { get; set; } = default!;
|
||||
public DbSet<Budget> Budget { get; set; } = default!;
|
||||
public DbSet<Expense> Expense { 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<PositiveAdjustment> PositiveAdjustment { get; set; } = default!;
|
||||
public DbSet<NegativeAdjustment> NegativeAdjustment { 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<SalesRepresentative> SalesRepresentative { get; set; } = default!;
|
||||
public DbSet<SalesReturn> SalesReturn { get; set; } = default!;
|
||||
public DbSet<SalesTeam> SalesTeam { get; set; } = default!;
|
||||
public DbSet<Scrapping> Scrapping { get; set; } = default!;
|
||||
public DbSet<StockCount> StockCount { get; set; } = default!;
|
||||
public DbSet<Todo> Todo { get; set; } = default!;
|
||||
public DbSet<TodoItem> TodoItem { get; set; } = default!;
|
||||
public DbSet<TransferIn> TransferIn { get; set; } = default!;
|
||||
public DbSet<TransferOut> TransferOut { 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);
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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,81 @@
|
||||
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 & CRM Related
|
||||
await SalesTeamSeeder.GenerateDataAsync(context);
|
||||
await SalesRepresentativeSeeder.GenerateDataAsync(context);
|
||||
await CampaignSeeder.GenerateDataAsync(context);
|
||||
await LeadSeeder.GenerateDataAsync(context);
|
||||
await LeadContactSeeder.GenerateDataAsync(context);
|
||||
await LeadActivitySeeder.GenerateDataAsync(context);
|
||||
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);
|
||||
await TransferOutSeeder.GenerateDataAsync(context);
|
||||
await TransferInSeeder.GenerateDataAsync(context);
|
||||
await PositiveAdjustmentSeeder.GenerateDataAsync(context);
|
||||
await NegativeAdjustmentSeeder.GenerateDataAsync(context);
|
||||
await ScrappingSeeder.GenerateDataAsync(context);
|
||||
await StockCountSeeder.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 BudgetSeeder.GenerateDataAsync(context);
|
||||
await ExpenseSeeder.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();
|
||||
}
|
||||
@@ -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,96 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class BudgetSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Budget.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(Budget);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var targetCampaigns = await context.Campaign
|
||||
.Where(c => c.Status == CampaignStatus.Confirmed ||
|
||||
c.Status == CampaignStatus.OnProgress ||
|
||||
c.Status == CampaignStatus.Finished)
|
||||
.Select(c => c.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!targetCampaigns.Any()) return;
|
||||
|
||||
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
|
||||
{
|
||||
var transactionDaysList = GetRandomDays(date.Year, date.Month, 8).ToList();
|
||||
|
||||
foreach (var transDate in transactionDaysList)
|
||||
{
|
||||
var status = GetRandomStatus(random);
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var budget = new Budget
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
Title = $"Budget for {transDate:MMMM yyyy}",
|
||||
Description = $"Description for budget on {transDate:MMMM yyyy}",
|
||||
BudgetDate = transDate,
|
||||
Status = status,
|
||||
Amount = (decimal)(10000 * Math.Ceiling((random.NextDouble() * 89) + 1)),
|
||||
CampaignId = GetRandomValue(targetCampaigns, random)
|
||||
};
|
||||
|
||||
await context.Budget.AddAsync(budget);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static BudgetStatus GetRandomStatus(Random random)
|
||||
{
|
||||
var statuses = new[] { BudgetStatus.Draft, BudgetStatus.Cancelled, BudgetStatus.Confirmed, BudgetStatus.Archived };
|
||||
var weights = new[] { 1, 1, 3, 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 BudgetStatus.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,100 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class CampaignSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Campaign.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(Campaign);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var salesTeamIds = await context.SalesTeam
|
||||
.Select(st => st.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!salesTeamIds.Any()) return;
|
||||
|
||||
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
|
||||
{
|
||||
DateTime[] campaignStarts = GetRandomDays(date.Year, date.Month, 3);
|
||||
|
||||
foreach (var campaignStart in campaignStarts)
|
||||
{
|
||||
var duration = random.Next(1, 4);
|
||||
var campaignEnd = campaignStart.AddMonths(duration);
|
||||
|
||||
var status = GetRandomStatus(random);
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
string firstFourChars = autoNo.Length >= 4 ? autoNo.Substring(0, 4) : autoNo;
|
||||
|
||||
var campaign = new Campaign
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
Title = $"{firstFourChars} Campaign for {campaignStart:MMMM yyyy}",
|
||||
Description = $"Description for campaign starting {campaignStart:MMMM yyyy}",
|
||||
TargetRevenueAmount = (decimal)(10000 * Math.Ceiling((random.NextDouble() * 89) + 1)),
|
||||
CampaignDateStart = campaignStart,
|
||||
CampaignDateFinish = campaignEnd,
|
||||
Status = status,
|
||||
SalesTeamId = GetRandomValue(salesTeamIds, random)
|
||||
};
|
||||
|
||||
await context.Campaign.AddAsync(campaign);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static CampaignStatus GetRandomStatus(Random random)
|
||||
{
|
||||
var statuses = new[] { CampaignStatus.Draft, CampaignStatus.Cancelled, CampaignStatus.Confirmed, CampaignStatus.OnProgress, CampaignStatus.OnHold, CampaignStatus.Finished, CampaignStatus.Archived };
|
||||
var weights = new[] { 1, 1, 10, 2, 1, 5, 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 CampaignStatus.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,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,97 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class ExpenseSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Expense.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(Expense);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var targetCampaigns = await context.Campaign
|
||||
.Where(c => c.Status == CampaignStatus.Confirmed ||
|
||||
c.Status == CampaignStatus.OnProgress ||
|
||||
c.Status == CampaignStatus.Finished)
|
||||
.Select(c => c.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!targetCampaigns.Any()) return;
|
||||
|
||||
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
|
||||
{
|
||||
DateTime[] expenseDates = GetRandomDays(date.Year, date.Month, 5);
|
||||
|
||||
foreach (var expenseDate in expenseDates)
|
||||
{
|
||||
var status = GetRandomStatus(random);
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var expense = new Expense
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
Title = $"Expense for {expenseDate:MMMM yyyy}",
|
||||
Description = $"Description for expense on {expenseDate:MMMM yyyy}",
|
||||
ExpenseDate = expenseDate,
|
||||
Status = status,
|
||||
Amount = (decimal)(1000 * Math.Ceiling((random.NextDouble() * 89) + 1)),
|
||||
CampaignId = GetRandomValue(targetCampaigns, random)
|
||||
};
|
||||
|
||||
await context.Expense.AddAsync(expense);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static ExpenseStatus GetRandomStatus(Random random)
|
||||
{
|
||||
var statuses = new[] { ExpenseStatus.Draft, ExpenseStatus.Cancelled, ExpenseStatus.Confirmed, ExpenseStatus.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 ExpenseStatus.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,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,80 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class LeadActivitySeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.LeadActivity.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(LeadActivity);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var leads = await context.Lead.Select(l => l.Id).ToListAsync();
|
||||
|
||||
if (!leads.Any()) return;
|
||||
|
||||
var activityTypeValues = Enum.GetValues(typeof(LeadActivityType)).Cast<LeadActivityType>().ToList();
|
||||
|
||||
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
|
||||
{
|
||||
DateTime[] activityDates = GetRandomDays(date.Year, date.Month, 10);
|
||||
|
||||
foreach (var activityDate in activityDates)
|
||||
{
|
||||
var leadId = GetRandomValue(leads, random);
|
||||
var fromDate = activityDate;
|
||||
var toDate = fromDate.AddHours(random.Next(1, 5));
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var leadActivity = new LeadActivity
|
||||
{
|
||||
LeadId = leadId,
|
||||
AutoNumber = autoNo,
|
||||
Summary = $"Activity on {fromDate:MMMM d, yyyy}",
|
||||
Description = $"Description for activity on {fromDate:MMMM d, yyyy}",
|
||||
FromDate = fromDate,
|
||||
ToDate = toDate,
|
||||
Type = activityTypeValues[random.Next(activityTypeValues.Count)],
|
||||
AttachmentName = random.Next(1, 100) % 2 == 0 ? $"file_{random.Next(1, 100)}.pdf" : null
|
||||
};
|
||||
|
||||
await context.LeadActivity.AddAsync(leadActivity);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
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 Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class LeadContactSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.LeadContact.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(LeadContact);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var leads = await context.Lead.Select(l => l.Id).ToListAsync();
|
||||
|
||||
if (!leads.Any()) return;
|
||||
|
||||
for (DateTime date = dateStart; date <= dateFinish; date = date.AddMonths(1))
|
||||
{
|
||||
DateTime[] contactDates = GetRandomDays(date.Year, date.Month, 5);
|
||||
|
||||
foreach (var contactDate in contactDates)
|
||||
{
|
||||
var leadId = GetRandomValue(leads, random);
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var leadContact = new LeadContact
|
||||
{
|
||||
LeadId = leadId,
|
||||
AutoNumber = autoNo,
|
||||
FullName = $"Contact {random.Next(1000, 9999)}",
|
||||
Description = "Sample contact description",
|
||||
AddressStreet = "456 Elm St",
|
||||
AddressCity = "Anytown",
|
||||
AddressState = "State",
|
||||
AddressZipCode = "67890",
|
||||
AddressCountry = "Country",
|
||||
PhoneNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
FaxNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
MobileNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
Email = $"contact{random.Next(1000, 9999)}@company.com",
|
||||
Website = $"www.contact{random.Next(1000, 9999)}.com",
|
||||
WhatsApp = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
LinkedIn = $"linkedin.com/in/contact{random.Next(1000, 9999)}",
|
||||
Facebook = $"facebook.com/contact{random.Next(1000, 9999)}",
|
||||
Twitter = $"twitter.com/contact{random.Next(1000, 9999)}",
|
||||
Instagram = $"instagram.com/contact{random.Next(1000, 9999)}",
|
||||
AvatarName = $"avatar_{random.Next(1, 100)}.jpg"
|
||||
};
|
||||
|
||||
await context.LeadContact.AddAsync(leadContact);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
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,110 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class LeadSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Lead.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(Lead);
|
||||
var dateFinish = DateTime.Now;
|
||||
var dateStart = new DateTime(dateFinish.AddMonths(-11).Year, dateFinish.AddMonths(-11).Month, 1);
|
||||
|
||||
var confirmedCampaigns = await context.Campaign
|
||||
.Where(c => c.Status == CampaignStatus.Confirmed)
|
||||
.Select(c => c.Id)
|
||||
.ToListAsync();
|
||||
|
||||
var salesTeamIds = await context.SalesTeam
|
||||
.Select(st => st.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!confirmedCampaigns.Any() || !salesTeamIds.Any()) return;
|
||||
|
||||
var closingStatusValues = Enum.GetValues(typeof(ClosingStatus)).Cast<ClosingStatus>().ToList();
|
||||
|
||||
var pipelineStageCounts = new Dictionary<PipelineStage, int>
|
||||
{
|
||||
{ PipelineStage.Prospecting, 80 },
|
||||
{ PipelineStage.Qualification, 70 },
|
||||
{ PipelineStage.NeedAnalysis, 60 },
|
||||
{ PipelineStage.Proposal, 50 },
|
||||
{ PipelineStage.Negotiation, 40 },
|
||||
{ PipelineStage.DecisionMaking, 30 },
|
||||
{ PipelineStage.Closed, 15 }
|
||||
};
|
||||
|
||||
foreach (var stage in pipelineStageCounts)
|
||||
{
|
||||
for (int i = 0; i < stage.Value; i++)
|
||||
{
|
||||
var prospectingDate = GetRandomDate(dateStart, dateFinish, random);
|
||||
var closingEstimation = prospectingDate.AddDays(random.Next(30, 90));
|
||||
var closingActual = closingEstimation.AddDays(random.Next(-10, 11));
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var lead = new Lead
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
Title = $"Lead from {prospectingDate:MMMM yyyy}",
|
||||
Description = $"Lead description for {prospectingDate:MMMM yyyy}",
|
||||
CompanyName = $"Company Name {random.Next(1000, 9999)}",
|
||||
CompanyDescription = "Sample company description",
|
||||
CompanyAddressStreet = "123 Main St",
|
||||
CompanyAddressCity = "Anytown",
|
||||
CompanyAddressState = "State",
|
||||
CompanyAddressZipCode = "12345",
|
||||
CompanyAddressCountry = "Country",
|
||||
CompanyPhoneNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
CompanyFaxNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
CompanyEmail = $"info{random.Next(1000, 9999)}@company.com",
|
||||
CompanyWebsite = $"www.company{random.Next(1000, 9999)}.com",
|
||||
CompanyWhatsApp = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
CompanyLinkedIn = $"linkedin.com/company{random.Next(1000, 9999)}",
|
||||
CompanyFacebook = $"facebook.com/company{random.Next(1000, 9999)}",
|
||||
CompanyInstagram = $"instagram.com/company{random.Next(1000, 9999)}",
|
||||
CompanyTwitter = $"twitter.com/company{random.Next(1000, 9999)}",
|
||||
DateProspecting = prospectingDate,
|
||||
DateClosingEstimation = closingEstimation,
|
||||
DateClosingActual = closingActual,
|
||||
AmountTargeted = (decimal)(10000 * Math.Ceiling((random.NextDouble() * 89) + 1)),
|
||||
AmountClosed = (decimal)(10000 * Math.Ceiling((random.NextDouble() * 89) + 1)),
|
||||
BudgetScore = (decimal)(10.0 * Math.Ceiling(random.NextDouble() * 10)),
|
||||
AuthorityScore = (decimal)(10.0 * Math.Ceiling(random.NextDouble() * 10)),
|
||||
NeedScore = (decimal)(10.0 * Math.Ceiling(random.NextDouble() * 10)),
|
||||
TimelineScore = (decimal)(10.0 * Math.Ceiling(random.NextDouble() * 10)),
|
||||
PipelineStage = stage.Key,
|
||||
ClosingStatus = closingStatusValues[random.Next(closingStatusValues.Count)],
|
||||
ClosingNote = "Sample closing note",
|
||||
CampaignId = GetRandomValue(confirmedCampaigns, random),
|
||||
SalesTeamId = GetRandomValue(salesTeamIds, random)
|
||||
};
|
||||
|
||||
await context.Lead.AddAsync(lead);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static DateTime GetRandomDate(DateTime startDate, DateTime endDate, Random random)
|
||||
{
|
||||
var range = (endDate - startDate).Days;
|
||||
return startDate.AddDays(random.Next(range));
|
||||
}
|
||||
|
||||
private static string GetRandomValue(List<string> list, Random random)
|
||||
{
|
||||
return list[random.Next(list.Count)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class NegativeAdjustmentSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.NegativeAdjustment.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var adjustmentStatusValues = Enum.GetValues(typeof(AdjustmentStatus)).Cast<AdjustmentStatus>().ToList();
|
||||
var entityName = nameof(NegativeAdjustment);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var products = await context.Product
|
||||
.Where(x => x.Physical == true)
|
||||
.ToListAsync();
|
||||
|
||||
var warehouses = await context.Warehouse
|
||||
.Where(x => x.SystemWarehouse == false)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!products.Any() || !warehouses.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 (var transDate in transactionDates)
|
||||
{
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var adjustmentMinus = new NegativeAdjustment
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
AdjustmentDate = transDate,
|
||||
Status = adjustmentStatusValues[random.Next(adjustmentStatusValues.Count)],
|
||||
};
|
||||
await context.NegativeAdjustment.AddAsync(adjustmentMinus);
|
||||
|
||||
int numberOfProducts = random.Next(3, 6);
|
||||
for (int i = 0; i < numberOfProducts; i++)
|
||||
{
|
||||
var product = products[random.Next(products.Count)];
|
||||
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = adjustmentMinus.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "ADJ-",
|
||||
ModuleNumber = adjustmentMinus.AutoNumber,
|
||||
MovementDate = adjustmentMinus.AdjustmentDate!.Value,
|
||||
Status = (InventoryTransactionStatus)adjustmentMinus.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = GetRandomValue(warehouses, random),
|
||||
ProductId = product.Id,
|
||||
Movement = random.Next(1, 3)
|
||||
};
|
||||
|
||||
context.CalculateInvenTrans(inventoryTransaction);
|
||||
await context.InventoryTransaction.AddAsync(inventoryTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static DateTime[] GetRandomDays(int year, int month, int count)
|
||||
{
|
||||
var random = new Random();
|
||||
var daysInMonth = DateTime.DaysInMonth(year, month);
|
||||
return Enumerable.Range(1, count)
|
||||
.Select(_ => new DateTime(year, month, random.Next(1, daysInMonth + 1)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static T GetRandomValue<T>(IList<T> list, Random random)
|
||||
{
|
||||
return list[random.Next(list.Count)];
|
||||
}
|
||||
}
|
||||
@@ -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,98 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class PositiveAdjustmentSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.PositiveAdjustment.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var adjustmentStatusValues = Enum.GetValues(typeof(AdjustmentStatus)).Cast<AdjustmentStatus>().ToList();
|
||||
var entityName = nameof(PositiveAdjustment);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var products = await context.Product
|
||||
.Where(x => x.Physical == true)
|
||||
.ToListAsync();
|
||||
|
||||
var warehouses = await context.Warehouse
|
||||
.Where(x => x.SystemWarehouse == false)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!products.Any() || !warehouses.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 (var transDate in transactionDates)
|
||||
{
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var adjustmentPlus = new PositiveAdjustment
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
AdjustmentDate = transDate,
|
||||
Status = adjustmentStatusValues[random.Next(adjustmentStatusValues.Count)],
|
||||
};
|
||||
await context.PositiveAdjustment.AddAsync(adjustmentPlus);
|
||||
|
||||
int numberOfProducts = random.Next(3, 6);
|
||||
for (int i = 0; i < numberOfProducts; i++)
|
||||
{
|
||||
var product = products[random.Next(products.Count)];
|
||||
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = adjustmentPlus.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "ADJ+",
|
||||
ModuleNumber = adjustmentPlus.AutoNumber,
|
||||
MovementDate = adjustmentPlus.AdjustmentDate!.Value,
|
||||
Status = (InventoryTransactionStatus)adjustmentPlus.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = GetRandomValue(warehouses, random),
|
||||
ProductId = product.Id,
|
||||
Movement = random.Next(5, 10)
|
||||
};
|
||||
|
||||
context.CalculateInvenTrans(inventoryTransaction);
|
||||
await context.InventoryTransaction.AddAsync(inventoryTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static DateTime[] GetRandomDays(int year, int month, int count)
|
||||
{
|
||||
var random = new Random();
|
||||
var daysInMonth = DateTime.DaysInMonth(year, month);
|
||||
return Enumerable.Range(1, count)
|
||||
.Select(_ => new DateTime(year, month, random.Next(1, daysInMonth + 1)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static T GetRandomValue<T>(IList<T> list, Random random)
|
||||
{
|
||||
return list[random.Next(list.Count)];
|
||||
}
|
||||
}
|
||||
@@ -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,44 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class SalesRepresentativeSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.SalesRepresentative.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var entityName = nameof(SalesRepresentative);
|
||||
var salesTeams = await context.SalesTeam.ToListAsync();
|
||||
|
||||
foreach (var team in salesTeams)
|
||||
{
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var salesRep = new SalesRepresentative
|
||||
{
|
||||
Name = $"Rep {i} - {team.Name}",
|
||||
AutoNumber = autoNo,
|
||||
JobTitle = "Sales " + (i == 1 ? "Manager" : "Representative"),
|
||||
EmployeeNumber = $"EMP-{random.Next(1000, 9999)}",
|
||||
PhoneNumber = $"+1{random.Next(100, 999)}-{random.Next(100, 999)}-{random.Next(1000, 9999)}",
|
||||
EmailAddress = $"salesrep{i}@company.com",
|
||||
Description = $"Sales Rep for {team.Name}",
|
||||
SalesTeamId = team.Id
|
||||
};
|
||||
|
||||
await context.SalesRepresentative.AddAsync(salesRep);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
@@ -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,33 @@
|
||||
using Indotalent.Data.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class SalesTeamSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.SalesTeam.AnyAsync()) return;
|
||||
|
||||
var salesTeams = new List<SalesTeam>
|
||||
{
|
||||
new SalesTeam { Name = "The Trailblazers" },
|
||||
new SalesTeam { Name = "Revenue Rockets" },
|
||||
new SalesTeam { Name = "Deal Makers" },
|
||||
new SalesTeam { Name = "Sales Ninjas" },
|
||||
new SalesTeam { Name = "Profit Pioneers" },
|
||||
new SalesTeam { Name = "Closing Crew" },
|
||||
new SalesTeam { Name = "Growth Gurus" },
|
||||
new SalesTeam { Name = "The Persuaders" },
|
||||
new SalesTeam { Name = "Market Mavens" },
|
||||
new SalesTeam { Name = "Sales Savants" }
|
||||
};
|
||||
|
||||
foreach (var salesTeam in salesTeams)
|
||||
{
|
||||
await context.SalesTeam.AddAsync(salesTeam);
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
@@ -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 ScrappingSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Scrapping.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var scrappingStatusValues = Enum.GetValues(typeof(ScrappingStatus)).Cast<ScrappingStatus>().ToList();
|
||||
var entityName = nameof(Scrapping);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var products = await context.Product
|
||||
.Where(x => x.Physical == true)
|
||||
.ToListAsync();
|
||||
|
||||
var warehouses = await context.Warehouse
|
||||
.Where(x => x.SystemWarehouse == false)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!products.Any() || !warehouses.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 (var transDate in transactionDates)
|
||||
{
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var scrapping = new Scrapping
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
ScrappingDate = transDate,
|
||||
Status = scrappingStatusValues[random.Next(scrappingStatusValues.Count)],
|
||||
WarehouseId = GetRandomValue(warehouses, random),
|
||||
};
|
||||
await context.Scrapping.AddAsync(scrapping);
|
||||
|
||||
int numberOfProducts = random.Next(3, 6);
|
||||
for (int i = 0; i < numberOfProducts; i++)
|
||||
{
|
||||
var product = products[random.Next(products.Count)];
|
||||
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = scrapping.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "SCRP",
|
||||
ModuleNumber = scrapping.AutoNumber,
|
||||
MovementDate = scrapping.ScrappingDate!.Value,
|
||||
Status = (InventoryTransactionStatus)scrapping.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = scrapping.WarehouseId,
|
||||
ProductId = product.Id,
|
||||
Movement = (double)random.Next(1, 10)
|
||||
};
|
||||
|
||||
context.CalculateInvenTrans(inventoryTransaction);
|
||||
await context.InventoryTransaction.AddAsync(inventoryTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static DateTime[] GetRandomDays(int year, int month, int count)
|
||||
{
|
||||
var random = new Random();
|
||||
var daysInMonth = DateTime.DaysInMonth(year, month);
|
||||
return Enumerable.Range(1, count)
|
||||
.Select(_ => new DateTime(year, month, random.Next(1, daysInMonth + 1)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static T GetRandomValue<T>(IList<T> list, Random random)
|
||||
{
|
||||
return list[random.Next(list.Count)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class StockCountSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.StockCount.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var stockCountStatusValues = Enum.GetValues(typeof(StockCountStatus)).Cast<StockCountStatus>().ToList();
|
||||
var entityName = nameof(StockCount);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var products = await context.Product
|
||||
.Where(x => x.Physical == true)
|
||||
.ToListAsync();
|
||||
|
||||
var warehouses = await context.Warehouse
|
||||
.Where(x => x.SystemWarehouse == false)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!products.Any() || !warehouses.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 (var transDate in transactionDates)
|
||||
{
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var stockCount = new StockCount
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
CountDate = transDate,
|
||||
Status = stockCountStatusValues[random.Next(stockCountStatusValues.Count)],
|
||||
WarehouseId = GetRandomValue(warehouses, random),
|
||||
};
|
||||
await context.StockCount.AddAsync(stockCount);
|
||||
|
||||
int numberOfProducts = random.Next(3, 6);
|
||||
for (int i = 0; i < numberOfProducts; i++)
|
||||
{
|
||||
var product = products[random.Next(products.Count)];
|
||||
|
||||
var stock = context.GetStock(stockCount.WarehouseId, product.Id);
|
||||
var qtyCount = stock + (double)random.Next(-10, 10);
|
||||
|
||||
if (qtyCount <= 0.0)
|
||||
{
|
||||
if (qtyCount < 0.0)
|
||||
{
|
||||
qtyCount = Math.Abs(qtyCount) * 2.0;
|
||||
}
|
||||
else if (qtyCount == 0.0)
|
||||
{
|
||||
qtyCount = qtyCount + (double)random.Next(40, 50);
|
||||
}
|
||||
}
|
||||
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = stockCount.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "COUNT",
|
||||
ModuleNumber = stockCount.AutoNumber,
|
||||
MovementDate = stockCount.CountDate!.Value,
|
||||
Status = (InventoryTransactionStatus)stockCount.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = stockCount.WarehouseId,
|
||||
ProductId = product.Id,
|
||||
QtySCCount = qtyCount,
|
||||
};
|
||||
|
||||
context.CalculateInvenTrans(inventoryTransaction);
|
||||
await context.InventoryTransaction.AddAsync(inventoryTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static DateTime[] GetRandomDays(int year, int month, int count)
|
||||
{
|
||||
var random = new Random();
|
||||
var daysInMonth = DateTime.DaysInMonth(year, month);
|
||||
return Enumerable.Range(1, count)
|
||||
.Select(_ => new DateTime(year, month, random.Next(1, daysInMonth + 1)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static T GetRandomValue<T>(IList<T> list, Random random)
|
||||
{
|
||||
return list[random.Next(list.Count)];
|
||||
}
|
||||
}
|
||||
@@ -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 TransferInSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.TransferIn.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var transferStatusValues = Enum.GetValues(typeof(TransferStatus)).Cast<TransferStatus>().ToList();
|
||||
var entityName = nameof(TransferIn);
|
||||
var transferOutEntityName = nameof(TransferOut);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var transferOuts = await context.TransferOut
|
||||
.Where(x => x.Status >= TransferStatus.Confirmed)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var transferOut in transferOuts)
|
||||
{
|
||||
bool skip = random.Next(2) == 0;
|
||||
if (skip) continue;
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var transferIn = new TransferIn
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
TransferReceiveDate = transferOut.TransferReleaseDate?.AddDays(random.Next(1, 5)),
|
||||
Status = transferStatusValues[random.Next(transferStatusValues.Count)],
|
||||
TransferOutId = transferOut.Id,
|
||||
};
|
||||
await context.TransferIn.AddAsync(transferIn);
|
||||
|
||||
var items = await context.InventoryTransaction
|
||||
.Where(x => x.ModuleId == transferOut.Id && x.ModuleName == transferOutEntityName)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = transferIn.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "TO-IN",
|
||||
ModuleNumber = transferIn.AutoNumber,
|
||||
MovementDate = transferIn.TransferReceiveDate!.Value,
|
||||
Status = (InventoryTransactionStatus)transferIn.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = transferOut.WarehouseToId,
|
||||
ProductId = item.ProductId,
|
||||
Movement = item.Movement
|
||||
};
|
||||
|
||||
context.CalculateInvenTrans(inventoryTransaction);
|
||||
await context.InventoryTransaction.AddAsync(inventoryTransaction);
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Data.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.Demo;
|
||||
|
||||
public static class TransferOutSeeder
|
||||
{
|
||||
public static async Task GenerateDataAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.TransferOut.AnyAsync()) return;
|
||||
|
||||
var random = new Random();
|
||||
var transferStatusValues = Enum.GetValues(typeof(TransferStatus)).Cast<TransferStatus>().ToList();
|
||||
var entityName = nameof(TransferOut);
|
||||
var ivtEntityName = nameof(InventoryTransaction);
|
||||
|
||||
var products = await context.Product
|
||||
.Where(x => x.Physical == true)
|
||||
.ToListAsync();
|
||||
|
||||
var warehouses = await context.Warehouse
|
||||
.Where(x => x.SystemWarehouse == false)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!products.Any() || warehouses.Count < 2) 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))
|
||||
{
|
||||
var transactionDates = GetRandomDays(date.Year, date.Month, 6);
|
||||
|
||||
foreach (DateTime transDate in transactionDates)
|
||||
{
|
||||
var fromId = GetRandomValue(warehouses, random);
|
||||
var toId = GetRandomValue(warehouses.Where(x => x != fromId).ToList(), random);
|
||||
|
||||
var autoNo = await context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var transferOut = new TransferOut
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
TransferReleaseDate = transDate,
|
||||
Status = transferStatusValues[random.Next(transferStatusValues.Count)],
|
||||
WarehouseFromId = fromId,
|
||||
WarehouseToId = toId,
|
||||
};
|
||||
await context.TransferOut.AddAsync(transferOut);
|
||||
|
||||
int numberOfProducts = random.Next(3, 6);
|
||||
for (int i = 0; i < numberOfProducts; i++)
|
||||
{
|
||||
var product = GetRandomValue(products, random);
|
||||
|
||||
var autoNoIVT = await context.GenerateAutoNumberAsync(
|
||||
entityName: ivtEntityName,
|
||||
prefixTemplate: $"{ivtEntityName.ToShortNameConsonant(3)}/{{Year}}/"
|
||||
);
|
||||
|
||||
var inventoryTransaction = new InventoryTransaction
|
||||
{
|
||||
ModuleId = transferOut.Id,
|
||||
ModuleName = entityName,
|
||||
ModuleCode = "TO-OUT",
|
||||
ModuleNumber = transferOut.AutoNumber,
|
||||
MovementDate = transferOut.TransferReleaseDate!.Value,
|
||||
Status = (InventoryTransactionStatus)transferOut.Status,
|
||||
AutoNumber = autoNoIVT,
|
||||
WarehouseId = transferOut.WarehouseFromId,
|
||||
ProductId = product.Id,
|
||||
Movement = (double)random.Next(1, 10)
|
||||
};
|
||||
|
||||
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)];
|
||||
}
|
||||
|
||||
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 index = random.Next(daysInMonth.Count);
|
||||
selectedDays.Add(daysInMonth[index]);
|
||||
daysInMonth.RemoveAt(index);
|
||||
}
|
||||
|
||||
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 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,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 BudgetConfiguration : IEntityTypeConfiguration<Budget>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Budget> builder)
|
||||
{
|
||||
builder.Property(e => e.AutoNumber)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Title)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Description)
|
||||
.HasMaxLength(GlobalConsts.StringLengthMedium);
|
||||
|
||||
builder.Property(e => e.CampaignId)
|
||||
.HasMaxLength(GlobalConsts.StringLengthId);
|
||||
|
||||
builder.HasOne(e => e.Campaign)
|
||||
.WithMany()
|
||||
.HasForeignKey(e => e.CampaignId)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasIndex(e => e.AutoNumber).IsUnique();
|
||||
builder.HasIndex(e => e.BudgetDate);
|
||||
builder.HasIndex(e => e.CampaignId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Indotalent.Data.Entities;
|
||||
using Indotalent.Shared.Consts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace Indotalent.Infrastructure.Database.MsSQL.Configuration;
|
||||
|
||||
public class CampaignConfiguration : IEntityTypeConfiguration<Campaign>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Campaign> builder)
|
||||
{
|
||||
builder.Property(e => e.AutoNumber)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Title)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Description)
|
||||
.HasMaxLength(GlobalConsts.StringLengthMedium);
|
||||
|
||||
builder.Property(e => e.SalesTeamId)
|
||||
.HasMaxLength(GlobalConsts.StringLengthId);
|
||||
|
||||
builder.HasOne(e => e.SalesTeam)
|
||||
.WithMany()
|
||||
.HasForeignKey(e => e.SalesTeamId)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasMany(e => e.BudgetList)
|
||||
.WithOne(e => e.Campaign)
|
||||
.HasForeignKey(e => e.CampaignId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasMany(e => e.ExpenseList)
|
||||
.WithOne(e => e.Campaign)
|
||||
.HasForeignKey(e => e.CampaignId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasMany(e => e.LeadList)
|
||||
.WithOne(e => e.Campaign)
|
||||
.HasForeignKey(e => e.CampaignId)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasIndex(e => e.AutoNumber).IsUnique();
|
||||
builder.HasIndex(e => e.SalesTeamId);
|
||||
builder.HasIndex(e => e.CampaignDateStart);
|
||||
builder.HasIndex(e => e.CampaignDateFinish);
|
||||
}
|
||||
}
|
||||
@@ -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,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 ExpenseConfiguration : IEntityTypeConfiguration<Expense>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Expense> builder)
|
||||
{
|
||||
builder.Property(e => e.AutoNumber)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Title)
|
||||
.HasMaxLength(GlobalConsts.StringLengthShort);
|
||||
|
||||
builder.Property(e => e.Description)
|
||||
.HasMaxLength(GlobalConsts.StringLengthMedium);
|
||||
|
||||
builder.Property(e => e.CampaignId)
|
||||
.HasMaxLength(GlobalConsts.StringLengthId);
|
||||
|
||||
builder.HasOne(e => e.Campaign)
|
||||
.WithMany(e => e.ExpenseList)
|
||||
.HasForeignKey(e => e.CampaignId)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasIndex(e => e.AutoNumber).IsUnique();
|
||||
builder.HasIndex(e => e.ExpenseDate);
|
||||
builder.HasIndex(e => e.CampaignId);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user