Stable multitenancy
This commit is contained in:
@@ -15,7 +15,7 @@ public sealed class AuditService(IDbContextFactory<ApplicationDbContext> context
|
||||
{
|
||||
EntityId = entityId,
|
||||
Action = action,
|
||||
Changes = changes,
|
||||
Changes = new Domain.Models.AuditChanges { Logs = changes },
|
||||
EntityName = entityName,
|
||||
PerformedBy = performedBy,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PostFundManagement.Domain.Abstractions;
|
||||
|
||||
public interface ITenantEntity
|
||||
{
|
||||
public long TenantId { get; set; }
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
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 +28,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 +43,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)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using PostFundManagement.Domain.Models;
|
||||
using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<AuditLogConfiguration, AuditLog>]
|
||||
public sealed class AuditLog : Models.AuditLog;
|
||||
|
||||
public sealed class AuditLogConfiguration : IEntityTypeConfiguration<AuditLog>
|
||||
@@ -16,7 +16,9 @@ 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).HasColumnType("jsonb")
|
||||
.HasConversion(model => JsonSerializer.Serialize(model, JsonSerializerOptions.Default),
|
||||
provider => JsonSerializer.Deserialize<AuditChanges>(provider, JsonSerializerOptions.Default));
|
||||
builder.Property(f => f.PerformedBy).IsRequired();
|
||||
builder.Property(f => f.Timestamp).IsRequired().HasDefaultValueSql("now()");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
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; }
|
||||
|
||||
@@ -41,7 +42,7 @@ public sealed class AwardConfiguration : IEntityTypeConfiguration<Award>
|
||||
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany(f => f.Awards)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
@@ -77,9 +78,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,18 @@
|
||||
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 +23,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 +34,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,12 @@
|
||||
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 +21,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 +30,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,12 @@
|
||||
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 +21,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 +34,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,12 @@
|
||||
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 +21,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,11 @@
|
||||
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 +18,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 +31,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,11 @@
|
||||
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 +22,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 +33,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,11 @@
|
||||
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 +26,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 +42,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,12 @@
|
||||
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 +19,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 +29,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,12 @@
|
||||
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 +19,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 +29,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,11 @@
|
||||
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 +24,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 +35,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,12 @@
|
||||
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 +21,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 +35,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,12 @@
|
||||
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 +21,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 +34,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,9 @@
|
||||
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; }
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<OrganisationConfiguration, Organisation>]
|
||||
public class Organisation : Models.Organisation
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
@@ -2,7 +2,6 @@ using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<OutcomeConfiguration, Outcome>]
|
||||
public class Outcome : Models.Outcome
|
||||
{
|
||||
public virtual Beneficiary? Beneficiary { get; set; }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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; }
|
||||
|
||||
@@ -32,7 +32,7 @@ public sealed class PortfolioConfiguration : IEntityTypeConfiguration<Portfolio>
|
||||
builder.Property(f => f.Description).IsRequired(false).HasMaxLength(TextLength);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany(f => f.Portfolios)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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; }
|
||||
|
||||
@@ -41,7 +41,7 @@ public sealed class ProgrammeConfiguration : IEntityTypeConfiguration<Programme>
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany(f => f.Programmes)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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; }
|
||||
|
||||
@@ -41,7 +41,7 @@ public sealed class ProjectConfiguration : IEntityTypeConfiguration<Project>
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany(f => f.Projects)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
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 +19,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 +30,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,12 @@
|
||||
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 +21,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 +32,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,13 @@
|
||||
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 +19,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 +29,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)
|
||||
|
||||
@@ -2,20 +2,11 @@
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<TenantConfiguration, Tenant>]
|
||||
public class Tenant : Models.Tenant
|
||||
{
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
public virtual User? Updator { get; set; }
|
||||
|
||||
public ICollection<Award> Awards { get; set; } = [];
|
||||
|
||||
public ICollection<Project> Projects { get; set; } = [];
|
||||
|
||||
public ICollection<Programme> Programmes { get; set; } = [];
|
||||
|
||||
public ICollection<Portfolio> Portfolios { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class TenantConfiguration : IEntityTypeConfiguration<Tenant>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<TenantOrganisationConfiguration, TenantOrganisation>]
|
||||
public class TenantOrganisation : Models.TenantOrganisation
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
@@ -17,6 +16,8 @@ public sealed class TenantOrganisationConfiguration : IEntityTypeConfiguration<T
|
||||
builder.ToTable(nameof(TenantOrganisation).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.HasIndex(to => new { to.TenantId, to.OrganisationId }).IsUnique();
|
||||
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<TenantUserConfiguration, TenantUser>]
|
||||
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; }
|
||||
}
|
||||
|
||||
@@ -17,6 +18,8 @@ public sealed class TenantUserConfiguration : IEntityTypeConfiguration<TenantUse
|
||||
builder.ToTable(nameof(TenantUser).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.HasIndex(tu => new { tu.TenantId, tu.UserId }).IsUnique();
|
||||
|
||||
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UserId).IsRequired();
|
||||
|
||||
@@ -2,7 +2,6 @@ using static PostFundManagement.Domain.Extensions.Constants;
|
||||
|
||||
namespace PostFundManagement.Domain.Entities;
|
||||
|
||||
[EntityTypeConfiguration<UserConfiguration, User>]
|
||||
public sealed class User : Models.User;
|
||||
|
||||
public sealed class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -12,7 +12,8 @@ public class AuditLog
|
||||
|
||||
public string? Action { get; set; }
|
||||
|
||||
public string[]? Changes { get; set; }
|
||||
[NotMapped]
|
||||
public AuditChanges? Changes { get; set; }
|
||||
|
||||
public Guid PerformedBy { 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 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,60 @@ 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);
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
|
||||
|
||||
modelBuilder.Entity<Programme>()
|
||||
.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<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<User>().HasQueryFilter(o => BypassFilter ||
|
||||
Set<TenantUser>().Any(to => to.TenantId == CurrentTenantId && to.UserId == o.Id));
|
||||
}
|
||||
|
||||
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
+560
-512
File diff suppressed because it is too large
Load Diff
@@ -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