# FruitBank.Common Domain Rules & Glossary > This file acts as the single source of truth for the core Measurement System and Common Traps shared across all FruitBank applications (Hybrid App, Blazor, and nopCommerce server plugin). ## Measurement System | Term | Definition | |---|---| | **IsMeasurable** | Product-level flag. If `false`: weights = 0.0, only `TrayQuantity` matters. A Pallet record is still created. | | **NetWeight** | `GrossWeight − PalletWeight − (TrayQuantity × TareWeight)` — universal formula across all three hierarchies. | | **TrayQuantity** | Always recorded, regardless of measurability. Count of trays/crates. | | **GrossWeight** | Total weight including pallet and packaging. 0.0 if not measurable. | | **PalletWeight** | Weight of the physical pallet. 0.0 if goods arrive without one. | | **TareWeight** | Weight of a single tray/crate. Used in NetWeight calculation. | | **AverageWeight** | Per-pallet average: `NetWeight / TrayQuantity`. Validated against threshold. | | **MeasuringStatus** | NotStarted(0) → Started(10) → **Finnished**(20) → Audited(30). Note: "Finnished" is intentional. | | **RevisorId** | Quality auditor's Customer ID. OrderItemPallet becomes "Audited" when RevisorId > 0. | ## Three Measurement Hierarchies All share `MeasuringItemPalletBase` with the same NetWeight formula: | Flow | Parent | Pallet Record | Extra | |--------------|-----------------|-------------------------|---------------------------------------| | **Inbound** | ShippingItem | ShippingItemPallet | Declared vs measured discrepancy | | **Outbound** | OrderItemDto | OrderItemPallet | RevisorId for audit | | **Inventory**| StockTakingItem | StockTakingItemPallet | QuantityDiff for stock adjustment | ## Common Traps | Trap | Correct Behavior | |---|---| | "Pallet" = physical pallet | ❌ It's a measurement record. Always created. | | Shipping = outgoing | ❌ Shipping = INBOUND. Order = OUTBOUND. | | Fix "Finnished" spelling | ❌ Intentional legacy typo. Do NOT fix. | | IsMeasurable=false means no Pallet | ❌ Pallet is always created, weights just = 0.0 | | NetWeight is stored/settable | ❌ It is calculated. The setter throws an Exception! It only exists to satisfy the `IMeasuringItemPalletBase` interface boundary. Set `GrossWeight`, `PalletWeight`, `TareWeight` instead. | | Setting MeasuringStatus | ❌ It's a calculated property (evaluates `IsMeasured`, `Id`, or child pallets). Do not try to set it. | | Setting ForeignKey | ❌ `ForeignKey` is read-only. Use `SetForeignKey(id)` method instead. | | GenericAttribute is simple | ❌ It's polymorphic: KeyGroup determines which entity type owns the record |