From 66f720a20bd5ef0cc15490cf575e3fb8485633fb Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 6 Sep 2026 10:48:09 +0200 Subject: [PATCH] Stable run with validations --- .../Evidence/GetProjectEvidenceEndpoint.cs | 2 +- .../Services/Communications/Records.cs | 9 ++++- .../Services/Evidence/EvidenceService.cs | 5 ++- .../Services/Evidence/Records.cs | 19 ++++++++-- .../Services/Execution/Records.cs | 17 +++++++-- .../Services/Grants/Records.cs | 19 +++++++--- .../Services/Projects/ProjectService.cs | 28 ++++++++++---- .../Services/Projects/Records.cs | 37 +++++++++++++++---- .../Configuration/Entities/Activity.cs | 3 +- .../Configuration/Entities/Award.cs | 3 +- .../Configuration/Entities/ChangeRequest.cs | 3 +- .../Configuration/Entities/ComplianceItem.cs | 3 +- .../Configuration/Entities/Contract.cs | 3 +- .../Configuration/Entities/Disbursement.cs | 3 +- .../Configuration/Entities/Evidence.cs | 6 ++- .../Configuration/Entities/Instrument.cs | 3 +- .../Configuration/Entities/Issue.cs | 6 ++- .../Configuration/Entities/Milestone.cs | 6 ++- .../Configuration/Entities/Notification.cs | 6 ++- .../Configuration/Entities/Organisation.cs | 6 ++- .../Configuration/Entities/Programme.cs | 3 +- .../Configuration/Entities/Project.cs | 9 +++-- .../Configuration/Entities/Risk.cs | 6 ++- .../Configuration/Entities/Rule.cs | 3 +- .../Configuration/Entities/SiteVisit.cs | 3 +- .../Configuration/Entities/User.cs | 3 +- 26 files changed, 157 insertions(+), 57 deletions(-) diff --git a/PostFundManagement.Api/Endpoints/Evidence/GetProjectEvidenceEndpoint.cs b/PostFundManagement.Api/Endpoints/Evidence/GetProjectEvidenceEndpoint.cs index bab6199..aeaee08 100644 --- a/PostFundManagement.Api/Endpoints/Evidence/GetProjectEvidenceEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Evidence/GetProjectEvidenceEndpoint.cs @@ -13,7 +13,7 @@ public class GetProjectEvidenceEndpoint : IEndpoint { public void Map(IEndpointRouteBuilder builder) { - builder.MapGet("api/evidence/milestone/{projectId}", async (string projectId, IEvidenceService service, + builder.MapGet("api/evidence/{projectId}", async (string projectId, IEvidenceService service, CancellationToken cancellationToken = default) => await service.GetProjectEvidencesAsync(projectId, cancellationToken) switch { diff --git a/PostFundManagement.Application/Services/Communications/Records.cs b/PostFundManagement.Application/Services/Communications/Records.cs index 1283660..67b36b2 100644 --- a/PostFundManagement.Application/Services/Communications/Records.cs +++ b/PostFundManagement.Application/Services/Communications/Records.cs @@ -1,5 +1,12 @@ using PostFundManagement.Domain; +using static PostFundManagement.Domain.Extensions.Constants; namespace PostFundManagement.Application.Services.Communications; -public record InviteRequest(long OrganisationId, long InvitedOrganisationId, long AwardId, long ContractId, Guid Recipient, string Message, NotificationPlatform Platform); +public record InviteRequest([Required] long OrganisationId, + [Required] long InvitedOrganisationId, + [Required] long AwardId, + [Required] long ContractId, + [Required] Guid Recipient, + [Required][MaxLength(LabelLength)] string Message, + [Required] NotificationPlatform Platform); diff --git a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs index 998c6a9..e5558dd 100644 --- a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs +++ b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs @@ -102,6 +102,9 @@ public sealed class EvidenceService(IDbContextFactory cont { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (!await context.Users.AnyAsync(u => u.Id == userId, cancellationToken)) + return Result.Fail(NotFoundError.New); + if (!await context.Projects.AnyAsync(p => p.Id == request.ProjectId, cancellationToken)) return Result.Fail(NotFoundError.New); @@ -116,7 +119,7 @@ public sealed class EvidenceService(IDbContextFactory cont CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.Create("No record could be created.")); })); public async ValueTask CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default) => diff --git a/PostFundManagement.Application/Services/Evidence/Records.cs b/PostFundManagement.Application/Services/Evidence/Records.cs index 24531f7..ef82c23 100644 --- a/PostFundManagement.Application/Services/Evidence/Records.cs +++ b/PostFundManagement.Application/Services/Evidence/Records.cs @@ -1,11 +1,22 @@ using PostFundManagement.Domain; +using static PostFundManagement.Domain.Extensions.Constants; namespace PostFundManagement.Application.Services.Evidence; -public record UpdateEvidenceRequest(long EvidenceId, int Version, EvidenceType EvidenceType, ApprovalStatus Status); +public record UpdateEvidenceRequest([Required] long EvidenceId, + [Required] int Version, + [Required] EvidenceType EvidenceType, + [Required] ApprovalStatus Status); -public record RecordActualRequest(decimal ActualAmount); +public record RecordActualRequest([Required] decimal ActualAmount); -public record CreateMilestoneRequest(long ProjectId, DateTime DueAt, string Name, Priority Priority); +public record CreateMilestoneRequest([Required] long ProjectId, + [Required] DateTime DueAt, + [Required][MaxLength(LabelLength)] string Name, + [Required] Priority Priority); -public record CreateIndicatorRequest(long ProjectId, string Name, UnitOfMeasure UnitOfMeasure, decimal BaselineAmount, decimal TargetAmount); +public record CreateIndicatorRequest([Required] long ProjectId, + [Required][MaxLength(LabelLength)] string Name, + [Required] UnitOfMeasure UnitOfMeasure, + [Required] decimal BaselineAmount, + [Required] decimal TargetAmount); diff --git a/PostFundManagement.Application/Services/Execution/Records.cs b/PostFundManagement.Application/Services/Execution/Records.cs index a45f54a..0f737cc 100644 --- a/PostFundManagement.Application/Services/Execution/Records.cs +++ b/PostFundManagement.Application/Services/Execution/Records.cs @@ -1,11 +1,20 @@ using PostFundManagement.Domain; +using static PostFundManagement.Domain.Extensions.Constants; namespace PostFundManagement.Application.Services.Execution; -public record UpdateDisbursementRequest(long DisbursementId, long? MilestoneId, decimal Amount); +public record UpdateDisbursementRequest([Required] long DisbursementId, long? MilestoneId, [Required] decimal Amount); -public record UpdateRiskRequest(long RiskId, RiskLikelihood Likelihood, RiskImpact Impact, string Name, string Description); +public record UpdateRiskRequest([Required] long RiskId, + [Required] RiskLikelihood Likelihood, + [Required] RiskImpact Impact, + [Required][MaxLength(LabelLength)] string Name, + [Required][MaxLength(TextLength)] string Description); -public record CreateDisbursementRequest(long ProjectId, long? MilestoneId, decimal Amount); +public record CreateDisbursementRequest([Required] long ProjectId, long? MilestoneId, [Required] decimal Amount); -public record CreateRiskRequest(long ProjectId, RiskLikelihood Likelihood, RiskImpact Impact, string Name, string Description); +public record CreateRiskRequest([Required] long ProjectId, + [Required] RiskLikelihood Likelihood, + [Required] RiskImpact Impact, + [Required][MaxLength(LabelLength)] string Name, + [Required][MaxLength(TextLength)] string Description); diff --git a/PostFundManagement.Application/Services/Grants/Records.cs b/PostFundManagement.Application/Services/Grants/Records.cs index 2c4b266..6e82d28 100644 --- a/PostFundManagement.Application/Services/Grants/Records.cs +++ b/PostFundManagement.Application/Services/Grants/Records.cs @@ -1,9 +1,18 @@ -namespace PostFundManagement.Application.Services.Grants; +using static PostFundManagement.Domain.Extensions.Constants; -public record CreateAwardRequest(long OrganisationId, long ProgrammeId, decimal Amount); +namespace PostFundManagement.Application.Services.Grants; -public record CreateBudgetRequest(long ProjectId, string Name, decimal Amount); +public record CreateAwardRequest([Required] long OrganisationId, [Required] long ProgrammeId, [Required] decimal Amount); -public record CreateContractRequest(long AwardId, decimal TotalValue, DateTime EffectiveAt, DateTime ExpiresAt); +public record CreateBudgetRequest([Required] long ProjectId, + [Required][MaxLength(LabelLength)] string Name, + [Required] decimal Amount); -public record ExecuteContractRequest(long ContractId, string ExternalSignatureId, string SignedDocumentUrl); +public record CreateContractRequest([Required] long AwardId, + [Required] decimal TotalValue, + [Required] DateTime EffectiveAt, + [Required] DateTime ExpiresAt); + +public record ExecuteContractRequest([Required] long ContractId, + [Required][MaxLength(LabelLength)] string ExternalSignatureId, + [Required][MaxLength(LabelLength)] string SignedDocumentUrl); diff --git a/PostFundManagement.Application/Services/Projects/ProjectService.cs b/PostFundManagement.Application/Services/Projects/ProjectService.cs index a3b822f..ea061c1 100644 --- a/PostFundManagement.Application/Services/Projects/ProjectService.cs +++ b/PostFundManagement.Application/Services/Projects/ProjectService.cs @@ -15,14 +15,17 @@ public sealed class ProjectService(IDbContextFactory conte { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (!await context.Users.AnyAsync(u => u.Id == userId, cancellationToken)) + return Result.Fail(NotFoundError.New); + var changedTotal = await context.Projects - .Where(p => p.Id != request.ProjectId) + .Where(f => f.Id == request.ProjectId) .ExecuteUpdateAsync(f => f .SetProperty(p => p.Status, request.Status) .SetProperty(p => p.UpdatedBy, userId) .SetProperty(p => p.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal == 0, UpdateError.New); + return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -102,7 +105,8 @@ public sealed class ProjectService(IDbContextFactory conte CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, + CreateError.Create("No changes detected, update cancelled.")); })); public async ValueTask CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -121,7 +125,7 @@ public sealed class ProjectService(IDbContextFactory conte { ProjectId = request.ProjectId, MilestoneId = request.MilestoneId, - Category = request.Category, + Category = request.Category.Humanize(LetterCasing.Title).Trim(), Amount = request.Amount, Title = request.Title.Humanize(LetterCasing.Title).Trim(), Description = request.Description, @@ -131,7 +135,8 @@ public sealed class ProjectService(IDbContextFactory conte CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, + CreateError.Create("No record was created.")); })); public async ValueTask> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) => @@ -209,6 +214,9 @@ public sealed class ProjectService(IDbContextFactory conte { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + if (!await context.Users.AnyAsync(u => u.Id == userId, cancellationToken)) + return Result.Fail(NotFoundError.New); + var changedTotal = await context.Milestones.Where(m => m.Id == request.MilestoneId) .ExecuteUpdateAsync(f => f .SetProperty(u => u.Name, request.Name.Humanize(LetterCasing.Title).Trim()) @@ -218,7 +226,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.UpdatedBy, userId) .SetProperty(u => u.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -237,7 +245,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.Sector, request.Sector) .SetProperty(u => u.ProjectType, request.ProjectType), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => @@ -285,11 +293,15 @@ public sealed class ProjectService(IDbContextFactory conte var name = request.Name.Humanize(LetterCasing.Title).Trim(); + if (!await context.Portfolios.AnyAsync(p => p.Id == request.PortfolioId, cancellationToken)) + return Result.Fail(ValidationError.Create("Portfolio does not exist.")); + if (await context.Programmes.AnyAsync(p => p.Name == name, cancellationToken)) return Result.Fail(ValidationError.Create("Programme of the same name exists")); context.Programmes.Add(new Domain.Entities.Programme { + PortfolioId = request.PortfolioId, OwnedBy = request.OwnerId, Name = name, CreatedBy = userId, @@ -316,7 +328,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.UpdatedBy, userId) .SetProperty(u => u.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) => diff --git a/PostFundManagement.Application/Services/Projects/Records.cs b/PostFundManagement.Application/Services/Projects/Records.cs index 5607b46..8f8e8a3 100644 --- a/PostFundManagement.Application/Services/Projects/Records.cs +++ b/PostFundManagement.Application/Services/Projects/Records.cs @@ -1,17 +1,40 @@ using PostFundManagement.Domain; +using static PostFundManagement.Domain.Extensions.Constants; namespace PostFundManagement.Application.Services.Projects; -public record UpdateProgrammeRequest(long ProgrammeId, string Name, Guid OwnerId, ApprovalStatus Status); +public record UpdateProgrammeRequest([Required] long ProgrammeId, + [Required][MaxLength(LabelLength)] string Name, + [Required] Guid OwnerId, + [Required] ApprovalStatus Status); -public record CreateProgrammeRequest(string Name, Guid OwnerId); +public record CreateProgrammeRequest(long PortfolioId, string Name, Guid OwnerId); -public record UpdateProjectRequest(long ProjectId, string Name, string Description, DateTime StartedAt, DateTime? EndedAt, IndustrySector Sector, ProjectType ProjectType); +public record UpdateProjectRequest([Required] long ProjectId, + [Required][MaxLength(LabelLength)] string Name, + [Required][MaxLength(TextLength)] string Description, + DateTime? StartedAt, DateTime? EndedAt, + [Required] IndustrySector Sector, + [Required] ProjectType ProjectType); -public record UpdateMilestoneRequest(long MilestoneId, DateTime DueAt, string Name, Priority Priority, ApprovalStatus Status); +public record UpdateMilestoneRequest([Required] long MilestoneId, + [Required] DateTime DueAt, + [Required][MaxLength(LabelLength)] string Name, + [Required] Priority Priority, + [Required] ApprovalStatus Status); -public record UpdateProjectStatusRequest(long ProjectId, ApprovalStatus Status); +public record UpdateProjectStatusRequest([Required] long ProjectId, [Required] ApprovalStatus Status); -public record CreateProjectRequest(long ProgrammeId, string Name, string Description, IndustrySector Sector, ProjectType ProjectType); +public record CreateProjectRequest([Required] long ProgrammeId, + [Required][MaxLength(LabelLength)] string Name, + [Required][MaxLength(TextLength)] string Description, + [Required] IndustrySector Sector, + [Required] ProjectType ProjectType); -public record CreateActivityRequest(long ProjectId, long? MilestoneId, string Category, decimal Amount, string Title, string Description, DateTime? PerformedAt); +public record CreateActivityRequest([Required] long ProjectId, + [Required] long? MilestoneId, + [Required][MaxLength(LabelLength)] string Category, + [Required] decimal Amount, + [Required][MaxLength(LabelLength)] string Title, + [Required][MaxLength(TextLength)] string Description, + DateTime? PerformedAt); diff --git a/PostFundManagement.Domain/Configuration/Entities/Activity.cs b/PostFundManagement.Domain/Configuration/Entities/Activity.cs index 401224d..040c9eb 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Activity.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Activity.cs @@ -18,7 +18,8 @@ public sealed class Activity : IEntityTypeConfiguration 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.Status).IsRequired().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); 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); diff --git a/PostFundManagement.Domain/Configuration/Entities/Award.cs b/PostFundManagement.Domain/Configuration/Entities/Award.cs index b5fd58e..c6d2dbb 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Award.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Award.cs @@ -15,7 +15,8 @@ public sealed class Award : IEntityTypeConfiguration 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.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2); builder.HasOne(f => f.Organisation) diff --git a/PostFundManagement.Domain/Configuration/Entities/ChangeRequest.cs b/PostFundManagement.Domain/Configuration/Entities/ChangeRequest.cs index 4ad15fe..433a7c8 100644 --- a/PostFundManagement.Domain/Configuration/Entities/ChangeRequest.cs +++ b/PostFundManagement.Domain/Configuration/Entities/ChangeRequest.cs @@ -18,7 +18,8 @@ public sealed class ChangeRequest : IEntityTypeConfiguration f.Justification).IsRequired().HasMaxLength(TextLength); builder.Property(f => f.RevisedBudget).IsRequired(false).HasPrecision(18, 2); builder.Property(f => f.RevisedEndedAt).IsRequired(false); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/ComplianceItem.cs b/PostFundManagement.Domain/Configuration/Entities/ComplianceItem.cs index f6cc845..dff70db 100644 --- a/PostFundManagement.Domain/Configuration/Entities/ComplianceItem.cs +++ b/PostFundManagement.Domain/Configuration/Entities/ComplianceItem.cs @@ -16,7 +16,8 @@ public sealed class ComplianceItem : IEntityTypeConfiguration f.UpdatedAt).IsRequired(false); builder.Property(f => f.Title).IsRequired().HasMaxLength(LabelLength); builder.Property(f => f.Requirements).IsRequired().HasMaxLength(MediumTextLength); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/Contract.cs b/PostFundManagement.Domain/Configuration/Entities/Contract.cs index 4b6920c..60c4eca 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Contract.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Contract.cs @@ -17,7 +17,8 @@ public sealed class Contract : IEntityTypeConfiguration f.EffectiveAt).IsRequired(false); builder.Property(f => f.ExpiresAt).IsRequired(false); builder.Property(f => f.TotalValue).IsRequired().HasPrecision(18, 2); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ContractStatus.Draft); builder.HasOne(f => f.Award) .WithOne(f => f.Contract) diff --git a/PostFundManagement.Domain/Configuration/Entities/Disbursement.cs b/PostFundManagement.Domain/Configuration/Entities/Disbursement.cs index ee085b1..b95016c 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Disbursement.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Disbursement.cs @@ -14,7 +14,8 @@ public sealed class Disbursement : IEntityTypeConfiguration f.CreatedAt).IsRequired().HasDefaultValueSql("now()"); builder.Property(f => f.UpdatedAt).IsRequired(false); builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/Evidence.cs b/PostFundManagement.Domain/Configuration/Entities/Evidence.cs index 2b7c716..998b1b5 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Evidence.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Evidence.cs @@ -17,8 +17,10 @@ public sealed class Evidence : IEntityTypeConfiguration f.UpdatedAt).IsRequired(false); builder.Property(f => f.Version).IsRequired().HasDefaultValue(1); builder.Property(f => f.DocumentUrl).IsRequired(); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); - builder.Property(f => f.Type).IsRequired().HasConversion().HasDefaultValueSql("9"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); + builder.Property(f => f.Type).IsRequired().HasConversion().HasDefaultValueSql("9") + .HasSentinel(EvidenceType.ProcurementDocument); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/Instrument.cs b/PostFundManagement.Domain/Configuration/Entities/Instrument.cs index eeae07b..789594e 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Instrument.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Instrument.cs @@ -13,7 +13,8 @@ public sealed class Instrument : IEntityTypeConfiguration 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().HasDefaultValueSql("2"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("2") + .HasSentinel(ActivityStatus.Inactive); builder.Property(f => f.CreatedBy).IsRequired(); builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()"); diff --git a/PostFundManagement.Domain/Configuration/Entities/Issue.cs b/PostFundManagement.Domain/Configuration/Entities/Issue.cs index c1b5252..49c7d33 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Issue.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Issue.cs @@ -16,8 +16,10 @@ public sealed class Issue : IEntityTypeConfiguration 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().HasDefaultValueSql("1"); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Priority).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(Priority.Low); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ActivityStatus.Active); builder.Property(f => f.Resolution).IsRequired(); builder.HasOne(f => f.Project) diff --git a/PostFundManagement.Domain/Configuration/Entities/Milestone.cs b/PostFundManagement.Domain/Configuration/Entities/Milestone.cs index b8e7f77..513731b 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Milestone.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Milestone.cs @@ -16,8 +16,10 @@ public sealed class Milestone : IEntityTypeConfiguration f.UpdatedAt).IsRequired(false); builder.Property(f => f.DueAt).IsRequired(); builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); - builder.Property(f => f.Priority).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); + builder.Property(f => f.Priority).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(Priority.Low); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/Notification.cs b/PostFundManagement.Domain/Configuration/Entities/Notification.cs index 4c12bf1..563b988 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Notification.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Notification.cs @@ -14,8 +14,10 @@ public sealed class Notification : IEntityTypeConfiguration f.SentAt).IsRequired(false); builder.Property(f => f.Recipient).IsRequired(); builder.Property(f => f.OrganisationId).IsRequired(); - builder.Property(f => f.Platform).IsRequired().HasConversion().HasDefaultValueSql("1"); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Platform).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(NotificationPlatform.Email); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(NotificationStatus.Pending); 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); diff --git a/PostFundManagement.Domain/Configuration/Entities/Organisation.cs b/PostFundManagement.Domain/Configuration/Entities/Organisation.cs index b01684e..ddacef1 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Organisation.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Organisation.cs @@ -14,8 +14,10 @@ public sealed class Organisation : IEntityTypeConfiguration f.RegistrationNo).IsRequired().HasMaxLength(LabelLength); builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength); builder.Property(f => f.Email).IsRequired().HasMaxLength(LabelLength); - builder.Property(f => f.Type).IsRequired().HasConversion().HasDefaultValueSql("5"); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Type).IsRequired().HasConversion().HasDefaultValueSql("5") + .HasSentinel(OrganisationType.PrivateLimitedCompany); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ActivityStatus.Active); builder.HasOne(f => f.Creator) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/Programme.cs b/PostFundManagement.Domain/Configuration/Entities/Programme.cs index b80e328..d5180c4 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Programme.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Programme.cs @@ -16,7 +16,8 @@ public sealed class Programme : IEntityTypeConfiguration f.CreatedAt).IsRequired().HasDefaultValueSql("now()"); builder.Property(f => f.UpdatedAt).IsRequired(false); builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Portfolio) .WithMany(f => f.Programmes) diff --git a/PostFundManagement.Domain/Configuration/Entities/Project.cs b/PostFundManagement.Domain/Configuration/Entities/Project.cs index 162ac45..4f55526 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Project.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Project.cs @@ -18,9 +18,12 @@ public sealed class Project : IEntityTypeConfiguration 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().HasDefaultValueSql("11"); - builder.Property(f => f.ProjectType).IsRequired().HasConversion().HasDefaultValueSql("10"); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Sector).IsRequired().HasConversion().HasDefaultValueSql("11") + .HasSentinel(IndustrySector.InformationCommunicationTechnology); + builder.Property(f => f.ProjectType).IsRequired().HasConversion().HasDefaultValueSql("10") + .HasSentinel(ProjectType.Innovation); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Programme) .WithMany(f => f.Projects) diff --git a/PostFundManagement.Domain/Configuration/Entities/Risk.cs b/PostFundManagement.Domain/Configuration/Entities/Risk.cs index 77b1794..3c731b0 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Risk.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Risk.cs @@ -12,8 +12,10 @@ public sealed class Risk : IEntityTypeConfiguration builder.Property(f => f.ProjectId).IsRequired(); builder.Property(f => f.CreatedBy).IsRequired(); builder.Property(f => f.CreatedAt).IsRequired().HasDefaultValueSql("now()"); - builder.Property(f => f.Likelihood).IsRequired().HasConversion().HasDefaultValueSql("3"); - builder.Property(f => f.Impact).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Likelihood).IsRequired().HasConversion().HasDefaultValueSql("3") + .HasSentinel(RiskLikelihood.Possible); + builder.Property(f => f.Impact).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(RiskImpact.Negligible); builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength); builder.Property(f => f.Description).IsRequired().HasMaxLength(TextLength); diff --git a/PostFundManagement.Domain/Configuration/Entities/Rule.cs b/PostFundManagement.Domain/Configuration/Entities/Rule.cs index f5fbcf7..0160edb 100644 --- a/PostFundManagement.Domain/Configuration/Entities/Rule.cs +++ b/PostFundManagement.Domain/Configuration/Entities/Rule.cs @@ -16,7 +16,8 @@ public sealed class Rule : IEntityTypeConfiguration builder.Property(f => f.UpdatedAt).IsRequired(false); builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength); builder.Property(f => f.Version).IsRequired().HasDefaultValue(1); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("2"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("2") + .HasSentinel(ActivityStatus.Inactive); builder.HasOne(f => f.Programme) .WithMany(f => f.Rules) diff --git a/PostFundManagement.Domain/Configuration/Entities/SiteVisit.cs b/PostFundManagement.Domain/Configuration/Entities/SiteVisit.cs index d2301f8..116348e 100644 --- a/PostFundManagement.Domain/Configuration/Entities/SiteVisit.cs +++ b/PostFundManagement.Domain/Configuration/Entities/SiteVisit.cs @@ -15,7 +15,8 @@ public sealed class SiteVisit : IEntityTypeConfiguration f.VisitedAt).IsRequired(); builder.Property(f => f.InspectorName).IsRequired(); builder.Property(f => f.Findings).IsRequired(false).HasMaxLength(LargeTextLength); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("1") + .HasSentinel(ApprovalStatus.Pending); builder.HasOne(f => f.Project) .WithMany() diff --git a/PostFundManagement.Domain/Configuration/Entities/User.cs b/PostFundManagement.Domain/Configuration/Entities/User.cs index bb2148a..183e4f7 100644 --- a/PostFundManagement.Domain/Configuration/Entities/User.cs +++ b/PostFundManagement.Domain/Configuration/Entities/User.cs @@ -10,7 +10,8 @@ public sealed class User : IEntityTypeConfiguration builder.HasKey(pk => pk.Id); builder.Property(f => f.Email).IsRequired().HasMaxLength(LabelLength); - builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("2"); + builder.Property(f => f.Status).IsRequired().HasConversion().HasDefaultValueSql("2") + .HasSentinel(ActivityStatus.Inactive); builder.Property(f => f.LastLoginAt).IsRequired(false); } } \ No newline at end of file