Skip to content

Pick Container Documentation

Overview

The Pick Container module (pick.container) provides a simple junction table that links stock pickings with containers. This model facilitates container tracking during picking operations, enabling efficient warehouse management and shipment preparation.


Model Information

Model Name: pick.container
Display Name: Pick Container
Key Fields: N/A

Features

  • ❌ Audit logging enabled
  • ❌ Multi-company support
  • ❌ Complex business logic
  • ✅ Simple junction/relationship table

Key Fields Reference

Relationship Fields

Field Type Required Description
picking_id Many2One Stock picking reference (stock.picking), deleted on cascade
container_id Many2One Container reference (stock.container), deleted on cascade

Understanding Cascade Deletion

Both fields use on_delete="cascade", which means: - When a picking is deleted, all associated pick_container records are automatically deleted - When a container is deleted, all associated pick_container records are automatically deleted - This maintains referential integrity in the database


API Methods

1. Create Pick Container Association

Method: create(vals, context)

Links a container to a picking operation.

Parameters:

vals = {
    "picking_id": 123,                    # Stock picking ID
    "container_id": 456                   # Container ID
}

Returns: int - New record ID

Example:

# Associate container with picking
pc_id = get_model("pick.container").create({
    "picking_id": picking_id,
    "container_id": container_id
})


2. Bulk Create Container Associations

Method: create(vals, context) with multiple calls

Creates multiple container associations for a single picking.

Example:

# Associate multiple containers with one picking
container_ids = [101, 102, 103]

for cont_id in container_ids:
    get_model("pick.container").create({
        "picking_id": picking_id,
        "container_id": cont_id
    })


Search Functions

Search by Picking

# Find all containers associated with a picking
condition = [["picking_id", "=", picking_id]]
pc_records = get_model("pick.container").search(condition)

# Get container IDs
container_ids = [
    get_model("pick.container").browse(pc_id).container_id.id 
    for pc_id in pc_records
]

Search by Container

# Find all pickings that used a specific container
condition = [["container_id", "=", container_id]]
pc_records = get_model("pick.container").search(condition)

# Get picking IDs
picking_ids = [
    get_model("pick.container").browse(pc_id).picking_id.id 
    for pc_id in pc_records
]

Model Relationship Description
stock.picking Many2One Warehouse picking operations
stock.container Many2One Physical containers used in warehouse

Common Use Cases

Use Case 1: Associate Container with Picking

# When preparing a shipment, link containers to picking

# 1. Create or get picking
pick_id = get_model("stock.picking").create({
    "type": "out",
    # ... other fields
})

# 2. Create or get container
cont_id = get_model("stock.container").create({
    "number": "CONT-2025-001",
    # ... other fields
})

# 3. Link container to picking
get_model("pick.container").create({
    "picking_id": pick_id,
    "container_id": cont_id
})

Use Case 2: Track Multiple Containers per Picking

# When a large order requires multiple containers

pick_id = 123

# Add multiple containers
containers = ["CONT-A", "CONT-B", "CONT-C"]

for cont_no in containers:
    # Find or create container
    res = get_model("stock.container").search([["number", "=", cont_no]])
    if res:
        cont_id = res[0]
    else:
        cont_id = get_model("stock.container").create({"number": cont_no})

    # Link to picking
    get_model("pick.container").create({
        "picking_id": pick_id,
        "container_id": cont_id
    })

Use Case 3: Get All Containers for a Picking

# Retrieve all containers used in a picking

def get_picking_containers(picking_id):
    """Returns list of container objects for a picking"""
    pc_ids = get_model("pick.container").search([
        ["picking_id", "=", picking_id]
    ])

    containers = []
    for pc_id in pc_ids:
        pc = get_model("pick.container").browse(pc_id)
        containers.append(pc.container_id)

    return containers

# Usage
containers = get_picking_containers(123)
for cont in containers:
    print(f"Container: {cont.number}")

Use Case 4: Get Picking History for a Container

# Track which pickings have used a specific container

def get_container_history(container_id):
    """Returns list of pickings that used this container"""
    pc_ids = get_model("pick.container").search([
        ["container_id", "=", container_id]
    ])

    pickings = []
    for pc_id in pc_ids:
        pc = get_model("pick.container").browse(pc_id)
        pickings.append(pc.picking_id)

    return pickings

