Files
pokemon-inventory/docs/DATA-MODEL.md
T
fragginwagon c728016dec feat: establish auth listing and image vertical slices
Includes MFA-capable authentication, session and CSRF security, password recovery, listing lifecycle and ownership rules, inventory image metadata, local ImageStorage, migrations, tests, and implementation status documentation. Verification: npm test (62 passing) and integration suite (14 passing).
2026-09-08 17:32:03 -04:00

4.1 KiB

Data Model

Core relationship

User → Seller → Product → Inventory Item → Listing
                                  │
                                  ├── Images
                                  ├── Acquisition
                                  ├── Pricing Observations
                                  ├── Market Valuations
                                  └── Activity

Sale → Sale Items → Inventory Items

Product

Represents what the item is, independent of physical ownership.

Examples:

  • Charizard ex — SV151 — #199/165
  • Pokémon Center Worlds 2025 Pikachu Plush

Products persist after all inventory is sold.

Inventory Item

Represents one physical copy.

Each copy has its own:

  • condition
  • images
  • acquisition
  • asking price/listing
  • market valuation
  • notes
  • status

Do not model multiple physical copies as a quantity field on one Inventory Item.

Listing

Represents how an Inventory Item is currently offered publicly.

A Product can have many physical Inventory Items with different conditions and asking prices.

Sale

A manual external transaction. One Sale can contain multiple Sale Items.

Provider Product Mapping

Provider mappings are Product-level relationships.

Recommended fields:

  • id
  • product_id
  • provider_id
  • mapping_type (PRODUCT or SEARCH)
  • external_identifier
  • search_query / search parameters
  • source_url
  • status
  • metadata
  • created_at
  • updated_at
  • disabled_at

A provider can support one or both mapping types.

eBay supports both:

  • specific product/catalog mappings where appropriate
  • search/query mappings where no canonical product is appropriate

Mappings can be replaced without destroying historical records.

Only one active/default mapping per provider should be used for normal pricing unless a provider integration explicitly supports multiple active sources.

Suggested pricing tables

pricing_providers

id, name, code, is_enabled, priority, configuration, created_at, updated_at

product_pricing_providers

product_id, provider_id, is_enabled

pricing_provider_mappings

As described above.

pricing_observations

id, product_id, inventory_item_id, provider_id, source_identifier, source_url, condition_id, price_minor, currency, observed_at, quality_score, is_outlier, outlier_reason, raw_reference

market_valuations

id, inventory_item_id, value_minor, currency, strategy, confidence, source_count, calculated_at

market_value_overrides

id, inventory_item_id, value_minor, currency, reason, created_by, created_at, removed_at

pricing_jobs

id, job_type, status, requested_by, started_at, completed_at, total_items, processed_items, successful_items, failed_items, error_summary, created_at

Conditions

condition_profiles:

  • id
  • category_id
  • name
  • active
  • sort

conditions:

  • id
  • condition_profile_id
  • name
  • code
  • quality_rank
  • description
  • active
  • sort

Images

inventory_images:

  • id
  • inventory_item_id
  • storage_key
  • original_filename
  • mime_type
  • file_size
  • width
  • height
  • alt_text
  • sort_order
  • is_primary
  • processing_status
  • created_at
  • updated_at

Acquisitions

acquisitions:

  • id
  • inventory_item_id
  • method
  • cost_minor
  • currency
  • date
  • source
  • location
  • shipping_minor
  • tax_minor
  • other_fees_minor
  • estimated_trade_value_minor
  • notes
  • created_at
  • updated_at

Sales

sales:

  • id
  • seller_id
  • sale_date
  • sale_location
  • sold_price_minor
  • currency
  • platform_fees_minor
  • payment_processing_fees_minor
  • shipping_cost_minor
  • taxes_minor
  • other_fees_minor
  • buyer_name
  • buyer_contact
  • notes
  • created_by
  • created_at
  • updated_at

sale_items:

  • id
  • sale_id
  • inventory_item_id
  • sold_price_minor
  • cost_basis_minor

Activity

Activity records retain:

  • affected Product/Inventory Item
  • event
  • previous value where applicable
  • new value
  • actor
  • timestamp

Security events are stored separately.

Money

Store money as integer minor units. Negative values are prohibited; zero is valid. USD is canonical for stored/calculated market values unless a documented external representation requires another currency.