# shipping-calculator

Shipping, freight and landed-cost calculator for e-commerce, logistics and fulfillment. dimWeight computes dimensional (volumetric) weight from length x width x height / divisor and returns the...


**Shipping / freight / landed-cost microservice** for e-commerce, logistics and fulfillment. Pure,
deterministic math — no external carrier API. Compute dimensional weight, look up zone/weight-break
rates, roll up full landed cost (duty + tax), map distance to a zone, compare carrier quotes and drive
free-shipping upsell messaging.

Every tool runs fully **offline**. The one analytical tool (`compareCarriers`) also wires an optional
LLM path that adds a plain-English recommendation and silently falls back — that result carries
`{ mode: 'heuristic' | 'llm' }`.

## Tools

| Tool | Input | What it does |
|---|---|---|
| `dimWeight` | `l`, `w`, `h`, `divisor?`, `weight?` | Volumetric weight = l·w·h / divisor; returns chargeable = max(actual, dim). Unit-aware (cm→5000, in→139). |
| `rate` | `zone`, `weight`, `table` | Looks up price from a zone × weight-break rate table with per-kg overflow beyond the top break. |
| `landedCost` | `item`, `ship`, `dutyPct`, `taxPct` | Sums item + shipping + duty + tax into total landed cost with a full breakdown. |
| `zoneFromDistance` | `distance` | Maps a shipping distance (km/mi) to a zone band 1–8. |
| `compareCarriers` | `carriers` | Ranks quotes by price + delivery days; returns cheapest, fastest, best value + recommendation. |
| `freeShippingThreshold` | `cartTotal`, `threshold` | How much more to unlock free shipping, progress % and incentive copy. |

## Usage

```js
import pack from './index.js';

pack.adapters.dimWeight({ l: 40, w: 30, h: 20, weight: 3, options: { unit: 'cm' } });
// → chargeableWeight = max(3, 24000/5000 = 4.8) = 4.8, billedBy: 'dimensional'

pack.adapters.rate({
  zone: 3, weight: 2.5,
  table: [{ maxWeight: 1, rates: { 3: 8 } }, { maxWeight: 5, rates: { 3: 14 } }],
});

pack.adapters.landedCost({ item: 100, ship: 20, dutyPct: 5, taxPct: 8 });

await pack.adapters.compareCarriers({ carriers: [{ name: 'UPS', price: 14, days: 3 }, { name: 'USPS', price: 9, days: 6 }] });
```

Each tool takes ONE args object (maps 1:1 to an HTTP POST body). Invalid input throws `TypeError`;
missing zone rates throw a 404-tagged error.

## Options

`options`: `unit` (cm/in for `dimWeight`; km/mi for `zoneFromDistance`), `currency`, `precision`,
`dutyOnShipping` (charge duty on item+ship), `taxBase` (`landed` vs `item`), `narrate` (LLM path for
`compareCarriers`).

## DRY boundaries

- General currency/percent math lives in `numbers` / `finance` / `tax`. This pack owns the **shipping
  domain model** (dim weight, zone rate tables, landed cost, carrier compare). The duty/tax percentage
  math is reused inline to keep the pack self-contained.
- No cross-pack imports except `../_shared/llm.js`.


---
Source: shared/engines/adapters/domain/shipping-calculator/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/shipping-calculator
