Files
prefab-page-detail/Prefab/Domain/Common/EntityWithAuditAndStatus.cs
2025-10-27 17:39:18 -04:00

119 lines
3.4 KiB
C#

using System.ComponentModel.DataAnnotations;
using Prefab.Data;
namespace Prefab.Domain.Common;
/// <summary>
/// Represents an audited entity that also tracks status transitions such as deactivate and delete.
/// </summary>
/// <typeparam name="T">The identifier type.</typeparam>
public interface IEntityWithAuditAndStatus<T> : IEntityWithAudit<T>, IStatus
{
/// <summary>
/// Gets or sets the identifier of the user that deactivated the entity.
/// </summary>
Guid? InactivatedBy { get; set; }
/// <summary>
/// Gets or sets when the entity was deactivated.
/// </summary>
DateTimeOffset? InactivatedOn { get; set; }
/// <summary>
/// Gets or sets the identifier of the user that soft-deleted the entity.
/// </summary>
Guid? DeletedBy { get; set; }
/// <summary>
/// Gets or sets when the entity was soft-deleted.
/// </summary>
DateTimeOffset? DeletedOn { get; set; }
/// <summary>
/// Gets or sets the concurrency token used for optimistic locking.
/// </summary>
byte[] RowVersion { get; set; }
}
/// <summary>
/// Base type for audited entities that support activation, deactivation, and soft-delete flows.
/// </summary>
/// <typeparam name="T">The identifier type.</typeparam>
public abstract class EntityWithAuditAndStatus<T> : EntityWithAudit<T>, IEntityWithAuditAndStatus<T>
{
/// <inheritdoc />
public AuditStatus AuditStatus => DeletedOn.HasValue
? AuditStatus.Deleted
: InactivatedOn.HasValue
? AuditStatus.Inactive
: AuditStatus.Active;
/// <inheritdoc />
public Guid? InactivatedBy { get; set; }
/// <inheritdoc />
public DateTimeOffset? InactivatedOn { get; set; }
/// <inheritdoc />
public Guid? DeletedBy { get; set; }
/// <inheritdoc />
public DateTimeOffset? DeletedOn { get; set; }
/// <inheritdoc />
[Timestamp]
public byte[] RowVersion { get; set; } = [];
/// <summary>
/// Marks the entity as active by clearing any inactive markers.
/// </summary>
/// <param name="userId">Identifier of the user performing the change.</param>
public virtual void Activate(Guid? userId = null)
{
if (InactivatedOn.HasValue)
{
InactivatedOn = null;
InactivatedBy = null;
}
}
/// <summary>
/// Marks the entity as inactive if it is not already inactive.
/// </summary>
/// <param name="userId">Identifier of the user performing the change.</param>
public virtual void Deactivate(Guid? userId = null)
{
if (!InactivatedOn.HasValue)
{
InactivatedOn = DateTimeOffset.UtcNow;
InactivatedBy = userId;
}
}
/// <summary>
/// Soft deletes the entity when it has not already been deleted.
/// </summary>
/// <param name="userId">Identifier of the user performing the change.</param>
public virtual void Delete(Guid? userId = null)
{
if (!DeletedOn.HasValue)
{
DeletedOn = DateTimeOffset.UtcNow;
DeletedBy = userId;
}
}
/// <summary>
/// Restores a previously soft-deleted entity to an inactive state.
/// </summary>
/// <param name="userId">Identifier of the user performing the change.</param>
public virtual void Restore(Guid? userId = null)
{
if (DeletedOn.HasValue)
{
DeletedOn = null;
DeletedBy = null;
}
}
}