- type
- summary
- created
- Tue Apr 07 2026 02:00:00 GMT+0200 (Central European Summer Time)
- updated
- Tue Apr 07 2026 02:00:00 GMT+0200 (Central European Summer Time)
- sources
- raw/articles/DISCOVERIES
- tags
- architecture decisions patterns domain discoveries
Discoveries Summary
Overview
This file serves as an architectural decision record (ADR) and knowledge base. It covers five areas: architecture decisions, backend integration notes, MorichalAI data migration details, frontend implementation patterns, and paper industry domain knowledge.
Architecture Decisions
Django 6.0.2
The project uses Django 6.0.2 (recently released at the time) with DRF 3.16.1. All dependencies confirmed compatible in the virtual environment.
UUID Primary Keys Everywhere
All models inherit from TimestampedModel using UUID4 primary keys. Rationale:
- Prevents sequential ID enumeration attacks
- Enables easier data merging for future multi-tenancy
- Better suited for distributed systems
23 Centralized Enums
All domain enums live in common/enums.py rather than per-app files. This prevents circular imports and makes the domain vocabulary discoverable in one place. Covers: 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 split into config/settings/ with base.py (shared), dev.py, testing.py, prod.py. Default: config.settings.dev.
9 Feature-Based Apps
Apps map to business domains:
accounts-- CustomUser, authenticationmills-- Mill entitiesbuyers-- Buyer entities, BuyerSpecsurplus-- SurplusItem, Product, VisibilityRulematching-- MatchResultcontainers-- ContainerProposalnewsletters-- Newsletter generation and deliveryingestion-- Excel/email parsing, IngestionBatch, ParserConfigtransactions-- 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 independently testable.
Backend Integration Notes
Database
- PostgreSQL on localhost, DB:
marketplace, User:marketplace - uuid-ossp extension enabled
- Redis DB 1 reserved for caching/Celery
morichal_sourceDB contains legacy MorichalAI data (read-only)
13 Entity Models
CustomUser, Mill, Buyer, BuyerSpec, Product, SurplusItem, VisibilityRule, MatchResult, ContainerProposal, Newsletter, IngestionBatch, ParserConfig, Transaction.
SurplusItem State Machine
Strict status transitions: pre_production -> available; available -> exclusive, expired, withdrawn; exclusive -> sold, available (on expiry/decline). Invalid transitions raise errors.
MorichalAI Migration
- Service at
backend/common/services/morichal_import/with 11 modules - Uses psycopg 3.3.3 (not psycopg2) for direct source DB access
- Management command:
python manage.py import_morichal - Supports --dry-run, --phases (selective), --clear-existing, --report-file
- Results: 111 mills, 162 buyers, 486 products, 170 buyer specs, 12 freight rates, 773 transactions (1,714 total)
- All records tagged with
[Imported from MorichalAI ...]in notes field - Idempotent via get_or_create
Frontend Notes
Three Container Visualization Scales
- container-mini -- Card-size (ViewBox 120x52), simplified 3D, up to 2 containers + overflow count
- container-svg -- Full detail (ViewBox 400x200), 3D isometric with corrugation ridges, fill animation, configurable legend
- reel-container-widget -- Interactive calculator replacing static Container Fit card on product detail pages
All use CSS variables for light/dark theme support.
Surplus Card CTA Pattern
"Request Quote" button uses event.preventDefault() + event.stopPropagation() to prevent the card's routerLink from firing.
Transaction UI Pattern
Status timeline component, conditional action buttons based on status + role, Angular Material dialogs for confirmations.
Navigation
Role-based routing (admin sees all, mills see surplus/transactions, buyers see matching/transactions), lazy-loaded feature modules, JWT in localStorage with interceptor.
Paper Industry Domain Knowledge
- GSM ranges: 13-500 (industry standard), typical surplus 60-350
- Container specs: 20ft (~21,770 kg), 40ft (~26,780 kg), 40ft HC (~26,480 kg)
- Incoterms supported: EXW, FCA, FOB, CFR, CIF, DAP, DDP (ICC Incoterms 2020 subset)
- Container assembly uses greedy bin-packing algorithm
Sources
- raw/articles/DISCOVERIES -- full discovery document with all architecture decisions and domain notes
Related
- wiki/concepts/four-layer-architecture -- the system architecture these decisions support
- wiki/entities/morichal-ai -- the legacy data source
- wiki/concepts/database-credentials-and-roles -- PostgreSQL details referenced here
- wiki/summaries/frontend-spec-summary -- the spec that drove frontend implementation
- wiki/summaries/status-summary -- current deployment using these patterns