Skip to content

Product Dimensions (Window Blinds)

Core module for window blinds pricing based on dimensions (Width x Height).

Module Overview

Field Value
Technical Name bi_product_dimension
Version 15.0.1.0.0
Category Sales
Dependencies sale, purchase, stock, mrp

Overview

This module implements custom pricing logic for window blinds products based on dimensions (Width x Height in mm), with automatic calculation of m2 area and premium add-on costs. It's the core business logic module for the JDX window blinds workflow.

Pricing Calculation

Calculation Modes

Company-level setting in Settings → General Settings → Price Calculation:

Mode Description
dimension Price based on m2 (Width × Height / 1,000,000)
qty Standard quantity-based pricing

Price Formula

For dimension-based pricing:
  net_price = m2 × price_unit × quantity

Where:
  m2 = MAX(actual_m2, minimum_size) if is_minimum=True
  actual_m2 = width × height / 1,000,000

Minimum Size Pricing

Products can specify a minimum chargeable area:

Product Field Description
is_minimum Enable minimum size pricing
minimum_size Minimum m2 to charge (e.g., 0.5m2)

If the actual calculated m2 is less than minimum_size, the minimum is used for pricing.

Sale Order Line Fields

Dimension Fields

Field Type Description
width Float Width in mm
height Float Height in mm
m2 Computed Calculated area (width × height / 1,000,000)
actual_m2 Computed Actual area before minimum applied
net_price Computed m2 × price_unit × qty

Installation Options

Field Type Description
item_location_id Many2one Installation location (e.g., "Living Room", "Bedroom")
mount Selection In / Out mount

Control Options (motorized field)

Value Description
L / R Left/Right cord
Motorized Electric motor control
One Cord Single cord operation
One Cord Top Down Single cord with top-down
SC Top Down Side cord top-down
Simplicity Simplicity system
Simplicity Top Down Simplicity with top-down
One Touch One touch operation
Smart Semi Auto Smart semi-automatic
Semi Auto Top Down Semi-auto with top-down
Cordless Combi Cordless combination
Cordless Roll Cordless roller
A/S After Service

Hardware Options

Field Type Description
supply_color_id Many2one Hardware color
remote Selection YES / NO
smart_hub Selection YES / NO
high_top Selection Premium headrail options
valance Selection Valance style
fablic_on_head Selection Fabric on top (YES_20 / NO)
fablic_on_bt Selection Fabric on bottom (YES_20 / NO)
string Selection Control system type

Premium Add-on Pricing

When order is confirmed, additional costs are automatically calculated and added as separate line items:

Option Value Additional Cost
High Top YES +$100/unit
High Top YES w/ Extension +$150/unit
Valance Compact +$25/unit
Fabric Top YES +$20/unit
Fabric Bottom YES +$20/unit
Steel String - +$25/unit
Copper String - +$35/unit
Cordless System - +$35/unit
Simplicity System - +$15/unit
Smart System - +$55/unit

How It Works

flowchart LR
    A[Confirm Order] --> B{Check Options}
    B --> C[High Top?]
    B --> D[Valance?]
    B --> E[Fabric?]
    B --> F[String Type?]
    C --> G[Add Cost Line]
    D --> G
    E --> G
    F --> G
    G --> H[Updated Order Total]

Order Sequence Configuration

Configurable Prefixes

Company-level settings for order number prefixes:

Setting Default Description
Sale Order Prefix SO Prefix for sale orders (e.g., AH, LV)
Sale Order Next Number 1 Next sequence number
Purchase Order Prefix PO Prefix for purchase orders
Purchase Order Next Number 1 Next sequence number
Invoice Prefix INV Prefix for invoices
Invoice Next Number 1 Next sequence number

Configuration

  1. Go to Settings → General Settings → Order Number Sequences
  2. Enter desired prefix (e.g., "AH" for Austin)
  3. Set starting number (e.g., 1001)
  4. Click Save first
  5. Click Apply Sequences

Purchase Order Behavior

1 SO = 1 PO Logic

Each Sale Order creates its own separate Purchase Order, even for the same vendor. This is enforced by including the SO origin in the PO search domain.

# stock_rule.py
def _make_po_get_domain(self, company_id, values, partner):
    domain = super()._make_po_get_domain(company_id, values, partner)
    if values.get('group_id') and values['group_id'].name:
        domain += (('origin', '=', values['group_id'].name),)
    return domain

PO Line Split

By default, quantities > 1 are split into separate PO lines (qty=1 each) for individual tracking. Categories can be excluded from this behavior:

Settings → General Settings → Exclude Categories from PO Split

Dimension Fields Flow

Dimension fields flow through the entire order lifecycle:

flowchart TD
    A[Sale Order Line] --> B[Stock Move]
    A --> C[Purchase Order Line]
    A --> D[Manufacturing Order]
    B --> E[Delivery Report]
    C --> F[PO Report]
    D --> G[MO Production]
Model Dimension Fields
sale.order.line width, height, m2, all options
stock.move width, height, location, color, options
purchase.order.line width, height, location, color, options
mrp.production width, height, location, color, options

Master Data

Item Locations

Create locations for installation tracking:

Sales → Configuration → Item Locations

Examples: Living Room, Bedroom, Kitchen, Office, Bathroom

Supply Colors

Create hardware colors:

Sales → Configuration → Supply Colors

Examples: White, Brown, Black, Champagne, Bronze

Company Settings

Setting Location Description
Price Calculation General Settings Dimension or Quantity
PO Split Exclusions General Settings Categories to exclude from split
Order Prefixes General Settings SO/PO/INV prefixes

Installation

# Install module
docker compose exec odoo odoo -i bi_product_dimension --stop-after-init -d DATABASE_NAME

# Upgrade module
docker compose exec odoo odoo -u bi_product_dimension --stop-after-init -d DATABASE_NAME

Module Structure

bi_product_dimension/
├── __manifest__.py
├── __init__.py
├── models/
│   ├── __init__.py
│   ├── sale_order.py         # Sale order line dimensions
│   ├── purchase_order.py     # PO line dimensions
│   ├── stock_move.py         # Stock move dimensions
│   ├── stock_rule.py         # PO creation logic
│   ├── res_company.py        # Company settings
│   └── res_setting_config.py # Settings UI
├── views/
│   ├── sale_order_view.xml
│   ├── purchase_order_view.xml
│   ├── stock_move_view.xml
│   ├── setting_config_view.xml
│   └── mo_extended.xml       # MO views
├── data/
│   └── product_data.xml      # Default products
└── security/
    └── ir.model.access.csv

Troubleshooting

Price Not Calculating

  1. Verify company price_calculation is set to dimension
  2. Check product has valid price_unit
  3. Verify width and height are entered in mm (not cm or m)

Add-on Costs Not Added

  1. Check additional cost product exists (Settings → Products)
  2. Verify option selections on SO lines
  3. Upgrade module if recently updated

Sequence Prefix Not Applied

  1. Click Save before Apply Sequences
  2. Verify ir.sequence records exist for sale.order, purchase.order
  3. Check company_id matches current company

PO Lines Merging

  1. Verify _make_po_get_domain override is active
  2. Upgrade module: -u bi_product_dimension
  3. Check origin field is populated on procurements

Prerequisites

MTO Route Required

For the SO → PO workflow to function, products must have the Replenish on Order (MTO) route enabled. See MTO Configuration for setup instructions.