Aller au contenu

Fees

Language: en Mirror page: fees.md Status: partial migration

See also the historical technical page: ../fees.md.

Operational summaryA fee carries an amount, but its quantity must remain aligned with the lots it applies to. Per packing is the only exception: it follows packing units, not lot weight.
Marker Topic Short rule
Quantity fee.quantity Sum of linked lots in fee.lots.
State empty fee.qt_state Uses the contract weight basis.
State filled fee.qt_state Uses that state, capped by the weight basis.
Fallback state missing on lot Uses the closest previous state by sequence.
Net / gross fee.weight_type net reads quantity, brut reads gross_quantity.
Packing ppack Packing quantity, decoupled from weight.
Control Python + SQL Application guard and SQL diagnostic.

Consultant Rules

BR-PT-FEE-001 - Freight value from shipment fee

Source: BR-PT-003

Consultant Rule

The freight value printed on invoice documents comes from the maritime freight fee on the shipment, not from a direct invoice field.

Developer Notes

  • Find the physical lot from the invoice.
  • Find its shipment_in.
  • Search the fee.fee with product.name = 'Maritime freight'.
  • Use fee.get_amount().

BR-PT-FEE-002 - Effective lots for fees

Source: BR-PT-021

Consultant Rule

A fee follows the virtual lot until a physical lot is linked. As soon as a physical lot is linked, physical lots become the calculation basis for the fee.

Developer Notes

  • Do not remove the virtual lot link: it remains the fallback.
  • Effective lots are:
    • physical lots if at least one physical lot is linked;
    • otherwise virtual lots.
  • The same selection applies to fee PnL.
  • Synchronization points:
    • fee creation;
    • fee.lots link;
    • quantity_theorical change;
    • weighing;
    • physical lot removal.

BR-PT-FEE-003 - Fee quantity

Consultant Rule

The quantity of a fee follows the quantity life cycle of its linked lots. It must represent the sum of those lots in the authorized contractual quantity state.

Short Rule

fee.quantity = sum(applicable quantity of effective fee.lots)

Quantity State Selection

Case Target state
empty fee.qt_state weight basis of the fee carrier contract
filled fee.qt_state fee.qt_state, unless later than the weight basis
fee.qt_state later than weight basis weight basis
target state missing on lot closest previous state by lot.qt.type.sequence
no target state available current lot weight, only when no weight basis applies

Weight Basis Source

Fee weight basis
Purchase fee fee.line.purchase.wb.qt_type
Sale fee fee.sale_line.sale.wb.qt_type
Shipment fee purchase weight basis of the lot when present
Shipment fee without purchase sale weight basis of the lot when present

Net / Gross

  • If fee.weight_type = net:
    • read lot.qt.hist.quantity.
  • If fee.weight_type = brut:
    • read lot.qt.hist.gross_quantity.

Per Packing

  • mode = ppack is excluded from the weight rule.
  • fee.quantity represents a packing quantity.
  • This quantity may be decoupled from net or gross weight.

Lump Sum

  • mode = lumpsum also follows the quantity rule.
  • The amount remains fixed.
  • The quantity gives a more accurate per-ton price.

BR-PT-FEE-004 - % rate fees from financing delta

Source: historical BR-PT-016 and 2026-04-30 notes

Consultant Rule

Percentage financial fees are calculated with the financing delta from the BL date estimated line, not with the current date.

Developer Notes

  • Formula: amount = unit_price * quantity * (price / 100) * fin_int_delta / 360.
  • Delta source: Estimated date line with trigger = bldate.
  • If no bldate line exists, do not calculate a % rate amount.

Developer Section

Key Fields

  • Fee: fee.fee
  • Fee lots: fee.lots
  • Fee quantity: fee.fee.quantity
  • Mode: fee.fee.mode
  • Optional quantity state: fee.fee.qt_state
  • Net / gross: fee.fee.weight_type
  • Lot quantity state: lot.qt.hist.quantity_type
  • Net quantity: lot.qt.hist.quantity
  • Gross quantity: lot.qt.hist.gross_quantity
  • State order: lot.qt.type.sequence
  • Purchase / sale weight basis: purchase.weight.basis.qt_type

Calculation Functions

  • Fee._get_effective_fee_lots():
    • selects physical lots, then virtual lots.
  • Fee._target_qt_type_for_lot():
    • chooses fee.qt_state or the weight basis;
    • caps the state at the weight basis.
  • Fee._select_lot_qt_type():
    • takes the exact state when it exists;
    • otherwise takes the closest previous state by sequence.
  • Fee._get_lot_fee_quantity():
    • reads net or gross depending on weight_type.
  • Fee.sync_quantity_from_lots():
    • resynchronizes fee.quantity.

Python Guards

  • Central check:
    • fee.fee.assert_quantity_consistency()
    • fee.fee.assert_quantities_consistency()
  • Trigger points:
    • fee creation;
    • fee modification;
    • fee.lots creation / modification / deletion;
    • weighing through linked fee resynchronization.
  • Exception:
    • mode = ppack is not controlled as weight.

Known Gap

  • Lot split / merge:
    • the workflow may clone or create physical lots;
    • rewiring fee.lots to the new lots is not guaranteed yet;
    • affected fees must therefore be checked with the SQL diagnostic after this workflow is used.

SQL Diagnostic

  • Script:
  • Usage:
    • audit test databases;
    • audit historical data;
    • qualify data before correction.
  • The script returns non-ppack fees where fee.quantity does not match the sum of effective lots according to the applicable quantity state.