Skip to main content

Dimensional weight calculator and box selector for shipping

Project description

dimcalc

A Python library for calculating dimensional (volumetric) weight and selecting optimal shipping boxes.

Features

  • Calculate dimensional weight using configurable DIM factors
  • Select optimal shipping boxes from a list of available sizes
  • Distribute chargeable weight proportionally across products
  • Built with Pydantic for data validation
  • Type hints throughout for IDE support

Installation

pip install dimcalc

Quick Start

Basic Dimensional Weight Calculation

from dimcalc import DimCalc, Dimensions

# Create a calculator with your carrier's DIM factor
calc = DimCalc(dimensional_factor=5.0)  # 5.0 for cm³ to grams

# Define product dimensions (in centimeters)
dims = Dimensions(length=30, width=20, height=10)

# Calculate chargeable weight
result = calc.calculate_chargeable_weight(
    actual_weight=500,  # grams
    dimensions=dims,
    quantity=2
)

print(f"Actual weight: {result.actual_weight}g")
print(f"Dimensional weight: {result.dimensional_weight}g")
print(f"Chargeable weight: {result.chargeable_weight}g")
print(f"Using dimensional: {result.is_dimensional_used}")

Box Selection

from dimcalc import BoxSelector, Box, Product, Dimensions

# Define your available box sizes
boxes = [
    Box(id="small", length=20, width=15, height=10, name="Small"),
    Box(id="medium", length=30, width=25, height=15, name="Medium"),
    Box(id="large", length=40, width=30, height=20, name="Large"),
]

# Create a selector with 20% volume buffer for packing inefficiency
selector = BoxSelector(boxes=boxes, volume_buffer_percentage=20.0)

# Define products to ship
products = [
    Product(
        weight=500,  # grams per unit
        quantity=2,
        dimensions=Dimensions(length=15, width=10, height=8)
    ),
    Product(
        weight=300,
        quantity=1,
        dimensions=Dimensions(length=10, width=10, height=5)
    ),
]

# Select optimal box
result = selector.select_box(products)

print(f"Selected box: {result.box.name}")
print(f"Chargeable weight: {result.weight.chargeable_weight}g")
print(f"Box utilization: {result.utilization_percentage:.1f}%")

Weight Distribution

When using box-based calculation, distribute the chargeable weight back to individual products:

from dimcalc import WeightDistributor

# After box selection...
distributed = WeightDistributor.distribute(products, result)

for i, dist in enumerate(distributed):
    print(f"Product {i+1}: {dist.distributed_weight}g per unit")

API Reference

Models

Dimensions

Represents physical dimensions in centimeters.

dims = Dimensions(length=30, width=20, height=10)
dims.volume        # 6000.0 (cm³)
dims.max_dimension # 30.0

Box

Represents a shipping box.

box = Box(
    id="box_1",           # Unique identifier
    length=30,            # cm
    width=20,             # cm
    height=10,            # cm
    name="Medium Box"     # Optional display name
)
box.volume         # 6000.0 (cm³)
box.max_dimension  # 30.0
box.dimensions     # Returns Dimensions object

Product

Represents a product for weight/box calculation.

product = Product(
    weight=500,                    # grams per unit
    quantity=2,                    # number of units (default: 1)
    dimensions=Dimensions(...)     # optional dimensions
)
product.total_weight  # 1000 (weight × quantity)
product.total_volume  # volume × quantity (or None if no dimensions)

WeightResult

Result of a dimensional weight calculation.

result.actual_weight       # Total actual weight in grams
result.dimensional_weight  # Calculated dimensional weight
result.chargeable_weight   # max(actual, dimensional)
result.is_dimensional_used # True if dimensional > actual
result.weight_difference   # chargeable - actual

BoxSelectionResult

Result of box selection with weight calculation.

result.box                    # Selected Box
result.weight                 # WeightResult
result.total_products_volume  # Sum of product volumes
result.utilization_percentage # (products_volume / box_volume) × 100
result.to_dict()              # Convert to dictionary for JSON

Classes

DimCalc

Core dimensional weight calculator.

calc = DimCalc(dimensional_factor=5.0)

