Shipping Port Documentation¶
Overview¶
The Shipping Port module (ship.port) maintains a registry of ports used for international shipping operations. This master data model links ports to countries for logistics tracking and planning.
Model Information¶
Model Name: ship.port
Display Name: Shipping Port
Key Fields: None
Features¶
- ❌ No audit logging
- ❌ No multi-company support
- ❌ No full-text search
- ❌ No unique constraints
Key Fields Reference¶
Header Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
Char | ✅ | Port name |
country_id |
Many2One | ❌ | Country location |
Default Order: Ordered by name alphabetically
API Methods¶
1. Create Port¶
Method: create(vals, context)
Creates a new shipping port record.
Parameters:
Returns: int - New record ID
Example:
# Create port with country
port_id = get_model("ship.port").create({
"name": "Port of Los Angeles",
"country_id": usa_id
})
# Create port without country
port_id = get_model("ship.port").create({
"name": "Port of Singapore"
})
2. Search Ports¶
Method: search_browse(condition, context)
Search ports by name or country.
Example:
# Search by name
ports = get_model("ship.port").search_browse([
["name", "ilike", "singapore"]
])
# Search by country
us_ports = get_model("ship.port").search_browse([
["country_id", "=", usa_id]
])
# Get all ports
all_ports = get_model("ship.port").search_browse([])
Common Use Cases¶
Use Case 1: Register Major International Ports¶
# Register world's busiest ports
ports = [
{"name": "Port of Shanghai", "country_id": china_id},
{"name": "Port of Singapore", "country_id": singapore_id},
{"name": "Port of Ningbo-Zhoushan", "country_id": china_id},
{"name": "Port of Shenzhen", "country_id": china_id},
{"name": "Port of Guangzhou", "country_id": china_id},
{"name": "Port of Busan", "country_id": south_korea_id},
{"name": "Port of Hong Kong", "country_id": hong_kong_id},
{"name": "Port of Qingdao", "country_id": china_id},
{"name": "Port of Los Angeles", "country_id": usa_id},
{"name": "Port of Rotterdam", "country_id": netherlands_id}
]
port_ids = []
for port_data in ports:
port_id = get_model("ship.port").create(port_data)
port_ids.append(port_id)
print(f"Created: {port_data['name']}")
print(f"\nRegistered {len(port_ids)} shipping ports")
Use Case 2: List Ports by Region¶
# Get all Asian ports
asian_countries = [china_id, singapore_id, japan_id, south_korea_id, thailand_id]
asian_ports = get_model("ship.port").search_browse([
["country_id", "in", asian_countries]
])
print("Asian Shipping Ports:")
for port in asian_ports:
print(f"- {port.name} ({port.country_id.name})")
Use Case 3: Setup Regional Port Groups¶
def setup_regional_ports(region_name, port_list):
"""
Setup ports for a specific region
Args:
region_name: Name of the region
port_list: List of (port_name, country_id) tuples
Returns:
List of created port IDs
"""
print(f"Setting up {region_name} ports...")
port_ids = []
for port_name, country_id in port_list:
# Check if port exists
existing = get_model("ship.port").search([
["name", "=", port_name]
])
if existing:
print(f" ✓ {port_name} (already exists)")
port_ids.append(existing[0])
else:
port_id = get_model("ship.port").create({
"name": port_name,
"country_id": country_id
})
port_ids.append(port_id)
print(f" + {port_name} (created)")
return port_ids
# Usage
north_america_ports = [
("Port of Los Angeles", usa_id),
("Port of Long Beach", usa_id),
("Port of New York/New Jersey", usa_id),
("Port of Savannah", usa_id),
("Port of Vancouver", canada_id),
("Port of Prince Rupert", canada_id)
]
na_port_ids = setup_regional_ports("North America", north_america_ports)
Use Case 4: Update Port Information¶
# Update port name or country
port_id = 1
get_model("ship.port").write([port_id], {
"name": "Port of Los Angeles (POLA)",
"country_id": usa_id
})
Search Functions¶
Search by Name Pattern¶
# Case-insensitive partial match
condition = [["name", "ilike", "%angeles%"]]
results = get_model("ship.port").search_browse(condition)
Search by Country¶
# Exact country match
condition = [["country_id", "=", usa_id]]
results = get_model("ship.port").search_browse(condition)
Search Ports Without Country¶
# Find ports missing country assignment
condition = [["country_id", "=", False]]
results = get_model("ship.port").search_browse(condition)
Related Models¶
| Model | Relationship | Description |
|---|---|---|
country |
Many2One | Port location country |
sale.order |
Referenced by | Orders may specify port |
purchase.order |
Referenced by | Purchases may specify port |
stock.picking |
Referenced by | Pickings may track port |
Best Practices¶
1. Use Standard Port Names¶
# Good: Official port names
get_model("ship.port").create({
"name": "Port of Los Angeles",
"country_id": usa_id
})
# Avoid: Abbreviations or informal names
get_model("ship.port").create({
"name": "LA Port" # Unclear, not standard
})
2. Always Assign Country¶
# Good: Include country for geographic clarity
get_model("ship.port").create({
"name": "Port of Shanghai",
"country_id": china_id
})
# Bad: No country makes logistics unclear
get_model("ship.port").create({
"name": "Port of Shanghai"
# Missing country_id
})
3. Check for Duplicates¶
# Good: Check before creating
def create_or_get_port(name, country_id):
# Check by name
existing = get_model("ship.port").search([
["name", "=", name]
])
if existing:
return existing[0]
# Create new
return get_model("ship.port").create({
"name": name,
"country_id": country_id
})
# Usage
port_id = create_or_get_port("Port of Singapore", singapore_id)
Performance Tips¶
1. Cache Port Lists¶
# Good: Cache commonly used port lists
_port_cache = {}
def get_ports_by_country(country_id):
if country_id not in _port_cache:
ports = get_model("ship.port").search_browse([
["country_id", "=", country_id]
])
_port_cache[country_id] = ports
return _port_cache[country_id]
# Usage
us_ports = get_ports_by_country(usa_id)
2. Bulk Load for Dropdowns¶
# Good: Load all ports once for selection lists
all_ports = get_model("ship.port").search_browse([])
port_options = [(p.id, p.name, p.country_id.name) for p in all_ports]
# Use cached list for multiple operations
Troubleshooting¶
"Port not found"¶
Cause: Port record doesn't exist
Solution: Create port record first
# Check if port exists
port_name = "Port of Shanghai"
existing = get_model("ship.port").search([
["name", "=", port_name]
])
if not existing:
print(f"Port '{port_name}' not found. Creating...")
get_model("ship.port").create({
"name": port_name,
"country_id": china_id
})
"Multiple ports with same name"¶
Cause: No unique constraint on name field
Solution: Use name + country combination for uniqueness
# Check for duplicates
name = "Port of Victoria"
duplicates = get_model("ship.port").search([
["name", "=", name]
])
if len(duplicates) > 1:
print(f"Found {len(duplicates)} ports named '{name}':")
for port_id in duplicates:
port = get_model("ship.port").browse(port_id)
print(f" - ID {port.id}: {port.country_id.name if port.country_id else 'No country'}")
Testing Examples¶
Unit Test: Create and Retrieve Port¶
def test_port_crud():
# Create port
port_id = get_model("ship.port").create({
"name": "Test Port",
"country_id": usa_id
})
# Verify creation
assert port_id is not None
# Read back
port = get_model("ship.port").browse(port_id)
assert port.name == "Test Port"
assert port.country_id.id == usa_id
# Update
get_model("ship.port").write([port_id], {
"name": "Updated Test Port"
})
# Verify update
port = get_model("ship.port").browse(port_id)
assert port.name == "Updated Test Port"
# Delete
get_model("ship.port").delete([port_id])
Security Considerations¶
Permission Model¶
- View: Users with logistics/shipping access
- Create/Modify: Admin or logistics manager
- Delete: Admin only
Data Access¶
- Public reference data
- No sensitive information
- No multi-company isolation needed
Version History¶
Last Updated: October 2025
Model File: ship_port.py
Framework: Netforce
Additional Resources¶
- Port Destination Documentation:
port.destination - Port Loading Documentation:
port.loading - Country Documentation:
country
This documentation is generated for developer onboarding and reference purposes.