OElite.Common.Platform 5.0.9-develop.448

OElite.Common.Platform

NuGet Version Target Framework

Platform-specific domain entities, DTOs, and shared types for the OElite eCommerce and business platform, extending the core OElite.Common package with specialized business domain models.

Overview

OElite.Common.Platform provides the comprehensive domain model and data transfer objects for the OElite eCommerce and business platform. It extends the foundational OElite.Common package with specialized entities for customers, products, orders, payments, inventory, and platform-specific business logic. This package serves as the shared contract between all platform layers and services.

Features

eCommerce Domain Models

  • Customer Management: Customer profiles, segmentation, loyalty, and support entities
  • Product Catalog: Products, categories, brands, attributes, and inventory management
  • Order Processing: Orders, order items, shopping carts, and order lifecycle management
  • Payment Processing: Payment methods, transactions, refunds, and payment gateway integration
  • Shipping & Fulfillment: Shipping methods, rates, tracking, and fulfillment workflows

Platform Entities

  • Multi-Tenant Support: Merchant accounts, store configurations, and tenant isolation
  • User Management: Platform users, roles, permissions, and authentication
  • Configuration: Platform settings, feature flags, and configuration management
  • Analytics: Business metrics, KPIs, reporting entities, and performance tracking
  • Marketing: Campaigns, promotions, discounts, and customer engagement

Data Transfer Objects

  • Request/Response Models: Standardized DTOs for API communication
  • Validation Models: Input validation with business rules and constraints
  • View Models: Presentation-ready models for frontend applications
  • Integration Models: Data exchange models for external system integration
  • Event Models: Domain event models for event-driven architecture

Installation

dotnet add package OElite.Common.Platform

Core Domain Models

Customer Domain

Customer Entity

using OElite.Common.Platform.Customers;

public class Customer : BaseEntity
{
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string PhoneNumber { get; set; } = string.Empty;
    public DateTime? DateOfBirth { get; set; }

    // Platform-specific properties
    public string MerchantId { get; set; } = string.Empty;
    public CustomerStatus Status { get; set; } = CustomerStatus.Active;
    public CustomerType Type { get; set; } = CustomerType.Individual;
    public string PreferredLanguage { get; set; } = "en";
    public string PreferredCurrency { get; set; } = "USD";

    // Loyalty and engagement
    public int LoyaltyPoints { get; set; }
    public DateTime? LastLoginAt { get; set; }
    public DateTime? LastOrderAt { get; set; }

    // Address and contact
    public List<CustomerAddress> Addresses { get; set; } = new();
    public CustomerAddress? DefaultBillingAddress => Addresses.FirstOrDefault(a => a.IsDefaultBilling);
    public CustomerAddress? DefaultShippingAddress => Addresses.FirstOrDefault(a => a.IsDefaultShipping);
}

public enum CustomerStatus
{
    Active = 1,
    Inactive = 2,
    Suspended = 3,
    Deleted = 4
}

public enum CustomerType
{
    Individual = 1,
    Business = 2,
    Premium = 3,
    Wholesale = 4
}

public class CustomerAddress : BaseEntity
{
    public string CustomerId { get; set; } = string.Empty;
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Company { get; set; } = string.Empty;
    public string AddressLine1 { get; set; } = string.Empty;
    public string AddressLine2 { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public string StateProvince { get; set; } = string.Empty;
    public string PostalCode { get; set; } = string.Empty;
    public string CountryCode { get; set; } = string.Empty;
    public bool IsDefaultBilling { get; set; }
    public bool IsDefaultShipping { get; set; }
}

Customer Segmentation

public class CustomerSegment : BaseEntity
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string Criteria { get; set; } = string.Empty; // JSON criteria
    public SegmentType Type { get; set; } = SegmentType.Dynamic;
    public bool IsActive { get; set; } = true;
    public int CustomerCount { get; set; }
    public DateTime? LastCalculatedAt { get; set; }
}

public enum SegmentType
{
    Static = 1,     // Manually managed
    Dynamic = 2,    // Rule-based
    Behavioral = 3  // AI/ML driven
}

public class CustomerSegmentMembership : BaseEntity
{
    public string CustomerId { get; set; } = string.Empty;
    public string SegmentId { get; set; } = string.Empty;
    public DateTime AssignedAt { get; set; }
    public string AssignedBy { get; set; } = string.Empty; // System or UserId
    public SegmentMembershipType Type { get; set; } = SegmentMembershipType.Automatic;
}