# Calculate dimensional weight only
dim_weight = calc.calculate_dimensional_weight(dimensions, quantity=1)

# Calculate chargeable weight (max of actual and dimensional)
result = calc.calculate_chargeable_weight(
    actual_weight=500,
    dimensions=dims,
    quantity=1
)

# Calculate for multiple products
result = calc.calculate_for_products(products)

BoxSelector

Selects optimal shipping box for products.

selector = BoxSelector(
    boxes=boxes,                      # List of available Box objects
    volume_buffer_percentage=20.0,    # Extra space for packing (default: 20%)
    calculator=DimCalc()              # Optional custom calculator
)

result = selector.select_box(products)  # Returns BoxSelectionResult or None
can_fit = selector.can_fit(products)    # Returns bool

WeightDistributor

Distributes chargeable weight across products.

# Proportional distribution (based on actual weight)
distributed = WeightDistributor.distribute(products, box_result)

# Even distribution (equal per unit)
distributed = WeightDistributor.distribute_evenly(products, total_weight)

Dimensional Factors

The dimensional factor (DIM factor) converts volume to weight. Common values:

Carrier Factor Unit Conversion
Iran Post 5.0 cm³ → grams
DHL 5000.0 cm³ → kg

Formula: dimensional_weight = volume / dimensional_factor

Presets

The library includes example presets you can use as reference:

from dimcalc.presets import IRAN_POST_BOXES, DIMENSIONAL_FACTORS, get_iran_post_selector

# Example box configurations
print(IRAN_POST_BOXES)  # List of 8 standard Iran Post boxes

# Common DIM factors
print(DIMENSIONAL_FACTORS)  # {"iran_post": 5.0, "dhl": 5000.0, ...}

# Pre-configured selector for Iran Post
selector = get_iran_post_selector()

Note: Box sizes vary by region and carrier. Create your own box list based on your specific requirements:

# Define your own boxes
MY_BOXES = [
    Box(id="xs", length=15, width=10, height=10, name="Extra Small"),
    Box(id="s", length=20, width=15, height=10, name="Small"),
    Box(id="m", length=30, width=20, height=15, name="Medium"),
    Box(id="l", length=40, width=30, height=20, name="Large"),
]

selector = BoxSelector(boxes=MY_BOXES)

JSON Serialization

Results can be easily serialized for API responses:

result = selector.select_box(products)
data = result.to_dict()

# Returns:
{
    "box_id": "medium",
    "box_name": "Medium Box",
    "box_dimensions": {
        "length_cm": 30,
        "width_cm": 20,
        "height_cm": 15,
        "volume_cm3": 9000
    },
    "weight": {
        "actual_weight_g": 1300,
        "dimensional_weight_g": 1800,
        "chargeable_weight_g": 1800,
        "is_dimensional_used": True
    },
    "packing_info": {
        "total_products_volume_cm3": 2900,
        "utilization_percentage": 32.22
    }
}

Pydantic models also support .model_dump() for serialization:

dims = Dimensions(length=30, width=20, height=10)
dims.model_dump()  # {"length": 30, "width": 20, "height": 10, "volume": 6000, "max_dimension": 30}

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dimcalc-1.0.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dimcalc-1.0.0-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file dimcalc-1.0.0.tar.gz.

File metadata

  • Download URL: dimcalc-1.0.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for dimcalc-1.0.0.tar.gz
Algorithm Hash digest
SHA256 98b23afa611186208811c46180f0fe55f336333757ff198a7273d9578a5fa584
MD5 b482bdf4feae1d3731c862614f858912
BLAKE2b-256 5c30adad28737c533ab76ffc681e693ae69cc25d0b5539a739888508862ecc4b

See more details on using hashes here.

File details

Details for the file dimcalc-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: dimcalc-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for dimcalc-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3b510478ba23e05aea5c3a8d78a7647b3d43787ebe316b454f4c50447af3c04b
MD5 4c3cef8f7613f4fa99915e93b98433c0
BLAKE2b-256 02e7facd17859fc2a7302dee6c30d841d007bb952c7811cd73b6a774a5285e84

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page