backbone-inventory 0.17.2

Inventory: stock ledger of record (SLE) + moving-average valuation; emits COGS/asset AccountingPost (Delivery/Receipt -> GL)
Documentation
# =============================================================================
# Domain: Inventory
# Entities: Lot (Odoo `stock.lot`), Package (Odoo `stock.package`)
# =============================================================================
# Tracking aggregates. Lot is the lot/serial registry, unique per
# (name, item, org unit) — guard R5. Package is the physical container:
# nested via parent_package_id + materialized parent_path, org-scoped via
# the acting unit (guard R27 — a write-time
# derivation, not a free column).
#
# Naming fidelity (Odoo master): the lot model is `stock.lot` (not
# production.lot) and the package is `stock.package` (not quant.package).
#
# Tenancy: none, by design (ADR-0029). The module is tenant-agnostic; the
# composing service's decorator owns org scoping. Shared lots/packages
# anchor at the tenant ROOT under allow_root; a lot or package anchored at a
# regular unit stays that unit's private row.
# =============================================================================

models:
  # ===========================================================================
  # Entity: Lot — a lot / serial number per item
  # ===========================================================================
  - name: Lot
    collection: lots
    description: "A lot / serial number for an item (unique per name x item x org unit — guard R5)"

    fields:
      id:
        type: uuid
        attributes: ["@id", "@default(uuid)"]
        description: "Unique lot identifier"

      name:
        type: string
        attributes: ["@required", "@max(150)"]
        description: "Lot / serial identifier (unique per item x org unit — guard R5)"

      reference:
        type: string?
        attributes: ["@max(150)"]
        description: "External reference (stock.lot's `ref` field, renamed — `ref` is a reserved Rust keyword and the generator emits broken identifiers for it)"

      item_id:
        type: uuid
        attributes: ["@required", "@exclude_from_foreign_key_check"]
        description: "The item # logical FK to catalog.Item.id (the spec's product.product)"


      product_qty:
        type: decimal
        attributes: ["@default(0)", "@precision(18,4)"]
        description: "Quantity on hand across quants tracking this lot (stored compute over quants — trigger T10)"

      location_id:
        type: uuid?
        attributes: ["@foreign_key(Location.id)"]
        description: "Current dominant location of this lot (stored compute over its quants — trigger T10; editable inverse resets the quant's location)"

      note:
        type: string?
        attributes: ["@max(2000)"]
        description: "Free-form notes"

      metadata:
        type: Metadata
        attributes: ["@audit_metadata"]
        description: "Audit metadata"

    indexes:
      - type: index
        fields: [item_id]

  # ===========================================================================
  # Entity: Package — a physical container (nestable)
  # ===========================================================================
  - name: Package
    collection: packages
    description: "A physical package containing quants; supports nesting (parent_package_id + parent_path); org unit derived from the location chain (guard R27)"

    fields:
      id:
        type: uuid
        attributes: ["@id", "@default(uuid)"]
        description: "Unique package identifier"

      name:
        type: string
        attributes: ["@required", "@max(150)"]
        description: "Package identifier (often the SSCC)"

      complete_name:
        type: string
        attributes: ["@max(1000)"]
        description: "Full nested path including parent packages (recursive stored compute — trigger T7)"

      location_id:
        type: uuid?
        attributes: ["@foreign_key(Location.id)"]
        description: "Current location (recursive stored compute; editable inverse moves the contained quants)"


      parent_package_id:
        type: uuid?
        attributes: ["@foreign_key(Package.id)"]
        description: "Parent package (self-referential nesting); null = top-level"

      parent_path:
        type: string
        attributes: ["@max(1000)"]
        description: "Materialized path of the package tree — load-bearing for subtree walks"

      pack_date:
        type: date?
        description: "Date the package was packed"

      package_type_id:
        type: uuid?
        attributes: ["@foreign_key(PackageType.id)"]
        description: "The package's archetype (box / tote) — the join key a storage category's package-type capacity rows (R9) match on"

      metadata:
        type: Metadata
        attributes: ["@audit_metadata"]
        description: "Audit metadata"

    indexes:
      - type: index
        fields: [parent_path]
        description: "Package-tree hierarchy walks (parent_store pattern)"
      - type: index
        fields: [parent_package_id]
      - type: index
        fields: [package_type_id]
        description: "Package-type joins (the R9 capacity match key)"
      - type: index
        fields: [location_id]