Product Domain

Product Entity

using OElite.Common.Platform.Products;

public class Product : BaseEntity
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string ShortDescription { get; set; } = string.Empty;
    public string SKU { get; set; } = string.Empty;
    public string Barcode { get; set; } = string.Empty;

    // Categorization
    public string CategoryId { get; set; } = string.Empty;
    public string BrandId { get; set; } = string.Empty;
    public List<string> TagIds { get; set; } = new();

    // Pricing and inventory
    public decimal BasePrice { get; set; }
    public string Currency { get; set; } = "USD";
    public int StockQuantity { get; set; }
    public int ReorderLevel { get; set; } = 10;
    public bool TrackInventory { get; set; } = true;

    // Physical properties
    public decimal Weight { get; set; }
    public string WeightUnit { get; set; } = "kg";
    public ProductDimensions Dimensions { get; set; } = new();

    // Status and visibility
    public ProductStatus Status { get; set; } = ProductStatus.Draft;
    public bool IsVisible { get; set; } = true;
    public bool IsFeatured { get; set; }
    public int SortOrder { get; set; }

    // SEO and marketing
    public string MetaTitle { get; set; } = string.Empty;
    public string MetaDescription { get; set; } = string.Empty;
    public string UrlSlug { get; set; } = string.Empty;

    // Media
    public List<ProductImage> Images { get; set; } = new();
    public ProductImage? PrimaryImage => Images.FirstOrDefault(i => i.IsPrimary);

    // Relationships
    public List<ProductVariant> Variants { get; set; } = new();
    public List<ProductAttribute> Attributes { get; set; } = new();
    public List<RelatedProduct> RelatedProducts { get; set; } = new();
}

public enum ProductStatus
{
    Draft = 1,
    Active = 2,
    Inactive = 3,
    OutOfStock = 4,
    Discontinued = 5
}

public class ProductDimensions
{
    public decimal Length { get; set; }
    public decimal Width { get; set; }
    public decimal Height { get; set; }
    public string Unit { get; set; } = "cm";
}

public class ProductImage : BaseEntity
{
    public string ProductId { get; set; } = string.Empty;
    public string ImageUrl { get; set; } = string.Empty;
    public string AltText { get; set; } = string.Empty;
    public bool IsPrimary { get; set; }
    public int SortOrder { get; set; }
}

Product Catalog

public class Category : BaseEntity
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string ParentCategoryId { get; set; } = string.Empty;
    public string ImageUrl { get; set; } = string.Empty;
    public bool IsActive { get; set; } = true;
    public int SortOrder { get; set; }
    public string UrlSlug { get; set; } = string.Empty;

    // SEO
    public string MetaTitle { get; set; } = string.Empty;
    public string MetaDescription { get; set; } = string.Empty;

    // Hierarchy helpers
    public List<Category> SubCategories { get; set; } = new();
    public Category? ParentCategory { get; set; }
}

public class Brand : BaseEntity
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string LogoUrl { get; set; } = string.Empty;
    public string Website { get; set; } = string.Empty;
    public bool IsActive { get; set; } = true;
    public int SortOrder { get; set; }
}

public class ProductAttribute : BaseEntity
{
    public string ProductId { get; set; } = string.Empty;
    public string AttributeName { get; set; } = string.Empty;
    public string AttributeValue { get; set; } = string.Empty;
    public AttributeType Type { get; set; } = AttributeType.Text;
    public bool IsRequired { get; set; }
    public bool IsVariant { get; set; } // Used for product variants
}

public enum AttributeType
{
    Text = 1,
    Number = 2,
    Boolean = 3,
    Date = 4,
    Choice = 5  // Predefined options
}

Order Domain

Order Entity

using OElite.Common.Platform.Orders;

public class Order : BaseEntity
{
    public string OrderNumber { get; set; } = string.Empty; // Human-readable order number
    public string CustomerId { get; set; } = string.Empty;
    public string MerchantId { get; set; } = string.Empty;

    // Order status and lifecycle
    public OrderStatus Status { get; set; } = OrderStatus.Pending;
    public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending;
    public FulfillmentStatus FulfillmentStatus { get; set; } = FulfillmentStatus.Pending;

    // Order items and pricing
    public List<OrderItem> Items { get; set; } = new();
    public decimal SubTotal { get; set; }
    public decimal TaxAmount { get; set; }
    public decimal ShippingAmount { get; set; }
    public decimal DiscountAmount { get; set; }
    public decimal TotalAmount { get; set; }
    public string Currency { get; set; } = "USD";

