Discoveries — Paper Surplus Marketplace

Last Updated: 2026-02-27


Architecture Decisions

Django 6.0.2 (not 5.x)

Using Django 6.0.2 which was recently released. DRF 3.16.1 is compatible. All dependencies confirmed working in venv.

UUID Primary Keys Everywhere

All models inherit from TimestampedModel which uses UUID4 primary keys. This is intentional for:

23 TextChoices Enums in common/enums.py

All domain enums are centralized in common/enums.py rather than per-app. This prevents circular imports and makes the domain vocabulary discoverable in one place. Enums cover: PaperType (11 types), QualityGrade, Incoterm (7 types), OnboardingStatus, FiberType, ProductForm, FluteType, Region (7 regions), CompanyType, CreditStatus, NewsletterFrequency, SurplusSource (8 types), ContainerType, SurplusItemStatus (7 states), MatchType, MatchStatus, ContainerProposalStatus, IngestionStatus, NewsletterStatus, NewsletterTrigger, PaymentStatus, PaymentMethod, ShippingStatus, VisibilityRuleType, VisibilityScope.

Split Settings Pattern

Settings are split into config/settings/ with base.py (shared), dev.py, testing.py, prod.py. The DJANGO_SETTINGS_MODULE defaults to config.settings.dev.

9 Feature-Based Apps

Apps map to business domains:

  1. accounts — CustomUser, authentication
  2. mills — Mill entities
  3. buyers — Buyer entities, BuyerSpec
  4. surplus — SurplusItem, Product, VisibilityRule
  5. matching — MatchResult
  6. containers — ContainerProposal
  7. newsletters — Newsletter generation and delivery
  8. ingestion — Excel/email parsing, IngestionBatch, ParserConfig
  9. transactions — Transaction records, payments, shipping

Service Layer Pattern

Business logic lives in apps/<app>/services.py, not in views or models. Views call services, services orchestrate model operations. This keeps views thin and business logic testable.


Backend Integration Notes

Database

Entity Model Count

13 models across 9 apps — all implemented and migrated:

  1. CustomUser (accounts)
  2. Mill (mills)
  3. Buyer (buyers)
  4. BuyerSpec (buyers)
  5. Product (surplus)
  6. SurplusItem (surplus)
  7. VisibilityRule (surplus)
  8. MatchResult (matching)
  9. ContainerProposal (containers)
  10. Newsletter (newsletters)
  11. IngestionBatch (ingestion)
  12. ParserConfig (ingestion)
  13. Transaction (transactions)

SurplusItem State Machine

Status transitions follow strict rules:


MorichalAI Data Migration

Import Architecture

Import Results

Key Decisions


Frontend Notes

Container Visualization Architecture (2026-02-27)

Three container components at different scales:

  1. container-mini.component.ts — Card-size (ViewBox 120x52). Simplified 3D shape, no ridges/door lines. Shows up to 2 containers + overflow count. Used in browse grid cards.
  2. container-svg.component.ts — Full detail (ViewBox 400x200). 3D isometric with corrugation ridges, door lines, fill animation. Has showLegend input for grid usage. Used when a single large container visualization is needed.
  3. reel-container-widget.component.ts — Interactive calculator widget. Replaced the old static Container Fit card on product detail pages. Includes reel-based container packing logic.

All use CSS variables (--surface-sunken, --border-strong, --accent-400, --surface-overlay, --surface-raised, --text-primary, --text-secondary) for light/dark theme support.

Surplus Card CTA Pattern

Cards now include a "Request Quote" button that shows a toast notification. Uses event.preventDefault() + event.stopPropagation() to prevent the card's routerLink from firing when button is clicked.

Transaction UI Pattern

Navigation


Paper Industry Domain Notes

GSM Ranges

Container Specs

Incoterms

7 supported: EXW, FCA, FOB, CFR, CIF, DAP, DDP (subset of ICC Incoterms 2020)