Finishline #90
@@ -20,8 +20,11 @@
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
"Default": "Warning",
|
||||
"Quartz": "Error",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Microsoft.EntityFrameworkCore.Database": "Error",
|
||||
"Microsoft.EntityFrameworkCore.Update": "Error"
|
||||
}
|
||||
},
|
||||
"EmailProcessorCron": "0 */5 * * * ?",
|
||||
|
||||
@@ -7,12 +7,16 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface ICommunicationsService
|
||||
{
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,32 +7,44 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IEvidenceService
|
||||
{
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateMilestoneAsync(CreateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken);
|
||||
|
||||
[Log]
|
||||
Task<Result<Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateEvidenceAsync(UpdateEvidenceRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<string>> GetEvidenceUrlAsync(string evidenceIdHash, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,26 +7,35 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IExecutionService
|
||||
{
|
||||
[Log]
|
||||
Task<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,31 +7,43 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IGovernanceService
|
||||
{
|
||||
[Log]
|
||||
Task<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreatePortfolioAsync(CreatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdatePortfolioAsync(UpdatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
[Log]
|
||||
Task<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
[Log]
|
||||
Task<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,36 +7,49 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IGrantsService
|
||||
{
|
||||
[Log]
|
||||
Task<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result<string>> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UploadContractAsync(string contractIdHash, Guid userId, IFormFile file, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateContractAsync(UpdateContractRequest request, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IIdentityService
|
||||
{
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UserIsAuthorisedAsync(Guid userId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,48 +7,67 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IProjectService
|
||||
{
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> CreateProgrammeAsync(CreateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateProgrammeAsync(UpdateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
[Log]
|
||||
Task<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
||||
|
||||
public interface IUserService
|
||||
{
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> SyncUserAsync(Guid userId, string email, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
[Audit]
|
||||
Task<Result> UpdateUserStatusAsync(Guid userId, ActivityStatus status, CancellationToken cancellationToken = default);
|
||||
|
||||
[Log]
|
||||
Task<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace PostFundManagement.Application.Extensions;
|
||||
|
||||
public static class Services
|
||||
{
|
||||
public static IServiceCollection AddAuditedCachedScoped<TInterface, TImplementation, TCacheDecorator>(this IServiceCollection services)
|
||||
public static IServiceCollection AddLoggedCachedServiceScoped<TInterface, TImplementation, TCacheDecorator>(this IServiceCollection services)
|
||||
where TInterface : class
|
||||
where TImplementation : class, TInterface
|
||||
where TCacheDecorator : class, TInterface
|
||||
@@ -27,30 +27,40 @@ public static class Services
|
||||
services.AddScoped(sp =>
|
||||
{
|
||||
var proxyGenerator = sp.GetRequiredService<ProxyGenerator>();
|
||||
var interceptor = sp.GetRequiredService<AuditInterceptor>();
|
||||
var loggingInterceptor = sp.GetRequiredService<LoggingInterceptor>();
|
||||
|
||||
var actual = sp.GetRequiredService<TImplementation>();
|
||||
|
||||
var cached = ActivatorUtilities.CreateInstance<TCacheDecorator>(sp, actual);
|
||||
|
||||
return proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(cached, interceptor.ToInterceptor());
|
||||
return proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(cached,
|
||||
loggingInterceptor.ToInterceptor());
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddAuditedScoped<TInterface, TImplementation>(this IServiceCollection services)
|
||||
where TInterface : class
|
||||
where TImplementation : class, TInterface
|
||||
public static IServiceCollection AddLoggedAuditedCachedServiceScoped<TInterface, TImplementation, TCacheDecorator>(this IServiceCollection services)
|
||||
where TInterface : class
|
||||
where TImplementation : class, TInterface
|
||||
where TCacheDecorator : class, TInterface
|
||||
{
|
||||
services.AddScoped<TImplementation>();
|
||||
services.AddScoped<TCacheDecorator>();
|
||||
|
||||
services.AddScoped(sp =>
|
||||
{
|
||||
var proxyGenerator = sp.GetRequiredService<ProxyGenerator>();
|
||||
var actual = sp.GetRequiredService<TImplementation>();
|
||||
var interceptor = sp.GetRequiredService<AuditInterceptor>();
|
||||
var auditInterceptor = sp.GetRequiredService<AuditInterceptor>();
|
||||
var loggingInterceptor = sp.GetRequiredService<LoggingInterceptor>();
|
||||
|
||||
return proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(actual, interceptor.ToInterceptor());
|
||||
var actual = sp.GetRequiredService<TImplementation>();
|
||||
|
||||
var cached = ActivatorUtilities.CreateInstance<TCacheDecorator>(sp, actual);
|
||||
|
||||
return proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(cached,
|
||||
loggingInterceptor.ToInterceptor(),
|
||||
auditInterceptor.ToInterceptor());
|
||||
});
|
||||
|
||||
return services;
|
||||
@@ -59,21 +69,19 @@ public static class Services
|
||||
public static IServiceCollection AddRegisterServicesWithCaching(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddScoped<AuditInterceptor>();
|
||||
services.AddScoped<LoggingInterceptor>();
|
||||
services.AddSingleton<ProxyGenerator>();
|
||||
|
||||
services.AddAuditedCachedScoped<ICommunicationsService, CommunicationsService, CommunicationsCacheService>();
|
||||
services.AddAuditedCachedScoped<IEvidenceService, EvidenceService, EvidenceCacheService>();
|
||||
services.AddAuditedCachedScoped<IUserService, UserService, UserCacheService>();
|
||||
services.AddAuditedCachedScoped<IExecutionService, ExecutionService, ExecutionCacheService>();
|
||||
services.AddAuditedCachedScoped<IGovernanceService, GovernanceService, GovernanceCacheService>();
|
||||
services.AddAuditedCachedScoped<IGrantsService, GrantsService, GrantsCacheService>();
|
||||
services.AddAuditedCachedScoped<IProjectService, ProjectService, ProjectCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<ICommunicationsService, CommunicationsService, CommunicationsCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IEvidenceService, EvidenceService, EvidenceCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IUserService, UserService, UserCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IExecutionService, ExecutionService, ExecutionCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IGovernanceService, GovernanceService, GovernanceCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IGrantsService, GrantsService, GrantsCacheService>();
|
||||
services.AddLoggedAuditedCachedServiceScoped<IProjectService, ProjectService, ProjectCacheService>();
|
||||
|
||||
services.AddScoped<IIdentityService, IdentityService>();
|
||||
services.Decorate<IIdentityService, IdentityCacheService>();
|
||||
|
||||
services.AddScoped<IToolService, ToolService>();
|
||||
services.Decorate<IToolService, ToolCacheService>();
|
||||
services.AddLoggedCachedServiceScoped<IIdentityService, IdentityService, IdentityCacheService>();
|
||||
services.AddLoggedCachedServiceScoped<IToolService, ToolService, ToolCacheService>();
|
||||
|
||||
services.AddStackExchangeRedisCache(options =>
|
||||
{
|
||||
|
||||
@@ -25,8 +25,12 @@ public sealed class ActiveUserFilter(IIdentityService identityService) : IEndpoi
|
||||
var path = context.HttpContext.Request.Path.Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(path) && !path!.EndsWith("integration/sync", StringComparison.InvariantCultureIgnoreCase))
|
||||
if ((await identityService.UserIsAuthorisedAsync(userId, context.HttpContext.RequestAborted)).IsFailed)
|
||||
{
|
||||
var userAuthResult = await identityService.UserIsAuthorisedAsync(userId, context.HttpContext.RequestAborted);
|
||||
|
||||
if (userAuthResult.IsFailed)
|
||||
return Results.Json(new { message = "Account approval is pending or inactive." }, statusCode: StatusCodes.Status403Forbidden);
|
||||
}
|
||||
|
||||
context.HttpContext.Items[UserIdItemKey] = userId;
|
||||
context.HttpContext.Items[EmailtemKey] = email;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using PostFundManagement.Domain.Attributes;
|
||||
|
||||
namespace PostFundManagement.Application.Interceptors;
|
||||
|
||||
public sealed class LoggingInterceptor(ILogger<LoggingInterceptor> logger) : IAsyncInterceptor
|
||||
{
|
||||
public void InterceptSynchronous(IInvocation invocation)
|
||||
{
|
||||
invocation.Proceed();
|
||||
|
||||
CheckAndLogIfFailed(invocation, invocation.ReturnValue);
|
||||
}
|
||||
|
||||
public void InterceptAsynchronous(IInvocation invocation) =>
|
||||
invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
|
||||
|
||||
public void InterceptAsynchronous<TResult>(IInvocation invocation) =>
|
||||
invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
|
||||
|
||||
private static async Task InternalInterceptAsynchronous(IInvocation invocation)
|
||||
{
|
||||
invocation.Proceed();
|
||||
|
||||
var task = (Task)invocation.ReturnValue;
|
||||
|
||||
await task.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
|
||||
{
|
||||
invocation.Proceed();
|
||||
|
||||
var task = (Task<TResult>)invocation.ReturnValue;
|
||||
var resultObj = await task.ConfigureAwait(false);
|
||||
|
||||
var method = invocation.MethodInvocationTarget ?? invocation.Method;
|
||||
var auditAttr = method.GetCustomAttribute<LogAttribute>()
|
||||
?? invocation.Method.GetCustomAttribute<LogAttribute>();
|
||||
|
||||
if (auditAttr == null) return resultObj;
|
||||
|
||||
CheckAndLogIfFailed(invocation, resultObj);
|
||||
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
private void CheckAndLogIfFailed(IInvocation invocation, object? resultObj)
|
||||
{
|
||||
if (resultObj is IResultBase result && result.IsFailed)
|
||||
{
|
||||
try
|
||||
{
|
||||
var method = invocation.MethodInvocationTarget ?? invocation.Method;
|
||||
var parameters = BuildPayloadSummary(method.GetParameters(), invocation.Arguments);
|
||||
|
||||
var errorMessages = new List<string>();
|
||||
|
||||
if (result.Reasons != null)
|
||||
{
|
||||
foreach (var reason in result.Reasons)
|
||||
if (reason is IError error)
|
||||
errorMessages.Add(error.Message);
|
||||
}
|
||||
|
||||
var errorsString = string.Join("; ", errorMessages);
|
||||
|
||||
logger.LogError("Method {MethodName} failed. Errors: [{ErrorType}] {Errors}. Parameters: {@Parameters}",
|
||||
method.Name, result.Reasons?.FirstOrDefault()?.GetType().Name.Replace("Error", string.Empty), errorsString, parameters);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "Failed to write error log for method {MethodName}.", invocation.Method.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] BuildPayloadSummary(ParameterInfo[] parameters, object[] args)
|
||||
{
|
||||
var entries = new List<string>();
|
||||
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var param = parameters[i];
|
||||
var arg = args[i];
|
||||
|
||||
if (param.ParameterType == typeof(CancellationToken))
|
||||
continue;
|
||||
|
||||
if (arg == null)
|
||||
{
|
||||
entries.Add($"{param.Name}: null");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg is IFormFile file)
|
||||
{
|
||||
entries.Add($"{param.Name}: [File] Name='{file.FileName}', Size={file.Length} bytes, Type='{file.ContentType}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg is IEnumerable<IFormFile> files)
|
||||
{
|
||||
var fileSummaries = new List<string>();
|
||||
|
||||
foreach (var f in files)
|
||||
fileSummaries.Add($"'{f.FileName}' ({f.Length} bytes)");
|
||||
|
||||
entries.Add($"{param.Name}: [Files] count={fileSummaries.Count} [{string.Join(", ", fileSummaries)}]");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg is Stream stream)
|
||||
{
|
||||
entries.Add($"{param.Name}: [Stream] Length={(stream.CanSeek ? stream.Length : -1)} bytes");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(arg);
|
||||
|
||||
entries.Add($"{param.Name}: {json}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
entries.Add($"{param.Name}: [Unserializable]");
|
||||
}
|
||||
}
|
||||
|
||||
return [.. entries];
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public sealed class UserService(IDbContextFactory<ApplicationDbContext> contextF
|
||||
var user = await context.Users.AsNoTracking()
|
||||
.FirstOrDefaultAsync(f => f.Id == userId, cancellationToken);
|
||||
|
||||
return Result.FailIf(user is null, NotFoundError.New)
|
||||
.ToResult(user!.Map());
|
||||
return Result.FailIf(user == null, NotFoundError.New)
|
||||
.ToResult(user?.Map()!);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PostFundManagement.Domain.Abstractions;
|
||||
|
||||
public interface ITenantEntity
|
||||
{
|
||||
public long TenantId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace PostFundManagement.Domain.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class LogAttribute : Attribute;
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ActivityConfiguration, Activity>]
|
||||
public class Activity : Models.Activity
|
||||
public class Activity : Models.Activity, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
public virtual User? Updator { get; set; }
|
||||
@@ -26,6 +29,7 @@ public sealed class ActivityConfiguration : IEntityTypeConfiguration<Activity>
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.MilestoneId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UpdatedBy).IsRequired(false);
|
||||
@@ -40,6 +44,12 @@ public sealed class ActivityConfiguration : IEntityTypeConfiguration<Activity>
|
||||
builder.Property(f => f.Title).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -16,7 +16,7 @@ public sealed class AuditLogConfiguration : IEntityTypeConfiguration<AuditLog>
|
||||
builder.Property(f => f.EntityName).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.EntityId).IsRequired();
|
||||
builder.Property(f => f.Action).IsRequired().HasMaxLength(ShortLabelLength);
|
||||
builder.Property(f => f.Changes).IsRequired(false).HasColumnType("jsonb");
|
||||
builder.Property(f => f.Changes).IsRequired(false);
|
||||
builder.Property(f => f.PerformedBy).IsRequired();
|
||||
builder.Property(f => f.Timestamp).IsRequired().HasDefaultValueSql("now()");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<AwardConfiguration, Award>]
|
||||
public class Award : Models.Award
|
||||
public class Award : Models.Award, ITenantEntity
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
@@ -77,9 +79,9 @@ public sealed class AwardConfiguration : IEntityTypeConfiguration<Award>
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Approver)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ApprovedBy)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ApprovedBy)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<BeneficiaryConfiguration, Beneficiary>]
|
||||
public class Beneficiary : Models.Beneficiary
|
||||
public class Beneficiary : Models.Beneficiary, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
[ForeignKey(nameof(CreatedBy))]
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public virtual User? User { get; set; }
|
||||
}
|
||||
|
||||
@@ -19,6 +24,7 @@ public sealed class BeneficiaryConfiguration : IEntityTypeConfiguration<Benefici
|
||||
builder.ToTable(nameof(Beneficiary).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UserId).IsRequired();
|
||||
@@ -29,6 +35,12 @@ public sealed class BeneficiaryConfiguration : IEntityTypeConfiguration<Benefici
|
||||
builder.Property(f => f.ReachedCount).IsRequired();
|
||||
builder.Property(f => f.Location).IsRequired();
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<BudgetConfiguration, Budget>]
|
||||
public class Budget : Models.Budget
|
||||
public class Budget : Models.Budget, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class BudgetConfiguration : IEntityTypeConfiguration<Budget>
|
||||
builder.ToTable(nameof(Budget).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.ApprovedBy).IsRequired(false);
|
||||
@@ -27,6 +31,12 @@ public sealed class BudgetConfiguration : IEntityTypeConfiguration<Budget>
|
||||
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ChangeRequestConfiguration, ChangeRequest>]
|
||||
public class ChangeRequest : Models.ChangeRequest
|
||||
public class ChangeRequest : Models.ChangeRequest, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class ChangeRequestConfiguration : IEntityTypeConfiguration<Change
|
||||
builder.ToTable(nameof(ChangeRequest).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.ApprovedBy).IsRequired(false);
|
||||
@@ -31,6 +35,12 @@ public sealed class ChangeRequestConfiguration : IEntityTypeConfiguration<Change
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ComplianceItemConfiguration, ComplianceItem>]
|
||||
public class ComplianceItem : Models.ComplianceItem
|
||||
public class ComplianceItem : Models.ComplianceItem, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class ComplianceItemConfiguration : IEntityTypeConfiguration<Compl
|
||||
builder.ToTable(nameof(ComplianceItem).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.VerifiedBy).IsRequired(false);
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ContractConfiguration, Contract>]
|
||||
public class Contract : Models.Contract
|
||||
public class Contract : Models.Contract, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Award? Award { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -15,8 +19,8 @@ public sealed class ContractConfiguration : IEntityTypeConfiguration<Contract>
|
||||
builder.ToTable(nameof(Contract).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.HasIndex(f => f.AwardId).IsUnique();
|
||||
|
||||
builder.Property(f => f.AwardId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
@@ -28,6 +32,12 @@ public sealed class ContractConfiguration : IEntityTypeConfiguration<Contract>
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ContractStatus.Draft);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Award)
|
||||
.WithOne(f => f.Contract)
|
||||
.HasForeignKey<Domain.Entities.Contract>(fk => fk.AwardId)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<DisbursementConfiguration, Disbursement>]
|
||||
public class Disbursement : Models.Disbursement
|
||||
public class Disbursement : Models.Disbursement, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual Milestone? Milestone { get; set; }
|
||||
@@ -19,6 +23,7 @@ public sealed class DisbursementConfiguration : IEntityTypeConfiguration<Disburs
|
||||
builder.ToTable(nameof(Disbursement).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.MilestoneId).IsRequired(false);
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
@@ -29,6 +34,12 @@ public sealed class DisbursementConfiguration : IEntityTypeConfiguration<Disburs
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<EvidenceConfiguration, Evidence>]
|
||||
public class Evidence : Models.Evidence
|
||||
public class Evidence : Models.Evidence, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual Milestone? Milestone { get; set; }
|
||||
@@ -23,6 +27,7 @@ public sealed class EvidenceConfiguration : IEntityTypeConfiguration<Evidence>
|
||||
builder.ToTable(nameof(Evidence).Pluralize());
|
||||
|
||||
builder.HasKey(f => f.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.MilestoneId).IsRequired();
|
||||
builder.Property(f => f.IndicatorId).IsRequired();
|
||||
@@ -38,6 +43,12 @@ public sealed class EvidenceConfiguration : IEntityTypeConfiguration<Evidence>
|
||||
builder.Property(f => f.Type).IsRequired().HasConversion<int>().HasDefaultValueSql("9")
|
||||
.HasSentinel(EvidenceType.ProcurementDocument);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<IndicatorConfiguration, Indicator>]
|
||||
public class Indicator : Models.Indicator
|
||||
public class Indicator : Models.Indicator, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -17,6 +20,7 @@ public sealed class IndicatorConfiguration : IEntityTypeConfiguration<Indicator>
|
||||
builder.ToTable(nameof(Indicator).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
@@ -26,6 +30,12 @@ public sealed class IndicatorConfiguration : IEntityTypeConfiguration<Indicator>
|
||||
builder.Property(f => f.TargetAmount).IsRequired().HasPrecision(18, 2);
|
||||
builder.Property(f => f.ActualAmount).IsRequired().HasPrecision(18, 2);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<InstrumentConfiguration, Instrument>]
|
||||
public class Instrument : Models.Instrument
|
||||
public class Instrument : Models.Instrument, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
public virtual Programme? Programme { get; set; }
|
||||
@@ -17,6 +20,7 @@ public sealed class InstrumentConfiguration : IEntityTypeConfiguration<Instrumen
|
||||
builder.ToTable(nameof(Instrument).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProgrammeId).IsRequired();
|
||||
builder.Property(f => f.Code).IsRequired().HasMaxLength(ShortLabelLength);
|
||||
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
|
||||
@@ -26,6 +30,12 @@ public sealed class InstrumentConfiguration : IEntityTypeConfiguration<Instrumen
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Programme)
|
||||
.WithMany(f => f.Instruments)
|
||||
.HasForeignKey(fk => fk.ProgrammeId)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<InviteConfiguration, Invite>]
|
||||
public class Invite : Models.Invite
|
||||
public class Invite : Models.Invite, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Organisation? Organisation { get; set; }
|
||||
|
||||
public virtual Organisation? InvitedOrganisation { get; set; }
|
||||
@@ -21,6 +25,7 @@ public sealed class InviteConfiguration : IEntityTypeConfiguration<Invite>
|
||||
builder.ToTable(nameof(Invite).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.OrganisationId).IsRequired();
|
||||
builder.Property(f => f.InvitedOrganisationId).IsRequired();
|
||||
builder.Property(f => f.AwardId).IsRequired();
|
||||
@@ -31,6 +36,12 @@ public sealed class InviteConfiguration : IEntityTypeConfiguration<Invite>
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.UpdatedAt).IsRequired(false);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Organisation)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.OrganisationId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<IssueConfiguration, Issue>]
|
||||
public class Issue : Models.Issue
|
||||
public class Issue : Models.Issue, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class IssueConfiguration : IEntityTypeConfiguration<Issue>
|
||||
builder.ToTable(nameof(Issue).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
@@ -32,6 +36,12 @@ public sealed class IssueConfiguration : IEntityTypeConfiguration<Issue>
|
||||
.HasSentinel(ActivityStatus.Active);
|
||||
builder.Property(f => f.Resolution).IsRequired();
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<MilestoneConfiguration, Milestone>]
|
||||
public class Milestone : Models.Milestone
|
||||
public class Milestone : Models.Milestone, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class MilestoneConfiguration : IEntityTypeConfiguration<Milestone>
|
||||
builder.ToTable(nameof(Milestone).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UpdatedBy).IsRequired(false);
|
||||
@@ -31,6 +35,12 @@ public sealed class MilestoneConfiguration : IEntityTypeConfiguration<Milestone>
|
||||
builder.Property(f => f.Priority).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(Priority.Low);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<NotificationConfiguration, Notification>]
|
||||
public class Notification : Models.Notification
|
||||
public class Notification : Models.Notification, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<OutcomeConfiguration, Outcome>]
|
||||
public class Outcome : Models.Outcome
|
||||
public class Outcome : Models.Outcome, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Beneficiary? Beneficiary { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -17,12 +20,19 @@ public sealed class OutcomeConfiguration : IEntityTypeConfiguration<Outcome>
|
||||
builder.ToTable(nameof(Outcome).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.BeneficiaryId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Beneficiary)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.BeneficiaryId)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<PortfolioConfiguration, Portfolio>]
|
||||
public class Portfolio : Models.Portfolio
|
||||
public class Portfolio : Models.Portfolio, ITenantEntity
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ProgrammeConfiguration, Programme>]
|
||||
public class Programme : Models.Programme
|
||||
public class Programme : Models.Programme, ITenantEntity
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ProjectConfiguration, Project>]
|
||||
public class Project : Models.Project
|
||||
public class Project : Models.Project, ITenantEntity
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<RiskConfiguration, Risk>]
|
||||
public class Risk : Models.Risk
|
||||
public class Risk : Models.Risk, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
@@ -17,6 +20,7 @@ public sealed class RiskConfiguration : IEntityTypeConfiguration<Risk>
|
||||
builder.ToTable(nameof(Risk).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
@@ -27,6 +31,12 @@ public sealed class RiskConfiguration : IEntityTypeConfiguration<Risk>
|
||||
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<RuleConfiguration, Rule>]
|
||||
public class Rule : Models.Rule
|
||||
public class Rule : Models.Rule, ITenantEntity
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
public virtual User? Updator { get; set; }
|
||||
@@ -19,6 +22,7 @@ public sealed class RuleConfiguration : IEntityTypeConfiguration<Rule>
|
||||
builder.ToTable(nameof(Rule).Pluralize());
|
||||
|
||||
builder.HasKey(fk => fk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProgrammeId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UpdatedBy).IsRequired(false);
|
||||
@@ -29,6 +33,12 @@ public sealed class RuleConfiguration : IEntityTypeConfiguration<Rule>
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("2")
|
||||
.HasSentinel(ActivityStatus.Inactive);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Programme)
|
||||
.WithMany(f => f.Rules)
|
||||
.HasForeignKey(fk => fk.ProgrammeId)
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using PostFundManagement.Domain.Abstractions;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<SiteVisitConfiguration, SiteVisit>]
|
||||
public class SiteVisit : Models.SiteVisit
|
||||
public class SiteVisit : Models.SiteVisit, ITenantEntity
|
||||
{
|
||||
public virtual Project? Project { get; set; }
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Project? Project { get; set; }
|
||||
|
||||
public virtual User? Creator { get; set; }
|
||||
}
|
||||
@@ -17,6 +20,7 @@ public sealed class SiteVisitConfiguration : IEntityTypeConfiguration<SiteVisit>
|
||||
builder.ToTable(nameof(SiteVisit).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
@@ -26,6 +30,12 @@ public sealed class SiteVisitConfiguration : IEntityTypeConfiguration<SiteVisit>
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Project)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.ProjectId)
|
||||
|
||||
@@ -5,8 +5,10 @@ public class TenantUser : Models.TenantUser
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
[ForeignKey(nameof(CreatedBy))]
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public virtual User? User { get; set; }
|
||||
}
|
||||
|
||||
@@ -16,7 +18,7 @@ public sealed class TenantUserConfiguration : IEntityTypeConfiguration<TenantUse
|
||||
{
|
||||
builder.ToTable(nameof(TenantUser).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UserId).IsRequired();
|
||||
|
||||
@@ -3,6 +3,8 @@ namespace PostFundManagement.Domain.Models;
|
||||
public class Activity
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long? ProjectId { get; set; }
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PostFundManagement.Domain.Models;
|
||||
|
||||
public sealed class AuditChanges
|
||||
{
|
||||
public string[]? Logs { get; set; }
|
||||
}
|
||||
@@ -4,6 +4,8 @@ public class Beneficiary
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Budget
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class ChangeRequest
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class ComplianceItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Contract
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long AwardId { get; set; }
|
||||
|
||||
public string? ExternalSignatureId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Disbursement
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public long? MilestoneId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Evidence
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public long MilestoneId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Indicator
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Instrument
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProgrammeId { get; set; }
|
||||
|
||||
public string? Code { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Invite
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long OrganisationId { get; set; }
|
||||
|
||||
public long InvitedOrganisationId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Issue
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Milestone
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Outcome
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long BeneficiaryId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Risk
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Rule
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProgrammeId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class SiteVisit
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
public DateTime VisitedAt { get; set; }
|
||||
|
||||
@@ -199,6 +199,7 @@
|
||||
|
||||
<!-- Shared Usings -->
|
||||
<ItemGroup>
|
||||
<Using Include="System.ComponentModel.DataAnnotations.Schema" />
|
||||
<Using Include="Microsoft.AspNetCore.DataProtection" />
|
||||
<Using Include="System.Security.Cryptography.X509Certificates" />
|
||||
<Using Include="Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage" />
|
||||
|
||||
@@ -65,35 +65,61 @@ public sealed class ApplicationDbContext(DbContextOptions<ApplicationDbContext>
|
||||
|
||||
public DbSet<User> Users => Set<User>();
|
||||
|
||||
private void ApplyGlobalTenantFilter<TEntity>(ModelBuilder modelBuilder)
|
||||
where TEntity : class, ITenantEntity =>
|
||||
modelBuilder.Entity<TEntity>().HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Portfolio>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
if (typeof(ITenantEntity).IsAssignableFrom(entityType.ClrType))
|
||||
{
|
||||
var method = typeof(ApplicationDbContext).GetMethod(nameof(ApplyGlobalTenantFilter),
|
||||
BindingFlags.NonPublic | BindingFlags.Instance)?.MakeGenericMethod(entityType.ClrType);
|
||||
|
||||
modelBuilder.Entity<Programme>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<Project>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<Award>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<Notification>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<TenantOrganisation>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<TenantUser>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<AuditLog>()
|
||||
.HasQueryFilter(e => BypassFilter || e.TenantId == CurrentTenantId);
|
||||
method?.Invoke(this, [modelBuilder]);
|
||||
}
|
||||
}
|
||||
|
||||
modelBuilder.Entity<Organisation>().HasQueryFilter(o => BypassFilter ||
|
||||
Set<TenantOrganisation>().Any(to => to.TenantId == CurrentTenantId && to.OrganisationId == o.Id));
|
||||
|
||||
modelBuilder.Entity<TenantOrganisation>()
|
||||
.HasQueryFilter(to => BypassFilter || to.TenantId == CurrentTenantId);
|
||||
|
||||
modelBuilder.Entity<TenantUser>()
|
||||
.HasQueryFilter(to => BypassFilter || to.TenantId == CurrentTenantId);
|
||||
}
|
||||
|
||||
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
AlterQualifyingTenantEntity();
|
||||
|
||||
return base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public override int SaveChanges()
|
||||
{
|
||||
AlterQualifyingTenantEntity();
|
||||
|
||||
return base.SaveChanges();
|
||||
}
|
||||
|
||||
private void AlterQualifyingTenantEntity()
|
||||
{
|
||||
var entries = ChangeTracker.Entries<ITenantEntity>()
|
||||
.Where(e => e.State == EntityState.Added && e.Entity.TenantId == 0)
|
||||
.ToList();
|
||||
|
||||
if (entries.Count == 0) return;
|
||||
|
||||
if (CurrentTenantId <= 0 && !BypassFilter)
|
||||
throw new InvalidOperationException("Cannot save multi-tenant entity: CurrentTenantId is not set in the active execution context.");
|
||||
|
||||
foreach (var entry in entries)
|
||||
entry.Entity.TenantId = CurrentTenantId;
|
||||
}
|
||||
}
|
||||
+2272
File diff suppressed because it is too large
Load Diff
+5767
File diff suppressed because it is too large
Load Diff
+2285
File diff suppressed because it is too large
Load Diff
+50
@@ -0,0 +1,50 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedTenantIdToOutcomes : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "TenantId",
|
||||
table: "Outcomes",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
defaultValue: 0L);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Outcomes_TenantId",
|
||||
table: "Outcomes",
|
||||
column: "TenantId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Outcomes_Tenants_TenantId",
|
||||
table: "Outcomes",
|
||||
column: "TenantId",
|
||||
principalTable: "Tenants",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Outcomes_Tenants_TenantId",
|
||||
table: "Outcomes");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Outcomes_TenantId",
|
||||
table: "Outcomes");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TenantId",
|
||||
table: "Outcomes");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2445
File diff suppressed because it is too large
Load Diff
+5599
File diff suppressed because it is too large
Load Diff
+223
-2
@@ -69,6 +69,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -90,6 +93,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UpdatedBy");
|
||||
|
||||
b.ToTable("Activities", (string)null);
|
||||
@@ -108,8 +113,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.PrimitiveCollection<string>("Changes")
|
||||
.HasColumnType("jsonb");
|
||||
b.PrimitiveCollection<string[]>("Changes")
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<string>("EntityId")
|
||||
.IsRequired()
|
||||
@@ -240,6 +245,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
b.Property<int>("TargetCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
@@ -249,6 +257,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Beneficiaries", (string)null);
|
||||
@@ -285,6 +295,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
b.Property<long>("ProjectId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -296,6 +309,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Budgets", (string)null);
|
||||
});
|
||||
|
||||
@@ -338,6 +353,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -354,6 +372,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("ChangeRequests", (string)null);
|
||||
});
|
||||
|
||||
@@ -386,6 +406,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -403,6 +426,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("VerifiedBy");
|
||||
|
||||
b.ToTable("ComplianceItems", (string)null);
|
||||
@@ -444,6 +469,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<decimal>("TotalValue")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("numeric(18,2)");
|
||||
@@ -455,6 +483,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Contracts", (string)null);
|
||||
});
|
||||
|
||||
@@ -489,6 +519,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -503,6 +536,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UpdatedBy");
|
||||
|
||||
b.ToTable("Disbursements", (string)null);
|
||||
@@ -545,6 +580,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
@@ -573,6 +611,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UpdatedBy");
|
||||
|
||||
b.ToTable("Evidences", (string)null);
|
||||
@@ -614,6 +654,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("numeric(18,2)");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("UnitOfMeasure")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
@@ -625,6 +668,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Indicators", (string)null);
|
||||
});
|
||||
|
||||
@@ -666,12 +711,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("2");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
|
||||
b.HasIndex("ProgrammeId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Instruments", (string)null);
|
||||
});
|
||||
|
||||
@@ -706,6 +756,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
b.Property<Guid>("Recipient")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -724,6 +777,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("Recipient");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Invites", (string)null);
|
||||
});
|
||||
|
||||
@@ -771,6 +826,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -784,6 +842,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Issues", (string)null);
|
||||
});
|
||||
|
||||
@@ -824,6 +884,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -836,6 +899,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UpdatedBy");
|
||||
|
||||
b.ToTable("Milestones", (string)null);
|
||||
@@ -984,12 +1049,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BeneficiaryId");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Outcomes", (string)null);
|
||||
});
|
||||
|
||||
@@ -1205,12 +1275,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
b.Property<long>("ProjectId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("Risks", (string)null);
|
||||
});
|
||||
|
||||
@@ -1243,6 +1318,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("2");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -1260,6 +1338,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProgrammeId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("UpdatedBy");
|
||||
|
||||
b.ToTable("Rules", (string)null);
|
||||
@@ -1297,6 +1377,9 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValueSql("1");
|
||||
|
||||
b.Property<long>("TenantId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("VisitedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -1306,6 +1389,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.ToTable("SiteVisits", (string)null);
|
||||
});
|
||||
|
||||
@@ -1475,6 +1560,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Updator")
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
@@ -1488,6 +1579,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Updator");
|
||||
});
|
||||
|
||||
@@ -1561,6 +1654,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
@@ -1571,6 +1670,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
@@ -1593,11 +1694,19 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Approver");
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.ChangeRequest", b =>
|
||||
@@ -1619,11 +1728,19 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Approver");
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.ComplianceItem", b =>
|
||||
@@ -1640,6 +1757,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Verifier")
|
||||
.WithMany()
|
||||
.HasForeignKey("VerifiedBy")
|
||||
@@ -1649,6 +1772,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Verifier");
|
||||
});
|
||||
|
||||
@@ -1666,9 +1791,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Award");
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Disbursement", b =>
|
||||
@@ -1690,6 +1823,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Updator")
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
@@ -1701,6 +1840,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Updator");
|
||||
});
|
||||
|
||||
@@ -1736,6 +1877,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Updator")
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
@@ -1751,6 +1898,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Updator");
|
||||
});
|
||||
|
||||
@@ -1768,9 +1917,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Instrument", b =>
|
||||
@@ -1787,9 +1944,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Programme");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Invite", b =>
|
||||
@@ -1824,6 +1989,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Award");
|
||||
|
||||
b.Navigation("Contract");
|
||||
@@ -1833,6 +2004,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
b.Navigation("Organisation");
|
||||
|
||||
b.Navigation("RecipientUser");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Issue", b =>
|
||||
@@ -1855,11 +2028,19 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Assignee");
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Milestone", b =>
|
||||
@@ -1876,6 +2057,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Updator")
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
@@ -1885,6 +2072,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Updator");
|
||||
});
|
||||
|
||||
@@ -1940,9 +2129,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Beneficiary");
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Portfolio", b =>
|
||||
@@ -2063,9 +2260,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Rule", b =>
|
||||
@@ -2082,6 +2287,12 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.User", "Updator")
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
@@ -2091,6 +2302,8 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
|
||||
b.Navigation("Programme");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
|
||||
b.Navigation("Updator");
|
||||
});
|
||||
|
||||
@@ -2108,9 +2321,17 @@ namespace PostFundManagement.Infrastructure.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PostFundManagement.Domain.Entities.Tenant", "Tenant")
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("Project");
|
||||
|
||||
b.Navigation("Tenant");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PostFundManagement.Domain.Entities.Tenant", b =>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.3" />
|
||||
|
||||
<Using Include="System.Reflection" />
|
||||
<Using Include="Microsoft.EntityFrameworkCore" />
|
||||
<Using Include="Microsoft.EntityFrameworkCore.Design" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user