models:
- name: PackageType
collection: package_types
description: "A package type (box / tote archetype): dimensions, weight and barcode — the capacity join key for storage categories (guards R10 barcode unique, R16 non-negative dimensions/weight)"
fields:
id:
type: uuid
attributes: ["@id", "@default(uuid)"]
description: "Unique package-type identifier"
name:
type: string
attributes: ["@required", "@max(150)"]
description: "Type label (e.g. 'Tote M')"
barcode:
type: string?
attributes: ["@max(64)"]
description: "Scan barcode (unique — guard R10, _barcode_uniq)"
package_use:
type: PackageUse
attributes: ["@default(disposable)"]
description: "disposable / reusable"
sequence:
type: integer
attributes: ["@default(0)"]
description: "Ordering"
length:
type: decimal?
attributes: ["@precision(12,4)"]
description: "Outer length (≥ 0 — guard R16)"
width:
type: decimal?
attributes: ["@precision(12,4)"]
description: "Outer width (≥ 0 — guard R16)"
height:
type: decimal?
attributes: ["@precision(12,4)"]
description: "Outer height (≥ 0 — guard R16)"
max_weight:
type: decimal?
attributes: ["@precision(18,4)"]
description: "Maximum loadable weight (≥ 0 — guard R16)"
active:
type: bool
attributes: ["@default(true)"]
description: "Archive support"
metadata:
type: Metadata
attributes: ["@audit_metadata"]
description: "Audit metadata"
indexes:
- type: unique
fields: [barcode]
where: "deleted_at IS NULL AND barcode IS NOT NULL"
description: "R10 — one package type per barcode (_barcode_uniq)"
- name: StorageCategory
collection: storage_categories
description: "A storage category — the capacity frame locations hang on their storage_category_id (max_weight ≥ 0 — guard R17; allow_new_product band)"
fields:
id:
type: uuid
attributes: ["@id", "@default(uuid)"]
description: "Unique storage-category identifier"
name:
type: string
attributes: ["@required", "@max(150)"]
description: "Category label (e.g. 'Pallet rack L')"
max_weight:
type: decimal?
attributes: ["@precision(18,4)"]
description: "Maximum weight the frame holds (≥ 0 — guard R17)"
allow_new_product:
type: StorageAllowNewProduct
attributes: ["@default(mixed)"]
description: "Mixed-goods policy: mixed / empty / same"
active:
type: bool
attributes: ["@default(true)"]
description: "Archive support"
metadata:
type: Metadata
attributes: ["@audit_metadata"]
description: "Audit metadata"
indexes:
- name: StorageCategoryCapacity
collection: storage_category_capacities
description: "A storage-category capacity row — item OR package type × category (mutually exclusive targets), quantity > 0 (guards R8 unique per item, R9 unique per package type, R15 positive quantity)"
fields:
id:
type: uuid
attributes: ["@id", "@default(uuid)"]
description: "Unique capacity-row identifier"
storage_category_id:
type: uuid
attributes: ["@required", "@foreign_key(StorageCategory.id)"]
description: "Parent category"
item_id:
type: uuid?
attributes: ["@exclude_from_foreign_key_check"]
description: "Item this capacity row is for — mutually exclusive with package_type_id # logical FK to catalog.Item.id"
package_type_id:
type: uuid?
attributes: ["@foreign_key(PackageType.id)"]
description: "Package type this capacity row is for — mutually exclusive with item_id"
quantity:
type: decimal
attributes: ["@required", "@default(1)", "@precision(18,4)"]
description: "Capacity quantity (> 0 — guard R15, _positive_quantity)"
metadata:
type: Metadata
attributes: ["@audit_metadata"]
description: "Audit metadata"
indexes:
- type: unique
fields: [item_id, storage_category_id]
where: "deleted_at IS NULL AND item_id IS NOT NULL"
description: "R8 — one capacity rule per item per category (_unique_product)"
- type: unique
fields: [package_type_id, storage_category_id]
where: "deleted_at IS NULL AND package_type_id IS NOT NULL"
description: "R9 — one capacity rule per package type per category (_unique_package_type)"
- type: index
fields: [storage_category_id]
- name: PutawayRule
collection: putaway_rules
description: "A putaway rule — where to store an item / category / package type arriving at a source location; storage_category_id is a stored derived copy of the destination location's category (trigger T12)"
fields:
id:
type: uuid
attributes: ["@id", "@default(uuid)"]
description: "Unique putaway-rule identifier"
sequence:
type: integer
attributes: ["@default(0)"]
description: "Ordering (the match walk is sequence-leading)"
location_in_id:
type: uuid
attributes: ["@required", "@foreign_key(Location.id)"]
description: "The location stock arrives at"
location_out_id:
type: uuid
attributes: ["@required", "@foreign_key(Location.id)"]
description: "The destination (putaway) location — whose storage category T12 derives from"
item_id:
type: uuid?
attributes: ["@exclude_from_foreign_key_check"]
description: "Optional — the rule applies to one item # logical FK to catalog.Item.id"
category_id:
type: uuid?
attributes: ["@exclude_from_foreign_key_check"]
description: "Optional — the rule applies to an item category # logical FK to catalog.ItemCategory.id"
package_type_id:
type: uuid?
attributes: ["@foreign_key(PackageType.id)"]
description: "Optional — the rule applies to a package type"
storage_category_id:
type: uuid?
attributes: ["@foreign_key(StorageCategory.id)"]
description: "STORED derived copy of location_out_id.storage_category_id (trigger T12) — re-derived on every destination write, never a free column"
sublocation:
type: PutawaySublocation
attributes: ["@default(no)"]
description: "Strategy for choosing a sublocation of the destination: no / last_used / closest_location"
active:
type: bool
attributes: ["@default(true)"]
description: "Archive support"
metadata:
type: Metadata
attributes: ["@audit_metadata"]
description: "Audit metadata"
indexes:
- type: index
fields: [location_in_id]
- type: index
fields: [location_out_id]
- type: index
fields: [storage_category_id]
enums:
- name: PackageUse
description: "stock.package.type.package_use"
variants:
- name: disposable
description: "Disposable box"
default: true
- name: reusable
description: "Reusable box (totes)"
- name: StorageAllowNewProduct
description: "stock.storage.category.allow_new_product"
variants:
- name: mixed
description: "Allow mixed items"
default: true
- name: empty
description: "Only when the location is empty"
- name: same
description: "Only when all stored items are the same"
- name: PutawaySublocation
description: "stock.putaway.rule.sublocation — how a sublocation of the destination is chosen"
variants:
- name: no
description: "Use the destination as-is"
default: true
- name: last_used
description: "The sublocation this item was last stored in"
- name: closest_location
description: "The nearest free sublocation"