213 lines
10 KiB
Markdown
213 lines
10 KiB
Markdown
# SignalR Endpoints and External Integrations
|
|
|
|
> Part of `Nop.Plugin.Misc.FruitBankPlugin`. See `README.md` for project overview.
|
|
> For measurement workflows see `docs/MEASUREMENT.md`.
|
|
> For data layer see `docs/DATA_LAYER.md`.
|
|
|
|
The plugin communicates with FruitBankHybridApp (MAUI + Blazor WASM hybrid clients) via SignalR. Methods decorated with `[SignalR]` attributes auto-broadcast results to connected clients.
|
|
|
|
## SignalR Configuration
|
|
|
|
Configured in `PluginNopStartup`:
|
|
|
|
| Setting | Value |
|
|
|---|---|
|
|
| KeepAliveInterval | `FruitBankConstClient.SignalRKeepAliveIntervalSecond` = 60 s |
|
|
| ClientTimeoutInterval | `FruitBankConstClient.SignarlRTimeoutIntervalSecond` = 180 s |
|
|
| MaximumReceiveMessageSize | 30 MB |
|
|
| EnableDetailedErrors | true |
|
|
| StatefulReconnectBufferSize | 30 MB |
|
|
| **Hub protocols** | **`json` (default) + `acbinary`** — a kliens a handshake-ben választ |
|
|
|
|
**Wire protocol:** `AcBinaryHubProtocol` (`AyCode.Services.SignalRs`) — custom binary `IHubProtocol` using `AcBinarySerializer`. Eliminates JSON+Base64 overhead. Protocol name: `"acbinary"`. Registered via `.AddSignalR(...).AddAcBinaryProtocol(opts => { ProtocolMode=Bytes; FlushPolicy=Coalesced; Logger=new Logger(nameof(AyCodeBinaryHubProtocol)); })` — a default **JSON MELLÉ** kerül (nem cseréli); a `#if DEBUG` startup-dump (`>>> HubProtocol: …`) kiírja a ténylegesen regisztrált protokollokat.
|
|
|
|
Hubs registered (mindkettő WebSockets-only endpoint):
|
|
- `DevAdminSignalRHub` (`/fbHub`) — fő adat-hub, acbinary protokollon.
|
|
- `LoggerSignalRHub` (`/loggerHub`, `FruitBank.Common.Server`; base: `AcLoggerSignalRHub<TLogger, TLogItem>` az `AyCode.Services.Server`-ből) — kliens-log feltöltés fogadása, wire-típus: `LogItemClient` (2026-07 óta acbinary protokollon; korábban JSON). Kapcsolat-életciklust logol (`Logger client connected/disconnected`), így a halott feltöltő-csatorna a konzolból látszik.
|
|
|
|
## FruitBankHub
|
|
|
|
`Services/FruitBankHub.cs` — Minimal hub inheriting `Hub`.
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `SendMessage(string user, string message)` | Broadcast message to all connected clients |
|
|
|
|
## CustomOrderSignalREndpoint
|
|
|
|
`Areas/Admin/Controllers/CustomOrderSignalREndpoint.cs` — Order management via SignalR. Implements `ICustomOrderSignalREndpointServer`.
|
|
|
|
### Query Methods
|
|
|
|
| Method | Parameters | Returns | Broadcast Tag |
|
|
|---|---|---|---|
|
|
| `GetAllOrderDtos()` | — | Orders from last 15 days with relations | — |
|
|
| `GetOrderDtoById` | orderId | Single order with relations | — |
|
|
| `GetPendingOrderDtos()` | — | Pending status orders | — |
|
|
| `GetPendingOrderDtosForMeasuring` | lastDaysCount | Orders for measurement (unpaid, not cancelled, with DateOfReceipt) | — |
|
|
| `GetAllOrderDtoByIds` | orderIds[] | Batch retrieval | — |
|
|
| `GetAllOrderDtoByProductId` | productId | Orders containing product | — |
|
|
|
|
### Mutation Methods
|
|
|
|
| Method | Parameters | Broadcast Tag | Key Logic |
|
|
|---|---|---|---|
|
|
| `StartMeasuring` | orderId, userId | `SendOrderChanged` | Sets MeasurementOwnerId, OrderStatus=Processing, PaymentStatus=Pending |
|
|
| `SetOrderStatusToComplete` | orderId, revisorId | `SendOrderChanged` | Validates pallets, recalculates prices, updates stock, publishes OrderPaidEvent |
|
|
| `AddOrUpdateMeasuredOrderItemPallet` | OrderItemPallet | `SendOrderItemPalletChanged` | Saves pallet, triggers price recalculation |
|
|
|
|
### Order Item & Pallet Queries
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetOrderItemDtosByOrderId` | Items for a specific order |
|
|
| `GetOrderItemPalletsByOrderItemId` | Pallets for a specific item |
|
|
| `GetOrderItemPalletById` | Single pallet |
|
|
|
|
## StockSignalREndpointServer
|
|
|
|
`Areas/Admin/Controllers/StockSignalREndpointServer.cs` — Inventory management via SignalR.
|
|
|
|
| Method | Parameters | Key Logic |
|
|
|---|---|---|
|
|
| `GetStockTakings` | loadRelations | All stock taking sessions |
|
|
| `AddStockTaking` | StockTaking | Creates session, auto-populates items from products + pending order items |
|
|
| `CloseStockTaking` | stockTakingId | Validates all measured, applies stock corrections, marks closed |
|
|
| `UpdateStockTaking` | StockTaking | Updates session |
|
|
| `RefreshStockTakingItem` | stockTakingItemId | Refreshes measured values from pallets |
|
|
| `GetStockTakingItems` | loadRelations | All items |
|
|
| `GetStockTakingItemsByStockTakingId` | stockTakingId | Filtered items |
|
|
| `AddOrUpdateMeasuredStockTakingItemPallet` | StockTakingItemPallet | Saves pallet, refreshes item values |
|
|
|
|
## FruitBankDataController
|
|
|
|
`Controllers/FruitBankDataController.cs` — Main data API implementing `IFruitBankDataControllerServer`. Methods decorated with `[SignalR]` attributes for FruitBankHybridApp integration.
|
|
|
|
### Shipping Operations
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetShippings()` | Last 15 days with relations |
|
|
| `GetNotMeasuredShippings()` | Incomplete shipments |
|
|
| `GetShippingById` / `AddShipping` / `UpdateShipping` | CRUD |
|
|
| `GetShippingItems` / `AddShippingItem` / `UpdateShippingItem` | Item CRUD |
|
|
| `GetShippingItemPallets` / `AddShippingItemPallet` / `UpdateShippingItemPallet` | Pallet CRUD |
|
|
| `AddOrUpdateMeasuredShippingItemPallet` | Measurement + average weight update + cascade |
|
|
| `GetShippingDocuments` / `AddShippingDocument` | Document operations, updates product costs on add |
|
|
| `ProcessAndSaveFullShippingJson` | Parses FullProcessModel JSON, saves complete shipping data |
|
|
|
|
### Partner & Depot Operations
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetPartners()` | All partners, depots included (`LoadWith(PartnerDepots)` — partners are client-cached, enables client-side depot cascading) |
|
|
| `GetPartnerById` / `AddPartner` / `UpdatePartner` | CRUD |
|
|
| `GetPartnerDepots()` / `GetPartnerDepotById` / `GetPartnerDepotsByPartnerId` | Depot queries |
|
|
| `AddPartnerDepot` / `UpdatePartnerDepot` | Depot CRUD |
|
|
|
|
### Cargo Operations
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetCargoPartners()` / `GetCargoPartnerById` | Cargo partner queries |
|
|
| `AddCargoPartner` / `UpdateCargoPartner` | Cargo partner CRUD |
|
|
| `GetCargoTrucks()` / `GetCargoTruckById` / `GetCargoTrucksByCargoPartnerId` | Truck queries |
|
|
| `AddCargoTruck` / `UpdateCargoTruck` | Truck CRUD |
|
|
|
|
### EKÁER Operations
|
|
|
|
Domain logic, mapping and validation rules: `docs/EKAER/README.md`.
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetEkaerHistories(filter)` / `GetEkaerHistoryCount(filter)` | `EkaerHistoryFilter`-based queries |
|
|
| `GetEkaerHistoryById` / `GetEkaerHistoriesByForeignKey` | Lookups |
|
|
| `AddEkaerHistory` / `UpdateEkaerHistory` | CRUD |
|
|
| `CreateEkaerHistory(foreignKey, isOutgoing)` | Creates history for a source record; idempotent — an existing mapping (same source, same direction) returns the existing history |
|
|
| `CreateMissingEkaerHistories(fromDate)` | Batch backfill, returns `EkaerCreateResult` (created histories + deduplicated validation messages) |
|
|
| `GenerateEkaerXmlDocument(ekaerHistoryId)` | NAV XML generation; throws if the history does not exist |
|
|
|
|
### Product & Attribute Operations
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetProductDtos()` | All products with GenericAttributes |
|
|
| `GetProductDtoById` | Single product |
|
|
| `GetGenericAttributeDtosByEntityIdAndKeyGroup` | Custom attributes by entity + key group |
|
|
| `AddGenericAttributeDto` / `UpdateGenericAttributeDto` | Attribute CRUD |
|
|
|
|
### Grid Layout Roaming
|
|
|
|
Server-side storage for MgGrid user layouts (client behaviour: AyCode.Blazor `docs/MGGRID/MGGRID_LAYOUT.md` — Server Roaming). Tags are framework-level (`AcSignalRTags`), not FruitBank-specific. Storage: GenericAttribute rows — `KeyGroup="GridLayout"`, `Key`=composite layout key (already contains the userId), `EntityId`=userId, `StoreId=0`.
|
|
|
|
| Method | Tag | Purpose |
|
|
|---|---|---|
|
|
| `GetGridLayout(key, userId)` | `GetGridLayoutTag` (90010) | Returns layout JSON, `null` if none saved |
|
|
| `SaveGridLayout(key, layoutJson, userId)` | `SaveGridLayoutTag` (90011) | Upsert |
|
|
| `DeleteGridLayout(key, userId)` | `DeleteGridLayoutTag` (90012) | Returns `false` if no stored layout |
|
|
|
|
### User & Auth Operations
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetMeasuringUsers()` | Users in "Measuring" role |
|
|
| `GetCustomerRolesByCustomerId` | Customer roles |
|
|
| `LoginMeasuringUser` | Authentication with role check |
|
|
|
|
### Environment
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `IsProdEnvironment()` | `true` if the server runs against the PROD database. Definite by construction (ambiguous DB catalog fails server startup); consumers must fail closed on any error |
|
|
|
|
### Stock History
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetStockQuantityHistoryDtos()` | Last 15 days |
|
|
| `GetStockQuantityHistoryDtosByProductId` | Product-filtered history |
|
|
|
|
## InnVoice Integration (Billingo)
|
|
|
|
### InnVoiceOrderService
|
|
|
|
`Services/InnVoiceOrderService.cs` — Order synchronization with Billingo/InnVoice accounting system via XML API.
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `CreateOrdersAsync(List<OrderCreateRequest>)` | Batch order creation |
|
|
| `CreateOrderAsync(OrderCreateRequest)` | Single order creation |
|
|
| `GetOrdersByUpdateTimeAsync(DateTime)` | Query by last update time |
|
|
| `GetOrdersByDateAsync(DateTime)` | Query by order date |
|
|
| `GetOrderByTechIdAsync(int)` | Query by InnVoice tech ID |
|
|
| `GetOrderByTableIdAsync(int)` | Query by table ID |
|
|
|
|
**Models:** `OrderCreateRequest`, `OrderCreateResponse`, `InnVoiceOrder`, `InnVoiceOrderLineItem`
|
|
|
|
### InnvoiceApiService
|
|
|
|
`Services/InnvoiceApiService.cs` — Invoice CRUD with Billingo XML API.
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetInvoiceByIdAsync` / `GetInvoiceByNumberAsync` / `GetInvoiceByTechIdAsync` | Invoice queries |
|
|
| `GetInvoicesByDateRangeAsync` | Date-range filtered invoices |
|
|
| `CreateInvoiceAsync` / `UpdateInvoiceAsync` | Invoice CRUD |
|
|
|
|
**Models:** `Invoice`, `InvoiceLineItem`, `InvoiceCreateRequest`, `InvoiceCreateResponse`
|
|
|
|
Both services build and parse XML payloads. Called from `InnVoiceOrderController` and `InnVoiceOrderSyncController`.
|
|
|
|
## FruitBankAttributeService
|
|
|
|
`Services/FruitBankAttributeService.cs` — GenericAttribute CRUD helper for measurement-related attributes.
|
|
|
|
| Method | Purpose |
|
|
|---|---|
|
|
| `GetGenericAttributeValueAsync<TEntity, TPropType>` | Type-safe attribute retrieval |
|
|
| `GetMeasuringAttributeValuesAsync<TEntity>` | Get IsMeasurable, NetWeight, Tare, etc. as batch |
|
|
| `InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>` | Upsert measurement attributes |
|
|
| `IsMeasurableEntityAsync<TEntity>` | Check if entity's product is measurable |
|
|
|
|
Supports cumulative weight updates (adds to existing value rather than replacing).
|