159 lines
4.7 KiB
C#
159 lines
4.7 KiB
C#
using FnbEngine.Domain.Events;
|
|
using FnbEngine.Domain.Exceptions;
|
|
using FnbEngine.Domain.SeedWork;
|
|
|
|
namespace FnbEngine.Domain.AggregatesModel.SampleAggregate;
|
|
|
|
/// <summary>
|
|
/// EN: Sample aggregate root demonstrating DDD patterns.
|
|
/// VI: Sample aggregate root minh họa các pattern DDD.
|
|
/// </summary>
|
|
public class Sample : Entity, IAggregateRoot
|
|
{
|
|
// EN: Private fields for encapsulation
|
|
// VI: Fields private để đóng gói
|
|
private string _name = null!;
|
|
private string? _description;
|
|
private SampleStatus _status = null!;
|
|
private DateTime _createdAt;
|
|
private DateTime? _updatedAt;
|
|
|
|
/// <summary>
|
|
/// EN: Sample name (required).
|
|
/// VI: Tên sample (bắt buộc).
|
|
/// </summary>
|
|
public string Name => _name;
|
|
|
|
/// <summary>
|
|
/// EN: Optional description.
|
|
/// VI: Mô tả tùy chọn.
|
|
/// </summary>
|
|
public string? Description => _description;
|
|
|
|
/// <summary>
|
|
/// EN: Current status.
|
|
/// VI: Trạng thái hiện tại.
|
|
/// </summary>
|
|
public SampleStatus Status => _status;
|
|
|
|
/// <summary>
|
|
/// EN: Status ID for EF Core mapping.
|
|
/// VI: ID trạng thái cho EF Core mapping.
|
|
/// </summary>
|
|
public int StatusId { get; private set; }
|
|
|
|
/// <summary>
|
|
/// EN: Creation timestamp.
|
|
/// VI: Thời gian tạo.
|
|
/// </summary>
|
|
public DateTime CreatedAt => _createdAt;
|
|
|
|
/// <summary>
|
|
/// EN: Last update timestamp.
|
|
/// VI: Thời gian cập nhật cuối.
|
|
/// </summary>
|
|
public DateTime? UpdatedAt => _updatedAt;
|
|
|
|
/// <summary>
|
|
/// EN: Private constructor for EF Core.
|
|
/// VI: Constructor private cho EF Core.
|
|
/// </summary>
|
|
protected Sample()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Create a new Sample with required information.
|
|
/// VI: Tạo một Sample mới với thông tin bắt buộc.
|
|
/// </summary>
|
|
/// <param name="name">EN: Sample name / VI: Tên sample</param>
|
|
/// <param name="description">EN: Optional description / VI: Mô tả tùy chọn</param>
|
|
public Sample(string name, string? description = null) : this()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
throw new SampleDomainException("Sample name cannot be empty");
|
|
|
|
Id = Guid.NewGuid();
|
|
_name = name;
|
|
_description = description;
|
|
_status = SampleStatus.Draft;
|
|
StatusId = SampleStatus.Draft.Id;
|
|
_createdAt = DateTime.UtcNow;
|
|
|
|
// EN: Add domain event for creation
|
|
// VI: Thêm domain event cho việc tạo
|
|
AddDomainEvent(new SampleCreatedDomainEvent(this));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Update sample information.
|
|
/// VI: Cập nhật thông tin sample.
|
|
/// </summary>
|
|
public void Update(string name, string? description)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
throw new SampleDomainException("Sample name cannot be empty");
|
|
|
|
if (_status == SampleStatus.Cancelled)
|
|
throw new SampleDomainException("Cannot update a cancelled sample");
|
|
|
|
_name = name;
|
|
_description = description;
|
|
_updatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Activate the sample.
|
|
/// VI: Kích hoạt sample.
|
|
/// </summary>
|
|
public void Activate()
|
|
{
|
|
if (_status != SampleStatus.Draft)
|
|
throw new SampleDomainException("Only draft samples can be activated");
|
|
|
|
var previousStatus = _status;
|
|
_status = SampleStatus.Active;
|
|
StatusId = SampleStatus.Active.Id;
|
|
_updatedAt = DateTime.UtcNow;
|
|
|
|
AddDomainEvent(new SampleStatusChangedDomainEvent(Id, previousStatus, _status));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Complete the sample.
|
|
/// VI: Hoàn thành sample.
|
|
/// </summary>
|
|
public void Complete()
|
|
{
|
|
if (_status != SampleStatus.Active)
|
|
throw new SampleDomainException("Only active samples can be completed");
|
|
|
|
var previousStatus = _status;
|
|
_status = SampleStatus.Completed;
|
|
StatusId = SampleStatus.Completed.Id;
|
|
_updatedAt = DateTime.UtcNow;
|
|
|
|
AddDomainEvent(new SampleStatusChangedDomainEvent(Id, previousStatus, _status));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Cancel the sample.
|
|
/// VI: Hủy sample.
|
|
/// </summary>
|
|
public void Cancel()
|
|
{
|
|
if (_status == SampleStatus.Completed)
|
|
throw new SampleDomainException("Cannot cancel a completed sample");
|
|
|
|
if (_status == SampleStatus.Cancelled)
|
|
throw new SampleDomainException("Sample is already cancelled");
|
|
|
|
var previousStatus = _status;
|
|
_status = SampleStatus.Cancelled;
|
|
StatusId = SampleStatus.Cancelled.Id;
|
|
_updatedAt = DateTime.UtcNow;
|
|
|
|
AddDomainEvent(new SampleStatusChangedDomainEvent(Id, previousStatus, _status));
|
|
}
|
|
}
|