# Lots and Quantities Language: `en` Mirror page: [lots-and-quantities.md](lots-and-quantities.md) Status: `partial migration` Last code verification: `2026-05-13` This page consolidates `BR-PT-LOT-001`, `BR-PT-LOT-002`, and `BR-PT-LOT-003`. Goal: drive quantity rules from a readable business definition, then secure them with Python guards and SQL diagnostics. ## Key Points
Operational SummaryA trade line has exactly one virtual lot. The virtual lot carries the global open balance, lot.qt carries the operational forecast, and physical lots consume that forecast.
Topic Short Rule
Entered quantity quantity_theorical is the business quantity.
Standard quantity quantity is a read-only technical counter.
Before physical lots quantity follows quantity_theorical.
After physical lots quantity reflects physical execution.
Open line Line amount uses quantity_theorical.
Finished line Line amount may switch back to physical execution.
Weight basis Purchase and sale may read two different states of the same lot.
Invoicing It chooses states from lot.qt.hist.
Controls Invariants are blocked in Python and auditable with SQL.
quantity_theorical
        |
        v
  virtual lot P1  --->  lot.qt forecast  --->  physical lot
        ^                    |
        |                    v
        +------ recalculation after consumption
## Consultant Rules ### BR-PT-LOT-001 - Virtual lot / forecast / physical life cycle
Moment Business Effect
Line creation One unique virtual lot is created.
Initialization The virtual lot takes quantity_theorical.
Forecast One open line is created in lot.qt.
Planning lot.qt may be split by sale, matching, transport, or shipment.
Physical add The physical lot consumes a precise lot.qt line.
After add lot.qt decreases and the virtual lot is recalculated.
Split of an open P1 balanceP1S1T1, P1S1T2, P1S2T3, P1S2T4
Key PointThese splits do not create several virtual lots. They only describe the forecast allocation of the open balance.
### BR-PT-LOT-002 - Contractual quantity, counter quantity, finished line
Situation Reference Quantity
User entry quantity_theorical
No physical lot quantity = quantity_theorical
Physical lots exist quantity = sum of physical lots
finished = False Amount based on quantity_theorical
finished = True Amount based on physical execution
Weight basis available Amount based on the contract wb.qt_type state
What finished Does Not Dofinished does not erase the contractual quantity, delete physical lots, or hide their PnL. It only means that the open balance may be ignored for execution calculations.
Reading of the Same Physical Lot Possible State
Purchase BL through purchase.purchase.wb.qt_type
Sale LR or Weight Report through sale.sale.wb.qt_type
Invoicing Independent choice in lot.qt.hist
### BR-PT-LOT-003 - Quantity Invariants
Invariant Formula
Conservation sum(physical lots) + virtual lot = quantity_theorical
Minimum open forecast sum(non-zero lot.qt) >= max(virtual lot, 0)
Case Rule
Purchase virtual lot Sum all lot.qt where lot_p = virtual lot, with or without lot_s.
Sale virtual lot Sum all lot.qt where lot_s = virtual lot, with or without lot_p.
lot.qt = 0 Ignored by checks; possible memory of a consumed forecast.
Forecast overconsumption Allowed after tolerance confirmation: lot.qt stops at zero, but the virtual lot absorbs the whole physical lot.
lot.qt greater than virtual lot Accepted when remaining open forecast exceeds the positive virtual lot because of physical overconsumption.
Negative virtual lot Allowed to compensate theoretical / executed gap; expected forecast = zero.
Non-zero orphan lot.qt Forbidden if neither lot_p nor lot_s is set.
### BR-PT-LOT-004 - Quantity history and weighing
Element Rule
lot.qt.hist Carries lot quantity states.
lot.lot form No direct state entry.
Update Only through Do weighing.
Virtual lot No manual packing.
Virtual packing fields lot_qt and lot_unit are not editable.
### Tolerances
Point Rule
Level Tolerance is defined on the purchase / sale header.
Inheritance Lines inherit the header tolerance by default.
Transport No independent tolerance per transport.
Physical lot addition The check is performed during Add physical lots.
Matched forecast If lot_qt carries both lot_p and lot_s, the check applies to both purchase and sale sides.
Line excess Confirmable warning in English when the projected physical quantity exceeds the current line tolerance. The message names the blocking side: purchase, sale, or both if both checks are triggered successively.
Global envelope A line excess is accepted after confirmation and consumes the contract-level envelope.
Remaining tolerance Contract lines are recalculated with inherit_tol = False.
Over-execution A line exceeding the header tolerance keeps a + tolerance at least equal to its actual excess.
Other lines Their + tolerance is reduced according to the remaining envelope.
Under-execution Mechanically restores tolerance available to other lines on the next recalculation.
Open matching Go to matching may match above the strict open balance if the projected quantity remains within Qt max.
Line gauge On a line with physical lots, the gauge uses the sum of physical lots; without physical lots, it uses the sum of linked lot.qt.
Header gauge The purchase/sale gauge is the weighted average of line gauges, weighted by quantity_theorical.
Matching gauge In Go to matching, the gauge projects already matched + Qt to match against quantity_theorical, with -tol_min / tol_max bounds.
Line gauge layout On purchase.line / sale.line forms, place the gauge and targeted_qt directly in the main grid, without a colspan="4" subgroup, and use xalign="0" to avoid a double right shift.
## Developer Section ### Key Fields ### Line / Virtual Lot Creation ### Updating `quantity_theorical`
target_quantity = quantity_theorical - sum(converted physical lots)
free_quantity = target_quantity - sum(already matched or shipped lot.qt)
### Adding Physical Lots ### Removing Physical Lots ### Weighing / Quantity States ### Quantity Counter `quantity` ### Line Amount ### Python Guards ### SQL Diagnostic ## Nearby Tests