Added Invite, Notification and Activity

This commit is contained in:
2026-08-20 13:37:24 +02:00
parent f3c405fca2
commit 5ab977e335
33 changed files with 3259 additions and 393 deletions
@@ -0,0 +1,56 @@
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Domain.Configuration;
public sealed class Activity : IEntityTypeConfiguration<Entities.Activity>
{
public void Configure(EntityTypeBuilder<Entities.Activity> builder)
{
builder.ToTable(nameof(Entities.Activity).Pluralize());
builder.HasKey(pk => pk.Id);
builder.Property(f => f.ProjectId).IsRequired();
builder.Property(f => f.MilestoneId).IsRequired();
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.UpdatedBy).IsRequired(false);
builder.Property(f => f.ApprovedBy).IsRequired(false);
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
builder.Property(f => f.UpdatedAt).IsRequired(false);
builder.Property(f => f.PerformedAt).IsRequired(false);
builder.Property(f => f.Category).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Status).IsRequired().HasDefaultValueSql("1");
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
builder.Property(f => f.Title).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
builder.HasOne(f => f.Project)
.WithMany()
.HasForeignKey(fk => fk.ProjectId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Milestone)
.WithMany()
.HasForeignKey(fk => fk.MilestoneId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Creator)
.WithMany()
.HasForeignKey(fk => fk.CreatedBy)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(f => f.Updator)
.WithMany()
.HasForeignKey(fk => fk.UpdatedBy)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(f => f.Approver)
.WithMany()
.HasForeignKey(fk => fk.ApprovedBy)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);
}
}
@@ -1,6 +1,6 @@
namespace PostFundManagement.Domain.Configuration;
public class Award : IEntityTypeConfiguration<Entities.Award>
public sealed class Award : IEntityTypeConfiguration<Entities.Award>
{
public void Configure(EntityTypeBuilder<Entities.Award> builder)
{
@@ -10,6 +10,7 @@ public sealed class Evidence : IEntityTypeConfiguration<Entities.Evidence>
builder.Property(f => f.ProjectId).IsRequired();
builder.Property(f => f.MilestoneId).IsRequired();
builder.Property(f => f.IndicatorId).IsRequired();
builder.Property(f => f.ActivityId).IsRequired();
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.UpdatedBy).IsRequired();
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
@@ -17,6 +18,7 @@ public sealed class Evidence : IEntityTypeConfiguration<Entities.Evidence>
builder.Property(f => f.Version).IsRequired().HasDefaultValue(1);
builder.Property(f => f.DocumentUrl).IsRequired();
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Type).IsRequired().HasConversion<int>().HasDefaultValueSql("9");
builder.HasOne(f => f.Project)
.WithMany()
@@ -27,7 +29,19 @@ public sealed class Evidence : IEntityTypeConfiguration<Entities.Evidence>
builder.HasOne(f => f.Milestone)
.WithMany()
.HasForeignKey(fk => fk.MilestoneId)
.IsRequired(false)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Indicator)
.WithMany()
.HasForeignKey(fk => fk.IndicatorId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Activity)
.WithMany(f => f.Evidences)
.HasForeignKey(fk => fk.ActivityId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Creator)
@@ -9,13 +9,20 @@ public sealed class Instrument : IEntityTypeConfiguration<Entities.Instrument>
builder.ToTable(nameof(Entities.Instrument).Pluralize());
builder.HasKey(pk => pk.Id);
builder.Property(f => f.ProgrammeId).IsRequired();
builder.Property(f => f.Code).IsRequired().HasMaxLength(ShortLabelLength);
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Description).IsRequired(false).HasMaxLength(TextLength);
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("2");
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
builder.HasOne(f => f.Programme)
.WithMany(f => f.Instruments)
.HasForeignKey(fk => fk.ProgrammeId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Creator)
.WithMany()
.HasForeignKey(fk => fk.CreatedBy)
@@ -0,0 +1,51 @@
namespace PostFundManagement.Domain.Configuration;
public sealed class Invite : IEntityTypeConfiguration<Entities.Invite>
{
public void Configure(EntityTypeBuilder<Entities.Invite> builder)
{
builder.ToTable(nameof(Entities.Invite).Pluralize());
builder.HasKey(pk => pk.Id);
builder.Property(f => f.OrganisationId).IsRequired();
builder.Property(f => f.InvitedOrganisationId).IsRequired();
builder.Property(f => f.AwardId).IsRequired();
builder.Property(f => f.ContractId).IsRequired();
builder.Property(f => f.Recipient).IsRequired();
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.UpdatedBy).IsRequired(false);
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
builder.Property(f => f.UpdatedAt).IsRequired(false);
builder.HasOne(f => f.Organisation)
.WithMany()
.HasForeignKey(fk => fk.OrganisationId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.InvitedOrganisation)
.WithMany()
.HasForeignKey(fk => fk.InvitedOrganisationId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Award)
.WithMany()
.HasForeignKey(fk => fk.AwardId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Contract)
.WithMany()
.HasForeignKey(fk => fk.ContractId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.RecipientUser)
.WithMany()
.HasForeignKey(fk => fk.Recipient)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
}
}
@@ -13,10 +13,12 @@ public sealed class Issue : IEntityTypeConfiguration<Entities.Issue>
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
builder.Property(f => f.ResolvedAt).IsRequired(false);
builder.Property(f => f.AssignedTo).IsRequired(false);
builder.Property(f => f.Title).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
builder.Property(f => f.Priority).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Resolution).IsRequired();
builder.HasOne(f => f.Project)
.WithMany()
@@ -29,5 +31,11 @@ public sealed class Issue : IEntityTypeConfiguration<Entities.Issue>
.HasForeignKey(fk => fk.CreatedBy)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(f => f.Assignee)
.WithMany()
.HasForeignKey(fk => fk.AssignedTo)
.IsRequired()
.OnDelete(DeleteBehavior.SetNull);
}
}
@@ -17,6 +17,7 @@ public sealed class Milestone : IEntityTypeConfiguration<Entities.Milestone>
builder.Property(f => f.DueAt).IsRequired();
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Priority).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.HasOne(f => f.Project)
.WithMany()
@@ -0,0 +1,36 @@
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Domain.Configuration;
public sealed class Notification : IEntityTypeConfiguration<Entities.Notification>
{
public void Configure(EntityTypeBuilder<Entities.Notification> builder)
{
builder.ToTable(nameof(Entities.Notification).Pluralize());
builder.HasKey(pk => pk.Id);
builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()");
builder.Property(f => f.UpdatedAt).IsRequired(false);
builder.Property(f => f.SentAt).IsRequired(false);
builder.Property(f => f.Recipient).IsRequired();
builder.Property(f => f.OrganisationId).IsRequired();
builder.Property(f => f.Platform).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.Property(f => f.Subject).IsRequired(false).HasMaxLength(LabelLength);
builder.Property(f => f.Message).IsRequired().HasMaxLength(LargeTextLength);
builder.Property(f => f.Destination).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Error).IsRequired(false);
builder.HasOne(f => f.Organisation)
.WithMany()
.HasForeignKey(fk => fk.OrganisationId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.RecipientUser)
.WithMany()
.HasForeignKey(fk => fk.Recipient)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
}
}
@@ -10,7 +10,6 @@ public sealed class Programme : IEntityTypeConfiguration<Entities.Programme>
builder.HasKey(pk => pk.Id);
builder.Property(f => f.PortfolioId).IsRequired();
builder.Property(f => f.InstrumentId).IsRequired();
builder.Property(f => f.OwnedBy).IsRequired();
builder.Property(f => f.CreatedBy).IsRequired();
builder.Property(f => f.UpdatedBy).IsRequired(false);
@@ -25,12 +24,6 @@ public sealed class Programme : IEntityTypeConfiguration<Entities.Programme>
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(f => f.Instrument)
.WithMany(f => f.Programmes)
.HasForeignKey(fk => fk.InstrumentId)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
builder.HasOne(f => f.Creator)
.WithMany()
.HasForeignKey(fk => fk.CreatedBy)
@@ -18,13 +18,15 @@ public sealed class Project : IEntityTypeConfiguration<Entities.Project>
builder.Property(f => f.EndedAt).IsRequired(false);
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength);
builder.Property(f => f.Sector).IsRequired().HasConversion<int>().HasDefaultValueSql("11");
builder.Property(f => f.ProjectType).IsRequired().HasConversion<int>().HasDefaultValueSql("10");
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1");
builder.HasOne(f => f.Programme)
.WithMany(f => f.Projects)
.HasForeignKey(fk => fk.ProgrammeId)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(f => f.Creator)
.WithMany()
@@ -0,0 +1,17 @@
namespace PostFundManagement.Domain.Entities;
[EntityTypeConfiguration<Configuration.Activity, Activity>]
public class Activity : Models.Activity
{
public virtual User? Creator { get; set; }
public virtual User? Updator { get; set; }
public virtual User? Approver { get; set; }
public virtual Project? Project { get; set; }
public virtual Milestone? Milestone { get; set; }
public virtual ICollection<Evidence> Evidences { get; set; } = [];
}
@@ -9,6 +9,8 @@ public class Evidence : Models.Evidence
public virtual Indicator? Indicator { get; set; }
public virtual Activity? Activity { get; set; }
public virtual User? Creator { get; set; }
public virtual User? Updator { get; set; }
@@ -5,5 +5,5 @@ public class Instrument : Models.Instrument
{
public virtual User? Creator { get; set; }
public virtual ICollection<Programme> Programmes { get; set; } = [];
public virtual Programme? Programme { get; set; }
}
@@ -0,0 +1,15 @@
namespace PostFundManagement.Domain.Entities;
[EntityTypeConfiguration<Configuration.Invite, Invite>]
public class Invite : Models.Invite
{
public virtual Organisation? Organisation { get; set; }
public virtual Organisation? InvitedOrganisation { get; set; }
public virtual Award? Award { get; set; }
public virtual Contract? Contract { get; set; }
public virtual User? RecipientUser { get; set; }
}
@@ -6,4 +6,6 @@ public class Issue : Models.Issue
public virtual Project? Project { get; set; }
public virtual User? Creator { get; set; }
public virtual User? Assignee { get; set; }
}
@@ -0,0 +1,9 @@
namespace PostFundManagement.Domain.Entities;
[EntityTypeConfiguration<Configuration.Notification, Notification>]
public class Notification : Models.Notification
{
public virtual Organisation? Organisation { get; set; }
public virtual User? RecipientUser { get; set; }
}
@@ -9,7 +9,7 @@ public class Programme : Models.Programme
public virtual Portfolio? Portfolio { get; set; }
public virtual Instrument? Instrument { get; set; }
public virtual ICollection<Instrument> Instruments { get; set; } = [];
public virtual ICollection<Rule> Rules { get; set; } = [];
+79
View File
@@ -1,5 +1,84 @@
namespace PostFundManagement.Domain;
public enum NotificationStatus : int
{
Pending = 1,
Queued = 2,
Processing = 3,
Sent = 4,
Delivered = 5,
Read = 6,
Failed = 7,
Cancelled = 8,
Bounced = 9
}
public enum NotificationPlatform : int
{
Email = 1,
SMS = 2,
WhatsApp = 3,
PushNotification = 4,
InApp = 5,
Teams = 6,
Slack = 7,
Webhook = 8,
Other = 99
}
public enum EvidenceType : int
{
AttendanceRegister = 1,
BankStatement = 2,
CompletionCertificate = 3,
FinancialInvoiceOrReceipt = 4,
GeotaggedPhoto = 5,
InspectionReport = 6,
MeetingMinutes = 7,
PayrollOrStipendRegister = 8,
ProcurementDocument = 9,
TechnicalSpecificationOrDesign = 10,
VideoRecording = 11,
Other = 99
}
public enum ProjectType : int
{
CapacityBuildingAndTraining = 1,
CapitalExpenditureAndInfrastructure = 2,
CommercializationAndScaling = 3,
FeasibilityAndTechnicalAssistance = 4,
OperationalGrantAndSubsidy = 5,
ProductDevelopmentAndPrototyping = 6,
ResearchAndDevelopment = 7,
SocialImpactAndCommunityDevelopment = 8,
TechnologyTransferAndAdoption = 9,
Innovation = 10,
Other = 99
}
public enum IndustrySector : int
{
AgricultureAndAgroProcessing = 1,
AutomotiveAndTransportEquipment = 2,
ChemicalsAndPharmaceuticals = 3,
ConstructionAndInfrastructure = 4,
CreativeIndustriesAndMedia = 5,
DefenseAndAerospace = 6,
EducationAndSkillsDevelopment = 7,
EnergyAndUtilities = 8,
FinancialServices = 9,
HealthcareAndLifeSciences = 10,
InformationCommunicationTechnology = 11,
ManufacturingAndIndustrial = 12,
MiningAndMetals = 13,
RealEstateAndHousing = 14,
RetailAndConsumerGoods = 15,
TourismAndHospitality = 16,
WaterAndSanitation = 17,
Other = 99
}
public enum OrganisationType : int
{
// Non-Profit & Civil Society
@@ -4,6 +4,25 @@ namespace PostFundManagement.Domain.Extensions;
public static class Mappers
{
public static Activity Map(this Entities.Activity entity) => new()
{
Id = entity.Id,
Amount = entity.Amount,
ApprovedBy = entity.ApprovedBy,
Category = entity.Category,
CreatedAt = entity.CreatedAt,
CreatedBy = entity.CreatedBy,
Description = entity.Description,
MilestoneId = entity.MilestoneId,
PerformedAt = entity.PerformedAt,
ProjectId = entity.ProjectId,
Status = entity.Status,
Title = entity.Title,
UpdatedAt = entity.UpdatedAt,
UpdatedBy = entity.UpdatedBy
};
public static AuditLog Map(this Entities.AuditLog entity) => new()
{
Id = entity.Id,
@@ -108,7 +127,9 @@ public static class Mappers
Status = entity.Status,
UpdatedAt = entity.UpdatedAt,
UpdatedBy = entity.UpdatedBy,
Version = entity.Version
Version = entity.Version,
ActivityId = entity.ActivityId,
Type = entity.Type
};
public static Indicator Map(this Entities.Indicator entity) => new()
@@ -132,7 +153,22 @@ public static class Mappers
CreatedBy = entity.CreatedBy,
Description = entity.Description,
Name = entity.Name,
Status = entity.Status
Status = entity.Status,
ProgrammeId = entity.ProgrammeId
};
public static Invite Map(this Entities.Invite entity) => new()
{
Id = entity.Id,
AwardId = entity.AwardId,
ContractId = entity.ContractId,
CreatedAt = entity.CreatedAt,
CreatedBy = entity.CreatedBy,
InvitedOrganisationId = entity.InvitedOrganisationId,
OrganisationId = entity.OrganisationId,
Recipient = entity.Recipient,
UpdatedAt = entity.UpdatedAt,
UpdatedBy = entity.UpdatedBy
};
public static Issue Map(this Entities.Issue entity) => new()
@@ -145,7 +181,9 @@ public static class Mappers
ProjectId = entity.ProjectId,
ResolvedAt = entity.ResolvedAt,
Status = entity.Status,
Title = entity.Title
Title = entity.Title,
AssignedTo = entity.AssignedTo,
Resolution = entity.Resolution
};
public static Milestone Map(this Entities.Milestone entity) => new()
@@ -158,7 +196,8 @@ public static class Mappers
ProjectId = entity.ProjectId,
Status = entity.Status,
UpdatedAt = entity.UpdatedAt,
UpdatedBy = entity.UpdatedBy
UpdatedBy = entity.UpdatedBy,
Priority = entity.Priority
};
public static Organisation Map(this Entities.Organisation entity) => new()
@@ -193,12 +232,27 @@ public static class Mappers
OwnedBy = entity.OwnedBy
};
public static Notification Map(this Entities.Notification entity) => new()
{
Id = entity.Id,
CreatedAt = entity.CreatedAt,
Destination = entity.Destination,
Error = entity.Error,
Message = entity.Message,
OrganisationId = entity.OrganisationId,
Platform = entity.Platform,
Recipient = entity.Recipient,
SentAt = entity.SentAt,
Status = entity.Status,
Subject = entity.Subject,
UpdatedAt = entity.UpdatedAt
};
public static Programme Map(this Entities.Programme entity) => new()
{
Id = entity.Id,
CreatedAt = entity.CreatedAt,
CreatedBy = entity.CreatedBy,
InstrumentId = entity.InstrumentId,
Name = entity.Name,
OwnedBy = entity.OwnedBy,
PortfolioId = entity.PortfolioId,
@@ -219,7 +273,9 @@ public static class Mappers
StartedAt = entity.StartedAt,
Status = entity.Status,
UpdatedAt = entity.UpdatedAt,
UpdatedBy = entity.UpdatedBy
UpdatedBy = entity.UpdatedBy,
ProjectType = entity.ProjectType,
Sector = entity.Sector
};
public static Risk Map(this Entities.Risk entity) => new()
@@ -0,0 +1,32 @@
namespace PostFundManagement.Domain.Models;
public class Activity
{
public long Id { get; set; }
public long? ProjectId { get; set; }
public long? MilestoneId { get; set; }
public Guid CreatedBy { get; set; }
public Guid? UpdatedBy { get; set; }
public Guid? ApprovedBy { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public string? Category { get; set; }
public ApprovalStatus Status { get; set; }
public decimal Amount { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public DateTime? PerformedAt { get; set; }
}
+6 -2
View File
@@ -6,9 +6,11 @@ public class Evidence
public long ProjectId { get; set; }
public long? MilestoneId { get; set; }
public long MilestoneId { get; set; }
public long? IndicatorId { get; set; }
public long IndicatorId { get; set; }
public long ActivityId { get; set; }
public Guid CreatedBy { get; set; }
@@ -20,6 +22,8 @@ public class Evidence
public int Version { get; set; }
public EvidenceType Type { get; set; }
public string? DocumentUrl { get; set; }
public ApprovalStatus Status { get; set; }
@@ -4,6 +4,8 @@ public class Instrument
{
public long Id { get; set; }
public long ProgrammeId { get; set; }
public string? Code { get; set; }
public string? Name { get; set; }
@@ -0,0 +1,24 @@
namespace PostFundManagement.Domain.Models;
public class Invite
{
public long Id { get; set; }
public long OrganisationId { get; set; }
public long InvitedOrganisationId { get; set; }
public long AwardId { get; set; }
public long ContractId { get; set; }
public Guid Recipient { get; set; }
public Guid CreatedBy { get; set; }
public Guid? UpdatedBy { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
}
@@ -18,5 +18,9 @@ public class Issue
public DateTime CreatedAt { get; set; }
public Guid? AssignedTo { get; set; }
public DateTime? ResolvedAt { get; set; }
public string? Resolution { get; set; }
}
@@ -19,4 +19,6 @@ public class Milestone
public string? Name { get; set; }
public ApprovalStatus Status { get; set; }
public Priority Priority { get; set; }
}
@@ -0,0 +1,28 @@
namespace PostFundManagement.Domain.Models;
public class Notification
{
public long Id { get; set; }
public long OrganisationId { get; set; }
public Guid Recipient { get; set; }
public NotificationPlatform Platform { get; set; }
public NotificationStatus Status { get; set; }
public string? Subject { get; set; }
public string? Message { get; set; }
public string? Destination { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? SentAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public string? Error { get; set; }
}
@@ -6,8 +6,6 @@ public class Programme
public long PortfolioId { get; set; }
public long InstrumentId { get; set; }
public Guid OwnedBy { get; set; }
public Guid CreatedBy { get; set; }
@@ -18,6 +18,10 @@ public class Project
public DateTime? EndedAt { get; set; }
public IndustrySector Sector { get; set; }
public ProjectType ProjectType { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }