Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/docs/DATA_LAYER.md

7.8 KiB

Data Layer

Part of Nop.Plugin.Misc.FruitBankPlugin. See README.md for project overview. For entity model see docs/DOMAIN_MODEL.md. For measurement workflows see docs/MEASUREMENT.md.

DbContext Classes

FruitBankDbContext

Inherits MgDbContextBase (from Mango.Nop.Data). Main data context for orders, shipping, partners, and files.

Implements interfaces: IOrderDtoDbSet, IOrderItemDtoDbSet, IPartnerDbSet, IShippingDbSet, IShippingDocumentDbSet, IShippingItemDbSet, IShippingItemPalletDbSet, IOrderItemPalletDbSet, IShippingDocumentToFilesDbSet, IFilesDbSet

DbSet properties:

DbSet Entity Table
OrderDtos OrderDto Order
OrderItemDtos OrderItemDto OrderItem
OrderItemPallets OrderItemPallet fbOrderItemPallet
Partners Partner fbPartner
Shippings Shipping fbShipping
ShippingDocuments ShippingDocument fbShippingDocument
ShippingItems ShippingItem fbShippingItem
ShippingItemPallets ShippingItemPallet fbShippingItemPallet
Files Files fbFiles
ShippingDocumentToFiles ShippingDocumentToFiles fbShippingDocumentToFiles
ProductDtos ProductDto Product
GenericAttributeDtos GenericAttributeDto GenericAttribute
StockQuantityHistoryDtos StockQuantityHistoryDto StockQuantityHistory
Customers Customer Customer
CustomerRoles CustomerRole CustomerRole

Key methods:

Method Purpose
AddShippingItemAsync() Creates item, copies IsMeasurable from ProductDto
UpdateShippingItemAsync() Complex: updates measuring values, handles stock/weight changes, manages product transitions
SetupShippingItemMeasuringValues() Recalculates totals from child pallets
AddShippingItemPalletAsync() / UpdateShippingItemPalletAsync() Pallet CRUD with cascade to parent ShippingItem
StartMeasuringAsync() Sets MeasurementOwnerId GenericAttribute, updates order status
SetOrderStatusToCompleteAsync() Validates pallets, updates stock, sets RevisorId, publishes event
DeleteOrderItemConstraintsAsync() Cleanup when order items deleted
UpdateStockQuantityAndWeightAsync() Updates Product.StockQuantity + NetWeight, creates history entry
DeleteShippingSafeAsync() Transactional cascade delete of shipping + children
DeleteShippingDocumentSafeAsync() Transactional cascade delete of document + children
GetCustomersBySystemRoleName() LINQ query for role-based customer lookup

All state-changing operations wrapped in TransactionSafeAsync() for ACID compliance.

StockTakingDbContext

Inherits MgDbContextBase. Dedicated context for inventory sessions.

DbSet properties:

DbSet Entity
ProductDtos ProductDto
OrderItemDtos OrderItemDto
StockTakings StockTaking
StockTakingItems StockTakingItem
StockTakingItemPallets StockTakingItemPallet
StockQuantityHistories StockQuantityHistory
GenericAttributes GenericAttribute

Key methods:

Method Purpose
CloseStockTaking() Validates all measured, updates stock/weight per item, marks closed
AddStockTakingItemPallet() / UpdateStockTakingItemPallet() Pallet CRUD with measured values refresh
RefreshStockTakingItemMeasuredValuesFromPallets() Sums quantities/weights from pallets

DbTable Repositories

Each entity has a *DbTable class inheriting MgDbTableBase<T> (from Mango.Nop.Data). Located in Domains/DataLayer/.

ShippingDbTable

Method Purpose
GetAll() All shippings ordered by ShippingDate
GetAll(bool loadRelations) Eager loads full graph: Documents → Items → Pallets + Pallet type + ProductDto + GenericAttributes
GetAllNotMeasured() Filters for incomplete/recent shipments
GetByIdAsync(bool loadRelations) Single with optional eager loading
OnUpdate() Hook: sets MeasuredDate when IsAllMeasured becomes true