    // Customer information
    public CustomerInfo Customer { get; set; } = new();
    public OrderAddress BillingAddress { get; set; } = new();
    public OrderAddress ShippingAddress { get; set; } = new();

    // Shipping and fulfillment
    public string ShippingMethodId { get; set; } = string.Empty;
    public string TrackingNumber { get; set; } = string.Empty;
    public DateTime? ShippedAt { get; set; }
    public DateTime? DeliveredAt { get; set; }

    // Payment information
    public List<OrderPayment> Payments { get; set; } = new();

    // Order dates
    public DateTime PlacedAt { get; set; }
    public DateTime? CancelledAt { get; set; }
    public string CancellationReason { get; set; } = string.Empty;

    // Notes and communication
    public string CustomerNotes { get; set; } = string.Empty;
    public string InternalNotes { get; set; } = string.Empty;
}

public enum OrderStatus
{
    Pending = 1,
    Confirmed = 2,
    Processing = 3,
    Shipped = 4,
    Delivered = 5,
    Cancelled = 6,
    Refunded = 7
}

public class OrderItem : BaseEntity
{
    public string OrderId { get; set; } = string.Empty;
    public string ProductId { get; set; } = string.Empty;
    public string ProductVariantId { get; set; } = string.Empty;
    public string ProductName { get; set; } = string.Empty;
    public string ProductSKU { get; set; } = string.Empty;
    public decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
    public decimal LineTotal { get; set; }

    // Product snapshot at time of order
    public string ProductImageUrl { get; set; } = string.Empty;
    public Dictionary<string, string> ProductAttributes { get; set; } = new();
}

public class CustomerInfo
{
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string PhoneNumber { get; set; } = string.Empty;
}

public class OrderAddress
{
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Company { get; set; } = string.Empty;
    public string AddressLine1 { get; set; } = string.Empty;
    public string AddressLine2 { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public string StateProvince { get; set; } = string.Empty;
    public string PostalCode { get; set; } = string.Empty;
    public string CountryCode { get; set; } = string.Empty;
}

Payment Domain

using OElite.Common.Platform.Payments;

public class Payment : BaseEntity
{
    public string OrderId { get; set; } = string.Empty;
    public string CustomerId { get; set; } = string.Empty;
    public decimal Amount { get; set; }
    public string Currency { get; set; } = "USD";
    public PaymentStatus Status { get; set; } = PaymentStatus.Pending;
    public PaymentMethod Method { get; set; } = PaymentMethod.CreditCard;

    // Gateway information
    public string PaymentGatewayId { get; set; } = string.Empty;
    public string GatewayTransactionId { get; set; } = string.Empty;
    public string GatewayResponse { get; set; } = string.Empty;

    // Payment details (encrypted/tokenized)
    public string PaymentToken { get; set; } = string.Empty;
    public string LastFourDigits { get; set; } = string.Empty;
    public string CardBrand { get; set; } = string.Empty;

    // Transaction details
    public DateTime ProcessedAt { get; set; }
    public string ProcessorReferenceId { get; set; } = string.Empty;
    public string AuthorizationCode { get; set; } = string.Empty;

    // Refund information
    public List<PaymentRefund> Refunds { get; set; } = new();
    public decimal RefundedAmount => Refunds.Where(r => r.Status == RefundStatus.Completed).Sum(r => r.Amount);
    public decimal RemainingAmount => Amount - RefundedAmount;
}

public enum PaymentStatus
{
    Pending = 1,
    Authorized = 2,
    Captured = 3,
    Failed = 4,
    Cancelled = 5,
    Refunded = 6,
    PartiallyRefunded = 7
}

public enum PaymentMethod
{
    CreditCard = 1,
    DebitCard = 2,
    PayPal = 3,
    BankTransfer = 4,
    Cryptocurrency = 5,
    StoreCredit = 6,
    LoyaltyPoints = 7
}

public class PaymentRefund : BaseEntity
{
    public string PaymentId { get; set; } = string.Empty;
    public decimal Amount { get; set; }
    public string Reason { get; set; } = string.Empty;
    public RefundStatus Status { get; set; } = RefundStatus.Pending;
    public string GatewayRefundId { get; set; } = string.Empty;
    public DateTime ProcessedAt { get; set; }
    public string ProcessedBy { get; set; } = string.Empty; // UserId
}

public enum RefundStatus
{
    Pending = 1,
    Processing = 2,
    Completed = 3,
    Failed = 4,
    Cancelled = 5
}

Data Transfer Objects (DTOs)

Request/Response Models

using OElite.Common.Platform.DTOs;

// Customer DTOs
public class CreateCustomerRequest
{
    [Required, StringLength(100)]
    public string FirstName { get; set; } = string.Empty;

