OElite.Common.Platform 5.0.9-develop.478
OElite.Common.Platform
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
- OElite.Common (>= 5.0.9-develop.478)
- OElite.Restme (>= 2.0.9-develop.442)
- OElite.Restme.Utils (>= 2.0.9-develop.442)