OrderDtoDbTable

Method Purpose
GetAll(bool loadRelations) Eager loads: GenericAttributes, Customer, OrderNotes, OrderItemDtos (with ProductDto, GenericAttributes, OrderItemPallets)
GetByIdAsync(bool loadRelations) Single order with optional relations
GetAllByOrderStatus() Status-filtered query
GetAllForMeasuring(DateTime fromDate) Unpaid, not cancelled, with DateOfReceipt >= fromDate
GetAllByProductId() / GetAllByProductIds() Product-filtered queries
GetAllByIds() Batch retrieval

Other DbTable classes

Class Entity Key behaviors
ProductDtoDbTable ProductDto GetAll with GenericAttributes
PartnerDbTable Partner Standard CRUD
ShippingDocumentDbTable ShippingDocument GetAll with items, files, partner
ShippingItemDbTable ShippingItem GetAll with pallets
ShippingItemPalletDbTable ShippingItemPallet Standard CRUD
OrderItemDtoDbTable OrderItemDto GetAll with pallets, product
OrderItemPalletDbTable OrderItemPallet Standard CRUD
FilesDbTable Files Standard CRUD
ShippingDocumentToFilesDbTable ShippingDocumentToFiles Standard CRUD
StockTakingDbTable StockTaking GetAll with items, pallets
StockTakingItemDbTable StockTakingItem GetAll with pallets
StockTakingItemPalletDbTable StockTakingItemPallet Standard CRUD
StockQuantityHistoryDtoDbTable StockQuantityHistoryDto Filtered by date range

Repository Interfaces

Located in Domains/DataLayer/Interfaces/. Each interface (e.g., IShippingDbSet, IOrderDtoDbSet) declares the DbSet property that the DbContext must implement. This allows DbTable classes to accept any context that provides the required DbSet.

Entity Mapping

  • Mapping/Builders/PluginBuilder.cs — EF Core Fluent API entity configuration for plugin-owned tables (fb* prefix)
  • Mapping/NameCompatibility.cs — Table name mapping for nopCommerce compatibility
  • Migrations/SchemaMigration.cs — FluentMigrator schema setup for CustomTable base entity

FruitBankEventConsumer

Located in Domains/EventConsumers/. Extends MgEventConsumerBase (from Mango.Nop.Services). Handles entity lifecycle events for cascading updates.

Product events:

Event Action
EntityInsertedEvent<Product> Saves custom attributes (IsMeasurable, NetWeight, Tare, AverageWeight, AverageWeightTreshold, IncomingQuantity)
EntityUpdatedEvent<Product> Updates custom attributes, syncs IsMeasurable/Tare changes to existing ShippingItems

Shipping cascade events:

Event Action
EntityDeletedEvent<ShippingItemPallet> Refreshes parent ShippingItem measuring values
EntityInsertedEvent/UpdatedEvent<ShippingItem> Rechecks ShippingDocument.IsAllMeasured
EntityInsertedEvent/UpdatedEvent<ShippingDocument> Rechecks Shipping.IsAllMeasured
EntityDeletedEvent<Shipping> Cascade deletes child documents
EntityDeletedEvent<ShippingDocument> Cascade deletes child items
EntityDeletedEvent<ShippingItem> Cascade deletes child pallets

Order events:

Event Action
EntityDeletedEvent<OrderItem> Cleanup via MeasurementService.DeleteOrderItemConstraintsAsync()
EntityInsertedEvent/UpdatedEvent<OrderItem> Post-process via MeasurementService.OrderItemInsertedOrUpdatedPostProcess()

Eager Loading Pattern

DbTable GetAll(bool loadRelations = true) uses LoadWith() chains to eagerly load entity graphs. Example for OrderDtoDbTable:

OrderDto
  → GenericAttributes
  → Customer
  → OrderNotes
  → OrderItemDtos
      → ProductDto → GenericAttributes
      → GenericAttributes
      → OrderItemPallets

This avoids N+1 queries when transferring full entity graphs to FruitBankHybridApp via SignalR.