FruitBankHybridApp/docs/ARCHITECTURE.md

144 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Architecture
## Solution Dependency Graph
```
FruitBank.Common (shared domain, net9.0)
FruitBank.Common.Server (server-side services, nopCommerce, net9.0)
FruitBankHybrid.Shared.Common (shared utilities, net10.0)
FruitBankHybrid.Shared (Blazor UI components, pages, services, net10.0)
↑ ↑ ↑
FruitBankHybrid FruitBankHybrid.Web FruitBankHybrid.Web.Client
(MAUI, net10.0) (Server, net10.0) (WASM, net10.0)
```
All projects also reference **AyCode.Core** (net9.0) and **AyCode.Blazor** (net10.0) via DLL references (not ProjectReference).
> **Context:** When a type or base class is not found in this solution, browse the external repos:
> - **AyCode.Core**: `../../../Aycode/Source/AyCode.Core/` — SignalR, serialization, binary protocol, data sources
> - **AyCode.Blazor**: `../../../Aycode/Source/AyCode.Blazor/` — MgGridBase, UI components, layout persistence
> - **Mango.Nop Libraries**: `../NopCommerce.Common/4.70/Libraries/` — independent library with own [copilot-instructions](../NopCommerce.Common/4.70/Libraries/.github/copilot-instructions.md) and [docs/](../NopCommerce.Common/4.70/Libraries/docs/)
> - **FruitBank Plugin**: `../NopCommerce.Common/4.70/Plugins/Nop.Plugin.Misc.AIPlugin/` — server-side SignalR hubs, measurement services, DbTable classes
## Target Frameworks
nopCommerce 4.80.9 requires .NET 9
| Project | TFM | Reason |
|---|---|---|
| FruitBank.Common | net9.0 | nopCommerce entity references |
| FruitBank.Common.Server | net9.0 | nopCommerce server integration |
| FruitBankHybrid.Shared | net10.0 | Blazor UI |
| FruitBankHybrid.Shared.Common | net10.0 | Shared utilities |
| FruitBankHybrid | net10.0android/ios/win | MAUI Hybrid |
| FruitBankHybrid.Web | net10.0 | Blazor Server host |
| FruitBankHybrid.Web.Client | net10.0 | Blazor WASM |
| FruitBankHybrid.Shared.Tests | net10.0 | Tests |
| **AyCode.Core** (external) | net9.0 | Foundation — used by nopCommerce layer |
| **AyCode.Blazor** (external) | net10.0 | UI framework |
| **AyCode.Core.Serializers.SourceGenerator** | netstandard2.0 | Roslyn analyzer requirement |
## Three Deployment Targets
| Target | Project | How UI Runs |
|---|---|---|
| **MAUI Hybrid** | FruitBankHybrid | Native app with BlazorWebView |
| **Blazor Server** | FruitBankHybrid.Web | Server-side rendering + SignalR |
| **Blazor WASM** | FruitBankHybrid.Web.Client | Downloaded to browser, runs in WASM |
All three share the same UI components from `FruitBankHybrid.Shared`.
## Data Flow
```
User → DevExpress Grid → AcSignalRDataSource → SignalR (AcBinary) → DevAdminSignalRHub
DynamicMethodRegistry
IFruitBankDataControllerServer
ICustomOrderSignalREndpointServer
IStockSignalREndpointServer
nopCommerce Database
```
## MgGrid — Grid System
All data screens use **MgGridBase** from AyCode.Blazor (see [AyCode.Blazor/docs/MGGRID.md](../../../Aycode/Source/AyCode.Blazor/docs/MGGRID.md) for full technical docs).
### FruitBank Grid Hierarchy
```
MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> (AyCode.Blazor)
└── FruitBankGridBase<TDataItem> (FruitBankHybrid.Shared)
├── GridShippingBase → Shipping
├── GridShippingDocumentBase → ShippingDocument (detail of Shipping)
├── GridPartnerBase → Partner
├── GridGenericAttributeBase → GenericAttributeDto
└── GridStockTakingItemBase → StockTakingItem
```
### FruitBankGridBase<TDataItem>
Project-level adapter that fixes 3 of 4 generic parameters:
```csharp
public class FruitBankGridBase<TDataItem>
: MgGridBase<SignalRDataSourceObservable<TDataItem>, TDataItem, int, LoggerClient>
```
Adds FruitBank-specific defaults (master vs detail grid settings, alternating row style, header background). For the full settings table see [`FruitBankHybrid.Shared/Components/Grids/README.md`](../FruitBankHybrid.Shared/Components/Grids/README.md).
### SignalR Tag Mapping
Each concrete grid sets CRUD tags in its constructor:
```csharp
public GridShippingBase()
{
GetAllMessageTag = SignalRTags.GetShippings; // e.g. 300
AddMessageTag = SignalRTags.AddShipping; // e.g. 302
UpdateMessageTag = SignalRTags.UpdateShipping; // e.g. 303
}
```
Tags are defined in `FruitBank.Common/SignalRs/SignalRTags.cs` with numeric ranges per domain area.
### Grid Usage Pattern (Razor)
```razor
<MgGridWithInfoPanel ShowInfoPanel="@IsMasterGrid">
<GridContent>
<GridShippingBase @ref="Grid"
DataSource="Shippings"
AutoSaveLayoutName="GridShipping"
SignalRClient="FruitBankSignalRClient"
Logger="_logger"
OnGridFocusedRowChanged="Grid_FocusedRowChanged">
<Columns>
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="Descending" ReadOnly />
<DxGridDataColumn FieldName="ShippingDate" Caption="Beérkezés" />
...
</Columns>
<DetailRowTemplate>
@{ var shipping = (Shipping)context.DataItem; }
<GridShippingDocument ParentDataItem="@shipping" ... />
</DetailRowTemplate>
</GridShippingBase>
</GridContent>
</MgGridWithInfoPanel>
```
## Key Architectural Decisions
- **nopCommerce plugin** — Customer, Order, Product are nopCommerce entities extended via GenericAttributes and DTOs
- **SignalR over REST** — all data flows through SignalR with AcBinary protocol
- **DevExpress Blazor 25.1.3** — exclusive UI component library
- **MgGridBase** — canonical grid base from AyCode.Blazor for all data screens (SignalR CRUD, layout persistence, master-detail)
- **Three measurement hierarchies** — Shipping/Order/StockTaking share same base but have different audit rules
- **Client-side database** — `DatabaseClient` caches entities in ConcurrentDictionary for offline/fast access
- **Platform-specific credential storage** — MAUI uses SecureStorage, Web uses obfuscated localStorage, Server uses no-op