# Nop.Plugin.Misc.AIPlugin (FruitBank nopCommerce Plugin)

@project {
  type = "nopcommerce-plugin"
  own-dep-projects = [
    "Mango.Nop.Core, Mango.Nop.Services (in NopCommerce.Common/4.70/Libraries)"
  ]
}

> For Mango.Nop library docs see `NopCommerce.Common/4.70/Libraries/README.md`
> For FruitBankHybridApp domain rules see the FruitBankHybridApp solution's `.github/copilot-instructions.md`
> For core measurement system rules and common domain traps, see: `../../../../FruitBankHybridApp/FruitBank.Common/docs/GLOSSARY.md`

Server-side nopCommerce plugin for FruitBank, a fruit and vegetable wholesaler. Manages supplier inbound delivery (receiving), warehouse weighing (net/gross/pallet/tare weights), outbound order measurement, customer pre-orders, inventory stocktaking, AI services, and Billingo invoicing. Runs inside nopCommerce 4.80.9 (**net9.0**).

Project file: `Nop.Plugin.Misc.FruitBankPlugin.csproj`

## Documentation

| Document | Topic |
|---|---|
| `docs/SCHEMA.md` | Authoritative domain model in TOON format — all entities, DTOs, enums, relationships |
| `docs/DOMAIN_MODEL.md` | Behavioral docs: weight formula, MeasuringStatus lifecycle, GenericAttribute keys, entity hierarchy overview |
| `docs/MEASUREMENT.md` | Three measurement workflows (inbound shipping, outbound order, stocktaking), MeasuringStatus lifecycle, pricing, checkout filter |
| `docs/AI_SERVICES.md` | OpenAI, Cerebras, Replicate providers, FruitBankSettings, file storage, PDF conversion, audio transcription |
| `docs/DATA_LAYER.md` | FruitBankDbContext, StockTakingDbContext, DbTable repositories, entity mapping, FruitBankEventConsumer |
| `docs/SIGNALR/README.md` | SignalR endpoints, FruitBankDataController, InnVoice/Billingo integration, FruitBankAttributeService |
| `docs/PREORDER/README.md` | Customer pre-order workflow — placement, FCFS allocation on incoming stock, conversion to real orders, expiry |

## Folder Structure

| Folder | Purpose |
|---|---|
| `Areas/Admin/Controllers/` | Admin MVC controllers — order, product, shipping, SignalR endpoints, file management |
| `Areas/Admin/Components/` | Admin ViewComponents — DevExtreme grids |
| `Areas/Admin/Models/` | Admin view models |
| `Areas/Admin/Views/` | Admin Razor views |
| `Components/` | Public-side ViewComponents |
| `Controllers/` | Public-side controllers — `FruitBankDataController`, `CheckoutController` |
| `Domains/DataLayer/` | DbContexts, DbTable repositories, interfaces |
| `Domains/EventConsumers/` | nopCommerce entity event handlers |
| `Factories/` | Model factories (order, product, shipping) |
| `Filters/` | `PendingMeasurementCheckoutFilter` |
| `Infrastructure/` | `PluginNopStartup` (DI), `RouteProvider`, `ViewLocationExpander` |
| `Mapping/` | EF Core entity mapping, `PluginBuilder` |
| `Migrations/` | FluentMigrator database schema |
| `Models/` | Shared models — AI chat, MgBase extensions, order/product models |
| `Services/` | Business logic — AI, measurement, file storage, invoicing, locking |

## Dependencies

- `Mango.Nop.Core`, `Mango.Nop.Services` (ProjectReferences via `../../Libraries/`)
- `Nop.Services`, `Nop.Web` (nopCommerce ProjectReferences)
- AyCode.Core solution assemblies (DLL HintPaths in .csproj)
- DevExpress ASP.NET Core 25.1.3, DevExtreme 25.1.3
- SignalR, EF Core 9.0, PdfPig, PDFtoImage

## Initialization & Quirks

- **AcBinary Source Generator Registration**: NopCommerce plugins are loaded dynamically via `AssemblyLoadContext`, which prevents the .NET runtime from executing `[ModuleInitializer]` attributes. To ensure the high-performance binary serializers are registered (instead of falling back to slow reflection), `PluginNopStartup.ConfigureServices` must call `Mango.Nop.Core.AcBinaryForcedInit.ForceRegister()`.

## Type-Location Map

Quick lookup for "where does this type live?" — saves cross-repo grep rounds.

| Type / class family | Lives in | Path (relative or NuGet) |
|---|---|---|
| `Customer`, `Order`, `OrderItem`, `OrderNote`, `Product`, `GenericAttribute`, `CustomerRole` | nopCommerce framework | `Nop.Core` (ProjectRef) |
| `*Dto` classes (`OrderDto`, `OrderItemDto`, `ProductDto`, `GenericAttributeDto`, `StockQuantityHistoryDto`) | Mango.Nop.Core | `../../Libraries/Mango.Nop.Core/` |
| `MgDbContextBase`, `MgDbTableBase<T>`, `MgEventConsumerBase`, other `Mg*` base types | Mango.Nop.* libraries | `../../Libraries/Mango.Nop.{Core,Services,Data}/` |
| `Ac*` types (`AcBinaryHubProtocol`, `AcBinarySerializer`, `AcLoggerBase`, `AcBinaryForcedInit`) | AyCode.Core (DLL HintPath) | `../../../Aycode/Source/AyCode.Core/` |
| `fb*`-table entities: `Shipping`, `ShippingDocument`, `ShippingItem`, `ShippingItemPallet`, `OrderItemPallet`, `StockTaking`, `StockTakingItem`, `StockTakingItemPallet`, `Partner`, `Files`, `Pallet` | this plugin | `Domains/...` (full schema in `docs/SCHEMA.md`) |
| `FullProcessModel` (bulk SignalR sync container) | this plugin | `Models/` |
| `FruitBankDbContext`, `StockTakingDbContext`, `*DbTable` repositories (`OrderDtoDbTable`, `ShippingDbTable`, …), `I*DbSet` interfaces | this plugin | `Domains/DataLayer/` |
| `FruitBankEventConsumer`, `MeasurementService`, `CustomPriceCalculationService`, `FruitBankAttributeService` | this plugin | `Domains/EventConsumers/`, `Services/` |
| AI: `OpenAIApiService`, `CerebrasAPIService`, `ReplicateService`, `OpenAIService`, `AICalculationService` | this plugin | `Services/` |
| File / PDF / Audio: `FileStorageService`, `LocalStorageProvider`, `PdfToImageService`, `FruitBankAudioController` | this plugin | `Services/`, `Controllers/` |
| Billingo: `InnVoiceOrderService`, `InnvoiceApiService` (+ `InnVoiceOrderController`, `InnVoiceOrderSyncController`) | this plugin | `Services/`, `Areas/Admin/Controllers/` |
| SignalR: `FruitBankHub`, `CustomOrderSignalREndpoint`, `StockSignalREndpointServer`, `FruitBankDataController` | this plugin | `Services/`, `Areas/Admin/Controllers/`, `Controllers/` |
| Infra: `FruitBankSettings`, `PluginNopStartup`, `RouteProvider`, `ViewLocationExpander`, `PendingMeasurementCheckoutFilter` | this plugin | `Infrastructure/`, `Filters/` |

If a type isn't listed: grep `../../Libraries/` first → `../../../Aycode/Source/AyCode.Core/` next → otherwise it's a nopCommerce framework type (`Nop.Core`, `Nop.Services`, `Nop.Web`).