    [Required, StringLength(100)]
    public string LastName { get; set; } = string.Empty;

    [Required, EmailAddress]
    public string Email { get; set; } = string.Empty;

    [Phone]
    public string? PhoneNumber { get; set; }

    public DateTime? DateOfBirth { get; set; }
    public CustomerType Type { get; set; } = CustomerType.Individual;
    public List<CreateAddressRequest> Addresses { get; set; } = new();
}

public class CustomerResponse
{
    public string Id { get; set; } = string.Empty;
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string PhoneNumber { get; set; } = string.Empty;
    public CustomerStatus Status { get; set; }
    public int LoyaltyPoints { get; set; }
    public DateTime CreatedAt { get; set; }
    public List<AddressResponse> Addresses { get; set; } = new();
}

// Product DTOs
public class CreateProductRequest
{
    [Required, StringLength(200)]
    public string Name { get; set; } = string.Empty;

    [StringLength(1000)]
    public string Description { get; set; } = string.Empty;

    [Required, StringLength(50)]
    public string SKU { get; set; } = string.Empty;

    [Required]
    public string CategoryId { get; set; } = string.Empty;

    public string? BrandId { get; set; }

    [Range(0, double.MaxValue)]
    public decimal BasePrice { get; set; }

    [Range(0, int.MaxValue)]
    public int StockQuantity { get; set; }

    public bool TrackInventory { get; set; } = true;
    public List<ProductAttributeRequest> Attributes { get; set; } = new();
}

public class ProductResponse
{
    public string Id { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string SKU { get; set; } = string.Empty;
    public decimal BasePrice { get; set; }
    public string Currency { get; set; } = "USD";
    public ProductStatus Status { get; set; }
    public bool IsVisible { get; set; }
    public int StockQuantity { get; set; }
    public CategoryResponse Category { get; set; } = new();
    public BrandResponse? Brand { get; set; }
    public List<ProductImageResponse> Images { get; set; } = new();
}

// Order DTOs
public class CreateOrderRequest
{
    [Required]
    public string CustomerId { get; set; } = string.Empty;

    [Required]
    public List<OrderItemRequest> Items { get; set; } = new();

    public OrderAddressRequest BillingAddress { get; set; } = new();
    public OrderAddressRequest ShippingAddress { get; set; } = new();
    public string? ShippingMethodId { get; set; }
    public string? CouponCode { get; set; }
    public string? CustomerNotes { get; set; }
}

public class OrderResponse
{
    public string Id { get; set; } = string.Empty;
    public string OrderNumber { get; set; } = string.Empty;
    public OrderStatus Status { get; set; }
    public PaymentStatus PaymentStatus { get; set; }
    public decimal TotalAmount { get; set; }
    public string Currency { get; set; } = "USD";
    public DateTime PlacedAt { get; set; }
    public CustomerResponse Customer { get; set; } = new();
    public List<OrderItemResponse> Items { get; set; } = new();
    public OrderAddressResponse BillingAddress { get; set; } = new();
    public OrderAddressResponse ShippingAddress { get; set; } = new();
}

Validation Attributes

public class SKUValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value is string sku && !string.IsNullOrEmpty(sku))
        {
            // SKU format: ABC-123-XYZ
            var pattern = @"^[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+$";
            if (Regex.IsMatch(sku.ToUpperInvariant(), pattern))
                return ValidationResult.Success;
        }

        return new ValidationResult("SKU must be in format ABC-123-XYZ");
    }
}

public class PhoneValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) return ValidationResult.Success; // Optional field

        if (value is string phone && !string.IsNullOrEmpty(phone))
        {
            // Basic international phone number validation
            var pattern = @"^\+?[1-9]\d{1,14}$";
            if (Regex.IsMatch(phone.Replace(" ", "").Replace("-", ""), pattern))
                return ValidationResult.Success;
        }

        return new ValidationResult("Phone number must be a valid international format");
    }
}

Platform Configuration

Feature Flags and Settings

