- Documentation
- /
- Cmovements
- /
- Application Overview
Application Overview
What Container Movements models, and the ideas behind it
Core Chains
Vessel (+ ShippingCompany, Master) → VoyageService (POL → POD, ETL / ETD / ETA)
Container (size, owner) → ContainerHistory (dated action lifecycle) → VoyageService
ContainerHistory → Manifest tab: Container / Breakbulk / LCL - Breakbulk (by consignee + commodity)
ContainerHistory DCHF → next LODF → charge via DepotChargeRate (free days, tiered bands)
DemurragePeriod → DemurrageInvoice (+ DemurrageInvoicePeriod) → client notification
ContainerHistory → DeliveryDocket / ReleaseDocket / ReceivalsDocket
Owner → Container; Client (canonical ← possible_duplicate) ← ClientAlias
Commodity → CommodityPrimaryCategory / CommoditySubCategory / CommodityType
Key Concepts
One fleet register, owned and on-hire. A Container carries its number (mostly
valid ISO-6346, some internal asset codes), its size and TEU, and the Owner that
holds it. The operator's own house fleet owns the bulk of the boxes; the rest sit
with external lessors and lines. An owner marked not demurrage_applicable is
excluded from charging, so the house fleet's own repositioning never bills itself.
Movements are a dated lifecycle, not a status field. Every event on a box is a ContainerHistory row stamped with an action code — receive empty (RCVE), receive full (RCVF), load full (LODF), discharge full (DCHF), discharge empty (DCHE), send/transfer (SNTS/SNTR) and so on — plus an action date, a location, and, for loaded cargo, a shipper, consignee and commodity. The status is simply FCL or EMPTY; a box's current state is its latest action, denormalised onto the container so the list view shows where each one stands.
Voyages run a fixed lane. A VoyageService books a Vessel (with its shipping
company and master) on a coded sailing — V148E eastbound, V149W westbound —
between a port of loading and a port of discharge. The Port Meridian ↔ Halcyon
trunk carries most sailings; the smaller feeder ports take the rest. Load and
discharge movements attach to the voyage they sail on, which is how a voyage
opens up into its cargo.
Cargo becomes a manifest. The full containers on a voyage are grouped by manifest type — Container, Breakbulk or LCL - Breakbulk — so a voyage drills down into a cargo manifest and per-type container, breakbulk and LCL lists. Empty repositioning moves carry no manifest.
Demurrage is computed from the movement pairing, not stored as a flag. The demurrage reports pair each full discharge (DCHF) with the container's next load-out (LODF): the days held between them, less the free days set for that depot and charge type in DepotChargeRate (storage vs detention, in tiered daily bands), give the chargeable amount. A box discharged and not yet reloaded is an open, still-accruing period. Depots (Port Meridian MRD, Halcyon HAL) set 7 free storage days and 30 free detention days; charges run in the operator's currency, USD.
Charges roll up and bill. Chargeable holds become DemurragePeriod rows by client and party — consignee for storage, shipper for detention — which bundle into a DemurrageInvoice through DemurrageInvoicePeriod lines. The invoice run previews and issues PDFs; the notification run emails clients who have open charges outstanding.
Clients are de-duplicated. Real import feeds spell the same customer many
ways, so a Client can be flagged possible_duplicate and pointed at a canonical
record; deprecated variants drop out of the pick-lists, and a ClientAlias table
maps each raw import name to the resolved client.
Dockets, taxonomy and audit underneath. Delivery, release and receival dockets hang off the movements that generated them; a commodity taxonomy (primary category → subcategory → type) classifies what is being shipped; and a change log records edits across the system.