using SmartStack.Domain.Platform.Administration.Tenants.Organisation;
using SmartStack.Domain.Platform.Administration.Users;
using {{ProjectName}}.Domain.Common;
namespace {{ProjectName}}.Domain.Entities;
///
/// Example entity demonstrating REAL navigation properties + SQL foreign keys
/// to Core entities in the V1 whitelist (User, TenantOrganisation).
///
/// The owning side carries the GUID FK column AND a navigation property to
/// the Core principal. EF Core emits a real cross-schema FK in the migration
/// (targeting core.auth_Users(Id) / core.tenant_TenantOrganisations(Id))
/// because SmartStackExtensionDbContext exposes those entities via
/// ExcludeFromMigrations — see the base class.
///
/// You can .Include(o => o.Customer) / .Include(o => o.Organisation)
/// to hydrate the principal in the same SQL query (INNER JOIN), or query a
/// nav field directly: _db.Orders.Where(o => o.Customer.Email == ...).
///
public class Order : ExtensionBaseEntity
{
public string OrderNumber { get; private set; } = null!;
/// FK to core.auth_Users(Id) — the user placing the order.
public Guid CustomerUserId { get; private set; }
/// FK to core.tenant_TenantOrganisations(Id) — the customer's organisation.
public Guid OrganisationId { get; private set; }
public OrderStatus Status { get; private set; }
public decimal TotalAmount { get; private set; }
public DateTime OrderDate { get; private set; }
public string? Notes { get; private set; }
/// Navigation to the placing User. Real cross-schema FK.
public User Customer { get; private set; } = null!;
/// Navigation to the TenantOrganisation (the shared organisation directory). Real cross-schema FK.
public TenantOrganisation Organisation { get; private set; } = null!;
// Private constructor for EF Core
private Order() { }
///
/// Creates a new order. The Customer / Organisation navigations are lazily
/// hydrated by .Include(...) at query time — the factory only
/// stores the FK GUIDs.
///
public static Order Create(string orderNumber, Guid customerUserId, Guid organisationId, decimal totalAmount)
{
ArgumentException.ThrowIfNullOrWhiteSpace(orderNumber);
return new Order
{
OrderNumber = orderNumber,
CustomerUserId = customerUserId,
OrganisationId = organisationId,
Status = OrderStatus.Pending,
TotalAmount = totalAmount,
OrderDate = DateTime.UtcNow
};
}
public void Confirm()
{
if (Status != OrderStatus.Pending)
throw new InvalidOperationException("Only pending orders can be confirmed.");
Status = OrderStatus.Confirmed;
}
public void Ship()
{
if (Status != OrderStatus.Confirmed)
throw new InvalidOperationException("Only confirmed orders can be shipped.");
Status = OrderStatus.Shipped;
}
public void Complete()
{
if (Status != OrderStatus.Shipped)
throw new InvalidOperationException("Only shipped orders can be completed.");
Status = OrderStatus.Completed;
}
public void Cancel()
{
if (Status == OrderStatus.Completed)
throw new InvalidOperationException("Completed orders cannot be cancelled.");
Status = OrderStatus.Cancelled;
}
public void AddNotes(string notes)
{
Notes = notes;
}
}
///
/// Order status enum.
///
public enum OrderStatus
{
Pending = 0,
Confirmed = 1,
Shipped = 2,
Completed = 3,
Cancelled = 4
}