public class PlatformConfiguration : BaseEntity
{
    public string Key { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
    public ConfigurationType Type { get; set; } = ConfigurationType.String;
    public string Description { get; set; } = string.Empty;
    public bool IsEditable { get; set; } = true;
    public string Category { get; set; } = string.Empty;
}

public enum ConfigurationType
{
    String = 1,
    Integer = 2,
    Boolean = 3,
    Decimal = 4,
    Json = 5
}

public class FeatureFlag : BaseEntity
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public bool IsEnabled { get; set; }
    public DateTime? EnabledFrom { get; set; }
    public DateTime? EnabledUntil { get; set; }
    public List<string> EnabledForUserIds { get; set; } = new();
    public List<string> EnabledForSegments { get; set; } = new();
}

Event Models for Domain Events

using OElite.Common.Platform.Events;

public abstract class DomainEvent
{
    public string EventId { get; set; } = Guid.NewGuid().ToString();
    public DateTime OccuredAt { get; set; } = DateTime.UtcNow;
    public string EventType => GetType().Name;
}

// Customer events
public class CustomerCreatedEvent : DomainEvent
{
    public string CustomerId { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public CustomerType CustomerType { get; set; }
    public string MerchantId { get; set; } = string.Empty;
}

public class CustomerUpdatedEvent : DomainEvent
{
    public string CustomerId { get; set; } = string.Empty;
    public List<string> ChangedFields { get; set; } = new();
    public Dictionary<string, object> PreviousValues { get; set; } = new();
    public Dictionary<string, object> NewValues { get; set; } = new();
}

// Product events
public class ProductCreatedEvent : DomainEvent
{
    public string ProductId { get; set; } = string.Empty;
    public string SKU { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string CategoryId { get; set; } = string.Empty;
    public decimal BasePrice { get; set; }
}

public class ProductStockChangedEvent : DomainEvent
{
    public string ProductId { get; set; } = string.Empty;
    public string SKU { get; set; } = string.Empty;
    public int PreviousStock { get; set; }
    public int NewStock { get; set; }
    public string Reason { get; set; } = string.Empty;
}

// Order events
public class OrderPlacedEvent : DomainEvent
{
    public string OrderId { get; set; } = string.Empty;
    public string OrderNumber { get; set; } = string.Empty;
    public string CustomerId { get; set; } = string.Empty;
    public decimal TotalAmount { get; set; }
    public string Currency { get; set; } = "USD";
    public List<string> ProductIds { get; set; } = new();
}

public class OrderStatusChangedEvent : DomainEvent
{
    public string OrderId { get; set; } = string.Empty;
    public OrderStatus PreviousStatus { get; set; }
    public OrderStatus NewStatus { get; set; }
    public string ChangedBy { get; set; } = string.Empty;
    public string Reason { get; set; } = string.Empty;
}

Integration with OElite Platform

With OElite.Common

// Platform entities extend base OElite entities
public class Product : BaseEntity  // BaseEntity from OElite.Common
{
    // Platform-specific properties
}

// Platform DTOs use OElite utilities
public class ProductResponse
{
    public string Id { get; set; } = GuidUtils.CreateShortGuid();
    public DateTime CreatedAt { get; set; } = DateTimeUtils.GetUtcNow();
}

With OElite.Restme

// Platform entities can be cached using Restme
public async Task<Product> GetProductAsync(string productId)
{
    return await _cacheProvider.FindmeAsync<Product>(
        key: $"product:{productId}",
        refreshAction: () => _productRepository.GetByIdAsync(productId)
    );
}

Validation and Business Rules

Entity Validation

public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(c => c.FirstName)
            .NotEmpty()
            .MaximumLength(100);

        RuleFor(c => c.LastName)
            .NotEmpty()
            .MaximumLength(100);

        RuleFor(c => c.Email)
            .NotEmpty()
            .EmailAddress();

        RuleFor(c => c.PhoneNumber)
            .Matches(@"^\+?[1-9]\d{1,14}$")
            .When(c => !string.IsNullOrEmpty(c.PhoneNumber));
    }
}

public class ProductValidator : AbstractValidator<Product>
{
    public ProductValidator()
    {
        RuleFor(p => p.Name)
            .NotEmpty()
            .MaximumLength(200);

        RuleFor(p => p.SKU)
            .NotEmpty()
            .Matches(@"^[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+$")
            .WithMessage("SKU must be in format ABC-123-XYZ");

        RuleFor(p => p.BasePrice)
            .GreaterThanOrEqualTo(0);

        RuleFor(p => p.StockQuantity)
            .GreaterThanOrEqualTo(0)
            .When(p => p.TrackInventory);
    }
}

