Product Measurement System
This document describes the comprehensive measurement system implemented for products in BaldrTs.
Overview
The measurement system replaces the simple weight field with a structured measurements object that includes:
- Weight with unit specification
- Dimensions (length, width, height) with unit specification
- Volume with unit specification
Structure
Weight
{
value: number,
unit: "g" | "kg" | "mg"
}
Dimensions
{
length: { value: number, unit: LengthUnit },
width: { value: number, unit: LengthUnit },
height: { value: number, unit: LengthUnit }
}
// LengthUnit: "mm" | "cm" | "m"
Volume
{
value: number,
unit: "ml" | "cl" | "l"
}
Usage Examples
Creating a Product with Measurements
import Product from "./models/product.model";
// Example 1: Small item (jewelry)
const ring = await Product.create({
module_id: moduleId,
title: "Gold Ring",
slug: "gold-ring-18k",
active: true,
translation: { /* ... */ },
availability: { /* ... */ },
measurements: {
weight: {
value: 5.2,
unit: "g"
},
dimensions: {
length: { value: 20, unit: "mm" },
width: { value: 18, unit: "mm" },
height: { value: 5, unit: "mm" }
}
}
});
// Example 2: Packaged product (wine)
const wine = await Product.create({
module_id: moduleId,
title: "Champagne Brut 2018",
slug: "champagne-brut-2018",
active: true,
translation: { /* ... */ },
availability: { /* ... */ },
measurements: {
weight: {
value: 1.5,
unit: "kg"
},
dimensions: {
length: { value: 8, unit: "cm" },
width: { value: 8, unit: "cm" },
height: { value: 30, unit: "cm" }
},
volume: {
value: 750,
unit: "ml"
}
}
});
// Example 3: Large item (furniture)
const table = await Product.create({
module_id: moduleId,
title: "Dining Table",
slug: "dining-table-oak",
active: true,
translation: { /* ... */ },
availability: { /* ... */ },
measurements: {
weight: {
value: 45,
unit: "kg"
},
dimensions: {
length: { value: 180, unit: "cm" },
width: { value: 90, unit: "cm" },
height: { value: 75, unit: "cm" }
}
}
});
Using Conversion Utilities
import {
convertWeight,
convertDimensions,
convertVolume,
calculateVolumeFromDimensions,
formatWeight,
formatDimensions,
formatVolume
} from "./utils/measurement.utils";
// Convert weight from kg to g
const weightInKg = { value: 1.5, unit: "kg" };
const weightInG = convertWeight(weightInKg, "g");
// Result: { value: 1500, unit: "g" }
// Convert dimensions from cm to mm
const dimensionsInCm = {
length: { value: 30, unit: "cm" },
width: { value: 20, unit: "cm" },
height: { value: 10, unit: "cm" }
};
const dimensionsInMm = convertDimensions(dimensionsInCm, "mm");
// Result: { length: { value: 300, unit: "mm" }, ... }
// Calculate volume from dimensions
const volume = calculateVolumeFromDimensions(dimensionsInCm);
// Result: { value: 6000, unit: "ml" } (30*20*10 = 6000 cm³ = 6000 ml)
// Format for display
const displayWeight = formatWeight(weightInKg);
// Result: "1.5 kg"
const displayDimensions = formatDimensions(dimensionsInCm);
// Result: "30 × 20 × 10 cm"
const displayVolume = formatVolume({ value: 750, unit: "ml" });
// Result: "750 ml"
Using Validation
import { productMeasurementsSchema } from "./validations/measurement.validation";
// Validate measurements before saving
const measurementData = {
weight: {
value: 1.5,
unit: "kg"
},
dimensions: {
length: { value: 30, unit: "cm" },
width: { value: 20, unit: "cm" },
height: { value: 10, unit: "cm" }
}
};
try {
const validatedMeasurements = productMeasurementsSchema.parse(measurementData);
// Data is valid, proceed with saving
} catch (error) {
// Handle validation errors
console.error("Invalid measurement data:", error);
}
Shipping Calculations
The measurement system is designed to integrate with shipping providers:
// Calculate shipping costs based on weight and dimensions
function calculateShipping(product) {
const { weight, dimensions } = product.measurements;
// Convert to standard units for shipping calculation
const weightInKg = convertWeight(weight, "kg");
const dimsInCm = convertDimensions(dimensions, "cm");
// Calculate volumetric weight (for air shipping)
const volumetricWeight =
(dimsInCm.length.value * dimsInCm.width.value * dimsInCm.height.value) / 5000;
// Use the greater of actual weight or volumetric weight
const chargeableWeight = Math.max(weightInKg.value, volumetricWeight);
return calculateShippingCost(chargeableWeight);
}
Migration from Old Weight Field
If you have existing products with the old weight field, here's a migration script:
// Migration script
async function migrateProductWeights() {
const products = await Product.find({ weight: { $exists: true } });
for (const product of products) {
if (product.weight && !product.measurements) {
product.measurements = {
weight: {
value: product.weight,
unit: "kg" // Assuming old weight was in kg
}
};
// Remove old weight field
product.weight = undefined;
await product.save();
}
}
console.log(`Migrated ${products.length} products`);
}
Benefits
- Metric System: All measurements use French/European metric units
- Accurate Shipping: Calculate shipping costs based on actual dimensions
- Consistent Standards: Standardized measurements across the platform
- Warehouse Integration: Better inventory management with precise dimensions
- Type Safety: Full TypeScript support with type checking
- Validation: Built-in validation with Zod schemas
API Response Examples
{
"_id": "507f1f77bcf86cd799439011",
"title": "Gold Ring",
"measurements": {
"weight": {
"value": 5.2,
"unit": "g"
},
"dimensions": {
"length": { "value": 20, "unit": "mm" },
"width": { "value": 18, "unit": "mm" },
"height": { "value": 5, "unit": "mm" }
}
}
}