# Measurement Workflows > Part of `Nop.Plugin.Misc.FruitBankPlugin`. See `README.md` for project overview. > For entity model see `docs/DOMAIN_MODEL.md`. > For SignalR endpoints see `docs/SIGNALR/README.md`. > For core measurement system rules and common domain traps, see: `../../../../../FruitBankHybridApp/FruitBank.Common/docs/GLOSSARY.md` Three parallel measurement workflows share the same weight formula and `MeasuringStatus` lifecycle. ## Shared concepts (canonical in DOMAIN_MODEL.md) These are defined once in [`DOMAIN_MODEL.md`](DOMAIN_MODEL.md) — referenced here, not duplicated: - **Weight formula** — `NetWeight = GrossWeight − PalletWeight − (TrayQuantity × TareWeight)`. See [DOMAIN_MODEL.md § Weight Formula](DOMAIN_MODEL.md#weight-formula) for field meanings and edge cases. - **MeasuringStatus lifecycle** — `NotStarted (0) → Started (10) → Finnished (20) → Audited (30)`. See [DOMAIN_MODEL.md § MeasuringStatus Lifecycle](DOMAIN_MODEL.md#measuringstatus-lifecycle) for state transitions. Note: `Finnished` is an intentional double-n typo — do not "fix" it. - **IsMeasurable Flag** — `ProductDto.IsMeasurable` master toggle for weight validation. See [DOMAIN_MODEL.md § IsMeasurable Flag](DOMAIN_MODEL.md#ismeasurable-flag) for `false`-branch semantics. ## Workflow 1: Inbound Shipping Supplier truck arrives at the warehouse. Goods are weighed and compared to the delivery document. ``` Shipping (truck) → ShippingDocument (supplier delivery note) → ShippingItem (product line) → ShippingItemPallet (individual measurement) ``` ### Flow 1. **Create Shipping** — truck registration (LicencePlate, ShippingDate, CargoCompany) 2. **Add ShippingDocument** — link to Partner (supplier), upload PDF delivery note 3. **Add ShippingItem** — product line from document. `IsMeasurable` copied from `ProductDto.IsMeasurable` 4. **Weigh pallets** — `FruitBankDataController.AddOrUpdateMeasuredShippingItemPallet()` - Each pallet: GrossWeight, PalletWeight, TareWeight, TrayQuantity → NetWeight (formula in Shared concepts above) 5. **Cascade update** — after each pallet measurement: - `ShippingItem`: MeasuredGrossWeight, MeasuredNetWeight, MeasuredQuantity recalculated from pallets - `ShippingDocument.IsAllMeasured` = all items measured - `Shipping.IsAllMeasured` = all documents measured - Product `AverageWeight` updated from measured data ### Event Cascade (FruitBankEventConsumer) ``` ShippingItemPallet deleted → ShippingItem measuring values refreshed ShippingItem inserted/updated → ShippingDocument.IsAllMeasured rechecked ShippingDocument inserted/updated → Shipping.IsAllMeasured rechecked Shipping deleted → cascade delete ShippingDocuments ShippingDocument deleted → cascade delete ShippingItems ShippingItem deleted → cascade delete ShippingItemPallets ``` ### ShippingItem: Declared vs Measured | Declared (from document) | Measured (warehouse) | Discrepancy tracked | |---|---|---| | `QuantityOnDocument` | `MeasuredQuantity` | Yes | | `GrossWeightOnDocument` | `MeasuredGrossWeight` | Yes | | `NetWeightOnDocument` | `MeasuredNetWeight` | Yes | ## Workflow 2: Outbound Order Customer order is prepared. Items are weighed before dispatch. ``` OrderDto (order) → OrderItemDto (line item) → OrderItemPallet (measurement record) ``` ### Flow 1. **Start Measuring** — `CustomOrderSignalREndpoint.StartMeasuring(orderId, userId)` - Sets `MeasurementOwnerId` via GenericAttribute - Order status set to Processing, Payment to Pending - Broadcasts `SendOrderChanged` 2. **Weigh pallets** — `CustomOrderSignalREndpoint.AddOrUpdateMeasuredOrderItemPallet()` - Same weight formula as shipping - Triggers price recalculation after each pallet - Broadcasts `SendOrderItemPalletChanged` 3. **Complete order** — `CustomOrderSignalREndpoint.SetOrderStatusToComplete(orderId, revisorId)` - Validates: all order items must have pallets - Recalculates final prices v!Ievüq |-0 .񈳂 `8à pʳB0 à800Ha@@À l!!Aa Gp c k GjJ.WBETzz2gxeFH0h)!J< ew0 *B`` p`,fI` DC\(HBp@p(dq PB.@ pjqJC @F@.!`  0paʗ`P,"!,.H0D Pl *E`($`0 .Ȝa`@`0f(( ,Ȁ00`0j 0 p(,"@@p0jJ@   *` ``3@8@p@.ш  818fJ` *ሚA` A fQ"a@ Dbp@(*  0dP @0 *Ȟ P@0jC Ap8 . @lJ!Da8B` ,ш P d p( !A,H0a À` hʙCA @A( 2HAp8 Ph#Aa@,ȏBaP( 0la"X8 A880 B0(@ P0hJ€2`@"lʻPH Ba00ȭ H a8n6A1X C!!H2ȇaPa8(pJ 8 8.@``  Ba@ pDP,E@6P8 C@0r a  P80! ` `@(tKa@ a 6!00=pC8 8A0  x 1C` (`02!P( P8x!`pH P8 2AAa  A"C`@2QɞA0@` t =p0 A0L! XHʤE, APD:!p C($A("q$4AaP@(q 00P<񈇁Bh4h,1 Bq`<>!H @(0Ă C`Kp DmپK  B4$*RńTFȦzQ̋10_XGqPeUQtN %^[V[fl;\ (F f  ,~2"߅PH3d8Gf ȴT.*`hh@6 &Al./|4Ȥx:5mF,@%n'r94d p|DymePR qJ-$Np@,SYfY,p:%KeX, $u (` 2 Jcp.n3Lox: (`R<zVܡ:rqZäen- ~>m ɇ`cCv$ i˄ #qHa0*B ph$`h  6F:DtzO'[TԁM?8 00@"ՓÑ1,ƀyh F8E`4Դhx2 AXP p`, a 4 Opd0O(AAP q2UBPK#\ DP$"h CBhP"Rx!@Y,q@<<&!PX(AdDQAA0$C1 <ӗ3e2(0ñT!dh0xB 8D`AQ $r`HNX"$I(0NBh @,LS%h8J$3X&P EAqj#ٛp8&glap A8 lS `,"ƅ\Ošp0(aqPh&Lr<" цs ]bpP8p$hDaJbDbOA`X!H SڏL("S1Ra0H,Cñ\ bTbDA80Ca@8cZ.Ep0 3HRϣE`@, pP$ZGaA8d"y2)DP ʠ0*c OA(@ b@ =F"YD (a9I$H( Z7v7ݍr cƀ00$"\~|՗@ <<+_Y. t8 T & lT"@ QFH$ 0H2ԧ X,Dt܁pHxTS``,ɦsBa΂EPE!(Lӗ CsD& HCI ((s\(L6CTTfIB4 A@`#y46Gqc8M>c t*]&( ~U#D9 rAZF0*c5a"A(Ȕ҃&p:4>tõBX3܁Ѹx*ІkƁAd&l,#ZN6ьs͛}r 2Zv[>l*|Ng˹J$p#N,8ti R5Чn(NSQr mcD@00$V` T!2̈́A@" < y=+p*hɖ dRLa̒QD V#`q ˤ` ڱ(̅ B @X$J  `P$FVQ p AXA "r8Bq8I@ $$sX$"  (Lg:fϼ|