Requirements

  • .NET 10.0+
  • OElite.Common (base entities and utilities)
  • OElite.Restme and OElite.Restme.Utils (for caching and utilities)
  • System.ComponentModel.DataAnnotations (for validation attributes)
  • Newtonsoft.Json (for JSON serialization)

Usage Patterns

Repository Pattern

public interface IProductRepository
{
    Task<Product?> GetByIdAsync(string productId);
    Task<Product?> GetBySkuAsync(string sku);
    Task<List<Product>> GetByCategoryAsync(string categoryId);
    Task<Product> CreateAsync(Product product);
    Task<Product> UpdateAsync(Product product);
    Task<bool> DeleteAsync(string productId);
}

Service Layer Integration

public class ProductService
{
    public async Task<ProductResponse> CreateProductAsync(CreateProductRequest request)
    {
        var product = new Product
        {
            Id = GuidUtils.CreateShortGuid(),
            Name = request.Name,
            SKU = request.SKU,
            // ... other properties
            CreatedAt = DateTime.UtcNow
        };

        // Validate
        await ValidateProductAsync(product);

        // Save
        var savedProduct = await _repository.CreateAsync(product);

        // Return DTO
        return MapToResponse(savedProduct);
    }
}

Thread Safety

All entities and DTOs are designed to be thread-safe for read operations. Modification operations should be handled through proper service layer patterns with appropriate locking or optimistic concurrency control.

License

Copyright © OElite Limited. All rights reserved.

Showing the top 20 packages that depend on OElite.Common.Platform.

Packages Downloads
OElite.Common.Hosting.AspNetCore
Package Description
96
OElite.Common.Hosting.AspNetCore
Package Description
32
OElite.Common.Hosting.AspNetCore
Package Description
11
OElite.Data.Platform
Package Description
9
OElite.Data.Platform
Package Description
8
OElite.Data.Platform
Package Description
7
OElite.Common.Hosting.AspNetCore
Package Description
7
OElite.Data.Platform
Package Description
6

.NET 10.0

Version Downloads Last updated
5.0.9-develop.511 4 11/26/2025
5.0.9-develop.510 3 11/26/2025
5.0.9-develop.509 4 11/23/2025
5.0.9-develop.480 4 11/17/2025
5.0.9-develop.478 3 11/17/2025
5.0.9-develop.477 4 11/17/2025
5.0.9-develop.476 5 11/17/2025
5.0.9-develop.472 4 11/15/2025
5.0.9-develop.471 4 11/15/2025
5.0.9-develop.470 4 11/15/2025
5.0.9-develop.462 4 11/14/2025
5.0.9-develop.448 4 11/11/2025
5.0.9-develop.446 4 11/11/2025
5.0.9-develop.443 4 11/11/2025
5.0.9-develop.441 4 11/09/2025
5.0.9-develop.415 7 10/28/2025
5.0.9-develop.412 3 10/27/2025
5.0.9-develop.411 3 10/27/2025
5.0.9-develop.410 3 10/27/2025
5.0.9-develop.409 3 10/27/2025
5.0.9-develop.402 3 10/26/2025
5.0.9-develop.399 8 10/26/2025
5.0.9-develop.394 6 10/25/2025
5.0.9-develop.391 6 10/25/2025
5.0.9-develop.389 6 10/25/2025
5.0.9-develop.376 35 10/25/2025
5.0.9-develop.374 12 10/24/2025
5.0.9-develop.373 7 10/24/2025
5.0.9-develop.372 8 10/24/2025
5.0.9-develop.259 97 10/20/2025
5.0.9-develop.258 9 10/20/2025
5.0.9-develop.244 6 10/19/2025
5.0.9-develop.240 10 10/18/2025
5.0.9-develop.239 10 10/18/2025
5.0.9-develop.238 10 10/18/2025
5.0.9-develop.236 13 10/18/2025
5.0.9-develop.235 11 10/18/2025
5.0.9-develop.234 10 10/17/2025
5.0.9-develop.227 10 10/17/2025
5.0.9-develop.226 12 10/17/2025
5.0.9-develop.225 11 10/17/2025
5.0.9-develop.224 6 10/16/2025
5.0.9-develop.222 10 10/16/2025
5.0.9-develop.216 7 10/16/2025
5.0.9-develop.215 7 10/16/2025
5.0.9-develop.212 7 10/15/2025
5.0.9-develop.211 6 10/14/2025
5.0.9-develop.210 7 10/14/2025