# Usage
pickings = get_container_history(456)
for pick in pickings:
    print(f"Picking: {pick.number}, Date: {pick.date}")

Best Practices

1. Check Existing Associations

# Good: Check before creating duplicate associations
existing = get_model("pick.container").search([
    ["picking_id", "=", picking_id],
    ["container_id", "=", container_id]
])

if not existing:
    get_model("pick.container").create({
        "picking_id": picking_id,
        "container_id": container_id
    })

# Bad: Create without checking
get_model("pick.container").create({  # ❌ May create duplicates
    "picking_id": picking_id,
    "container_id": container_id
})

2. Batch Operations

# Efficient: Batch create operations
container_ids = [101, 102, 103, 104]

# Create all associations at once
for cont_id in container_ids:
    get_model("pick.container").create({
        "picking_id": picking_id,
        "container_id": cont_id
    })

# Then fetch picking to refresh relationships
pick = get_model("stock.picking").browse(picking_id)

3. Clean Up Orphaned Records

# The cascade deletion handles this automatically, but be aware:

# When deleting a picking:
get_model("stock.picking").delete([picking_id])
# All pick.container records automatically deleted

# When deleting a container:
get_model("stock.container").delete([container_id])
# All pick.container records automatically deleted

Database Constraints

Cascade Deletion

-- Foreign key constraints with cascade
ALTER TABLE pick_container 
    ADD CONSTRAINT fk_picking 
    FOREIGN KEY (picking_id) 
    REFERENCES stock_picking(id) 
    ON DELETE CASCADE;

ALTER TABLE pick_container 
    ADD CONSTRAINT fk_container 
    FOREIGN KEY (container_id) 
    REFERENCES stock_container(id) 
    ON DELETE CASCADE;

This ensures referential integrity - orphaned records cannot exist.


Performance Tips

1. Index Queries

  • Both picking_id and container_id are implicitly indexed as foreign keys
  • Queries on either field are efficient

2. Bulk Retrieval

# Efficient: Single query with browse_multi
pc_ids = get_model("pick.container").search([["picking_id", "=", picking_id]])
pc_records = get_model("pick.container").browse(pc_ids)

# Access all containers in one batch
containers = [pc.container_id for pc in pc_records]

3. Count Operations

# Fast: Count without retrieving full records
count = get_model("pick.container").search_count([
    ["picking_id", "=", picking_id]
])
print(f"Picking has {count} containers")

Integration Points

Internal Modules

  • Stock Picking: Main warehouse operation module
  • Stock Container: Container management system

Typical Workflow

Stock Picking Created
Items Picked & Packed
Containers Assigned ← pick.container links created here
Shipment Prepared
Picking Completed

Troubleshooting

"Foreign key violation"

Cause: Trying to create pick.container with non-existent picking_id or container_id
Solution: Verify both picking and container exist before creating association

"Duplicate records"

Cause: Creating multiple pick.container records with same picking_id and container_id
Solution: Check for existing associations before creating new ones (see Best Practices)


Testing Examples

Unit Test: Basic Association

def test_pick_container_association():
    # Create picking
    pick_id = get_model("stock.picking").create({
        "type": "out"
    })

    # Create container
    cont_id = get_model("stock.container").create({
        "number": "TEST-CONT-001"
    })

    # Create association
    pc_id = get_model("pick.container").create({
        "picking_id": pick_id,
        "container_id": cont_id
    })

    # Verify
    pc = get_model("pick.container").browse(pc_id)
    assert pc.picking_id.id == pick_id
    assert pc.container_id.id == cont_id

Unit Test: Cascade Deletion

def test_cascade_deletion():
    # Create picking and container association
    pick_id = get_model("stock.picking").create({"type": "out"})
    cont_id = get_model("stock.container").create({"number": "TEST"})

    pc_id = get_model("pick.container").create({
        "picking_id": pick_id,
        "container_id": cont_id
    })

    # Delete picking
    get_model("stock.picking").delete([pick_id])

    # Verify pick.container also deleted
    result = get_model("pick.container").search([["id", "=", pc_id]])
    assert len(result) == 0, "pick.container should be cascade deleted"

Version History

Last Updated: 2025-10-27
Model Version: pick_container.py
Framework: Netforce


Additional Resources

  • Stock Picking Documentation: stock.picking
  • Stock Container Documentation: stock.container

This documentation is generated for developer onboarding and reference purposes.