20 KiB
Domain Model Schema (Toon Format)
Part of
Nop.Plugin.Misc.FruitBankPlugin. SeeREADME.mdfor project overview. Full domain model in Toon (Token-Oriented Object Notation) format — seeAyCode.Core/Serializers/Toons/README.md(in AyCode.Core solution). This is the authoritative schema for entities, DTOs, and enums in the FruitBank domain. For behavioral documentation (workflows, lifecycles, event cascades) seedocs/DOMAIN_MODEL.md.
@meta { version = "1.0" format = "toon" source-code-language = "C#" context = "This is a nopCommerce plugin developed for FruitBank, a fruit and vegetable wholesaler. The plugin manages supplier inbound delivery (receiving), warehouse weighing (net/gross/pallet/tare weights), and inventory stocktaking. The business logic is centered around FruitBank's requirement for precise physical measurement and quantity tracking." types = ["OrderStatus", "ShippingStatus", "PaymentStatus", "GenericAttributeDto", "MeasuringStatus", "VatNumberStatus", "TaxDisplayType", "OrderNote", "DocumentType", "Files", "Pallet", "ProductDto", "Customer", "FullProcessModel", "OrderDto", "OrderItemDto", "OrderItemPallet", "Partner", "Shipping", "ShippingDocument", "ShippingDocumentToFiles", "ShippingItem", "ShippingItemPallet", "StockTaking", "StockTakingItem", "StockTakingItemPallet"] }
@types { OrderStatus: enum underlying-type: "int" default-value: 10 values: Pending = 10 Processing = 20 Complete = 30 Cancelled = 40
ShippingStatus: enum underlying-type: "int" default-value: 10 values: ShippingNotRequired = 10 NotYetShipped = 20 PartiallyShipped = 25 Shipped = 30 Delivered = 40
PaymentStatus: enum underlying-type: "int" default-value: 10 values: Pending = 10 Authorized = 20 Paid = 30 PartiallyRefunded = 35 Refunded = 40 Voided = 50
GenericAttributeDto: "Data transfer object for GenericAttribute" table-name: "GenericAttribute" related-type: "dto-of GenericAttribute" CreatedOrUpdatedDateUTC: DateTime? EntityId: int constraints: "polymorphic-fk(KeyGroup)" Key: string KeyGroup: string StoreId: int Value: string purpose: "Raw string representation of the Key's value" Id: int purpose: "Primary key / unique identification" primary-key: true
MeasuringStatus: enum underlying-type: "int" default-value: 0 values: NotStarted = 0 Started = 10 Finnished = 20 Audited = 30
VatNumberStatus: enum underlying-type: "int" default-value: 0 values: Unknown = 0 Empty = 10 Valid = 20 Invalid = 30
TaxDisplayType: enum underlying-type: "int" default-value: 0 values: IncludingTax = 0 ExcludingTax = 10
OrderNote: "NopCommerce order note entity" table-name: "OrderNote" CreatedOnUtc: DateTime DisplayToCustomer: bool DownloadId: int Note: string OrderId: int description: "Foreign key to parent Order" Id: int purpose: "Primary key / unique identification" primary-key: true
DocumentType: enum underlying-type: "int" default-value: 0 values: NotSet = 0 Unknown = 5 ShippingDocument = 10 OrderConfirmation = 15 Invoice = 20
Files: "Uploaded file with extracted text content" table-name: "fbFiles" purpose: "A centralized repository for all uploaded binary content and metadata, featuring a 'RawText' field that stores OCR-extracted information for full-text search and automated data validation across the system" Created: DateTime FileExtension: string FileHash: string FileName: string FileSubPath: string IsCompressed: bool purpose: "Status flag" Modified: DateTime RawText: string Id: int purpose: "Primary key / unique identification" primary-key: true
Pallet: "Pallet type definition with size and weight" table-name: "fbPallet" Created: DateTime Modified: DateTime Name: string Size: string Weight: double? Id: int purpose: "Primary key / unique identification" primary-key: true
ProductDto: "Product data with measurements and generic attributes" table-name: "Product" related-type: "dto-of Product" AvailableQuantity: int business-logic: "get => StockQuantity + IncomingQuantity" constraints: "readonly, not-mapped" AverageWeight: double business-logic: "get => GenericAttributes.GetValueOrDefault('AverageWeight')" constraints: "readonly, not-mapped" AverageWeightTreshold: double business-logic: "get => GenericAttributes.GetValueOrDefault('AverageWeightTreshold')" constraints: "readonly, not-mapped" GenericAttributes: List navigation: "one-to-many" IncomingQuantity: int business-logic: "get => GenericAttributes.GetValueOrDefault('IncomingQuantity')" constraints: "not-mapped" IsMeasurable: bool purpose: "Master flag: if false, the system bypasses weight validation but still creates one Measurement Record (PalletItem) with TrayQuantity." business-logic: "get => GenericAttributes.GetValueOrDefault('IsMeasurable')" constraints: "not-mapped" NetWeight: double business-logic: "get => GenericAttributes.GetValueOrDefault('NetWeight')" constraints: "not-mapped" Tare: double business-logic: "get => GenericAttributes.GetValueOrDefault('Tare')" constraints: "not-mapped" Deleted: bool FullDescription: string Height: decimal Length: decimal LimitedToStores: bool Name: string ParentGroupedProductId: int Price: decimal ProductCost: decimal ProductTypeId: int ShortDescription: string StockQuantity: int SubjectToAcl: bool WarehouseId: int Weight: decimal Width: decimal Id: int purpose: "Primary key / unique identification" primary-key: true
Customer: "NopCommerce customer entity" table-name: "Customer" Active: bool AdminComment: string AffiliateId: int BillingAddressId: int? CannotLoginUntilDateUtc: DateTime? City: string Company: string CountryId: int County: string CreatedOnUtc: DateTime CurrencyId: int? CustomCustomerAttributesXML: string CustomerGuid: Guid DateOfBirth: DateTime? Deleted: bool Email: string constraints: "email-format" EmailToRevalidate: string constraints: "email-format" FailedLoginAttempts: int Fax: string FirstName: string Gender: string HasShoppingCartItems: bool IsSystemAccount: bool purpose: "Status flag" IsTaxExempt: bool purpose: "Status flag" LanguageId: int? constraints: "range: 0-150" LastActivityDateUtc: DateTime LastIpAddress: string LastLoginDateUtc: DateTime? LastName: string MustChangePassword: bool Phone: string RegisteredInStoreId: int RequireReLogin: bool ShippingAddressId: int? StateProvinceId: int StreetAddress: string StreetAddress2: string SystemName: string TaxDisplayType: TaxDisplayType? TaxDisplayTypeId: int? TimeZoneId: string Username: string VatNumber: string VatNumberStatus: VatNumberStatus VatNumberStatusId: int VendorId: int ZipPostalCode: string Id: int purpose: "Primary key / unique identification" primary-key: true
FullProcessModel: "Object of type FullProcessModel" table-name: "FullProcessModel" purpose: "Container model for Shipping, Order" Orders: List navigation: "one-to-many" Shippings: List navigation: "one-to-many" StockTakings: List navigation: "one-to-many"
OrderDto: "Data transfer object for Order" table-name: "Order" related-type: "dto-of Order" DateOfReceipt: DateTime? business-logic: "get => GenericAttributes.GetValueOrNull('DateOfReceipt')" constraints: "readonly, not-mapped" DateOfReceiptOrCreated: DateTime constraints: "readonly, not-mapped" GenericAttributes: List navigation: "one-to-many" IsAllOrderItemAudited: bool purpose: "Status flag" business-logic: "get => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited)" constraints: "readonly, not-mapped" IsAllOrderItemAvgWeightValid: bool purpose: "Status flag" business-logic: "get => OrderItemDtos.All(oi => oi.AverageWeightIsValid)" constraints: "readonly, not-mapped" IsComplete: bool purpose: "Status flag" business-logic: "get => OrderStatus == OrderStatus.Complete" constraints: "readonly, not-mapped" IsMeasurable: bool purpose: "Status flag" business-logic: "get => OrderItemDtos.Any(oi => oi.IsMeasurable)" constraints: "readonly, not-mapped" IsMeasured: bool purpose: "Status flag" business-logic: "get => Id > 0 && OrderItemDtos.Count > 0 && OrderItemDtos.All(x => x.IsMeasured)" constraints: "readonly, not-mapped" MeasurementOwnerId: int business-logic: "get => GenericAttributes.GetValueOrDefault('MeasurementOwnerId', 0)" constraints: "readonly, not-mapped" MeasuringStatus: MeasuringStatus constraints: "readonly, not-mapped" RevisorId: int business-logic: "get => GenericAttributes.GetValueOrDefault('RevisorId', 0)" constraints: "readonly, not-mapped" TimeOfReceiptText: string constraints: "readonly, not-mapped" CreatedOnUtc: DateTime CustomOrderNumber: string CustomValuesXml: string Customer: Customer foreign-key: "CustomerId" navigation: "many-to-one" CustomerId: int Deleted: bool OrderDiscount: decimal OrderGuid: Guid OrderItemDtos: List other-key: "OrderId" navigation: "one-to-many" inverse-property: "OrderDto" OrderNotes: List other-key: "OrderId" navigation: "one-to-many" OrderStatus: OrderStatus purpose: "Enum wrapper" business-logic: "get, set => OrderStatusId" OrderStatusId: int OrderTotal: decimal PaidDateUtc: DateTime? PaymentStatus: PaymentStatus purpose: "Enum wrapper" business-logic: "get, set => PaymentStatusId" PaymentStatusId: int ShippingMethod: string ShippingStatus: ShippingStatus purpose: "Enum wrapper" business-logic: "get, set => ShippingStatusId" ShippingStatusId: int StoreId: int Id: int purpose: "Primary key / unique identification" primary-key: true
OrderItemDto: "Order item with measurements, pallets, and validation" table-name: "OrderItem" related-type: "dto-of OrderItem" AverageWeight: double business-logic: "get => IsMeasurable && OrderItemPallets.Count > 0 ? double.Round(OrderItemPallets.Sum(oip => oip.AverageWeight) / OrderItemPallets.Count, 1) : 0d" constraints: "readonly, not-mapped" AverageWeightDifference: double business-logic: "get => IsMeasurable ? double.Round(ProductDto!.AverageWeight - AverageWeight, 1) : 0" constraints: "readonly, not-mapped" AverageWeightIsValid: bool business-logic: "get => !IsMeasurable || (ProductDto!.AverageWeight > 0 && ((AverageWeightDifference / ProductDto!.AverageWeight) * 100) < ProductDto!.AverageWeightTreshold)" constraints: "readonly, not-mapped" GenericAttributes: List navigation: "one-to-many" GrossWeight: double business-logic: "get => double.Round(OrderItemPallets.Sum(x => x.NetWeight), 1)" constraints: "not-mapped" IsAudited: bool purpose: "Status flag" business-logic: "get => OrderItemPallets.Count > 0 && OrderItemPallets.All(oip => oip.IsAudited)" constraints: "readonly, not-mapped" IsMeasurable: bool purpose: "Status flag" business-logic: "get => ProductDto!.IsMeasurable" constraints: "not-mapped" IsMeasured: bool purpose: "Status flag" business-logic: "get => IsMeasuredAndValid()" constraints: "not-mapped" MeasuringStatus: MeasuringStatus business-logic: "get => complex conditional logic based on IsAudited, IsMeasured, and OrderItemPallets status" constraints: "readonly, not-mapped" NetWeight: double business-logic: "get => double.Round(OrderItemPallets.Sum(x => x.NetWeight), 1)" constraints: "not-mapped" OrderDto: OrderDto foreign-key: "OrderId" navigation: "many-to-one" inverse-property: "OrderItemDtos" OrderItemPallets: List other-key: "OrderItemId" navigation: "one-to-many" inverse-property: "OrderItemDto" TrayQuantity: int business-logic: "get => OrderItemPallets.Sum(x => x.TrayQuantity)" constraints: "not-mapped" AttributesXml: string ItemWeight: decimal? OrderId: int OrderItemGuid: Guid PriceExclTax: decimal PriceInclTax: decimal ProductDto: ProductDto foreign-key: "ProductId" navigation: "many-to-one" ProductId: int ProductName: string business-logic: "get => ProductDto?.Name ?? 'ProductDto is null!!!'" constraints: "readonly" Quantity: int UnitPriceExclTax: decimal UnitPriceInclTax: decimal Id: int purpose: "Primary key / unique identification" primary-key: true
OrderItemPallet: "Pallet measurements for order items with audit tracking" table-name: "fbOrderItemPallet" purpose: "A measurement record for outgoing goods. NOTE: Despite the 'Pallet' name, this is a general measurement record that is ALWAYS created for every item." AverageWeight: double business-logic: "get => double.Round(NetWeight / TrayQuantity, 1)" constraints: "readonly, not-mapped" IsAudited: bool purpose: "Status flag" business-logic: "get => RevisorId > 0" constraints: "readonly, not-mapped" MeasuringStatus: MeasuringStatus business-logic: "get => IsAudited ? MeasuringStatus.Audited : base.MeasuringStatus" constraints: "readonly, not-mapped" OrderItemDto: OrderItemDto foreign-key: "OrderItemId" navigation: "many-to-one" inverse-property: "OrderItemPallets" OrderItemId: int RevisorId: int purpose: "User/Customer ID of the quality auditor" Created: DateTime CreatorId: int? GrossWeight: double IsMeasured: bool Modified: DateTime ModifierId: int? NetWeight: double business-logic: "get => GrossWeight - PalletWeight - (TrayQuantity * TareWeight)" constraints: "readonly, not-mapped" PalletWeight: double TareWeight: double TrayQuantity: int Id: int primary-key: true
Partner: "Business partner with address and tax information" table-name: "fbPartner" purpose: "External supplier providing goods" CertificationNumber: string City: string Country: string County: string Created: DateTime Modified: DateTime Name: string PostalCode: string ShippingDocuments: List navigation: "one-to-many" State: string Street: string TaxId: string Id: int primary-key: true
Shipping: "Inbound delivery event at warehouse" table-name: "fbShipping" CargoCompany: string Comment: string Created: DateTime IsAllMeasured: bool LicencePlate: string MeasuredDate: DateTime? Modified: DateTime ShippingDate: DateTime ShippingDocuments: List navigation: "one-to-many" Id: int primary-key: true
ShippingDocument: "Supplier delivery note or invoice" table-name: "fbShippingDocument" Comment: string Country: string Created: DateTime DocumentIdNumber: string IsAllMeasured: bool Modified: DateTime Partner: Partner foreign-key: "PartnerId" navigation: "many-to-one" PartnerId: int PdfFileName: string Shipping: Shipping foreign-key: "ShippingId" navigation: "many-to-one" ShippingDate: DateTime ShippingDocumentToFiles: List navigation: "one-to-many" ShippingId: int? ShippingItems: List navigation: "one-to-many" TotalPallets: int Id: int primary-key: true
ShippingDocumentToFiles: "Links documents to files with type" table-name: "fbShippingDocumentToFiles" Created: DateTime DocumentType: DocumentType DocumentTypeId: int FilesId: int Modified: DateTime ShippingDocument: ShippingDocument foreign-key: "ShippingDocumentId" navigation: "many-to-one" ShippingDocumentFile: Files foreign-key: "FilesId" navigation: "many-to-one" ShippingDocumentId: int Id: int primary-key: true
ShippingItem: "Product line on shipping document" table-name: "fbShippingItem" Created: DateTime GrossWeightOnDocument: double HungarianName: string IsMeasurable: bool IsMeasured: bool MeasuredGrossWeight: double MeasuredNetWeight: double MeasuredQuantity: int MeasuringCount: int MeasuringStatus: MeasuringStatus constraints: "readonly, not-mapped" Modified: DateTime Name: string NameOnDocument: string NetWeightOnDocument: double Pallet: Pallet foreign-key: "PalletId" navigation: "many-to-one" PalletId: int? PalletsOnDocument: int ProductDto: ProductDto foreign-key: "ProductId" navigation: "many-to-one" ProductId: int? QuantityOnDocument: int ShippingDocument: ShippingDocument foreign-key: "ShippingDocumentId" navigation: "many-to-one" ShippingDocumentId: int ShippingItemPallets: List navigation: "one-to-many" UnitPriceOnDocument: double Id: int primary-key: true
ShippingItemPallet: "Measurement record for incoming goods" table-name: "fbShippingItemPallet" purpose: "Always created even without physical pallet" ShippingItem: ShippingItem foreign-key: "ShippingItemId" navigation: "many-to-one" ShippingItemId: int Created: DateTime CreatorId: int? GrossWeight: double IsMeasured: bool MeasuringStatus: MeasuringStatus constraints: "readonly, not-mapped" Modified: DateTime ModifierId: int? NetWeight: double business-logic: "get => GrossWeight - PalletWeight - (TrayQuantity * TareWeight)" constraints: "readonly, not-mapped" PalletWeight: double TareWeight: double TrayQuantity: int Id: int primary-key: true
StockTaking: "Inventory session record" table-name: "fbStockTaking" Created: DateTime Creator: int IsClosed: bool Modified: DateTime StartDateTime: DateTime StockTakingItems: List navigation: "one-to-many" Id: int primary-key: true
StockTakingItem: "Line item for product reconciliation" table-name: "fbStockTakingItem" purpose: "Reconciles snapshot quantity with physical count" InProcessOrdersQuantity: int IsInvalid: bool constraints: "readonly, not-mapped" IsMeasurable: bool IsRequiredForMeasuring: bool constraints: "readonly, not-mapped" MeasuredNetWeight: double NetWeightDiff: double constraints: "readonly, not-mapped" OriginalNetWeight: double QuantityDiff: int constraints: "readonly, not-mapped" StockTakingItemPallets: List navigation: "one-to-many" TotalOriginalQuantity: int constraints: "readonly, not-mapped" Created: DateTime IsMeasured: bool MeasuredStockQuantity: int Modified: DateTime OriginalStockQuantity: int Product: ProductDto foreign-key: "ProductId" navigation: "many-to-one" ProductId: int StockTaking: StockTaking foreign-key: "StockTakingId" navigation: "many-to-one" StockTakingId: int Id: int primary-key: true
StockTakingItemPallet: "Weight record for inventory item" table-name: "fbStockTakingItemPallet" purpose: "Mandatory for every inventory item, even non-measurable" StockTakingItem: StockTakingItem foreign-key: "StockTakingItemId" navigation: "many-to-one" StockTakingItemId: int Created: DateTime CreatorId: int? GrossWeight: double IsMeasured: bool MeasuringStatus: MeasuringStatus constraints: "readonly, not-mapped" Modified: DateTime ModifierId: int? NetWeight: double business-logic: "get => GrossWeight - PalletWeight - (TrayQuantity * TareWeight)" constraints: "readonly, not-mapped" PalletWeight: double TareWeight: double TrayQuantity: int Id: int primary-key: true }